Skip to content

Commit 3962766

Browse files
dpgeorgepfalcon
authored andcommitted
esp8266: Add esp.neopixel_write function to bit-bang WS2812 data.
1 parent b62bead commit 3962766

5 files changed

Lines changed: 79 additions & 0 deletions

File tree

esp8266/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ SRC_C = \
5858
lexerstr32.c \
5959
uart.c \
6060
esppwm.c \
61+
espneopixel.c \
6162
modpyb.c \
6263
modpybpin.c \
6364
modpybpwm.c \

esp8266/espneopixel.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Original version from https://github.com/adafruit/Adafruit_NeoPixel
2+
// Modifications by dpgeorge to support auto-CPU-frequency detection
3+
4+
// This is a mash-up of the Due show() code + insights from Michael Miller's
5+
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
6+
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
7+
8+
#include "c_types.h"
9+
#include "eagle_soc.h"
10+
#include "user_interface.h"
11+
#include "espneopixel.h"
12+
13+
#define NEO_KHZ400 (1)
14+
15+
static uint32_t _getCycleCount(void) __attribute__((always_inline));
16+
static inline uint32_t _getCycleCount(void) {
17+
uint32_t ccount;
18+
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
19+
return ccount;
20+
}
21+
22+
void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
23+
24+
uint8_t *p, *end, pix, mask;
25+
uint32_t t, time0, time1, period, c, startTime, pinMask;
26+
27+
pinMask = 1 << pin;
28+
p = pixels;
29+
end = p + numBytes;
30+
pix = *p++;
31+
mask = 0x80;
32+
startTime = 0;
33+
34+
uint32_t fcpu = system_get_cpu_freq() * 1000000;
35+
36+
#ifdef NEO_KHZ400
37+
if(is800KHz) {
38+
#endif
39+
time0 = fcpu / 2500000; // 0.4us
40+
time1 = fcpu / 1250000; // 0.8us
41+
period = fcpu / 800000; // 1.25us per bit
42+
#ifdef NEO_KHZ400
43+
} else { // 400 KHz bitstream
44+
time0 = fcpu / 2000000; // 0.5uS
45+
time1 = fcpu / 833333; // 1.2us
46+
period = fcpu / 400000; // 2.5us per bit
47+
}
48+
#endif
49+
50+
for(t = time0;; t = time0) {
51+
if(pix & mask) t = time1; // Bit high duration
52+
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
53+
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
54+
startTime = c; // Save start time
55+
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
56+
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
57+
if(!(mask >>= 1)) { // Next bit/byte
58+
if(p >= end) break;
59+
pix = *p++;
60+
mask = 0x80;
61+
}
62+
}
63+
while((_getCycleCount() - startTime) < period); // Wait for last bit
64+
}

esp8266/espneopixel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz);

esp8266/modesp.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "espconn.h"
4040
#include "spi_flash.h"
4141
#include "utils.h"
42+
#include "espneopixel.h"
43+
#include "modpyb.h"
4244

4345
#define MODESP_ESPCONN (0)
4446

@@ -573,6 +575,15 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
573575
}
574576
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
575577

578+
STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) {
579+
mp_buffer_info_t bufinfo;
580+
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
581+
esp_neopixel_write(mp_obj_get_pin_obj(pin)->phys_port,
582+
(uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_is_true(is800k));
583+
return mp_const_none;
584+
}
585+
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
586+
576587
STATIC const mp_map_elem_t esp_module_globals_table[] = {
577588
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) },
578589

@@ -586,6 +597,7 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
586597
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
587598
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
588599
#endif
600+
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
589601

590602
#if MODESP_INCLUDE_CONSTANTS
591603
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11B),

esp8266/qstrdefsport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Q(onconnect)
8787
Q(onrecv)
8888
Q(onsent)
8989
Q(ondisconnect)
90+
Q(neopixel_write)
9091
Q(MODE_11B)
9192
Q(MODE_11G)
9293
Q(MODE_11N)

0 commit comments

Comments
 (0)