Anyone know the code for the shiftOut function?

Hi all,

I was wondering if anyone knew the code that was used to create the shiftOut function. I’ve heard that it just uses bit banging, but when I tried to create my own code to bit bang the shift of the eight bits, it won’t work. The reason why I’m asking is I would like to work on my project without using the arduino higher level functions. Any help is appreciated.

Thanks.

P.S. Here’s my code that I was using (the commented portion under shiftOut is what I was using to replace it):

void send_info(uint8_t select, uint8_t byte_send){
  // select either command or data to be sent
  if(select == 0x00){
     PORTA &= ~_BV(PA2); 
  }else{
     PORTA |= _BV(PA2); 
  }
  
  PORTA &= ~_BV(PA4); // SET SCLK TO LOW
  PORTA &= ~_BV(PA0); // SET SCE TO LOW (ENABLE)
  shiftOut(25, 26, MSBFIRST, byte_send);
  /*
  uint8_t temp = 0;
  uint8_t i = 7;
  for(i = 7; i >= 0 ; i--){
    temp = byte_send &(0x01 << i); // mask the current bit
    temp = temp >> i; // move the current bit to bit 0
    temp = temp & 0x01; // make sure only the LSB is included
                      
    // send current bit through DN (IF LOW FOR DN BITWISE AND WITH REGISTER, IF HIGH FOR DN BITWISE OR WITH REGISTER)
    if(temp == 0x01){
      PORTA |= _BV(PA3);    
    }else{
      PORTA &= ~_BV(PA3); 
    }
    
    // PULSE THE SCLK
    PORTA &= ~_BV(PA4);
    delay(1);
    PORTA |= _BV(PA4);
    delay(1);
    
  }
  */
  
  PORTA |= _BV(PA0); // SET SCE TO HIGH (DISABLE)
}

Look in wiring_shift.c:

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
      uint8_t i;

      for (i = 0; i < 8; i++)  {
            if (bitOrder == LSBFIRST)
                  digitalWrite(dataPin, !!(val & (1 << i)));
            else      
                  digitalWrite(dataPin, !!(val & (1 << (7 - i))));
                  
            digitalWrite(clockPin, HIGH);
            digitalWrite(clockPin, LOW);            
      }
}

Thanks, Paul. That was what I was looking for.

I recently spent a bit of time optimizing an 8-bit shift out function and settled on this:

void putByte(uint8_t value) {
  uint8_t mask = 0x80, i;
  for (i = 8; i > 1; i--) {
    digitalWrite(dataPin, value & mask);
    delayMicroseconds(SETUP_TIME);
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(CLOCK_HIGH);
    digitalWrite(clockPin, LOW);
    delayMicroseconds(CLOCK_LOW);
    mask >>= 1;
  }
}

Only one shift instruction per loop, digitalWrite sets the pin HIGH for any non-zero value, and found that counting down from 8 resulted in smaller code than counting up from 0. YMMV.

(edited: originally typed "delay" when I meant "delayMicroseconds". I included these because I don't like depending on the execution time of digitalWrite)

And I like mine as well.

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
{
    byte mask = ((LSBFIRST != bitOrder) ? B10000000 : B00000001);
    
    do
    {
        digitalWrite(dataPin, !!(mask & val));
        
        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
    } while ( mask = ((LSBFIRST != bitOrder) ? (mask >> 1) : (mask << 1)) );
}

I recently spent a bit of time optimizing an 8-bit shift out function and settled on this

Changing from the data and clock pins being input to being global variables is not a good thing.

Your function can not be used to output data to different pins in one sketch, if #define or const int is used to define the pin numbers (which is preferred).

Changing from the data and clock pins being input to being global variables is not a good thing.

In this case, it's part of a library and the pin numbers are passed through the constructor. Is there still a better way?

Is there still a better way?

Pass the pin numbers as arguments, just like the original shiftOut function is used.

In general a variable should have only the scope it needs, and no more.

I don’t want to hijack this thread but I am interested in best practices for the libraries I am writing. Specifically to this case, you could take a look at the enhancements I’ve posted to the Sensirion library (which contains putByte and getByte functions to keep this thread relevant :slight_smile: ) The original version of the library I based my work on passes the pin numbers via the constructor and stores them in private variables. I prefer this over including them in each user-level function call (which I hope isn’t what you mean). Inside the library, I could pass the pin numbers down from the public functions to the low-level functions that will eventually require them but wouldn’t that add bytes to the stack for each level of function call? I am trying to keep this library as small as possible (RAM and program memory) and I’m not clear this is worth the trade-off. Thanks.

I prefer this over including them in each user-level function call (which I hope isn't what you mean).

It wasn't. I was referring more generally to sketch functions.

Inside the library, I could pass the pin numbers down from the public functions to the low-level functions that will eventually require them but wouldn't that add bytes to the stack for each level of function call?

Two bytes for each int argument. One byte for each byte argument. I'm not sure why pin numbers are ints. They really don't need to be. There are not even close to 255 of them on any Arduino.

The stack consumes space in SRAM, but only during the function call. It would be an issue only when SRAM is in very short supply. Even then, I don't think that global variables or private/public members are the answer.

I'm not sure why pin numbers are ints.

They shouldn't be - I used uint8_t (and I believe Arduino's digitalWrite / digitalRead do as well).

The stack consumes space in SRAM, but only during the function call.

True - and I don't think I have more than three levels of calls so the usage would be small but I've run out of RAM enough times to be sensitive to it.

Even then, I don't think that global variables or private/public members are the answer.

Trying to understand the alternatives for libraries as I'm not a c++ expert: - Passing the pin numbers via the constructor seems like a good idea. Is there another way to store them besides as private class variables? - If not, doesn't that make them accessible to all functions in the class? If so, then I'm not sure what I gain by not simply referencing directly them where needed.

Passing the pin numbers via the constructor seems like a good idea.

Agreed.

Is there another way to store them besides as private class variables?

No.

If not, doesn’t that make them accessible to all functions in the class?

Yes.

If so, then I’m not sure what I gain by not simply referencing directly them where needed.

None.

When I first brought the issue up, it was not in the context of a member of a class. The shiftOut function that was shown as an alternative to the Arduino-provided shiftOut function was not (that I remember) mentioned as being a class method.

In that case, not passing the pin numbers as arguments IS a big(ger) deal.

Personal preference but I prefer something along the lines of the following as well.

struct input_component_t
{
    const uint8_t   _pin;
    
    input_component_t(byte pin)     : _pin(pin) { pinMode(_pin, INPUT); }
}

struct output_component_t
{
    const uint8_t   _pin;
    
    output_component_t(byte pin)    : _pin(pin) { pinMode(_pin, OUTPUT); }
}


output_component_t  g_compLED(13);
input_component_t   g_compButton(9);


void loop()
{
    ... code ...
    ... code ...
    ... code ...
    ... code ...
}

void setup()
{}

As I/O objects the pin numbers are stored as constants within the object itself thus it knows its pin assignment. Additionally being an object it is able to set its pin mode during construction. Remember that class instance constants must be initialized in the constructors initializtion list before any instance variables.