// https://forum.arduino.cc/t/issue-with-matrix-keypad-vs-pull-up-buttons-in-the-code/1239164
// https://wokwi.com/projects/393248438299541505

# include <EEPROM.h>
# include <Keypad.h>

// hack it to use a strip of neopixels
//
# define NINE   8   // # of LEDs to handle (lose status LED at 13)
# define BASE   5   // base. pins must++

# include <Adafruit_NeoPixel.h>

# define LED_PIN    A0
# define LED_COUNT  NINE

Adafruit_NeoPixel disaply(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void myDigitalWrite(int theLED, int theValue)
{

  unsigned long was = disaply.getPixelColor(theLED - BASE);

  disaply.setPixelColor(theLED - BASE, theValue ? 0xff0000 : 0x202020);
  disaply.show();

  return;   // rest is for 

  if (was == disaply.getPixelColor(theLED - BASE)) Serial.println("                         work to do");

  Serial.print(theLED);
  Serial.print(" + ");

  bool any = false;
  for (int ii = 0; ii < 9; ii++)
    any |= disaply.getPixelColor(ii) == 0xff0000;

//  if (any) {
  {
    for (int ii = 0; ii < 9; ii++)
      Serial.print(disaply.getPixelColor(ii) == 0xff0000 ? "X" : ".");
  
    Serial.println("");
  }
}

# define digitalWrite myDigitalWrite
//
// end of hack. sue me, I said it was a hack

// the rest is reworked original


// yeah? int (*p[4]) (int x, int y);


void (*flist[])() = {
  pattern_off,
  traffic_left,
  traffic_center,
  traffic_right,
  traffic_warning,
};

void (*fwarn[]) () = {
  even_odd, even_odd_flash, half_half,
  half_half_flash, two_by_two, tow_by_two_flash,
  two_by_two_parallel, two_by_two_parallel_flash, three_by_one,
  three_by_one_flash, outboard, outboard_flash,
  inboard_6, inboard_6_flash, solid,
  solid_flash, solid_flash_pause, multi_pattern, 
};

const byte nWarnings = sizeof fwarn / sizeof *fwarn;

const byte ROWS = 2;
const byte COLS = 3;
const byte key [ROWS][COLS] = 
{
  {1,2,3},
  {4,5,6}
};

const String ButtonPress[6] = {"Stop", "Warn", "Change", "Left", "Center", "Right"};
enum buttonNames {Stop = 0, Warn, Change, Left, Center, Right};

byte rowPins[ROWS] = {3, 2};
byte colPins[COLS] = {A2, A3, A4};

// bool gotKey = false;

byte pressedKey;

Keypad keypad = Keypad(makeKeymap(key),rowPins, colPins, ROWS, COLS);

int statuslight = 13;
int LEDleft[] = {5, 6, 7, 8, 9, 10, 11, 12};
int LEDright[] = {12, 11, 10, 9, 8, 7, 6, 5};
int centerleft[] = {9, 10, 11, 12};
int centerright[] = {8, 7, 6, 5};
int light = 0;
int counter = 1;
int pattern_count = 0;
int warning_count = EEPROM.read(0);
long lasttimer = 0;
static long timer = 100;
static long timer2 = 200;
#define LEFTside 0x0
#define RIGHTside 0x1
byte whichLED = LEFTside;
byte LEFT_state = LOW;
byte RIGHT_state = LOW;
byte arrow_state = HIGH;
unsigned long strobeDelay = 75;
unsigned long switchDelay = 500;
unsigned long switchDelay2 = 1000;
unsigned long switchDelay3 = 450;
unsigned long strobeWait = strobeDelay;
unsigned long waitUntilSwitch = switchDelay;
unsigned long sequenceStartTime;
unsigned long sequenceStartTime2;

void setup() {
  Serial.begin(9600);

  disaply.begin();
  disaply.setPixelColor(1, 0xff40c0);
  disaply.show();
  delay(777);
  disaply.clear();  
  disaply.show();

  pinMode(statuslight, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT);

}
void loop() {

//  digitalWrite(statuslight, HIGH);

  byte key = (byte)keypad.getKey();
  if (key) {
    Serial.print("\n$raw key "); Serial.print(key);
 //   gotKey = true;
    pressedKey = key - 1;
    key = 0;
/*  }
  if (gotKey == true) {
*/

    Serial.print("  "); Serial.print("now key "); Serial.println(pressedKey); Serial.print("  $ ");
    Serial.println(ButtonPress[pressedKey]);
//    gotKey = false;

    /*}
    if (0) {*/

    switch (pressedKey) {
    case Stop :
      pattern_count = 0;
      EEPROM.update(0, warning_count);
      break;
    
    case Warn :
      pattern_count = 4;
      break;
    
    case Change :
      warning_count++;
      if (warning_count >= nWarnings) warning_count = 1;

      break;
    
    case Left :
      pattern_count = 3;
      break;
    
    case Center :
      pattern_count = 2;
      break;
    
    case Right :
      pattern_count = 1;
      break;
    
    default :
      Serial.println("Can't happen.");
      break;
    }

    static int lastPattern = -1;
    if (pattern_count != lastPattern) {
      Serial.print("pattern_count case "); Serial.println(pattern_count);
      lastPattern = pattern_count;
    }
  }

// dereference the indexed function pointer and apply it
  (*flist[pattern_count])();

if (0)
  switch (pattern_count) {
  case 0:
    pattern_off();
    break;
  case 1:
    traffic_left();
    break;
  case 2:
    traffic_center();
    break;
  case 3:
    traffic_right();
    break;
  case 4:
    traffic_warning();
    break;
  }
}

void pattern_off() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
}

