I got it.
New .h Library:
#ifndef OWKPtest_h
#define OWKPtest_h
#include <Arduino.h>
#include "BitBool.h"
#define NO_KEY '\0'
#define WAITING 0
#define PRESSED 1
#define RELEASED 2
#define HELD 3
/*--- Main Class ---*/
template< typename T, unsigned MAX_KEYS >
class OWKPtest{
public:
OWKPtest( T &port, char KP[], uint8_t Rows, uint8_t Cols, uint8_t Pin, int R1, int R2 )
: port_( port ), latchedKey( BitBool< MAX_KEYS >() ), _Data( KP ), _Rows( Rows ), _Cols( Cols ), _Pin( Pin ),
holdTime( 500 ), startTime( 0 ), lastState( 0 ), lastRead( 0 ), debounceTime( 10 ), R1( R1 ), R2( R2 ) {}
char Getkey();
void SetHoldTime(unsigned long setH_Time) { holdTime = setH_Time; }
void SetDebounceTime(unsigned long setD_Time) { debounceTime = setD_Time; }
uint8_t Key_State();
bool Readpin() { return analogRead(_Pin)? 1 : 0; }
void LatchKey();
bool checkLatchedKey(char _key);
protected:
T &port_;
private:
BitBool< MAX_KEYS > latchedKey;
char *_Data;
char Out[20];
uint8_t _Rows, _Cols, _Pin;
char lastKey;
enum{ SIZE = MAX_KEYS };
unsigned long time;
unsigned long holdTime;
unsigned long startTime;
unsigned long debounceTime;
bool state, lastState, lastRead;
int R1, R2;
};
template < typename T, typename U > struct IsSameType{
enum { Value = false };
};
template < typename T > struct IsSameType< T, T > {
enum { Value = true };
};
template < typename T, unsigned MAX_KEYS >
char OWKPtest< T, MAX_KEYS > :: Getkey()
{
if( int Reading = analogRead(_Pin)){
if(millis() - startTime > debounceTime){
for( byte i = 0, R = _Rows-1, C = _Cols-1; i < SIZE; i++ ){
float V = ( 5.0f * float( R2 ) )/( float( R2 ) + ( float( R1 ) * float( R ) ) + ( float( R2 ) *float( C ) ) );
float Vfinal = V * (1023.0f / 5.0f);
if( Reading <= ( int(Vfinal) + 1.9f ) ) return _Data[(SIZE-1)-i];
if( C == 0 )
{
R--;
C = _Cols-1;
}
else C--;
}
startTime = millis();
}
}
return NO_KEY;
}
template < typename T, unsigned MAX_KEYS >
uint8_t OWKPtest< T, MAX_KEYS > :: Key_State()
{
if((state = Readpin()) != lastState)
return ( ( lastState = state ) ? PRESSED : RELEASED); //MOD
else if(Readpin())
{
time = millis();
while(Readpin()){
if((millis() - time) > holdTime) return HELD;
}
lastState = 0;
return RELEASED;
}
return WAITING;
}
template < typename T, unsigned MAX_KEYS >
void OWKPtest<T, MAX_KEYS > :: LatchKey()
{
char output[20];
bool PRINT = false;
char read = Getkey();
if(read != lastRead)
{
if( read )
{
for( int idx = 0; idx < SIZE; idx++ )
{
if(read == _Data[idx] )
{
strcpy_P( output, ( latchedKey[idx] = !latchedKey[idx] ) ? PSTR( "Key X was Latched" ) : PSTR( "Key X was Unlatched" ) ); //MOD
PRINT = true;
output[ 4 ] = read; //MOD <- very clever
}
}
}
lastRead = read;
if( PRINT ) //port_.println(output);
{
if( IsSameType< T, LiquidCrystal_I2C >::Value)
port_.print(output);
else
port_.println(output);
}
}
}
template < typename T, unsigned MAX_KEYS >
bool OWKPtest< T, MAX_KEYS > :: checkLatchedKey(char _key)
{
for( int idx = 0; idx < SIZE; idx++ )
{
if( _key == _Data[idx] ) return latchedKey[idx];
}
return false;
}
#endif
New Sketch:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "OWKPtest.h"
char KEYS[]= {
'1','2','3',//'A',
'4','5','6',//'B',
'7','8','9',//'C',
'*','0','#',//'D'
};
LiquidCrystal_I2C lcd(0x20,20,4);
OWKPtest <LiquidCrystal_I2C, 12> KP( lcd, KEYS, 4, 3, A0, 4700, 1000 );
OWKPtest <Print, 12 > KP2(Serial, KEYS, 4, 3, A0, 4700, 1000 );
void setup (){
Serial.begin(115200);
lcd.init();
lcd.backlight();
}
void loop()
{
if( KP.Getkey() ){
lcd.clear();
lcd.home();
lcd.print( F( "KP: " ) );
lcd.setCursor(4,0);
KP.LatchKey();
}
if( KP2.Getkey() ){
Serial.print( F( "KP2: " ) );
Serial.println(KP2.Key_State());
KP2.LatchKey();
Serial.println();
}
}