5
5
#ifdef ESPFC_LED_WS2812
6
6
#include " driver/i2s.h"
7
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
+
8
11
static constexpr size_t LED_NUMBER = 1 ;
9
- static constexpr size_t PIXEL_SIZE = 12 ; // each colour takes 4 bytes
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;
10
15
static constexpr uint32_t SAMPLE_RATE = 93750 ;
11
- static constexpr size_t ZERO_BUFFER = 48 ;
12
16
static constexpr i2s_port_t I2S_NUM = I2S_NUM_0;
13
17
14
18
typedef struct {
15
- uint8_t green ;
16
- uint8_t red ;
17
- uint8_t blue ;
19
+ uint8_t g ;
20
+ uint8_t r ;
21
+ uint8_t b ;
18
22
} ws2812_pixel_t ;
19
23
20
24
static i2s_config_t i2s_config = {
@@ -24,8 +28,8 @@ static i2s_config_t i2s_config = {
24
28
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
25
29
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
26
30
.intr_alloc_flags = 0 ,
27
- .dma_buf_count = 4 ,
28
- .dma_buf_len = LED_NUMBER * PIXEL_SIZE ,
31
+ .dma_buf_count = 2 ,
32
+ .dma_buf_len = SIZE_BUFFER / 2 ,
29
33
.use_apll = false ,
30
34
.tx_desc_auto_clear = false ,
31
35
.fixed_mclk = 0 ,
@@ -40,9 +44,7 @@ static i2s_pin_config_t pin_config = {
40
44
.data_in_num = -1
41
45
};
42
46
43
- static uint8_t out_buffer[LED_NUMBER * PIXEL_SIZE] = {0 };
44
- static uint8_t off_buffer[ZERO_BUFFER] = {0 };
45
- static uint16_t size_buffer = LED_NUMBER * PIXEL_SIZE;
47
+ static uint8_t out_buffer[SIZE_BUFFER] = {0 };
46
48
47
49
static const uint16_t bitpatterns[4 ] = {0x88 , 0x8e , 0xe8 , 0xee };
48
50
@@ -51,44 +53,45 @@ static void ws2812_init(int8_t pin)
51
53
pin_config.data_out_num = pin;
52
54
i2s_driver_install (I2S_NUM, &i2s_config, 0 , NULL );
53
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 ];
54
76
}
55
77
56
78
static void ws2812_update (const ws2812_pixel_t * pixels)
57
79
{
58
80
size_t bytes_written = 0 ;
59
-
60
- for (uint16_t i = 0 ; i < LED_NUMBER; i++) {
61
- int loc = i * PIXEL_SIZE;
62
-
63
- out_buffer[loc] = bitpatterns[pixels[i].green >> 6 & 0x03 ];
64
- out_buffer[loc + 1 ] = bitpatterns[pixels[i].green >> 4 & 0x03 ];
65
- out_buffer[loc + 2 ] = bitpatterns[pixels[i].green >> 2 & 0x03 ];
66
- out_buffer[loc + 3 ] = bitpatterns[pixels[i].green & 0x03 ];
67
-
68
- out_buffer[loc + 4 ] = bitpatterns[pixels[i].red >> 6 & 0x03 ];
69
- out_buffer[loc + 5 ] = bitpatterns[pixels[i].red >> 4 & 0x03 ];
70
- out_buffer[loc + 6 ] = bitpatterns[pixels[i].red >> 2 & 0x03 ];
71
- out_buffer[loc + 7 ] = bitpatterns[pixels[i].red & 0x03 ];
72
-
73
- out_buffer[loc + 8 ] = bitpatterns[pixels[i].blue >> 6 & 0x03 ];
74
- out_buffer[loc + 9 ] = bitpatterns[pixels[i].blue >> 4 & 0x03 ];
75
- out_buffer[loc + 10 ] = bitpatterns[pixels[i].blue >> 2 & 0x03 ];
76
- out_buffer[loc + 11 ] = bitpatterns[pixels[i].blue & 0x03 ];
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]);
77
85
}
78
-
79
- i2s_write (I2S_NUM, out_buffer, size_buffer, &bytes_written, portMAX_DELAY);
80
- i2s_write (I2S_NUM, off_buffer, ZERO_BUFFER, &bytes_written, portMAX_DELAY);
81
- delay (1 ); // was 10
82
86
i2s_zero_dma_buffer (I2S_NUM);
87
+ i2s_write (I2S_NUM, out_buffer, SIZE_BUFFER, &bytes_written, portMAX_DELAY);
83
88
}
84
89
85
- static const ws2812_pixel_t PIXEL_ON[] = {{127 , 0 , 0 }};
90
+ static const ws2812_pixel_t PIXEL_ON[] = {{0x40 , 0x40 , 0x80 }};
86
91
static const ws2812_pixel_t PIXEL_OFF[] = {{0 , 0 , 0 }};
87
92
88
93
#endif
89
94
90
- // https://github.com/vunam/esp32-i2s-ws2812/blob/master/ws2812.c
91
-
92
95
namespace Espfc ::Connect
93
96
{
94
97
@@ -99,14 +102,17 @@ static int LED_ON_PATTERN[] = {100, 0};
99
102
100
103
StatusLed::StatusLed () : _pin(-1 ), _invert(0 ), _status(LED_OFF), _next(0 ), _state(LOW), _step(0 ), _pattern(LED_OFF_PATTERN) {}
101
104
102
- void StatusLed::begin (int8_t pin, uint8_t invert)
105
+ void StatusLed::begin (int8_t pin, uint8_t type, uint8_t invert)
103
106
{
104
107
if (pin == -1 ) return ;
108
+
105
109
_pin = pin;
110
+ _type = type;
106
111
_invert = invert;
107
112
108
113
#ifdef ESPFC_LED_WS2812
109
- ws2812_init (_pin);
114
+ if (_type == LED_STRIP) ws2812_init (_pin);
115
+ if (_type == LED_SIMPLE) pinMode (_pin, OUTPUT);
110
116
#else
111
117
pinMode (_pin, OUTPUT);
112
118
#endif
@@ -168,7 +174,8 @@ void StatusLed::update()
168
174
void StatusLed::_write (uint8_t val)
169
175
{
170
176
#ifdef ESPFC_LED_WS2812
171
- ws2812_update (val ? PIXEL_ON : PIXEL_OFF);
177
+ if (_type == LED_STRIP) ws2812_update (val ? PIXEL_ON : PIXEL_OFF);
178
+ if (_type == LED_SIMPLE) digitalWrite (_pin, val ^ _invert);
172
179
#else
173
180
digitalWrite (_pin, val ^ _invert);
174
181
#endif
0 commit comments