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 =
|
||||
xreef/PCF8574 library@^2.2.1
|
||||
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"
|
||||
//#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;
|
||||
}
|
@ -5,19 +5,24 @@
|
||||
class Keyboard
|
||||
{
|
||||
private:
|
||||
unsigned long timeElapsed;
|
||||
std::queue<char> buffer;
|
||||
uint8_t debounce;
|
||||
unsigned long _timeElapsed;
|
||||
std::deque<char> _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
|
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 <Wire.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_SCL D4
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
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");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user