add a writing animation of words
This commit is contained in:
parent
e0cbb4acb6
commit
3c22de49c7
155
src/Clock.cpp
155
src/Clock.cpp
@ -30,13 +30,21 @@ void Clock::turnOn() {
|
||||
}
|
||||
|
||||
void Clock::paintAlwaysOnLeds() {
|
||||
printWord(types::es, Adafruit_NeoPixel::Color(255, 255, 0));
|
||||
printWord(types::ist, Adafruit_NeoPixel::Color(255, 0, 255));
|
||||
addque.push_back(Word(types::es, 0xFFFF00));
|
||||
addque.push_back(Word(types::ist, 0xFF00FF));
|
||||
}
|
||||
|
||||
void Clock::printWord(const std::vector<uint8_t>& word, uint32_t color) {
|
||||
for (const uint8_t i : word) {
|
||||
strip.setPixelColor(i, color);
|
||||
void Clock::printWord(const std::vector<uint8_t>& word, uint32_t color, bool highlightfirst) {
|
||||
uint r = (color >> 16) & 0xFF;
|
||||
uint g = (color >> 8) & 0xFF;
|
||||
uint b = (color)&0xFF;
|
||||
|
||||
for (const uint8_t& i : word) {
|
||||
strip.setPixelColor(
|
||||
i,
|
||||
!highlightfirst || (&i == &word.back())
|
||||
? color
|
||||
: (((r > 200 ? r - 200 : r) << 16) | ((g > 200 ? g - 200 : g) << 8) | (b > 200 ? b - 200 : b)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,8 +58,13 @@ void Clock::refreshTime() {
|
||||
return;
|
||||
}
|
||||
|
||||
animator.stopLoadAnimation();
|
||||
strip.clear();
|
||||
if (animator.animationActive()) {
|
||||
animator.stopLoadAnimation();
|
||||
strip.clear();
|
||||
|
||||
// only add on first time iteration
|
||||
paintAlwaysOnLeds();
|
||||
}
|
||||
|
||||
tm* loctime = localtime(&now);
|
||||
|
||||
@ -65,18 +78,17 @@ void Clock::refreshTime() {
|
||||
strip.setBrightness(DAYBRIGHTNESS);
|
||||
}
|
||||
|
||||
paintAlwaysOnLeds();
|
||||
setTime(hour, minute, this->twentyAfterSyntax, this->clockAlwaysOn);
|
||||
|
||||
strip.show();
|
||||
Serial.printf("Time now: %uh %uM\n", hour, minute);
|
||||
}
|
||||
|
||||
void Clock::setTime(uint8_t hour, uint8_t minute, bool twentyAfterSyntax, bool alwaysClockWord) {
|
||||
void Clock::setTime(uint8_t hour, uint8_t minute, bool twas, bool alwaysClockWord) {
|
||||
const uint8_t minuteselector = minute / 5;
|
||||
|
||||
// if minuteselector >= 4 +1 to hour
|
||||
if (twentyAfterSyntax ? minuteselector >= 5 : minuteselector >= 4)
|
||||
if (twas ? minuteselector >= 5 : minuteselector >= 4)
|
||||
hour++;
|
||||
|
||||
// convert to 12h format
|
||||
@ -98,24 +110,39 @@ void Clock::setTime(uint8_t hour, uint8_t minute, bool twentyAfterSyntax, bool a
|
||||
: hour == 0 || hour == 12 ? types::zwoelf
|
||||
: hourWord;
|
||||
|
||||
printWord(hourWord, Adafruit_NeoPixel::Color(0, 255, 255));
|
||||
if (oldhourWord != hourWord) {
|
||||
addque.push_back(Word(hourWord, 0x00FFFF));
|
||||
delque.push_back(Word(oldhourWord, 0x00FFFF));
|
||||
|
||||
oldhourWord = hourWord;
|
||||
}
|
||||
// printWord(hourWord, Adafruit_NeoPixel::Color(0, 255, 255));
|
||||
|
||||
// print the minute words and the corresponding after/before half words
|
||||
printMinutes(minuteselector, twentyAfterSyntax);
|
||||
printMinutes(minuteselector, twas);
|
||||
|
||||
// uhr
|
||||
if (minuteselector == 0 || alwaysClockWord)
|
||||
printWord(types::uhr, Adafruit_NeoPixel::Color(255, 0, 0));
|
||||
bool uhractive = minuteselector == 0 || alwaysClockWord;
|
||||
|
||||
if (oldUhrActive != uhractive) {
|
||||
const Word wrd = Word(types::uhr, 0xFF0000);
|
||||
(uhractive ? addque : delque).push_back(wrd);
|
||||
oldUhrActive = uhractive;
|
||||
}
|
||||
|
||||
performWordTransition();
|
||||
}
|
||||
|
||||
void Clock::printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax) {
|
||||
void Clock::printMinutes(uint8_t minuteSelector, bool twas) {
|
||||
// fuenf / zehn / viertl word
|
||||
std::vector<uint8_t> minuteWord;
|
||||
std::vector<uint8_t> minuteWord, vornachWord;
|
||||
bool halfActive = false;
|
||||
|
||||
if (minuteSelector == 1 || minuteSelector == 5 || minuteSelector == 7 || minuteSelector == 11) {
|
||||
minuteWord = types::fuenf;
|
||||
} else if (minuteSelector == 2 || minuteSelector == 4 || minuteSelector == 8 || minuteSelector == 10) {
|
||||
// check if we use the twenty after syntax
|
||||
if ((minuteSelector == 4 || minuteSelector == 8) && twentyAfterSyntax)
|
||||
if ((minuteSelector == 4 || minuteSelector == 8) && twas)
|
||||
minuteWord = types::zwanzig;
|
||||
else
|
||||
minuteWord = types::zehn;
|
||||
@ -126,34 +153,45 @@ void Clock::printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax) {
|
||||
else if (minuteSelector == 6)
|
||||
minuteWord = types::halb;
|
||||
|
||||
printWord(minuteWord, Adafruit_NeoPixel::Color(0, 255, 0));
|
||||
if (oldminuteWord != minuteWord) {
|
||||
addque.push_back(Word(minuteWord, 0x00FF00));
|
||||
delque.push_back(Word(oldminuteWord, 0x00FF00));
|
||||
oldminuteWord = minuteWord;
|
||||
}
|
||||
|
||||
// vor / nach
|
||||
std::vector<uint8_t> vornachWord;
|
||||
if (minuteSelector == 1 || minuteSelector == 2 || minuteSelector == 3 ||
|
||||
((minuteSelector == 8) &&
|
||||
!twentyAfterSyntax) || // check if twentyafter syntax is enabled - if not display the the after
|
||||
((minuteSelector == 8) && !twas) || // check if twentyafter syntax is enabled - if not display the the after
|
||||
minuteSelector == 7 ||
|
||||
((minuteSelector == 4) &&
|
||||
twentyAfterSyntax)) // check if twentyafter syntax is enabled - if yes display the the after
|
||||
((minuteSelector == 4) && twas)) // check if twentyafter syntax is enabled - if yes display the the after
|
||||
vornachWord = types::nach;
|
||||
else if (minuteSelector == 5 ||
|
||||
((minuteSelector == 4) && !twentyAfterSyntax) // check if twentyafter enabled if not -- display vor
|
||||
((minuteSelector == 4) && !twas) // check if twentyafter enabled if not -- display vor
|
||||
|| minuteSelector == 10 || minuteSelector == 11 ||
|
||||
((minuteSelector == 8) && twentyAfterSyntax)) // check if twentyafter enabled if yess -- display vor
|
||||
((minuteSelector == 8) && twas)) // check if twentyafter enabled if yess -- display vor
|
||||
vornachWord = types::vor;
|
||||
printWord(vornachWord, Adafruit_NeoPixel::Color(255, 255, 255));
|
||||
|
||||
if (oldvornachWord != vornachWord) {
|
||||
addque.push_back(Word(vornachWord, 0xFFFFFF));
|
||||
delque.push_back(Word(oldvornachWord, 0xFFFFFF));
|
||||
oldvornachWord = vornachWord;
|
||||
}
|
||||
|
||||
// halb
|
||||
if (minuteSelector >= 4 && minuteSelector <= 8) {
|
||||
// only 3 times if twentyafter syntax is on
|
||||
if (!twentyAfterSyntax || (minuteSelector >= 5 && minuteSelector <= 7))
|
||||
printWord(types::halb, Adafruit_NeoPixel::Color(255, 0, 0));
|
||||
if (!twas || (minuteSelector >= 5 && minuteSelector <= 7))
|
||||
halfActive = true;
|
||||
}
|
||||
|
||||
if (oldhalfActive != halfActive) {
|
||||
(halfActive ? addque : delque).push_back(Word(types::halb, 0xFF0000));
|
||||
oldhalfActive = halfActive;
|
||||
}
|
||||
}
|
||||
|
||||
void Clock::useTwentyAfterSyntax(bool twentyAFterSyntax) {
|
||||
this->twentyAfterSyntax = twentyAFterSyntax;
|
||||
void Clock::useTwentyAfterSyntax(bool twas) {
|
||||
this->twentyAfterSyntax = twas;
|
||||
}
|
||||
|
||||
void Clock::useAlwaysOnUhrSyntax(bool alwaysOnUhr) {
|
||||
@ -164,3 +202,60 @@ void Clock::update() {
|
||||
if (refreshTicker.active())
|
||||
this->refreshTime();
|
||||
}
|
||||
|
||||
int it = 0;
|
||||
void Clock::performWordTransition() {
|
||||
if (addque.empty() && delque.empty())
|
||||
return;
|
||||
|
||||
int maxdels = 0;
|
||||
for (const Word& el : delque) {
|
||||
if (el.wrd.size() > maxdels) {
|
||||
maxdels = el.wrd.size();
|
||||
}
|
||||
}
|
||||
|
||||
int maxadds = 0;
|
||||
for (const Word& el : addque) {
|
||||
if (el.wrd.size() > maxadds) {
|
||||
maxadds = el.wrd.size();
|
||||
}
|
||||
}
|
||||
|
||||
// const uint iterationcount = maxdels + maxadds;
|
||||
|
||||
if (!transitionTicker.active()) {
|
||||
transitionTicker.attach_ms(150, [this, maxdels, maxadds]() {
|
||||
if (it <= maxdels) {
|
||||
for (Word word : delque) {
|
||||
if (word.wrd.size() < it)
|
||||
continue;
|
||||
|
||||
this->printWord(word.wrd, 0x0, false);
|
||||
this->printWord({word.wrd.begin(), word.wrd.end() - it}, word.color, false);
|
||||
}
|
||||
|
||||
this->strip.show();
|
||||
} else if (it - maxdels <= maxadds) {
|
||||
// we are modding the endword
|
||||
int idx = it - maxdels;
|
||||
for (Word word : addque) {
|
||||
if (word.wrd.size() < idx)
|
||||
continue;
|
||||
|
||||
this->printWord(word.wrd, 0x0, false);
|
||||
this->printWord({word.wrd.begin(), word.wrd.begin() + idx}, word.color, idx < word.wrd.size());
|
||||
}
|
||||
this->strip.show();
|
||||
} else {
|
||||
addque.clear();
|
||||
delque.clear();
|
||||
|
||||
transitionTicker.detach();
|
||||
it = 0;
|
||||
}
|
||||
|
||||
it++;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
14
src/Clock.h
14
src/Clock.h
@ -8,8 +8,8 @@
|
||||
#include "Arduino.h"
|
||||
#include <Ticker.h>
|
||||
#include "Adafruit_NeoPixel.h"
|
||||
#include "Arduino.h"
|
||||
#include "LoadAnimator.h"
|
||||
#include "Word.h"
|
||||
|
||||
// define the strip length of the wordclock
|
||||
#define NUMPIXELS 108
|
||||
@ -24,6 +24,13 @@ class Clock {
|
||||
Adafruit_NeoPixel strip{};
|
||||
LoadAnimator animator;
|
||||
Ticker refreshTicker;
|
||||
Ticker transitionTicker;
|
||||
|
||||
std::vector<Word> delque;
|
||||
std::vector<Word> addque;
|
||||
|
||||
std::vector<uint8_t> oldminuteWord, oldvornachWord, oldhourWord;
|
||||
bool oldhalfActive, oldUhrActive;
|
||||
|
||||
bool twentyAfterSyntax;
|
||||
bool clockAlwaysOn;
|
||||
@ -33,12 +40,15 @@ class Clock {
|
||||
*/
|
||||
void paintAlwaysOnLeds();
|
||||
|
||||
std::vector<uint8_t> minuteBefore;
|
||||
void performWordTransition();
|
||||
|
||||
/**
|
||||
* paint a specific word
|
||||
* @param word word pointer to print
|
||||
* @param color the color in which to print it
|
||||
*/
|
||||
void printWord(const std::vector<uint8_t>& word, uint32_t color);
|
||||
void printWord(const std::vector<uint8_t>& word, uint32_t color, bool highlightfirst);
|
||||
|
||||
/**
|
||||
* logic to print the correct minute word and its corresponding wods
|
||||
|
@ -43,4 +43,7 @@ void LoadAnimator::animationStep() {
|
||||
nrooo = nroo;
|
||||
nroo = nro;
|
||||
nro = nr;
|
||||
}
|
||||
}
|
||||
bool LoadAnimator::animationActive() {
|
||||
return timer.active();
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ class LoadAnimator {
|
||||
* stop the animation
|
||||
*/
|
||||
void stopLoadAnimation();
|
||||
|
||||
bool animationActive();
|
||||
};
|
||||
|
||||
#endif // LEDSTRIPINTERFACE_LOADANIMATOR_H
|
||||
|
10
src/Word.cpp
Normal file
10
src/Word.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by lukas on 31.01.22.
|
||||
//
|
||||
|
||||
#include "Word.h"
|
||||
|
||||
#include <utility>
|
||||
Word::Word(std::vector<uint8_t> wrd, uint32_t color) : wrd(std::move(wrd)), color(color) {
|
||||
|
||||
}
|
19
src/Word.h
Normal file
19
src/Word.h
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by lukas on 31.01.22.
|
||||
//
|
||||
|
||||
#ifndef LEDSTRIPINTERFACE_WORD_H
|
||||
#define LEDSTRIPINTERFACE_WORD_H
|
||||
|
||||
#include <Ticker.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
class Word {
|
||||
public:
|
||||
std::vector<uint8_t> wrd;
|
||||
uint32_t color;
|
||||
|
||||
Word(std::vector<uint8_t> wrd, uint32_t color);
|
||||
};
|
||||
|
||||
#endif // LEDSTRIPINTERFACE_WORD_H
|
Loading…
Reference in New Issue
Block a user