Browse Source

Improved neopixel-handling + single-LED-support

master
Torsten Stauder 4 years ago
parent
commit
7ee8c3fa4a
  1. 7
      src/Button.cpp
  2. 2
      src/Button.h
  3. 146
      src/Led.cpp
  4. 2
      src/revision.h

7
src/Button.cpp

@ -6,6 +6,8 @@
#include "Port.h"
#include "System.h"
bool gButtonInitComplete = false;
// Only enable those buttons that are not disabled (99 or >115)
// 0 -> 39: GPIOs
// 100 -> 115: Port-expander
@ -159,14 +161,19 @@ void Button_Cyclic() {
if (!gButtons[i].currentState) {
gButtons[i].isPressed = true;
gButtons[i].lastPressedTimestamp = currentTimestamp;
if (!gButtons[i].firstPressedTimestamp) {
gButtons[i].firstPressedTimestamp = currentTimestamp;
}
} else {
gButtons[i].isReleased = true;
gButtons[i].lastReleasedTimestamp = currentTimestamp;
gButtons[i].firstPressedTimestamp = 0;
}
}
gButtons[i].lastState = gButtons[i].currentState;
}
}
gButtonInitComplete = true;
Button_DoButtonActions();
}

2
src/Button.h

@ -7,9 +7,11 @@ typedef struct {
bool isReleased : 1;
unsigned long lastPressedTimestamp;
unsigned long lastReleasedTimestamp;
unsigned long firstPressedTimestamp;
} t_button;
extern uint8_t gShutdownButton;
extern bool gButtonInitComplete;
void Button_Init(void);
void Button_Cyclic(void);

146
src/Led.cpp

