From afc8694c1a87fb22cec859af97e192eac9356927 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 12 Apr 2026 18:06:40 -0500 Subject: [PATCH] Switch DoA to AUDIO_MGR_SELECTED_AZIMUTHS (auto-select beam) DOA_VALUE on GPO resource was sluggish/cached. The beamformer-level AUDIO_MGR_SELECTED_AZIMUTHS on resource 35 tracks the active speaker in real time. Falls back to simple DOA_VALUE when both azimuths are NaN. Co-Authored-By: Claude Opus 4.6 (1M context) --- xvf3800.py | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/xvf3800.py b/xvf3800.py index cd98e5e..1589952 100644 --- a/xvf3800.py +++ b/xvf3800.py @@ -33,8 +33,15 @@ GPO_RESID = 20 # Command IDs (wValue in USB control transfer) # Verified against official xvf_host.py WriteCMD output -DOA_VALUE_CMD = 18 # returns (angle 0-359, vad 0/1) +DOA_VALUE_CMD = 18 # returns (angle 0-359, vad 0/1) — simple, sluggish LED_EFFECT_CMD = 12 # 0=off, 1=breath, 2=rainbow, 3=solid, 4=doa, 5=ring + +# AEC resource (resid=33) — beamformer-level commands, more responsive +AEC_RESID = 33 +AEC_AZIMUTH_CMD = 75 # 4 floats: beam1, beam2, free-running, auto-select (radians) +AEC_SPENERGY_CMD = 80 # 4 floats: speech energy per beam (>0 = speech) +AUDIO_MGR_RESID = 35 +AUDIO_MGR_SELECTED_AZ_CMD = 11 # 2 floats: processed DoA, auto-select DoA (radians) LED_BRIGHTNESS_CMD = 14 LED_COLOR_CMD = 16 # single uint32 color (confirmed: xvf_host LED_COLOR cmdid=16) LED_DOA_COLOR_CMD = 17 # two uint32 values: base + indicator @@ -94,13 +101,35 @@ class XVF3800: # --- DoA --- def read_doa(self) -> tuple[int, bool]: - """Read Direction of Arrival. Returns (angle 0-359, vad True/False). - Response format: 1 status byte + 2 uint16 words (angle, vad).""" - data = self._read_uint16(GPO_RESID, DOA_VALUE_CMD, 2) - if len(data) < 5: + """Read Direction of Arrival using the auto-select beam azimuth. + Returns (angle 0-359 degrees, vad True/False). + Uses AUDIO_MGR_SELECTED_AZIMUTHS which tracks the active speaker.""" + import math + + # Read auto-select beam azimuth (2 floats: processed_doa, auto_select_doa) + data = self._read_float(AUDIO_MGR_RESID, AUDIO_MGR_SELECTED_AZ_CMD, 2) + if len(data) < 9: # 1 status + 2*4 bytes return 0, False - angle, vad = struct.unpack_from("= 5: + angle, vad_flag = struct.unpack_from("