cewkomator/firmware/src/keyboard.cpp

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];
}