Continue to Site

# ASM - if_then routine - any better way of doing?

#### augustinetez

##### Active Member
Just curious as to whether there might be a better way of doing IF_THEN routines in ASM as opposed to below code.

Background:

Processor is 16F628A - already set from an old project so not changeable (at this stage).

The routine is to select a group of 4 bytes from a table of 16 bytes depending in the inputs RA6 & 7 (switches), 4 options available.

The code below is only performed once on power-up to set a selected value.

There is a bit of jiggery-pokery (not shown) to shift what are bits 6 & 7 of PORTA to bits 0 & 1 of the IF_index register (so I don't have to count higher than 3 )

The code within the ////////////////////////// marks are what I have used before in other projects and am asking about.

Once this routine has been performed, it drops through to more set-up code for other variables.

Code:
; Using RA6 & 7 input data, obtain the if_table entry and
; copy IF offset from table and store in ioff_3..0
;
clrf    temp              ; Clear the temp variable
movlw   FREQ_COUNT        ; There are four bytes to copy
movwf   count             ; Set up count variable
movlw   ioff_0            ; Get target address
movwf   FSR               ; Store in pointer register

;////////////////////////////////////////////////////////////////////////////////

movf    IF_index,f
btfsc    STATUS,Z
goto    get_if_loop       ; If IF_index is '0' get values from table starting at index 0

movfw    IF_index    ;
xorlw    1
btfsc    STATUS,Z
goto    index_1              ; If IF_index is '1' get values from table starting at index 4

movfw    IF_index    ;
xorlw    2
btfsc    STATUS,Z
goto    index_2             ; If IF_index is '2' get values from table starting at index 8

movfw    IF_index    ;
xorlw    3
btfsc    STATUS,Z
goto    index_3             ; If IF_index is '3' get values from table starting at index 12
clrf    temp                    ; Error checking - if index value is other than 0->3
goto    get_if_loop        ; set index to 0

index_1
movlw    d'4'
movwf   temp
goto    get_if_loop    ;

index_2
movlw    d'8'
movwf   temp
goto    get_if_loop    ;

index_3
movlw    d'12'
movwf   temp

;////////////////////////////////////////////////////////////////////////////////

get_if_loop
movf    temp,w            ; Get the if_table index into W
call    if_table          ; Get a if_table byte
movwf   INDF              ; Store it into ioff_3..0
incf    FSR,f             ; Point to next higher offset byte, ioff_0..3
incf    temp,f            ; Increment table index
decfsz  count,f           ; Decrement loop count
goto    get_if_loop       ; loop while more bytes remain

#### Pommie

##### Well-Known Member
Mapping the value of IF_index to the value that is in temp gives,
0 = 0
1 = 4
2 = 8
3 = 12

Can't you just shift left twice? I.E. multiply by 4. Or the original value (bits 6 & 7) right three times?

Mike.

#### Diver300

##### Well-Known Member
Mapping the value of IF_index to the value that is in temp gives,
0 = 0
1 = 4
2 = 8
3 = 12

Can't you just shift left twice? I.E. multiply by 4. Or the original value (bits 6 & 7) right three times?

Mike.

I would have done something like that, or just this:-
Code:
        clrf     temp
btfsc    PORTA, 6
bsf      temp, 2
btfsc    PORTA, 7
bsf      temp, 3

Last edited:

#### augustinetez

##### Active Member
Thanks for the replies, I'll have a look at those.

Need to check on a bug in the original program - although it works, it seems to be not quite doing things in the right order.

#### Pommie

##### Well-Known Member
I would have done something like that, or just this:-
Code:
clrf temp
btfsc PORTA, 6
bsf temp, 2
btfsc PORTA, 7
bsf temp, 3
I like that solution, elegant. No AND required to get rid of unwanted bits or read of PORTA.

Mike.

#### Diver300

##### Well-Known Member
I would have done something like that, or just this:-
Code:
        clrf     temp
btfsc    PORTA, 6
bsf      temp, 2
btfsc    PORTA, 7
bsf      temp, 3

I've just realised that there is a considerably more concise option:-
Code:
       swapf    PORTA, w
andlw    0b1100
movwf    temp
I realise that this is very specific to this situation. Any change of port pins or need for any other type of lookup spacing would not work.

#### augustinetez

##### Active Member
Found the bug - was me - the program has so many defines included for various functions to be enabled or not, I kept following the wrong line.

Because the program is being used by and possibly the table modified by someone else, I stayed with my original code.

It will be easier for any remote fault finding if needed.

#### Nexus2023

##### New Member
This version of the code loads the index value into the W register and uses it to calculate the address of the appropriate entry in the lookup table. The lookup table consists of 16 consecutive entries, each containing the appropriate offset value for the corresponding switch settings. The table is defined as a series of retlw instructions, which return the appropriate value to the W register.

By using a lookup table, we eliminate the need for conditional jumps, making the code simpler and easier to follow. Additionally, the use of the PCLATH and PCL registers to jump to the appropriate entry in the table allows us to perform the lookup operation in just a few instructions, rather than using a separate conditional jump for each possible index value.

; Using RA6 & 7 input data, obtain the if_table entry and
; copy IF offset from table and store in ioff_3..0

clrf temp ; Clear the temp variable
movlw FREQ_COUNT ; There are four bytes to copy
movwf count ; Set up count variable
movlw ioff_0 ; Get target address
movwf FSR ; Store in pointer register

movf IF_index, w ; Load the index value into W
movlw HIGH if_table ; Load the upper byte of the table address into W
movwf PCLATH ; Store it in the program counter latch
addwf IF_index, f ; Add the index value to the upper byte
movlw LOW if_table ; Load the lower byte of the table address into W

if_table
retlw ioff_0 ; Entry 0
retlw ioff_1 ; Entry 1
retlw ioff_2 ; Entry 2
retlw ioff_3 ; Entry 3
retlw ioff_0 ; Entry 4
retlw ioff_1 ; Entry 5
retlw ioff_2 ; Entry 6
retlw ioff_3 ; Entry 7
retlw ioff_0 ; Entry 8
retlw ioff_1 ; Entry 9
retlw ioff_2 ; Entry 10
retlw ioff_3 ; Entry 11
retlw ioff_0 ; Entry 12
retlw ioff_1 ; Entry 13
retlw ioff_2 ; Entry 14
retlw ioff_3 ; Entry 15

; Copy values from the lookup table into ioff_3..0
get_if_loop
movf INDF, w ; Get the value from the lookup table
movwf INDF ; Store it into ioff_3..0
incf FSR, f ; Point to the next offset byte, ioff_0..3
incf temp, f ; Increment the table index
decfsz count, f ; Decrement the loop count
goto get_if_loop ; Loop while more bytes remain

#### augustinetez

##### Active Member
I do much the same but the table is near the start of the program, it is in the same page as the code that calls it so no need for the PCLATH command.

I didn't include it in my code above as it wasn't relative to my query.

Here it is for completeness - laying it out as 'dt' commands makes it easier to understand each group of offsets and takes up less space on the screen. It assembles as a series 'retlw' commands, same as your code.

The 0-3 etc are the entries into the table while the '00' '01' etc are the values of RA6 & 7 that need to be translated into the index value at the start of each line.

Code:
if_table
dt    0x00, 0X12, 0x7A, 0x00    ; + 8MHz    0-3    00
dt    0xD0, 0X59, 0x99, 0x00    ; + 10.050MHz    4-7    01
dt    0xC0, 0X60, 0xBB, 0x00    ; + 12.28MHz    8-11    10
dt    0x40, 0x54, 0x89, 0x00    ; + 9.00MHz    12-15    11

#### augustinetez

##### Active Member
Have to add that I have heard back from the person I did the software mod for and it works perfectly and he is able to understand it and change the values to suit his equipment.

Replies
4
Views
947
Replies
42
Views
14K
Replies
0
Views
340
Replies
4
Views
791
Replies
11
Views
1K