Help me improve "shiftOut" speed

So far, I have improved the theoretical speed more than 8 times than the original shiftOut function for my specific project., and I am pretty sure more can be done. I am using a high speed 595 chip, so what is the theoretical maximum switching speed for it? According to my test and understanding, when using a clock speed of 8mhz, the maximum switching speed for the 595 should be about 32khz. (see shiftOutxxx() ), so if that is the case, I have a long way to go, from 12k to 32k.

Also, I notice something is wrong with the original shiftOut function. A low−to−high transition on S-clk shifts the data on the S-in pin into the register, but it’s high-to-low there.

//shiftOut(dataPin, clockPin, MSBFIRST ,tog);  //1.5k
//shiftOutx(dataPin, clockPin ,tog); //2.7k
//shiftOuty(dataPin ,tog); //5.2k-6k
//shiftOutz(tog); //8.9K-11.3k
//shiftOutk(tog); //9.5K-12.4

shiftOutxxx(tog); //32k
#include "fastDW.h"

byte latchPin = 13; //B5
byte clockPin = 12; //B4
byte dataPin = 11;  //B3

byte tog;

void setup() {
DDRD=0b11111110;
DDRB=0b00111111;

PORTD=0b11111110;
PORTB=0b00001111;

PORTD=0b00000000;
PORTB=0b00000000;
}

void loop() {

while(1){

tog=!tog;
//fastDW(latchPin, LOW);
PORTB &= ~(1<<5);

//shiftOut(dataPin, clockPin, MSBFIRST ,tog);  //1.5k
//shiftOutx(dataPin, clockPin ,tog); //2.7k
//shiftOuty(dataPin ,tog); //5.2k-6k
//shiftOutz(tog); //8.9K-11.3k
//shiftOutk(tog); //9.5K-12.4

shiftOutxxx(tog); //32k
           
PORTB |= (1<<5);   
//fastDW(latchPin, HIGH);
  
  }
}

void shiftOutx(uint8_t pin, uint8_t clockPin, uint8_t val)
{
     for (uint8_t i = 0; i < 8; i++)  {
           fastDW(dataPin, !!(val & (1 << (7 - i))));
           fastDW(clockPin, LOW);  
           fastDW(clockPin, HIGH);         
     }
}


void shiftOuty(uint8_t pin, uint8_t val)
{
     for (uint8_t i = 0; i < 8; i++)  {
           fastDW(dataPin, !!(val & (1 << (7 - i))));
           PORTB &= ~(1<<4);
           PORTB |= (1<<4);      
     }
}


void shiftOutz( uint8_t val)
{
     for (uint8_t i = 0; i < 8; i++)  {
           PORTB =  (PORTB & ~(1<< 3)) | (!!(val & (1 << (7 - i))) <<3 );
           PORTB &= ~(1<<4);
           PORTB |= (1<<4);      
     }
}

void shiftOutk( uint8_t val)
{
     for (uint8_t i = 0; i < 8; i++)  {
           if (val & (1 << (7 - i))) PORTB |= 1<<3;
           else PORTB &= ~(1<<3);
           PORTB &= ~(1<<4);
           PORTB |= (1<<4);      
     }
}


void shiftOutxxx(uint8_t val)
{
  uint8_t c=0;
     while(c<8)  {
           c++;
           if(val)PORTB = 1<<3;
           else PORTB &= ~(1<<3);
           PORTB &= ~(1<<4);
           PORTB |= (1<<4);      
     }
}

Why don't you just use SPI? It has a clock speed of 8 MHz, it'll shift those bits out in no time.

Pieter

PieterP:
Why don't you just use SPI? It has a clock speed of 8 MHz, it'll shift those bits out in no time.

Pieter

Maybe because it's not wired like that, even if it uses all those SPI pins.

Take a look at Nerd Ralph: Fastest AVR software SPI in the West

westfw:
Take a look at Nerd Ralph: Fastest AVR software SPI in the West

Is there a good reason to take a look at that when my question is about "improving "shiftOut" speed" and that my hardware doesn't support ISP?

flyandance:
and that my hardware doesn't support ISP?

Who said ISP.

What hardware.

Wawa:
Who said ISP.

What hardware.

typo

byte latchPin = 13; //B5
byte clockPin = 12; //B4
byte dataPin = 11; //B3

Is there a good reason to take a look at that when my question is about "improving "shiftOut" speed" and that my hardware doesn't support ISP?

SPI (not ISP) output-only is essentially identical to shiftOut(); there just aren't that many combinations of "data on one pin, clock on another pin" that COULD exist. (That's also why people are pointing you at the SPI hardware peripheral.)
Ralph's code is good enough that I can't immediately see any way to improve it, and his blog post covers some of the issues and strategies involved in implementing it.

westfw:
SPI (not ISP) output-only is essentially identical to shiftOut(); there just aren't that many combinations of "data on one pin, clock on another pin" that COULD exist. (That's also why people are pointing you at the SPI hardware peripheral.)
Ralph's code is good enough that I can't immediately see any way to improve it, and his blog post covers some of the issues and strategies involved in implementing it.

