//
//  I2CKeypad test using Tillaart I2CKeypad library 
//  AUTHOR:  Gary Dyrkacz, based on pieces of library examples.
//  PURPOSE: demo reads up to two digits(user expandable)  from 4x4 keypad 
//           until specific keyPress to end input, curretnly "#"
//  URL:     of original info: https://github.com/RobTillaart/I2CKeyPad
//  
// PCF8574
//    pin p0-p3 rows
//    pin p4-p7 columns
// 4x4 or smaller keypad.
//
//  This demo doesn't use the built in key mapping.
//Specify map in keymap variable.
//Code was verified with an Arduino Uno, but except for pin 
//changes, should work with ESP32

#include "Wire.h"
#include "I2CKeyPad.h"
#define deltaTime(val) (millis()-val)
char buf[6];
const uint8_t KEYPAD_ADDRESS = 0x38; //modules may use this or 0x20 as base
unsigned long lastKeyPress = 0;
I2CKeyPad kpd(KEYPAD_ADDRESS);
// ued to get key and to indicate NoKey or Failure.
char keymap[19] = "123A456B789C*0#DNF";     // ... NoKey  Fail }
String s;

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

  Wire.begin();
  Wire.setClock(400000);
  if (kpd.begin() == false)
  {
    Serial.println("\nERROR: cannot communicate to keypad.\nPlease reboot.\n");
    while (1);
  }
  kpd.loadKeyMap(keymap);
}

void loop() {
  int result;
  uint8_t strlen = 3;
  if (kpd.isPressed()) {
    result = readKeyPadUntil('#', strlen, 5000);
  }  
  if (result == 0) {
    if (s.length() == 0) {
      Serial.println("No number!");
  } else {
    Serial.print("SUCCESS: ");
    Serial.println(s);
  }
  delay(200);
}
  if (result == -1) {
    Serial.print("FAILURE: ");
    Serial.println(s);
        delay(200);
  }
  if (result == -2) {
    Serial.print("TIMEOUT: ");
    Serial.println(s);
        delay(200);
  }
  if (result == -3) {
    Serial.print("OVERFLW: ");
    Serial.println(s);
       delay(200); 
   }
}


//
// until   = end character
// length  = max allowed length of string
// timeout = timeout in milliseconds
// returns 0 = success
//        -1 = keyPad fail
//        -2 = timeout
//        -3 = buffer overflow
int readKeyPadUntil(char until, uint8_t length, uint16_t timeout) {
  uint8_t bufferIndex = 0;
  uint32_t start = millis();
  char ch;
  s = "";

  //use no delays before this point, or it may clear the buffer if delays over
  //100 ms.
  while (millis() - start < timeout) {
    //Serial.println("while");
    if (kpd.isPressed()) {
      ch = kpd.getChar();
      if (ch == until) {
        return 0;  // success
      } 
      else if (ch == 'F') {
        return -1;
      }      // keyPad fail
      else {
        bufferIndex++;
        s+=ch;
        if ( bufferIndex == length ) {
          bufferIndex = 0;
          return -3;  // overflow
        }
      }
  delay(200);
   // yield();

  }

  //return -2;    //  timeout
  }

 
}
8bit I2CBreakout