But... it seems
Code:
if (digitalReadFast(portPinsC[0])) ret |= (1<<0);
if (digitalReadFast(portPinsC[1])) ret |= (1<<1);
if (digitalReadFast(portPinsC[2])) ret |= (1<<2);
if (digitalReadFast(portPinsC[3])) ret |= (1<<3);
if (digitalReadFast(portPinsC[4])) ret |= (1<<4);
if (digitalReadFast(portPinsC[5])) ret |= (1<<5);
if (digitalReadFast(portPinsC[6])) ret |= (1<<6);
if (digitalReadFast(portPinsC[7])) ret |= (1<<7);
that is very slow (Teensy 4.0 800 MHz)... slower as with Teensy 3.5 with 164 Mhz.
Sometimes code fragments like the above it is hard to know what the code will compile to without having any idea of some of your definitions.
That is if you look at the code fragment: digitalReadFast(portPinsC[1])
How is portPinsC[1] defined as?
What I ask is digitalReadFast is setup that IF the pin number passed in was a built in constant, than the compiler reduces all of the code down to something real simple:
Code:
uint8_t digitalRead(uint8_t pin);
static inline uint8_t digitalReadFast(uint8_t pin) __attribute__((always_inline, unused));
static inline uint8_t digitalReadFast(uint8_t pin)
{
if (__builtin_constant_p(pin)) {
if (pin == 0) {
return (CORE_PIN0_PINREG & CORE_PIN0_BITMASK) ? 1 : 0;
} else if (pin == 1) {
return (CORE_PIN1_PINREG & CORE_PIN1_BITMASK) ? 1 : 0;
} else if (pin == 2) {
return (CORE_PIN2_PINREG & CORE_PIN2_BITMASK) ? 1 : 0;
} else if (pin == 3) {
return (CORE_PIN3_PINREG & CORE_PIN3_BITMASK) ? 1 : 0;
} else if (pin == 4) {
return (CORE_PIN4_PINREG & CORE_PIN4_BITMASK) ? 1 : 0;
} else if (pin == 5) {
return (CORE_PIN5_PINREG & CORE_PIN5_BITMASK) ? 1 : 0;
} else if (pin == 6) {
...
So the compiler with optimizer if you call it with a constant like 0,
The code will be reduced to: CORE_PIN0_PINREG & CORE_PIN0_BITMASK) ? 1 : 0;
However if it is not a constant that the compiler can not deduce at compile time:
Then it will reduce to: return (*portInputRegister(pin) & digitalPinToBitMask(pin)) ? 1 : 0;
So it will have to do two macros, both which index into an array with the pin number and then extract either the address of the register or the mask. So again more code.
So again I don't know fully all of the details on how the compiler decides if __builtin_constant_p
For example if your array is setup: as const uint8_t portPinsC[] = {0, 1, 2, 3, 4, 5, 6, 7};
Then hopefully it will deduce the constants...