Jelajahi Sumber

once more with feeling

Jariullah Safi 4 bulan lalu
induk
melakukan
0905720edf
2 mengubah file dengan 20 tambahan dan 7 penghapusan
  1. 15 1
      OpenPuck/haptics.cpp
  2. 5 6
      docs/index.html

+ 15 - 1
OpenPuck/haptics.cpp

@@ -231,11 +231,25 @@ void hapticConnectInit(){
   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);
-  hapticReinit();   // then the haptic-engine register block + 0x81 resets (same as the puck's connect haptic init)
+  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;

+ 5 - 6
docs/index.html

@@ -91,18 +91,18 @@
         <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>
-      <div class="row" style="margin:10px 0 0"><button id="hapClear">Clear stuck buzz</button>
+      <!-- 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>
         <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"><label>Connect-time flood</label><button id="buzzFlood">off</button>
+      <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>
       <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>
       </div>
-      <div class="row" style="margin:10px 0 0"><input type="color" id="ledColor" value="#ffffff"><button id="ledSet">Set LED color</button>
-        <span class="note" style="flex:1">Sends the controller LED-color command (0xC1 RGBW). Brightness is separate (Steam's 0x87 reg 2d).</span>
-      </div>
       <div class="row" style="margin:18px 0 0;border-top:1px solid #4a2030;padding-top:14px">
         <button id="factoryErase" style="background:#3a1420;border-color:#7a2233;color:#ff9bb0;font-weight:600">⚠ Factory erase</button>
         <span class="note" style="flex:1"><strong style="color:#ff9bb0">Danger:</strong> wipes <em>all</em> persistent storage on the copycat — the paired controller bond <em>and</em> every saved setting (mode, chords, back-paddle map, sensitivity). The copycat reboots to factory defaults and you must <strong>re-pair the controller</strong>. This cannot be undone.</span>
@@ -352,7 +352,6 @@ $("#capStop").onclick=stopCapture;
 let buzzFloodTimer=null;
 $("#hapClear").onclick=async()=>{ if(dev){ await send([0x07]); $("#hapClear").classList.add("active"); clearTimeout(buzzFloodTimer); buzzFloodTimer=setTimeout(()=>$("#hapClear").classList.remove("active"),30000); log("buzz-clear flood armed — 10Hz re-init for 30s (click again to restart)"); } };
 $("#ctlrOff").onclick=async()=>{ if(dev){ await send([0x08]); log("controller power-off attempt sent — watch link status / capture"); } };
-$("#ledSet").onclick=async()=>{ if(dev){ const h=$("#ledColor").value; const r=parseInt(h.substr(1,2),16),g=parseInt(h.substr(3,2),16),b=parseInt(h.substr(5,2),16); await send([0x09,r,g,b]); log(`LED color set ${h} (r${r} g${g} b${b})`); } };
 $("#factoryErase").onclick=async()=>{
   if(!dev){ log("not connected"); return; }
   // Triple gate so this is impossible to fire accidentally: warn, warn harder, then require typing ERASE.