Complex table lookups - text strings

There is no way on the 16 series PICs to read a byte directly from program memory. The way a table is achieved is by the use of a computed goto and a return with literal in w instruction. For very simple tables where a byte maps to another byte, the code would be as follows:

	movlw	a			;index for table
	call	lookup			;get table value
	.
	.
	do something with the byte.


lookup	addwf	pc,f			;add the offset in w to
					;the program counter

	retlw	b			;return from the call with b in w
	retlw	c
	retlw	d
In MPASM, there is a shorthand for great long lists of retlw's. It is DT, define table.
Therefore the table above could be replaced with

	DT	b,c,d



Handling fixed length strings with a PIC processor is fairly straight forward using a table look-up approach. However, very seldom are all strings the same length. So the following section of code uses two table look-ups to handle variable length strings.

The first table is a table of CALLs. The index into this table is the string number that you wish to access. The second table contains the strings. The index into this table is a local variable (buffer2). Compared to C, you can think of these two tables as an array of pointers to strings:

char *string0 = "zeroeth";
char *string1 = "first";
char *string2 = "second";

char *string_ptrs[3] = {string0,string1,string2};
The table of CALLs is analogous to the array of pointers, while the table of strings is analogous to the string declarations.

;*******************************************************************
;write_string
;
;  The purpose of this routine is to display a string on the LCD module.
;On entry, W contains the string number to be displayed. The current cursor
;location is the destination of the output.
;
; Memory used
;    buffer2, buffer3
; Calls
;    LCD_WRITE_DATA
; Inputs
;    W = String Number
;

write_string
        CLRF    buffer2                 ;Used as an index into the string table
        MOVWF   buffer3                 ;Save a copy of which string we're to write

ws1:    CLRC
        RLF     buffer3, W              ;Get the saved copy and multiply it by two
        ADDWF   PCL, F                  ;Computed GOTO

        CALL    string0                 ;Get next character in the string
        GOTO    ws2

        CALL    string1
        GOTO    ws2

        CALL    string2
        GOTO    ws2

        CALL    string3
        GOTO    ws2

        CALL    string4

ws2:    ANDLW   0xff                    ;"Return" point for computed goto's.
        BTFSC   STATUS, Z               ;If the returned byte is zero, end reached
        RETURN
        CALL    LCD_WRITE_DATA          ;Write a single character
        INCF    buffer2, F              ;Point to the next character in the string
        GOTO    ws1

string0 MOVF    buffer2, W              ;Get the string index
        ADDWF   PCL, F                  ;and add it to the PC to get the next character
        dt   "SENSOR",0                 ;Note the zero termination.

string1 MOVF    buffer2, W
        ADDWF   PCL, F
        dt   "SMALL",0

string2 MOVF    buffer2, W
        ADDWF   PCL, F
        dt   "MEDIUM",0

string3 MOVF    buffer2, W
        ADDWF   PCL, F
        dt   "LARGE",0

string4 MOVF    buffer2, W
        ADDWF   PCL, F
        dt   "0123456789ABCDEF",0



Here is another method that is more compact in code density but has the disadvantage that the strings all need to be the same length.
Charater is returned from (w*4)+counter.

day_table   movwf   temp        ;day number 0-6
            clrc
            rlf    temp,f      ;multiply by 2
            rlf    temp,w      ;multiply by 2
                               ;this takes us to the correct day
            addwf  counter,w   ;add char offset within day string 0-3
            addwf  pc,f

            dt  "Sun "
            dt  "Mon "
            dt  "Tue "
            dt  "Wed "
            dt  "Thu "
            dt  "Fri "
            dt  "Sat "
            dt  "Sun "

Write_day   clrf    counter

another     movlw   5           	;write "Fri " as an example.
            call    day_table
            call    write_to_LCD    	;character is now in w. print it.
            incf    counter,f
            movlw   4
            subwf   counter,w
            btfss   status,z
            goto    another_char
	    .
            .
	    end