11#include " StatusLed.hpp"
2+ #include " Target/Target.h"
23#include < Arduino.h>
34
5+ #ifdef ESPFC_LED_WS2812
6+ #include " driver/i2s.h"
7+
8+ // https://docs.espressif.com/projects/esp-idf/en/v4.4.4/esp32/api-reference/peripherals/i2s.html
9+ // https://github.com/vunam/esp32-i2s-ws2812/blob/master/ws2812.c
10+
11+ static constexpr size_t LED_NUMBER = 1 ;
12+ static constexpr size_t PIXEL_SIZE = 12 ; // each colour takes 4 bytes in buffer
13+ static constexpr size_t ZERO_BUFFER = 32 ;
14+ static constexpr size_t SIZE_BUFFER = LED_NUMBER * PIXEL_SIZE + ZERO_BUFFER;
15+ static constexpr uint32_t SAMPLE_RATE = 93750 ;
16+ static constexpr i2s_port_t I2S_NUM = I2S_NUM_0;
17+
18+ typedef struct {
19+ uint8_t g;
20+ uint8_t r;
21+ uint8_t b;
22+ } ws2812_pixel_t ;
23+
24+ static i2s_config_t i2s_config = {
25+ .mode = (i2s_mode_t )(I2S_MODE_MASTER | I2S_MODE_TX),
26+ .sample_rate = SAMPLE_RATE,
27+ .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
28+ .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
29+ .communication_format = I2S_COMM_FORMAT_STAND_MSB,
30+ .intr_alloc_flags = 0 ,
31+ .dma_buf_count = 2 ,
32+ .dma_buf_len = SIZE_BUFFER / 2 ,
33+ .use_apll = false ,
34+ .tx_desc_auto_clear = false ,
35+ .fixed_mclk = 0 ,
36+ .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
37+ .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
38+ };
39+
40+ static i2s_pin_config_t pin_config = {
41+ .bck_io_num = -1 ,
42+ .ws_io_num = -1 ,
43+ .data_out_num = -1 ,
44+ .data_in_num = -1
45+ };
46+
47+ static uint8_t out_buffer[SIZE_BUFFER] = {0 };
48+
49+ static const uint16_t bitpatterns[4 ] = {0x88 , 0x8e , 0xe8 , 0xee };
50+
51+ static void ws2812_init (int8_t pin)
52+ {
53+ pin_config.data_out_num = pin;
54+ i2s_driver_install (I2S_NUM, &i2s_config, 0 , NULL );
55+ i2s_set_pin (I2S_NUM, &pin_config);
56+ i2s_zero_dma_buffer (I2S_NUM);
57+ std::fill_n (out_buffer, SIZE_BUFFER, 0 );
58+ }
59+
60+ static void ws2812_write_pixel (uint8_t * buffer, const ws2812_pixel_t & pixel)
61+ {
62+ *buffer++ = bitpatterns[pixel.g >> 6 & 0x03 ];
63+ *buffer++ = bitpatterns[pixel.g >> 4 & 0x03 ];
64+ *buffer++ = bitpatterns[pixel.g >> 2 & 0x03 ];
65+ *buffer++ = bitpatterns[pixel.g >> 0 & 0x03 ];
66+
67+ *buffer++ = bitpatterns[pixel.r >> 6 & 0x03 ];
68+ *buffer++ = bitpatterns[pixel.r >> 4 & 0x03 ];
69+ *buffer++ = bitpatterns[pixel.r >> 2 & 0x03 ];
70+ *buffer++ = bitpatterns[pixel.r >> 0 & 0x03 ];
71+
72+ *buffer++ = bitpatterns[pixel.b >> 6 & 0x03 ];
73+ *buffer++ = bitpatterns[pixel.b >> 4 & 0x03 ];
74+ *buffer++ = bitpatterns[pixel.b >> 2 & 0x03 ];
75+ *buffer++ = bitpatterns[pixel.b >> 0 & 0x03 ];
76+ }
77+
78+ static void ws2812_update (const ws2812_pixel_t * pixels)
79+ {
80+ size_t bytes_written = 0 ;
81+ for (size_t i = 0 ; i < LED_NUMBER; i++)
82+ {
83+ size_t loc = i * PIXEL_SIZE;
84+ ws2812_write_pixel (out_buffer + loc, pixels[i]);
85+ }
86+ i2s_zero_dma_buffer (I2S_NUM);
87+ i2s_write (I2S_NUM, out_buffer, SIZE_BUFFER, &bytes_written, portMAX_DELAY);
88+ }
89+
90+ static const ws2812_pixel_t PIXEL_ON[] = {{0x40 , 0x40 , 0x80 }};
91+ static const ws2812_pixel_t PIXEL_OFF[] = {{0 , 0 , 0 }};
92+
93+ #endif
94+
495namespace Espfc ::Connect
596{
697
@@ -11,12 +102,20 @@ static int LED_ON_PATTERN[] = {100, 0};
11102
12103StatusLed::StatusLed () : _pin(-1 ), _invert(0 ), _status(LED_OFF), _next(0 ), _state(LOW), _step(0 ), _pattern(LED_OFF_PATTERN) {}
13104
14- void StatusLed::begin (int8_t pin, uint8_t invert)
105+ void StatusLed::begin (int8_t pin, uint8_t type, uint8_t invert)
15106{
16107 if (pin == -1 ) return ;
108+
17109 _pin = pin;
110+ _type = type;
18111 _invert = invert;
112+
113+ #ifdef ESPFC_LED_WS2812
114+ if (_type == LED_STRIP) ws2812_init (_pin);
115+ if (_type == LED_SIMPLE) pinMode (_pin, OUTPUT);
116+ #else
19117 pinMode (_pin, OUTPUT);
118+ #endif
20119 setStatus (LED_ON, true );
21120}
22121
@@ -74,7 +173,12 @@ void StatusLed::update()
74173
75174void StatusLed::_write (uint8_t val)
76175{
176+ #ifdef ESPFC_LED_WS2812
177+ if (_type == LED_STRIP) ws2812_update (val ? PIXEL_ON : PIXEL_OFF);
178+ if (_type == LED_SIMPLE) digitalWrite (_pin, val ^ _invert);
179+ #else
77180 digitalWrite (_pin, val ^ _invert);
181+ #endif
78182}
79183
80184}
0 commit comments