Lepsi casovani, funkcni pro PL9823 pomoci definice WSLED_PL9823
This commit is contained in:
parent
b607188a15
commit
6800956d92
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name": "WSLed",
|
"name": "WSLed",
|
||||||
"version": "0.0.2"
|
"version": "0.0.3"
|
||||||
}
|
}
|
@ -1,102 +0,0 @@
|
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
NeoPixel library helper functions for Esp8266 and Esp32.
|
|
||||||
|
|
||||||
Written by Michael C. Miller.
|
|
||||||
|
|
||||||
I invest time and resources providing this open source code,
|
|
||||||
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
This file is part of the Makuna/NeoPixelBus library.
|
|
||||||
|
|
||||||
NeoPixelBus is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
NeoPixelBus is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with NeoPixel. If not, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <eagle_soc.h>
|
|
||||||
#if (ARDUINO_ESP8266_MAJOR < 3)
|
|
||||||
# define INRAM ICACHE_RAM_ATTR
|
|
||||||
#else
|
|
||||||
# define INRAM IRAM_ATTR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ESP32 doesn't define ICACHE_RAM_ATTR
|
|
||||||
#ifndef INRAM
|
|
||||||
# define INRAM IRAM_ATTR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline uint32_t _getCycleCount()
|
|
||||||
{
|
|
||||||
uint32_t ccount;
|
|
||||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
|
||||||
return ccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(NEOPIXEL_OLD_TIMING)
|
|
||||||
# define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us
|
|
||||||
# define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
|
|
||||||
# define CYCLES_800 (F_CPU / 800000) // 1.25us per bit
|
|
||||||
#else
|
|
||||||
# define CYCLES_800_T0H (F_CPU / 2600000) // 0.4us
|
|
||||||
# define CYCLES_800_T1H (F_CPU / 1350000) // 0.8us
|
|
||||||
# define CYCLES_800 (F_CPU / 900000) // 1.25us per bit
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void INRAM send_pixels_800(uint8_t* pixels, size_t count, uint8_t pin)
|
|
||||||
{
|
|
||||||
const uint32_t pinRegister = _BV(pin);
|
|
||||||
uint8_t mask;
|
|
||||||
uint8_t subpix;
|
|
||||||
uint32_t cyclesStart;
|
|
||||||
uint8_t *end = pixels + (3 * count);
|
|
||||||
|
|
||||||
// trigger emediately
|
|
||||||
cyclesStart = _getCycleCount() - CYCLES_800;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
subpix = *pixels++;
|
|
||||||
for (mask = 0x80; mask != 0; mask >>= 1)
|
|
||||||
{
|
|
||||||
// do the checks here while we are waiting on time to pass
|
|
||||||
uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_800_T1H : CYCLES_800_T0H;
|
|
||||||
uint32_t cyclesNext = cyclesStart;
|
|
||||||
|
|
||||||
// after we have done as much work as needed for this next bit
|
|
||||||
// now wait for the HIGH
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// cache and use this count so we don't incur another
|
|
||||||
// instruction before we turn the bit high
|
|
||||||
cyclesStart = _getCycleCount();
|
|
||||||
} while ((cyclesStart - cyclesNext) < CYCLES_800);
|
|
||||||
|
|
||||||
// set high
|
|
||||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
|
|
||||||
|
|
||||||
// wait for the LOW
|
|
||||||
do
|
|
||||||
{
|
|
||||||
cyclesNext = _getCycleCount();
|
|
||||||
} while ((cyclesNext - cyclesStart) < cyclesBit);
|
|
||||||
|
|
||||||
// set low
|
|
||||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
|
|
||||||
}
|
|
||||||
} while (pixels < end);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
252
src/WSLed.cpp
252
src/WSLed.cpp
@ -1,28 +1,22 @@
|
|||||||
// Ovladani signalizacni chytre LED diody
|
// Ovladani signalizacni chytre LED diody
|
||||||
#include "WSLed.hpp"
|
#include "WSLed.hpp"
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
//# include "esp_task.h"
|
// # include "esp_task.h"
|
||||||
// https://github.com/JSchaenzle/ESP32-NeoPixel-WS2812-RMT/blob/master/ws2812_control.c
|
// https://github.com/JSchaenzle/ESP32-NeoPixel-WS2812-RMT/blob/master/ws2812_control.c
|
||||||
# include <set>
|
#include <set>
|
||||||
# ifndef LED_RMT_TX_CHANNEL
|
#ifndef LED_RMT_TX_CHANNEL
|
||||||
# define LED_RMT_TX_CHANNEL RMT_CHANNEL_0
|
#define LED_RMT_TX_CHANNEL RMT_CHANNEL_0
|
||||||
# endif
|
#endif
|
||||||
// These values are determined by measuring pulse timing with logic analyzer and adjusting to match datasheet.
|
// These values are determined by measuring pulse timing with logic analyzer and adjusting to match datasheet.
|
||||||
# define T0H 16 // 0 bit high time
|
#define T0H 16 // 0 bit high time
|
||||||
# define T1H 32 // 1 bit high time
|
#define T1H 32 // 1 bit high time
|
||||||
# define T0L 34 // 0 bit low time
|
#define T0L 34 // 0 bit low time
|
||||||
# define T1L 18 // 1 bit low time
|
#define T1L 18 // 1 bit low time
|
||||||
# define INRAM IRAM_ATTR
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
// due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are
|
// due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are
|
||||||
// moved into a C file so the attribute will be applied correctly
|
// moved into a C file so the attribute will be applied correctly
|
||||||
#if (ARDUINO_ESP8266_MAJOR < 3)
|
extern "C" IRAM_ATTR void espShow(uint8_t pin, uint8_t * pixels, uint32_t numBytes, boolean is800KHz);
|
||||||
# define INRAM ICACHE_RAM_ATTR
|
|
||||||
#else
|
|
||||||
# define INRAM IRAM_ATTR
|
|
||||||
#endif
|
|
||||||
extern "C" void INRAM send_pixels_800(uint8_t* pixel, size_t count, uint8_t pin);
|
|
||||||
#endif
|
#endif
|
||||||
// TODO: Proverit ESP32 s https://github.com/adafruit/Adafruit_NeoPixel/blob/master/esp.c
|
// TODO: Proverit ESP32 s https://github.com/adafruit/Adafruit_NeoPixel/blob/master/esp.c
|
||||||
// ... a s https://github.com/Freenove/Freenove_WS2812_Lib_for_ESP32
|
// ... a s https://github.com/Freenove/Freenove_WS2812_Lib_for_ESP32
|
||||||
@ -30,14 +24,13 @@ extern "C" void INRAM send_pixels_800(uint8_t* pixel, size_t count, uint8_t pin)
|
|||||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
static const uint16_t LB[] PROGMEM = {
|
static const uint16_t LB[] PROGMEM = {
|
||||||
0x201 , 0x202 , 0x103 , 0x104 , 0x105 , 0x106 , 0x107 , 0x109 , 0x10a , 0x10c , 0x10e , 0x110 , 0x112 , 0x114 , 0x116 , 0x119 , 0x11c , 0x11e , 0x122 , 0x125 , 0x128 , 0x12c , 0x130 , 0x134,
|
0x201, 0x202, 0x103, 0x104, 0x105, 0x106, 0x107, 0x109, 0x10a, 0x10c, 0x10e, 0x110, 0x112, 0x114, 0x116, 0x119, 0x11c, 0x11e, 0x122, 0x125, 0x128, 0x12c, 0x130, 0x134,
|
||||||
0x139 , 0x13d , 0x142 , 0x147 , 0x14d , 0x152 , 0x158 , 0x15e , 0x165 , 0x16b , 0x172 , 0x179 , 0x180 , 0x187 , 0x18e , 0x196 , 0x19d , 0x1a5 , 0x1ac , 0x1b3 , 0x1bb , 0x1c2 , 0x1c9 , 0x1cf,
|
0x139, 0x13d, 0x142, 0x147, 0x14d, 0x152, 0x158, 0x15e, 0x165, 0x16b, 0x172, 0x179, 0x180, 0x187, 0x18e, 0x196, 0x19d, 0x1a5, 0x1ac, 0x1b3, 0x1bb, 0x1c2, 0x1c9, 0x1cf,
|
||||||
0x1d6 , 0x1dc , 0x1e2 , 0x1e7 , 0x1ec , 0x1f0 , 0x1f4 , 0x1f7 , 0x1fa , 0x1fc , 0x1fd , 0x3fe , 0x1fd , 0x1fb , 0x1f8 , 0x1f5 , 0x1f2 , 0x1ed , 0x1e9 , 0x1e4 , 0x1de , 0x1d8 , 0x1d2 , 0x1cb,
|
0x1d6, 0x1dc, 0x1e2, 0x1e7, 0x1ec, 0x1f0, 0x1f4, 0x1f7, 0x1fa, 0x1fc, 0x1fd, 0x3fe, 0x1fd, 0x1fb, 0x1f8, 0x1f5, 0x1f2, 0x1ed, 0x1e9, 0x1e4, 0x1de, 0x1d8, 0x1d2, 0x1cb,
|
||||||
0x1c4 , 0x1bd , 0x1b6 , 0x1af , 0x1a7 , 0x1a0 , 0x198 , 0x191 , 0x18a , 0x182 , 0x17b , 0x174 , 0x16d , 0x167 , 0x161 , 0x15a , 0x154 , 0x14f , 0x149 , 0x144 , 0x13f , 0x13a , 0x136 , 0x131,
|
0x1c4, 0x1bd, 0x1b6, 0x1af, 0x1a7, 0x1a0, 0x198, 0x191, 0x18a, 0x182, 0x17b, 0x174, 0x16d, 0x167, 0x161, 0x15a, 0x154, 0x14f, 0x149, 0x144, 0x13f, 0x13a, 0x136, 0x131,
|
||||||
0x12d , 0x12a , 0x126 , 0x123 , 0x11f , 0x11c , 0x11a , 0x117 , 0x115 , 0x112 , 0x110 , 0x10e , 0x10c , 0x10b , 0x109 , 0x108 , 0x107 , 0x105 , 0x104 , 0x203 , 0x102 , 0x201 , 0x2900
|
0x12d, 0x12a, 0x126, 0x123, 0x11f, 0x11c, 0x11a, 0x117, 0x115, 0x112, 0x110, 0x10e, 0x10c, 0x10b, 0x109, 0x108, 0x107, 0x105, 0x104, 0x203, 0x102, 0x201, 0x2900};
|
||||||
};
|
|
||||||
|
|
||||||
static void ledTrampoline(wsLED *ptr)
|
static void ledTrampoline(wsLED * ptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
ptr->rtLed();
|
ptr->rtLed();
|
||||||
@ -46,7 +39,7 @@ static void ledTrampoline(wsLED *ptr)
|
|||||||
inline bool wsLED::canShow() const
|
inline bool wsLED::canShow() const
|
||||||
{
|
{
|
||||||
|
|
||||||
return (micros() - _endtime) >= 70L;
|
return (micros() - mEndTime) >= 70L;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::show()
|
void wsLED::show()
|
||||||
@ -54,66 +47,66 @@ void wsLED::show()
|
|||||||
uint8_t color[3];
|
uint8_t color[3];
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
// https://github.com/FastLED/FastLED/wiki/FastLED-Color-Correction
|
// https://github.com/FastLED/FastLED/wiki/FastLED-Color-Correction
|
||||||
uint16_t c = (uint16_t)_color[i] * (1 + (uint16_t)_scale);
|
uint16_t c = (uint16_t) mColor[i] * (1 + (uint16_t) mScale);
|
||||||
color[i] = (uint8_t)(c >> 8);
|
color[i] = (uint8_t) (c >> 8);
|
||||||
}
|
}
|
||||||
while (!canShow())
|
while (!canShow())
|
||||||
__asm__ volatile ("nop");
|
__asm__ volatile("nop");
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
uint32_t bits_to_send = ((uint32_t)color[0] << 16) | ((uint32_t)color[1] << 8) | (uint32_t)color[2];
|
uint32_t bits_to_send = ((uint32_t) color[0] << 16) | ((uint32_t) color[1] << 8) | (uint32_t) color[2];
|
||||||
uint32_t mask = 1 << (BITS_PER_LED_CMD - 1);
|
uint32_t mask = 1 << (BITS_PER_LED_CMD - 1);
|
||||||
for (uint32_t bit = 0; bit < BITS_PER_LED_CMD; bit++) {
|
for (uint32_t bit = 0; bit < BITS_PER_LED_CMD; bit++) {
|
||||||
uint32_t bit_is_set = bits_to_send & mask;
|
uint32_t bit_is_set = bits_to_send & mask;
|
||||||
|
|
||||||
led_data_buffer[bit] = bit_is_set ? (rmt_item32_t) {{{T1H, 1, T1L, 0}}} : (rmt_item32_t) {{{T0H, 1, T0L, 0}}};
|
led_data_buffer[bit] = bit_is_set ? (rmt_item32_t){{{T1H, 1, T1L, 0}}} : (rmt_item32_t){{{T0H, 1, T0L, 0}}};
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(rmt_write_items(LED_RMT_TX_CHANNEL, led_data_buffer, LED_BUFFER_ITEMS, false));
|
ESP_ERROR_CHECK(rmt_write_items(LED_RMT_TX_CHANNEL, led_data_buffer, LED_BUFFER_ITEMS, false));
|
||||||
_endtime = micros() + 100; // TODO: unfortunately this time is not valid for ESP32 using RMT peripheral
|
_endtime = micros() + 100; // TODO: unfortunately this time is not valid for ESP32 using RMT peripheral
|
||||||
#else
|
#else
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
send_pixels_800(color, 1, _pin);
|
#if defined(WSLED_PL9823)
|
||||||
|
espShow(_pin, color, 1 * 3, false);
|
||||||
|
#else
|
||||||
|
espShow(mPin, color, 1 * 3, true);
|
||||||
|
#endif
|
||||||
interrupts();
|
interrupts();
|
||||||
_endtime = micros();
|
mEndTime = micros();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
wsLED::wsLED(int pin, int order)
|
wsLED::wsLED(int pin, int order)
|
||||||
: _pin(pin)
|
: mPin(pin), mOrder(order)
|
||||||
, _order(order)
|
{
|
||||||
, _scale(0xff)
|
}
|
||||||
, _ledState(LED_STOP)
|
|
||||||
{}
|
|
||||||
|
|
||||||
wsLED::wsLED()
|
wsLED::wsLED()
|
||||||
: _pin(NOT_A_PIN)
|
: mPin(NOT_A_PIN), mOrder(RGB)
|
||||||
, _order(RGB)
|
{
|
||||||
, _scale(0xff)
|
}
|
||||||
, _ledState(LED_STOP)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void wsLED::begin(int pin)
|
void wsLED::begin(int pin)
|
||||||
{
|
{
|
||||||
|
|
||||||
_pin = pin;
|
mPin = pin;
|
||||||
begin();
|
begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::begin()
|
void wsLED::begin()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (NOT_A_PIN != _pin) {
|
if (NOT_A_PIN != mPin) {
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
pinMode(_pin, OUTPUT);
|
pinMode(mPin, OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
// TODO: mozna nejak zkusit najit volny RMT kanal?
|
// TODO: mozna nejak zkusit najit volny RMT kanal?
|
||||||
rmt_config_t config;
|
rmt_config_t config;
|
||||||
|
|
||||||
config.rmt_mode = RMT_MODE_TX;
|
config.rmt_mode = RMT_MODE_TX;
|
||||||
config.channel = LED_RMT_TX_CHANNEL;
|
config.channel = LED_RMT_TX_CHANNEL;
|
||||||
config.gpio_num = (gpio_num_t)_pin;
|
config.gpio_num = (gpio_num_t) _pin;
|
||||||
config.mem_block_num = 3;
|
config.mem_block_num = 3;
|
||||||
config.tx_config.loop_en = false;
|
config.tx_config.loop_en = false;
|
||||||
config.tx_config.carrier_en = false;
|
config.tx_config.carrier_en = false;
|
||||||
@ -124,91 +117,90 @@ void wsLED::begin()
|
|||||||
ESP_ERROR_CHECK(rmt_config(&config));
|
ESP_ERROR_CHECK(rmt_config(&config));
|
||||||
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
|
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
|
||||||
#endif
|
#endif
|
||||||
_color[0] = _color[1] = _color[2] = 0;
|
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::setColor(LEDRGB color)
|
void wsLED::setColor(const LEDRGB & color)
|
||||||
{
|
{
|
||||||
|
|
||||||
_color[(_order >> 6) & 7] = color.r;
|
mColor[(mOrder >> 6) & 7] = color.r;
|
||||||
_color[(_order >> 3) & 7] = color.g;
|
mColor[(mOrder >> 3) & 7] = color.g;
|
||||||
_color[_order & 7] = color.b;
|
mColor[mOrder & 7] = color.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::rtLed()
|
void wsLED::rtLed()
|
||||||
{
|
{
|
||||||
uint32_t timing;
|
uint32_t timing;
|
||||||
|
|
||||||
_handler.detach();
|
mTimer.detach();
|
||||||
switch (_ledState) {
|
switch (mLedState) {
|
||||||
case LED_BLINK:
|
case LED_BLINK:
|
||||||
if (_subState) {
|
if (mSubState) {
|
||||||
setColor(_color2);
|
setColor(mColor2);
|
||||||
} else {
|
} else {
|
||||||
setColor(_color1);
|
setColor(mColor1);
|
||||||
|
}
|
||||||
|
mSubState = !mSubState;
|
||||||
|
timing = mBlinkSpeed;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LED_BREATH: {
|
||||||
|
++mSubState;
|
||||||
|
mSubState %= countof(LB);
|
||||||
|
uint16_t val = pgm_read_word(&LB[mSubState]);
|
||||||
|
mScale = (uint8_t) val;
|
||||||
|
val >>= 8;
|
||||||
|
timing = 30ul * val;
|
||||||
|
if (timing < 30) {
|
||||||
|
timing = 30;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_subState = !_subState;
|
|
||||||
timing = _blinkSpeed;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LED_BREATH: {
|
case LED_PULSE: {
|
||||||
++_subState;
|
mLedState = mSavedState;
|
||||||
_subState %= countof(LB);
|
mSubState = 0;
|
||||||
uint16_t val = pgm_read_word(&LB[_subState]);
|
setColor(mColor1);
|
||||||
_scale = (uint8_t)val;
|
timing = 5;
|
||||||
val >>= 8;
|
break;
|
||||||
timing = 30ul * val;
|
|
||||||
if (timing < 30) {
|
|
||||||
timing = 30;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LED_PULSE: {
|
case LED_PULSE_START:
|
||||||
_ledState = _savedState;
|
setColor(mPulseColor);
|
||||||
_subState = 0;
|
mLedState = LED_PULSE;
|
||||||
setColor(_color1);
|
timing = mPulseDuration;
|
||||||
timing = 5;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LED_PULSE_START:
|
default:
|
||||||
setColor(_pulseColor);
|
timing = 5000;
|
||||||
_ledState = LED_PULSE;
|
break;
|
||||||
timing = _pulseDuration;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
timing = 5000;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
show();
|
show();
|
||||||
_handler.attach_ms(timing, ledTrampoline, this);
|
mTimer.attach_ms(timing, ledTrampoline, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::setColors(LEDRGB color1, LEDRGB color2)
|
void wsLED::setColors(const LEDRGB & color1, const LEDRGB & color2)
|
||||||
{
|
{
|
||||||
|
|
||||||
_color1 = color1;
|
mColor1 = color1;
|
||||||
_color2 = color2;
|
mColor2 = color2;
|
||||||
if (LED_BREATH == _ledState) {
|
if (LED_BREATH == mLedState) {
|
||||||
setColor(_color1);
|
setColor(mColor1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::blink(uint32_t speed)
|
void wsLED::blink(uint32_t speed)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (NOT_A_PIN != _pin) {
|
if (NOT_A_PIN != mPin) {
|
||||||
if (LED_BLINK != _ledState) {
|
if (LED_BLINK != mLedState) {
|
||||||
_handler.detach();
|
mTimer.detach();
|
||||||
_ledState = LED_BLINK;
|
mLedState = LED_BLINK;
|
||||||
_scale = 0xff;
|
mScale = 0xff;
|
||||||
_subState = 1;
|
mSubState = 1;
|
||||||
_blinkSpeed = speed;
|
mBlinkSpeed = speed;
|
||||||
_handler.attach_ms(5, ledTrampoline, this);
|
mTimer.attach_ms(5, ledTrampoline, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,13 +208,13 @@ void wsLED::blink(uint32_t speed)
|
|||||||
void wsLED::breath()
|
void wsLED::breath()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (NOT_A_PIN != _pin) {
|
if (NOT_A_PIN != mPin) {
|
||||||
if (LED_BREATH != _ledState) {
|
if (LED_BREATH != mLedState) {
|
||||||
_handler.detach();
|
mTimer.detach();
|
||||||
_ledState = LED_BREATH;
|
mLedState = LED_BREATH;
|
||||||
_subState = 0;
|
mSubState = 0;
|
||||||
setColor(_color1);
|
setColor(mColor1);
|
||||||
_handler.attach_ms(5, ledTrampoline, this);
|
mTimer.attach_ms(5, ledTrampoline, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,40 +222,40 @@ void wsLED::breath()
|
|||||||
void wsLED::setOrder(int neworder)
|
void wsLED::setOrder(int neworder)
|
||||||
{
|
{
|
||||||
|
|
||||||
_order = neworder;
|
mOrder = neworder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::pulse(LEDRGB color, uint32_t duration)
|
void wsLED::pulse(const LEDRGB & color, uint32_t duration)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (NOT_A_PIN != _pin) {
|
if (NOT_A_PIN != mPin) {
|
||||||
_handler.detach();
|
mTimer.detach();
|
||||||
_scale = 0xff;
|
mScale = 0xff;
|
||||||
_pulseColor = color;
|
mPulseColor = color;
|
||||||
if (LED_BREATH == _ledState || LED_BLINK == _ledState) {
|
if (LED_BREATH == mLedState || LED_BLINK == mLedState) {
|
||||||
_savedState = _ledState;
|
mSavedState = mLedState;
|
||||||
} else {
|
} else {
|
||||||
_savedState = LED_STOP;
|
mSavedState = LED_STOP;
|
||||||
}
|
}
|
||||||
_pulseDuration = duration;
|
mPulseDuration = duration;
|
||||||
_ledState = LED_PULSE_START;
|
mLedState = LED_PULSE_START;
|
||||||
_handler.attach_ms(5, ledTrampoline, this);
|
mTimer.attach_ms(5, ledTrampoline, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ledstate_t wsLED::getState()
|
ledstate_t wsLED::getState()
|
||||||
{
|
{
|
||||||
|
|
||||||
return _ledState;
|
return mLedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsLED::stop(LEDRGB color)
|
void wsLED::stop(const LEDRGB & color)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (NOT_A_PIN != _pin) {
|
if (NOT_A_PIN != mPin) {
|
||||||
_handler.detach();
|
mTimer.detach();
|
||||||
_ledState = LED_STOP;
|
mLedState = LED_STOP;
|
||||||
_scale = 0xff;
|
mScale = 0xff;
|
||||||
setColor(color);
|
setColor(color);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Ovladani RGB WS2812 LED diody pro signalizacni ucely
|
// Ovladani RGB WS2812 LED diody pro signalizacni ucely
|
||||||
/**The MIT License (MIT)
|
/**The MIT License (MIT)
|
||||||
Copyright (c) 2017,2020 by Pavel Brychta
|
Copyright (c) 2017,20,23 by Pavel Brychta, http://www.xpablo.cz
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
@ -16,16 +16,15 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
See more at http://www.xpablo.cz
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Ticker.h>
|
#include <Ticker.h>
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
# include <driver/rmt.h>
|
#include <driver/rmt.h>
|
||||||
# define BITS_PER_LED_CMD 24
|
#define BITS_PER_LED_CMD 24
|
||||||
# define LED_BUFFER_ITEMS ((1 * BITS_PER_LED_CMD))
|
#define LED_BUFFER_ITEMS ((1 * BITS_PER_LED_CMD))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct LEDRGB {
|
struct LEDRGB {
|
||||||
@ -44,17 +43,17 @@ struct LEDRGB {
|
|||||||
uint8_t blue;
|
uint8_t blue;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
uint8_t raw[3];
|
uint8_t raw[3]{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Array access operator to index into the crgb object
|
// Array access operator to index into the crgb object
|
||||||
inline uint8_t& operator[] (uint8_t x) __attribute__((always_inline))
|
inline uint8_t & operator[](uint8_t x) __attribute__((always_inline))
|
||||||
{
|
{
|
||||||
return raw[x];
|
return raw[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Array access operator to index into the crgb object
|
// Array access operator to index into the crgb object
|
||||||
inline const uint8_t& operator[] (uint8_t x) const __attribute__((always_inline))
|
inline const uint8_t & operator[](uint8_t x) const __attribute__((always_inline))
|
||||||
{
|
{
|
||||||
return raw[x];
|
return raw[x];
|
||||||
}
|
}
|
||||||
@ -65,19 +64,19 @@ struct LEDRGB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow construction from R, G, B
|
// allow construction from R, G, B
|
||||||
inline LEDRGB( uint8_t ir, uint8_t ig, uint8_t ib) __attribute__((always_inline))
|
inline LEDRGB(uint8_t ir, uint8_t ig, uint8_t ib) __attribute__((always_inline))
|
||||||
: r(ir), g(ig), b(ib)
|
: r(ir), g(ig), b(ib)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow construction from 32-bit (really 24-bit) bit 0xRRGGBB color code
|
// allow construction from 32-bit (really 24-bit) bit 0xRRGGBB color code
|
||||||
inline LEDRGB( uint32_t colorcode) __attribute__((always_inline))
|
inline LEDRGB(uint32_t colorcode) __attribute__((always_inline))
|
||||||
: r((colorcode >> 16) & 0xFF), g((colorcode >> 8) & 0xFF), b((colorcode >> 0) & 0xFF)
|
: r((colorcode >> 16) & 0xFF), g((colorcode >> 8) & 0xFF), b((colorcode >> 0) & 0xFF)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow copy construction
|
// allow copy construction
|
||||||
inline LEDRGB(const LEDRGB& rhs) __attribute__((always_inline))
|
inline LEDRGB(const LEDRGB & rhs) __attribute__((always_inline))
|
||||||
{
|
{
|
||||||
r = rhs.r;
|
r = rhs.r;
|
||||||
g = rhs.g;
|
g = rhs.g;
|
||||||
@ -85,7 +84,7 @@ struct LEDRGB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow assignment from one RGB struct to another
|
// allow assignment from one RGB struct to another
|
||||||
inline LEDRGB& operator= (const LEDRGB& rhs) __attribute__((always_inline))
|
inline LEDRGB & operator=(const LEDRGB & rhs) __attribute__((always_inline))
|
||||||
{
|
{
|
||||||
r = rhs.r;
|
r = rhs.r;
|
||||||
g = rhs.g;
|
g = rhs.g;
|
||||||
@ -94,16 +93,16 @@ struct LEDRGB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow assignment from 32-bit (really 24-bit) 0xRRGGBB color code
|
// allow assignment from 32-bit (really 24-bit) 0xRRGGBB color code
|
||||||
inline LEDRGB& operator= (const uint32_t colorcode) __attribute__((always_inline))
|
inline LEDRGB & operator=(const uint32_t colorcode) __attribute__((always_inline))
|
||||||
{
|
{
|
||||||
r = (colorcode >> 16) & 0xFF;
|
r = (colorcode >> 16) & 0xFF;
|
||||||
g = (colorcode >> 8) & 0xFF;
|
g = (colorcode >> 8) & 0xFF;
|
||||||
b = (colorcode >> 0) & 0xFF;
|
b = (colorcode >> 0) & 0xFF;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow assignment from R, G, and B
|
// allow assignment from R, G, and B
|
||||||
inline LEDRGB& setRGB (uint8_t nr, uint8_t ng, uint8_t nb) __attribute__((always_inline))
|
inline LEDRGB & setRGB(uint8_t nr, uint8_t ng, uint8_t nb) __attribute__((always_inline))
|
||||||
{
|
{
|
||||||
r = nr;
|
r = nr;
|
||||||
g = ng;
|
g = ng;
|
||||||
@ -124,45 +123,44 @@ typedef enum {
|
|||||||
LED_PULSE_START,
|
LED_PULSE_START,
|
||||||
LED_PULSE,
|
LED_PULSE,
|
||||||
LED_PATTERN,
|
LED_PATTERN,
|
||||||
}ledstate_t;
|
} ledstate_t;
|
||||||
|
|
||||||
class wsLED
|
class wsLED {
|
||||||
{
|
protected:
|
||||||
protected:
|
int mPin; // pin, na kterem je LED pripojena
|
||||||
int _pin; // pin, na kterem je LED pripojena
|
LEDRGB mColor1;
|
||||||
LEDRGB _color1;
|
LEDRGB mColor2;
|
||||||
LEDRGB _color2;
|
int mOrder; // ColorOrder
|
||||||
int _order; // ColorOrder
|
uint8_t mScale = 0xff;
|
||||||
uint8_t _scale;
|
uint8_t mColor[3]{};
|
||||||
uint8_t _color[3];
|
Ticker mTimer;
|
||||||
Ticker _handler;
|
volatile ledstate_t mLedState = LED_STOP; // stav LEDky (blika, dycha, ...)
|
||||||
volatile ledstate_t _ledState; // stav LEDky (blika, dycha, ...)
|
volatile ledstate_t mSavedState = LED_STOP; // stav pro navrat
|
||||||
volatile ledstate_t _savedState; // stav pro navrat
|
volatile int mSubState = 0; // pomocny stav/index v poli dychani
|
||||||
volatile int _subState; // pomocny stav/index v poli dychani
|
uint32_t mPulseDuration = 0;
|
||||||
uint32_t _pulseDuration;
|
uint32_t mBlinkSpeed = 0;
|
||||||
uint32_t _blinkSpeed;
|
LEDRGB mPulseColor;
|
||||||
LEDRGB _pulseColor;
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
int _rmtChannel = 0;
|
int _rmtChannel = 0;
|
||||||
rmt_item32_t led_data_buffer[LED_BUFFER_ITEMS] = {0};
|
rmt_item32_t led_data_buffer[LED_BUFFER_ITEMS] = {0};
|
||||||
#endif
|
#endif
|
||||||
uint32_t _endtime;
|
uint32_t mEndTime = 0;
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
void setColor(LEDRGB color);
|
void setColor(const LEDRGB & color);
|
||||||
bool canShow() const;
|
bool canShow() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wsLED(int pin, int order = RGB);
|
wsLED(int pin, int order = RGB);
|
||||||
wsLED();
|
wsLED();
|
||||||
void begin();
|
void begin();
|
||||||
void begin(int pin);
|
void begin(int pin);
|
||||||
void rtLed(); // vykonna metoda
|
void rtLed(); // vykonna metoda
|
||||||
void setColors(LEDRGB color1, LEDRGB color2 = LEDRGB(0, 0, 0));
|
void setColors(const LEDRGB & color1, const LEDRGB & color2 = LEDRGB(0, 0, 0));
|
||||||
void blink(uint32_t speed = 300);
|
void blink(uint32_t speed = 300);
|
||||||
void breath();
|
void breath();
|
||||||
void setOrder(int neworder);
|
void setOrder(int neworder);
|
||||||
ledstate_t getState();
|
ledstate_t getState();
|
||||||
void pulse(LEDRGB color, uint32_t duration);
|
void pulse(const LEDRGB & color, uint32_t duration);
|
||||||
void stop(LEDRGB color = LEDRGB(0, 0, 0));
|
void stop(const LEDRGB & color = LEDRGB(0, 0, 0));
|
||||||
};
|
};
|
||||||
|
82
src/esp8266.c
Normal file
82
src/esp8266.c
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// This is a mash-up of the Due show() code + insights from Michael Miller's
|
||||||
|
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
|
||||||
|
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#ifdef ESP8266
|
||||||
|
#include <eagle_soc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint32_t _getCycleCount(void) __attribute__((always_inline));
|
||||||
|
static inline uint32_t _getCycleCount(void) {
|
||||||
|
uint32_t ccount;
|
||||||
|
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||||
|
return ccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
IRAM_ATTR void espShow(
|
||||||
|
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
|
||||||
|
#else
|
||||||
|
void espShow(
|
||||||
|
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CYCLES_800_T0H (F_CPU / 2500001) // 0.4us
|
||||||
|
#define CYCLES_800_T1H (F_CPU / 1250001) // 0.8us
|
||||||
|
#define CYCLES_800 (F_CPU / 800001) // 1.25us per bit
|
||||||
|
#define CYCLES_400_T0H (F_CPU / 2000000) // 0.5uS
|
||||||
|
#define CYCLES_400_T1H (F_CPU / 833333) // 1.2us
|
||||||
|
#define CYCLES_400 (F_CPU / 400000) // 2.5us per bit
|
||||||
|
|
||||||
|
uint8_t *p, *end, pix, mask;
|
||||||
|
uint32_t t, time0, time1, period, c, startTime;
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
uint32_t pinMask;
|
||||||
|
pinMask = _BV(pin);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p = pixels;
|
||||||
|
end = p + numBytes;
|
||||||
|
pix = *p++;
|
||||||
|
mask = 0x80;
|
||||||
|
startTime = 0;
|
||||||
|
|
||||||
|
if(is800KHz) {
|
||||||
|
time0 = CYCLES_800_T0H;
|
||||||
|
time1 = CYCLES_800_T1H;
|
||||||
|
period = CYCLES_800;
|
||||||
|
} else { // 400 KHz bitstream
|
||||||
|
time0 = CYCLES_400_T0H;
|
||||||
|
time1 = CYCLES_400_T1H;
|
||||||
|
period = CYCLES_400;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(t = time0;; t = time0) {
|
||||||
|
if(pix & mask) t = time1; // Bit high duration
|
||||||
|
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
|
||||||
|
#ifdef ESP8266
|
||||||
|
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||||
|
#else
|
||||||
|
gpio_set_level(pin, HIGH);
|
||||||
|
#endif
|
||||||
|
startTime = c; // Save start time
|
||||||
|
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
|
||||||
|
#ifdef ESP8266
|
||||||
|
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||||
|
#else
|
||||||
|
gpio_set_level(pin, LOW);
|
||||||
|
#endif
|
||||||
|
if(!(mask >>= 1)) { // Next bit/byte
|
||||||
|
if(p >= end) break;
|
||||||
|
pix = *p++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while((_getCycleCount() - startTime) < period); // Wait for last bit
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP8266
|
Loading…
Reference in New Issue
Block a user