ASM: LCD to PIC 4-bit writing to screen problem

Thread Starter

pic122

Joined Jul 10, 2014
8
Hi everyone,

I have a problem with writing to a hitachi hd44780 16x2 display using the PIC16F1459. I have written several programs in C for this particular arrangement so I know from this that the wiring, LCD and PIC are all working correctly. I decided to switch over to writing in assembly because I wanted more control over the PIC. I am not a beginner with assembly would say I have a moderate understanding and have searched around a lot of forums and websites to better understand writing assembly for PIC's. However I cant seem to get the LCD to print out the correct characters. The code attached below initialises the LCD correctly - 16 boxes over 2 lines but when I want to write to it I can only get the LCD to print out 5 strange characters.

Rich (BB code):
; date: Tue 8th July                 *
; version: 1.0                       *
; filename: LCD                      *
; PIC: p16f1459                      *
; clock frequency: 4MHz              *
; cty: 1 us                          *
;*************************************

;=================
; Config Settings

        list    P=16f1459
        include "p16f1459.inc"

; CONFIG1
; __config 0x3FE4
 __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
; CONFIG2
; __config 0x1FFF
 __CONFIG _CONFIG2, _WRT_OFF & _CPUDIV_CLKDIV6 & _USBLSCLK_48MHz & _PLLMULT_3x & _PLLEN_ENABLED & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_OFF




;======================
; Declarations

#define     LCD_PORT    LATC
#define     LCD_RS      LATC,4
#define     LCD_E       LATC,5

; RW is grounded
; D4 ----> RC0
; D5 ----> RC1
; D6 ----> RC2
; D7 ----> RC3

;=====================
; Variable Definitions

        cblock  H'20'
        count
        delay_1
        delay_2
        delay_3
        tempLCD
        endc

;==============
; Reset Vector

        org   0x0000
        goto  Start

Init
;====================
; Disable comparators

        bcf     CM1CON0,C1ON    ; clear C1ON
        bcf     CM2CON0,C2ON    ; clear C2ON

;========================
;Set Oscillator frequency

        banksel OSCCON
        movlw   B'11110111'     ; 4MHz internal oscillator ; cty = 1us
        movwf   OSCCON

        banksel TRISC           ; select LCD bus
        movlw   B'00000000'     ; all pins output
        movwf   TRISC

        banksel LATC
        clrf    LATC
        

        ; initialisation delay - 1 sec
        movlw   D'100'
        call    delay_long

        return

;============================================
; Delay subroutine which lasts for 100 * cty

delay_long
        movwf   delay_3
delay_long_loop2
        movlw   D'13'
        movwf   delay_2
        clrf    delay_1
delay_long_loop1
        decfsz  delay_1,f
        goto    delay_long_loop1
        decfsz  delay_2,f
        goto    delay_long_loop1
        decfsz  delay_3,f
        goto    delay_long_loop2

        return

;=========================
; Delay subroutine 10 * cty

delay_short
        movwf   delay_2
delay_short_loop2
        movlw   D'249'
        movwf   delay_1
delay_short_loop1
        nop
        decfsz  delay_1,f
        goto    delay_short_loop1
        decfsz  delay_2,f
        goto    delay_short_loop2

        return

;==================
;LCD Initialisation

LCD_Init
        banksel LATC
        bcf     LCD_RS          ; commands so RS bit low

        movlw   D'16'
        call    delay_short
        banksel LATC
        movlw   0x03
        movwf   LCD_PORT
        call    Nibble
        movlw   D'6'
        call    delay_short
        banksel LATC
        movlw   0x03
        movwf   LCD_PORT
        call    Nibble
        movlw   D'1'
        call    delay_short
        banksel LATC
        movlw   0x03
        movwf   LCD_PORT
        call    Nibble
        movlw   D'5'
        call    delay_short

        banksel LATC
        movlw   0x20            ; set 4 bit mode
        movwf   LCD_PORT
        call    Nibble
        movlw   0x28            ; 2 lines, 5 x 7 font
        call    LCD_Cmd
        movlw   0x08            ; display switch: D = 0, C = 0, B = 0
        call    LCD_Cmd
        movlw   0x0F            ; display switch: D = 1, C = 1, B = 1
        call    LCD_Cmd
        call    LCD_Clear       ; clear display
        movlw   0x06            ; input set: I/D = 1, S = 0
        call    LCD_Cmd


        return

