ASM look up table question?

Started by G. Hoffman, July 13, 2010, 03:11:59 AM

Previous topic - Next topic

G. Hoffman

I'm working on a project that requires a couple of long look-up tables (or at least, I can't think of any better way to do it).  I'm using a 16f887 - and programing it in .asm - which has plenty of program memory (8K), but I'm running into a problem with the program memory.  An ADDLW PC command only effects the low byte of the 13 bit program counter, so a look up table that crosses two high bit values doesn't work.

So, if I'm not mistaken, the way to take care of this is to start my look up tables a appropriate addresses with an ORG command, right?  For instance:

Quote

LOOKUP1     ORG        0X1D00
                  ADDLW    PCL
{look up table follows}



Right?  And of course, this all assumes my program doesn't get into addresses that high to begin with, which it really shouldn't - At least, I sure as heck hope not!


Gabriel

potul

lookup tables in ASM for PICs is really a pain in the neck.
What I usually do is put all my tables at the beginning of the memory, and then the program. This way you never overwrite.
Gererally, you need to be careful with 2 things:

-A table should not cross a page boundary.
-A call to a table not in the same page as the code requires some manual changes in PCLATH, as the CALL funtion is not dealing with it. (this is valid for whatever call, not only tables).

You can find more info here:
http://www.piclist.com/techref/microchip/tables.htm

I use the fcall macro.

Potul

cpm

i'm not a pic developer, but afaik, if you are programming in asm, it means you get direct control over memory boundaries, no heap and no stack overhead from proc calls, context switching, etc

but also there isnt any memory management so i guess you do it explicitly. I think you could use a big table that spans for some pages if you manage it properly.





MoltenVoltage

There's a method in the app notes on how to pre-load the pclath with the proper value so you can jump to other pages.
MoltenVoltage.com for PedalSync audio control chips - make programmable and MIDI-controlled analog pedals!

potul

I've never dealt with lookup tables crossing page boundaries, so I really can't help on how to do it. For tables in a different page, I use this macro:

; table call macro
tcall macro table
movwf tcall_temp ; save W
local tcall_here
pageselw table ; select the proper page
movfw tcall_temp ; restore W
call table
pagesel tcall_here
tcall_here:
endm


It basically determines the valid PCLATH for the table, and does the correction before and after the call to ensure we are jumping to the correct address.
I hope it helps.

Potul

slotbot

#5
Im not sure if i understand your problem 100 percent but i think the issue your having is already handled in the hardware. Excerpt from the pic data sheets:

2.3.1 MODIFYING PCL
Executing any instruction with the PCL register as the
destination simultaneously causes the Program
Counter PC<12:8> bits (PCH) to be replaced by the
contents of the PCLATH register. This allows the entire
contents of the program counter to be changed by
writing the desired upper 5 bits to the PCLATH register.
When the lower 8 bits are written to the PCL register, all
13 bits of the program counter will change to the values
contained in the PCLATH register and those being
written to the PCL register.

So you need to load the high byte into PCLATH first, then when you write the low byte into PCL, PCH is also simultaneously loaded with the contents of PCLATH. Its a trick to allow you to write 16 bits of data is one cycle.

This is probably why you are also having problems now, since if you are writing to PCL you are also writing whatever is in PCLATH to PCH without even knowing it !

edit: also ADDLW  ADDs a Literal to Working register. It will not change PCL. I think you meant ADDWF PCL, 1. Not sure how big your tables are but you may have to check for a carry depending on the resulting address as well.


MoltenVoltage

Quote from: slotbot on July 13, 2010, 01:28:59 PM
you need to load the high byte into PCLATH first, then when you write the low byte into PCL, PCH is also simultaneously loaded with the contents of PCLATH.

+1

there is also a 256 byte limit on a given page, at least with the 16f688, so a given table can't exceed that limit.
MoltenVoltage.com for PedalSync audio control chips - make programmable and MIDI-controlled analog pedals!

slotbot

@MV ya sorry i realized after i posted that this is exactly what you were saying too, just with a bit more detail.

slotbot

Quote from: MoltenVoltage on July 13, 2010, 02:01:25 PM

there is also a 256 byte limit on a given page, at least with the 16f688, so a given table can't exceed that limit.

I dont see why you couldn't put your table over multiple pages.

Use 2 bytes of ram to act as a 16 bit pointer to index the table and just make a small function that maps the logical address in the pointer to the physical address in the memory space. Use the table start location as a base and then add the index as an offset. Load the resulting highbyte into PCLATH and then the low into PCL. It should take you anywhere in the memory space regardless of page boundaries.


MoltenVoltage

you can put tables over multiple pages, you just need to plan ahead

