From c8ca5406518d1f13c996b143863da1a1328fcfa2 Mon Sep 17 00:00:00 2001 From: Eirik Stople Date: Sun, 26 May 2024 22:29:25 +0200 Subject: [PATCH] Disable PS2 pullup when power supply is off This is to prevent trying to power the keyboard via the PS2 ports when the power supply is off. --- ps2.h | 13 +++++++++++-- x16-smc.ino | 21 ++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/ps2.h b/ps2.h index 3fc4efc..fa5800a 100644 --- a/ps2.h +++ b/ps2.h @@ -4,6 +4,8 @@ #include "optimized_gpio.h" #define SCANCODE_TIMEOUT_MS 50 +bool PWR_ON_active(); + enum PS2_CMD_STATUS : uint8_t { IDLE = 0, CMD_PENDING = 1, @@ -44,8 +46,15 @@ class PS2Port }; virtual void resetInput() { - gpio_inputWithPullup(datPin); - gpio_inputWithPullup(clkPin); + if (PWR_ON_active()) { + gpio_inputWithPullup(datPin); + gpio_inputWithPullup(clkPin); + } else { + // Prevent powering the keyboard via the pull-ups when system is off + // Call reset() after changing PWR_ON + pinMode_opt(datPin, INPUT); + pinMode_opt(clkPin, INPUT); + } curCode = 0; parity = 0; rxBitCount = 0; diff --git a/x16-smc.ino b/x16-smc.ino index 0a1ad42..7ff7d60 100644 --- a/x16-smc.ino +++ b/x16-smc.ino @@ -171,8 +171,8 @@ void setup() { // Setup Power Supply pinMode_opt(PWR_OK, INPUT); - pinMode_opt(PWR_ON, OUTPUT); digitalWrite_opt(PWR_ON, HIGH); + pinMode_opt(PWR_ON, OUTPUT); // Turn Off Activity LED pinMode_opt(ACT_LED, OUTPUT); @@ -317,6 +317,8 @@ void PowerOffSeq() { digitalWrite_opt(ACT_LED, ACT_LED_OFF); // Ensure activity LED is off _delay_ms(AUDIOPOP_HOLDTIME_MS); // Wait for audio system to stabilize before power is turned off digitalWrite_opt(PWR_ON, HIGH); // Turn off supply + Keyboard.reset(); // Reset and deactivate pullup + Mouse.reset(); // Reset and deactivate pullup SYSTEM_POWERED = 0; // Global Power state Off _delay_ms(RESB_HOLDTIME_MS); // Mostly here to add some delay between presses deassertReset(); @@ -325,6 +327,8 @@ void PowerOffSeq() { void PowerOnSeq() { assertReset(); digitalWrite_opt(PWR_ON, LOW); // turn on power supply + Keyboard.reset(); // Reset and activate pullup + Mouse.reset(); // Reset and activate pullup unsigned long TimeDelta = 0; unsigned long StartTime = millis(); // get current time while (!digitalRead_opt(PWR_OK)) { // Time how long it takes @@ -336,8 +340,6 @@ void PowerOnSeq() { // insert error handler, flash activity light & Halt? IE, require hard power off before continue? } else { - Keyboard.flush(); - Mouse.reset(); defaultRequest = I2C_CMD_GET_KEYCODE_FAST; _delay_ms(RESB_HOLDTIME_MS); // Allow system to stabilize SYSTEM_POWERED = 1; // Global Power state On @@ -594,3 +596,16 @@ ISR(TIMER1_COMPA_vect) { Keyboard.timerInterrupt(); Mouse.timerInterrupt(); } + +bool PWR_ON_active() +{ + // Returns the status of the PWR_ON output port. + // PWR_ON is active low. + // Thus, return true if DDR is output (1) and if PORT is low (0). + // Similar to the SYSTEM_POWERED variable, but this is more accurate when power is changing. + // A future code improvement can be to make gpio functions to read from PORT/DDR register + // PWR_ON is 5, which is PA5 + + if ((DDRA & _BV(5)) == 0) return false; // Port is input. This is the case when mouse and keyboard objects are created + return (PORTA & _BV(5)) ? false : true; +}