소스 검색

Fix for intermittent connection drops (#115)

* increase max tx power to 8dBm to avoid random disconnects

* stream a neutral input on disconnect to prevent issue where controller was stuck reporting last input while disconnected
Chris Leveille 3 달 전
부모
커밋
ff6bffae5c
2개의 변경된 파일과 38개의 추가작업 그리고 1개의 파일을 삭제
  1. 9 1
      OpenPuck/radio.cpp
  2. 29 0
      OpenPuck/rf_link.cpp

+ 9 - 1
OpenPuck/radio.cpp

@@ -126,8 +126,16 @@ void rfConfig(uint8_t ch)
 	NRF_RADIO->EVENTS_DISABLED = 0;
 	NRF_RADIO->MODE = ((uint32_t)g_mode << RADIO_MODE_MODE_Pos);
 	NRF_RADIO->FREQUENCY = ch;
+	// +8dBm = the nRF52840's max TX power (was 0dBm). The link margin is thin on
+	// the Pro Micro's PCB-trace antenna (RSSI reads ~20dB below a real puck), and
+	// 2.4GHz is crowded, so weak polls the controller can't hear -> no reply ->
+	// the reply gaps that read as intermittent disconnects. This only lifts the
+	// puck->controller side (poll/beacon reach); the controller's own TX (the F1
+	// reply) is fixed -- but the poll MUST land for the controller to answer, so
+	// the extra 8dB of headroom directly cuts missed-poll dropouts. USB-powered,
+	// so the higher current draw is free.
 	NRF_RADIO->TXPOWER =
-		(RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);
+		(RADIO_TXPOWER_TXPOWER_Pos8dBm << RADIO_TXPOWER_TXPOWER_Pos);
 #if defined(RADIO_MODECNF0_RU_Fast)
 	NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos);
 #endif

+ 29 - 0
OpenPuck/rf_link.cpp

@@ -941,6 +941,35 @@ void rfLinkTask()
 		rfConnStep();
 	} // connected-mode: poll controller, read input
 
+	// Release stale input on a per-slot link-drop edge. g_in[s] is refreshed ONLY
+	// by the 0x45 decode on a fresh reply, so once a controller goes silent the
+	// last-decoded input is frozen in place: STREAM modes (Switch Hori/Pro, PS5,
+	// DS4-gyro) keep emitting it every cycle, and PUSH modes (Steam/puck, Xbox)
+	// leave the host holding their last report -- a feathered trigger, or a
+	// "release" frame that was the one lost in the gap, stays asserted for the
+	// whole outage (the stuck / false-trigger symptom, most visible on the analog
+	// triggers). On the up->down edge, zero g_in[s] (neutralizes the stream modes)
+	// and push one synthetic neutral 0x45 through the active push mode's normal
+	// build path (neutralizes Steam/puck -- including held lizard keys/mouse --
+	// and Xbox; a no-op for stream modes, which don't override onReport45). The
+	// next real 0x45 on reconnect refills everything. PS3 already streams its own
+	// neutral when no slot is live, so it needs nothing here.
+	{
+		static bool wasUp[NSLOT] = {};
+		static const uint8_t neutral45[46] = { 0x45 };
+		for (int s = 0; s < NSLOT; s++) {
+			bool up = g_slot[s].used && g_connReplyMs[s] != 0 &&
+				  (millis() - g_connReplyMs[s] < 300u);
+			if (wasUp[s] && !up) {
+				memset(&g_in[s], 0, sizeof g_in[s]);
+				if (g_active)
+					g_active->onReport45(s, neutral45, true,
+							     sizeof neutral45);
+			}
+			wasUp[s] = up;
+		}
+	}
+
 	// ---- RF stall self-heal -------------------------------------------------------------------------------
 	// Field wedge: the controllers stay powered and show a SOLID (connected) light, the puck keeps issuing E3
 	// polls + E1 beacons (radio TX is provably alive -- a power-cycled controller still re-adopts the session