Merge branch 'animation' into 'master'
insert animation See merge request lukas/ledstripinterface!2
This commit is contained in:
		
							
								
								
									
										169
									
								
								src/Clock.cpp
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								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,33 +58,40 @@ void Clock::refreshTime() {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (animator.animationActive()) {
 | 
			
		||||
    animator.stopLoadAnimation();
 | 
			
		||||
    strip.clear();
 | 
			
		||||
 | 
			
		||||
    // only add on first time iteration
 | 
			
		||||
    paintAlwaysOnLeds();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tm* loctime = localtime(&now);
 | 
			
		||||
 | 
			
		||||
  const uint8_t hour = loctime->tm_hour;
 | 
			
		||||
  const uint8_t minute = loctime->tm_min;
 | 
			
		||||
 | 
			
		||||
  // enable night brighntess at 21' and disable it at 6'
 | 
			
		||||
  if (hour >= 22 || hour <= 6) {
 | 
			
		||||
    strip.setBrightness(NIGHTBRIGHTNESS);
 | 
			
		||||
  } else {
 | 
			
		||||
    strip.setBrightness(DAYBRIGHTNESS);
 | 
			
		||||
  bool daybrightness = !(hour >= 22 || hour <= 6);
 | 
			
		||||
 | 
			
		||||
  if (oldDayBrightness != daybrightness) {
 | 
			
		||||
    strip.setBrightness(daybrightness ? DAYBRIGHTNESS : NIGHTBRIGHTNESS);
 | 
			
		||||
    paintAlwaysOnLeds();
 | 
			
		||||
 | 
			
		||||
    oldDayBrightness = 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 +113,38 @@ 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));
 | 
			
		||||
 | 
			
		||||
  // print the minute words and the corresponding after/before half words
 | 
			
		||||
  printMinutes(minuteselector, twentyAfterSyntax);
 | 
			
		||||
 | 
			
		||||
  // uhr
 | 
			
		||||
  if (minuteselector == 0 || alwaysClockWord)
 | 
			
		||||
    printWord(types::uhr, Adafruit_NeoPixel::Color(255, 0, 0));
 | 
			
		||||
    oldhourWord = hourWord;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
void Clock::printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax) {
 | 
			
		||||
  // print the minute words and the corresponding after/before half words
 | 
			
		||||
  printMinutes(minuteselector, twas);
 | 
			
		||||
 | 
			
		||||
  // uhr
 | 
			
		||||
  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 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;
 | 
			
		||||
@@ -123,37 +152,46 @@ void Clock::printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax) {
 | 
			
		||||
    minuteWord = types::viertel;
 | 
			
		||||
  else if (minuteSelector == 9)
 | 
			
		||||
    minuteWord = types::dreiviertel;
 | 
			
		||||
  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, oldDayBrightness;
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
 
 | 
			
		||||
@@ -44,3 +44,6 @@ void LoadAnimator::animationStep() {
 | 
			
		||||
  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
 | 
			
		||||
		Reference in New Issue
	
	Block a user