[SOLVED]Need help referencing two classes in one constructor.

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();
  } 
}

To stop the '#' char I simply changed: if( int Reading = analogRead(_Pin)){ to use random( 1, 1023 ) while I was testing. The hash was simply the floating read from the analog pin. From your changes, it appears I was reading from the wrong end??

My BitBool is pretty safe, it is just a 'drop in' replacement for bool arrays.

I didn't have a keypad or anything so I was just leaving it up to you to verify anyway XD.
Was the non-connected screen the cause of the Uno problem?

It took a while to go through and apply those changes, are you unsure about anything I did change?

The issue with the code only returning the # was because in the Calc function I originally made, it started the calculations at zero to store the first value ie 1023. Now when you made the code do it on the fly, it again started from 0 and it saw that every analog value was less than 1023 so it never incremented the keypad array. In short, to get the proper readings you have to calculate everything backwards to output the right keypad chars.

Another thing, no I don't need the lcd attached to compile the code, I'm not sure why your getting that error. Do you have the Liquidcrystal_I2C library?

Last thing, yes I understood everything you changed.

Final version of OneWireKeypad.

OneWireKeypad.zip (3.93 KB)

If you used any of the changes I helped you with, I hope you actually appreciated them.

I absolutely do, Thank you for all of your help. I learned a great deal, and I'm actually using what you taught me for my other libraries.

Again Thank you very much.

You're welcome, I'm glad to hear it was useful enough to apply elsewhere.

If I ever acquire an I2C lcd, I'll give it run :slight_smile:
Good luck with your future development.

The way the library is written, it should work with a regular Lcd too.

Updated library in playground.
http://playground.arduino.cc/Code/OneWireKeyPad