0

I'm trying to use simple lookup tables in assembly by adding a certain index to the program counter. It appears to be working in a range of the PCL (so until 0xff) but afterwards, when the PCH comes in to play the PCH just resets after the addwf instruction.

How do I prevent the PCH from resetting after addition? Do I need to manipulate the PCLATH and PCLATU in some way so PCH will keep its value.

I'm using a pic18f25k50 with the mpasm assembler.

So this lookup table works fine:

TABLE_GET_VALUE
    movf    index, 0 ; memory location = 0x9E 
    mullw   4
    movf    PRODL, 0
    addwf   PC
    movf    0x20, 0
    return
    movf    0x21, 0
    return
    movf    0x22, 0
    return
    movf    0x23, 0
    return
    movf    0x24, 0
    return
    movf    0x25, 0
    return
    movf    0x26, 0
    return
    movf    0x27, 0
    return
    movf    0x28, 0
    return      ; memory location = 0xC8

while this one resets the program back to the first instructions:

TABLE_GET_COEFFICIENT
    movf    index, 0    ; memory location 0x108
    mullw   4
    movf    PRODL, 0
    addwf   PC
    movf    0x30, 0
    return
    movf    0x31, 0
    return
    movf    0x32, 0
    return
    movf    0x33, 0
    return
    movf    0x34, 0
    return
    movf    0x35, 0
    return
    movf    0x36, 0
    return
    movf    0x37, 0
    return
    movf    0x38, 0
    return      ; memory location 0x132

2 Answers2

1

This is one example of a complete way to code the table look up for a PIC18F controller.

;------------------------------------------------------------------------------ 
; MAIN PROGRAM 
;------------------------------------------------------------------------------ 
MAIN_CODE CODE              ; let linker place main program 

Main: 
    movlw   8
    call    TableOneLookup
    bra     Main

;------------------------------------------------------------------------------ 
;
; TableOneLookup
;
; Description: Look up data in table placed in code space
;
; Input:  WREG = byte offset in table
;
; Output: WREG = byte from table
;
;------------------------------------------------------------------------------ 
TABLE_ONE_CODE  code
TableOneLookup:
    push
    clrf    TOSU
    clrf    TOSH
    movwf   TOSL                ; Save offset in to TableOne
    addwf   TOSL,F              ; Double offset in to TableOne
    rlcf    TOSH,F              ; Propagate carry
    movlw   LOW(TabelOne)       ; Add TableOne address low byte
    addwf   TOSL,F
    movlw   HIGH(TabelOne)      ; Add TableOne address high byte
    addwfc  TOSH,F
    movlw   UPPER(TabelOne)     ; Add TableOne address upper byte
    addwfc  TOSU,F
    return                      ; Branch in to TableOne
TabelOne:
    DT      0x30
    DT      0x31
    DT      0x32
    DT      0x33
    DT      0x34
    DT      0x35
    DT      0x36
    DT      0x37
    DT      0x38
    end

There are better ways to do this using the assembly language opcodes specifically designed for program memory read operations.

Dan1138
  • 1,150
  • 8
  • 11
0

So I found the answer.

Apparently when you write to the PCL the PCLATH and PCLATU 's content is written directly to the PCH and PCU. This means the latches are never updated with the current value in this process. A way to update the PCLATH and PCLATU is by reading the PCL. This triggers the latches to update to the current value which means when writing to PCL later the wright value is copied in.

Like so:

TABLE_GET_COEFFICIENT
    movf    index, 0    ; memory location 0x108
    mullw   4
    movf    PC, 0       ; writing te PC value just for updating latches
    movf    PRODL, 0
    addwf   PC
    movf    0x30, 0
    return
    movf    0x31, 0
    return
    movf    0x32, 0
    return
    movf    0x33, 0
    return
    movf    0x34, 0
    return
    movf    0x35, 0
    return
    movf    0x36, 0
    return
    movf    0x37, 0
    return
    movf    0x38, 0
    return      ; memory location 0x132

more info in the data sheet: 3.1.1 and 5.1.1