Async Keyboard implementation
This commit is contained in:
		
							parent
							
								
									230d843457
								
							
						
					
					
						commit
						c65d505969
					
				
							
								
								
									
										13
									
								
								Readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Readme.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | # Documentation  | ||||||
|  | ## 1.0 Keypad | ||||||
|  | The kepad is driven by an io-expander. Thus it can be acessed over i2c. | ||||||
|  | Adress 0x21 | ||||||
|  | ### 1.1 Wiring | ||||||
|  | * Red: 3.3V | ||||||
|  | * Black GND | ||||||
|  | * Green SDA -> D3 | ||||||
|  | * Grey SCL -> D4   | ||||||
|  | 
 | ||||||
|  | ## 2.0 LCD | ||||||
|  | The LCD display is driven on the same i2c bus as the keypad. | ||||||
|  | 
 | ||||||
| @ -15,3 +15,4 @@ framework = arduino | |||||||
| lib_deps =  | lib_deps =  | ||||||
| 	xreef/PCF8574 library@^2.2.1 | 	xreef/PCF8574 library@^2.2.1 | ||||||
| 	marcoschwartz/LiquidCrystal_I2C@^1.1.4 | 	marcoschwartz/LiquidCrystal_I2C@^1.1.4 | ||||||
|  | 	miguelbalboa/MFRC522@^1.4.9 | ||||||
|  | |||||||
							
								
								
									
										105
									
								
								src/Keyboard.cpp
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								src/Keyboard.cpp
									
									
									
									
									
								
							| @ -1,14 +1,14 @@ | |||||||
| #include "Keyboard.h" | #include "Keyboard.h" | ||||||
| //#define DEBUG
 | #define DEBUG | ||||||