void traffic_left() {
  long time = millis() - sequenceStartTime;
  if (time < 16000)
  {
    left_arrow();
  }
  else if (time < 18000)
  {
    half_half_flash();
  }
  else sequenceStartTime = millis();
}

void traffic_center() {
  long time = millis() - sequenceStartTime;
  if (time < 16000)
  {
    center_arrow();
  }
  else if (time < 18000)
  {
    half_half_flash();
  }
  else sequenceStartTime = millis();
}

void traffic_right() {
  long time = millis() - sequenceStartTime;
  if (time < 16000)
  {
    right_arrow();
  }
  else if (time < 18000)
  {
    half_half_flash();
  }
  else sequenceStartTime = millis();
}

void traffic_warning()
{
  if (warning_count >= 1 && warning_count <= nWarnings)
    (*fwarn[warning_count - 1])();
  else {
    warning_count = nWarnings >> 1;
    (*fwarn[warning_count])();
  }
}

void even_odd() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 300)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, LOW);
    digitalWrite(10, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(5, LOW);
  }
  else if (time < 600)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(5, HIGH);
  }
  else sequenceStartTime = millis();
}

void even_odd_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, LEFT_state);
  digitalWrite(11, RIGHT_state);
  digitalWrite(10, LEFT_state);
  digitalWrite(9, RIGHT_state);
  digitalWrite(8, LEFT_state);
  digitalWrite(7, RIGHT_state);
  digitalWrite(6, LEFT_state);
  digitalWrite(5, RIGHT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void half_half() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 250)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else if (time < 500)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else sequenceStartTime = millis();
}
void half_half_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, LEFT_state);
  digitalWrite(11, LEFT_state);
  digitalWrite(10, LEFT_state);
  digitalWrite(9, LEFT_state);
  digitalWrite(8, RIGHT_state);
  digitalWrite(7, RIGHT_state);
  digitalWrite(6, RIGHT_state);
  digitalWrite(5, RIGHT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void two_by_two() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 150)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else if (time < 300)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else sequenceStartTime = millis();
}

void tow_by_two_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, LEFT_state);
  digitalWrite(11, LEFT_state);
  digitalWrite(10, RIGHT_state);
  digitalWrite(9, RIGHT_state);
  digitalWrite(8, RIGHT_state);
  digitalWrite(7, RIGHT_state);
  digitalWrite(6, LEFT_state);
  digitalWrite(5, LEFT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void three_by_one() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 400)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else if (time < 800)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, LOW);
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else sequenceStartTime = millis();
}

void three_by_one_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, RIGHT_state);
  digitalWrite(11, RIGHT_state);
  digitalWrite(10, RIGHT_state);
  digitalWrite(8, RIGHT_state);
  digitalWrite(9, LEFT_state);
  digitalWrite(7, LEFT_state);
  digitalWrite(6, LEFT_state);
  digitalWrite(5, LEFT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void two_by_two_parallel() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 150)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else if (time < 300)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else sequenceStartTime = millis();
}

void two_by_two_parallel_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, LEFT_state);
  digitalWrite(11, LEFT_state);
  digitalWrite(10, RIGHT_state);
  digitalWrite(9, RIGHT_state);
  digitalWrite(8, LEFT_state);
  digitalWrite(7, LEFT_state);
  digitalWrite(6, RIGHT_state);
  digitalWrite(5, RIGHT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void outboard() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 300)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else if (time < 600)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else sequenceStartTime = millis();
}