;============
; Send nibble

Nibble
        banksel LATC
        bsf     LCD_E           ; high
        movlw   D'1'
        call    delay_short
        banksel LATC
        bcf     LCD_E           ; low
        movlw   D'2'
        call    delay_short

        return

;============
; LCD Command

LCD_Cmd
        movwf   tempLCD
        swapf   tempLCD         ; higher nibble to W
        movfw   tempLCD
        andlw   0xF0
        banksel LATC
        bcf     LCD_RS          ; RS set low due to instruction write
        banksel LATC
        movwf   LCD_PORT
        call    Nibble
        movlw   D'2'
        call    delay_short

        swapf   tempLCD         ; lower nibble to W
        movfw   tempLCD
        andlw   0xF0
        banksel  LATC
        bcf     LCD_RS
        banksel LATC
        movwf   LCD_PORT
        banksel  LATC
        bcf     LCD_RS
        call    Nibble
        movlw   D'10'
        call    delay_short

        return

;==========
; LCD Write

LCD_Write
        movwf   tempLCD
        swapf   tempLCD         ; higher nibble to W
        movfw   tempLCD
        andlw   0xF0
        banksel LATC
        bsf     LCD_RS          ; RS set high due to data write
        banksel LATC
        movwf  LCD_PORT
        call   Nibble
        movlw   D'2'
        call    delay_short

        swapf   tempLCD         ; lower nibble to W
        movfw   tempLCD
        andlw   0xF0
        banksel LATC
        bsf     LCD_RS
        banksel LATC
        movwf   LCD_PORT
        call    Nibble
        movlw   D'10'
        call    delay_short

        return

;===========
; LCD line 1

LCD_Line1
        movlw   0x80
        call    LCD_Cmd

        return

;===========
; LCD line 2

LCD_Line2
        movlw   0xC0
        call    LCD_Cmd

        return

;==============
; Clear Command

LCD_Clear
        movwf   0x01
        call    LCD_Cmd

        return

;=============
; Program main
Start
        call    Init
        call    LCD_Init

Main
        movlw   0x50        ;P
        call    LCD_Write
        movlw   0x49        ;I
        call    LCD_Write
        movlw   0x43        ;C
        call    LCD_Write
        goto    $           ; loop forever

        end
I have a few ideas what might be wrong the obvious one is the LCD_Write subroutine also I'm wondering whether the PIC is correctly initialised. I would be grateful if you could look over the code.

Thanks.


 

takao21203

Joined Apr 28, 2012
3,695
using assembler, there are countless things that can go wrong.

Did you run the program in a simulator?
Did you try to reduce the clocking frequency?
Is the LCD OK?

Go through the datasheet again, and check your code step by step.
Remove everything that is not required.

b) dont use ASM it does not give you more control.
 

MMcLaren

Joined Feb 14, 2010
846
Hi pic122. Welcome to the Forum.

I didn't see where you turned off the analog functions for PORTC in your code.

Are you sure you've got correct Config' and OSCCON settings for 4-MHz INTOSC?

Looks like you're masking off the wrong nibble in your LCD_Cmd and LCD_Write subroutines. That will definitely mess up the HD44780 LCD "initialization by instruction" procedure.

This section in LCD_Init is incorrect (operand should be 0x02 instead of 0x20);

Rich (BB code):
        banksel LATC
        movlw   0x20            ; set 4 bit mode
        movwf   LCD_PORT
Also, the LCD 'home' and 'clear' commands usually require a ~1550 us delay to complete.

Perhaps you can try to flash an LED at some interval to verify correct config, ANSELC, and OSCCON settings?

Good luck on your project.

Cheerful regards, Mike
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,058
First off, welcome to the forums.

Next, please note 4 very experienced people read your post and none of them read your code. They may have wandered thru it briefly but no one will give it the detailed study you can.

Do you have a PICkit for programming? If you do, it can also work as an in circuit debugger, though you need to keep it's connection pins free. I always keep those pins available in every project so I can do such debugging. With just a DVM (or even a LED) you can check all the pins for proper ones and zeros.

