Jariullah Safi 4 mesiacov pred
rodič
commit
75902791ef
3 zmenil súbory, kde vykonal 66 pridanie a 38 odobranie
  1. 6 5
      ARCHITECTURE.md
  2. 28 13
      OpenPuck/status_led.cpp
  3. 32 20
      OpenPuck/status_led.h

+ 6 - 5
ARCHITECTURE.md

@@ -86,7 +86,7 @@ just points at the `OpenPuck` directory). Modules are layered low → high:
 | `webusb_config.{h,cpp}` | The WebUSB binary config channel for the browser panel. |
 | `serial_console.{h,cpp}` | The CDC single-letter debug command line. |
 | `wake_hid.{h,cpp}` | A boot-mouse HID interface added to the clean controller modes so the host honors USB remote-wakeup (see "Wake from sleep"). |
-| `status_led.{h,cpp}` | Wake-sent LED indicator: dark in all steady states; flashes 500 ms at each `remoteWakeup()`. Drives both the Feather user LED (P1.15) and the SuperMini clone's blue LED (P0.15); pins/polarity overridable. |
+| `status_led.{h,cpp}` | Two-LED status (PWM-dimmed): blue dim = awake, red dim blink = asleep/wake-armed, blue bright flash = wake sent. Pins/levels/polarity overridable (defaults guess the SuperMini clone). |
 
 ## The controller abstraction
 
