From c65d505969330e116271462717e966d9c4d613fc Mon Sep 17 00:00:00 2001 From: Jean Jacques Avril Date: Wed, 29 Sep 2021 22:19:43 +0200 Subject: [PATCH] Async Keyboard implementation --- Readme.md | 13 ++++ platformio.ini | 1 + src/Keyboard.cpp | 105 +++++++++++++++++++++++++----- src/Keyboard.h | 17 +++-- src/Rfid.cpp | 9 +++ src/Rfid.h | 8 +++ src/main.cpp | 166 +++++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 292 insertions(+), 27 deletions(-) create mode 100644 Readme.md create mode 100644 src/Rfid.cpp create mode 100644 src/Rfid.h diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..e53c739 --- /dev/null +++ b/Readme.md @@ -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. + diff --git a/platformio.ini b/platformio.ini index 26851cc..4e99892 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,3 +15,4 @@ framework = arduino lib_deps = xreef/PCF8574 library@^2.2.1 marcoschwartz/LiquidCrystal_I2C@^1.1.4 + miguelbalboa/MFRC522@^1.4.9 diff --git a/src/Keyboard.cpp b/src/Keyboard.cpp index 5956450..f8bc932 100644 --- a/src/Keyboard.cpp +++ b/src/Keyboard.cpp @@ -1,14 +1,14 @@ #include "Keyboard.h" -//#define DEBUG +#define DEBUG #define PIN_WIRE_SDA D3 #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) { - 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); for (int i = 1; i < 8; i++) { @@ -35,12 +35,13 @@ Keyboard::~Keyboard() } void Keyboard::scan() { - if (millis() < timeElapsed + this->debounce) - return 0; + if (millis() < _timeElapsed + this->_debounce) + return; uint8_t key = 0; for (int i = 7; i > 4; i--) // Columns { pcf8574->digitalWrite(i, LOW); + delay(15); for (int j = 1; j < 5; j++) { // Rows key++; @@ -51,14 +52,73 @@ void Keyboard::scan() #endif if (val == 0) { - timeElapsed = millis(); - this->lastKey = key; - this->buffer.push(mapChr(key)); + _timeElapsed = millis(); + this->_lastKey = key; + this->_buffer.push_back(mapChr(key)); + pcf8574->digitalWrite(i, HIGH); + return; } } 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) { @@ -73,9 +133,9 @@ char Keyboard::mapChr(uint8_t key) case 4: return 'O'; case 5: - return '5'; + return '2'; case 6: - return '1'; + return '5'; case 7: return '8'; case 8: @@ -93,11 +153,26 @@ char Keyboard::mapChr(uint8_t key) return 'F'; } } -char Keyboard::getChr() +char Keyboard::getLastChr() { - return this->getChr(this->lastKey); + return this->mapChr(this->_lastKey); } -bool Keyboard::available(){ - return (!this->buffer.empty()); +bool Keyboard::available() +{ + 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; } \ No newline at end of file diff --git a/src/Keyboard.h b/src/Keyboard.h index 628563b..ba4e459 100644 --- a/src/Keyboard.h +++ b/src/Keyboard.h @@ -5,19 +5,24 @@ class Keyboard { private: - unsigned long timeElapsed; - std::queue buffer; - uint8_t debounce; + unsigned long _timeElapsed; + std::deque _buffer; + uint8_t _debounce; PCF8574* pcf8574; - int lastKey; + uint8_t _lastKey; + uint8_t _current_scan_col; + void scanColumn(uint8_t *key, uint8_t start, uint8_t stop); /* data */ public: Keyboard(uint8_t debounce); ~Keyboard(); void scan(); + void scanAsync(); void begin(TwoWire *databus); - static char getChr(uint8_t key); - char getChr(); + static char mapChr(uint8_t key); + char getLastChr(); bool available(); + void clear(); + String getString(); }; #endif \ No newline at end of file diff --git a/src/Rfid.cpp b/src/Rfid.cpp new file mode 100644 index 0000000..d1aa5df --- /dev/null +++ b/src/Rfid.cpp @@ -0,0 +1,9 @@ +#include "Rfid.h" + +Rfid::Rfid(/* args */) +{ +} + +Rfid::~Rfid() +{ +} diff --git a/src/Rfid.h b/src/Rfid.h new file mode 100644 index 0000000..5449a01 --- /dev/null +++ b/src/Rfid.h @@ -0,0 +1,8 @@ +class Rfid +{ +private: + /* data */ +public: + Rfid(/* args */); + ~Rfid(); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c84874e..ae7fa9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,25 +2,179 @@ #include #include #include "Keyboard.h" +#include +#include +// 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_SCL D4 #include -TwoWire databus; 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() { Serial.begin(9600); Serial.print("Starting"); 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() { - char key = keyboard.getKey(); - if(key!=0) - Serial.println("Key " + String(key) + "was pressed"); + keyboard.scanAsync(); + + 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"); } \ No newline at end of file