Ulozeni kodu

This commit is contained in:
Pavel Brychta 2020-04-04 09:52:53 +02:00
parent fbc32db3fd
commit 69a5b37616
3 changed files with 400 additions and 0 deletions

104
src/NeoPixelesp8266.c Normal file
View File

@ -0,0 +1,104 @@
/*-------------------------------------------------------------------------
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) || defined(ARDUINO_ARCH_ESP32)
#include <Arduino.h>
#if defined(ARDUINO_ARCH_ESP8266)
#include <eagle_soc.h>
#endif
// ESP32 doesn't define ICACHE_RAM_ATTR
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR
#endif
inline uint32_t _getCycleCount()
{
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
//#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
#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
void ICACHE_RAM_ATTR 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
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
// wait for the LOW
do
{
cyclesNext = _getCycleCount();
} while ((cyclesNext - cyclesStart) < cyclesBit);
// set low
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
}
} while (pixels < end);
}
#endif

145
src/wsLED.cpp Normal file
View File

@ -0,0 +1,145 @@
// Ovladani signalizacni chytre LED diody
#include "wsLED.h"
// 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
extern "C" void ICACHE_RAM_ATTR send_pixels_800(uint8_t* pixel, size_t count, uint8_t pin);
#define countof(a) (sizeof(a) / sizeof(a[0]))
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,
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,
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 , 0x2a00
};
inline bool wsLED::canShow(void)
{
return (micros() - _endtime) >= 50L;
}
void wsLED::show(void)
{
uint8_t color[3];
for (uint8_t i = 0; i < 3; i++) {
// https://github.com/FastLED/FastLED/wiki/FastLED-Color-Correction
uint16_t c = (uint16_t)_color[i] * (1 + (uint16_t)_scale);
color[i] = (uint8_t)(c >> 8);
}
while (!canShow())
__asm__ volatile ("nop");
#if defined(ARDUINO_ARCH_ESP32)
uint32_t volatile register ilevel = XTOS_DISABLE_ALL_INTERRUPTS;
#else
noInterrupts();
//cli();
#endif
send_pixels_800(color, 1, _pin);
#if defined(ARDUINO_ARCH_ESP32)
XTOS_RESTORE_INTLEVEL(ilevel);
#else
interrupts();
//sei();
#endif
_endtime = micros();
}
wsLED::wsLED(int pin, int order)
{
_pin = pin;
_order = order;
}
void wsLED::begin(void)
{
pinMode(_pin, OUTPUT);
_color[0] = _color[1] = _color[2] = 0;
show();
}
void wsLED::setColor(LEDRGB &color)
{
_color[(_order >> 6) & 7] = color.r;
_color[(_order >> 3) & 7] = color.g;
_color[_order & 7] = color.b;
}
void ICACHE_RAM_ATTR wsLED::rtLed(void)
{
switch (_ledState) {
case LED_BLINK:
_scale = 0xff;
if (_subState) {
_subState = 0;
setColor(_color2);
} else {
_subState = 1;
setColor(_color1);
}
show();
break;
case LED_BREATH: {
++_subState;
_subState %= countof(LB);
uint16_t val = pgm_read_word(&LB[_subState]);
_scale = (uint8_t)val;
show();
val >>= 8;
_handler.attach_ms(30ul * val, lh, this);
break;
}
default:
_handler.attach_ms(300, lh, this); // jen pomale casovani
break;
}
}
void ICACHE_RAM_ATTR wsLED::lh(wsLED *ptr)
{
wsLED *pled = ptr;
pled->rtLed();
}
void wsLED::setColors(LEDRGB color1, LEDRGB color2)
{
_color1 = color1;
_color2 = color2;
}
void wsLED::blink(int speed)
{
_handler.detach();
_ledState = LED_BLINK;
_subState = 1;
_handler.attach_ms(300, lh, this);
}
void wsLED::breath(void)
{
_handler.detach();
_ledState = LED_BREATH;
_subState = 0;
setColor(_color1);
_handler.attach_ms(1, lh, this);
}
void wsLED::setOrder(int neworder)
{
_order = neworder;
}

151
src/wsLED.h Normal file
View File

@ -0,0 +1,151 @@
// Ovladani RGB WS2812 LED diody pro signalizacni ucely
/**The MIT License (MIT)
Copyright (c) 2017,2020 by Pavel Brychta
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
See more at http://www.xpablo.cz
*/
#ifndef __WSLED_H__
#define __WSLED_H__
#include <Arduino.h>
#include <Ticker.h>
struct LEDRGB {
union {
struct {
union {
uint8_t r;
uint8_t red;
};
union {
uint8_t g;
uint8_t green;
};
union {
uint8_t b;
uint8_t blue;
};
};
uint8_t raw[3];
};
// Array access operator to index into the crgb object
inline uint8_t& operator[] (uint8_t x) __attribute__((always_inline))
{
return raw[x];
}
// Array access operator to index into the crgb object
inline const uint8_t& operator[] (uint8_t x) const __attribute__((always_inline))
{
return raw[x];
}
// default values are UNINITIALIZED
inline LEDRGB() __attribute__((always_inline))
{
}
// allow construction from R, G, B
inline LEDRGB( uint8_t ir, uint8_t ig, uint8_t ib) __attribute__((always_inline))
: r(ir), g(ig), b(ib)
{
}
// allow construction from 32-bit (really 24-bit) bit 0xRRGGBB color code
inline LEDRGB( uint32_t colorcode) __attribute__((always_inline))
: r((colorcode >> 16) & 0xFF), g((colorcode >> 8) & 0xFF), b((colorcode >> 0) & 0xFF)
{
}
// allow copy construction
inline LEDRGB(const LEDRGB& rhs) __attribute__((always_inline))
{
r = rhs.r;
g = rhs.g;
b = rhs.b;
}
// allow assignment from one RGB struct to another
inline LEDRGB& operator= (const LEDRGB& rhs) __attribute__((always_inline))
{
r = rhs.r;
g = rhs.g;
b = rhs.b;
return *this;
}
// allow assignment from 32-bit (really 24-bit) 0xRRGGBB color code
inline LEDRGB& operator= (const uint32_t colorcode) __attribute__((always_inline))
{
r = (colorcode >> 16) & 0xFF;
g = (colorcode >> 8) & 0xFF;
b = (colorcode >> 0) & 0xFF;
return *this;
}
// allow assignment from R, G, and B
inline LEDRGB& setRGB (uint8_t nr, uint8_t ng, uint8_t nb) __attribute__((always_inline))
{
r = nr;
g = ng;
b = nb;
return *this;
}
};
enum ColorOrder {
RGB = 0012,
GRB = 0102
};
class wsLED
{
protected:
int _pin; // pin, na kterem je LED pripojena
LEDRGB _color1;
LEDRGB _color2;
int _order; // ColorOrder
uint32_t _endtime;
uint8_t _scale;
uint8_t _color[3];
Ticker _handler;
enum {
LED_STOP = 0,
LED_BLINK,
LED_BREATH,
LED_PATTERN,
} _ledState; // stav LEDky (blika, dycha, ...)
int _subState; // pomocny stav/index v poli dychani
bool canShow(void);
void show(void);
void setColor(LEDRGB &color);
public:
wsLED(int pin, int order = RGB);
void begin(void);
static void lh(wsLED *ptr);
void rtLed(void); // vykonna metoda
void setColors(LEDRGB color1, LEDRGB color2 = LEDRGB(0, 0, 0));
void blink(int speed = 300);
void breath(void);
void setOrder(int neworder);
};
#endif