Teensy 4.0 how to bitbang with shiftOut_lsbFirst?

Aende

New member
Hello together,

I need to steer a CPLD test mode via SPI in my project but the lowest SPI speed is just too fast for the CPLD.
So, instead of using SPI on pins 11-Data,13-Clock I used the shiftOut_lsbFirst function on a Teensy 3.2 on these pins.

Transferring a byte tooks 4ms which works fine (Signal Pin 13):
2024-06-13_09h57_39.png


Used function:
Code:
//*--------------------------------------------------------------------------------------------------------
//  send 3 bytes to the CPLD via shiftOut
//*--------------------------------------------------------------------------------------------------------
void SetCPLD_SO(uint32_t buf) {
  uint8_t bytes[3];
 
  bytes[0] = buf & 0xFF;
  bytes[1] = (buf >> 8)  & 0xFF;
  bytes[2] = (buf >> 16) & 0xFF;
  Serial.print("CPLD set: ");
  for (int c = 0; c < 3; c++)
  {
    Serial.print("0x"); 
    Serial.print(bytes[c], HEX);
    Serial.write(' ');
  } 
  Serial.print('\n');
  #ifdef shiftOut
  digitalWrite(slaveSelectPin,HIGH);   
  delayMicroseconds(250);
  shiftOut_lsbFirst(shiftOut_Data,shiftOut_Clock,bytes[0]);
  shiftOut_lsbFirst(shiftOut_Data,shiftOut_Clock,bytes[1]);
  shiftOut_lsbFirst(shiftOut_Data,shiftOut_Clock,bytes[2]);
  delayMicroseconds(250);
  digitalWrite(slaveSelectPin,LOW);
  delayMicroseconds(250);
  digitalWrite(t_EnablePin,LOW);
  delayMicroseconds(250);
  digitalWrite(t_EnablePin,HIGH);
  #endif
}

Using the code on a Teensy 4.0 on the same pins doesn't work. I'm not getting any signal on the clock pin 13. Checking the definition of shiftOut_lsbFirst inside digital.c doesn't give me any hint why I'm not able to produce any clock signal. Can someone give me a hint how I can shift out 3 bytes in 12ms?

Snippet of .platformio.packages.framework-arduinoteensy.cores.teensy4.digital.c:

Code:
static const unsigned maxSpeed = 10000000ULL; //10 MHz
static const unsigned maxSpeedBeforeDelay = 392000000ULL; //max F_CPU_ACTUAL before doing delays (measured for 10MHz, -O2)
void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value)
{
    uint8_t mask;
    if (F_CPU_ACTUAL > maxSpeedBeforeDelay) {
        uint32_t cycles = (F_CPU_ACTUAL / 2 / maxSpeed);
        uint32_t t = ARM_DWT_CYCCNT;
        for (mask = 0x01; mask; mask <<= 1) {
            digitalWrite(dataPin, value & mask);
            do {;} while(ARM_DWT_CYCCNT - t < cycles);
            t += cycles / 2;
            digitalWrite(clockPin, HIGH);
            do {;} while(ARM_DWT_CYCCNT - t < cycles);
            t += cycles;
            digitalWrite(clockPin, LOW);
            do {;} while(ARM_DWT_CYCCNT - t < cycles);
            t += cycles / 2;
        }
    }
    else
    for (mask=0x01; mask; mask <<= 1) {
        digitalWrite(dataPin, value & mask);
        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
    }
}
 
Oh, my fault. There's a signal on pin 13. I missed the correct setting of time in the oszi :-(. Sorry
Now I adjust the both parameters to get the correct settings to transfer a byte in 4ms.
The board is running at board_build.f_cpu = 100000000 //100MHz
 
Last edited:
Back
Top