Computed GOTO failing

Discussion in 'Embedded Systems and Microcontrollers' started by corsair, Mar 31, 2010.

  1. corsair

    Thread Starter Member

    Mar 6, 2010
    I was trying to do a simple computed goto, where it was something like:

    Code ( (Unknown Language)):
    1.        movlw 0x3
    2.        call     hex_to_7seg
    3. ...
    4. hex_to_7seg:
    5.        addwf PCL
    6.        retlw xx
    7.        retlw xx
    8.        retlw xx
    9.        retlw xx
    10.        etc..
    But when it adds 0x3 to the PCL, it goes bogus. Anyone know what the problem may be? I have screenshots attached which show a trace.

    I found this somewhere, but it still doesn't seem to work. Instead of adding 0x3 it will add 0x6. The whole adding thing, even if I try to add 0x0, will make it flip out.
    Last edited: Mar 31, 2010
  2. MMcLaren

    Well-Known Member

    Feb 14, 2010
    The program counter increments by two bytes for 18F' 16-bit instructions and so you need to multiply your "index" by two before modifying PCL.

    Regards, Mike

    Code ( (Unknown Language)):
    2. segtbl
    3.         rlncf   WREG,W          ; index 0..9 -> 0,2,4...E    
    4.         addwf   PCL,F           ;                                
    5.         retlw   b'00111111'     ; "0"   -|-|F|E|D|C|B|A        
    6.         retlw   b'00000110'     ; "1"   -|-|-|-|-|C|B|-        
    7.         retlw   b'01011011'     ; "2"   -|G|-|E|D|-|B|A        
    8.         retlw   b'01001111'     ; "3"   -|G|-|-|D|C|B|A      
    9.         retlw   b'01100110'     ; "4"   -|G|F|-|-|C|B|-      
    10.         retlw   b'01101101'     ; "5"   -|G|F|-|D|C|-|A        
    11.         retlw   b'01111101'     ; "6"   -|G|F|E|D|C|-|A        
    12.         retlw   b'00000111'     ; "7"   -|-|-|-|-|C|B|A          
    13.         retlw   b'01111111'     ; "8"   -|G|F|E|D|C|B|A        
    14.         retlw   b'01101111'     ; "9"   -|G|F|-|D|C|B|A      
  3. corsair

    Thread Starter Member

    Mar 6, 2010
    Hmm, yea I read that somewhere but it still doesn't seem to work. It doesn't like it when I add anything (even 0x0) to PCL. It compiles correctly and everything, it just doesn't goto the correct location. In this case it, instead of going from 0x26 to 0x29, it goes from 0x26 to 0xFE. But yes, that was another thing I was doing incorrectly. So it should be going from 0x28 (since I add that one instruction) to 0x2D.
  4. BMorse

    Senior Member

    Sep 26, 2009
    I had run into a similar problem with a PIC16F628A, one way I found to fix it was this:

    I added 5 more lines of data in the data table.....
    Code ( (Unknown Language)):
    2. bin2seg    addwf    PCL, F            ; Jump into the lookup table
    3.         retlw   0x7E    ;b'01111110'        ;0
    4.         retlw   0x0C    ;b'00001100'        ;1
    5.         retlw   0xB6    ;b'10110110'        ;2
    6.         retlw   0x9E    ;b'10011110'        ;3
    7.         retlw   0xCC    ;b'11001100'        ;4
    8.         retlw   0xDA    ;b'11011010'        ;5
    9.         retlw   0xFA    ;b'11111010'        ;6
    10.         retlw   0x0E    ;b'00001110'        ;7
    11.         retlw   0xFE    ;b'11111110'        ;8
    12.         retlw    0xCE   ;b'11001110'        ;9
    13.         retlw    0xFF   ;b'00000000'        ;Blank
    14.         retlw    0xFF   ;b'00000000'        ;Blank
    15.         retlw    0xFF   ;b'00000000'        ;Blank
    16.         retlw    0xFF   ;b'00000000'        ;Blank
    17.         retlw    0xFF   ;b'00000000'        ;Blank
    Then before calling the lookup table, I made sure the digit I was passing to PCL was within my table boundaries....
    Code ( (Unknown Language)):
    2.     movfw  cnt_dig4  ;load number to display
    3.     andlw   0x0F       ;make sure it is within table limits
    4.     call      bin2seg    ;Convert number in W to the segment value
    5.     movwf  PORTB     ;Send value returned in W to the segments
    I am not sure if this is whats causing your issue but I just thought it was worth a mention...

    B. Morse
  5. corsair

    Thread Starter Member

    Mar 6, 2010
    Nope, nothing =(

    If it helps, the DC bit in STATUS is affected after 0x6 is added to PCL
  6. t06afre

    AAC Fanatic!

    May 11, 2009
  7. rjenkins

    AAC Fanatic!

    Nov 6, 2005
    You need to set the high half of the program counter to the table location, and make sure the table does not cross a memory page.

    I always start tables at a new program origin, well above the main program, rather than check each lookup for page wrapping, it's simpler and quicker.

    Have a look at this article:

    The section by Mike Keitz about a page down (using W as the index) looks like what you need.
    corsair likes this.
  8. eblc1388

    Senior Member

    Nov 28, 2008
    Not only must one ensure the value added to the PCL would stay within the table boundary, one must ensure that the whole table is NOT crossing a page boundary in the flash memory address.

    Note to OP, look at the flash address of the table to see if it is situated in the boundary of two memory pages, if so, move it around until it doesn't. One can place additional codes for table read operation such that table crossing page boundary will no longer be an issue, like the following:

    Code ( (Unknown Language)):
    2.         movlw LOW Table         ;get low 8 bits of Table address
    3.         addwf offset,F          ;add offset to Table and save for later use
    4.                                 ;if page is crossed, carry will be set
    5.         movlw HIGH Table        ;next get high 5 bits of Table address
    6.         btfsc STATUS,C          ;check page crossed? Skip next if NO
    7.         addlw 1                 ;yes, increment W
    8.         movwf PCLATH            ;place into PCLATH
    9.         movf offset,w           ;load computed offset into W
    10.         call Table              ;call to table
    11. ;
    12. ;
    13. ;
    14. Table:
    15.         movwf PCL,F        ;load computed offset to PCL
    16.         retlw  A              ;return the ASCII char A
    17.         retlw  B              ;return the ASCII char B
    18.         retlw  C             ;return the ASCII char C
    corsair likes this.
  9. corsair

    Thread Starter Member

    Mar 6, 2010
    omg this is a lot more complicated than i thought, haha. ill try to do some more reading and ill let u know if i get it fixed... thanks guys

    btw, i have a PIC18F4550 processor. a lot of these hints are saying things like:

    im still going to read them, nonetheless. just not sure if they will apply
  10. corsair

    Thread Starter Member

    Mar 6, 2010
    ah yes! got it working, i used the code eblc posted and it worked after modifying it a little for the pic18f =) tyvm!! (time to take some tylenol)