@@ -220,10 +220,11 @@ graze and nearly impossible to keep asleep. The only wake triggers are a **Steam
    because some hosts ignore a bare resume signal unless real keyboard/mouse input follows it; it can't be
    sent *during* suspend (reports can't cross a suspended bus), so it's delivered immediately after resume.
 
-The board LED is a wake debugger (`status_led.cpp`): dark in all steady states (including while armed), and a
-500 ms flash at the moment a `remoteWakeup()` is actually sent. Flash + host stays asleep = the resume was sent
-and the host ignored it (fix host-side, e.g. `powercfg /deviceenablewake`); no flash = the firmware never fired
-(it didn't see the gesture, or didn't consider the bus suspended). USB remote wakeup is a **device-level**
+The two board LEDs are a status + wake debugger (`status_led.cpp`, PWM-dimmed): **blue dim** = awake; **red dim
+blink (~2s)** = host asleep and we're armed to wake it; **blue bright flash** = a `remoteWakeup()` was just
+sent. Blue flash + host stays asleep = the resume was sent and the host ignored it (host-side fix, e.g.
+`powercfg /deviceenablewake`, or a missing wake-capable function — see below); no flash on a wake gesture = the
+firmware never fired (didn't see the gesture, or didn't consider the bus suspended). USB remote wakeup is a **device-level**
 signal — one wake line per device, armed by a single `SET_FEATURE(DEVICE_REMOTE_WAKEUP)`; there is no
 per-interface arming on the wire. Which Windows device *node* gets credited is host-internal policy.
 

+ 28 - 13
OpenPuck/status_led.cpp

@@ -1,28 +1,43 @@
 #include "status_led.h"
+#include <Adafruit_TinyUSB.h>
 #include <Arduino.h>
 
-#define WAKE_LED_OFF ((WAKE_LED_ON)==HIGH ? LOW : HIGH)
-#define PULSE_MS 500u   // wake flash duration
+#define BLINK_PERIOD_MS 2000u   // red heartbeat: one dim blip every 2s while wake-armed
+#define BLINK_ON_MS       80u
+#define WAKE_FLASH_MS    500u    // blue flash duration when a wake is sent
 
-static unsigned long g_pulseMs = 0;
-static bool g_lit = false;
+static bool          g_flash = false;
+static unsigned long g_flashMs = 0;
 
-static void ledWrite(int level){
-  digitalWrite(WAKE_LED_PIN_A, level);
-  digitalWrite(WAKE_LED_PIN_B, level);
+// brightness 0 = off .. 255 = full; mapped for LED polarity
+static void ledWrite(int pin, uint8_t brightness){
+#if LED_ACTIVE_HIGH
+  analogWrite(pin, brightness);
+#else
+  analogWrite(pin, (uint8_t)(255 - brightness));
+#endif
 }
 
 void ledInit(){
-  pinMode(WAKE_LED_PIN_A, OUTPUT);
-  pinMode(WAKE_LED_PIN_B, OUTPUT);
-  ledWrite(WAKE_LED_OFF);
+  ledWrite(LED_BLUE_PIN, 0);
+  ledWrite(LED_RED_PIN, 0);
 }
 
 void ledWakePulse(){
-  g_pulseMs = millis(); g_lit = true;
-  ledWrite(WAKE_LED_ON);   // light immediately at the remoteWakeup() call site, not on the next loop
+  g_flash = true; g_flashMs = millis();   // ledTask() picks it up on the next loop (sub-ms)
 }
 
 void ledTask(){
-  if (g_lit && millis()-g_pulseMs >= PULSE_MS){ g_lit = false; ledWrite(WAKE_LED_OFF); }
+  static int lastBlue = -1, lastRed = -1;   // force the first write
+  if (g_flash && millis()-g_flashMs >= WAKE_FLASH_MS) g_flash = false;
+
+  uint8_t blue, red;
+  if (!USBDevice.suspended()){
+    blue = LED_BLUE_DIM; red = 0;                                           // awake
+  } else {
+    blue = g_flash ? LED_BLUE_FLASH : 0;                                    // asleep: blue only on a wake flash
+    red  = ((millis() % BLINK_PERIOD_MS) < BLINK_ON_MS) ? LED_RED_DIM : 0;  // dim heartbeat
+  }
+  if ((int)blue != lastBlue){ lastBlue = blue; ledWrite(LED_BLUE_PIN, blue); }
+  if ((int)red  != lastRed ){ lastRed  = red;  ledWrite(LED_RED_PIN,  red ); }
 }

+ 32 - 20
OpenPuck/status_led.h

@@ -1,28 +1,40 @@
-// status_led.h -- LED indication of wake activity.
+// status_led.h -- two-LED status + wake indicator (PWM-dimmed).
 //
-// The LED is DARK in all steady states -- including while wake is armed (host suspended) -- and flashes for
-// half a second at the moment a wake is actually sent (USBDevice.remoteWakeup() fired by a Steam-button short
-// press, a controller connect, or the boot-time wake). This turns the LED into a wake debugger you can read
-// from the couch: flash + PC stays asleep = the resume signal was sent and the HOST ignored it (fix on the
-// host: powercfg /deviceenablewake); no flash = the firmware never fired (it didn't see the gesture, or it
-// didn't consider the bus suspended).
+//   Awake (bus not suspended):        BLUE on, dim                         RED off
+//   Asleep / wake-armed (suspended):  BLUE off                            RED dim blink every ~2s
+//   Asleep + a wake is being sent:    BLUE flashes bright (~500ms)        RED keeps blinking
 //
-// Board note: the sketch is built with the Feather nRF52840 variant, but the usual hardware is a SuperMini
-// "Pro Micro" clone. The Feather's user LED is P1.15 (D3, active high); the SuperMini's blue user LED is
-// P0.15 (= D24 in the Feather pin map -- SPI MISO, unused by this project). We drive BOTH pins so the
-// indicator works on either board. Override the pins/polarity below if your board differs.
+// So at a glance: steady dim blue = running; slow dim red heartbeat = host asleep & we're armed to wake it;
+// blue flash = we just fired a wake (if the PC then stays asleep, the host ignored our resume -- see
+// "Wake from sleep" in ARCHITECTURE.md).
+//
+// Pin/level config: the sketch builds with the Feather variant but the hardware is a "Pro Micro" nRF52840
+// clone, so these are the board's actual user-LED GPIOs, not the Feather's. Defaults are a best guess for the
+// SuperMini clone (blue P0.15 = D24, red P1.15 = D3, active-high). If the two colors are swapped, swap the
+// pins; if a color never lights, it's on a different GPIO -- override here.
 #pragma once
 
-#ifndef WAKE_LED_PIN_A
-#define WAKE_LED_PIN_A LED_BUILTIN   // Feather: P1.15 user LED (harmless unconnected pad on SuperMini clones)
+#ifndef LED_BLUE_PIN
+#define LED_BLUE_PIN 24            // P0.15 (D24 in the Feather pin map)
+#endif
+#ifndef LED_RED_PIN
+#define LED_RED_PIN  LED_BUILTIN   // P1.15 (D3)
+#endif
+#ifndef LED_ACTIVE_HIGH
+#define LED_ACTIVE_HIGH 1          // 1 = LED lit when pin driven high; set 0 for active-low boards
+#endif
+
+// brightness 0..255 (PWM duty)
+#ifndef LED_BLUE_DIM
+#define LED_BLUE_DIM   16          // "on, dim" steady blue during normal operation
 #endif
-#ifndef WAKE_LED_PIN_B
-#define WAKE_LED_PIN_B 24            // SuperMini "Pro Micro" clone: P0.15 blue user LED (D24 in the Feather map)
+#ifndef LED_BLUE_FLASH
+#define LED_BLUE_FLASH 255         // bright blue flash when a wake is sent
 #endif
-#ifndef WAKE_LED_ON
-#define WAKE_LED_ON HIGH             // set LOW if your board's LED is wired active-low
+#ifndef LED_RED_DIM
+#define LED_RED_DIM    16          // dim red heartbeat while wake-armed
 #endif
 
-void ledInit();        // call once from setup(): pins to output, LED off
-void ledWakePulse();   // call at each USBDevice.remoteWakeup() site: LED on now, off after 500ms
-void ledTask();        // call every loop(): times out the pulse
+void ledInit();        // call once from setup()
+void ledWakePulse();   // call at each USBDevice.remoteWakeup() site -> blue bright for ~500ms
+void ledTask();        // call every loop()