feat(radio): support faster RGB led timings on compatible hardware (#7144)
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
|
||||
#if defined(LED_STRIP_GPIO)
|
||||
|
||||
#include "stm32_ws2812.h"
|
||||
#include "stm32_rgbleds.h"
|
||||
#include "stm32_dma.h"
|
||||
#include "stm32_gpio.h"
|
||||
#include "hal/gpio.h"
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
// Front buffer: read by the WS2812 DMA ISR. Mutated only inside
|
||||
// _flush_and_update() and only when DMA is idle.
|
||||
static uint8_t _led_colors[WS2812_BYTES_PER_LED * LED_STRIP_LENGTH];
|
||||
static uint8_t _led_colors[RGBLEDS_BYTES_PER_LED * LED_STRIP_LENGTH];
|
||||
|
||||
// Back buffer: written by rgbSetLedColor (menu task / pre-OS, single writer).
|
||||
// Read only inside _flush_and_update() when a new frame has been published.
|
||||
static uint8_t _back_colors[WS2812_BYTES_PER_LED * LED_STRIP_LENGTH];
|
||||
static uint8_t _back_colors[RGBLEDS_BYTES_PER_LED * LED_STRIP_LENGTH];
|
||||
|
||||
// Seqlock-style publish using a single counter:
|
||||
// - LSB set (odd) → menu task is mid-batch, back buffer not consistent
|
||||
@@ -77,50 +77,15 @@ static timer_handle_t _refresh_timer = TIMER_INITIALIZER;
|
||||
|
||||
static void _flush_and_update()
|
||||
{
|
||||
if (!ws2812_is_busy(&_led_timer)) {
|
||||
if (!rgbleds_is_busy(&_led_timer)) {
|
||||
uint32_t seq = _commit_seq;
|
||||
// Skip if mid-batch (odd) or already consumed.
|
||||
if ((seq & 1u) == 0u && seq != _consumed_seq) {
|
||||
memcpy(_led_colors, _back_colors, sizeof(_led_colors));
|
||||
_consumed_seq = seq;
|
||||
}
|
||||
rgbleds_update(&_led_timer);
|
||||
}
|
||||
ws2812_update(&_led_timer);
|
||||
}
|
||||
|
||||
void rgbSetLedColor(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
_begin_batch();
|
||||
ws2812_set_color_in_buf(_back_colors, led, r, g, b);
|
||||
}
|
||||
|
||||
uint32_t rgbGetLedColor(uint8_t led)
|
||||
{
|
||||
return ws2812_get_color_in_buf(_back_colors, led);
|
||||
}
|
||||
|
||||
bool rgbGetState(uint8_t led)
|
||||
{
|
||||
return ws2812_get_state_in_buf(_back_colors, led);
|
||||
}
|
||||
|
||||
void rgbLedColorApply()
|
||||
{
|
||||
// Publish: ensure the back-buffer write is complete, then advance to
|
||||
// the next even value. (seq | 1) + 1 == round up to next even.
|
||||
_compiler_barrier();
|
||||
_commit_seq = (_commit_seq | 1u) + 1u;
|
||||
if (!scheduler_is_running()) {
|
||||
// Pre-OS: timer task isn't running, drive the flush synchronously.
|
||||
_flush_and_update();
|
||||
}
|
||||
}
|
||||
|
||||
void rgbLedClearAll()
|
||||
{
|
||||
_begin_batch();
|
||||
memset(_back_colors, 0, sizeof(_back_colors));
|
||||
rgbLedColorApply();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void rgbLedOnUpdate() {}
|
||||
@@ -168,7 +133,7 @@ static bool _hw_initialised = false;
|
||||
void rgbLedHwInit()
|
||||
{
|
||||
if (_hw_initialised) return;
|
||||
ws2812_init(&_led_timer, _led_colors, LED_STRIP_LENGTH, WS2812_GRB);
|
||||
rgbleds_init(&_led_timer, _led_colors, LED_STRIP_LENGTH, RGBLEDS_GRB);
|
||||
_hw_initialised = true;
|
||||
rgbLedClearAll();
|
||||
}
|
||||
@@ -179,6 +144,41 @@ void rgbLedInit()
|
||||
rgbLedStart();
|
||||
}
|
||||
|
||||
void rgbSetLedColor(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
_begin_batch();
|
||||
rgbleds_set_color_in_buf(_back_colors, led, r, g, b);
|
||||
}
|
||||
|
||||
uint32_t rgbGetLedColor(uint8_t led)
|
||||
{
|
||||
return rgbleds_get_color_in_buf(_back_colors, led);
|
||||
}
|
||||
|
||||
bool rgbGetState(uint8_t led)
|
||||
{
|
||||
return rgbleds_get_state_in_buf(_back_colors, led);
|
||||
}
|
||||
|
||||
void rgbLedColorApply()
|
||||
{
|
||||
// Publish: ensure the back-buffer write is complete, then advance to
|
||||
// the next even value. (seq | 1) + 1 == round up to next even.
|
||||
_compiler_barrier();
|
||||
_commit_seq = (_commit_seq | 1u) + 1u;
|
||||
if (!scheduler_is_running()) {
|
||||
// Pre-OS: timer task isn't running, drive the flush synchronously.
|
||||
_flush_and_update();
|
||||
}
|
||||
}
|
||||
|
||||
void rgbLedClearAll()
|
||||
{
|
||||
_begin_batch();
|
||||
memset(_back_colors, 0, sizeof(_back_colors));
|
||||
rgbLedColorApply();
|
||||
}
|
||||
|
||||
// Make sure the timer channel is supported
|
||||
static_assert(__STM32_PULSE_IS_TIMER_CHANNEL_SUPPORTED(LED_STRIP_TIMER_CHANNEL),
|
||||
"Unsupported timer channel");
|
||||
@@ -193,7 +193,7 @@ static_assert(__STM32_DMA_IS_STREAM_SUPPORTED(LED_STRIP_TIMER_DMA_STREAM),
|
||||
|
||||
extern "C" void LED_STRIP_TIMER_DMA_IRQHandler()
|
||||
{
|
||||
ws2812_dma_isr(&_led_timer);
|
||||
rgbleds_dma_isr(&_led_timer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "bsp_io.h"
|
||||
|
||||
#include "stm32_ws2812.h"
|
||||
#include "stm32_rgbleds.h"
|
||||
#include "stm32_switch_driver.h"
|
||||
#include "stm32_i2c_driver.h"
|
||||
#include "hal/switch_driver.h"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "os/sleep.h"
|
||||
#include "os/time.h"
|
||||
#if !defined(SIMU)
|
||||
#include "stm32_ws2812.h"
|
||||
#include "stm32_rgbleds.h"
|
||||
#include "boards/generic_stm32/rgb_leds.h"
|
||||
#include "stm32_hal.h"
|
||||
#include "stm32_hal_ll.h"
|
||||
|
||||
+66
-45
@@ -19,10 +19,10 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "stm32_ws2812.h"
|
||||
#include "stm32_rgbleds.h"
|
||||
#include "stm32_dma.h"
|
||||
|
||||
#if defined(DEBUG_WS2812)
|
||||
#if defined(DEBUG_RGBLEDS)
|
||||
// LED_STRIP_DEBUG_GPIO && LED_STRIP_DEBUG_GPIO_PIN
|
||||
#include "hal.h"
|
||||
#endif
|
||||
@@ -43,24 +43,35 @@ static uint8_t _b_offset;
|
||||
|
||||
// DMA buffer contains data for 2 LEDs and is filled
|
||||
// half by half on DMA HT and TC IRQs
|
||||
#define WS2821_DMA_BUFFER_HALF_LEN (WS2812_BYTES_PER_LED * 8)
|
||||
#define WS2821_DMA_BUFFER_LEN (WS2821_DMA_BUFFER_HALF_LEN * 2)
|
||||
#define RGBLEDS_DMA_BUFFER_HALF_LEN (RGBLEDS_BYTES_PER_LED * 8)
|
||||
#define RGBLEDS_DMA_BUFFER_LEN (RGBLEDS_DMA_BUFFER_HALF_LEN * 2)
|
||||
#define RGBLEDS_DMA_IRQ_PRIO 3
|
||||
|
||||
// Bit timing in ns (period / '1' HIGH / '0' HIGH), converted to timer ticks at
|
||||
// init from the actual timer clock so it holds on any clock domain.
|
||||
#if defined(RGB_LEDS_900NS)
|
||||
#define RGBLEDS_PERIOD_NS 917UL
|
||||
#define RGBLEDS_T1H_NS 583UL
|
||||
#define RGBLEDS_T0H_NS 250UL
|
||||
#else
|
||||
#define RGBLEDS_PERIOD_NS 1250UL
|
||||
#define RGBLEDS_T1H_NS 938UL
|
||||
#define RGBLEDS_T0H_NS 313UL
|
||||
#endif
|
||||
|
||||
#define RGBLEDS_NS_TO_TICKS(freq, ns) \
|
||||
(uint32_t)(((uint64_t)(freq) * (ns) + 500000000UL) / 1000000000UL)
|
||||
|
||||
#define WS2812_FREQ 800000UL // 800 kHz
|
||||
#define WS2812_TIMER_PERIOD 20UL
|
||||
#define WS2812_ONE (3 * WS2812_TIMER_PERIOD / 4)
|
||||
#define WS2812_ZERO (1 * WS2812_TIMER_PERIOD / 4)
|
||||
#define WS2812_DMA_IRQ_PRIO 3
|
||||
|
||||
// Debug facility
|
||||
#if defined(LED_STRIP_DEBUG_GPIO) && defined(LED_STRIP_DEBUG_GPIO_PIN)
|
||||
|
||||
#define WS2812_DBG_INIT _led_dbg_init()
|
||||
#define RGBLEDS_DBG_INIT _led_dbg_init()
|
||||
|
||||
#define WS2812_DBG_HIGH \
|
||||
#define RGBLEDS_DBG_HIGH \
|
||||
LL_GPIO_SetOutputPin(LED_STRIP_DEBUG_GPIO, LED_STRIP_DEBUG_GPIO_PIN)
|
||||
|
||||
#define WS2812_DBG_LOW \
|
||||
#define RGBLEDS_DBG_LOW \
|
||||
LL_GPIO_ResetOutputPin(LED_STRIP_DEBUG_GPIO, LED_STRIP_DEBUG_GPIO_PIN)
|
||||
|
||||
static void _led_dbg_init() {
|
||||
@@ -68,26 +79,30 @@ static void _led_dbg_init() {
|
||||
pinInit.Mode = LL_GPIO_MODE_OUTPUT;
|
||||
pinInit.Pin = LED_STRIP_DEBUG_GPIO_PIN;
|
||||
LL_GPIO_Init(LED_STRIP_DEBUG_GPIO, &pinInit);
|
||||
WS2812_DBG_LOW;
|
||||
RGBLEDS_DBG_LOW;
|
||||
}
|
||||
|
||||
#else // LED_STRIP_DEBUG_GPIO && LED_STRIP_DEBUG_GPIO_PIN
|
||||
|
||||
#define WS2812_DBG_INIT
|
||||
#define WS2812_DBG_HIGH
|
||||
#define WS2812_DBG_LOW
|
||||
#define RGBLEDS_DBG_INIT
|
||||
#define RGBLEDS_DBG_HIGH
|
||||
#define RGBLEDS_DBG_LOW
|
||||
|
||||
#endif
|
||||
|
||||
typedef uint16_t led_timer_value_t;
|
||||
uint8_t pulse_inc = 1;
|
||||
|
||||
// HIGH time (timer ticks) for a '1' and a '0' bit, computed at init.
|
||||
static led_timer_value_t _led_one;
|
||||
static led_timer_value_t _led_zero;
|
||||
|
||||
// DMA buffer contains pulses for 2 LED at a time
|
||||
// (allows for refill at HT and TC)
|
||||
#if defined(STM32_SUPPORT_32BIT_TIMERS)
|
||||
static led_timer_value_t _led_dma_buffer[WS2821_DMA_BUFFER_LEN * 2] __DMA_NO_CACHE;
|
||||
static led_timer_value_t _led_dma_buffer[RGBLEDS_DMA_BUFFER_LEN * 2] __DMA_NO_CACHE;
|
||||
#else
|
||||
static led_timer_value_t _led_dma_buffer[WS2821_DMA_BUFFER_LEN] __DMA_NO_CACHE;
|
||||
static led_timer_value_t _led_dma_buffer[RGBLEDS_DMA_BUFFER_LEN] __DMA_NO_CACHE;
|
||||
#endif
|
||||
|
||||
static uint8_t _led_seq_cnt;
|
||||
@@ -95,7 +110,7 @@ static uint8_t _led_seq_cnt;
|
||||
static void _fill_byte(uint8_t c, led_timer_value_t* dma_buffer)
|
||||
{
|
||||
for (int i = 0; i < 8; i++) {
|
||||
dma_buffer[i*pulse_inc] = c & 0x80 ? WS2812_ONE : WS2812_ZERO;
|
||||
dma_buffer[i*pulse_inc] = c & 0x80 ? _led_one : _led_zero;
|
||||
c <<= 1;
|
||||
}
|
||||
}
|
||||
@@ -111,25 +126,25 @@ static void _fill_pulses(const uint8_t* colors, led_timer_value_t* dma_buffer, u
|
||||
|
||||
static inline uint32_t _calc_offset(uint8_t tc)
|
||||
{
|
||||
return tc * WS2821_DMA_BUFFER_HALF_LEN * pulse_inc;
|
||||
return tc * RGBLEDS_DMA_BUFFER_HALF_LEN * pulse_inc;
|
||||
}
|
||||
|
||||
static void _update_dma_buffer(const stm32_pulse_timer_t* tim, uint8_t tc)
|
||||
{
|
||||
WS2812_DBG_HIGH;
|
||||
RGBLEDS_DBG_HIGH;
|
||||
if (_led_seq_cnt < _led_strip_len) {
|
||||
|
||||
auto idx = WS2812_BYTES_PER_LED * _led_seq_cnt;
|
||||
auto idx = RGBLEDS_BYTES_PER_LED * _led_seq_cnt;
|
||||
auto offset = _calc_offset(tc);
|
||||
_fill_pulses(&_led_colors[idx], &_led_dma_buffer[offset], WS2812_BYTES_PER_LED);
|
||||
_fill_pulses(&_led_colors[idx], &_led_dma_buffer[offset], RGBLEDS_BYTES_PER_LED);
|
||||
_led_seq_cnt++;
|
||||
|
||||
} else if(_led_seq_cnt < _led_strip_len + WS2812_TRAILING_RESET) {
|
||||
} else if(_led_seq_cnt < _led_strip_len + RGBLEDS_TRAILING_RESET) {
|
||||
|
||||
// no need to reset the buffer after 2 cycles
|
||||
if (_led_seq_cnt < _led_strip_len + 2) {
|
||||
auto offset = _calc_offset(tc);
|
||||
auto size = WS2821_DMA_BUFFER_HALF_LEN * sizeof(led_timer_value_t) * pulse_inc;
|
||||
auto size = RGBLEDS_DMA_BUFFER_HALF_LEN * sizeof(led_timer_value_t) * pulse_inc;
|
||||
memset(&_led_dma_buffer[offset], 0, size);
|
||||
}
|
||||
_led_seq_cnt++;
|
||||
@@ -147,10 +162,10 @@ static void _update_dma_buffer(const stm32_pulse_timer_t* tim, uint8_t tc)
|
||||
|
||||
LL_TIM_CC_DisableChannel(tim->TIMx, tim->TIM_Channel);
|
||||
}
|
||||
WS2812_DBG_LOW;
|
||||
RGBLEDS_DBG_LOW;
|
||||
}
|
||||
|
||||
void ws2812_dma_isr(const stm32_pulse_timer_t* tim)
|
||||
void rgbleds_dma_isr(const stm32_pulse_timer_t* tim)
|
||||
{
|
||||
if (LL_DMA_IsEnabledIT_HT(tim->DMAx, tim->DMA_Stream) &&
|
||||
stm32_dma_check_ht_flag(tim->DMAx, tim->DMA_Stream)) {
|
||||
@@ -187,31 +202,37 @@ static void _led_set_dma_periph_addr(const stm32_pulse_timer_t* tim)
|
||||
|
||||
static void _init_timer(const stm32_pulse_timer_t* tim)
|
||||
{
|
||||
stm32_pulse_init(tim, WS2812_FREQ * WS2812_TIMER_PERIOD);
|
||||
// Run at the full timer clock (prescaler 0) and derive the periods from it.
|
||||
uint32_t cnt_freq = tim->TIM_Freq;
|
||||
stm32_pulse_init(tim, cnt_freq);
|
||||
stm32_pulse_config_output(tim, true, LL_TIM_OCMODE_PWM1, 0);
|
||||
LL_TIM_SetAutoReload(tim->TIMx, WS2812_TIMER_PERIOD - 1);
|
||||
|
||||
uint32_t period = RGBLEDS_NS_TO_TICKS(cnt_freq, RGBLEDS_PERIOD_NS);
|
||||
_led_one = RGBLEDS_NS_TO_TICKS(cnt_freq, RGBLEDS_T1H_NS);
|
||||
_led_zero = RGBLEDS_NS_TO_TICKS(cnt_freq, RGBLEDS_T0H_NS);
|
||||
LL_TIM_SetAutoReload(tim->TIMx, period - 1);
|
||||
|
||||
// pulse driver uses DMA to ARR, but we need CCRx
|
||||
_led_set_dma_periph_addr(tim);
|
||||
|
||||
LL_DMA_SetMode(tim->DMAx, tim->DMA_Stream, LL_DMA_MODE_CIRCULAR);
|
||||
LL_DMA_SetDataLength(tim->DMAx, tim->DMA_Stream, WS2821_DMA_BUFFER_LEN);
|
||||
LL_DMA_SetDataLength(tim->DMAx, tim->DMA_Stream, RGBLEDS_DMA_BUFFER_LEN);
|
||||
LL_DMA_SetMemoryAddress(tim->DMAx, tim->DMA_Stream, (uint32_t)_led_dma_buffer);
|
||||
|
||||
// we need to use a higher prio to avoid having
|
||||
// issues with some other things used during boot
|
||||
NVIC_SetPriority(tim->DMA_IRQn, WS2812_DMA_IRQ_PRIO);
|
||||
NVIC_SetPriority(tim->DMA_IRQn, RGBLEDS_DMA_IRQ_PRIO);
|
||||
}
|
||||
|
||||
void ws2812_init(const stm32_pulse_timer_t* timer, uint8_t* strip_colors,
|
||||
void rgbleds_init(const stm32_pulse_timer_t* timer, uint8_t* strip_colors,
|
||||
uint8_t strip_len, uint8_t type)
|
||||
{
|
||||
WS2812_DBG_INIT;
|
||||
RGBLEDS_DBG_INIT;
|
||||
pulse_inc = IS_TIM_32B_COUNTER_INSTANCE(timer->TIMx) ? 2 : 1;
|
||||
|
||||
_led_colors = strip_colors;
|
||||
_led_strip_len = strip_len;
|
||||
memset(_led_colors, 0, strip_len * WS2812_BYTES_PER_LED);
|
||||
memset(_led_colors, 0, strip_len * RGBLEDS_BYTES_PER_LED);
|
||||
memset(_led_dma_buffer, 0, sizeof(_led_dma_buffer));
|
||||
|
||||
_r_offset = (type >> 4) & 0b11;
|
||||
@@ -221,41 +242,41 @@ void ws2812_init(const stm32_pulse_timer_t* timer, uint8_t* strip_colors,
|
||||
_init_timer(timer);
|
||||
}
|
||||
|
||||
void ws2812_set_color_in_buf(uint8_t* buf, uint8_t led,
|
||||
uint8_t r, uint8_t g, uint8_t b)
|
||||
void rgbleds_set_color_in_buf(uint8_t* buf, uint8_t led,
|
||||
uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
if (led >= _led_strip_len) return;
|
||||
|
||||
uint8_t* pixel = &buf[led * WS2812_BYTES_PER_LED];
|
||||
uint8_t* pixel = &buf[led * RGBLEDS_BYTES_PER_LED];
|
||||
pixel[_r_offset] = r;
|
||||
pixel[_g_offset] = g;
|
||||
pixel[_b_offset] = b;
|
||||
}
|
||||
|
||||
uint32_t ws2812_get_color_in_buf(const uint8_t* buf, uint8_t led)
|
||||
uint32_t rgbleds_get_color_in_buf(const uint8_t* buf, uint8_t led)
|
||||
{
|
||||
if (led >= _led_strip_len) return 0;
|
||||
|
||||
const uint8_t* pixel = &buf[led * WS2812_BYTES_PER_LED];
|
||||
const uint8_t* pixel = &buf[led * RGBLEDS_BYTES_PER_LED];
|
||||
return (pixel[1] << 16) + (pixel[0] << 8) + pixel[2];
|
||||
}
|
||||
|
||||
bool ws2812_get_state_in_buf(const uint8_t* buf, uint8_t led)
|
||||
bool rgbleds_get_state_in_buf(const uint8_t* buf, uint8_t led)
|
||||
{
|
||||
if (led >= _led_strip_len) return false;
|
||||
|
||||
const uint8_t* pixel = &buf[led * WS2812_BYTES_PER_LED];
|
||||
const uint8_t* pixel = &buf[led * RGBLEDS_BYTES_PER_LED];
|
||||
return pixel[0] || pixel[1] || pixel[2];
|
||||
}
|
||||
|
||||
bool ws2812_is_busy(const stm32_pulse_timer_t* tim)
|
||||
bool rgbleds_is_busy(const stm32_pulse_timer_t* tim)
|
||||
{
|
||||
return LL_DMA_IsEnabledStream(tim->DMAx, tim->DMA_Stream);
|
||||
}
|
||||
|
||||
void ws2812_update(const stm32_pulse_timer_t* tim)
|
||||
void rgbleds_update(const stm32_pulse_timer_t* tim)
|
||||
{
|
||||
WS2812_DBG_HIGH;
|
||||
RGBLEDS_DBG_HIGH;
|
||||
if (!stm32_pulse_if_not_running_disable(tim)) return;
|
||||
|
||||
_led_seq_cnt = 0;
|
||||
@@ -269,5 +290,5 @@ void ws2812_update(const stm32_pulse_timer_t* tim)
|
||||
LL_TIM_CC_EnableChannel(tim->TIMx, tim->TIM_Channel);
|
||||
LL_TIM_EnableCounter(tim->TIMx);
|
||||
|
||||
WS2812_DBG_LOW;
|
||||
RGBLEDS_DBG_LOW;
|
||||
}
|
||||
+14
-14
@@ -24,29 +24,29 @@
|
||||
#include "stm32_pulse_driver.h"
|
||||
|
||||
// Offset: R G B
|
||||
#define WS2812_RGB ((0 << 4) | (1 << 2) | (2))
|
||||
#define WS2812_GRB ((1 << 4) | (0 << 2) | (2))
|
||||
#define RGBLEDS_RGB ((0 << 4) | (1 << 2) | (2))
|
||||
#define RGBLEDS_GRB ((1 << 4) | (0 << 2) | (2))
|
||||
|
||||
// RGB
|
||||
#define WS2812_BYTES_PER_LED 3
|
||||
#define RGBLEDS_BYTES_PER_LED 3
|
||||
|
||||
// Number of LED periods used for trailing reset
|
||||
#if !defined(WS2812_TRAILING_RESET)
|
||||
# define WS2812_TRAILING_RESET 10
|
||||
#if !defined(RGBLEDS_TRAILING_RESET)
|
||||
# define RGBLEDS_TRAILING_RESET 10
|
||||
#endif
|
||||
|
||||
void ws2812_init(const stm32_pulse_timer_t* timer, uint8_t* strip_colors,
|
||||
void rgbleds_init(const stm32_pulse_timer_t* timer, uint8_t* strip_colors,
|
||||
uint8_t strip_len, uint8_t type);
|
||||
void ws2812_update(const stm32_pulse_timer_t* timer);
|
||||
void ws2812_dma_isr(const stm32_pulse_timer_t* timer);
|
||||
void rgbleds_update(const stm32_pulse_timer_t* timer);
|
||||
void rgbleds_dma_isr(const stm32_pulse_timer_t* timer);
|
||||
|
||||
// Returns true if a DMA transfer is currently in progress.
|
||||
bool ws2812_is_busy(const stm32_pulse_timer_t* timer);
|
||||
bool rgbleds_is_busy(const stm32_pulse_timer_t* timer);
|
||||
|
||||
// Buffer-parameterised setter/getter. The caller owns the buffer; ws2812
|
||||
// Buffer-parameterised setter/getter. The caller owns the buffer; rgbleds
|
||||
// applies the strip's RGB byte ordering through the offsets configured at
|
||||
// init time.
|
||||
void ws2812_set_color_in_buf(uint8_t* buf, uint8_t led,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
uint32_t ws2812_get_color_in_buf(const uint8_t* buf, uint8_t led);
|
||||
bool ws2812_get_state_in_buf(const uint8_t* buf, uint8_t led);
|
||||
void rgbleds_set_color_in_buf(uint8_t* buf, uint8_t led,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
uint32_t rgbleds_get_color_in_buf(const uint8_t* buf, uint8_t led);
|
||||
bool rgbleds_get_state_in_buf(const uint8_t* buf, uint8_t led);
|
||||
@@ -291,7 +291,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_softserial_driver.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
)
|
||||
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:board>)
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ add_definitions(
|
||||
-DSTM32H750ZBTx -DSTM32H750xx
|
||||
-DSDRAM -DCCMRAM
|
||||
-DHARDWARE_KEYS -DSOFTWARE_KEYBOARD
|
||||
-DWS2812_MAX_LEDS=24
|
||||
-DRGBLEDS_MAX_LEDS=24
|
||||
)
|
||||
|
||||
set(SDRAM ON)
|
||||
@@ -93,6 +93,7 @@ if(FUNCTION_SWITCHES_WITH_RGB)
|
||||
set(FUNCTION_SWITCHES YES)
|
||||
add_definitions(-DFUNCTION_SWITCHES)
|
||||
add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS)
|
||||
add_definitions(-DRGB_LEDS_900NS)
|
||||
endif()
|
||||
|
||||
if(FUNCTION_SWITCHES)
|
||||
@@ -153,7 +154,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_softserial_driver.cpp
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
)
|
||||
add_dependencies(board board_lib)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "stm32_gpio.h"
|
||||
#include "stm32_i2c_driver.h"
|
||||
#include "stm32_hal.h"
|
||||
#include "stm32_ws2812.h"
|
||||
#include "stm32_rgbleds.h"
|
||||
#include "stm32_spi.h"
|
||||
|
||||
#include "flash_driver.h"
|
||||
|
||||
@@ -242,7 +242,7 @@ endif()
|
||||
|
||||
if(LED_STRIP)
|
||||
target_sources(board PRIVATE ${TARGET_SRC_DIR}/led_driver.cpp)
|
||||
target_sources(board PRIVATE targets/common/arm/stm32/stm32_ws2812.cpp)
|
||||
target_sources(board PRIVATE targets/common/arm/stm32/stm32_rgbleds.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -50,19 +50,19 @@ uint8_t getRGBColorIndex(uint32_t color)
|
||||
}
|
||||
|
||||
// RGB
|
||||
#define WS2812_BYTES_PER_LED 3
|
||||
#define RGBLEDS_BYTES_PER_LED 3
|
||||
|
||||
// Maximum number of supported LEDs
|
||||
#if !defined(WS2812_MAX_LEDS)
|
||||
# define WS2812_MAX_LEDS 48
|
||||
#if !defined(RGBLEDS_MAX_LEDS)
|
||||
# define RGBLEDS_MAX_LEDS 48
|
||||
#endif
|
||||
|
||||
// Pixel values
|
||||
static uint8_t _led_colors[WS2812_BYTES_PER_LED * WS2812_MAX_LEDS];
|
||||
static uint8_t _led_colors[RGBLEDS_BYTES_PER_LED * RGBLEDS_MAX_LEDS];
|
||||
|
||||
void rgbSetLedColor(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
uint8_t* pixel = &_led_colors[led * WS2812_BYTES_PER_LED];
|
||||
uint8_t* pixel = &_led_colors[led * RGBLEDS_BYTES_PER_LED];
|
||||
pixel[0] = g;
|
||||
pixel[1] = r;
|
||||
pixel[2] = b;
|
||||
@@ -70,7 +70,7 @@ void rgbSetLedColor(uint8_t led, uint8_t r, uint8_t g, uint8_t b)
|
||||
|
||||
uint32_t rgbGetLedColor(uint8_t led)
|
||||
{
|
||||
uint8_t* pixel = &_led_colors[led * WS2812_BYTES_PER_LED];
|
||||
uint8_t* pixel = &_led_colors[led * RGBLEDS_BYTES_PER_LED];
|
||||
return (pixel[1] << 16) + (pixel[0] << 8) + pixel[2];
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ add_definitions(
|
||||
-DSTM32H750IBTx -DSTM32H750xx
|
||||
-DSDRAM -DCCMRAM
|
||||
-DHARDWARE_TOUCH -DHARDWARE_KEYS -DSOFTWARE_KEYBOARD
|
||||
-DWS2812_MAX_LEDS=24
|
||||
-DRGBLEDS_MAX_LEDS=24
|
||||
)
|
||||
|
||||
set(SDRAM ON)
|
||||
@@ -157,7 +157,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/vs1053b.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
)
|
||||
add_dependencies(board board_lib)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "stm32_gpio.h"
|
||||
#include "stm32_i2c_driver.h"
|
||||
#include "stm32_hal.h"
|
||||
#include "stm32_ws2812.h"
|
||||
#include "stm32_rgbleds.h"
|
||||
#include "stm32_spi.h"
|
||||
#include "vs1053b.h"
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ if(FUNCTION_SWITCHES_WITH_RGB)
|
||||
set(FUNCTION_SWITCHES YES)
|
||||
add_definitions(-DFUNCTION_SWITCHES)
|
||||
add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS)
|
||||
add_definitions(-DRGB_LEDS_900NS)
|
||||
endif()
|
||||
|
||||
if(FUNCTION_SWITCHES)
|
||||
@@ -155,7 +156,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_softserial_driver.cpp
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
)
|
||||
add_dependencies(board board_lib)
|
||||
|
||||
@@ -26,6 +26,7 @@ set(HARDWARE_EXTERNAL_MODULE YES)
|
||||
set(INTERNAL_MODULE_AFHDS3 NO)
|
||||
set(ROTARY_ENCODER YES)
|
||||
set(FUNCTION_SWITCHES_WITH_RGB YES)
|
||||
add_definitions(-DRGB_LEDS_900NS)
|
||||
|
||||
#option(STICKS_DEAD_ZONE "Enable sticks dead zone" YES)
|
||||
|
||||
@@ -150,7 +151,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_softserial_driver.cpp
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
)
|
||||
add_dependencies(board board_lib)
|
||||
|
||||
@@ -7,7 +7,7 @@ option(INTERNAL_MODULE_PPM "Support for PPM internal module" OFF)
|
||||
option(AUTOUPDATE "Auto update internal chips from SD" OFF)
|
||||
option(BIND_KEY "Enable bind button" OFF)
|
||||
option(BLUETOOTH "FrSky BT module support" OFF)
|
||||
option(RGBLEDS "WS2812 addressable LED support" OFF)
|
||||
option(RGBLEDS "RGBLEDS addressable LED support" OFF)
|
||||
|
||||
set(USE_RTC_CLOCK YES)
|
||||
set(HARDWARE_EXTERNAL_MODULE YES)
|
||||
@@ -287,6 +287,7 @@ elseif(PCB STREQUAL X7)
|
||||
set(ROTARY_ENCODER YES)
|
||||
set(USB_CHARGER YES)
|
||||
add_definitions(-DMANUFACTURER_RADIOMASTER)
|
||||
add_definitions(-DRGB_LEDS_900NS)
|
||||
set(PXX2 ON)
|
||||
set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough")
|
||||
set(FLYSKY_GIMBAL YES)
|
||||
@@ -602,7 +603,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_softserial_driver.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
)
|
||||
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:board>)
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ add_definitions(
|
||||
-DSTM32H750XBTx -DSTM32H750xx
|
||||
-DSDRAM -DCCMRAM
|
||||
-DHARDWARE_TOUCH -DHARDWARE_KEYS -DSOFTWARE_KEYBOARD
|
||||
-DWS2812_MAX_LEDS=26
|
||||
-DRGBLEDS_MAX_LEDS=26
|
||||
)
|
||||
|
||||
set(SDRAM ON)
|
||||
@@ -117,6 +117,7 @@ if(FUNCTION_SWITCHES_WITH_RGB)
|
||||
set(FUNCTION_SWITCHES YES)
|
||||
add_definitions(-DFUNCTION_SWITCHES)
|
||||
add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS)
|
||||
add_definitions(-DRGB_LEDS_900NS)
|
||||
endif()
|
||||
|
||||
if(FUNCTION_SWITCHES)
|
||||
@@ -193,7 +194,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_i2s.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
)
|
||||
add_dependencies(board board_lib)
|
||||
|
||||
@@ -89,7 +89,7 @@ add_definitions(
|
||||
-DSTM32H750XBTx -DSTM32H750xx
|
||||
-DSDRAM -DCCMRAM
|
||||
-DHARDWARE_TOUCH -DHARDWARE_KEYS -DSOFTWARE_KEYBOARD
|
||||
-DWS2812_MAX_LEDS=26
|
||||
-DRGBLEDS_MAX_LEDS=26
|
||||
)
|
||||
|
||||
set(SDRAM ON)
|
||||
@@ -115,6 +115,7 @@ if(FUNCTION_SWITCHES_WITH_RGB)
|
||||
set(FUNCTION_SWITCHES YES)
|
||||
add_definitions(-DFUNCTION_SWITCHES)
|
||||
add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS)
|
||||
add_definitions(-DRGB_LEDS_900NS)
|
||||
endif()
|
||||
|
||||
if(FUNCTION_SWITCHES)
|
||||
@@ -192,7 +193,7 @@ add_library(board OBJECT EXCLUDE_FROM_ALL
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_i2s.cpp
|
||||
targets/common/arm/stm32/stm32_switch_driver.cpp
|
||||
targets/common/arm/stm32/stm32_ws2812.cpp
|
||||
targets/common/arm/stm32/stm32_rgbleds.cpp
|
||||
targets/common/arm/stm32/trainer_driver.cpp
|
||||
)
|
||||
add_dependencies(board board_lib)
|
||||
|
||||
Reference in New Issue
Block a user