 64fd207533
			
		
	
	64fd207533
	
	
	
		
			
			- effect functions no longer part of class - methods to access private members - separate Segment, Segment_runtime, ColorTransition from WS2812FX
		
			
				
	
	
		
			159 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| #include "TFTs.h"
 | |
| #include "wled.h"
 | |
| 
 | |
| //Large parts of the code are from https://github.com/SmittyHalibut/EleksTubeHAX
 | |
| 
 | |
| class ElekstubeIPSUsermod : public Usermod {
 | |
|   private:
 | |
|     // strings to reduce flash memory usage (used more than twice)
 | |
|     static const char _name[];
 | |
|     static const char _tubeSeg[];
 | |
|     static const char _digitOffset[];
 | |
| 
 | |
|     char cronixieDisplay[7] = "HHMMSS";
 | |
| 
 | |
|     TFTs tfts;
 | |
|     void updateClockDisplay(TFTs::show_t show=TFTs::yes) {
 | |
|       bool set[6] = {false}; 
 | |
|       for (uint8_t i = 0; i<6; i++) {
 | |
|         char c = cronixieDisplay[i];
 | |
|         if (c >= '0' && c <= '9') {
 | |
|           tfts.setDigit(5-i, c - '0', show); set[i] = true;
 | |
|         } else if (c >= 'A' && c <= 'G') {
 | |
|           tfts.setDigit(5-i, c - 'A' + 10, show); set[i] = true; //10.bmp to 16.bmp static display
 | |
|         } else if (c == '-' || c == '_' || c == ' ') {
 | |
|           tfts.setDigit(5-i, 255, show); set[i] = true; //blank
 | |
|         } else {
 | |
|           set[i] = false; //display HHMMSS time
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       
 | |
|       uint8_t hr = hour(localTime);
 | |
|       uint8_t hrTens = hr/10;
 | |
|       uint8_t mi = minute(localTime);
 | |
|       uint8_t mittens = mi/10;
 | |
|       uint8_t s = second(localTime);
 | |
|       uint8_t sTens = s/10;
 | |
|       if (!set[0]) tfts.setDigit(HOURS_TENS, hrTens, show);
 | |
|       if (!set[1]) tfts.setDigit(HOURS_ONES, hr - hrTens*10, show);
 | |
|       if (!set[2]) tfts.setDigit(MINUTES_TENS, mittens, show);
 | |
|       if (!set[3]) tfts.setDigit(MINUTES_ONES, mi - mittens*10, show);
 | |
|       if (!set[4]) tfts.setDigit(SECONDS_TENS, sTens, show);
 | |
|       if (!set[5]) tfts.setDigit(SECONDS_ONES, s - sTens*10, show);
 | |
|     }
 | |
|     unsigned long lastTime = 0;
 | |
|   public:
 | |
| 
 | |
|     uint8_t lastBri;
 | |
|     uint32_t lastCols[6];
 | |
|     TFTs::show_t fshow=TFTs::yes;
 | |
| 
 | |
|     void setup() {
 | |
|       tfts.begin();
 | |
|       tfts.fillScreen(TFT_BLACK);
 | |
| 
 | |
|       for (int8_t i = 5; i >= 0; i--) {
 | |
|         tfts.setDigit(i, 255, TFTs::force); //turn all off
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     void loop() {
 | |
|       if (!toki.isTick()) return;
 | |
|       updateLocalTime();
 | |
| 
 | |
|       Segment& seg1 = strip.getSegment(tfts.tubeSegment);
 | |
|       if (seg1.isActive()) {
 | |
|         bool update = false;
 | |
|         if (seg1.opacity != lastBri) update = true;
 | |
|         lastBri = seg1.opacity;
 | |
|         for (uint8_t i = 0; i < 6; i++) {
 | |
|           uint32_t c = strip.getPixelColor(seg1.start + i);
 | |
|           if (c != lastCols[i]) update = true;
 | |
|           lastCols[i] = c;
 | |
|         }
 | |
|         if (update) fshow=TFTs::force;
 | |
|       } else if (lastCols[0] != 0) { // Segment 1 deleted
 | |
|         fshow=TFTs::force;
 | |
|         lastCols[0] = 0;
 | |
|       }
 | |
|       
 | |
|       updateClockDisplay(fshow);
 | |
|       fshow=TFTs::yes;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * addToConfig() (called from set.cpp) stores persistent properties to cfg.json
 | |
|      */
 | |
|     void addToConfig(JsonObject &root) {
 | |
|       // we add JSON object: {"EleksTubeIPS": {"tubeSegment": 1, "digitOffset": 0}}
 | |
|       JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
 | |
|       top[FPSTR(_tubeSeg)] = tfts.tubeSegment;
 | |
|       top[FPSTR(_digitOffset)] = tfts.digitOffset;
 | |
|       DEBUG_PRINTLN(F("EleksTube config saved."));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * readFromConfig() is called before setup() to populate properties from values stored in cfg.json
 | |
|      *
 | |
|      * The function should return true if configuration was successfully loaded or false if there was no configuration.
 | |
|      */
 | |
|     bool readFromConfig(JsonObject &root) {
 | |
|       // we look for JSON object: {"EleksTubeIPS": {"tubeSegment": 1, "digitOffset": 0}}
 | |
|       DEBUG_PRINT(FPSTR(_name));
 | |
| 
 | |
|       JsonObject top = root[FPSTR(_name)];
 | |
|       if (top.isNull()) {
 | |
|         DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|       tfts.tubeSegment = top[FPSTR(_tubeSeg)] | tfts.tubeSegment;
 | |
|       uint8_t digitOffsetPrev = tfts.digitOffset;
 | |
|       tfts.digitOffset = top[FPSTR(_digitOffset)] | tfts.digitOffset;
 | |
|       if (tfts.digitOffset > 240) tfts.digitOffset = 240;
 | |
|       if (tfts.digitOffset != digitOffsetPrev) fshow=TFTs::force;
 | |
| 
 | |
|       // use "return !top["newestParameter"].isNull();" when updating Usermod with new features
 | |
|       return !top[FPSTR(_digitOffset)].isNull();
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
 | |
|      * Values in the state object may be modified by connected clients
 | |
|      */
 | |
|     void addToJsonState(JsonObject& root)
 | |
|     {
 | |
|       root["nx"] = cronixieDisplay;
 | |
|       root[FPSTR(_digitOffset)] = tfts.digitOffset;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /*
 | |
|      * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
 | |
|      * Values in the state object may be modified by connected clients
 | |
|      */
 | |
|     void readFromJsonState(JsonObject& root)
 | |
|     {
 | |
|       if (root["nx"].is<const char*>()) {
 | |
|         strncpy(cronixieDisplay, root["nx"], 6);
 | |
|       }
 | |
| 
 | |
|       uint8_t digitOffsetPrev = tfts.digitOffset;
 | |
|       tfts.digitOffset = root[FPSTR(_digitOffset)] | tfts.digitOffset;
 | |
|       if (tfts.digitOffset > 240) tfts.digitOffset = 240;
 | |
|       if (tfts.digitOffset != digitOffsetPrev) fshow=TFTs::force;
 | |
|     }
 | |
| 
 | |
|     uint16_t getId()
 | |
|     {
 | |
|       return USERMOD_ID_ELEKSTUBE_IPS;
 | |
|     }
 | |
| };
 | |
| 
 | |
| // strings to reduce flash memory usage (used more than twice)
 | |
| const char ElekstubeIPSUsermod::_name[]         PROGMEM = "EleksTubeIPS";
 | |
| const char ElekstubeIPSUsermod::_tubeSeg[]      PROGMEM = "tubeSegment";
 | |
| const char ElekstubeIPSUsermod::_digitOffset[]  PROGMEM = "digitOffset";
 |