mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 09:49:32 +02:00
Merge branch 'main' into feature/raw-temp-readings-LEAF
This commit is contained in:
commit
ba39ba49d9
6 changed files with 35 additions and 505 deletions
|
@ -26,7 +26,7 @@ void update_machineryprotection() {
|
||||||
/* Check if the ESP32 CPU running the Battery-Emulator is too hot.
|
/* Check if the ESP32 CPU running the Battery-Emulator is too hot.
|
||||||
We start with a warning, you can start to see Wifi issues if it becomes too hot
|
We start with a warning, you can start to see Wifi issues if it becomes too hot
|
||||||
If the chip starts to approach the design limit, we perform a graceful shutdown */
|
If the chip starts to approach the design limit, we perform a graceful shutdown */
|
||||||
if (datalayer.system.info.CPU_temperature > 80.0f) {
|
if (datalayer.system.info.CPU_temperature > 87.0f) {
|
||||||
set_event(EVENT_CPU_OVERHEATING, 0);
|
set_event(EVENT_CPU_OVERHEATING, 0);
|
||||||
} else {
|
} else {
|
||||||
clear_event(EVENT_CPU_OVERHEATING);
|
clear_event(EVENT_CPU_OVERHEATING);
|
||||||
|
|
|
@ -24,7 +24,6 @@ bool led_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
led = new LED(datalayer.battery.status.led_mode, esp32hal->LED_PIN(), esp32hal->LED_MAX_BRIGHTNESS());
|
led = new LED(datalayer.battery.status.led_mode, esp32hal->LED_PIN(), esp32hal->LED_MAX_BRIGHTNESS());
|
||||||
led->init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -57,20 +56,20 @@ void LED::exe(void) {
|
||||||
switch (get_event_level()) {
|
switch (get_event_level()) {
|
||||||
case EVENT_LEVEL_INFO:
|
case EVENT_LEVEL_INFO:
|
||||||
color = led_color::GREEN;
|
color = led_color::GREEN;
|
||||||
pixels.setPixelColor(0, COLOR_GREEN(brightness)); // Green pulsing LED
|
pixels.setPixelColor(COLOR_GREEN(brightness)); // Green pulsing LED
|
||||||
break;
|
break;
|
||||||
case EVENT_LEVEL_WARNING:
|
case EVENT_LEVEL_WARNING:
|
||||||
color = led_color::YELLOW;
|
color = led_color::YELLOW;
|
||||||
pixels.setPixelColor(0, COLOR_YELLOW(brightness)); // Yellow pulsing LED
|
pixels.setPixelColor(COLOR_YELLOW(brightness)); // Yellow pulsing LED
|
||||||
break;
|
break;
|
||||||
case EVENT_LEVEL_DEBUG:
|
case EVENT_LEVEL_DEBUG:
|
||||||
case EVENT_LEVEL_UPDATE:
|
case EVENT_LEVEL_UPDATE:
|
||||||
color = led_color::BLUE;
|
color = led_color::BLUE;
|
||||||
pixels.setPixelColor(0, COLOR_BLUE(brightness)); // Blue pulsing LED
|
pixels.setPixelColor(COLOR_BLUE(brightness)); // Blue pulsing LED
|
||||||
break;
|
break;
|
||||||
case EVENT_LEVEL_ERROR:
|
case EVENT_LEVEL_ERROR:
|
||||||
color = led_color::RED;
|
color = led_color::RED;
|
||||||
pixels.setPixelColor(0, COLOR_RED(esp32hal->LED_MAX_BRIGHTNESS())); // Red LED full brightness
|
pixels.setPixelColor(COLOR_RED(esp32hal->LED_MAX_BRIGHTNESS())); // Red LED full brightness
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -9,16 +9,12 @@ class LED {
|
||||||
led_color color = led_color::GREEN;
|
led_color color = led_color::GREEN;
|
||||||
|
|
||||||
LED(gpio_num_t pin, uint8_t maxBrightness)
|
LED(gpio_num_t pin, uint8_t maxBrightness)
|
||||||
: pixels(1, pin, NEO_GRB),
|
: pixels(pin), max_brightness(maxBrightness), brightness(maxBrightness), mode(led_mode_enum::CLASSIC) {}
|
||||||
max_brightness(maxBrightness),
|
|
||||||
brightness(maxBrightness),
|
|
||||||
mode(led_mode_enum::CLASSIC) {}
|
|
||||||
|
|
||||||
LED(led_mode_enum mode, gpio_num_t pin, uint8_t maxBrightness)
|
LED(led_mode_enum mode, gpio_num_t pin, uint8_t maxBrightness)
|
||||||
: pixels(1, pin, NEO_GRB), max_brightness(maxBrightness), brightness(maxBrightness), mode(mode) {}
|
: pixels(pin), max_brightness(maxBrightness), brightness(maxBrightness), mode(mode) {}
|
||||||
|
|
||||||
void exe(void);
|
void exe(void);
|
||||||
void init(void) { pixels.begin(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Adafruit_NeoPixel pixels;
|
Adafruit_NeoPixel pixels;
|
||||||
|
|
|
@ -1,368 +1,38 @@
|
||||||
/*!
|
/*Based on the Adafruit Neopixel library, which has been heavily modified to support only 1x RGB LED for lowest possible CPU usage*/
|
||||||
* @file Adafruit_NeoPixel.cpp
|
|
||||||
*
|
|
||||||
* @mainpage Arduino Library for driving Adafruit NeoPixel addressable LEDs,
|
|
||||||
* FLORA RGB Smart Pixels and compatible devicess -- WS2811, WS2812, WS2812B,
|
|
||||||
* SK6812, etc.
|
|
||||||
*
|
|
||||||
* @section intro_sec Introduction
|
|
||||||
*
|
|
||||||
* This is the documentation for Adafruit's NeoPixel library for the
|
|
||||||
* Arduino platform, allowing a broad range of microcontroller boards
|
|
||||||
* (most AVR boards, many ARM devices, ESP8266 and ESP32, among others)
|
|
||||||
* to control Adafruit NeoPixels, FLORA RGB Smart Pixels and compatible
|
|
||||||
* devices -- WS2811, WS2812, WS2812B, SK6812, etc.
|
|
||||||
*
|
|
||||||
* Adafruit invests time and resources providing this open source code,
|
|
||||||
* please support Adafruit and open-source hardware by purchasing products
|
|
||||||
* from Adafruit!
|
|
||||||
*
|
|
||||||
* @section author Author
|
|
||||||
*
|
|
||||||
* Written by Phil "Paint Your Dragon" Burgess for Adafruit Industries,
|
|
||||||
* with contributions by PJRC, Michael Miller and other members of the
|
|
||||||
* open source community.
|
|
||||||
*
|
|
||||||
* @section license License
|
|
||||||
*
|
|
||||||
* This file is part of the Adafruit_NeoPixel library.
|
|
||||||
*
|
|
||||||
* Adafruit_NeoPixel 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.
|
|
||||||
*
|
|
||||||
* Adafruit_NeoPixel 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/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Adafruit_NeoPixel.h"
|
#include "Adafruit_NeoPixel.h"
|
||||||
|
|
||||||
/*!
|
extern "C" void espShow(uint16_t pin, uint8_t *pixels, uint8_t numBytes);
|
||||||
@brief NeoPixel constructor when length, pin and pixel type are known
|
|
||||||
at compile-time.
|
Adafruit_NeoPixel::Adafruit_NeoPixel(int16_t p) : pixels(NULL) {
|
||||||
@param n Number of NeoPixels in strand.
|
updateLength();
|
||||||
@param p Arduino pin number which will drive the NeoPixel data in.
|
|
||||||
@param t Pixel type -- add together NEO_* constants defined in
|
|
||||||
Adafruit_NeoPixel.h, for example NEO_GRB+NEO_KHZ800 for
|
|
||||||
NeoPixels expecting an 800 KHz (vs 400 KHz) data stream
|
|
||||||
with color bytes expressed in green, red, blue order per
|
|
||||||
pixel.
|
|
||||||
@return Adafruit_NeoPixel object. Call the begin() function before use.
|
|
||||||
*/
|
|
||||||
Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, int16_t p, neoPixelType t)
|
|
||||||
: begun(false), brightness(0), pixels(NULL), endTime(0) {
|
|
||||||
updateType(t);
|
|
||||||
updateLength(n);
|
|
||||||
setPin(p);
|
setPin(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
void Adafruit_NeoPixel::updateLength(void) {
|
||||||
@brief "Empty" NeoPixel constructor when length, pin and/or pixel type
|
|
||||||
are not known at compile-time, and must be initialized later with
|
|
||||||
updateType(), updateLength() and setPin().
|
|
||||||
@return Adafruit_NeoPixel object. Call the begin() function before use.
|
|
||||||
@note This function is deprecated, here only for old projects that
|
|
||||||
may still be calling it. New projects should instead use the
|
|
||||||
'new' keyword with the first constructor syntax (length, pin,
|
|
||||||
type).
|
|
||||||
*/
|
|
||||||
Adafruit_NeoPixel::Adafruit_NeoPixel()
|
|
||||||
:
|
|
||||||
begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0),
|
|
||||||
pixels(NULL), rOffset(1), gOffset(0), bOffset(2), wOffset(1), endTime(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Deallocate Adafruit_NeoPixel object, set data pin back to INPUT.
|
|
||||||
*/
|
|
||||||
Adafruit_NeoPixel::~Adafruit_NeoPixel() {
|
|
||||||
free(pixels);
|
free(pixels);
|
||||||
if (pin >= 0)
|
pixels = (uint8_t *)malloc(numBytes);
|
||||||
pinMode(pin, INPUT);
|
if (pixels) memset(pixels, 0, numBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Configure NeoPixel pin for output.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::begin(void) {
|
|
||||||
if (pin >= 0) {
|
|
||||||
pinMode(pin, OUTPUT);
|
|
||||||
digitalWrite(pin, LOW);
|
|
||||||
}
|
|
||||||
begun = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Change the length of a previously-declared Adafruit_NeoPixel
|
|
||||||
strip object. Old data is deallocated and new data is cleared.
|
|
||||||
Pin number and pixel format are unchanged.
|
|
||||||
@param n New length of strip, in pixels.
|
|
||||||
@note This function is deprecated, here only for old projects that
|
|
||||||
may still be calling it. New projects should instead use the
|
|
||||||
'new' keyword with the first constructor syntax (length, pin,
|
|
||||||
type).
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::updateLength(uint16_t n) {
|
|
||||||
free(pixels); // Free existing data (if any)
|
|
||||||
|
|
||||||
// Allocate new data -- note: ALL PIXELS ARE CLEARED
|
|
||||||
numBytes = n * ((wOffset == rOffset) ? 3 : 4);
|
|
||||||
if ((pixels = (uint8_t *)malloc(numBytes))) {
|
|
||||||
memset(pixels, 0, numBytes);
|
|
||||||
numLEDs = n;
|
|
||||||
} else {
|
|
||||||
numLEDs = numBytes = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Change the pixel format of a previously-declared
|
|
||||||
Adafruit_NeoPixel strip object. If format changes from one of
|
|
||||||
the RGB variants to an RGBW variant (or RGBW to RGB), the old
|
|
||||||
data will be deallocated and new data is cleared. Otherwise,
|
|
||||||
the old data will remain in RAM and is not reordered to the
|
|
||||||
new format, so it's advisable to follow up with clear().
|
|
||||||
@param t Pixel type -- add together NEO_* constants defined in
|
|
||||||
Adafruit_NeoPixel.h, for example NEO_GRB+NEO_KHZ800 for
|
|
||||||
NeoPixels expecting an 800 KHz (vs 400 KHz) data stream
|
|
||||||
with color bytes expressed in green, red, blue order per
|
|
||||||
pixel.
|
|
||||||
@note This function is deprecated, here only for old projects that
|
|
||||||
may still be calling it. New projects should instead use the
|
|
||||||
'new' keyword with the first constructor syntax
|
|
||||||
(length, pin, type).
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::updateType(neoPixelType t) {
|
|
||||||
bool oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW
|
|
||||||
|
|
||||||
wOffset = (t >> 6) & 0b11; // See notes in header file
|
|
||||||
rOffset = (t >> 4) & 0b11; // regarding R/G/B/W offsets
|
|
||||||
gOffset = (t >> 2) & 0b11;
|
|
||||||
bOffset = t & 0b11;
|
|
||||||
|
|
||||||
// If bytes-per-pixel has changed (and pixel data was previously
|
|
||||||
// allocated), re-allocate to new size. Will clear any data.
|
|
||||||
if (pixels) {
|
|
||||||
bool newThreeBytesPerPixel = (wOffset == rOffset);
|
|
||||||
if (newThreeBytesPerPixel != oldThreeBytesPerPixel)
|
|
||||||
updateLength(numLEDs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void espShow(uint16_t pin, uint8_t *pixels, uint32_t numBytes);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Transmit pixel data in RAM to NeoPixels.
|
|
||||||
@note On most architectures, interrupts are temporarily disabled in
|
|
||||||
order to achieve the correct NeoPixel signal timing. This means
|
|
||||||
that the Arduino millis() and micros() functions, which require
|
|
||||||
interrupts, will lose small intervals of time whenever this
|
|
||||||
function is called (about 30 microseconds per RGB pixel, 40 for
|
|
||||||
RGBW pixels). There's no easy fix for this, but a few
|
|
||||||
specialized alternative or companion libraries exist that use
|
|
||||||
very device-specific peripherals to work around it.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::show(void) {
|
|
||||||
|
|
||||||
if (!pixels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Data latch = 300+ microsecond pause in the output stream. Rather than
|
|
||||||
// put a delay at the end of the function, the ending time is noted and
|
|
||||||
// the function will simply hold off (if needed) on issuing the
|
|
||||||
// subsequent round of data until the latch time has elapsed. This
|
|
||||||
// allows the mainline code to start generating the next frame of data
|
|
||||||
// rather than stalling for the latch.
|
|
||||||
while (!canShow())
|
|
||||||
;
|
|
||||||
// endTime is a private member (rather than global var) so that multiple
|
|
||||||
// instances on different pins can be quickly issued in succession (each
|
|
||||||
// instance doesn't delay the next).
|
|
||||||
|
|
||||||
// In order to make this code runtime-configurable to work with any pin,
|
|
||||||
// SBI/CBI instructions are eschewed in favor of full PORT writes via the
|
|
||||||
// OUT or ST instructions. It relies on two facts: that peripheral
|
|
||||||
// functions (such as PWM) take precedence on output pins, so our PORT-
|
|
||||||
// wide writes won't interfere, and that interrupts are globally disabled
|
|
||||||
// while data is being issued to the LEDs, so no other code will be
|
|
||||||
// accessing the PORT. The code takes an initial 'snapshot' of the PORT
|
|
||||||
// state, computes 'pin high' and 'pin low' values, and writes these back
|
|
||||||
// to the PORT register as needed.
|
|
||||||
|
|
||||||
// NRF52 may use PWM + DMA (if available), may not need to disable interrupt
|
|
||||||
// ESP32 may not disable interrupts because espShow() uses RMT which tries to acquire locks
|
|
||||||
|
|
||||||
espShow(pin, pixels, numBytes);
|
|
||||||
|
|
||||||
endTime = micros(); // Save EOD time for latch on next call
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Set/change the NeoPixel output pin number. Previous pin,
|
|
||||||
if any, is set to INPUT and the new pin is set to OUTPUT.
|
|
||||||
@param p Arduino pin number (-1 = no pin).
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::setPin(int16_t p) {
|
void Adafruit_NeoPixel::setPin(int16_t p) {
|
||||||
if (begun && (pin >= 0))
|
if (pin >= 0) pinMode(pin, INPUT);
|
||||||
pinMode(pin, INPUT); // Disable existing out pin
|
|
||||||
pin = p;
|
pin = p;
|
||||||
if (begun) {
|
if ((p >= 0)) {
|
||||||
pinMode(p, OUTPUT);
|
pinMode(p, OUTPUT);
|
||||||
digitalWrite(p, LOW);
|
digitalWrite(p, LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
void Adafruit_NeoPixel::show(void) {
|
||||||
@brief Set a pixel's color using separate red, green and blue
|
if (!pixels) return;
|
||||||
components. If using RGBW pixels, white will be set to 0.
|
espShow(pin, pixels, numBytes);
|
||||||
@param n Pixel index, starting from 0.
|
|
||||||
@param r Red brightness, 0 = minimum (off), 255 = maximum.
|
|
||||||
@param g Green brightness, 0 = minimum (off), 255 = maximum.
|
|
||||||
@param b Blue brightness, 0 = minimum (off), 255 = maximum.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint8_t r, uint8_t g,
|
|
||||||
uint8_t b) {
|
|
||||||
|
|
||||||
if (n < numLEDs) {
|
|
||||||
if (brightness) { // See notes in setBrightness()
|
|
||||||
r = (r * brightness) >> 8;
|
|
||||||
g = (g * brightness) >> 8;
|
|
||||||
b = (b * brightness) >> 8;
|
|
||||||
}
|
|
||||||
uint8_t *p;
|
|
||||||
if (wOffset == rOffset) { // Is an RGB-type strip
|
|
||||||
p = &pixels[n * 3]; // 3 bytes per pixel
|
|
||||||
} else { // Is a WRGB-type strip
|
|
||||||
p = &pixels[n * 4]; // 4 bytes per pixel
|
|
||||||
p[wOffset] = 0; // But only R,G,B passed -- set W to 0
|
|
||||||
}
|
|
||||||
p[rOffset] = r; // R,G,B always stored
|
|
||||||
p[gOffset] = g;
|
|
||||||
p[bOffset] = b;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
void Adafruit_NeoPixel::setPixelColor(uint32_t c) {
|
||||||
@brief Set a pixel's color using separate red, green, blue and white
|
uint8_t *p = pixels;
|
||||||
components (for RGBW NeoPixels only).
|
uint8_t r = (uint8_t)(c >> 16), g = (uint8_t)(c >> 8), b = (uint8_t)c;
|
||||||
@param n Pixel index, starting from 0.
|
p[rOffset] = r;
|
||||||
@param r Red brightness, 0 = minimum (off), 255 = maximum.
|
p[gOffset] = g;
|
||||||
@param g Green brightness, 0 = minimum (off), 255 = maximum.
|
p[bOffset] = b;
|
||||||
@param b Blue brightness, 0 = minimum (off), 255 = maximum.
|
}
|
||||||
@param w White brightness, 0 = minimum (off), 255 = maximum, ignored
|
|
||||||
if using RGB pixels.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint8_t r, uint8_t g,
|
|
||||||
uint8_t b, uint8_t w) {
|
|
||||||
|
|
||||||
if (n < numLEDs) {
|
|
||||||
if (brightness) { // See notes in setBrightness()
|
|
||||||
r = (r * brightness) >> 8;
|
|
||||||
g = (g * brightness) >> 8;
|
|
||||||
b = (b * brightness) >> 8;
|
|
||||||
w = (w * brightness) >> 8;
|
|
||||||
}
|
|
||||||
uint8_t *p;
|
|
||||||
if (wOffset == rOffset) { // Is an RGB-type strip
|
|
||||||
p = &pixels[n * 3]; // 3 bytes per pixel (ignore W)
|
|
||||||
} else { // Is a WRGB-type strip
|
|
||||||
p = &pixels[n * 4]; // 4 bytes per pixel
|
|
||||||
p[wOffset] = w; // Store W
|
|
||||||
}
|
|
||||||
p[rOffset] = r; // Store R,G,B
|
|
||||||
p[gOffset] = g;
|
|
||||||
p[bOffset] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Set a pixel's color using a 32-bit 'packed' RGB or RGBW value.
|
|
||||||
@param n Pixel index, starting from 0.
|
|
||||||
@param c 32-bit color value. Most significant byte is white (for RGBW
|
|
||||||
pixels) or ignored (for RGB pixels), next is red, then green,
|
|
||||||
and least significant byte is blue.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
|
|
||||||
if (n < numLEDs) {
|
|
||||||
uint8_t *p, r = (uint8_t)(c >> 16), g = (uint8_t)(c >> 8), b = (uint8_t)c;
|
|
||||||
if (brightness) { // See notes in setBrightness()
|
|
||||||
r = (r * brightness) >> 8;
|
|
||||||
g = (g * brightness) >> 8;
|
|
||||||
b = (b * brightness) >> 8;
|
|
||||||
}
|
|
||||||
if (wOffset == rOffset) {
|
|
||||||
p = &pixels[n * 3];
|
|
||||||
} else {
|
|
||||||
p = &pixels[n * 4];
|
|
||||||
uint8_t w = (uint8_t)(c >> 24);
|
|
||||||
p[wOffset] = brightness ? ((w * brightness) >> 8) : w;
|
|
||||||
}
|
|
||||||
p[rOffset] = r;
|
|
||||||
p[gOffset] = g;
|
|
||||||
p[bOffset] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Adjust output brightness. Does not immediately affect what's
|
|
||||||
currently displayed on the LEDs. The next call to show() will
|
|
||||||
refresh the LEDs at this level.
|
|
||||||
@param b Brightness setting, 0=minimum (off), 255=brightest.
|
|
||||||
@note This was intended for one-time use in one's setup() function,
|
|
||||||
not as an animation effect in itself. Because of the way this
|
|
||||||
library "pre-multiplies" LED colors in RAM, changing the
|
|
||||||
brightness is often a "lossy" operation -- what you write to
|
|
||||||
pixels isn't necessary the same as what you'll read back.
|
|
||||||
Repeated brightness changes using this function exacerbate the
|
|
||||||
problem. Smart programs therefore treat the strip as a
|
|
||||||
write-only resource, maintaining their own state to render each
|
|
||||||
frame of an animation, not relying on read-modify-write.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::setBrightness(uint8_t b) {
|
|
||||||
// Stored brightness value is different than what's passed.
|
|
||||||
// This simplifies the actual scaling math later, allowing a fast
|
|
||||||
// 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t,
|
|
||||||
// adding 1 here may (intentionally) roll over...so 0 = max brightness
|
|
||||||
// (color values are interpreted literally; no scaling), 1 = min
|
|
||||||
// brightness (off), 255 = just below max brightness.
|
|
||||||
uint8_t newBrightness = b + 1;
|
|
||||||
if (newBrightness != brightness) { // Compare against prior value
|
|
||||||
// Brightness has changed -- re-scale existing data in RAM,
|
|
||||||
// This process is potentially "lossy," especially when increasing
|
|
||||||
// brightness. The tight timing in the WS2811/WS2812 code means there
|
|
||||||
// aren't enough free cycles to perform this scaling on the fly as data
|
|
||||||
// is issued. So we make a pass through the existing color data in RAM
|
|
||||||
// and scale it (subsequent graphics commands also work at this
|
|
||||||
// brightness level). If there's a significant step up in brightness,
|
|
||||||
// the limited number of steps (quantization) in the old data will be
|
|
||||||
// quite visible in the re-scaled version. For a non-destructive
|
|
||||||
// change, you'll need to re-render the full strip data. C'est la vie.
|
|
||||||
uint8_t c, *ptr = pixels,
|
|
||||||
oldBrightness = brightness - 1; // De-wrap old brightness value
|
|
||||||
uint16_t scale;
|
|
||||||
if (oldBrightness == 0)
|
|
||||||
scale = 0; // Avoid /0
|
|
||||||
else if (b == 255)
|
|
||||||
scale = 65535 / oldBrightness;
|
|
||||||
else
|
|
||||||
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
|
|
||||||
for (uint16_t i = 0; i < numBytes; i++) {
|
|
||||||
c = *ptr;
|
|
||||||
*ptr++ = (c * scale) >> 8;
|
|
||||||
}
|
|
||||||
brightness = newBrightness;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Fill the whole NeoPixel strip with 0 / black / off.
|
|
||||||
*/
|
|
||||||
void Adafruit_NeoPixel::clear(void) { memset(pixels, 0, numBytes); }
|
|
|
@ -38,52 +38,6 @@
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
// The order of primary colors in the NeoPixel data stream can vary among
|
|
||||||
// device types, manufacturers and even different revisions of the same
|
|
||||||
// item. The third parameter to the Adafruit_NeoPixel constructor encodes
|
|
||||||
// the per-pixel byte offsets of the red, green and blue primaries (plus
|
|
||||||
// white, if present) in the data stream -- the following #defines provide
|
|
||||||
// an easier-to-use named version for each permutation. e.g. NEO_GRB
|
|
||||||
// indicates a NeoPixel-compatible device expecting three bytes per pixel,
|
|
||||||
// with the first byte transmitted containing the green value, second
|
|
||||||
// containing red and third containing blue. The in-memory representation
|
|
||||||
// of a chain of NeoPixels is the same as the data-stream order; no
|
|
||||||
// re-ordering of bytes is required when issuing data to the chain.
|
|
||||||
// Most of these values won't exist in real-world devices, but it's done
|
|
||||||
// this way so we're ready for it (also, if using the WS2811 driver IC,
|
|
||||||
// one might have their pixels set up in any weird permutation).
|
|
||||||
|
|
||||||
// Bits 5,4 of this value are the offset (0-3) from the first byte of a
|
|
||||||
// pixel to the location of the red color byte. Bits 3,2 are the green
|
|
||||||
// offset and 1,0 are the blue offset. If it is an RGBW-type device
|
|
||||||
// (supporting a white primary in addition to R,G,B), bits 7,6 are the
|
|
||||||
// offset to the white byte...otherwise, bits 7,6 are set to the same value
|
|
||||||
// as 5,4 (red) to indicate an RGB (not RGBW) device.
|
|
||||||
// i.e. binary representation:
|
|
||||||
// 0bWWRRGGBB for RGBW devices
|
|
||||||
// 0bRRRRGGBB for RGB
|
|
||||||
|
|
||||||
// RGB NeoPixel permutations; white and red offsets are always same
|
|
||||||
// Offset: W R G B
|
|
||||||
#define NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2)) ///< Transmit as R,G,B
|
|
||||||
#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1)) ///< Transmit as R,B,G
|
|
||||||
#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2)) ///< Transmit as G,R,B
|
|
||||||
#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1)) ///< Transmit as G,B,R
|
|
||||||
#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0)) ///< Transmit as B,R,G
|
|
||||||
#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0)) ///< Transmit as B,G,R
|
|
||||||
|
|
||||||
// Add NEO_KHZ400 to the color order value to indicate a 400 KHz device.
|
|
||||||
// All but the earliest v1 NeoPixels expect an 800 KHz data stream, this is
|
|
||||||
// the default if unspecified. Because flash space is very limited on ATtiny
|
|
||||||
// devices (e.g. Trinket, Gemma), v1 NeoPixels aren't handled by default on
|
|
||||||
// those chips, though it can be enabled by removing the ifndef/endif below,
|
|
||||||
// but code will be bigger. Conversely, can disable the NEO_KHZ400 line on
|
|
||||||
// other MCUs to remove v1 support and save a little space.
|
|
||||||
|
|
||||||
#define NEO_KHZ400 0x0100 ///< 400 KHz data transmission
|
|
||||||
|
|
||||||
typedef uint16_t neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Class that stores state and functions for interacting with
|
@brief Class that stores state and functions for interacting with
|
||||||
Adafruit NeoPixels and compatible devices.
|
Adafruit NeoPixels and compatible devices.
|
||||||
|
@ -92,112 +46,23 @@ class Adafruit_NeoPixel {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor: number of LEDs, pin number, LED type
|
// Constructor: number of LEDs, pin number, LED type
|
||||||
Adafruit_NeoPixel(uint16_t n, int16_t pin = 6,
|
Adafruit_NeoPixel(int16_t pin = -1);
|
||||||
neoPixelType type = NEO_GRB);
|
|
||||||
Adafruit_NeoPixel(void);
|
Adafruit_NeoPixel(void);
|
||||||
~Adafruit_NeoPixel();
|
|
||||||
|
|
||||||
void begin(void);
|
|
||||||
void show(void);
|
void show(void);
|
||||||
void setPin(int16_t p);
|
void setPin(int16_t p);
|
||||||
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
|
void setPixelColor(uint32_t c);
|
||||||
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
void updateLength(void);
|
||||||
void setPixelColor(uint16_t n, uint32_t c);
|
|
||||||
void setBrightness(uint8_t);
|
|
||||||
void clear(void);
|
|
||||||
void updateLength(uint16_t n);
|
|
||||||
void updateType(neoPixelType t);
|
|
||||||
/*!
|
|
||||||
@brief Check whether a call to show() will start sending data
|
|
||||||
immediately or will 'block' for a required interval. NeoPixels
|
|
||||||
require a short quiet time (about 300 microseconds) after the
|
|
||||||
last bit is received before the data 'latches' and new data can
|
|
||||||
start being received. Usually one's sketch is implicitly using
|
|
||||||
this time to generate a new frame of animation...but if it
|
|
||||||
finishes very quickly, this function could be used to see if
|
|
||||||
there's some idle time available for some low-priority
|
|
||||||
concurrent task.
|
|
||||||
@return 1 or true if show() will start sending immediately, 0 or false
|
|
||||||
if show() would block (meaning some idle time is available).
|
|
||||||
*/
|
|
||||||
bool canShow(void) {
|
|
||||||
// It's normal and possible for endTime to exceed micros() if the
|
|
||||||
// 32-bit clock counter has rolled over (about every 70 minutes).
|
|
||||||
// Since both are uint32_t, a negative delta correctly maps back to
|
|
||||||
// positive space, and it would seem like the subtraction below would
|
|
||||||
// suffice. But a problem arises if code invokes show() very
|
|
||||||
// infrequently...the micros() counter may roll over MULTIPLE times in
|
|
||||||
// that interval, the delta calculation is no longer correct and the
|
|
||||||
// next update may stall for a very long time. The check below resets
|
|
||||||
// the latch counter if a rollover has occurred. This can cause an
|
|
||||||
// extra delay of up to 300 microseconds in the rare case where a
|
|
||||||
// show() call happens precisely around the rollover, but that's
|
|
||||||
// neither likely nor especially harmful, vs. other code that might
|
|
||||||
// stall for 30+ minutes, or having to document and frequently remind
|
|
||||||
// and/or provide tech support explaining an unintuitive need for
|
|
||||||
// show() calls at least once an hour.
|
|
||||||
uint32_t now = micros();
|
|
||||||
if (endTime > now) {
|
|
||||||
endTime = now;
|
|
||||||
}
|
|
||||||
return (now - endTime) >= 300L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Retrieve the pin number used for NeoPixel data output.
|
|
||||||
@return Arduino pin number (-1 if not set).
|
|
||||||
*/
|
|
||||||
int16_t getPin(void) const { return pin; };
|
|
||||||
/*!
|
|
||||||
@brief Return the number of pixels in an Adafruit_NeoPixel strip object.
|
|
||||||
@return Pixel count (0 if not set).
|
|
||||||
*/
|
|
||||||
uint16_t numPixels(void) const { return numLEDs; }
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Convert separate red, green and blue values into a single
|
|
||||||
"packed" 32-bit RGB color.
|
|
||||||
@param r Red brightness, 0 to 255.
|
|
||||||
@param g Green brightness, 0 to 255.
|
|
||||||
@param b Blue brightness, 0 to 255.
|
|
||||||
@return 32-bit packed RGB value, which can then be assigned to a
|
|
||||||
variable for later use or passed to the setPixelColor()
|
|
||||||
function. Packed RGB format is predictable, regardless of
|
|
||||||
LED strand color order.
|
|
||||||
*/
|
|
||||||
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
|
|
||||||
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
|
||||||
}
|
|
||||||
/*!
|
|
||||||
@brief Convert separate red, green, blue and white values into a
|
|
||||||
single "packed" 32-bit WRGB color.
|
|
||||||
@param r Red brightness, 0 to 255.
|
|
||||||
@param g Green brightness, 0 to 255.
|
|
||||||
@param b Blue brightness, 0 to 255.
|
|
||||||
@param w White brightness, 0 to 255.
|
|
||||||
@return 32-bit packed WRGB value, which can then be assigned to a
|
|
||||||
variable for later use or passed to the setPixelColor()
|
|
||||||
function. Packed WRGB format is predictable, regardless of
|
|
||||||
LED strand color order.
|
|
||||||
*/
|
|
||||||
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
|
||||||
return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool begun; ///< true if begin() previously called
|
uint8_t numBytes = 3; ///< Size of 'pixels' buffer below
|
||||||
uint16_t numLEDs; ///< Number of RGB LEDs in strip
|
|
||||||
uint16_t numBytes; ///< Size of 'pixels' buffer below
|
|
||||||
int16_t pin; ///< Output pin number (-1 if not yet set)
|
int16_t pin; ///< Output pin number (-1 if not yet set)
|
||||||
uint8_t brightness; ///< Strip brightness 0-255 (stored as +1)
|
|
||||||
uint8_t *pixels; ///< Holds LED color values (3 or 4 bytes each)
|
uint8_t *pixels; ///< Holds LED color values (3 or 4 bytes each)
|
||||||
uint8_t rOffset; ///< Red index within each 3- or 4-byte pixel
|
uint8_t rOffset = 0b01; ///< Red index within each 3- or 4-byte pixel
|
||||||
uint8_t gOffset; ///< Index of green byte
|
uint8_t gOffset = 0b00; ///< Index of green byte
|
||||||
uint8_t bOffset; ///< Index of blue byte
|
uint8_t bOffset = 0b10; ///< Index of blue byte
|
||||||
uint8_t wOffset; ///< Index of white (==rOffset if no white)
|
|
||||||
uint32_t endTime; ///< Latch timing reference
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ADAFRUIT_NEOPIXEL_H
|
#endif // ADAFRUIT_NEOPIXEL_H
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
TEST(SafetyTests, ShouldSetEventWhenTemperatureTooHigh) {
|
TEST(SafetyTests, ShouldSetEventWhenTemperatureTooHigh) {
|
||||||
init_events();
|
init_events();
|
||||||
datalayer.system.info.CPU_temperature = 82;
|
datalayer.system.info.CPU_temperature = 88;
|
||||||
update_machineryprotection();
|
update_machineryprotection();
|
||||||
|
|
||||||
auto event_pointer = get_event_pointer(EVENT_CPU_OVERHEATING);
|
auto event_pointer = get_event_pointer(EVENT_CPU_OVERHEATING);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue