-3

Im using a PIC18 on Mplab IDE in Assembly language where I have four LEDs. 2 LEDs tell me the status #1 and the 2 other LEDs the status #2. Finally, I have 2 more output LEDs to tell me the status of these 4 LEDs based on their status. This can be done using a switch statement to check the 4 LEDs' status and thus have the output led green or red. Each LEDs is connected to different Ports pins in the PIC18f as well the output LEDs to other pins. The final output leds will be based on the four leds status

sat#1 Red sat#1 Green sat#2 Red sat#2 Green out Red Out Green
1 0 0 0 0 0 0
2 0 0 0 1 0 1
3 0 0 1 0 1 0
4 0 1 0 0 0 0
5 1 0 0 0 0 0
6 1 0 1 0 1 0
7 0 1 0 1 0 1
8 0 1 1 0 1 0
9 1 0 0 1 1 0
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Citi
  • 47
  • 6
  • 4
    You don't need branching in the code: you could just use a data lookup table if you can efficiently turn your 4 input bits into one 4-bit integer. Or if the two output bits can each be computed as boolean functions of the 4 inputs, then that's also good. e.g. LED OUT Green = `op2green & ~op1red` seems to work for the 10 rows you've shown of the truth table; IDK if any of the other 6 possible states might be a problem for that expression, if they're possible at all. (I assume the 4th column is supposed to be OP#2 Green, not another OP#1 Green?) – Peter Cordes Jul 24 '21 at 02:21
  • 1
    Also I think `outred = op1red | op2red` works for the first output row. – Peter Cordes Jul 24 '21 at 02:27
  • 1
    Oh yeah, looks like it needs an `& ~out2green` (again assuming that's what the 4th input column really is, since the image still has duplicate labels. Also, don't post pictures of text. Stack Overflow has table formatting markdown: [New Feature: Table Support](https://meta.stackexchange.com/q/356997), or use a code block.) – Peter Cordes Jul 25 '21 at 01:22
  • 1
    Looks like you used `add` instead of `and`, unless that was intentional to use add's xor + carry operation. – Peter Cordes Jul 25 '21 at 01:52

1 Answers1

1

There are several ways to implement a solution code for your problem. But we keep it as simple as possible. ATTENTION this is not a whole complete code. I just give you the function implementations and you have to merge the big picture by making use of this implementation.

First of all we are going to define an input holding register, its bits and active cases for both output red and output green. Now that we have all cases defined, in the main loop wee need to scan input statuses and hold the last status in a register called inStates or call it whatever you wish. After that, we update the output LEDs according to the table that you showed in your question.

shared      UDATA_SHR   ; Declare variables in shared RAM
inStates    RES     1   ; Input states holder variable

; Bit definitions for inputs
OP1RED_BIT      EQU 0 ; bit-0 holds value for op#1 Red
OP1GREEN_BIT    EQU 1 ; bit-1 holds value for op#1 Green
OP2RED_BIT      EQU 2 ; bit-2 holds value for op#2 Red
OP2GREEN_BIT    EQU 3 ; bit-3 holds value for op#2 Green

; Active case definitions for out LED red
OUT_LED_RED_CASE_1  EQU (1 << OP2RED_BIT) ; case 1
OUT_LED_RED_CASE_2  EQU ( (1 << OP1RED_BIT) | (1 << OP2RED_BIT) ) ; case 2
OUT_LED_RED_CASE_3  EQU ( (1 << OP1GREEN_BIT) | (1 << OP2RED_BIT) ) ; case 3
OUT_LED_RED_CASE_4  EQU ( (1 << OP1RED_BIT) | (1 << OP2GREEN_BIT) ) ; case 4

; Active case definitions for out LED green
OUT_LED_GREEN_CASE_1    EQU (1 << OP2GREEN_BIT) ; case 1
OUT_LED_GREEN_CASE_2    EQU ( (1 << OP2GREEN_BIT) | (1 << OP1GREEN_BIT) ) ; case 2


; Maybe here there is some piece of init codes


main_loop:

    ; Other codes if applicable...
    
    ; Somewhere in the main loop
    call        readInStats ; read the input states
    call        setStateForOutLedRed ; set out red LED accordingly
    call        setStateForOutLedGreen ; set out green LED accordingly
    
    ; Other codes if applicable...
    
    goto        main_loop

; Assuming that the access bit is enabled...
readInStats:
    clrf        inStates
    btfsc       OP1RED_PORT, OP1RED_BIT
    bsf         inStates, 0
    btfsc       OP1GREEN_PORT, OP1GREEN_BIT
    bsf         inStates, 1
    btfsc       OP2RED_PORT, OP2RED_BIT
    bsf         inStates, 2
    btfsc       OP2GREEN_PORT, OP2GREEN_BIT
    bsf         inStates, 3
    ; Read complete
    return

setStateForOutLedRed:
    movlw       OUT_LED_RED_CASE_1
    xorwf       inStates, w
    bz          doSetOutRed
    movlw       OUT_LED_RED_CASE_2
    xorwf       inStates, w
    bz          doSetOutRed
    movlw       OUT_LED_RED_CASE_3
    xorwf       inStates, w
    bz          doSetOutRed
    movlw       OUT_LED_RED_CASE_4
    xorwf       inStates, w
    bz          doSetOutRed
    ; if the flow reaches here then no cases match to set red LED
    bcf         OUT_LED_RED_PORT, OUT_LED_RED_BIT
    return
doSetOutRed:
    ; One of the cases matches to set red LED
    bsf         OUT_LED_RED_PORT, OUT_LED_RED_BIT
    return;

setStateForOutLedGreen:
    movlw       OUT_LED_GREEN_CASE_1
    xorwf       inStates, w
    bz          doSetOutGreen
    movlw       OUT_LED_GREEN_CASE_2
    xorwf       inStates, w
    bz          doSetOutGreen
    ; if the flow reaches here then no cases match to set green LED
    bcf         OUT_LED_GREEN_PORT, OUT_LED_GREEN_BIT
    return
doSetOutGreen:
    ; One of the cases matches to set green LED
    bsf         OUT_LED_GREEN_PORT, OUT_LED_GREEN_BIT
    return;
    

Update for inStates structure info

inState Register Bits

bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
not used not used not used not used holds OP2GREEN_BIT holds OP2RED_BIT holds OP2RED_BIT holds OP1RED_BIT

If you have a look at readInStats function we read and save the values in this order to the inState register. If you flip the order, it will be the same order as in your truth table. I will share the active case assignments in binary format instead of shifting for you to better understand.

; Active case definitions for out LED red
OUT_LED_RED_CASE_1  EQU B'00000100' ; case 1
OUT_LED_RED_CASE_2  EQU B'00000101' ; case 2
OUT_LED_RED_CASE_3  EQU B'00000110' ; case 3
OUT_LED_RED_CASE_4  EQU B'00001001' ; case 4

; Active case definitions for out LED green
OUT_LED_GREEN_CASE_1    EQU B'00001000' ; case 1
OUT_LED_GREEN_CASE_2    EQU B'00001010' ; case 2

If you flip the low nibbles (lower 4 bits) you will see the same values as in your truth table that sets the corresponding outputs as 1. This how you can interpret a truth table as coding constant values.

Update: Fix for memory allocation in absolute mode

Just change these 2 lines of code:

shared      UDATA_SHR   ; Declare variables in shared RAM
inStates    RES     1   ; Input states holder variable

to this line:

inStates    EQU     0 ; Allocate a byte of memory in shared memory at address 0x00

Change you code and try compiling again, it must compile now without a linker problem.

Kozmotronik
  • 2,080
  • 3
  • 10
  • 25
  • Thank you, for your response. I'll give it a try. Im just confused about holding register, its bits, because the op1 red, op1green, op2red, op2green are Port pins that are outputs and they chanage status. So I just wanted to find a simple way to check their status. On my code above I was trying to take the status value 0 or 1 into the WERG – Citi Jul 26 '21 at 06:54
  • Also use the file register to do some bit manipulation AND/OR , and thus setting ledout green or red. I'll try to understand your function implementation to merge the big picture – Citi Jul 26 '21 at 06:56
  • 1
    Take it easy, give it a try. I used a holding register because the status LEDs might be at different pins of the different ports. This way I collect the status of each pin reading one by one and save their statuses in a holding register in order to make the checks of the case values I defined earlier. Don't hesitate to ask anything that make you confuse. I'd like to make you understand. – Kozmotronik Jul 26 '21 at 07:48
  • As for the Bit definitions for inputs, and Active case definitions for out LED. If possible can you show me like how a condition from the table would look like in the code. Thank you so much for your help – Citi Jul 27 '21 at 07:00
  • I feel if I clearly understand these bit and active definitions. Like in Bit definitions EQU 0,1,2,3, those are addresses that I can choose to hold the value and I'm confused about the Active def. shifting and the use of OR. Again thank you – Citi Jul 27 '21 at 07:04
  • @Citi you must have a digital electronics and logic circuit design background so that you can interpret a truth table logically and convert your interpretation into some code or logic circuit. Now the question is do you have that background or knowledge? Since this site is not an educational site, I cannot give you tutorials here. But we can do it by asking and answering. Don't hesitate to post new questions for different topics. But before, make sure it is not answered in here before you post it. – Kozmotronik Jul 27 '21 at 08:49
  • Don't forget, ask your questions clear, and just one question for each topic to comply the requirements of this site. – Kozmotronik Jul 27 '21 at 08:50
  • Yes, I have some background, but for instance OUT_LED_RED_CASE_2 EQU ( (1 << OP1RED_BIT) | (1 << OP2RED_BIt. Let say op1red bit =1 and op2red =0 then out_led_red (10 |01) = 11. Then case 2 will hold 11 right? – Citi Jul 27 '21 at 19:58
  • 1
    No, it won't. It will hold a constant value that is `0b00000101` in binary, which corresponds to the 6th row of your truth table. In the 6th row when both opred1 and opred2 are 1 then the outred will be 1. Since I hold opred1 in bit0, opred2 in bit2 it looks in binary form `0b00000101`. Does it make sense now? – Kozmotronik Jul 27 '21 at 20:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235358/discussion-between-kozmotronik-and-citi). – Kozmotronik Jul 27 '21 at 21:04