void outboard_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, RIGHT_state);
  digitalWrite(11, RIGHT_state);
  digitalWrite(6, LEFT_state);
  digitalWrite(5, LEFT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void inboard_6() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 200)
  {
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
  }
  else if (time < 400)
  {
    digitalWrite(11, LOW);
    digitalWrite(10, LOW);
    digitalWrite(9, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
  }
  else sequenceStartTime = millis();
}

void inboard_6_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(11, LEFT_state);
  digitalWrite(10, LEFT_state);
  digitalWrite(9, RIGHT_state);
  digitalWrite(8, RIGHT_state);
  digitalWrite(7, LEFT_state);
  digitalWrite(6, LEFT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void solid() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 800)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else if (time < 1600)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else sequenceStartTime = millis();
}

void solid_flash() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  long time = millis() - sequenceStartTime;
  if (time < 200)
  {
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
  }
  else if (time < 400)
  {
    digitalWrite(12, LOW);
    digitalWrite(11, LOW);
    digitalWrite(10, LOW);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
  }
  else sequenceStartTime = millis();
}

void solid_flash_pause() {
  for (int i = 0; i <= 7; i++) {
    digitalWrite(LEDright[i], LOW);
  }
  digitalWrite(12, LEFT_state);
  digitalWrite(11, LEFT_state);
  digitalWrite(10, LEFT_state);
  digitalWrite(9, LEFT_state);
  digitalWrite(8, LEFT_state);
  digitalWrite(7, LEFT_state);
  digitalWrite(6, LEFT_state);
  digitalWrite(5, LEFT_state);
  if ((long)(millis() - waitUntilSwitch) >= 0) {
    LEFT_state = LOW;
    RIGHT_state = LOW;
    whichLED = !whichLED;
    waitUntilSwitch += switchDelay3;
  }
  if ((long)(millis() - strobeWait) >= 0) {
    if (whichLED == LEFTside)
      LEFT_state = !LEFT_state;
    if (whichLED == RIGHTside)
      RIGHT_state = !RIGHT_state;
    strobeWait += strobeDelay;
  }
}

void left_arrow() {
  unsigned long currenttimer = millis();
  if (currenttimer - lasttimer >= timer) {
    lasttimer = currenttimer;
    for (int i = 0; i <= 7; i++) {
    }
    light = light + counter;
    if (light > 7) {
      arrow_state = !arrow_state;
      light = 0;
      counter = 1;
    }
    if (arrow_state == HIGH) {
      digitalWrite(LEDleft[light], HIGH);
    }
    else if (arrow_state == LOW) {
      digitalWrite(LEDleft[light], LOW);
    }
  }
}

void right_arrow() {
  unsigned long currenttimer = millis();
  if (currenttimer - lasttimer >= timer) {
    lasttimer = currenttimer;
    for (int i = 0; i <= 7; i++) {
    }
    light = light + counter;
    if (light > 7) {
      arrow_state = !arrow_state;
      light = 0;
      counter = 1;
    }
    if (arrow_state == HIGH) {
      digitalWrite(LEDright[light], HIGH);
    }
    else if (arrow_state == LOW) {
      digitalWrite(LEDright[light], LOW);
    }
  }
}

void center_arrow() {
  unsigned long currenttimer = millis();
  if (currenttimer - lasttimer >= timer2) {
    lasttimer = currenttimer;
    for (int i = 0; i <= 7; i++) {
    }
    light = light + counter;
    if (light > 3) {
      arrow_state = !arrow_state;
      light = 0;
      counter = 1;
    }
    if (arrow_state == HIGH) {
      digitalWrite(centerright[light], HIGH);
      digitalWrite(centerleft[light], HIGH);
    }
    if (arrow_state == LOW) {
      digitalWrite(centerright[light], LOW);
      digitalWrite(centerleft[light], LOW);
    }
  }
}

void multi_pattern(){
  long time = millis() - sequenceStartTime2;
  if (time < 4000)
  {
    half_half_flash();
  }
  else if (time < 8000)
  {
    outboard();
  }
  else if (time < 12000)
  {
    two_by_two_parallel_flash();
  }
  else if (time < 16000)
  {
    solid_flash_pause();
  }
  else if (time < 20000)
  {
    outboard_flash();
  }
  else if (time < 24000)
  {
    tow_by_two_flash();
  }
  else if (time < 28000)
  {
    half_half();
  }
  else if (time < 32000)
  {
    two_by_two_parallel();
  }
  else sequenceStartTime2 = millis();
}
STOP....WARN....CHANGE
LEFT.....CENTER....RIGHT