diff --git a/Dashboard/Dashboard.ino b/Dashboard/Dashboard.ino index 75740ddba3bdb705c2a333d8f8d5e84e05d91d5c..c87e1e13205804d88e54dcb86cb3a67f96a9cfad 100644 --- a/Dashboard/Dashboard.ino +++ b/Dashboard/Dashboard.ino @@ -122,8 +122,7 @@ struct uint8_t currentState; // Current state of current screen ANIMATION animation : 3; // The way to animate uint8_t prepare : 2; // 0 — Draw current screen; 1 — Call prepare function; 2 — Animate - // mData leds[NUMLEDS]; - mData leds[0]; // Sorry, but this buffer takes a lot of memory + mData leds[NUMLEDS]; // Additional buffer for animations // Service uint32_t timer; // Global timer for screens @@ -581,10 +580,12 @@ void loop() { case 1: PRINTLN_DEBUG(F("Prepared")); + unhandle(); + clearBuffer(&globalVars.leds[0]); screens[globalVars.currentScreen].funcPrepare(); case 2: PRINTLN_DEBUG(F("Animated")); - animate(50); + animate(AN_FRAMES_DELAY); break; case 0: PRINT_DEBUG(F("Screen ")); diff --git a/Dashboard/bitmaps.h b/Dashboard/bitmaps.h index d64a7f8796752c18035d443584dd0c7d9171e6c7..0fc8a8d21d15b83e2279f5d441edf565f6d504de 100644 --- a/Dashboard/bitmaps.h +++ b/Dashboard/bitmaps.h @@ -1,9 +1,6 @@ #pragma once -void setPixel(mData* buffer, uint8_t x, uint8_t y, mData c) -{ - buffer[matrix.getPixNumber(x, y)] = c; -} +extern void setPixel(mData* m, uint8_t x, uint8_t y, mData c); void drawTomato(mData* buffer) { diff --git a/Dashboard/config.h b/Dashboard/config.h index 32dda9d5546c0752cf792c5234151feb7f19df06..99be3cddd3b165e1e3b23a8ff4f185c6ee3e402b 100644 --- a/Dashboard/config.h +++ b/Dashboard/config.h @@ -25,6 +25,8 @@ #define DIRECTION DIR_LEFT // Delay between textboxes frames (greater => slower) #define TB_FRAMES_DELAY 100 +// Delay between animations frames (greater => slower) +#define AN_FRAMES_DELAY 50 // Favorite colors // Breeze diff --git a/Dashboard/screens.h b/Dashboard/screens.h index 34bf27bf3ef451f6790130737018731d391f12ab..e61dbcfe005cab0729fec4a7acc23a4d11ec9850 100644 --- a/Dashboard/screens.h +++ b/Dashboard/screens.h @@ -10,6 +10,12 @@ void changeScreen(SCREEN current, uint8_t next, ANIMATION anim = NO_ANIMATION); void animate(uint16_t reciprocal_speed); // Draw small number void drawSmallNumber(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 +mData getPixel(mData* m, uint8_t x, uint8_t y); +// Clear buffer +void clearBuffer(mData* m); void unhandle() { @@ -37,13 +43,94 @@ void changeScreen(SCREEN current, uint8_t next, ANIMATION anim = NO_ANIMATION) tb.disable(); } +void setPixel(mData* m, uint8_t x, uint8_t y, mData c) +{ + if (x * y >= NUMLEDS || x >= WIDTH || y >= HEIGHT) return; + m[matrix.getPixNumber(x, y)] = c; +} + +mData getPixel(mData* m, uint8_t x, uint8_t y) +{ + return m[matrix.getPixNumber(x, y)]; +} + +void clearBuffer(mData* m) +{ + memset(m, 0, sizeof(mData) * NUMLEDS); +} + void animate(uint16_t reciprocal_speed) { - //if(globalVars.animation == NO_ANIMATION) - if(true) + static uint8_t counter = 0; + + if(globalVars.animation == NO_ANIMATION) { + memcpy(&globalVars.leds[0], &matrix.leds[0], sizeof(mData) * NUMLEDS); globalVars.prepare = 0; - return; + } + else TIMER(globalVars.timer, reciprocal_speed) + { + globalVars.timer = millis(); + switch(globalVars.animation) + { + break; + case ANIMATION_SHIFT_DOWN: + { + for(uint8_t y = 0; y < (HEIGHT - 1); y++) + for(uint8_t x = 0; x < WIDTH; x++) + setPixel(&matrix.leds[0], x, y, getPixel(&matrix.leds[0], x, y + 1)); + for(uint8_t x = 0; x < WIDTH; x++) + setPixel(&matrix.leds[0], x, HEIGHT - 1, getPixel(&globalVars.leds[0], x, counter)); + if(++counter == HEIGHT) + { + counter = 0; + globalVars.prepare = 0; + } + } + break; + case ANIMATION_SHIFT_UP: + { + for(uint8_t y = HEIGHT - 1; y > 0; y--) + for(uint8_t x = 0; x < WIDTH; x++) + setPixel(&matrix.leds[0], x, y, getPixel(&matrix.leds[0], x, y - 1)); + for(uint8_t x = 0; x < WIDTH; x++) + setPixel(&matrix.leds[0], x, 0, getPixel(&globalVars.leds[0], x, (HEIGHT - counter - 1))); + if(++counter == HEIGHT) + { + counter = 0; + globalVars.prepare = 0; + } + } + break; + case ANIMATION_SHIFT_LEFT: + { + for(uint8_t x = 0; x < (WIDTH - 1); x++) + for(uint8_t y = 0; y < HEIGHT; y++) + setPixel(&matrix.leds[0], x, y, getPixel(&matrix.leds[0], x + 1, y)); + for(uint8_t y = 0; y < HEIGHT; y++) + setPixel(&matrix.leds[0], WIDTH - 1, y, getPixel(&globalVars.leds[0], counter, y)); + if(++counter == WIDTH) + { + counter = 0; + globalVars.prepare = 0; + } + } + break; + case ANIMATION_SHIFT_RIGHT: + { + for(uint8_t x = WIDTH - 1; x > 0; x--) + for(uint8_t y = 0; y < HEIGHT; y++) + setPixel(&matrix.leds[0], x, y, getPixel(&matrix.leds[0], x - 1, y)); + for(uint8_t y = 0; y < HEIGHT; y++) + setPixel(&matrix.leds[0], 0, y, getPixel(&globalVars.leds[0], (WIDTH - counter - 1), y)); + if(++counter == WIDTH) + { + counter = 0; + globalVars.prepare = 0; + } + } + break; + } } } @@ -89,7 +176,7 @@ void welcome(Arg *arg) : (counter < WIDTH + HEIGHT - 1 ? (counter - WIDTH + 1) : (counter < 2 * WIDTH + HEIGHT - 2 ? (HEIGHT - 1) : (2 * HEIGHT - counter + 2 * WIDTH - 4))); - matrix.set(x, y, COLOR1); + setPixel(&matrix.leds[0], x, y, COLOR1); PRINT_DEBUG(F("1 ")); PRINT_DEBUG(counter); PRINT_DEBUG(F(" ")); @@ -160,16 +247,15 @@ void welcome(Arg *arg) void welcomePrepare() { - //memset(globalVars.leds, mBlack, sizeof(mData) * NUMLEDS); - matrix.clear(); + clearBuffer(&globalVars.leds[0]); } -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) { uint16_t numBitmap = pgm_read_word(pgm_read_word(&(small_nums[num]))); // Run througth bits for(uint8_t i = 0; i < 15; i++) - matrix.set(x + (i % 3), y + 4 - (i / 3), bitRead(numBitmap, 15 - i) ? color : mBlack); + setPixel(m, x + (i % 3), y + 4 - (i / 3), bitRead(numBitmap, 15 - i) ? color : mBlack); } // Gradient for CO₂ bars @@ -197,14 +283,14 @@ void dashboard(Arg *arg) if(globalVars.ppm[globalVars.freshPPM] >= globalVars.maxPPM - CO2WINDOW) for(uint8_t i = 0; i < HEIGHT; i++) { - matrix.set(0, i, COLOR2); + setPixel(&matrix.leds[0], 0, i, COLOR2); matrix.fade(0, i, abs((int16_t)((millis() / 16) % 256) - 128)); } // Fresh room blinking else if(globalVars.ppm[globalVars.freshPPM] <= globalVars.minPPM + CO2WINDOW) for(uint8_t i = 0; i < HEIGHT; i++) { - matrix.set(0, i, COLOR1); + setPixel(&matrix.leds[0], 0, i, COLOR1); matrix.fade(0, i, abs((int16_t)((millis() / 16) % 256) - 128)); } // Else show progress bar @@ -213,18 +299,18 @@ void dashboard(Arg *arg) uint8_t ppmMapped = map(globalVars.ppm[globalVars.freshPPM], globalVars.minPPM, globalVars.maxPPM, 0, HEIGHT); uint8_t i; for(i = 0; i <= ppmMapped; i++) - matrix.set(0, i, barGrad.get(i, HEIGHT)); + setPixel(&matrix.leds[0], 0, i, barGrad.get(i, HEIGHT)); for(; i < HEIGHT; i++) - matrix.set(0, i, mBlack); + setPixel(&matrix.leds[0], 0, i, mBlack); } // Draw clock #if(TIME_FORMAT > (10 - (OVERFLOW_WITHOUT_ZERO == 1))) - drawSmallNumber(2, 1, globalVars.hours / 10, COLOR1); + drawSmallNumber(&matrix.leds[0], 2, 1, globalVars.hours / 10, COLOR1); #endif - drawSmallNumber(5, 1, globalVars.hours % 10, COLOR1); - drawSmallNumber(8, 1, globalVars.minutes / 10, COLOR2); - drawSmallNumber(11, 1, globalVars.minutes % 10, COLOR2); + drawSmallNumber(&matrix.leds[0], 5, 1, globalVars.hours % 10, COLOR1); + drawSmallNumber(&matrix.leds[0], 8, 1, globalVars.minutes / 10, COLOR2); + drawSmallNumber(&matrix.leds[0], 11, 1, globalVars.minutes % 10, COLOR2); // Draw pomodoro bar if(globalVars.pomodoroRunning) @@ -234,9 +320,9 @@ void dashboard(Arg *arg) 0, WIDTH - 2); uint8_t i; for(i = 1; i < minuteMapped + 1; i++) - matrix.set(i, HEIGHT - 1, globalVars.pomodoroState ? mGreen : mRed); + setPixel(&matrix.leds[0], i, HEIGHT - 1, globalVars.pomodoroState ? mGreen : mRed); for(; i < WIDTH; i++) - matrix.set(i, HEIGHT - 1, mBlack); + setPixel(&matrix.leds[0], i, HEIGHT - 1, mBlack); } } break; @@ -253,7 +339,50 @@ void dashboard(Arg *arg) void dashboardPrepare() { - matrix.clear(); + // 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); + } + // 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); + } + // Else show progress bar + else + { + 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)); + for(; i < HEIGHT; i++) + setPixel(&globalVars.leds[0], 0, i, mBlack); + } + + // Draw clock + #if(TIME_FORMAT > (10 - (OVERFLOW_WITHOUT_ZERO == 1))) + drawSmallNumber(&globalVars.leds[0], 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); + + // Draw pomodoro bar + if(globalVars.pomodoroRunning) + { + uint8_t minuteMapped = map( globalVars.pomodoroMinutes, + 0, globalVars.pomodoroState ? globalVars.pomodoroSavedBreak : globalVars.pomodoroSavedWork, + 0, WIDTH - 2); + uint8_t i; + for(i = 1; i < minuteMapped + 1; i++) + setPixel(&globalVars.leds[0], i, HEIGHT - 1, globalVars.pomodoroState ? mGreen : mRed); + for(; i < WIDTH; i++) + setPixel(&globalVars.leds[0], i, HEIGHT - 1, mBlack); + } } void graph(Arg *arg) @@ -268,8 +397,6 @@ void graph(Arg *arg) void graphPrepare() { - // Working with the main buffer cause there are no memory for additional - matrix.clear(); uint8_t x = WIDTH - 1; for(uint8_t f = globalVars.freshPPM; (f != globalVars.freshPPM) || (x == WIDTH - 1); f = (f == 0) ? WIDTH - 1 : (f-1)) { @@ -277,9 +404,9 @@ void graphPrepare() if(ppmMapped >= HEIGHT) ppmMapped = HEIGHT - 1; uint8_t i; for(i = 0; i <= ppmMapped; i++) - matrix.set(x, i, barGrad.get(i, HEIGHT)); + setPixel(&globalVars.leds[0], x, i, barGrad.get(i, HEIGHT)); for(; i < HEIGHT; i++) - matrix.set(x, i, mBlack); + setPixel(&globalVars.leds[0], x, i, mBlack); x--; } } @@ -320,17 +447,17 @@ void pomodoro(Arg *arg) // Work minutes for(uint8_t x = 0; x < 6; x++) { - matrix.set(x + 2, 7, globalVars.pomodoroState ? mBlack : COLOR1); + setPixel(&matrix.leds[0], x + 2, 7, globalVars.pomodoroState ? mBlack : COLOR1); } - drawSmallNumber(2, 1, globalVars.pomodoroMinutes / 10, COLOR1); - drawSmallNumber(5, 1, globalVars.pomodoroMinutes % 10, COLOR1); + drawSmallNumber(&matrix.leds[0], 2, 1, globalVars.pomodoroMinutes / 10, COLOR1); + drawSmallNumber(&matrix.leds[0], 5, 1, globalVars.pomodoroMinutes % 10, COLOR1); // Break minutes for(uint8_t x = 0; x < 6; x++) { - matrix.set(x + 8, 7, globalVars.pomodoroState ? COLOR2 : mBlack); + setPixel(&matrix.leds[0], x + 8, 7, globalVars.pomodoroState ? COLOR2 : mBlack); } - drawSmallNumber(8, 1, globalVars.pomodoroSeconds / 10, COLOR2); - drawSmallNumber(11, 1, globalVars.pomodoroSeconds % 10, COLOR2); + drawSmallNumber(&matrix.leds[0], 8, 1, globalVars.pomodoroSeconds / 10, COLOR2); + drawSmallNumber(&matrix.leds[0], 11, 1, globalVars.pomodoroSeconds % 10, COLOR2); globalVars.timer = millis(); } break; @@ -411,19 +538,17 @@ void pomodoro(Arg *arg) void pomodoroPrepare() { - // Working with the main buffer cause there are no memory for additional // Only 16x9 - matrix.clear(); - drawTomato(&matrix.leds[0]); + drawTomato(&globalVars.leds[0]); } void settings(Arg *arg) { // Only handle gestures, update when needed if(globalVars.swipeRight) - changeScreen(SCREEN_SETTINGS, 0, ANIMATION_SHIFT_RIGHT); + changeScreen(SCREEN_SETTINGS, 0, NO_ANIMATION); if(globalVars.swipeLeft) - changeScreen(SCREEN_SETTINGS, 1, ANIMATION_SHIFT_LEFT); + changeScreen(SCREEN_SETTINGS, 1, NO_ANIMATION); if(globalVars.tapLeft && (globalVars.currentState != 0)) { globalVars.currentState--; @@ -443,6 +568,8 @@ void settings(Arg *arg) void settingsPrepare() { + // Force no animation + globalVars.animation = NO_ANIMATION; strcpy_P(globalVars.S, strings[4]); tb.setup(globalVars.S, LANGMASK(4), COLOR2, TB_STATIC, 0, 1, 16, 0); tb.render(); @@ -559,9 +686,7 @@ void manualSleep(Arg *arg) } void manualSleepPrepare() -{ - // Working with the main buffer cause there are no memory for additional +{\ // Only 16x9 - matrix.clear(); - drawMoon(&matrix.leds[0]); + drawMoon(&globalVars.leds[0]); } \ No newline at end of file