4 digital reads to Dec/Int

What is the most efficient way to do the following --

Read 4 digital lines:
int _pin1 = digitalRead(25); // PIN 1
int _pin2 = digitalRead(24); // PIN 2
int _pin4 = digitalRead(23); // PIN 4
int _pin8 = digitalRead(22); // PIN 8

And convert to a byte (0-15) -- the rotary encoder only goes to 16 positions?

Define "efficient"

AWOL:
Define "efficient"

Most elegant? I was thinking of doing a conditional statement -- but I feel like the same can be accomplished by bitwise operations or some other "algorithm".

Shifts and ORs for me.
But Arduino offers bitWrite.

Based on AWOL's reminder of the bit functions, there is this:

byte inputNibble;  // variable to hold the input 0b0000 to 0b1111. Initializes to zero.
byte inputPins[] =  // array to hold the pin numbers.
{  // Using Mavromatis's pin numbers. Is this a Mega or Due? Just curious.
  25,  // PIN 1 (LSb)
  24,  // PIN 2
  23,  // PIN 4
  22  // PIN 8 (MSb)
};

void setup()
{
  for (byte i = 0; i < 4; i++)
  {
    pinMode(inputPins[i], INPUT);  // Set the input pins to INPUT.
  }
}

void loop()
{
  for (byte i = 0; i < 4; i++)
  {  // Set the bit at i to be the state of input pin i
    bitWrite(inputNibble, i, digitalRead(inputPins[i]));
  }
}

Another method for quick and efficient capture is as long as the 4 input pins are on the four LSb of a hardware port and bit order is the same, directly read the port through a bitmask. But that starts tiptoeing out of Arduino programming and pokes it's nose into AVR programming.

Interesting...

Taking my code in my previous post as is, it compiles in 1.0.4ERW to 1,030bytes. If I just make my array of pins a constant, the compilation size drops to 1,022bytes. (Estimated SRAM usage is 14bytes for both.)
Also, taking the same code and compiling through 1.5.2 I get 1,014bytes. Making the array a constant gets 1,006 bytes. (1.0.3 gets the same compile sizes as 1.5.2., and I don't have normal 1.0.4 installed.)

I wonder if this has to do with short vs. long addressing at the opcode level...

Using a mega -- and thanks! Bitwrite is the answer I was looking for.

This works great --

 byte inputPins[] =  // array to hold the pin numbers.
 { 
  25,  // PIN 1 (LSb)
  24,  // PIN 2
  23,  // PIN 4
  22  // PIN 8 (MSb)
 };

byte decoder()
{
     
  byte tmpBin;
  
  for (byte i = 0; i < 4; i++)
  {  // Set the bit at i to be the state of input pin i
    bitWrite(tmpBin, i, digitalRead(inputPins[i]));
  }

  Serial.println(tmpBin, DEC);
  return tmpBin;  
 
}

Mavromatis:
Using a mega -- and thanks! Bitwrite is the answer I was looking for.

Glad it works for you. Yeah, I knew it was either a Mega or Due. I never see pin numbers that large with my two UNOs. :wink:

Considering your 4 pins are on the same port (PA), you could do without an array, for loop, calls to digitalRead... using something like that:

byte decoder()
{
  return ( PORTA & 0xF0 ) >> 4;
}

I think that's the most efficient/elegant/faster/whatever :slight_smile:

guix:
Considering your 4 pins are on the same port (PA), you could do without an array, for loop, calls to digitalRead... using something like that:

byte decoder()

{
 return ( PORTA & 0xF0 ) >> 4;
}




I think that's the most efficient/elegant/faster/whatever :)

But not really portable across Arduino platforms and restricts what pins can be used. But I do agree that it is really fast (just a couple clock cycles), and elegant in that it actually does describe what is actually being done at the hardware level. The loop I suggested takes longer (probably a couple dozen clock cycles), but it is elegant in its own way by describing the intent of what is being done.

So, yeah... Six of one and half a dozen of the other.