From 5b5a0b3e1bce028f44e0577f72e3f3d3a22c4253 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 5 May 2026 08:44:12 +0200 Subject: [PATCH] refactor(driver): move 6POS tracker into board-level ADC callback (#7309) Co-authored-by: Claude Opus 4.7 (1M context) --- .../boards/generic_stm32/analog_inputs.cpp | 7 +++++ radio/src/boards/generic_stm32/rgb_6pos.cpp | 31 ++++++++++++------- radio/src/boards/generic_stm32/rgb_leds.h | 6 ++++ radio/src/hal/adc_driver.cpp | 5 --- radio/src/targets/horus/board.h | 4 --- radio/src/targets/taranis/board.h | 4 --- 6 files changed, 32 insertions(+), 25 deletions(-) diff --git a/radio/src/boards/generic_stm32/analog_inputs.cpp b/radio/src/boards/generic_stm32/analog_inputs.cpp index 0df5ebedc..09f8606e1 100644 --- a/radio/src/boards/generic_stm32/analog_inputs.cpp +++ b/radio/src/boards/generic_stm32/analog_inputs.cpp @@ -31,6 +31,10 @@ #include "ads79xx.h" #endif +#if defined(SIXPOS_SWITCH_INDEX) + #include "rgb_leds.h" +#endif + #include "definitions.h" #include "myeeprom.h" @@ -85,6 +89,9 @@ static void adc_wait_completion() if (n_ADC_spi > 0) ads79xx_adc_wait_completion(&_ADC_spi[0], _ADC_inputs); #endif stm32_hal_adc_wait_completion(_ADC_adc, n_ADC, _ADC_inputs, n_inputs); +#if defined(SIXPOS_SWITCH_INDEX) + sixPosUpdateFromAdc(); +#endif } const etx_hal_adc_driver_t _adc_driver = { diff --git a/radio/src/boards/generic_stm32/rgb_6pos.cpp b/radio/src/boards/generic_stm32/rgb_6pos.cpp index c012226fc..fafbdadff 100644 --- a/radio/src/boards/generic_stm32/rgb_6pos.cpp +++ b/radio/src/boards/generic_stm32/rgb_6pos.cpp @@ -23,29 +23,36 @@ #if defined(SIXPOS_SWITCH_INDEX) && !defined(SIMU) +#include "hal/adc_driver.h" #include "rgb_leds.h" #include // 6POS switch position tracking. // -// The ADC path (mixer task) feeds raw samples into getSixPosAnalogValue() -// which maintains a sticky "last pressed" position — the switch reads -// ~0 when no button is held, so a plain ADC threshold would bounce back -// to position 0. The mixer uses the returned value (0..4096) as the pot -// position for the multipos source. +// sixPosUpdateFromAdc() runs once per ADC conversion from the board +// adc_wait_completion callback. It reads the raw sample out of +// adcValues[SIXPOS_SWITCH_INDEX], maintains a sticky "last pressed" +// position (the switch reads ~0 when no button is held, so a plain +// threshold would bounce back to position 0), and writes the scaled +// 0..4096 sticky value back in place. Downstream consumers +// (getAnalogValue, diaganas, the mixer multipos source, …) then see a +// stable value without any of them driving the state machine. // -// The LED update is NOT done here: _six_pos_state is written by the -// mixer and consumed by rgbLedOnUpdate() below, which runs in the LED -// refresh timer task. That keeps the rgb_leds.cpp back buffer -// single-writer (the LED timer task) for the 6POS range, so Lua's -// applyRGBLedColors pattern cannot race with a mixer-context write. +// The LED update is NOT done here: _six_pos_state is consumed by +// rgbLedOnUpdate() below, which runs in the LED refresh timer task. +// That keeps the rgb_leds.cpp back buffer single-writer (the LED +// timer task) for the 6POS range, so Lua's applyRGBLedColors pattern +// cannot race with an ADC-context write. static uint8_t _last_adc_state = 0; static volatile uint8_t _six_pos_state = 0; -uint16_t getSixPosAnalogValue(uint16_t adcValue) +void sixPosUpdateFromAdc() { + uint16_t* values = getAnalogValues(); + uint16_t adcValue = values[SIXPOS_SWITCH_INDEX]; + uint8_t current = 0; if (adcValue > 3800) current = 6; else if (adcValue > 3100) current = 5; @@ -60,7 +67,7 @@ uint16_t getSixPosAnalogValue(uint16_t adcValue) _six_pos_state = _last_adc_state - 1; } - return (4096 / 5) * _six_pos_state; + values[SIXPOS_SWITCH_INDEX] = (4096 / 5) * _six_pos_state; } void rgbLedOnUpdate() diff --git a/radio/src/boards/generic_stm32/rgb_leds.h b/radio/src/boards/generic_stm32/rgb_leds.h index 155e65163..aacf1d438 100644 --- a/radio/src/boards/generic_stm32/rgb_leds.h +++ b/radio/src/boards/generic_stm32/rgb_leds.h @@ -43,3 +43,9 @@ void rgbLedColorApply(); // indicator) implement this to update their LEDs in the timer task // context, keeping rgb_leds.cpp's back buffer single-writer. void rgbLedOnUpdate(); + +// Invoked by the board ADC wait_completion callback once per conversion +// on radios with a 6POS switch. Reads the raw sample from adcValues[], +// runs the sticky-position state machine, and writes the scaled sticky +// value back in place. Linked only when SIXPOS_SWITCH_INDEX is defined. +void sixPosUpdateFromAdc(); diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 91118e17e..3a396f94d 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -242,11 +242,6 @@ void adcCalibStore() uint16_t getAnalogValue(uint8_t index) { if (index >= MAX_ANALOG_INPUTS) return 0; -#if defined(SIXPOS_SWITCH_INDEX) && !defined(SIMU) - if (index == SIXPOS_SWITCH_INDEX) - return getSixPosAnalogValue(adcValues[index]); - else -#endif return adcValues[index]; } diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 4dbd4e23b..0a5bbb22e 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -242,10 +242,6 @@ bool isBacklightEnabled(); } #endif -#if defined(RADIO_V16) - uint16_t getSixPosAnalogValue(uint16_t adcValue); -#endif - // Audio driver void audioInit(); diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 422954c13..7cecc6749 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -241,10 +241,6 @@ void usbChargerInit(); bool usbChargerLed(); #endif -#if defined(RADIO_V14) || defined(RADIO_V12) - uint16_t getSixPosAnalogValue(uint16_t adcValue); -#endif - // LED driver void ledInit(); void ledOff();