@ -139,6 +139,7 @@ static void Led_Task(void *parameter) {
static bool volumeChangeShown = false;
static bool showEvenError = false;
static bool turnedOffLeds = false;
static bool singleLedStatus = false;
static uint8_t ledPosWebstream = 0;
static uint8_t ledSwitchInterval = 5; // time in secs (webstream-only)
static uint8_t webstreamColor = 0;
@ -164,7 +165,9 @@ static void Led_Task(void *parameter) {
vTaskDelay(portTICK_RATE_MS * 10);
continue;
}
if (!LED_INDICATOR_IS_SET(LedIndicatorType::BootComplete)) { // Rotates orange unless boot isn't complete
// Multi-LED: rotates orange unless boot isn't complete
// Single-LED: blinking orange
if (!LED_INDICATOR_IS_SET(LedIndicatorType::BootComplete)) {
FastLED.clear();
for (uint8_t led = 0; led < NUM_LEDS; led++) {
if (showEvenError) {
@ -197,21 +200,43 @@ static void Led_Task(void *parameter) {
lastLedBrightness = Led_Brightness;
}
// LEDs growing red as long button for sleepmode is pressed.
// Multi-LED: growing red as long button for sleepmode is pressed.
// Single-LED: red when pressed and flashing red when long interval-duration is reached
if (gShutdownButton < (sizeof(gButtons) / sizeof(gButtons[0])) - 1) { // Only show animation, if CMD_SLEEPMODE was assigned to BUTTON_n_LONG + button is pressed
if (!gButtons[gShutdownButton].currentState) {
if (!gButtons[gShutdownButton].currentState && (millis() - gButtons[gShutdownButton].firstPressedTimestamp >= 150) && gButtonInitComplete) {
if (NUM_LEDS == 1) {
FastLED.clear();
if (millis() - gButtons[gShutdownButton].firstPressedTimestamp <= intervalToLongPress) {
leds[0] = CRGB::Red;
FastLED.show();
} else {
if (singleLedStatus) {
leds[0] = CRGB::Red;
} else {
leds[0] = CRGB::Black;
}
FastLED.show();
singleLedStatus = !singleLedStatus;
vTaskDelay(portTICK_RATE_MS * 50);
}
} else {
if (millis() - gButtons[gShutdownButton].firstPressedTimestamp >= intervalToLongPress) {
vTaskDelay(portTICK_RATE_MS * 50);
continue;
}
FastLED.clear();
for (uint8_t led = 0; led < NUM_LEDS; led++) {
leds[Led_Address(led)] = CRGB::Red;
if (gButtons[gShutdownButton].currentState) {
FastLED.show();
delay(5);
vTaskDelay(portTICK_RATE_MS * 5);
break;
}
FastLED.show();
vTaskDelay(intervalToLongPress / NUM_LEDS * portTICK_RATE_MS);
}
}
}
} else {
gShutdownButton = (sizeof(gButtons) / sizeof(gButtons[0])) - 1; // If CMD_SLEEPMODE was not assigned to an enabled button, dummy-button is used
if (!gButtons[gShutdownButton].currentState) {
@ -219,32 +244,65 @@ static void Led_Task(void *parameter) {
}
}
// Multi-LED: all leds flash red 1x
// Single-LED: led flashes red 5x
if (LED_INDICATOR_IS_SET(LedIndicatorType::Error)) { // If error occured (e.g. RFID-modification not accepted)
LED_INDICATOR_CLEAR(LedIndicatorType::Error);
notificationShown = true;
FastLED.clear();
if (NUM_LEDS == 1) {
for (uint8_t cnt = 0; cnt < 5; cnt++) {
FastLED.clear();
if (singleLedStatus) {
leds[0] = CRGB::Red;
} else {
leds[0] = CRGB::Black;
}
FastLED.show();
singleLedStatus = !singleLedStatus;
vTaskDelay(portTICK_RATE_MS * 100);
}
} else {
for (uint8_t led = 0; led < NUM_LEDS; led++) {
leds[Led_Address(led)] = CRGB::Red;
}
FastLED.show();
vTaskDelay(portTICK_RATE_MS * 200);
}
}
// Multi-LED: all leds flash green 1x
// Single-LED: led flashes green 5x
if (LED_INDICATOR_IS_SET(LedIndicatorType::Ok)) { // If action was accepted
LED_INDICATOR_CLEAR(LedIndicatorType::Ok);
notificationShown = true;
FastLED.clear();
if (NUM_LEDS == 1) {
for (uint8_t cnt = 0; cnt < 5; cnt++) {
FastLED.clear();
if (singleLedStatus) {
leds[0] = CRGB::Green;
} else {
leds[0] = CRGB::Black;
}
FastLED.show();
singleLedStatus = !singleLedStatus;
vTaskDelay(portTICK_RATE_MS * 100);
}
} else {
for (uint8_t led = 0; led < NUM_LEDS; led++) {
leds[Led_Address(led)] = CRGB::Green;
}
FastLED.show();
vTaskDelay(portTICK_RATE_MS * 400);
}
}
#ifdef MEASURE_BATTERY_VOLTAGE
if (LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning)) { // Flashes red three times if battery-voltage is low
// Single + Multiple LEDs: flashes red three times if battery-voltage is low
if (LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning)) {
LED_INDICATOR_CLEAR(LedIndicatorType::VoltageWarning);
notificationShown = true;
for (uint8_t i = 0; i < 3; i++) {
@ -265,6 +323,8 @@ static void Led_Task(void *parameter) {
}
}
// Single-LED: indicates voltage coloured between gradient green (high) => red (low)
// Multi-LED: number of LEDs indicates voltage-level with having green >= 60% ; orange < 60% + >= 30% ; red < 30%
if (LED_INDICATOR_IS_SET(LedIndicatorType::Voltage)) {
LED_INDICATOR_CLEAR(LedIndicatorType::Voltage);
float currentVoltage = Battery_GetVoltage();
@ -275,12 +335,22 @@ static void Led_Task(void *parameter) {
LED_INDICATOR_SET(LedIndicatorType::Error);
break;
} else {
uint8_t numLedsToLight = ((float)vDiffCurrent / vDiffIndicatorRange) * NUM_LEDS;
FastLED.clear();
if (NUM_LEDS == 1) {
if ((float) vDiffCurrent / vDiffIndicatorRange >= 0.6) {
leds[0] = CRGB::Green;
} else if ((float) vDiffCurrent / vDiffIndicatorRange < 0.6 && (float) vDiffCurrent / vDiffIndicatorRange >= 0.3) {
leds[0] = CRGB::Orange;
} else {
leds[0] = CRGB::Red;
}
FastLED.show();
} else {
uint8_t numLedsToLight = ((float)vDiffCurrent / vDiffIndicatorRange) * NUM_LEDS;
for (uint8_t led = 0; led < numLedsToLight; led++) {
if (((float)numLedsToLight / NUM_LEDS) >= 0.6) {
leds[Led_Address(led)] = CRGB::Green;
} else if (((float)numLedsToLight / NUM_LEDS) <= 0.6 && ((float)numLedsToLight / NUM_LEDS) >= 0.3) {
} else if (((float)numLedsToLight / NUM_LEDS) < 0.6 && ((float)numLedsToLight / NUM_LEDS) >= 0.3) {
leds[Led_Address(led)] = CRGB::Orange;
} else {
leds[Led_Address(led)] = CRGB::Red;
@ -288,6 +358,7 @@ static void Led_Task(void *parameter) {
FastLED.show();
vTaskDelay(portTICK_RATE_MS * 20);
}
}
for (uint8_t i = 0; i <= 100; i++) {
if (hlastVolume != AudioPlayer_GetCurrentVolume() || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) {
@ -300,14 +371,20 @@ static void Led_Task(void *parameter) {
}
#endif
// Single-LED: led indicates loudness between green (low) => red (high)
// Multiple-LEDs: number of LEDs indicate loudness; gradient is shown between green (low) => red (high)
if (hlastVolume != AudioPlayer_GetCurrentVolume()) { // If volume has been changed
uint8_t numLedsToLight = map(AudioPlayer_GetCurrentVolume(), 0, AudioPlayer_GetMaxVolume(), 0, NUM_LEDS);
hlastVolume = AudioPlayer_GetCurrentVolume();
volumeChangeShown = true;
FastLED.clear();
for (int led = 0; led < numLedsToLight; led++) { // (Inverse) color-gradient from green (85) back to (still) red (245) using unsigned-cast
leds[Led_Address(led)].setHue((uint8_t)(85 - ((double)95 / NUM_LEDS) * led));
if (NUM_LEDS == 1) {
leds[0].setHue((uint8_t)(85 - (90 * ((double)AudioPlayer_GetCurrentVolume() / (double)AudioPlayer_GetMaxVolumeSpeaker()))));
} else {
for (int led = 0; led < numLedsToLight; led++) { // (Inverse) color-gradient from green (85) back to (still) red (250) using unsigned-cast
leds[Led_Address(led)].setHue((uint8_t)(85 - ((double)90 / NUM_LEDS) * led));
}
}
FastLED.show();
@ -323,8 +400,11 @@ static void Led_Task(void *parameter) {
}
}
// < 4 LEDs: doesn't make sense at all
// >= 4 LEDs: collapsing ring (blue => black)
if (LED_INDICATOR_IS_SET(LedIndicatorType::Rewind)) {
LED_INDICATOR_CLEAR(LedIndicatorType::Rewind);
if (NUM_LEDS >= 4) {
for (uint8_t i = NUM_LEDS - 1; i > 0; i--) {
leds[Led_Address(i)] = CRGB::Black;
FastLED.show();
@ -335,9 +415,13 @@ static void Led_Task(void *parameter) {
}
}
}
}
// < 4 LEDs: doesn't make sense at all
// >= 4 LEDs: growing ring (black => blue); relative number of LEDs indicate playlist-progress
if (LED_INDICATOR_IS_SET(LedIndicatorType::PlaylistProgress)) {
LED_INDICATOR_CLEAR(LedIndicatorType::PlaylistProgress);
if (NUM_LEDS >= 4) {
if (gPlayProperties.numberOfTracks > 1 && gPlayProperties.currentTrackNumber < gPlayProperties.numberOfTracks) {
uint8_t numLedsToLight = map(gPlayProperties.currentTrackNumber, 0, gPlayProperties.numberOfTracks - 1, 0, NUM_LEDS);
FastLED.clear();
@ -383,6 +467,13 @@ static void Led_Task(void *parameter) {
}
}
}
}
// Skip playmodes if shutdown-button is pressed as this leads to ugly indications
if (!gButtons[gShutdownButton].currentState && gShutdownButton != 99) {
vTaskDelay(portTICK_RATE_MS * 20);
continue;
}
switch (gPlayProperties.playMode) {
case NO_PLAYLIST: // If no playlist is active (idle)
@ -427,6 +518,17 @@ static void Led_Task(void *parameter) {
case BUSY: // If uC is busy (parsing SD-card)
ledBusyShown = true;
if (NUM_LEDS == 1) {
FastLED.clear();
singleLedStatus = !singleLedStatus;
if (singleLedStatus) {
leds[0] = CRGB::BlueViolet;
} else {
leds[0] = CRGB::Black;
}
FastLED.show();
vTaskDelay(portTICK_RATE_MS * 100);
} else {
for (uint8_t i = 0; i < NUM_LEDS; i++) {
FastLED.clear();
if (Led_Address(i) == 0) {
@ -446,6 +548,7 @@ static void Led_Task(void *parameter) {
}
vTaskDelay(portTICK_RATE_MS * 50);
}
}
break;
default: // If playlist is active (doesn't matter which type)
@ -467,24 +570,32 @@ static void Led_Task(void *parameter) {
redrawProgress = true;
}
// Single-LED: led indicates between gradient green (beginning) => red (end)
// Multiple-LED: growing number of leds indicate between gradient green (beginning) => red (end)
if (!gPlayProperties.isWebstream) {
if (gPlayProperties.currentRelPos != lastPos || redrawProgress) {
redrawProgress = false;
lastPos = gPlayProperties.currentRelPos;
uint8_t numLedsToLight = map(gPlayProperties.currentRelPos, 0, 98, 0, NUM_LEDS);
FastLED.clear();
if (NUM_LEDS == 1) {
leds[0].setHue((uint8_t)(85 - ((double)90 / 100) * (double)gPlayProperties.currentRelPos));
} else {
uint8_t numLedsToLight = map(gPlayProperties.currentRelPos, 0, 98, 0, NUM_LEDS);
for (uint8_t led = 0; led < numLedsToLight; led++) {
if (System_AreControlsLocked()) {
leds[Led_Address(led)] = CRGB::Red;
} else if (!gPlayProperties.pausePlay) { // Hue-rainbow
leds[Led_Address(led)].setHue((uint8_t)(85 - ((double)95 / NUM_LEDS) * led));
leds[Led_Address(led)].setHue((uint8_t)(85 - ((double)90 / NUM_LEDS) * led));
}
}
}
if (gPlayProperties.pausePlay) {
leds[Led_Address(0)] = CRGB::Orange;
if (NUM_LEDS > 1) {
leds[(Led_Address(NUM_LEDS / 4)) % NUM_LEDS] = CRGB::Orange;
leds[(Led_Address(NUM_LEDS / 2)) % NUM_LEDS] = CRGB::Orange;
leds[(Led_Address(NUM_LEDS / 4 * 3)) % NUM_LEDS] = CRGB::Orange;
}
break;
}
}
@ -501,17 +612,26 @@ static void Led_Task(void *parameter) {
}
if (System_AreControlsLocked()) {
leds[Led_Address(ledPosWebstream)] = CRGB::Red;
if (NUM_LEDS > 1) {
leds[(Led_Address(ledPosWebstream) + NUM_LEDS / 2) % NUM_LEDS] = CRGB::Red;
}
} else if (!gPlayProperties.pausePlay) {
if (NUM_LEDS == 1) {
leds[0].setHue(webstreamColor++);
} else {
leds[Led_Address(ledPosWebstream)].setHue(webstreamColor);
leds[(Led_Address(ledPosWebstream) + NUM_LEDS / 2) % NUM_LEDS].setHue(webstreamColor++);
} else if (gPlayProperties.pausePlay)
{
}
} else if (gPlayProperties.pausePlay) {
if (NUM_LEDS == 1) {
leds[0] = CRGB::Orange;
} else {
leds[Led_Address(ledPosWebstream)] = CRGB::Orange;
leds[(Led_Address(ledPosWebstream) + NUM_LEDS / 2) % NUM_LEDS] = CRGB::Orange;
}
}
}
}
FastLED.show();
vTaskDelay(portTICK_RATE_MS * 5);
}

2
src/revision.h

@ -1,4 +1,4 @@
#ifndef __REVISION_H__
#define __REVISION_H__
constexpr const char softwareRevision[] PROGMEM = "Software-revision: 20210816-2";
constexpr const char softwareRevision[] PROGMEM = "Software-revision: 20210911-1";
#endif
Loading…
Cancel
Save