They are definitely NOT identical. With shiftout(), you can use on any pins, but for SPI, it only works on those SPI pins. I already have the board made, so I can't change the pins. You are NOT only not really answering my question, but I think you didn't really get my question in the first place. It's like, I asked how to cook a steak, and you direct me to McDonald. Surely, Mc's burger is yum, but steak and burger are kinda not the same thing, even thought they are like from the same animal.

Hi,
What is the application that needs high data rate?
How many 595 chips are you aiming to use?

Thanks.. Tom... :slight_smile:

TomGeorge:
Hi,
What is the application that needs high data rate?
How many 595 chips are you aiming to use?

Thanks.. Tom... :slight_smile:

Nothing fanny, I am just trying to add PWM to 80 leds. It has only 1 595, but since the outputs of the 595 are used as common anodes for the 8x10 matrix, it takes 8x2=16 of those shiftout for one multiplexing cycle. With my slightly improved shiftout, I can achieve 1.6khz for each count without much flickering. My aim would be about 6khz for each count for the PWM to work flawlessly.

for SPI, it only works on those SPI pins.

SPI is a “protocol” as well as a peripheral. If you’d spent half as much time actually looking at the page I linked as you did complaining that it wasn’t a suitable answer, you would have noticed pretty quickly that it is exclusively about implementing the SPI protocol on arbitrary pins…

westfw:
SPI is a "protocol" as well as a peripheral.

We are familiar with these jargon: Peripheral Controller, Peripheral Device, and Peripheral.

I would be glad to know which one of the following you would like to refer as peripheral/make a synopsis on the quoted text.

USB Port-driven External Modem is a Peripheral Device.

USB Port Controller is a Peripheral Controller.

which one of the following you would like to refer as peripheral

I've never really treated "peripheral controller" and "peripheral device" as having separate, distinct, meanings.
From a high-level perspective, I was taught that pretty much anything in a computer system that was CPU or Memory was a "peripheral." From the microcontroller perspective, I might limit "peripheral controller" to hardware logic inside the chip itself, with "peripheral device" including the thing that you're connecting to the chip.
In the case of a 74x595, the peripheral controller could be GPIO, the SPI controller, or the USART in synchronous mode, while the "peripheral device" would be the 595 chip (and whatever it's connected to, as well.)
The "device" can be "far away" from the actual chip. If I connect from my ASR33 teletype to a TCP/IP terminal server, make a telnet connection to a host on the other side of the world using the internet, where that host is connected over Ethernet using a WizNet chip that talks SPI to an Arduino, then I'm probably still willing to consider the ASR33 a "peripheral device" of the Arduino...

USB Port-driven External Modem is a Peripheral Device.
USB Port Controller is a Peripheral Controller.

That seems to be in agreement with my thinking. I would not want to define the terms so tightly that, say, a class exam would include a list of things that needed to be "correctly" sorted into the "peripheral controller" vs "peripheral device" categories.

I have showed my courage to place the queries; the answers have come boldly with enough clarity and brevity. I am thanked to have my understandings further nourished. :slight_smile:

westfw:
SPI is a "protocol" as well as a peripheral. If you'd spent half as much time actually looking at the page I linked as you did complaining that it wasn't a suitable answer, you would have noticed pretty quickly that it is exclusively about implementing the SPI protocol on arbitrary pins...

It's kinda dumb to implement something which is not into something kind of, and it really wouldn't work either since the 74HC595 needs additional latch clock. It's kinda like you want to eat a burger, but you are a vegan, so instead of going to MacDonald and eat a tasty burger like a normal human being, you decided to invent a vegan burger and force yourself into accepting it as a similar replacement or even superior choice. In my case, I was just asking how to improve the taste of my real little humble burger, and then you decided to recommend this vegan burger to me. It probably is taster than mine, but at what cost? and if you really know how SPI works or/and what a good nutritious diet is, you can easily tell both the above things are nothing but gimmicks that only teenage girls and middle age men will be interested in.

Hi,
Is there a reason you are not using a TLC5940, which is a 16ch PWM expansion IC?

https://playground.arduino.cc/Learning/TLC5940

Its is open collector/sink so will work with common anode array.

Tom... :slight_smile:

flyandance:
It's kinda dumb to implement something which is not into something kind of, and it really wouldn't work either since the 74HC595 needs additional latch clock. It's kinda like you want to eat a burger, but you are a vegan, so instead of going to MacDonald and eat a tasty burger like a normal human being, you decided to invent a vegan burger and force yourself into accepting it as a similar replacement or even superior choice. In my case, I was just asking how to improve the taste of my real little humble burger, and then you decided to recommend this vegan burger to me. It probably is taster than mine, but at what cost? and if you really know how SPI works or/and what a good nutritious diet is, you can easily tell both the above things are nothing but gimmicks that only teenage girls and middle age men will be interested in.

No, you still don't understand. SPI refers to the protocol and timing of the link.
What you have with those shift registers is 100% compatible with SPI. MISO isn't used, MOSI is DS, CLK is SH_CP, and CS is ST_CP. You don't have to use the SPI hardware to benefit from the software SPI implementations others have written.