Reading multiple digital IN, use IF/THEN/ELSE or Case or what?

Moving to the ASK the Community forum per suggestion.

aI am the Coach and programming mentor for Thunderstorm Robotics from Payne County Oklahoma, Heartland Trails BEST Hub. Game day is less than 2 weeks away. We don’t even have an actual connection for the digital inputs yet to read in so I haven’t tested the code. I just worked it up this weekend. I have programmed a very little in VB and tried to learn basics of C/C++ and Java. Just getting values of 3 digital inputs and comparing to a table of 8 possible combinations and then sending that back to a switch case to provide some kind of visual output depending on the unsigned char that’s returned.

I have the code that follows setup to read in three digital inputs (set as global unsigned chars) in a user function and then it runs through the possibilities and returns an unsigned char back to the main routine. First, am I setting the conditions correctly in the If’s? Also, would this be better set as a switch case??? And if so, then how to implement the multiple variables in the Switch statement.
Also, all variables are default to = 1 so that the last result is true and kicks out of the user function back to main.

#include "Main.h"

unsigned char Func_DataPort ( void )
{ // runs the routine to retrieve data port assignments and create a variable with the results
      unsigned char Port_Set = 1; 

      CHAR_PG2 = GetDigitalInput ( 1 ) ;
      CHAR_PG1 = GetDigitalInput ( 2 ) ;
      CHAR_PG0 = GetDigitalInput ( 3 ) ;
      if ( CHAR_PG2 == 0 & CHAR_PG1 == 1 & CHAR_PG0 == 1 )
      {
            Port_Set = 2 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 1 & CHAR_PG1 == 1 & CHAR_PG0 == 0 )
      {
            Port_Set = 3 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 1 & CHAR_PG1 == 0 & CHAR_PG0 == 1 )
      {
            Port_Set = 4 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 1 & CHAR_PG1 == 0 & CHAR_PG0 == 0 )
      {
            Port_Set = 5 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 0 & CHAR_PG1 == 1 & CHAR_PG0 == 0 )
      {
            Port_Set = 6 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 0 & CHAR_PG1 == 0 & CHAR_PG0 == 1 )
      {
            Port_Set = 7 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 0 & CHAR_PG1 == 0 & CHAR_PG0 == 0 )
      {
            Port_Set = 8 ;
            return Port_Set ;
      }
      else if ( CHAR_PG2 == 1 & CHAR_PG1 == 1 & CHAR_PG0 == 1 )
      {
            Port_Set = 1 ;
            return Port_Set ;
      }
}

Thanks for your answers.

Please do not double post, your question was answered in the easyC thread and General Forum

I assume the three “CHAR_PG#” variables are declared globally?
Other than that, you appear to be setting up the conditions correctly.

switch statements typically compile down to the same code that an “if/else if” list does. It may be a few instructions shorter one way or the other, but it is unlikely to make a big difference.

switch statements cannot operate on multiple variables. You can combine the three values into a single variable (as jgraber describes).

You could then use that value directly (if you could re-arange your values for Port_Set), or you could use it as an index into an array that maps the value to the desired output value. Something like this:


#include "Main.h"

const unsigned char Port_Set_Mapping[8] = ( 8, 7, 6, 2, 5, 4, 3, 1 );

unsigned char Func_DataPort ( void )
{ // runs the routine to retrieve data port assignments and create a variable with the results
    unsigned char Port_Set = 0; 
    
    CHAR_PG2 = GetDigitalInput ( 1 ) ;
    CHAR_PG1 = GetDigitalInput ( 2 ) ;
    CHAR_PG0 = GetDigitalInput ( 3 ) ;
    
    if ( CHAR_PG2 ) Port_Set |= 4 ;
    if ( CHAR_PG1 ) Port_Set |= 2 ;
    if ( CHAR_PG0 ) Port_Set |= 1 ;
    
    // Port_Set now contains a value 0..7
    // Translate that into the desired value using Port_Set_Mapping]
    
    return Port_Set_Mapping  Port_Set ] ;
}

Personally, I prefer to structure code in the way that best expresses what is actually happening. Only go through the trouble of optimizing if testing reveals you have a performance issue. This generally makes the code easier to understand and maintain.

The code is very clear the way you have it written, though you might want to add some comments about what each Port_Set value means.

Also, you could replace the eight “return Port_Set;” lines with a single one at the bottom of the function. Or you could eliminate the Port_Set variable entirely, and simply replace each assignment/return pair with “return 3;”, return 8;" ,…

An alternative way to code this could be to use a binary decision tree.
Something like this:


#include "Main.h"

unsigned char Func_DataPort ( void )
{ // runs the routine to retrieve data port assignments and create a variable with the results
    unsigned char Port_Set = 1; 
    
    CHAR_PG2 = GetDigitalInput ( 1 ) ;
    CHAR_PG1 = GetDigitalInput ( 2 ) ;
    CHAR_PG0 = GetDigitalInput ( 3 ) ;

    if ( CHAR_PG2 == 0 )
    {
        if ( CHAR_PG1 == 0 )
        {
            if ( CHAR_PG0 == 0 )
            {
                Port_Set = 8 ;
            }
            else    // CHAR_PG0 == 1
            {
                Port_Set = 7 ;
            }
        }
        else    // CHAR_PG1 == 1
        {
            if ( CHAR_PG0 == 0 )
            {
                Port_Set = 6 ;
            }
            else    // CHAR_PG0 == 1
            {
                Port_Set = 2 ;
            }
        }
    }
    else    // CHAR_PG2 == 1
    {
        if ( CHAR_PG1 == 0 )
        {
            if ( CHAR_PG0 == 0 )
            {
                Port_Set = 5 ;
            }
            else    // CHAR_PG0 == 1
            {
                Port_Set = 4 ;         
            }
        }
        else    // CHAR_PG1 == 1
        {
            if ( CHAR_PG0 == 0 )
            {
                Port_Set = 3 ;
            }
            else    // CHAR_PG0 == 1
            {
                Port_Set = 1 ;
            }
        }
    }
    
    return Port_Set ;
}

This may look like more code, but it will compile to a shorter binary and run slightly faster. The reason is that each of your if statements is actually three if statements on one line. The binary decision tree ensures you will have a result after exactly three if statements.

In the end, I don’t think any of these variations will make a relevant difference to the speed of execution. I’d suggest you keep the code structured in whatever way it makes the most sense to you, or whoever will be maintaining it.

Cheers,

  • Dean

[Warning - I haven’t compiled any of this code, so there may be errors.]