From b7bcd7848d46d863d83f3c472258c9591efdca89 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Mon, 5 Aug 2024 10:28:27 -0300 Subject: [PATCH] Adding pinout and parity check to PS/2 implementation --- README.md | 28 +++++++++++++++++++++++++-- lib/LinkPS2Keyboard.hpp | 43 ++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 348ddb4..bfc4dbf 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ A set of Game Boy Advance (GBA) C++ libraries to interact with the Serial Port. ## Usage -- Include the library you want (e.g. [LinkCable.hpp](lib/LinkCable.hpp)) in your game code, and refer to its comments for instructions. Most of these libraries are provided as single header files for simplicity. The only external dependency is **libtonc**, which comes preinstalled with *devkitPro*. +- Include the library you want (e.g. [LinkCable.hpp](lib/LinkCable.hpp)) in your game code, and refer to its comments for instructions. Most of these libraries are provided as single header files for simplicity. The only external dependency is **libtonc**, which comes preinstalled with *devkitARM*. - Check out the [examples](examples) folder. * Builds are available in [Releases](https://github.com/afska/gba-link-connection/releases). * They can be tested on real GBAs or using emulators. @@ -406,6 +406,18 @@ Name | Return type | Description `deactivate()` | - | Deactivates the library. `report(data[3])` | - | Fills the `data` int array with a report. The first int contains _clicks_ that you can check against the bitmasks `LINK_PS2_MOUSE_LEFT_CLICK`, `LINK_PS2_MOUSE_MIDDLE_CLICK`, and `LINK_PS2_MOUSE_RIGHT_CLICK`. The second int is the _X movement_, and the third int is the _Y movement_. +## Pinout + +``` + ____________ +|PS/2 --- GBA| +|------------| +|CLOCK -> SI | +|DATA --> SO | +|VCC ---> VCC| +|GND ---> GND| +``` + # ⌨️ LinkPS2Keyboard A PS/2 keyboard driver for the GBA. Use it to add keyboard support to your homebrew games. @@ -422,4 +434,16 @@ Name | Return type | Description --- | --- | --- `isActive()` | **bool** | Returns whether the library is active or not. `activate()` | - | Activates the library. -`deactivate()` | - | Deactivates the library. \ No newline at end of file +`deactivate()` | - | Deactivates the library. + +## Pinout + +``` + ____________ +|PS/2 --- GBA| +|------------| +|CLOCK -> SI | +|DATA --> SO | +|VCC ---> VCC| +|GND ---> GND| +``` \ No newline at end of file diff --git a/lib/LinkPS2Keyboard.hpp b/lib/LinkPS2Keyboard.hpp index 53851b7..02d287a 100644 --- a/lib/LinkPS2Keyboard.hpp +++ b/lib/LinkPS2Keyboard.hpp @@ -78,6 +78,7 @@ class LinkPS2Keyboard { bitcount = 0; incoming = 0; + parityBit = 0; prevFrame = 0; frameCounter = 0; @@ -94,33 +95,52 @@ class LinkPS2Keyboard { void _onVBlank() { frameCounter++; } void _onSerial() { + if (!isEnabled) + return; + u8 val = (REG_RCNT & LINK_PS2_KEYBOARD_SO_DATA) != 0; u32 nowFrame = frameCounter; if (nowFrame - prevFrame > LINK_PS2_KEYBOARD_TIMEOUT_FRAMES) { bitcount = 0; incoming = 0; + parityBit = 0; } prevFrame = nowFrame; - u8 n = bitcount - 1; - if (n <= 7) - incoming |= (val << n); - bitcount++; - - if (bitcount == 11) { - onEvent(incoming); + if (bitcount == 0 && val == 0) { // start bit detected + // start bit is always 0, so only proceed if val is 0 + bitcount++; + } else if (bitcount >= 1 && bitcount <= 8) { // data bits + incoming |= (val << (bitcount - 1)); + bitcount++; + } else if (bitcount == 9) { // parity bit + // store parity bit for later check + parityBit = val; + bitcount++; + } else if (bitcount == 10) { // stop bit + if (val == 1) { // stop bit should be 1 + // calculate parity (including the stored parity bit from previous IRQ) + u8 parity = 0; + for (u8 i = 0; i < 8; i++) + parity += (incoming >> i) & 1; + parity += parityBit; + if (parity % 2 != 0) // odd parity as expected + onEvent(incoming); + } bitcount = 0; incoming = 0; + parityBit = 0; } } private: bool isEnabled = false; - uint8_t bitcount = 0; - uint8_t incoming = 0; - uint32_t prevFrame = 0; + u8 bitcount = 0; + u8 incoming = 0; + u8 parityBit = 0; + u32 prevFrame = 0; u32 frameCounter = 0; std::function onEvent; }; @@ -135,9 +155,6 @@ inline void LINK_PS2_KEYBOARD_ISR_VBLANK() { } inline void LINK_PS2_KEYBOARD_ISR_SERIAL() { - if (!linkPS2Keyboard->isActive()) - return; - linkPS2Keyboard->_onSerial(); }