Firstly, don't scream.. I HAVE read the datasheets!. My table reading
subroutine is based on the final example in AN556 "Implementing a Table
Read" and can be used across page boundaries and be located anywhere in
memory... BUT!... will not work if the table itself is longer than 256
bytes. This is because the table element offset is passed in w (8 bits) and
then used in the calculation for the program counter. Trying to access
elements that start beyond an offset of 256 bytes won't work.
I could make a new separate table, but would prefer to keep it all together.
Based on the app note from Microchip, I can't see a simple way to do this
with one table. This particular example (example 5 in AN556) is already
complicated, and would be a mess if I try to make it cater for such things.
Has anyone posted a lookup table reader that can access defined elements in
a table longer than 256 bytes?. Weird thing is that AN556 does not
specifically warn of this. Maybe I'm doing something wrong... Hopefully one
of you can help.
My application is listed in part below. Firstly, the top of the table looks
like this. I have the modem strings arranged with the string length first,
then the string. This is the best way for this particular application.
;**********************************************************
;* Data tables
;**********************************************************
command
movwf PCL ;Update PCL with computed value
table_base ;Table start reference
off_hook
dt 0x07,"AATDT;",0x0d
hang_up
dt 0x05,"AATH",0x0d
modem_reset
dt 0x05,"AATZ",0x0d
dummy_dial
dt 0x17,"AATM2S07=48DT,xxxxxxxx",0x0d
;
You can call up one of these modem strings by simply doing this...
movlw modem_reset-table_base ;Calculate table offset for reset string
call send_command
;
And the big daddy of a table reader/modem string sender...
;*********************************************************
;* Send modem command string - called with table offset in w
;*********************************************************
send_command
movwf table_offset ;Save table offset
movlw LOW table_base ;Get low 8 bits of table address
addwf table_offset,f ;8-bit add to get abs location of string, could
overflow...
movlw HIGH table_base ;Get high 5 bits of table address
btfsc STATUS,C ;Did that last add cross page boundary?
addlw 1 ;Yes, roll over into next page
movwf PCLATH ;Preload high address
movf table_offset,w ;Update calculated offset
get_length
call command ;Get first byte (string length)
movwf msg_length ;Save message length
send_next
movlw 1 ;Increment table offset... carefully
addwf table_offset,f
movlw HIGH table_base
btfsc STATUS,C ;Crossed page boundary when incremented?
addlw 1 ;Roll over into next page
movwf PCLATH ;Preload high address
movf table_offset,w ;Update offset
call command ;Jump to table with offset in w...
loop_com
btfss PIR1,TXIF ;Check if txreg empty
goto loop_com ;Loop until free
;
wait_CTS ;Hardware flow control. CTS is normally LOW
btfsc PORTB,CTS ;Are we clear to send?
goto wait_CTS ;If CTS = HIGH, modem is busy
;
gie_tx
bcf INTCON,GIE ;Disable interrupts, dammit!
btfsc INTCON,GIE
goto gie_tx
movwf TXREG ;Send byte to modem
bsf INTCON,GIE ;Re-enable interrupts
decfsz msg_length,f ;Decrement length, if not zero
goto send_next ;Keep going...
return
Someone posted a long look-up table example for a few
days, just result the piclist search engine.
Beside of this: Which chip are you using? If it is
a 16f87x, you can read out the code memory directly,
and together with the "da" directive of MPASM it
is very simple to store ASCII data in backed byte
format, which makes your code much smaller! :)
Best Regards, Thorsten.
--
_____________________________________________
_/ uC-Stuff for MIDI at http://go.to/uCApps /_______
/ Music is aesthetisized frequency (Klaus Schulze) /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ;**********************************************************
> ;* Data tables
> ;**********************************************************
; *** Reserve TWO bytes for table_offset ***
> command
movlw table_offset ;Get high 5 bits of table address
movwf PCLATH ;Preload high address
; PCLATH must be set *in* the subroutine, not *before* it
movf table_offset+1,w ;Transfer low address
movwf PCL ; to PCL
; Data tables (may be anywhere in memory)
> off_hook
> dt 0x07,"AATDT;",0x0d
> hang_up
> dt 0x05,"AATH",0x0d
> modem_reset
> dt 0x05,"AATZ",0x0d
> dummy_dial
> dt 0x17,"AATM2S07=48DT,xxxxxxxx",0x0d
> ;
macro send_command where
movlw HIGH where ;table high address
movwf table_offset
movlw LOW where ;table low address
call do_send
endm
> You can call up one of these modem strings by simply doing this...
send_command modem_reset ;reset string
> ;*********************************************************
> ;* Send modem command string - called with table offset in w
> ;*********************************************************
do_send
movwf table_offset+1 ;Save table offset
call command ;Get first byte (string length)
movwf msg_length ;Save message length
send_next
incfsz table_offset+1,f ;Increment table offset
incfsz table_offset,f ; including high byte
call command ;Jump to table
> loop_com
> btfss PIR1,TXIF ;Check if txreg empty
> goto loop_com ;Loop until free
> ;
> wait_CTS ;Hardware flow control. CTS norm LOW
> btfsc PORTB,CTS ;Are we clear to send?
> goto wait_CTS ;If CTS = HIGH, modem is busy
Hi David, something like this should work for arbitrary table of any
length located anywhere in the program space. -- Rich
...
movlw high string ; point to a string
movwf look_hi ; in reality, a macro...
movlw low string
movwf look_lo
call process ; go process it
...
; subroutine to process string at look_hi/look_lo
process call lookup ; get a byte (this is the magic)
; here, do something with byte in W
; also, return if end of string
; otherwise...
goto process ; do it again
; Jump to address in look_hi/look_lo, which presumably is an RETLW.
; Note pointer post increment.
; Equivalent to: W=*look_ptr++
lookup movf look_hi,w ; set PCLATH
movwf PCLATH
movf look_lo,w ; and get PCL
incf look_lo,f ; but post inc
skpnz
incf look_hi,f
movwf PCL ; ok, now jump
On Sun, 21 May 2000, David Thompson wrote:
> Hi guys,
>
> Firstly, don't scream.. I HAVE read the datasheets!. My table reading
> subroutine is based on the final example in AN556 "Implementing a Table
> Read" and can be used across page boundaries and be located anywhere in
> memory... BUT!... will not work if the table itself is longer than 256
> bytes. This is because the table element offset is passed in w (8 bits) and
> then used in the calculation for the program counter. Trying to access
> elements that start beyond an offset of 256 bytes won't work.