Ver Fonte

going back to original buzz fix

Jariullah Safi há 4 meses atrás
pai
commit
4caa092378
5 ficheiros alterados com 24 adições e 61 exclusões
  1. 5 4
      OpenPuck/config.cpp
  2. 1 1
      OpenPuck/config.h
  3. 15 48
      OpenPuck/haptics.cpp
  4. 0 2
      OpenPuck/haptics.h
  5. 3 6
      docs/index.html

+ 5 - 4
OpenPuck/config.cpp

@@ -9,8 +9,9 @@ bool    g_xbox = false;
 uint8_t g_chordBtn[3] = { MODE_LIZARD, MODE_XBOX, MODE_SW_HORI };   // back4+B/X/Y -> these modes (A always STEAM)
 bool    g_persistMode = false;
 uint8_t g_bootMode = 0xFF;
-bool    g_buzzFlood = false;   // OFF by default: connect-time haptic config (hapticConnectInit) should prevent the
-                               // buzz on its own. ON = also flood the buzz-clear re-init at 10Hz/30s on connect.
+bool    g_buzzFlood = true;    // ON by default: flood the buzz-clear re-init at 10Hz/30s on connect. This is the
+                               // proven mitigation for the connect-time stuck buzz; the connect-config approach
+                               // alone did not fix it. Can be turned off from the WebUSB panel.
 
 bool          g_debugCdcThisBoot = false;
 static uint8_t g_debugCdc = 0;   // persisted one-shot arm, stored in Cfg.rsvd0 (1 = keep CDC for the next boot)
@@ -24,7 +25,7 @@ uint8_t g_back[4] = {5,6,7,8};   // L4->LB R4->RB L5->L3 R5->R3 (0..11 buttons,
 const uint32_t g_pollUs = POLL_US_DEFAULT;
 
 #define CFG_FILE "/cfg.bin"
-#define CFG_MAGIC 0xC8   // bumped (buzzFlood): old cfg ignored -> clean defaults on first boot
+#define CFG_MAGIC 0xC9   // bumped (buzzFlood default ON): old cfg ignored -> new default applies on first boot
 struct Cfg { uint8_t magic, mode, mDiv, mFric, rsvd0, abSwap, back[4], pollU100, persistMode, bootMode, chordBtn[3], buzzFlood; };  // rsvd0 = ex-padSmooth, now the one-shot debug-CDC arm
 
 void saveCfg(){
@@ -54,7 +55,7 @@ void loadCfg(){
       else                 g_usbMode = g_persistMode ? (modeValid(c.mode)?c.mode:0) : 0;
       static const uint8_t CHORD_DEF[3]={MODE_LIZARD,MODE_XBOX,MODE_SW_HORI};
       for(int i=0;i<3;i++) g_chordBtn[i]=modeValid(c.chordBtn[i])?c.chordBtn[i]:CHORD_DEF[i];
-      g_buzzFlood = c.buzzFlood?true:false;   // connect-time buzz-clear flood (default off)
+      g_buzzFlood = c.buzzFlood?true:false;   // connect-time buzz-clear flood (default ON; see g_buzzFlood init)
     }
     f.close();
   }

+ 1 - 1
OpenPuck/config.h

@@ -51,7 +51,7 @@ extern uint8_t g_chordBtn[3];   // back4+B/X/Y -> these modes (A always STEAM)
 // last selected mode across reboots.
 extern bool    g_persistMode;   // false (default) = always boot Steam; true = boot into last mode
 extern uint8_t g_bootMode;      // one-shot: boot into this mode once then clear (!persistMode + explicit switch)
-extern bool    g_buzzFlood;     // false (default) = connect-time haptic config only; true = also 10Hz/30s buzz-clear flood
+extern bool    g_buzzFlood;     // true (default) = 10Hz/30s buzz-clear flood on connect (proven buzz mitigation); false = off
 
 // One-shot debug CDC. Puck mode normally DROPS the CDC serial console to free the USB endpoint its wake-mouse
 // interface needs (so puck can wake a sleeping Windows host). Arming this keeps CDC for the NEXT boot only --

+ 15 - 48
OpenPuck/haptics.cpp

