A table lookup on the PIC16 basically takes the following steps:
  • Get the address of index zero of the table
  • Add the table index to the address
  • Jump to that address

The table itself is a sequence of retlw instructions, which put a value into W and return. (dt and related directives are just assembler shorthand for inserting many retlws.)

A first try at implementing a table lookup thus looks like this:

movlw TABLE_BASE # Get the address of index zero
addwf index, w # Add the table index to the address
movwf PCL # Jump to that address
TABLE_BASE:
dt "012...

However, this code sequence has significant limitations. Recall that PCL is only an 8-bit wide register, while the PIC16F8?7's program counter is 13 bits wide. This means that when a computed jump is made by modifying PCL, the remainder of the new program counter comes from the bottom 5 bits of PCLATH. If PCLATH is 0x00, then movwf PCL can only jump to 0x0000-0x00FF: the first 256 words of program memory.

If we want to be able to put tables anywhere, then we need to fix PCLATH as well:

movlw HIGH(TABLE_BASE) # Get the top byte of the address of index zero
movwf PCLATH # Set up the top byte of the jump address
movlw TABLE_BASE # Get the bottom byte of the address of index zero
addwf index, w # Add the table index to this address
movwf PCL # Jump to PCLATH:PCL+index
TABLE_BASE:
dt "012...

This code still has a potential problem, however. If the table crosses a 256-byte boundary, then the correct value for PCLATH is different for lookups on either side of the boundary, and we need to correct for this:

movlw HIGH(TABLE_BASE) # Get the top byte of the address of index zero
movwf PCLATH # Set up the top byte of the jump address
movlw TABLE_BASE # Get the bottom byte of the address of index zero
addwf index, w # Add the table index to this address
btfsc STATUS, C # If we overflowed, then...
incf PCLATH, f # ...increment the top byte of the jump address
movwf PCL # Jump to PCLATH:PCL+index
TABLE_BASE:
dt "012...

This technique will work for any table with 256 or fewer entries.

If we want a table with more than 256 entries, we just have to extend the same approach to deal with an index with top and bottom bytes as follows:

movlw HIGH(TABLE_BASE) # Get the top byte of the address of index zero
addwf index_hi, w # Add the top byte of the table index
movwf PCLATH # Set the top byte of the address
movlw TABLE_BASE # Get the bottom byte of the address of index zero
addwf index_lo, w # Add the bottom byte of the table index
btfsc STATUS, C # If we overflowed, then...
incf PCLATH, f # ...increment the top byte of the jump address
movwf PCL # Jump to PCLATH:PCL+index
TABLE_BASE:
dt "123...

Views: 2084

Comment

You need to be a member of Personal Mechatronics Lab to add comments!

Join Personal Mechatronics Lab

Comment by Jack Sparrow on January 28, 2011 at 9:04am

Remember that the last thing a table does is retlw the lookup value, meaning you need to call the table lookup routine for it to do what you expect. Hence you'd have to use the macro as follows:


ConvertBcdToAscii:
call_table TableBcdToAscii
TableBcdToAscii:
dt "0123456789"

SomeFunction:
...
movf some_char, w
call ConvertBcdToAscii
call LcdWrite


I suppose the macro would save you typing in the table lookup function.


I am neither a current AER201 student nor a TA, and my name is not actually Jack Sparrow.

Comment by Ritchie Thai on January 28, 2011 at 5:45am

Wait. Is your name actually Jack Sparrow? I assumed for a while that it was a fake name used by an AER201 student, but your posts seem to indicate the you are a TA. Disney ripped off your name.

 

More relevant to the post, this code would be more useful if it were a macro (I haven't tested this):

call_table macro TABLE_BASE

movlw HIGH(TABLE_BASE) # Get the top byte of the address of index zero

addwf index_hi, w # Add the top byte of the table index
movwf PCLATH # Set the top byte of the address
movlw TABLE_BASE # Get the bottom byte of the address of index zero
addwf index_lo, w # Add the bottom byte of the table index
btfsc STATUS, C # If we overflowed, then...
incf PCLATH, f # ...increment the top byte of the jump address
movwf PCL # Jump to PCLATH:PCL+index
 

Comment by Keiming Kwong on January 28, 2011 at 1:26am
Ok awesome.  :D  woot happy i chose pic18 now..  less stuff to deal with :P
Comment by Rick Zhang on January 28, 2011 at 1:24am
The same problem is not present for PIC18. Because the programming memory is 16 bits wide, tables can be stored more efficiently. Moreover, PIC18 provides special instructions for reading from and writing to tables. Have a look at the course notes pages 7-65 and 7-66.
Comment by Keiming Kwong on January 28, 2011 at 1:17am
Is the same problem present for pic 18?
Comment by Rick Zhang on January 28, 2011 at 1:10am
Hear, hear!

© 2024   Created by PML.   Powered by

Badges  |  Report an Issue  |  Terms of Service