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