@@ -29,7 +29,8 @@ unsigned long    g_hapticBlockUntil = 0;   // drop Steam haptics briefly during
 
 static unsigned long g_haptic82Ms = 0;     // millis of last 0x82 haptic OUTPUT relayed (Steam mode)
 static bool          g_haptic82On = false; // a non-zero 0x82 haptic is currently active (awaiting host stop)
-static unsigned long g_reinitAt = 0;       // when to fire the ONE post-(re)connect haptic CONNECT-INIT (0 = none)
+static unsigned long g_reinitAt = 0;       // when to fire the next post-reconnect haptic re-init (0 = none scheduled)
+static uint8_t       g_reinitLeft = 0;     // how many re-init shots remain in this connect window
 static bool          g_hapClearArmed=false;// haptic activity happened -> arm a clear once it goes idle (catches a
                                            // latch that engaged during/after use, even seconds after connect)
 
@@ -216,44 +217,9 @@ void hapticReinit(){
   relayEnqueue(0x81, T81A, sizeof T81A);
   relayEnqueue(0x81, T81B, sizeof T81B);
 }
-// ONE-TIME connect config, sent ~200ms after every (re)connect -- this is the part the previous build never sent.
-// The real puck, right after the controller connects, sends a config burst BEYOND the haptic-register block:
-// 0xdc/0xe2 setup commands and 0x87 register writes 0x22=0x64 / 0x23=0x50 (verified in steam-controller-sniff-
-// data.json). OpenPuck only ever sent the haptic-register subset, so the controller came up in a state prone to
-// the connect-buzz latch. We replay that extra config here, then the haptic-register block, ONCE per connect --
-// the intended root-cause fix so the buzz never engages (the 10Hz flood becomes an opt-in fallback, g_buzzFlood).
-// Deliberately omitted vs the raw capture: the LED writes (0x87 reg 0x2d brightness, 0xc1 color -- OpenPuck owns
-// the LED), the 0xed "user/wireless_transport" string (alters transport, Steam-session-specific), and the 0x30
-// gyro-mode writes (0x30=0 disables the gyro -- see hapticReinit). The on-air framing of these matches the puck
-// exactly: rid>=0x87 -> E3 [2+len][01][rid][len][data] (relayEnqueue), e.g. 0xdc -> e3 04 01 dc 02 01 02.
-void hapticConnectInit(){
-  static const uint8_t DC[]  = {0x01,0x02};        // 0xdc setup -> e3 04 01 dc 02 01 02
-  static const uint8_t E2[]  = {0x01,0x20};        // 0xe2 setup -> e3 04 01 e2 02 01 20
-  static const uint8_t R22[] = {0x22,0x64,0x00};   // 0x87 reg 0x22 = 0x0064
-  static const uint8_t R23[] = {0x23,0x50,0x00};   // 0x87 reg 0x23 = 0x0050
-  // reg 0x30 = subsystem enable: bit 0x10 = gyro/IMU streaming, bit 0x08 = haptic engine. 0x0018 enables BOTH.
-  // This is THE missing piece: the real puck's connect init leads with 0x30=0x18, but we had been OMITTING 0x30
-  // entirely (after the gyro bug where flooding 0x30=0x00 froze the IMU). Result: the haptic-enable bit 0x08
-  // never got set, so the engine came up un-armed and latch-prone -> the connect buzz. We send 0x18 (NOT 0x00):
-  // arms the haptic engine AND keeps the gyro streaming (verified in the sniff: 0x30=0x00 freezes gyro; 0x18 is
-  // the puck's own enable value). Sent ONCE per connect, never flooded, so it can't re-break the gyro.
-  static const uint8_t H30[] = {0x30,0x18,0x00, 0x07,0x07,0x00, 0x08,0x07,0x00, 0x31,0x02,0x00, 0x52,0x03,0x00};
-  static const uint8_t H18[] = {0x18,0x00,0x00, 0x2e,0x00,0x00, 0x34,0xff,0xff, 0x35,0xff,0xff, 0x2e,0x00,0x00};
-  static const uint8_t H34[] = {0x34,0xff,0xff, 0x35,0xff,0xff};
-  static const uint8_t T81B[]= {0x01,0x00,0x00,0x00,0x00,0x00,0x00};
-  relayEnqueue(0xdc, DC,  sizeof DC);
-  relayEnqueue(0xe2, E2,  sizeof E2);
-  relayEnqueue(0x87, R22, sizeof R22);
-  relayEnqueue(0x87, R23, sizeof R23);
-  relayEnqueue(0x87, H30, sizeof H30);             // 0x30=0x18 enable + 07/08/31/52
-  relayEnqueue(0x87, H18, sizeof H18);             // 18/2e/34/35 haptic config
-  relayEnqueue(0x87, H34, sizeof H34);
-  relayEnqueue(0x81, nullptr, 0);                  // 0x81 reset bracket
-  relayEnqueue(0x81, T81B, sizeof T81B);           // final 0x81 [01 00 ..] (matches the puck's last connect frame)
-}
 void hapticInit(){
   g_rqHead = g_rqTail = 0; g_haptic82On=false;
-  if(g_buzzFlood) hapticArmBuzzFlood();   // opt-in only: flood the buzz-clear for the first HAPTIC_FLOOD_MS
+  if(g_buzzFlood) hapticArmBuzzFlood();   // flood the buzz-clear for the first HAPTIC_FLOOD_MS (g_buzzFlood: default ON)
   g_hapticBlockUntil = millis() + HAPTIC_RECONNECT_BLOCK_MS;   // boot: block stale Steam 0x82 until link stable
   // NO fabricated stop burst. USB capture proves Steam only ever sends 0x82 [01 01 f7] pulses -- never a
   // zero-gain [01 01 00] "stop". Injecting our invented stop frame (which the real puck never sends) at
@@ -269,11 +235,12 @@ void hapticOnReconnect(){
   g_hapticBlockUntil = millis() + HAPTIC_RECONNECT_BLOCK_MS;   // no haptics relayed for the next 3s
   g_haptic82On = false;
   hapticCancelPendingOn();                                     // drop any haptic ON queued before the link came up
-  // DEFAULT: send the full connect config (hapticConnectInit) ONCE, ~200ms after the link is up -- like the real
-  // puck, so the haptic engine never latches in the first place.
+  // Proactive haptic re-init across the connect window: first shot ~200ms after the link is up, then every
+  // HAPTIC_REINIT_GAP_MS for HAPTIC_REINIT_SHOTS. NOTE: NO 0x30 write anywhere (hapticReinit omits it) -- any
+  // 0x30 write freezes the gyro, so the re-init must stay 0x30-free to keep the IMU streaming.
   g_reinitAt = millis() + 200u;
-  // OPT-IN fallback (g_buzzFlood): also hammer the buzz-clear re-init at 10Hz for 30s, in case the config alone
-  // doesn't fully prevent the buzz on a given board. Off by default.
+  g_reinitLeft = HAPTIC_REINIT_SHOTS;
+  // PRIMARY buzz mitigation (g_buzzFlood, default ON): also hammer the buzz-clear re-init at 10Hz for 30s.
   if(g_buzzFlood) hapticArmBuzzFlood();
   uint8_t mk=2; hapLogAdd(0xFD, 0xEE, &mk, 1);                 // capture marker: RECONNECT detected (block+init armed)
 }
@@ -285,14 +252,14 @@ void hapticTask(){
   if(up && !wasHapticLinkUp){ uint8_t mk=1; hapLogAdd(0xFD,0xEE,&mk,1); hapticOnReconnect(); }
   if(!up && wasHapticLinkUp){ uint8_t mk=0; hapLogAdd(0xFD,0xEE,&mk,1); }
   wasHapticLinkUp=up;
-  if(g_reinitAt && up && (int32_t)(millis()-g_reinitAt) >= 0){   // the ONE connect config, ~200ms after (re)connect
-    hapticConnectInit();
-    g_reinitAt = 0;
+  if(g_reinitAt && up && (int32_t)(millis()-g_reinitAt) >= 0){   // proactive haptic re-init across the connect window
+    hapticReinit();
+    g_reinitAt = (g_reinitLeft && --g_reinitLeft) ? (millis()+HAPTIC_REINIT_GAP_MS) : 0;
   }
-  // OPT-IN buzz-clear FLOOD (g_buzzFlood): while the armed window is open (-> g_buzzFloodUntil) and the link is up,
-  // replay the haptic re-init every HAPTIC_FLOOD_GAP_MS (10Hz) to hammer a stubborn latch. Auto-stops after 30s;
-  // re-armed on connect (only when enabled) and from the WebUSB panel. Off by default -- the connect config above
-  // is meant to prevent the buzz; this is the fallback for boards where it doesn't.
+  // Buzz-clear FLOOD (g_buzzFlood, default ON): while the armed window is open (-> g_buzzFloodUntil) and the link
+  // is up, replay the haptic re-init every HAPTIC_FLOOD_GAP_MS (10Hz) to hammer the stuck-buzz latch. Auto-stops
+  // after 30s; re-armed on every connect and from the WebUSB panel. This is the PRIMARY buzz mitigation -- the
+  // connect config alone did not reliably stop it. Can be disabled from the panel for testing.
   static unsigned long floodMs=0;
   if (g_buzzFlood && (int32_t)(g_buzzFloodUntil - millis()) > 0 && up && millis()-floodMs >= HAPTIC_FLOOD_GAP_MS){ floodMs=millis(); hapticReinit(); }
   // Controller power-off on host SLEEP: send the power-off command (0x9F "off!") the instant the USB bus

+ 0 - 2
OpenPuck/haptics.h

@@ -97,8 +97,6 @@ void rfConnFlushRelay(uint8_t ch, uint8_t s1);
 void hapticInit();   // boot reset: clear relay/active flags, arm the reconnect block
 void hapticTask();   // per-loop upkeep: link-edge markers + steam 0x82 quiet timeout + fires the scheduled re-init
 void hapticReinit(); // replay Steam's haptic-subsystem re-init to the controller -> clears a latched/stuck buzz
-void hapticConnectInit(); // ONE-TIME connect config (0xdc/0xe2 + 0x87 22/23 + the haptic block) -- the real puck's
-                          // full connect init; fired once ~200ms after each (re)connect to keep the buzz from latching
 // Called from rf_link the instant a controller (re)connect is detected (an F-reply after a gap): blocks haptic
 // relays for HAPTIC_RECONNECT_BLOCK_MS and schedules a re-init just after, to keep the freshly-booted
 // controller out of the degraded/latched haptic state. Reliable -- independent of hapticTask's link heuristic.

+ 3 - 6
docs/index.html

@@ -91,14 +91,11 @@
         <div class="stat"><div class="k">Build (git)</div><div class="v" id="stBuild">—</div></div>
       </div>
       <p class="note logonly">Polls/s ≈ 250 expected; it's capped by Loop period (≈4000 µs needed). "Slowest stage" is the loop section eating the most time per iteration.</p>
-      <!-- Buzz-clear controls hidden: the connect-time haptic config (hapticConnectInit) prevents the stuck buzz
-           on its own, so the manual flood + the connect-time flood toggle aren't needed. Elements kept (display:none)
-           so the firmware op 0x07 / SET field 21 and their JS handlers still work if re-shown for debugging. -->
-      <div class="row" style="margin:10px 0 0;display:none"><button id="hapClear">Clear stuck buzz</button>
+      <div class="row" style="margin:10px 0 0"><button id="hapClear">Clear stuck buzz</button>
         <span class="note" style="flex:1">Manually (re)arm the buzz-clear flood now: replays the haptic re-init at 10&nbsp;Hz for 30&nbsp;s (same as pressing Steam). Use it if a buzz shows up right now.</span>
       </div>
-      <div class="row" style="margin:10px 0 0;display:none"><label>Connect-time flood</label><button id="buzzFlood">off</button>
-        <span class="note" style="flex:1">The copycat now sends the real puck's full haptic config once on connect, which should keep the buzz from ever latching. If a board <em>still</em> buzzes in the first minute, turn this <strong>on</strong> to also flood the buzz-clear re-init at 10&nbsp;Hz for 30&nbsp;s after every connect. Off by default; persists across reboots.</span>
+      <div class="row" style="margin:10px 0 0"><label>Connect-time flood</label><button id="buzzFlood">off</button>
+        <span class="note" style="flex:1">Floods the buzz-clear re-init at 10&nbsp;Hz for 30&nbsp;s after every connect — the proven fix for the connect-time stuck buzz. <strong>On by default</strong>; only turn it off if you're testing. Persists across reboots.</span>
       </div>
       <div class="row" style="margin:10px 0 0"><button id="ctlrOff">Turn off controller (test)</button>
         <span class="note" style="flex:1">Fires the controller power-off (0x9F "off!", x3) — the same path host-suspend uses. Watch the capture / link status to see if the controller actually disconnects.</span>