initial commit

master
Sascha Nitsch 2022-01-05 19:43:28 +01:00
parent 1f065d2375
commit 30e3d7652f
2 changed files with 311 additions and 1 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) <year> <copyright holders>
Copyright (c) 2021 GrumyDeveloper https://contentnation.net/en/grumpydevelop/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

310
ps2keyboardfilter.ino Normal file
View File

@ -0,0 +1,310 @@
#include <EEPROM.h>
#include "ps2_Keyboard.h"
#include "ps2_NullDiagnostics.h"
#include "ps2_UsbTranslator.h"
#include "HID-Project.h"
#define DEBUG 1
// with serial.print...
#ifdef DEBUG
#define SP(a) Serial.print(a);
#define SPLN(a) Serial.println(a);
#else
#define SP(a) ;
#define SPLN(a) ;
#endif
static ps2::NullDiagnostics nd;
static ps2::UsbTranslator<ps2::NullDiagnostics> keyMapping(nd);
static ps2::Keyboard<4, 2, 16, ps2::NullDiagnostics> ps2Keyboard(nd);
static ps2::UsbKeyboardLeds ledValueLastSentToPs2 = ps2::UsbKeyboardLeds::none;
uint8_t activeFilter = 255;
class Filter {
private:
uint8_t m_keys[8] = {0};
uint8_t m_number;
uint8_t m_numKeys;
public:
Filter(uint8_t number) {
m_number = number;
m_numKeys = 0;
}
bool loadFromEEPROM() {
uint8_t offset = m_number * 10; // 10 bytes per filter config
m_numKeys = EEPROM.read(offset); // number of keys
if (m_numKeys > 8 || m_numKeys == 0) {
m_numKeys = 0;
return false;
}
uint8_t chksum = 0;
for (uint8_t i = 0; i < m_numKeys; ++i) {
uint8_t key = EEPROM.read(offset + i + 1);
m_keys[i] = key;
chksum += key;
}
// validate checksum
if (chksum != EEPROM.read(offset + m_numKeys + 1)) {
SP(m_number);
SPLN(F(" checksum failed"));
m_numKeys = 0;
return false;
}
SP(m_number);
SP(F(" loaded "));
SP(m_numKeys);
SPLN(F(" keys"));
return true;
}
void clear() {
for (uint8_t i = 0; i < m_numKeys; ++i) {
m_keys[i] = 0;
}
m_numKeys = 0;
}
void addKey(uint8_t key) {
for (uint8_t i = 0; i < m_numKeys; ++i) {
if (m_keys[i] == key) {
return;
}
}
if (m_numKeys < 7) {
m_keys[m_numKeys++] = key;
}
}
bool writeToEEPROM() {
uint8_t offset = m_number * 10; // 10 bytes per filter config
EEPROM.write(offset, m_numKeys); // number of keys
uint8_t chksum = 0;
for (uint8_t i = 0; i < m_numKeys; ++i) {
EEPROM.write(offset + i + 1, m_keys[i]);
chksum += m_keys[i];
}
// save checksum
EEPROM.write(offset + m_numKeys + 1, chksum);
SP(m_number);
SP(F(" saved "));
SP(m_numKeys);
SPLN(F(" keys"));
return true;
}
bool isFiltered(uint8_t key) {
for (uint8_t i = 0; i < m_numKeys; ++i) {
if (m_keys[i] == key) {
return true;
}
}
return false;
}
};
#define NUM_FILTERS 12
Filter* filters[NUM_FILTERS] = {0};
enum States {
NONE = 0,
PROGRAMMING_SHIFT,
PROGRAMMING_SCROLL,
PROGRAMMING_SELECT,
PROGRAMMING_ADD,
PROGRAMMING_DONE,
APPLY_SHIFT,
APPLY_SCROLL,
APPLY_SELECT,
APPLY_DONE
} currentState = NONE;
uint32_t pressedTime = 0;
uint8_t programFilter = 255;
// the setup function runs once when you press reset or power the board
void setup() {
ps2Keyboard.begin();
BootKeyboard.begin();
#ifdef DEBUG
delay(2000);
Serial.begin(115200);
SPLN(F("ready"));
#endif
for (uint8_t i = 0; i < NUM_FILTERS; ++i) {
filters[i] = new Filter(i);
filters[i]->loadFromEEPROM();
}
filters[11]->clear();
filters[11]->addKey(KEY_E);
activeFilter = 11;
}
#define BLINK_OFF 0
#define BLINK_VERY_SLOW 2000
#define BLINK_SLOW 1000
#define BLINK_MEDIUM 500
#define BLINK_FAST 250
uint16_t blinkTimer = 0;
void loop() {
uint32_t now = millis();
ps2::UsbKeyboardLeds newLedState = (ps2::UsbKeyboardLeds)BootKeyboard.getLeds();
if (blinkTimer != BLINK_OFF) {
uint8_t diff = (now - pressedTime) / blinkTimer;
if (diff & 1) newLedState = (ps2::UsbKeyboardLeds)((uint8_t)newLedState ^ (uint8_t)ps2::UsbKeyboardLeds::scrollLock);
}
if (newLedState != ledValueLastSentToPs2)
{
ps2Keyboard.sendLedStatus(keyMapping.translateLeds(newLedState));
ledValueLastSentToPs2 = newLedState;
}
ps2::KeyboardOutput scanCode = ps2Keyboard.readScanCode();
if (scanCode != ps2::KeyboardOutput::none && scanCode != ps2::KeyboardOutput::garbled) {
ps2::UsbKeyAction action = keyMapping.translatePs2Keycode(scanCode);
KeyboardKeycode hidCode = (KeyboardKeycode)action.hidCode;
switch(currentState) {
case NONE:
if (action.gesture == ps2::UsbKeyAction::KeyDown) {
if (hidCode == KeyboardKeycode::KEY_LEFT_SHIFT) {
currentState = PROGRAMMING_SHIFT;
SPLN(F("to PROGRAMMING_SHIFT"));
} else if (hidCode == KeyboardKeycode::KEY_RIGHT_SHIFT) {
currentState = APPLY_SHIFT;
SPLN(F("to APPLY_SHIFT"));
}
}
break;
case PROGRAMMING_SHIFT:
if (action.gesture == ps2::UsbKeyAction::KeyDown && hidCode == KeyboardKeycode::KEY_SCROLL_LOCK) {
currentState = PROGRAMMING_SCROLL;
blinkTimer = BLINK_SLOW;
pressedTime = now;
SPLN(F("to PROGRAMMING_SCROLL"));
} else if (action.gesture != ps2::UsbKeyAction::KeyDown || hidCode != KeyboardKeycode::KEY_LEFT_SHIFT) {
currentState = NONE;
SPLN(F("PROGRAMMING_SHIFT_to NONE"));
}
break;
case PROGRAMMING_SCROLL:
// to work around a library quirk insted of
// if (action.gesture == ps2::UsbKeyAction::KeyUp && hidCode == KeyboardKeycode::KEY_SCROLL_LOCK && (now - pressedTime) > 5000) {
if (action.gesture == ps2::UsbKeyAction::None && hidCode == 0 && (now - pressedTime) > 5000) {
blinkTimer = BLINK_MEDIUM;
currentState = PROGRAMMING_SELECT;
pressedTime = now;
SPLN(F("to PROGRAMMING_SELECT"));
} else if (action.gesture == ps2::UsbKeyAction::KeyUp || (hidCode != KEY_LEFT_SHIFT && hidCode != KEY_SCROLL_LOCK)) {
currentState = NONE;
blinkTimer = BLINK_OFF;
SPLN(F("PROGRAMMING_SCROLL to NONE"));
}
break;
case PROGRAMMING_SELECT:
if (action.gesture == ps2::UsbKeyAction::KeyDown) {
if(hidCode >= KeyboardKeycode::KEY_F1 && hidCode <= KeyboardKeycode::KEY_F12) {
programFilter = hidCode - KeyboardKeycode::KEY_F1;
filters[programFilter]->clear();
blinkTimer = BLINK_FAST;
SP(F("set filter to "));
SPLN(programFilter);
currentState = PROGRAMMING_ADD;
SPLN(F("to PROGRAMMING_ADD"));
return; // do not send
} else {
currentState = NONE;
programFilter = 255;
blinkTimer = BLINK_OFF;
SP(F("PROGRAMMING_SELECT != F to NONE"));
SPLN(hidCode);
}
return;
}
break;
case PROGRAMMING_ADD:
if (action.gesture == ps2::UsbKeyAction::KeyDown && hidCode == KeyboardKeycode::KEY_SCROLL_LOCK) {
SPLN(F("to PROGRAMMING_DONE"));
currentState = PROGRAMMING_DONE;
}
if (action.gesture == ps2::UsbKeyAction::KeyUp && hidCode != (KeyboardKeycode::KEY_F1 + programFilter)) {
SP(F("add key "));
SPLN(hidCode);
filters[programFilter]->addKey(hidCode);
}
return;
case PROGRAMMING_DONE:
if (action.gesture == ps2::UsbKeyAction::KeyUp && hidCode == KeyboardKeycode::KEY_SCROLL_LOCK) {
SPLN(F("to NONE"));
filters[programFilter]->writeToEEPROM();
currentState = NONE;
blinkTimer = BLINK_OFF;
}
return;
case APPLY_SHIFT:
if (action.gesture == ps2::UsbKeyAction::KeyDown && hidCode == KeyboardKeycode::KEY_SCROLL_LOCK) {
currentState = APPLY_SCROLL;
blinkTimer = BLINK_SLOW;
pressedTime = now;
SPLN(F("to APPLY_SCROLL"));
} else if (action.gesture != ps2::UsbKeyAction::KeyDown || hidCode != KeyboardKeycode::KEY_RIGHT_SHIFT) {
currentState = NONE;
SPLN(F("APPLY_SHIFT_to NONE"));
}
break;
case APPLY_SCROLL:
// to work around a library quirk insted of
// if (action.gesture == ps2::UsbKeyAction::KeyUp && hidCode == KeyboardKeycode::KEY_SCROLL_LOCK && (now - pressedTime) > 1000) {
if (action.gesture == ps2::UsbKeyAction::None && hidCode == 0 && (now - pressedTime) > 1000) {
blinkTimer = BLINK_MEDIUM;
currentState = APPLY_SELECT;
pressedTime = now;
SPLN(F("to APPLY_SELECT"));
} else if (action.gesture == ps2::UsbKeyAction::KeyUp || (hidCode != KEY_RIGHT_SHIFT && hidCode != KEY_SCROLL_LOCK)) {
currentState = NONE;
blinkTimer = BLINK_OFF;
SPLN(F("APPLY_SCROLL to NONE"));
}
break;
case APPLY_SELECT:
if (action.gesture == ps2::UsbKeyAction::KeyDown) {
if(hidCode == KeyboardKeycode::KEY_ESC || (hidCode >= KeyboardKeycode::KEY_F1 && hidCode <= KeyboardKeycode::KEY_F12)) {
activeFilter = hidCode == KeyboardKeycode::KEY_ESC ? 255 : hidCode - KeyboardKeycode::KEY_F1;
SP(F("set filter to "));
SPLN(activeFilter);
currentState = APPLY_DONE;
SPLN(F("to APPLY_DONE"));
return; // do not send
} else {
currentState = NONE;
blinkTimer = BLINK_OFF;
SP(F("APPLY_SELECT != F to NONE"));
SPLN(hidCode);
}
return;
}
break;
case APPLY_DONE:
if (action.gesture == ps2::UsbKeyAction::KeyUp) {
if(hidCode == KeyboardKeycode::KEY_ESC) {
blinkTimer = BLINK_OFF;
currentState = NONE;
SPLN(F("to NONE"));
}
if (hidCode >= KeyboardKeycode::KEY_F1 && hidCode <= KeyboardKeycode::KEY_F12) {
blinkTimer = BLINK_VERY_SLOW;
currentState = NONE;
SPLN(F("to NONE"));
}
}
return;
}
if (activeFilter != 255) {
if (filters[activeFilter]->isFiltered(hidCode)) {
action.gesture = ps2::UsbKeyAction::None;
}
}
switch (action.gesture) {
case ps2::UsbKeyAction::KeyDown:
BootKeyboard.press(hidCode);
break;
case ps2::UsbKeyAction::KeyUp:
BootKeyboard.release(hidCode);
break;
}
}
}