Sometimes your code only works when single stepping. That's good news as it means your delays are the problem. (Always make the delays hugely large in the beginning; once you can see "Hello World" on the display you can start slimming things down to quick but still works 100%)

If not, there is always the simulator. You can step thru your code line by line (and it's oft OK to comment out long delays) to see if the correct pins wiggle when commanded.

Good luck!
 

Thread Starter

pic122

Joined Jul 10, 2014
8
Hi all.

Wow thank you for all your replies. I will take my time to go through them all and try out your suggestions and will post back my progress.

Thanks once again.
 

MMcLaren

Joined Feb 14, 2010
846
pic122,

Just spotted some more code problems; (1) over-writing the RS bit in your LCD_Write routine and incorrect bank selection.

Let me put some notes together for you, Sir.

Regards, Mike
 

ErnieM

Joined Apr 24, 2011
8,058
Are you saying that The Pickit will perform the ICD2/ICD3 functions?
If so I must have missed this?
OK I see it mentions this, I stand corrected.
Max.
Well gee, you're not the only one not to realize that the PICkit 2 Development Programmer/Debugger is both a programmer AND a debugger.

I imagine the confusion that name must have caused, which may be why Microchip names the next version the PICkit 3 In-Circuit Debugger so someone just might notice it also works as a debugger.

I'm just waiting for the day for someone to ask "I only have a PICkit 3 debugger. What do I need to do programming?"

:D
 

Thread Starter

pic122

Joined Jul 10, 2014
8
Hi everyone.

Thank you for all your suggestions, links and help I have had success and now have a fully functioning LCD display using assembly code!

The problem was with the LCD_Cmd and LCD_Write routines I didn't fully understand the difference between moving the contents into a temporary file register and using the w register to perform instructions. So throughout my two routines I was overwriting the nibbles with the values I was using for the delay routine hence the garbage on the LCD. Also as MMcLaren pointed out I was overwriting the RS bit when trying to use the LCD_Write routine.

I solved this by using the simulator in mplab x as suggested and step through the code line by line whilst looking at Window > PIC Memory Views > SFRs where I could see the affect of each instruction on the various ports on the PIC.

Also I set the pins to digital and changed the 4 bit command to 0x02 from the wrong value.

Here is the working code below:

Rich (BB code):
;=================
; Config Settings

        list    P=16f1459
        include "p16f1459.inc"

; CONFIG1
; __config 0x3FE4
 __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
; CONFIG2
; __config 0x1FFF
 __CONFIG _CONFIG2, _WRT_OFF & _CPUDIV_CLKDIV6 & _USBLSCLK_48MHz & _PLLMULT_3x & _PLLEN_ENABLED & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_OFF




;======================
; Declarations

#define     LCD_PORT    LATC
#define     LCD_RS      LATC,4
#define     LCD_E       LATC,5


; RW is grounded
; D4 ----> RC0
; D5 ----> RC1
; D6 ----> RC2
; D7 ----> RC3

;=====================
; Variable Definitions

        cblock  H'20'
        delay_1
        delay_2
        delay_3
        tempLCD
        endc

;==============
; Reset Vector

        org   0x0000
        goto  Start

Init
;====================
; Disable comparators

        bcf     CM1CON0,C1ON    ; clear C1ON
        bcf     CM2CON0,C2ON    ; clear C2ON

;========================
;Set Oscillator frequency

        banksel OSCCON
        movlw   B'00110111'     ; 4MHz internal oscillator ; cty = 1us
        movwf   OSCCON

;=====================
; Set up port and pins

        banksel TRISC           ; select TRISC bus
        movlw   B'00000000'     ; all pins output
        movwf   TRISC

        banksel LATC            ; select LATC and clear
        clrf    LATC

        banksel ANSELC          ; set all pins to digital
        clrf    ANSELC

        return

;============================================
; Delay subroutine which lasts for 100 * cty

delay_long
        movwf   delay_3
delay_long_loop2
        movlw   D'13'
        movwf   delay_2
        clrf    delay_1
delay_long_loop1
        decfsz  delay_1,f
        goto    delay_long_loop1
        decfsz  delay_2,f
        goto    delay_long_loop1
        decfsz  delay_3,f
        goto    delay_long_loop2

        return

;============================
; Delay subroutine 1000 * cty

delay_short
        movwf   delay_2
delay_short_loop2
        movlw   D'249'
        movwf   delay_1
delay_short_loop1
        nop
        decfsz  delay_1,f
        goto    delay_short_loop1
        decfsz  delay_2,f
        goto    delay_short_loop2

        return

;==================
;LCD Initialisation

LCD_Init
        movlw   D'5'
        call    delay_long

        banksel LATC
        bcf     LCD_RS          ; commands so RS bit set low
        movlw   D'16'           ; must be more than 15ms
        call    delay_short
        banksel LATC
        movlw   0x03            ; send first high nibble
        movwf   LCD_PORT
        call    Nibble
        movlw   D'6'            ; must be more than 4.1ms
        call    delay_short
        banksel LATC
        movlw   0x03            ; send second high nibble
        movwf   LCD_PORT
        call    Nibble
        movlw   D'1'            ; must be more than 100us
        call    delay_short
        banksel LATC
        movlw   0x03            ; send third high nibble
        movwf   LCD_PORT
        call    Nibble
        movlw   D'5'            ; must be more than 5ms
        call    delay_short

        banksel LATC
        movlw   0x02            ; set 4 bit mode
        movwf   LCD_PORT
        call    Nibble
        movlw   0x28            ; function set: 4 bit, 2 lines, 5 x 7 font
        call    LCD_Cmd
        movlw   0x08            ; display switch: D = 0, C = 0, B = 0
        call    LCD_Cmd
        call    LCD_Clear
        movlw   0x0C            ; display switch: D = 1, C = 0, B = 0
        call    LCD_Cmd

        movlw   0x06            ; input set: I/D = 1, S = 0
        call    LCD_Cmd

        banksel LATC            ; make sure LATC port is clear
        clrf    LATC

        movlw   D'50'           ; initialisation delay
        call    delay_long

        return

;============
; LCD Command

;****************************
;                           *
; RS   ___________________  *
;                           *
; R/W  ___________________  *
;              __           *
; E    _______/  \________  *
;         _____________     *
; D4/7 __/   Command   \__  *
;                           *
;****************************

LCD_Cmd
        movwf   tempLCD           ; move contents of w into tempLCD
        swapf   tempLCD,w         ; swap contents of tempLCD put result in w
        andlw   0xf               ; select high nibble
        banksel LATC
        movwf   LCD_PORT
        banksel LATC
        bcf     LCD_RS            ; RS set low due to instruction write
        call    Nibble
        movlw   D'1'
        call    delay_short

        movfw   tempLCD           ; move contents of tempLCD into w
        andlw   0xf               ; select low nibble
        banksel LATC
        movwf   LCD_PORT
        banksel LATC
        bcf     LCD_RS            ; RS set low due to instruction write
        call    Nibble
        movlw   D'1'
        call    delay_short

        return

;==========
; LCD Write

;****************************
;         ________________  *
; RS   __/                  *
;                           *
; R/W  ___________________  *
;              __           *
; E    _______/  \________  *
;         _____________     *
; D4/7 __/    Data     \__  *
;                           *
;****************************

LCD_Write
        movwf   tempLCD           ; move contents of w into tempLCD
        swapf   tempLCD,w         ; swap contents of tempLCD put result in w
        andlw   0xf               ; select high nibble
        banksel LATC
        movwf   LCD_PORT
        banksel LATC
        bsf     LCD_RS            ; RS set high due to instruction write
        call    Nibble
        movlw   D'1'
        call    delay_short

        movfw   tempLCD           ; move contents of tempLCD into w
        andlw   0xf               ; select low nibble
        banksel LATC
        movwf   LCD_PORT
        banksel LATC
        bsf     LCD_RS            ; RS set high due to instruction write
        call    Nibble
        movlw   D'5'              ; vary this delay to control writing speed
        call    delay_long
        return

;===========================
; Send nibble - toggle E pin

Nibble
        banksel LATC
        bsf     LCD_E             ; E set high
        movlw   D'1'
        call    delay_short
        banksel LATC
        bcf     LCD_E             ; E set low
        movlw   D'2'
        call    delay_short

        return

;===========
; LCD line 1

LCD_Line1
        movlw   0x80
        call    LCD_Cmd

        return

;===========
; LCD line 2

LCD_Line2
        movlw   0xC0
        call    LCD_Cmd

        return

;==============
; Clear Command

LCD_Clear
        movlw   0x01
        call    LCD_Cmd

        return

;============
; Write Space

LCD_Space
        movlw   0x20
        call    LCD_Write

        return

;=============
; Program main

Start
        call    Init
        call    LCD_Init

Main
        call    LCD_Clear
        call    LCD_Line1

Top_Line
        movlw   'H'
        call    LCD_Write
        movlw   'e'
        call    LCD_Write
        movlw   'l'
        call    LCD_Write
        movlw   'l'
        call    LCD_Write
        movlw   'o'
        call    LCD_Write
        call    LCD_Space
        movlw   'W'
        call    LCD_Write
        movlw   'o'
        call    LCD_Write
        movlw   'r'
        call    LCD_Write
        movlw   'l'
        call    LCD_Write
        movlw   'd'
        call    LCD_Write
        movlw   D'255'
        call    delay_long

Bottom_Line
        call    LCD_Line2
        movlw   'I'
        call    LCD_Write
        movlw   't'
        call    LCD_Write
        movlw   0X27
        call    LCD_Write
        movlw   's'
        call    LCD_Write
        call    LCD_Space
        movlw   'p'
        call    LCD_Write
        movlw   'i'
        call    LCD_Write
        movlw   'c'
        call    LCD_Write
        movlw   '1'
        call    LCD_Write
        movlw   '2'
        call    LCD_Write
        movlw   '2'
        call    LCD_Write
        movlw   D'255'
        call    delay_long

        goto    $                  ; loop forever

        end
I also followed MacHeadRoom's suggestion and have successfully written another bit of code which uses the busy flag rather than delays.

Also going to incorporate a lookup table and to answer a question I'm using a PICKit 3.

Regards,
pic122.
 

Attachments

MMcLaren

Joined Feb 14, 2010
846
... I have had success and now have a fully functioning LCD display using assembly code!
Congrats', pic122. Happy to hear you're using the Simulator. When you get time, please check out your banking and you'll find you're using variable locations in bank 2 instead of bank 0. While it works ok for you in this case, it may become a problem in the future.

Your code looks great but your timing is off. While your code works fine, please check out the timing in the Hitachi HD44780 Datasheet for the "initialization by instruction" procedure for 4-bit interface mode. A simple fixed delay subsystem should handle most of your timing requirements.

Plenty of opportunities for optimizing your code, for example;

Rich (BB code):
Nibble_cmd
        clrc                    ; RS = 0 (command)                |00
Nibble_alt
        banksel LCD_PORT        ; bank 2                          |02
        andlw   0x0F            ;                                 |02
        skpnc                   ; C = 0? yes, skip (RS=0), else   |02
        iorlw   b'00010000'     ; set RS bit (RC4)                |02
        movwf   LCD_PORT        ;                                 |02
        bsf     LCD_E           ; toggle lcd 'E' pin              |02
        nop                     ;                                 |02
        nop                     ;                                 |02
        bcf     LCD_E           ;                                 |02
        movlb   0               ; bank 0                          |00
        return                  ;                                 |00
Rich (BB code):
LCD_Data
        setc                    ; C = 1 (data)                    |00
        skpc                    ; skip unconditionally            |00

LCD_Cmd_alt
        clrc                    ; C = 0 (command)                 |00
        movwf   tempLCD         ;                                 |00
        swapf   tempLCD,W       ; hi nibble in b3..b0 bits        |00
        call    Nibble_alt      ; write hi nibble to LCD          |00
        movf    tempLCD,W       ; lo nibble in b3..b0 bits        |00
        call    Nibble_alt      ; write lo nibble to LCD          |00
        delayCy(50*usecs)       ; 50-us inter-write delay         |00
        return                  ;                                 |00
Rich (BB code):
;
;  HD44780 "initialization by instruction" procedure for 4-bit mode
;
LCD_Init
        movlb   0               ; bank 0                          |00
        delayCy(50*msecs)       ; LCD 50 msec 'power up' reset    |00
        movlw   0x03            ; hi nibble of 0x30 '8-bit' cmd   |00
        call    Nibble_cmd      ; step 1                          |00
        delayCy(4*msecs)        ; required delay                  |00
        movlw   0x03            ; hi nibble of 0x30 '8-bit' cmd   |00
        call    Nibble_cmd      ; step 2                          |00
        delayCy(160*usecs)      ; required delay                  |00
        movlw   0x03            ; hi nibble of 0x30 '8-bit' cmd   |00
        call    Nibble_cmd      ; step 3                          |00
        delayCy(160*usecs)      ; required delay                  |00
        movlw   0x02            ; hi nibble of 0x20 '4-bit' cmd   |00
        call    Nibble_cmd      ; step 4                          |00
        delayCy(160*usecs)      ; required delay                  |00
;
;  now in 4-bit interface mode. ok to send full bytes.
;
        movlw   0x28            ; 4-bit, 2-lines, 5x7 font        |00
        call    LCD_Cmd_alt     ; send "function set" command     |00
        movlw   0x0C            ; display on, cursor & blink off  |00
        call    LCD_Cmd_alt     ; send "display on/off" command   |00
        movlw   0x06            ; cursor inc, shift off           |00
        call    LCD_Cmd_alt     ; send "entry mode set" command   |00
        movlw   0x01            ; clear display (1.53-msecs)      |00
        call    LCD_Cmd_alt     ; send "entry mode set" command   |00
        delayCy(1530*usecs)     ; 1.53 msec delay for "clear"     |00
        return                  ;                                 |00
The "enhanced mid-range" devices provide access to the stack which could be exploited to build a PutStr routine with in-line string storage;

Rich (BB code):
;
; PutStr macro usage example
;
        call    LCD_Line1       ;                                 |00
        PutStr "Hello World"    ;                                 |00
        call    LCD_Line2       ;                                 |00
        PutStr "It's pic122"    ;                                 |00
Rich (BB code):
PutStr  macro   string
        call    PutStrg         ; print in-line string
        dt      string,0        ; null terminated in-line string
        endm
Rich (BB code):
;
;  PutStrg subroutine - pull in-line string address from top of
;  stack, print string up to the null terminator, then return
;  to the address immediately following the in-line string.
;
PutStrg
	banksel	TOSL		; bank 31			  |31
	movf	TOSL,W		; top of stack lo		  |31
	movwf	FSR1L		;				  |31
	movf	TOSH,W		; top of stack hi		  |31
	iorlw   0x80            ; set FSR1 b15 for rom access     |31
	movwf	FSR1H		;				  |31
getchar
        banksel TOSL            ; bank 31                         |31
	moviw   INDF1++		; null terminator?		  |31
	bz	putexit		; yes, exit, else		  |31
	call	LCD_Data        ; send char to LCD		  |00
	bra	getchar		; loop				  |00
putexit
        movf    FSR1L,W         ; adjust return address           |31
        movwf   TOSL            ;                                 |31
        movf    FSR1H,W         ;                                 |31
        andlw   0x7F            ;                                 |31
        movwf   TOSH            ;                                 |31
        movlb   0               ; bank 0                          |00
        return                  ;                                 |00
Food for thought (forgive me for butting in).

Cheerful regards, Mike
 
Last edited:

MMcLaren

Joined Feb 14, 2010
846
Do you mean by this that cblock which has a value of H'20' in my code should be something different?
I mean that you're forgetting to use banksel statements before accessing those variables so you're actually in bank 2. That means you're accessing RAM locations at 0x120..0x124 instead of 0x020..0x024.

Since your code is always in bank 2 when you access those few variables, you could probably define them in bank 2 locations starting at 0x120. However many programmers will just make sure to switch back to bank 0 by default at the end of any routine that does bank switching.
 

Thread Starter

pic122

Joined Jul 10, 2014
8
So what you want to be doing is working in bank 0 with the variables and switching when you need to go to other banks and then switch back to bank 0 again.

For example in my code the Init routine should end ike this
Rich (BB code):
movlb   0
return
Is my understand of this now correct? I am now going to incorporate your optimising code suggestions which by looking at I can see you are able to avoid switching banks too often by carefully choosing which routine uses which bank.

Thank you for the help I have learnt a lot in these last few days.

Regards,

pic122
 
Top