add a writing animation of words
This commit is contained in:
parent
e0cbb4acb6
commit
3c22de49c7
151
src/Clock.cpp
151
src/Clock.cpp
@ -30,13 +30,21 @@ void Clock::turnOn() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Clock::paintAlwaysOnLeds() {
|
void Clock::paintAlwaysOnLeds() {
|
||||||
printWord(types::es, Adafruit_NeoPixel::Color(255, 255, 0));
|
addque.push_back(Word(types::es, 0xFFFF00));
|
||||||
printWord(types::ist, Adafruit_NeoPixel::Color(255, 0, 255));
|
addque.push_back(Word(types::ist, 0xFF00FF));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clock::printWord(const std::vector<uint8_t>& word, uint32_t color) {
|
void Clock::printWord(const std::vector<uint8_t>& word, uint32_t color, bool highlightfirst) {
|
||||||
for (const uint8_t i : word) {
|
uint r = (color >> 16) & 0xFF;
|
||||||
strip.setPixelColor(i, color);
|
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,9 +58,14 @@ void Clock::refreshTime() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (animator.animationActive()) {
|
||||||
animator.stopLoadAnimation();
|
animator.stopLoadAnimation();
|
||||||
strip.clear();
|
strip.clear();
|
||||||
|
|
||||||
|
// only add on first time iteration
|
||||||
|
paintAlwaysOnLeds();
|
||||||
|
}
|
||||||
|
|
||||||
tm* loctime = localtime(&now);
|
tm* loctime = localtime(&now);
|
||||||
|
|
||||||
const uint8_t hour = loctime->tm_hour;
|
const uint8_t hour = loctime->tm_hour;
|
||||||
@ -65,18 +78,17 @@ void Clock::refreshTime() {
|
|||||||
strip.setBrightness(DAYBRIGHTNESS);
|
strip.setBrightness(DAYBRIGHTNESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
paintAlwaysOnLeds();
|
|
||||||
setTime(hour, minute, this->twentyAfterSyntax, this->clockAlwaysOn);
|
setTime(hour, minute, this->twentyAfterSyntax, this->clockAlwaysOn);
|
||||||
|
|
||||||
strip.show();
|
strip.show();
|
||||||
Serial.printf("Time now: %uh %uM\n", hour, minute);
|
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;
|
const uint8_t minuteselector = minute / 5;
|
||||||
|
|
||||||
// if minuteselector >= 4 +1 to hour
|
// if minuteselector >= 4 +1 to hour
|
||||||
if (twentyAfterSyntax ? minuteselector >= 5 : minuteselector >= 4)
|
if (twas ? minuteselector >= 5 : minuteselector >= 4)
|
||||||
hour++;
|
hour++;
|
||||||
|
|
||||||
// convert to 12h format
|
// 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
|
: hour == 0 || hour == 12 ? types::zwoelf
|
||||||
: hourWord;
|
: 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
|
// print the minute words and the corresponding after/before half words
|
||||||
printMinutes(minuteselector, twentyAfterSyntax);
|
printMinutes(minuteselector, twas);
|
||||||
|
|
||||||
// uhr
|
// uhr
|
||||||
if (minuteselector == 0 || alwaysClockWord)
|
bool uhractive = minuteselector == 0 || alwaysClockWord;
|
||||||
printWord(types::uhr, Adafruit_NeoPixel::Color(255, 0, 0));
|
|
||||||
|
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
|
// 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) {
|
if (minuteSelector == 1 || minuteSelector == 5 || minuteSelector == 7 || minuteSelector == 11) {
|
||||||
minuteWord = types::fuenf;
|
minuteWord = types::fuenf;
|
||||||
} else if (minuteSelector == 2 || minuteSelector == 4 || minuteSelector == 8 || minuteSelector == 10) {
|
} else if (minuteSelector == 2 || minuteSelector == 4 || minuteSelector == 8 || minuteSelector == 10) {
|
||||||
// check if we use the twenty after syntax
|
// check if we use the twenty after syntax
|
||||||
if ((minuteSelector == 4 || minuteSelector == 8) && twentyAfterSyntax)
|
if ((minuteSelector == 4 || minuteSelector == 8) && twas)
|
||||||
minuteWord = types::zwanzig;
|
minuteWord = types::zwanzig;
|
||||||
else
|
else
|
||||||
minuteWord = types::zehn;
|
minuteWord = types::zehn;
|
||||||
@ -126,34 +153,45 @@ void Clock::printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax) {
|
|||||||
else if (minuteSelector == 6)
|
else if (minuteSelector == 6)
|
||||||
minuteWord = types::halb;
|
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
|
// vor / nach
|
||||||
std::vector<uint8_t> vornachWord;
|
|
||||||
if (minuteSelector == 1 || minuteSelector == 2 || minuteSelector == 3 ||
|
if (minuteSelector == 1 || minuteSelector == 2 || minuteSelector == 3 ||
|
||||||
((minuteSelector == 8) &&
|
((minuteSelector == 8) && !twas) || // check if twentyafter syntax is enabled - if not display the the after
|
||||||
!twentyAfterSyntax) || // check if twentyafter syntax is enabled - if not display the the after
|
|
||||||
minuteSelector == 7 ||
|
minuteSelector == 7 ||
|
||||||
((minuteSelector == 4) &&
|
((minuteSelector == 4) && twas)) // check if twentyafter syntax is enabled - if yes display the the after
|
||||||
twentyAfterSyntax)) // check if twentyafter syntax is enabled - if yes display the the after
|
|
||||||
vornachWord = types::nach;
|
vornachWord = types::nach;
|
||||||
else if (minuteSelector == 5 ||
|
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 == 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;
|
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
|
// halb
|
||||||
if (minuteSelector >= 4 && minuteSelector <= 8) {
|
if (minuteSelector >= 4 && minuteSelector <= 8) {
|
||||||
// only 3 times if twentyafter syntax is on
|
// only 3 times if twentyafter syntax is on
|
||||||
if (!twentyAfterSyntax || (minuteSelector >= 5 && minuteSelector <= 7))
|
if (!twas || (minuteSelector >= 5 && minuteSelector <= 7))
|
||||||
printWord(types::halb, Adafruit_NeoPixel::Color(255, 0, 0));
|
halfActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldhalfActive != halfActive) {
|
||||||
|
(halfActive ? addque : delque).push_back(Word(types::halb, 0xFF0000));
|
||||||
|
oldhalfActive = halfActive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clock::useTwentyAfterSyntax(bool twentyAFterSyntax) {
|
void Clock::useTwentyAfterSyntax(bool twas) {
|
||||||
this->twentyAfterSyntax = twentyAFterSyntax;
|
this->twentyAfterSyntax = twas;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clock::useAlwaysOnUhrSyntax(bool alwaysOnUhr) {
|
void Clock::useAlwaysOnUhrSyntax(bool alwaysOnUhr) {
|
||||||
@ -164,3 +202,60 @@ void Clock::update() {
|
|||||||
if (refreshTicker.active())
|
if (refreshTicker.active())
|
||||||
this->refreshTime();
|
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 "Arduino.h"
|
||||||
#include <Ticker.h>
|
#include <Ticker.h>
|
||||||
#include "Adafruit_NeoPixel.h"
|
#include "Adafruit_NeoPixel.h"
|
||||||
#include "Arduino.h"
|
|
||||||
#include "LoadAnimator.h"
|
#include "LoadAnimator.h"
|
||||||
|
#include "Word.h"
|
||||||
|
|
||||||
// define the strip length of the wordclock
|
// define the strip length of the wordclock
|
||||||
#define NUMPIXELS 108
|
#define NUMPIXELS 108
|
||||||
@ -24,6 +24,13 @@ class Clock {
|
|||||||
Adafruit_NeoPixel strip{};
|
Adafruit_NeoPixel strip{};
|
||||||
LoadAnimator animator;
|
LoadAnimator animator;
|
||||||
Ticker refreshTicker;
|
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 twentyAfterSyntax;
|
||||||
bool clockAlwaysOn;
|
bool clockAlwaysOn;
|
||||||
@ -33,12 +40,15 @@ class Clock {
|
|||||||
*/
|
*/
|
||||||
void paintAlwaysOnLeds();
|
void paintAlwaysOnLeds();
|
||||||
|
|
||||||
|
std::vector<uint8_t> minuteBefore;
|
||||||
|
void performWordTransition();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* paint a specific word
|
* paint a specific word
|
||||||
* @param word word pointer to print
|
* @param word word pointer to print
|
||||||
* @param color the color in which to print it
|
* @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
|
* logic to print the correct minute word and its corresponding wods
|
||||||
|
@ -44,3 +44,6 @@ void LoadAnimator::animationStep() {
|
|||||||
nroo = nro;
|
nroo = nro;
|
||||||
nro = nr;
|
nro = nr;
|
||||||
}
|
}
|
||||||
|
bool LoadAnimator::animationActive() {
|
||||||
|
return timer.active();
|
||||||
|
}
|
||||||
|
@ -32,6 +32,8 @@ class LoadAnimator {
|
|||||||
* stop the animation
|
* stop the animation
|
||||||
*/
|
*/
|
||||||
void stopLoadAnimation();
|
void stopLoadAnimation();
|
||||||
|
|
||||||
|
bool animationActive();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LEDSTRIPINTERFACE_LOADANIMATOR_H
|
#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