diff --git a/Dashboard/Dashboard.ino b/Dashboard/Dashboard.ino index c87e1e13205804d88e54dcb86cb3a67f96a9cfad..ef08d6ffef8bbe0114f66d0ddc79fe7bf339c1e5 100644 --- a/Dashboard/Dashboard.ino +++ b/Dashboard/Dashboard.ino @@ -45,10 +45,12 @@ /*******MHZ19 CO2 library********/ #include <MHZ19_uart.h> +MHZ19_uart co2; /********************************/ /**********RTC library***********/ #include <microDS3231.h> +MicroDS3231 rtc; /********************************/ /*************EEPROM*************/ @@ -62,6 +64,7 @@ // | 5 | Wake up minute | // | 6 | Pomodoro work minutes | // | 7 | Pomodoro break minutes | +// | 8 | Matrix Brightness | /********************************/ /*************Marcos*************/ @@ -77,13 +80,12 @@ union Arg const void *v; }; - // Screen entity with transition table struct Screen { void (*func)(const Arg *); const Arg arg; - void (*funcPrepare)(void); + void (*funcPrepare)(mData* buffer); const uint8_t nextScreen0; const uint8_t nextScreen1; const uint8_t nextScreen2; @@ -110,6 +112,7 @@ enum PANEL_ORIENTATION : uint8_t // Special key, which helps to validate EEPROM data const uint8_t special_key = 0b11011100; // Just a random number (it's actually the voltage from the outlet) +// Import configs #include "config.h" #include "configScreens.h" @@ -123,6 +126,7 @@ struct ANIMATION animation : 3; // The way to animate uint8_t prepare : 2; // 0 — Draw current screen; 1 — Call prepare function; 2 — Animate mData leds[NUMLEDS]; // Additional buffer for animations + uint8_t brightness; // Matrix brightness // Service uint32_t timer; // Global timer for screens @@ -171,17 +175,21 @@ struct uint8_t wakeupMinute : 6; } globalVars; -microLED<NUMLEDS, LEDsPin, MLED_NO_CLOCK, MODEL, CLI_AVER - #if(DEBUG) - , SAVE_MILLIS - #endif - > matrix(WIDTH, HEIGHT, CONNECTION_TYPE, CORNER, DIRECTION); +// Init matrix +#if(DEBUG) +microLED<NUMLEDS, LEDsPin, MLED_NO_CLOCK, MODEL, CLI_AVER, SAVE_MILLIS> matrix(WIDTH, HEIGHT, CONNECTION_TYPE, CORNER, DIRECTION); +#else +microLED<NUMLEDS, LEDsPin, MLED_NO_CLOCK, MODEL, CLI_AVER> matrix(WIDTH, HEIGHT, CONNECTION_TYPE, CORNER, DIRECTION); +#endif + +// Textbox #include "textbox.h" textbox tb; + +// Screens #include "screens.h" -MHZ19_uart co2; -MicroDS3231 rtc; +// Extern system timer extern volatile uint32_t timer0_overflow_count; extern volatile uint32_t timer0_millis; @@ -283,12 +291,37 @@ void buttons(uint8_t resetTimers = 0) } } +// Check sleep time +void checkSleep(DateTime* DT) +{ + if(globalVars.noAutoChangeScreen) globalVars.sleep = false; + else if ((globalVars.sleepHour > globalVars.wakeupHour) || + ((globalVars.sleepHour == globalVars.wakeupHour) && + (globalVars.sleepMinute >= globalVars.wakeupMinute))) + { + globalVars.sleep = (((DT->hour > globalVars.sleepHour) || + ((DT->hour == globalVars.sleepHour) && + (DT->minute >= globalVars.sleepMinute))) || + ((DT->hour < globalVars.wakeupHour) || + ((DT->hour == globalVars.wakeupHour) && + (DT->minute < globalVars.wakeupMinute)))); + } + else + { + globalVars.sleep = (((DT->hour > globalVars.sleepHour) || + ((DT->hour == globalVars.sleepHour) && + (DT->minute >= globalVars.sleepMinute))) && + ((DT->hour < globalVars.wakeupHour) || + ((DT->hour == globalVars.wakeupHour) && + (DT->minute < globalVars.wakeupMinute)))); + } +} + void setup() { // Hardware init pinMode(LBTN, INPUT); pinMode(RBTN, INPUT); - matrix.setBrightness(100); matrix.clear(); matrix.show(); co2.begin(CO2TX, CO2RX); @@ -301,7 +334,7 @@ void setup() // Reading settings from nonvolatile memory uint8_t eepromData, i; - for(i = 0; i <= 7; i++) + for(i = 0; i <= 8; i++) { eepromData = EEPROM.read(i); switch(i) @@ -333,48 +366,48 @@ void setup() // Sleep case 2: { - if(((eepromData & 0b11100000) == (special_key & 0b11100000)) && ((eepromData & 0b00011111) < 24)) + if(((eepromData & 0b11100000) == (special_key & 0b11100000)) && ((eepromData & 0b00011111) < 24) && !globalVars.unpreparedEEPROM) globalVars.sleepHour = eepromData & 0b00011111; else { - EEPROM.write(i, (eepromData & 0b11100000) | SLEEPHOUR); + EEPROM.write(i, (special_key & 0b11100000) | SLEEPHOUR); globalVars.sleepHour = SLEEPHOUR; globalVars.unpreparedEEPROM = true; } } break; - case 4: + // Wake up + case 3: { - if(((eepromData & 0b11100000) == (special_key & 0b11100000)) && ((eepromData & 0b00011111) < 24)) - globalVars.wakeupHour = eepromData & 0b00011111; + if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60) && !globalVars.unpreparedEEPROM) + globalVars.sleepMinute = eepromData & 0b00111111; else { - EEPROM.write(i, (eepromData & 0b11100000) | WAKEUPHOUR); - globalVars.wakeupHour = WAKEUPHOUR; + EEPROM.write(i, (special_key & 0b11000000) | SLEEPMINUTE); + globalVars.sleepMinute = SLEEPMINUTE; globalVars.unpreparedEEPROM = true; } } break; - // Wake up - case 3: + case 4: { - if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60)) - globalVars.sleepMinute = eepromData & 0b00111111; + if(((eepromData & 0b11100000) == (special_key & 0b11100000)) && ((eepromData & 0b00011111) < 24) && !globalVars.unpreparedEEPROM) + globalVars.wakeupHour = eepromData & 0b00011111; else { - EEPROM.write(i, (eepromData & 0b11000000) | SLEEPMINUTE); - globalVars.sleepMinute = SLEEPMINUTE; + EEPROM.write(i, (special_key & 0b11100000) | WAKEUPHOUR); + globalVars.wakeupHour = WAKEUPHOUR; globalVars.unpreparedEEPROM = true; } } break; case 5: { - if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60)) + if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60) && !globalVars.unpreparedEEPROM) globalVars.wakeupMinute = eepromData & 0b00111111; else { - EEPROM.write(i, (eepromData & 0b11000000) | WAKEUPMINUTE); + EEPROM.write(i, (special_key & 0b11000000) | WAKEUPMINUTE); globalVars.wakeupMinute = WAKEUPMINUTE; globalVars.unpreparedEEPROM = true; } @@ -383,11 +416,11 @@ void setup() // Pomodoro minutes case 6: { - if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60)) + if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60) && !globalVars.unpreparedEEPROM) globalVars.pomodoroSavedWork = eepromData & 0b00111111; else { - EEPROM.write(i, (eepromData & 0b11000000) | POMODORO_WORK); + EEPROM.write(i, (special_key & 0b11000000) | POMODORO_WORK); globalVars.pomodoroSavedWork = POMODORO_WORK; globalVars.unpreparedEEPROM = true; } @@ -395,19 +428,34 @@ void setup() break; case 7: { - if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60)) + if(((eepromData & 0b11000000) == (special_key & 0b11000000)) && ((eepromData & 0b00111111) < 60) && !globalVars.unpreparedEEPROM) globalVars.pomodoroSavedBreak = eepromData & 0b00111111; else { - EEPROM.write(i, (eepromData & 0b11000000) | POMODORO_BREAK); + EEPROM.write(i, (special_key & 0b11000000) | POMODORO_BREAK); globalVars.pomodoroSavedBreak = POMODORO_BREAK; globalVars.unpreparedEEPROM = true; } } break; + // Brightness + case 8: + { + if(!globalVars.unpreparedEEPROM) + globalVars.brightness = eepromData; + else + { + globalVars.brightness = BRIGHTNESS; + EEPROM.write(i, BRIGHTNESS); + globalVars.unpreparedEEPROM = true; + } + } + break; } } + // Set brightness + matrix.setBrightness(globalVars.brightness); // Set start screen globalVars.currentScreen = startWith; // Start without animation @@ -422,31 +470,6 @@ void setup() delay(500); } -void checkSleep(DateTime* DT) -{ - if(globalVars.noAutoChangeScreen) globalVars.sleep = false; - else if ((globalVars.sleepHour > globalVars.wakeupHour) || - ((globalVars.sleepHour == globalVars.wakeupHour) && - (globalVars.sleepMinute >= globalVars.wakeupMinute))) - { - globalVars.sleep = (((DT->hour > globalVars.sleepHour) || - ((DT->hour == globalVars.sleepHour) && - (DT->minute >= globalVars.sleepMinute))) || - ((DT->hour < globalVars.wakeupHour) || - ((DT->hour == globalVars.wakeupHour) && - (DT->minute < globalVars.wakeupMinute)))); - } - else - { - globalVars.sleep = (((DT->hour > globalVars.sleepHour) || - ((DT->hour == globalVars.sleepHour) && - (DT->minute >= globalVars.sleepMinute))) && - ((DT->hour < globalVars.wakeupHour) || - ((DT->hour == globalVars.wakeupHour) && - (DT->minute < globalVars.wakeupMinute)))); - } -} - void loop() { // Terminate if buttuns are holded @@ -519,6 +542,7 @@ void loop() if(globalVars.seconds != DTtmp.second) { timer3 = millis(); + // Check sleep time checkSleep(&DTtmp); } globalVars.seconds = DTtmp.second; @@ -564,7 +588,7 @@ void loop() PRINTLN_DEBUG(globalVars.pomodoroSeconds); } - // Display + // Back to homeScreen after 30 seconds static uint32_t timer5 = 0; TIMER(timer5, 30000) { @@ -576,17 +600,22 @@ void loop() } } else globalVars.sleep = false; + + // Display switch(globalVars.prepare) { + // Prepare additional buffer case 1: PRINTLN_DEBUG(F("Prepared")); unhandle(); clearBuffer(&globalVars.leds[0]); - screens[globalVars.currentScreen].funcPrepare(); + screens[globalVars.currentScreen].funcPrepare(&globalVars.leds[0]); + // Animate case 2: PRINTLN_DEBUG(F("Animated")); animate(AN_FRAMES_DELAY); break; + // Draw screen case 0: PRINT_DEBUG(F("Screen ")); PRINT_DEBUG(globalVars.currentScreen); @@ -597,20 +626,18 @@ void loop() globalVars.swipeLeft || globalVars.swipeRight ) { timer5 = millis(); - // if(globalVars.sleep) unhandle(); } if(globalVars.sleep) matrix.clear(); - else screens[globalVars.currentScreen].func(&screens[globalVars.currentScreen].arg); + else + screens[globalVars.currentScreen].func(&screens[globalVars.currentScreen].arg); break; } matrix.show(); // Wait until ppm data stabilize TIMER(0, 180000) - { globalVars.co2Ready = true; - } // Monthly preventative safe reset of the millis() timer TIMER(0, 3456000000) diff --git a/Dashboard/bitmaps.h b/Dashboard/bitmaps.h index 0fc8a8d21d15b83e2279f5d441edf565f6d504de..c0f9cca7a168d7b747e648db98633e9041f637d2 100644 --- a/Dashboard/bitmaps.h +++ b/Dashboard/bitmaps.h @@ -25,4 +25,37 @@ void drawMoon(mData* buffer) for(y = 1; y < 8; y++) for(x = 10; x >= 5; x--) setPixel(buffer, x, y, bitRead(bm, i++) ? mWhite : mBlack); +} + +void drawTool(mData* buffer) +{ + const uint64_t bm = 0b00001100000011000000111100011111001110000111000011100000; + uint8_t x, y, i; + + i = 0; + for(y = 1; y < 8; y++) + for(x = 11; x >= 4; x--) + setPixel(buffer, x, y, bitRead(bm, i++) ? mHEX("868c79") : mBlack); +} + +void drawSun(mData* buffer) +{ + const uint64_t bm = 0b101101011110011110111111011110011110101101; + uint8_t x, y, i; + + i = 0; + for(y = 1; y < 8; y++) + for(x = 10; x >= 5; x--) + setPixel(buffer, x, y, bitRead(bm, i++) ? mYellow : mBlack); +} + +void drawClock(mData* buffer) +{ + const uint64_t bm = 0b011110101001101011101101101001100001011110; + uint8_t x, y, i; + + i = 0; + for(y = 1; y < 8; y++) + for(x = 10; x >= 5; x--) + setPixel(buffer, x, y, bitRead(bm, i++) ? mHEX("845eff") : mBlack); } \ No newline at end of file diff --git a/Dashboard/config.h b/Dashboard/config.h index 99be3cddd3b165e1e3b23a8ff4f185c6ee3e402b..fbddb9e08d9e92bbcd1459c1e987f189f45acd1d 100644 --- a/Dashboard/config.h +++ b/Dashboard/config.h @@ -23,8 +23,10 @@ #define CONNECTION_TYPE ZIGZAG // Direction (DIR_RIGHT, DIR_UP, DIR_LEFT, DIR_DOWN) #define DIRECTION DIR_LEFT +// Brightness +#define BRIGHTNESS 100 // Delay between textboxes frames (greater => slower) -#define TB_FRAMES_DELAY 100 +#define TB_FRAMES_DELAY 80 // Delay between animations frames (greater => slower) #define AN_FRAMES_DELAY 50 @@ -51,7 +53,7 @@ #define HIGH_PPM_TIMEOUT 300000 // COâ‚‚ min-max window -#define CO2WINDOW 50 +#define CO2WINDOW 300 // COâ‚‚ graph update time #define GRAPH_UPDATE_TIME 180000 diff --git a/Dashboard/configScreens.h b/Dashboard/configScreens.h index 3c0b2857d80dd7a92768c9df0190769b04a05830..fab8f05f1945f3d599bd412e7b328167ada2092c 100644 --- a/Dashboard/configScreens.h +++ b/Dashboard/configScreens.h @@ -6,22 +6,31 @@ /* Welcome screen with greetings Swipe left when prompts to continue (nextScreeen0) */ extern void welcome(Arg *arg); -extern void welcomePrepare(); +extern void welcomePrepare(mData* buffer); /* Main screen with clock and COâ‚‚ bar */ extern void dashboard(Arg *arg); -extern void dashboardPrepare(); +extern void dashboardPrepare(mData* buffer); /* COâ‚‚ graph */ extern void graph(Arg *arg); -extern void graphPrepare(); +extern void graphPrepare(mData* buffer); /* Pomodoro timer */ extern void pomodoro(Arg *arg); -extern void pomodoroPrepare(); +extern void pomodoroPrepare(mData* buffer); /* Service desk email */ -extern void settings(Arg *arg); -extern void settingsPrepare(); +extern void serviceMail(Arg *arg); +extern void serviceMailPrepare(mData* buffer); /* Manual sleep screen */ extern void manualSleep(Arg *arg); -extern void manualSleepPrepare(); +extern void manualSleepPrepare(mData* buffer); +/* Settings */ +extern void settings(Arg *arg); +extern void settingsPrepare(mData* buffer); +/* Brightness */ +extern void settingBrightness(Arg *arg); +extern void settingBrightnessPrepare(mData* buffer); +/* Time */ +extern void settingTime(Arg *arg); +extern void settingTimePrepare(mData* buffer); // Links enum SCREEN : uint8_t @@ -31,16 +40,22 @@ enum SCREEN : uint8_t SCREEN_DASHBOARD, SCREEN_GRAPH, SCREEN_POMODORO, - SCREEN_SETTINGS, // For now it's just service desk + SCREEN_SERVICEMAIL, SCREEN_SLEEP, + SCREEN_SETTINGS, + SCREEN_BRIGHTNESS, + SCREEN_TIME, }; const Screen screens[] = { - { welcome, {0}, welcomePrepare, homeScreen, NONE, NONE }, -// Func Args Prepare func Back Forward Select - { dashboard, {0}, dashboardPrepare, SCREEN_GRAPH, SCREEN_POMODORO, NONE }, - { graph, {0}, graphPrepare, NONE, SCREEN_DASHBOARD, NONE }, - { pomodoro, {0}, pomodoroPrepare, SCREEN_DASHBOARD, SCREEN_SLEEP, NONE }, - { settings, {0}, settingsPrepare, SCREEN_SLEEP, NONE, NONE }, - { manualSleep, {0}, manualSleepPrepare, SCREEN_POMODORO, SCREEN_SETTINGS, homeScreen }, + { welcome, {0}, welcomePrepare, homeScreen, NONE, NONE }, +// Func Args Prepare func Back Forward Select + { dashboard, {0}, dashboardPrepare, SCREEN_GRAPH, SCREEN_POMODORO, NONE }, + { graph, {0}, graphPrepare, NONE, SCREEN_DASHBOARD, NONE }, + { pomodoro, {0}, pomodoroPrepare, SCREEN_DASHBOARD, SCREEN_SLEEP, homeScreen }, + { serviceMail, {0}, serviceMailPrepare, SCREEN_TIME, NONE, NONE }, + { manualSleep, {0}, manualSleepPrepare, SCREEN_POMODORO, SCREEN_SETTINGS, homeScreen }, + { settings, {0}, settingsPrepare, SCREEN_SLEEP, NONE, SCREEN_BRIGHTNESS }, + { settingBrightness, {0}, settingBrightnessPrepare, SCREEN_SETTINGS, SCREEN_TIME, NONE }, + { settingTime, {0}, settingTimePrepare, SCREEN_BRIGHTNESS, SCREEN_SERVICEMAIL, NONE }, }; \ No newline at end of file diff --git a/Dashboard/screens.h b/Dashboard/screens.h index e61dbcfe005cab0729fec4a7acc23a4d11ec9850..cd9649a2e705a3b4c1f9eb5eb3c734d2476a33ab 100644 --- a/Dashboard/screens.h +++ b/Dashboard/screens.h @@ -9,7 +9,7 @@ void changeScreen(SCREEN current, uint8_t next, ANIMATION anim = NO_ANIMATION); // Animate void animate(uint16_t reciprocal_speed); // Draw small number -void drawSmallNumber(uint8_t x, uint8_t y, uint8_t num, mData color); +void drawSmallNumber(mData* m, uint8_t x, uint8_t y, uint8_t num, mData color); // Set pixel in the buffer void setPixel(mData* m, uint8_t x, uint8_t y, mData c); // Get pixel from the buffer @@ -83,6 +83,7 @@ void animate(uint16_t reciprocal_speed) setPixel(&matrix.leds[0], x, HEIGHT - 1, getPixel(&globalVars.leds[0], x, counter)); if(++counter == HEIGHT) { + screens[globalVars.currentScreen].funcPrepare(&matrix.leds[0]); counter = 0; globalVars.prepare = 0; } @@ -97,6 +98,7 @@ void animate(uint16_t reciprocal_speed) setPixel(&matrix.leds[0], x, 0, getPixel(&globalVars.leds[0], x, (HEIGHT - counter - 1))); if(++counter == HEIGHT) { + screens[globalVars.currentScreen].funcPrepare(&matrix.leds[0]); counter = 0; globalVars.prepare = 0; } @@ -111,6 +113,7 @@ void animate(uint16_t reciprocal_speed) setPixel(&matrix.leds[0], WIDTH - 1, y, getPixel(&globalVars.leds[0], counter, y)); if(++counter == WIDTH) { + screens[globalVars.currentScreen].funcPrepare(&matrix.leds[0]); counter = 0; globalVars.prepare = 0; } @@ -125,6 +128,7 @@ void animate(uint16_t reciprocal_speed) setPixel(&matrix.leds[0], 0, y, getPixel(&globalVars.leds[0], (WIDTH - counter - 1), y)); if(++counter == WIDTH) { + screens[globalVars.currentScreen].funcPrepare(&matrix.leds[0]); counter = 0; globalVars.prepare = 0; } @@ -136,7 +140,7 @@ void animate(uint16_t reciprocal_speed) void welcome(Arg *arg) { - const uint16_t delayMap[] = {0, TB_FRAMES_DELAY / 2, 0, TB_FRAMES_DELAY - 1, 0, TB_FRAMES_DELAY - 1}; + const uint16_t delayMap[] = {0, TB_FRAMES_DELAY / 2, 0, TB_FRAMES_DELAY, 0, TB_FRAMES_DELAY}; // Local vars static uint8_t counter = 0; @@ -245,9 +249,9 @@ void welcome(Arg *arg) unhandle(); } -void welcomePrepare() +void welcomePrepare(mData* buffer) { - clearBuffer(&globalVars.leds[0]); + clearBuffer(buffer); } void drawSmallNumber(mData* m, uint8_t x, uint8_t y, uint8_t num, mData color) @@ -315,8 +319,9 @@ void dashboard(Arg *arg) // Draw pomodoro bar if(globalVars.pomodoroRunning) { - uint8_t minuteMapped = map( globalVars.pomodoroMinutes, - 0, globalVars.pomodoroState ? globalVars.pomodoroSavedBreak : globalVars.pomodoroSavedWork, + uint16_t ui16pomodoroMinutes = globalVars.pomodoroMinutes; + uint8_t minuteMapped = map( ui16pomodoroMinutes * 60 + globalVars.pomodoroSeconds, + 0, (globalVars.pomodoroState ? globalVars.pomodoroSavedBreak : globalVars.pomodoroSavedWork) * 60, 0, WIDTH - 2); uint8_t i; for(i = 1; i < minuteMapped + 1; i++) @@ -337,20 +342,20 @@ void dashboard(Arg *arg) unhandle(); } -void dashboardPrepare() +void dashboardPrepare(mData* buffer) { // Draw COâ‚‚ bar // Drawing critical ppm is more important if(globalVars.ppm[globalVars.freshPPM] >= globalVars.maxPPM - CO2WINDOW) for(uint8_t i = 0; i < HEIGHT; i++) { - setPixel(&globalVars.leds[0], 0, i, COLOR2); + setPixel(buffer, 0, i, COLOR2); } // Fresh room blinking else if(globalVars.ppm[globalVars.freshPPM] <= globalVars.minPPM + CO2WINDOW) for(uint8_t i = 0; i < HEIGHT; i++) { - setPixel(&globalVars.leds[0], 0, i, COLOR1); + setPixel(buffer, 0, i, COLOR1); } // Else show progress bar else @@ -358,30 +363,31 @@ void dashboardPrepare() uint8_t ppmMapped = map(globalVars.ppm[globalVars.freshPPM], globalVars.minPPM, globalVars.maxPPM, 0, HEIGHT); uint8_t i; for(i = 0; i <= ppmMapped; i++) - setPixel(&globalVars.leds[0], 0, i, barGrad.get(i, HEIGHT)); + setPixel(buffer, 0, i, barGrad.get(i, HEIGHT)); for(; i < HEIGHT; i++) - setPixel(&globalVars.leds[0], 0, i, mBlack); + setPixel(buffer, 0, i, mBlack); } // Draw clock #if(TIME_FORMAT > (10 - (OVERFLOW_WITHOUT_ZERO == 1))) - drawSmallNumber(&globalVars.leds[0], 2, 1, globalVars.hours / 10, COLOR1); + drawSmallNumber(buffer, 2, 1, globalVars.hours / 10, COLOR1); #endif - drawSmallNumber(&globalVars.leds[0], 5, 1, globalVars.hours % 10, COLOR1); - drawSmallNumber(&globalVars.leds[0], 8, 1, globalVars.minutes / 10, COLOR2); - drawSmallNumber(&globalVars.leds[0], 11, 1, globalVars.minutes % 10, COLOR2); + drawSmallNumber(buffer, 5, 1, globalVars.hours % 10, COLOR1); + drawSmallNumber(buffer, 8, 1, globalVars.minutes / 10, COLOR2); + drawSmallNumber(buffer, 11, 1, globalVars.minutes % 10, COLOR2); // Draw pomodoro bar if(globalVars.pomodoroRunning) { - uint8_t minuteMapped = map( globalVars.pomodoroMinutes, - 0, globalVars.pomodoroState ? globalVars.pomodoroSavedBreak : globalVars.pomodoroSavedWork, + uint16_t ui16pomodoroMinutes = globalVars.pomodoroMinutes; + uint8_t minuteMapped = map( ui16pomodoroMinutes * 60 + globalVars.pomodoroSeconds, + 0, (globalVars.pomodoroState ? globalVars.pomodoroSavedBreak : globalVars.pomodoroSavedWork) * 60, 0, WIDTH - 2); uint8_t i; for(i = 1; i < minuteMapped + 1; i++) - setPixel(&globalVars.leds[0], i, HEIGHT - 1, globalVars.pomodoroState ? mGreen : mRed); + setPixel(buffer, i, HEIGHT - 1, globalVars.pomodoroState ? mGreen : mRed); for(; i < WIDTH; i++) - setPixel(&globalVars.leds[0], i, HEIGHT - 1, mBlack); + setPixel(buffer, i, HEIGHT - 1, mBlack); } } @@ -395,7 +401,7 @@ void graph(Arg *arg) unhandle(); } -void graphPrepare() +void graphPrepare(mData* buffer) { uint8_t x = WIDTH - 1; for(uint8_t f = globalVars.freshPPM; (f != globalVars.freshPPM) || (x == WIDTH - 1); f = (f == 0) ? WIDTH - 1 : (f-1)) @@ -404,9 +410,9 @@ void graphPrepare() if(ppmMapped >= HEIGHT) ppmMapped = HEIGHT - 1; uint8_t i; for(i = 0; i <= ppmMapped; i++) - setPixel(&globalVars.leds[0], x, i, barGrad.get(i, HEIGHT)); + setPixel(buffer, x, i, barGrad.get(i, HEIGHT)); for(; i < HEIGHT; i++) - setPixel(&globalVars.leds[0], x, i, mBlack); + setPixel(buffer, x, i, mBlack); x--; } } @@ -414,7 +420,7 @@ void graphPrepare() void pomodoro(Arg *arg) { // Only 16x9 - const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY - 1, TB_FRAMES_DELAY - 1}; + const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY, TB_FRAMES_DELAY}; TIMER(globalVars.timer, delayMap[globalVars.currentState]) { @@ -495,7 +501,7 @@ void pomodoro(Arg *arg) globalVars.pomodoroMinutes = globalVars.pomodoroSavedWork; globalVars.pomodoroSeconds = 0; globalVars.pomodoroRunning = true; - changeScreen(SCREEN_POMODORO, 0, ANIMATION_SHIFT_UP); + changeScreen(SCREEN_POMODORO, 2, ANIMATION_SHIFT_UP); } } else @@ -516,39 +522,39 @@ void pomodoro(Arg *arg) if(globalVars.tapLeft) { strcpy_P(globalVars.S, strings[3]); - tb.setup(globalVars.S, LANGMASK(3), COLOR2, TB_REPEAT, 0, 1, 16, 80); + tb.setup(globalVars.S, LANGMASK(3), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); globalVars.pomodoroRunning = false; globalVars.currentState = 1; } if(globalVars.holdRight) { strcpy_P(globalVars.S, strings[6]); - tb.setup(globalVars.S, LANGMASK(6), COLOR2, TB_REPEAT, 0, 1, 16, 80); + tb.setup(globalVars.S, LANGMASK(6), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); globalVars.currentState = 1; } if(globalVars.holdLeft) { strcpy_P(globalVars.S, strings[7]); - tb.setup(globalVars.S, LANGMASK(7), COLOR2, TB_REPEAT, 0, 1, 16, 80); + tb.setup(globalVars.S, LANGMASK(7), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); globalVars.currentState = 1; } } unhandle(); } -void pomodoroPrepare() +void pomodoroPrepare(mData* buffer) { // Only 16x9 - drawTomato(&globalVars.leds[0]); + drawTomato(buffer); } -void settings(Arg *arg) +void serviceMail(Arg *arg) { // Only handle gestures, update when needed if(globalVars.swipeRight) - changeScreen(SCREEN_SETTINGS, 0, NO_ANIMATION); + changeScreen(SCREEN_SERVICEMAIL, 0, ANIMATION_SHIFT_RIGHT); if(globalVars.swipeLeft) - changeScreen(SCREEN_SETTINGS, 1, NO_ANIMATION); + changeScreen(SCREEN_SERVICEMAIL, 1, ANIMATION_SHIFT_LEFT); if(globalVars.tapLeft && (globalVars.currentState != 0)) { globalVars.currentState--; @@ -566,7 +572,7 @@ void settings(Arg *arg) unhandle(); } -void settingsPrepare() +void serviceMailPrepare(mData* buffer) { // Force no animation globalVars.animation = NO_ANIMATION; @@ -578,7 +584,7 @@ void settingsPrepare() void manualSleep(Arg *arg) { // Only 16x9 - const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY - 1, 0}; + const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY, 0, AN_FRAMES_DELAY}; TIMER(globalVars.timer, delayMap[globalVars.currentState]) { @@ -672,21 +678,304 @@ void manualSleep(Arg *arg) if(globalVars.holdRight) { strcpy_P(globalVars.S, strings[8]); - tb.setup(globalVars.S, LANGMASK(8), COLOR2, TB_REPEAT, 0, 1, 16, 80); + tb.setup(globalVars.S, LANGMASK(8), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); globalVars.currentState = 1; } if(globalVars.holdLeft) { strcpy_P(globalVars.S, strings[9]); - tb.setup(globalVars.S, LANGMASK(9), COLOR2, TB_REPEAT, 0, 1, 16, 80); + tb.setup(globalVars.S, LANGMASK(9), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); globalVars.currentState = 1; } } unhandle(); } -void manualSleepPrepare() +void manualSleepPrepare(mData* buffer) {\ // Only 16x9 - drawMoon(&globalVars.leds[0]); + drawMoon(buffer); +} + +void settings(Arg *arg) +{ + // Only 16x9 + const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY, 0}; + + TIMER(globalVars.timer, delayMap[globalVars.currentState]) + { + switch(globalVars.currentState) + { + case 0: + { + strcpy_P(globalVars.S, strings[10]); + tb.setup(globalVars.S, LANGMASK(10), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); + globalVars.currentState++; + } + break; + case 1: + { + switch(tb.render()) + { + case 1: + globalVars.timer = millis(); + break; + case 2: + matrix.clear(); + drawTool(&matrix.leds[0]); + globalVars.currentState = 0; + break; + } + } + break; + } + } + + // Gestures + if(globalVars.swipeRight) + changeScreen(SCREEN_SETTINGS, 0, ANIMATION_SHIFT_RIGHT); + if(globalVars.swipeLeft) + changeScreen(SCREEN_SETTINGS, 1, ANIMATION_SHIFT_LEFT); + if(globalVars.tapRight) + { + changeScreen(SCREEN_SETTINGS, 2, ANIMATION_SHIFT_DOWN); + } + if(globalVars.holdRight) + { + strcpy_P(globalVars.S, strings[11]); + tb.setup(globalVars.S, LANGMASK(11), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); + globalVars.currentState = 1; + } + unhandle(); +} + +void settingsPrepare(mData* buffer) +{ + // Only 16x9 + drawTool(buffer); +} + +void settingBrightness(Arg *arg) +{ + // Only 16x9 + const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY, TB_FRAMES_DELAY}; + + static uint8_t bright; + + TIMER(globalVars.timer, delayMap[globalVars.currentState]) + { + switch(globalVars.currentState) + { + case 0: + { + strcpy_P(globalVars.S, strings[12]); + tb.setup(globalVars.S, LANGMASK(12), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); + globalVars.currentState++; + } + break; + case 1: + { + switch(tb.render()) + { + case 1: + globalVars.timer = millis(); + break; + case 2: + matrix.clear(); + drawSun(&matrix.leds[0]); + globalVars.currentState = 0; + break; + } + } + break; + case 2: + { + for(uint8_t x = 0; x < 9; x++) + { + setPixel(&matrix.leds[0], x + 5, 7, COLOR1); + } + drawSmallNumber(&matrix.leds[0], 5, 1, bright / 100, COLOR1); + drawSmallNumber(&matrix.leds[0], 8, 1, (bright / 10) % 10, COLOR1); + drawSmallNumber(&matrix.leds[0], 11, 1, bright % 10, COLOR1); + globalVars.timer = millis(); + } + break; + } + } + + // Gestures + if(globalVars.currentState == 2) + { + if(globalVars.tapLeft) + { + if(bright > 0) bright--; + } + if(globalVars.tapRight) + { + if(bright < UINT8_MAX) bright++; + } + if(globalVars.swipeLeft) + { + if(bright > 9) bright -= 10; + } + if(globalVars.swipeRight) + { + if(bright < UINT8_MAX - 9) bright += 10; + } + if(globalVars.holdLeft) + { + matrix.clear(); + drawSun(&matrix.leds[0]); + globalVars.currentState = 0; + } + if(globalVars.holdRight) + { + globalVars.brightness = bright; + matrix.setBrightness(globalVars.brightness); + matrix.clear(); + drawSun(&matrix.leds[0]); + globalVars.currentState = 0; + } + } + else + { + if(globalVars.swipeRight) + changeScreen(SCREEN_BRIGHTNESS, 0, ANIMATION_SHIFT_RIGHT); + if(globalVars.swipeLeft) + changeScreen(SCREEN_BRIGHTNESS, 1, ANIMATION_SHIFT_LEFT); + if(globalVars.tapRight) + { + matrix.clear(); + globalVars.currentState = 2; + bright = globalVars.brightness; + } + if(globalVars.holdRight) + { + strcpy_P(globalVars.S, strings[13]); + tb.setup(globalVars.S, LANGMASK(13), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); + globalVars.currentState = 1; + } + } + unhandle(); +} + +void settingBrightnessPrepare(mData* buffer) +{ + // Only 16x9 + drawSun(buffer); +} + +void settingTime(Arg *arg) +{ + // Only 16x9 + const uint16_t delayMap[] = {2000, TB_FRAMES_DELAY, TB_FRAMES_DELAY}; + + static DateTime DTtmp; + static uint8_t state; + + TIMER(globalVars.timer, delayMap[globalVars.currentState]) + { + switch(globalVars.currentState) + { + case 0: + { + strcpy_P(globalVars.S, strings[14]); + tb.setup(globalVars.S, LANGMASK(14), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); + globalVars.currentState++; + } + break; + case 1: + { + switch(tb.render()) + { + case 1: + globalVars.timer = millis(); + break; + case 2: + matrix.clear(); + drawClock(&matrix.leds[0]); + globalVars.currentState = 0; + break; + } + } + break; + case 2: + { + // Hours + for(uint8_t x = 0; x < 6; x++) + { + setPixel(&matrix.leds[0], x + 2, 7, state ? mBlack : COLOR1); + } + drawSmallNumber(&matrix.leds[0], 2, 1, DTtmp.hour / 10, COLOR1); + drawSmallNumber(&matrix.leds[0], 5, 1, DTtmp.hour % 10, COLOR1); + // Minutes + for(uint8_t x = 0; x < 6; x++) + { + setPixel(&matrix.leds[0], x + 8, 7, state ? COLOR2 : mBlack); + } + drawSmallNumber(&matrix.leds[0], 8, 1, DTtmp.minute / 10, COLOR2); + drawSmallNumber(&matrix.leds[0], 11, 1, DTtmp.minute % 10, COLOR2); + globalVars.timer = millis(); + } + break; + } + } + + // Gestures + if(globalVars.currentState == 2) + { + if(globalVars.swipeRight) + state = true; + if(globalVars.swipeLeft) + state = false; + if(globalVars.tapLeft) + { + if(!state && DTtmp.hour > 0) DTtmp.hour--; + else if(state && DTtmp.minute > 0) DTtmp.minute--; + } + if(globalVars.tapRight) + { + if(!state && DTtmp.hour < 23) DTtmp.hour++; + else if(state && DTtmp.minute < 59) DTtmp.minute++; + } + if(globalVars.holdLeft) + { + matrix.clear(); + drawClock(&matrix.leds[0]); + globalVars.currentState = 0; + } + if(globalVars.holdRight) + { + DTtmp.second = 0; + rtc.setTime(DTtmp); + changeScreen(SCREEN_TIME, 3, ANIMATION_SHIFT_UP); + } + } + else + { + if(globalVars.swipeRight) + changeScreen(SCREEN_TIME, 0, ANIMATION_SHIFT_RIGHT); + if(globalVars.swipeLeft) + changeScreen(SCREEN_TIME, 1, ANIMATION_SHIFT_LEFT); + if(globalVars.tapRight) + { + matrix.clear(); + globalVars.currentState = 2; + state = false; + DTtmp = rtc.getTime(); + } + if(globalVars.holdRight) + { + strcpy_P(globalVars.S, strings[15]); + tb.setup(globalVars.S, LANGMASK(15), COLOR2, TB_REPEAT, 0, 1, 16, TB_FRAMES_DELAY); + globalVars.currentState = 1; + } + } + unhandle(); +} + +void settingTimePrepare(mData* buffer) +{ + // Only 16x9 + drawClock(buffer); } \ No newline at end of file diff --git a/Dashboard/strings.h b/Dashboard/strings.h index 977fa26fd1d713730fde84d20a416994c32bb8ab..de57b3e576909b106fec7e5802372a31a5291b8d 100644 --- a/Dashboard/strings.h +++ b/Dashboard/strings.h @@ -1,7 +1,8 @@ #pragma once #ifdef LANG_RU_RU -#define LANGMASK(n) langmask[n] +// #define LANGMASK(n) pgm_read_dword(pgm_read_word(&(langmask[n])) + sizeof(uint32_t)) + ((uint64_t)pgm_read_dword(pgm_read_word(&(langmask[n]))) << 32) +#define LANGMASK(n) (n == 4 ? 0 : UINT64_MAX) const char string_hello[] PROGMEM = "Ghbdtn"; // Привет const char string_start_prompt[] PROGMEM = "<- Cdfqgyb dktdj"; // Свайпни влево const char string_pomodoro[] PROGMEM = "Gjvbljh"; // Помидор @@ -11,8 +12,14 @@ const char string_help_pomodoro_stop[] PROGMEM = "Jcnfyjdbnm"; const char string_help_pomodoro_start[] PROGMEM = "Pfgecnbnm"; // ЗапуÑтить const char string_help_sleep_until_action[] PROGMEM = "Cjy (hexyjt ghj,e;ltybt)"; // Сон (ручное пробуждение) const char string_help_sleep_until_wakeup[] PROGMEM = "Cjy (fdnjvfnbxtcrjt ghj,e;ltybt)"; // Сон (автоматичеÑкое пробуждение) -// Need to make it PROGMEM -const uint64_t langmask[] = {0xFF, 0xFFFF, 0xFF, 0xFFFF, 0, 0xF, 0xFFF, 0xFFF, 0xFFFFFF, 0xFFFFFFFF}; +const char string_settings[] PROGMEM = "Yfcnhjqrb"; // ÐаÑтройки +const char string_help_all_settings[] PROGMEM = "Dct yfcnhjqrb"; // Ð’Ñе наÑтройки +const char string_brightness[] PROGMEM = "Zhrjcnm"; // ЯркоÑть +const char string_help_brightness[] PROGMEM = "Bpvtybnm zhrjcnm"; // Изменить ÑркоÑть +const char string_time[] PROGMEM = "Dhtvz"; // Ð’Ñ€ÐµÐ¼Ñ +const char string_help_time[] PROGMEM = "Ecnfyjdbnm dhtvz"; // УÑтановить Ð²Ñ€ÐµÐ¼Ñ +// ARV can't read uint64_t from progmem +// const uint64_t langmask[] PROGMEM = {0xFF, 0xFFFF, 0xFF, 0xFFFF, 0, 0xF, 0xFFF, 0xFFF, 0xFFFFFF, 0xFFFFFFFF, 0xFFF, 0xFFFF, 0xFFF, 0xFFFF}; #else #define LANGMASK(n) 0 const char string_hello[] PROGMEM = "Hello"; @@ -24,13 +31,23 @@ const char string_help_pomodoro_stop[] PROGMEM = "Stop pomodoro"; const char string_help_pomodoro_start[] PROGMEM = "Start pomodoro"; const char string_help_sleep_until_action[] PROGMEM = "Sleep (manual wake up)"; const char string_help_sleep_until_wakeup[] PROGMEM = "Sleep (auto wake up)"; +const char string_settings[] PROGMEM = "Settings"; +const char string_help_all_settings[] PROGMEM = "All settings"; +const char string_brightness[] PROGMEM = "Brightness"; +const char string_help_brightness[] PROGMEM = "Change brightness"; +const char string_time[] PROGMEM = "Time"; +const char string_help_time[] PROGMEM = "Set time"; #endif // Shared const char string_service_desk[] PROGMEM = "gitlab+egorguslyan-dashboard-851-issue-@edugit.org"; -const char* const strings[] = { string_hello, string_start_prompt, - string_pomodoro, string_stopped, - string_service_desk, string_sleep, - string_help_pomodoro_start, string_help_pomodoro_stop, - string_help_sleep_until_action, string_help_sleep_until_wakeup, }; \ No newline at end of file +const char* const strings[] = { string_hello, string_start_prompt, // 0 1 + string_pomodoro, string_stopped, // 2 3 + string_service_desk, string_sleep, // 4 5 + string_help_pomodoro_start, string_help_pomodoro_stop, // 6 7 + string_help_sleep_until_action, string_help_sleep_until_wakeup, // 8 9 + string_settings, string_help_all_settings, // 10 11 + string_brightness, string_help_brightness, // 12 13 + string_time, string_help_time, // 14 15 + }; \ No newline at end of file