Since your intervals are all under 65000 one easy change is to make .interval 'uint16_t' instead of 'uint32_t'. That's not enough to fit in an UNO/Nano/Mini so you really need PROGMEM. A quick way was to replace all "[]
" with "[] PROGMEM
".
Then you need to fetch the data from PROGMEM. This is going to involve a lot of changes because the code to go through a sequence was duplicated for each sequence.
x_SEQUENCE[x_SEQUENCE_INDEX].pattern
becomes:
pgm_read_word(&x_SEQUENCE[x_SEQUENCE_INDEX].pattern)
and
intervalLength = x_SEQUENCE[x_SEQUENCE_INDEX].interval;
becomes
intervalLength = pgm_read_word(&x_SEQUENCE[x_SEQUENCE_INDEX].interval);
You should move the code to play a sequence into a function. Then your 'switch/case' cases can be reduced to a single line each. By adding arguments for the list of pins and the number of pins you can use the same 'playSequence()' for all sequences. That would mean the 'pgm_read_word()' calls would be limited to that one function. Much easier to maintain.
void playSequence(const uint16_t *pinArray, size_t pinCount, const seq_entry *sequence, size_t count, uint16_t &index)
{
if (index >= count)
{
index = 0;
}
for (size_t a = 0; a < pinCount; a++)
{
uint16_t pat = pgm_read_word(&sequence[index].pattern);
digitalWrite(pinArray[a], ((pat & (0x1 << a)) == 0) ? LOW : HIGH);
}
intervalLength = pgm_read_word(&sequence[index].interval);
index++;
if (index >= count)
{
index = 0;
}
}
/****************************************************************************** ANIMATIONS ***********************************************************************/
void WHELEN_ANIMATION()
{
switch (WHELEN_pattern)
{
case 1: playSequence(PINS, PINS_NO, WHELEN1_SEQUENCE, WHELEN1_SEQUENCE_NO, WHELEN_SEQUENCE_INDEX); break;
case 2: playSequence(PINS, PINS_NO, WHELEN2_SEQUENCE, WHELEN2_SEQUENCE_NO, WHELEN_SEQUENCE_INDEX); break;
case 3: playSequence(PINS, PINS_NO, WHELEN3_SEQUENCE, WHELEN3_SEQUENCE_NO, WHELEN_SEQUENCE_INDEX); break;
}
}
/*
void GRILL_ANIMATION()
{
playSequence(GRILL_PINS, GRILL_PINS_NO, GRILL_SEQUENCE, GRILL_SEQUENCE_NO, GRILL_SEQUENCE_INDEX); break;
}
*/
void BLINKER_ANIMATION()
{
switch (BLINKER_pattern)
{
case 1: playSequence(BLINKER_PINS, BLINKER_PINS_NO, BLINKER_L_SEQUENCE, BLINKER_L_SEQUENCE_NO, BLINKER_SEQUENCE_INDEX); break;
case 2: playSequence(BLINKER_PINS, BLINKER_PINS_NO, BLINKER_R_SEQUENCE, BLINKER_R_SEQUENCE_NO, BLINKER_SEQUENCE_INDEX); break;
case 3: playSequence(BLINKER_PINS, BLINKER_PINS_NO, BLINKER_4_SEQUENCE, BLINKER_4_SEQUENCE_NO, BLINKER_SEQUENCE_INDEX); break;
}
}
void TA_ANIMATION()
{
switch (TA_pattern)
{
case 0: playSequence(TA_PINS, TA_PINS_NO, TA0_SEQUENCE, TA0_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 1: playSequence(TA_PINS, TA_PINS_NO, TA1_SEQUENCE, TA1_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 2: playSequence(TA_PINS, TA_PINS_NO, TA2_SEQUENCE, TA2_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 3: playSequence(TA_PINS, TA_PINS_NO, TA3_SEQUENCE, TA3_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 4: playSequence(TA_PINS, TA_PINS_NO, TA4_SEQUENCE, TA4_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 5: playSequence(TA_PINS, TA_PINS_NO, TA5_SEQUENCE, TA5_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 6: playSequence(TA_PINS, TA_PINS_NO, TA6_SEQUENCE, TA6_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 7: playSequence(TA_PINS, TA_PINS_NO, TA7_SEQUENCE, TA7_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 8: playSequence(TA_PINS, TA_PINS_NO, TA8_SEQUENCE, TA8_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 9: playSequence(TA_PINS, TA_PINS_NO, TA9_SEQUENCE, TA9_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
case 10: playSequence(TA_PINS, TA_PINS_NO, TA10_SEQUENCE, TA10_SEQUENCE_NO, TA_SEQUENCE_INDEX); break;
}
}