117 lines
2.4 KiB
C++
117 lines
2.4 KiB
C++
#include <PCF8574.h>
|
|
#include <Wire.h>
|
|
|
|
#include "constants.h"
|
|
#include "debug.h"
|
|
|
|
PCF8574 kbd(KBD_I2C_ADDR, &Wire);
|
|
|
|
/*
|
|
Keyboard layout:
|
|
|
|
row/col 0 1 2 3
|
|
|
|
0 1 2 3 A
|
|
1 4 5 6 B
|
|
2 7 8 9 C
|
|
3 * 0 # D
|
|
|
|
Keys, in order:
|
|
123A 456B 789C *0#D
|
|
*/
|
|
|
|
typedef uint8_t Key;
|
|
|
|
const char *allKeys = "123A456B789C*0#D";
|
|
#define KEY_NONE 255
|
|
const uint8_t digits[16] =
|
|
{ 1, 2, 3, KEY_NONE,
|
|
4, 5, 6, KEY_NONE,
|
|
7, 8, 9, KEY_NONE,
|
|
KEY_NONE, 0, KEY_NONE, KEY_NONE};
|
|
|
|
bool setupKeyboard() {
|
|
if (!kbd.begin()) {
|
|
Serial.println("Could not initialize keyboard");
|
|
return false;
|
|
}
|
|
if (!kbd.isConnected()) {
|
|
Serial.println("Keyboard not connected");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Key getPressedKey();
|
|
uint8_t getPressedDigit(Key key);
|
|
|
|
#define KBD_COL_MASK 0b11110000
|
|
#define KBD_ROW_MASK 0b00001111
|
|
|
|
void demoKeyboard() {
|
|
auto key = getPressedKey();
|
|
if (key != KEY_NONE) {
|
|
Serial.print("Key pressed: ");
|
|
Serial.print(allKeys[key]);
|
|
|
|
auto digit = getPressedDigit(key);
|
|
if (digit != KEY_NONE) {
|
|
Serial.print(", digit: ");
|
|
Serial.print(digit);
|
|
} else {
|
|
Serial.print(" (Not a digit)");
|
|
}
|
|
|
|
Serial.println();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns pressed key or KEY_NONE if no key is pressed
|
|
*
|
|
* NOTE: Only one key can be pressed at a time;
|
|
* if multiple keys are pressed, the result is undefined
|
|
*/
|
|
Key getPressedKey() {
|
|
// check pressed column
|
|
// first 4 bits are columns, low when pressed
|
|
kbd.write8(KBD_COL_MASK);
|
|
|
|
uint8_t cols = kbd.read8();
|
|
if (cols == KBD_COL_MASK) {
|
|
return KEY_NONE;
|
|
}
|
|
|
|
uint8_t colState = ~(cols >> 4);
|
|
uint8_t colPressed = 0;
|
|
if (colState & 0b1000) colPressed = 0;
|
|
else if (colState & 0b0100) colPressed = 1;
|
|
else if (colState & 0b0010) colPressed = 2;
|
|
else if (colState & 0b0001) colPressed = 3;
|
|
else fatal();
|
|
|
|
// check pressed row
|
|
// last 4 bits are rows, low when pressed
|
|
kbd.write8(KBD_ROW_MASK);
|
|
|
|
uint8_t rowState = ~kbd.read8();
|
|
uint8_t rowPressed = 0;
|
|
if (rowState & 0b1000) rowPressed = 0;
|
|
else if (rowState & 0b0100) rowPressed = 1;
|
|
else if (rowState & 0b0010) rowPressed = 2;
|
|
else if (rowState & 0b0001) rowPressed = 3;
|
|
else fatal();
|
|
|
|
// return key
|
|
return (rowPressed * 4) + colPressed;
|
|
}
|
|
|
|
/**
|
|
* Returns pressed digit or KEY_NONE if the key is not a digit
|
|
*/
|
|
uint8_t getPressedDigit(Key key) {
|
|
if (key == KEY_NONE) return KEY_NONE;
|
|
return digits[key];
|
|
}
|