| #define PIN_WIRE_SDA D3 | #define PIN_WIRE_SDA D3 | ||||||
| #define PIN_WIRE_SCL D4 | #define PIN_WIRE_SCL D4 | ||||||
| Keyboard::Keyboard(uint8_t debounce) | Keyboard::Keyboard(uint8_t _debounce) | ||||||
| { | { | ||||||
|     this->debounce = debounce; |     this->_debounce = _debounce; | ||||||
| } | } | ||||||
| void Keyboard::begin(TwoWire *databus) | void Keyboard::begin(TwoWire *databus) | ||||||
| { | { | ||||||
|     pcf8574 = new PCF8574(databus, 0x27, PIN_WIRE_SDA, PIN_WIRE_SCL); |     pcf8574 = new PCF8574(databus, 0x21, PIN_WIRE_SDA, PIN_WIRE_SCL); | ||||||
|     pcf8574->pinMode(0, OUTPUT); |     pcf8574->pinMode(0, OUTPUT); | ||||||
|     for (int i = 1; i < 8; i++) |     for (int i = 1; i < 8; i++) | ||||||
|     { |     { | ||||||
| @ -35,12 +35,13 @@ Keyboard::~Keyboard() | |||||||
| } | } | ||||||
| void Keyboard::scan() | void Keyboard::scan() | ||||||
| { | { | ||||||
|     if (millis() < timeElapsed + this->debounce) |     if (millis() < _timeElapsed + this->_debounce) | ||||||
|         return 0; |         return; | ||||||
|     uint8_t key = 0; |     uint8_t key = 0; | ||||||
|     for (int i = 7; i > 4; i--) // Columns
 |     for (int i = 7; i > 4; i--) // Columns
 | ||||||
|     { |     { | ||||||
|         pcf8574->digitalWrite(i, LOW); |         pcf8574->digitalWrite(i, LOW); | ||||||
|  |         delay(15); | ||||||
|         for (int j = 1; j < 5; j++) |         for (int j = 1; j < 5; j++) | ||||||
|         { // Rows
 |         { // Rows
 | ||||||
|             key++; |             key++; | ||||||
| @ -51,14 +52,73 @@ void Keyboard::scan() | |||||||
| #endif | #endif | ||||||
|             if (val == 0) |             if (val == 0) | ||||||
|             { |             { | ||||||
|                 timeElapsed = millis(); |                 _timeElapsed = millis(); | ||||||
|                 this->lastKey = key; |                 this->_lastKey = key; | ||||||
|                 this->buffer.push(mapChr(key)); |                 this->_buffer.push_back(mapChr(key)); | ||||||
|  |                 pcf8574->digitalWrite(i, HIGH); | ||||||
|  |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         pcf8574->digitalWrite(i, HIGH); |         pcf8574->digitalWrite(i, HIGH); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | void Keyboard::scanAsync() | ||||||
|  | { | ||||||
|  |     /** Without delay - scanning only one column per cycle **/ | ||||||
|  |     if (millis() < _timeElapsed + this->_debounce) | ||||||
|  |         return; | ||||||
|  |     uint8_t key = 0; | ||||||
|  |     switch (_current_scan_col) | ||||||
|  |     { | ||||||
|  |         default: | ||||||
|  |             pcf8574->digitalWrite(7, LOW); | ||||||
|  |             _current_scan_col = 1; | ||||||
|  |             break; | ||||||
|  |         case 1: | ||||||
|  |         { | ||||||
|  |             scanColumn(&key, 1, 4); | ||||||
|  |             pcf8574->digitalWrite(6, LOW);             | ||||||
|  |             pcf8574->digitalWrite(7, HIGH); | ||||||
|  |             _current_scan_col = 2; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case 2: | ||||||
|  |         { | ||||||
|  |             key=4; | ||||||
|  |             scanColumn(&key, 1, 4); | ||||||
|  |             pcf8574->digitalWrite(5, LOW);             | ||||||
|  |             pcf8574->digitalWrite(6, HIGH); | ||||||
|  |             _current_scan_col = 3; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case 3: | ||||||
|  |         { | ||||||
|  |             key=8; | ||||||
|  |             scanColumn(&key, 1, 4); | ||||||
|  |             pcf8574->digitalWrite(7, LOW);             | ||||||
|  |             pcf8574->digitalWrite(5, HIGH); | ||||||
|  |             _current_scan_col = 1; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Keyboard::scanColumn(uint8_t* key_ptr, uint8_t start, uint8_t stop){ | ||||||
|  |     for (int j = start; j <= stop; j++) | ||||||
|  |             { // Rows
 | ||||||
|  |                 (*key_ptr)++; | ||||||
|  |                 uint8_t val = pcf8574->digitalRead(j); | ||||||
|  |                 if (val == 0) | ||||||
|  |                 { | ||||||
|  |                     _timeElapsed = millis(); | ||||||
|  |                     this->_lastKey = *key_ptr; | ||||||
|  |                     this->_buffer.push_back(mapChr(*key_ptr)); | ||||||
|  |                     Serial.print(*key_ptr); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | } | ||||||
| char Keyboard::mapChr(uint8_t key) | char Keyboard::mapChr(uint8_t key) | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| @ -73,9 +133,9 @@ char Keyboard::mapChr(uint8_t key) | |||||||
|     case 4: |     case 4: | ||||||
|         return 'O'; |         return 'O'; | ||||||
|     case 5: |     case 5: | ||||||
|         return '5'; |         return '2'; | ||||||
|     case 6: |     case 6: | ||||||
|         return '1'; |         return '5'; | ||||||
|     case 7: |     case 7: | ||||||
|         return '8'; |         return '8'; | ||||||
|     case 8: |     case 8: | ||||||
| @ -93,11 +153,26 @@ char Keyboard::mapChr(uint8_t key) | |||||||
|         return 'F'; |         return 'F'; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| char Keyboard::getChr() | char Keyboard::getLastChr() | ||||||
| { | { | ||||||
|     return this->getChr(this->lastKey); |     return this->mapChr(this->_lastKey); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Keyboard::available(){ | bool Keyboard::available() | ||||||
|     return (!this->buffer.empty()); | { | ||||||
|  |     return (!this->_buffer.empty()); | ||||||
|  | } | ||||||
|  | void Keyboard::clear() | ||||||
|  | { | ||||||
|  |     this->_buffer.clear(); | ||||||
|  | } | ||||||
|  | String Keyboard::getString() | ||||||
|  | { | ||||||
|  |     String out; | ||||||
|  |     for (auto &&i : this->_buffer) | ||||||
|  |     { | ||||||
|  |         out.concat(i); | ||||||
|  |     } | ||||||
|  |     this->_buffer.clear(); | ||||||
|  |     return out; | ||||||
| } | } | ||||||
| @ -5,19 +5,24 @@ | |||||||
| class Keyboard | class Keyboard | ||||||
| { | { | ||||||
| private: | private: | ||||||
|     unsigned long timeElapsed; |     unsigned long _timeElapsed; | ||||||
|     std::queue<char> buffer; |     std::deque<char> _buffer; | ||||||
|     uint8_t debounce; |     uint8_t _debounce; | ||||||
|     PCF8574* pcf8574; |     PCF8574* pcf8574; | ||||||
|     int lastKey; |     uint8_t _lastKey; | ||||||
|  |     uint8_t _current_scan_col; | ||||||
|  |     void scanColumn(uint8_t *key, uint8_t start, uint8_t stop); | ||||||
|     /* data */ |     /* data */ | ||||||
| public: | public: | ||||||
|     Keyboard(uint8_t debounce); |     Keyboard(uint8_t debounce); | ||||||
|     ~Keyboard(); |     ~Keyboard(); | ||||||
|     void scan(); |     void scan(); | ||||||
|  |     void scanAsync(); | ||||||
|     void begin(TwoWire *databus); |     void begin(TwoWire *databus); | ||||||
|     static char getChr(uint8_t key); |     static char mapChr(uint8_t key); | ||||||
|     char getChr(); |     char getLastChr(); | ||||||
|     bool available(); |     bool available(); | ||||||
|  |     void clear(); | ||||||
|  |     String getString(); | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
							
								
								
									
										9
									
								
								src/Rfid.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Rfid.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | #include "Rfid.h" | ||||||
|  | 
 | ||||||
|  | Rfid::Rfid(/* args */) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Rfid::~Rfid() | ||||||
|  | { | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								src/Rfid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Rfid.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | class Rfid | ||||||
|  | { | ||||||
|  | private: | ||||||
|  |     /* data */ | ||||||
|  | public: | ||||||
|  |     Rfid(/* args */); | ||||||
|  |     ~Rfid(); | ||||||
|  | }; | ||||||
							
								
								
									
										166
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										166
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -2,25 +2,179 @@ | |||||||
| #include <Arduino.h> | #include <Arduino.h> | ||||||
| #include <Wire.h> | #include <Wire.h> | ||||||
| #include "Keyboard.h" | #include "Keyboard.h" | ||||||
|  | #include <SPI.h> | ||||||
|  | #include <MFRC522.h> | ||||||
| 
 | 
 | ||||||
|  | // RFID Reader
 | ||||||
|  | #define SS_PIN D8 | ||||||
|  | #define RST_PIN D1 | ||||||
|  | #define RFID_TIMEOUT 3000 | ||||||
|  | MFRC522 mfrc522(SS_PIN); // Create MFRC522 instance
 | ||||||
|  | MFRC522::MIFARE_Key key; | ||||||
|  | String rfid = ""; | ||||||
|  | String lastRfid = ""; | ||||||
|  | unsigned long lastRfidScan = 0; | ||||||
|  | // i2C Bus
 | ||||||
| #define PIN_WIRE_SDA D3 | #define PIN_WIRE_SDA D3 | ||||||
| #define PIN_WIRE_SCL D4 | #define PIN_WIRE_SCL D4 | ||||||
| #include <LiquidCrystal_I2C.h> | #include <LiquidCrystal_I2C.h> | ||||||
| TwoWire databus; |  | ||||||
| Keyboard keyboard(200); | Keyboard keyboard(200); | ||||||
|  | LiquidCrystal_I2C lcd(0x27, 20, 4); | ||||||
|  | int display_state = 0; | ||||||
|  | String pin; | ||||||
|  | unsigned long lastDisplayUpdate = 0; | ||||||
|  | unsigned long displayTimer1 = 0; | ||||||
|  | bool displayUpdate = true; | ||||||
| void setup() | void setup() | ||||||
| { | { | ||||||
| 	Serial.begin(9600); | 	Serial.begin(9600); | ||||||
| 	Serial.print("Starting"); | 	Serial.print("Starting"); | ||||||
| 	delay(500); | 	delay(500); | ||||||
| 	keyboard.begin(&databus); | 	keyboard.begin(&Wire); | ||||||
|  | 
 | ||||||
|  | 	// LCD
 | ||||||
|  | 	lcd.init(); | ||||||
|  | 	lcd.backlight(); | ||||||
|  | 
 | ||||||
|  | 	// RFID
 | ||||||
|  | 	SPI.begin(); | ||||||
|  | 	SPI.setClockDivider(SPI_CLOCK_DIV8); | ||||||
|  | 	mfrc522.PCD_Init(); | ||||||
|  | 	mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | namespace states | ||||||
|  | { | ||||||
|  | 	enum screenstates | ||||||
|  | 	{ | ||||||
|  | 		MAIN, | ||||||
|  | 		ENTER_PIN_START, | ||||||
|  | 		ENTER_PIN_ADD_NUM, | ||||||
|  | 		VALIDATE_PIN, | ||||||
|  | 		ABORT, | ||||||
|  | 		DELAY, | ||||||
|  | 		READ_RFID | ||||||
| 
 | 
 | ||||||
| 
 | 	}; | ||||||
|  | } | ||||||
| void loop() | void loop() | ||||||
| { | { | ||||||
| 	char key = keyboard.getKey(); | 	keyboard.scanAsync(); | ||||||
| 	if(key!=0) | 
 | ||||||
| 		Serial.println("Key " + String(key) +  "was pressed"); | 	if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) | ||||||
|  | 	{ | ||||||
|  | 		rfid = ""; | ||||||
|  | 		for (byte i = 0; i < mfrc522.uid.size; i++) | ||||||
|  | 		{ | ||||||
|  | 			rfid += mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "; | ||||||
|  | 			rfid += String(mfrc522.uid.uidByte[i], HEX); | ||||||
|  | 		} | ||||||
|  | 		rfid.trim(); | ||||||
|  | 		rfid.toUpperCase(); | ||||||
|  | 		if (rfid != lastRfid || millis() > lastRfidScan + RFID_TIMEOUT) | ||||||
|  | 		{ | ||||||
|  | 
 | ||||||
|  | 			display_state = states::READ_RFID; | ||||||
|  | 			displayUpdate = true; | ||||||
|  | 			Serial.print(rfid); | ||||||
|  | 			lastRfid = rfid; | ||||||
|  | 			lastRfidScan = millis(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (keyboard.available()) | ||||||
|  | 	{ | ||||||
|  | 		if (keyboard.getLastChr() == 'X') | ||||||
|  | 		{ | ||||||
|  | 			keyboard.clear(); | ||||||
|  | 			display_state = states::ABORT; | ||||||
|  | 			displayUpdate = true; | ||||||
|  | 		} | ||||||
|  | 		else if (('0' <= keyboard.getLastChr()) && (keyboard.getLastChr() <= '9')) | ||||||
|  | 		{ | ||||||
|  | 			Serial.print(keyboard.getLastChr()); | ||||||
|  | 			if (display_state == states::ENTER_PIN_START) | ||||||
|  | 				display_state = states::ENTER_PIN_ADD_NUM; | ||||||
|  | 			else if (display_state != states::ENTER_PIN_ADD_NUM) | ||||||
|  | 				display_state = states::ENTER_PIN_START; | ||||||
|  | 			displayUpdate = true; | ||||||
|  | 		} | ||||||
|  | 		else if (keyboard.getLastChr() == 'O' && (display_state == 2 || display_state == 1)) | ||||||
|  | 		{ | ||||||
|  | 			keyboard.clear(); | ||||||
|  | 			display_state = states::VALIDATE_PIN; | ||||||
|  | 			displayUpdate = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (displayUpdate) | ||||||
|  | 	{ | ||||||
|  | 		switch (display_state) | ||||||
|  | 		{ | ||||||
|  | 		case states::MAIN: | ||||||
|  | 			lcd.setCursor(0, 0); | ||||||
|  | 			lcd.print("Welcome!"); | ||||||
|  | 			lcd.setCursor(0, 1); | ||||||
|  | 			lcd.print("Enter Pin / Card"); | ||||||
|  | 			displayUpdate = false; | ||||||
|  | 			break; | ||||||
|  | 		case states::ENTER_PIN_START: // Starting Pin
 | ||||||
|  | 			pin.clear(); | ||||||
|  | 			lcd.clear(); | ||||||
|  | 			lcd.print("Please enter Pin"); | ||||||
|  | 			lcd.setCursor(0, 1); | ||||||
|  | 			pin.concat(keyboard.getString()); | ||||||
|  | 			lcd.print("Pin: " + pin); | ||||||
|  | 			display_state = 2; | ||||||
|  | 			displayUpdate = false; | ||||||
|  | 			break; | ||||||
|  | 		case states::ENTER_PIN_ADD_NUM: | ||||||
|  | 		{ | ||||||
|  | 			String input = keyboard.getString(); | ||||||
|  | 			pin.concat(input); | ||||||
|  | 			lcd.print(input); | ||||||
|  | 			displayUpdate = false; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		case states::VALIDATE_PIN: | ||||||
|  | 			lcd.clear(); | ||||||
|  | 			lcd.setCursor(0, 0); | ||||||
|  | 			lcd.print("Validating PIN"); | ||||||
|  | 			lcd.setCursor(0, 1); | ||||||
|  | 			if (pin == "2626") | ||||||
|  | 				lcd.print("Accepted!"); | ||||||
|  | 			else | ||||||
|  | 				lcd.print("Acess denied!"); | ||||||
|  | 			pin.clear(); | ||||||
|  | 			displayTimer1 = millis() + 3000; | ||||||
|  | 			display_state = states::DELAY; | ||||||
|  | 			break; | ||||||
|  | 		case states::ABORT: | ||||||
|  | 			lcd.clear(); | ||||||
|  | 			lcd.print("Input aborted!"); | ||||||
|  | 			displayTimer1 = millis() + 3000; | ||||||
|  | 			display_state = states::DELAY; | ||||||
|  | 			break; | ||||||
|  | 		case states::DELAY: // Delay
 | ||||||
|  | 			if (displayTimer1 != 0 && displayTimer1 < millis()) | ||||||
|  | 			{ | ||||||
|  | 				lcd.clear(); | ||||||
|  | 				display_state = states::MAIN; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case states::READ_RFID: | ||||||
|  | 		{ | ||||||
|  | 			lcd.clear(); | ||||||
|  | 			lcd.print("Card detected."); | ||||||
|  | 			lcd.setCursor(0, 1); | ||||||
|  | 
 | ||||||
|  | 			lcd.print(rfid); | ||||||
|  | 			displayTimer1 = millis() + 3000; | ||||||
|  | 			display_state = states::DELAY; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		default: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	//String input = keyboard.getString();
 | ||||||
|  | 	//Serial.println("Key " + input +  "was pressed");
 | ||||||
| } | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user