未验证 提交 109f500b 编写于 作者: N Nathaniel Wesley Filardo 提交者: GitHub

More LED fixes (#3368)

* apa102: remove dead code

We can't store strings of hundreds of thousands of characters in RAM, so
this can't possibly have fired, historically.  Pixbufs are still RAM
objects, so that's still out.  With LFS, it would take a pathological
example to hit the required 400KB TSTRING.

* Add IRQ management functions

* ws2812: fill UART FIFOs with IRQs off

Refactor code to make the use of two fill loops less gross.
上级 4023df7e
......@@ -102,10 +102,6 @@ static int apa102_write(lua_State* L) {
return luaL_argerror(L, 3, "String or pixbuf expected");
}
if (nbr_frames > 100000) {
return luaL_error(L, "The supplied buffer is too long, and might cause the callback watchdog to bark.");
}
// Initialize the output pins
platform_gpio_mode(data_pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT);
GPIO_OUTPUT_SET(alt_data_pin, PLATFORM_GPIO_HIGH); // Set pin high
......
......@@ -8,6 +8,7 @@
#include "user_interface.h"
#include "driver/uart.h"
#include "osapi.h"
#include "cpu_esp8266_irq.h"
#include "pixbuf.h"
......@@ -51,12 +52,18 @@ static int ws2812_init(lua_State* L) {
return 0;
}
// Stream data using UART1 routed to GPIO2
// ws2812.init() should be called first
//
// NODE_DEBUG should not be activated because it also uses UART1
void ICACHE_RAM_ATTR ws2812_write_data(const uint8_t *pixels, uint32_t length, const uint8_t *pixels2, uint32_t length2) {
static bool
ws2812_can_write(int uart)
{
// If something to send for first buffer and enough room
// in FIFO buffer (we wants to write 4 bytes, so less than
// 124 in the buffer)
return (((READ_PERI_REG(UART_STATUS(uart)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) <= 124);
}
static void
ws2812_write_byte(int uart, uint8_t value)
{
// Data are sent LSB first, with a start bit at 0, an end bit at 1 and all inverted
// 0b00110111 => 110111 => [0]111011[1] => 10001000 => 00
// 0b00000111 => 000111 => [0]111000[1] => 10001110 => 01
......@@ -66,31 +73,37 @@ void ICACHE_RAM_ATTR ws2812_write_data(const uint8_t *pixels, uint32_t length, c
// But declared in ".data" section to avoid read penalty from FLASH
static const __attribute__((section(".data._uartData"))) uint8_t _uartData[4] = { 0b00110111, 0b00000111, 0b00110100, 0b00000100 };
WRITE_PERI_REG(UART_FIFO(uart), _uartData[(value >> 6) & 3]);
WRITE_PERI_REG(UART_FIFO(uart), _uartData[(value >> 4) & 3]);
WRITE_PERI_REG(UART_FIFO(uart), _uartData[(value >> 2) & 3]);
WRITE_PERI_REG(UART_FIFO(uart), _uartData[(value >> 0) & 3]);
}
// Stream data using UART1 routed to GPIO2
// ws2812.init() should be called first
//
// NODE_DEBUG should not be activated because it also uses UART1
void ICACHE_RAM_ATTR ws2812_write_data(const uint8_t *pixels, uint32_t length, const uint8_t *pixels2, uint32_t length2) {
const uint8_t *end = pixels + length;
const uint8_t *end2 = pixels2 + length2;
/* Fill the UART fifos with IRQs disabled */
uint32_t irq_state = esp8266_defer_irqs();
while ((pixels < end) && ws2812_can_write(1)) {
ws2812_write_byte(1, *pixels++);
}
while ((pixels2 < end2) && ws2812_can_write(0)) {
ws2812_write_byte(0, *pixels2++);
}
esp8266_restore_irqs(irq_state);
do {
// If something to send for first buffer and enough room
// in FIFO buffer (we wants to write 4 bytes, so less than
// 124 in the buffer)
if (pixels < end && (((READ_PERI_REG(UART_STATUS(1)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) <= 124)) {
uint8_t value = *pixels++;
// Fill the buffer
WRITE_PERI_REG(UART_FIFO(1), _uartData[(value >> 6) & 3]);
WRITE_PERI_REG(UART_FIFO(1), _uartData[(value >> 4) & 3]);
WRITE_PERI_REG(UART_FIFO(1), _uartData[(value >> 2) & 3]);
WRITE_PERI_REG(UART_FIFO(1), _uartData[(value >> 0) & 3]);
if (pixels < end && ws2812_can_write(1)) {
ws2812_write_byte(1, *pixels++);
}
// Same for the second buffer
if (pixels2 < end2 && (((READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) <= 124)) {
uint8_t value = *pixels2++;
// Fill the buffer
WRITE_PERI_REG(UART_FIFO(0), _uartData[(value >> 6) & 3]);
WRITE_PERI_REG(UART_FIFO(0), _uartData[(value >> 4) & 3]);
WRITE_PERI_REG(UART_FIFO(0), _uartData[(value >> 2) & 3]);
WRITE_PERI_REG(UART_FIFO(0), _uartData[(value >> 0) & 3]);
if (pixels2 < end2 && ws2812_can_write(0)) {
ws2812_write_byte(0, *pixels2++);
}
} while(pixels < end || pixels2 < end2); // Until there is still something to send
}
......
#pragma once
static inline uint32_t
esp8266_defer_irqs(void)
{
uint32_t state;
__asm__ __volatile__ ("rsil %0, 15" : "=a"(state) : : "memory");
return state;
}
static inline void
esp8266_restore_irqs(uint32_t state)
{
__asm__ __volatile__ ("wsr %0, ps" : : "a"(state) : "memory");
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册