your suggested method sounds like a good way to do it
MoltenVoltage.com for PedalSync audio control chips - make programmable and MIDI-controlled analog pedals!

G. Hoffman

I guess I should clarify.  Each individual table is short enough for one page, but there are six of them that are about 100 lines long.  (They are for a 13 bit address register for an external EEPROM, so each table is one byte of the address.)  So, each pair of tables will take up most of a page.  I'm sure there is a better way to do it, but I don't know it!


Gabriel

slotbot

Quote from: G. Hoffman on July 14, 2010, 06:46:34 AM
I guess I should clarify.  Each individual table is short enough for one page, but there are six of them that are about 100 lines long.  (They are for a 13 bit address register for an external EEPROM, so each table is one byte of the address.)  So, each pair of tables will take up most of a page.  I'm sure there is a better way to do it, but I don't know it!


Gabriel

ultimately do you want them in an EEPROM or the program memory?


G. Hoffman

Quote from: slotbot on July 14, 2010, 09:28:50 AM
Quote from: G. Hoffman on July 14, 2010, 06:46:34 AM
I guess I should clarify.  Each individual table is short enough for one page, but there are six of them that are about 100 lines long.  (They are for a 13 bit address register for an external EEPROM, so each table is one byte of the address.)  So, each pair of tables will take up most of a page.  I'm sure there is a better way to do it, but I don't know it!


Gabriel

ultimately do you want them in an EEPROM or the program memory?




I need them in the program memory so I can access the EEPROM.  At least, that's the way I understand it.



Gabriel

slotbot

Overall, what are you trying to achieve?

If you store the tables (data) in the program memory is there still a need to store them in the EEPROM as well?




G. Hoffman

Quote from: slotbot on July 14, 2010, 03:50:55 PM
Overall, what are you trying to achieve?

If you store the tables (data) in the program memory is there still a need to store them in the EEPROM as well?



The EEPROM has groups of data bytes.  I'm using the tables in the program memory to find the first byte in the file, and then add one to get the next file, etc.  The data in the EEPROM can be edited, and I've yet to find an 8-bit PIC which has enough internal EEPROM to do the trick.

I'm sure I'm doing this all the wrong way, and certainly the difficult way.  What can I say - I'm a bit stubborn!


Gabriel

slotbot

#15
ok so you are basically storing a table of the page numbers in the program memory then trying to access that page number in an EEPROM?

If you need 2 bytes for the eeprom address from your lookup table just make 2 tables. one of high bytes and one of low bytes.

If your tables are at program memory requiring more than 8 bits to address use the PCLATH register as mentioned below to fetch the data.

Are you using an SPI EEPROM or?

G. Hoffman

Quote from: slotbot on July 14, 2010, 08:30:13 PM
ok so you are basically storing a table of the page numbers in the program memory then trying to access that page number in an EEPROM?

If you need 2 bytes for the eeprom address from your lookup table just make 2 tables. one of high bytes and one of low bytes.



That's exactly what I'm doing. 

I'm using an AT28C64B.


Gabriel

slotbot

ok if you are having trouble doing that maybe try something along these lines. this way just uses 2 separate tables for the eeprom addresses.

; setup some user registers....

t_index equ h'nn' ; some ram register
eeprom_a_l h'pp' ; the low byte of teh eeprom address you will access
eeprom_a_h h'qq' ; ... high byte ...


your code....
.
.
.
.
call get_low
movwf eeprom_a_l
call get_high
movwf eeprom_a_h

call read_eeprom; (some function you have to start teh read)
.
.
.
.
.




get_low movlw h'12' ;high byte of table_l
movwf PCLATH
movf t_index, 0; put the index in working register
addlw h'34' ; add to it the low byte of table_l
btfsc STATUS, C; check for carry
incf PCLATH,1; take care of carry
movwf PCL; put low byt eresult in PCL, shoudl jump to proper address

get_high movlw h'23' ;high byte of table_h
movwf PCLATH
movf t_index, 0; put the index in working register
addlw h'45' ; add to it the low byte of table_h
btfsc STATUS, C; check for carry
incf PCLATH,1; take care of carry
movwf PCL; put low byte result in PCL, shoudl jump to proper address....




org 0x1234
table_l retlw h'xx'
retlw h'yy'
retlw h'xx'
.
.
.
.


org 0x2345
table_h retlw h'xx'
retlw h'yy'
retlw h'xx'
.
.
.
.

G. Hoffman

Oh, no, I'm not having a problem - at least, not yet - I was just checking to make sure I was on the right track for how to do it before I started working on it.


Gabriel

slotbot

oh ok. what are you making btw?