// Gray_CustomKeypad4LedTest

const uint8_t PinC1 =  2; // keypad columns
const uint8_t PinC2 =  3;
const uint8_t PinC3 =  4;
const uint8_t PinC4 =  5;
const uint8_t PinR1 =  6; //  Pin6<--keypadR1 +--[LED)+--/\/\1k/\----<pin13  red
const uint8_t PinR2 =  7; //  Pin7<--keypadR2 +--[LED)+--/\/\1k/\----<pin13  blue
const uint8_t PinR3 =  8; //  Pin8<--keypadR3 +--[LED)+--/\/\1k/\----<pin13  green
const uint8_t PinPwmRed = 9;   // rgb led on pwm pins
const uint8_t PinPwmGreen = 10;
const uint8_t PinPwmBlue = 11;
const uint8_t PinR4 = 12; // Pin12<--keypadR3 +--[LED)--/\/\1k/\----<pin13   green
const uint8_t PinSpeaker = 13;
const uint8_t PinSwitch1 = A0;
const uint8_t PinSwitch2 = A1;
const uint8_t PinSwitch3 = A2;
const uint8_t PinLedsAnnode = A3;
const uint8_t PinUnused1 = A4;
const uint8_t PinUnused2 = A5;

uint8_t LedBits = 0;

const uint8_t KEYPAD_ROWS = 4;
const uint8_t KEYPAD_COLS = 4;
const unsigned long KeypadDebounceTimeMsec = 100;
const unsigned long LedMultiplexTimeMsec = 10;
uint8_t row[KEYPAD_ROWS], col[KEYPAD_COLS];

void setup() {
  Serial.begin(9600);
  Serial.println("Gray_CustomKeypadTest");
  DisableLeds();
  InitKeypad(PinC1,PinC2,PinC3,PinC4, PinR1,PinR2,PinR3,PinR4);
}

//----------------------------
void InitKeypad(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4, uint8_t r1, uint8_t r2, uint8_t r3, uint8_t r4)
{
  row[0] = r1; row[1] = r2; row[2] = r3; row[3] = r4;
  col[0] = c1; col[1] = c2; col[2] = c3; col[3] = c4;
  for(uint8_t r=0; r < KEYPAD_ROWS; r++)
  {
    pinMode(row[r], INPUT_PULLUP);
  }
}

char ScanKey()
{
  static unsigned long lastScan;
  static char activeKey[4] = { 0, 0, 0 };
  uint8_t key = 0;
  if(millis() - lastScan > KeypadDebounceTimeMsec)
  {
    lastScan = millis();
    activeKey[3] = activeKey[2];
    activeKey[2] = activeKey[1];
    activeKey[1] = activeKey[0];
    activeKey[0] = 0;

    DisableLeds();
    
    for(uint8_t c=0; c < KEYPAD_COLS && !activeKey[0]; c++)
    {
      pinMode(col[c], OUTPUT);
      digitalWrite(col[c], LOW);
      for(uint8_t r=0; r < KEYPAD_ROWS && !activeKey[0]; r++)
      {
        if(digitalRead(row[r]) == LOW)
        {
          activeKey[0] = r*KEYPAD_COLS+c+1; // keys 1-16, stays 0 if nothing pressed
        }
      }
      pinMode(col[c], INPUT);
    }

    if(activeKey[0] != activeKey[1] && activeKey[1] == activeKey[2])
    {
      // last 2 match but current is different, send the event
      key = activeKey[0];
    }
    
    DriveLeds();
  }
  return key;
}

void DisableLeds()
{
  pinMode(PinLedsAnnode, INPUT);
  digitalWrite(PinLedsAnnode, LOW);
  for(uint8_t c=0; c < KEYPAD_COLS; c++)
  {
    pinMode(col[c], INPUT);
  }
}

void DriveLeds()
{
  for(int led=0;led<KEYPAD_COLS; led++)
  {
    if(bitRead(LedBits, led))
    {
      pinMode(col[led], OUTPUT);
      digitalWrite(col[led], LOW);
    }
    else
    {
      pinMode(col[led], INPUT);
    }
  }
  pinMode(PinLedsAnnode, OUTPUT);
  digitalWrite(PinLedsAnnode, HIGH);
}


void loop() {
  char key = ScanKey();
  if(key)
  {
    Serial.print("key "); Serial.print((uint8_t)key); Serial.print(" ");
    if(key==1) bitSet(LedBits, 0);
    if(key==2) bitSet(LedBits, 1);
    if(key==3) bitSet(LedBits, 2);
    if(key==4) bitSet(LedBits, 3);
    if(key==5) bitClear(LedBits, 0);
    if(key==6) bitClear(LedBits, 1);
    if(key==7) bitClear(LedBits, 2);
    if(key==8) bitClear(LedBits, 3);
    Serial.println(LedBits);
  }
}