From 86a7ef66eedba432651f20f617ecd4831b918431 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Tue, 2 Nov 2021 18:33:55 +0100 Subject: [PATCH] More refactorings again --- main/CMakeLists.txt | 2 + main/displays/gameoflifedisplay.cpp | 126 +++++++++++++++ main/displays/gameoflifedisplay.h | 124 +-------------- main/displays/menus/otamenu.cpp | 46 ++++++ main/displays/menus/otamenu.h | 39 +---- main/displays/menus/selectotabuildmenu.cpp | 0 main/displays/menus/selectotabuildmenu.h | 5 - main/displays/pingpongdisplay.cpp | 175 +++++++++++++++++++++ main/displays/pingpongdisplay.h | 168 +------------------- main/displays/spirodisplay.cpp | 120 ++++++++++++++ main/displays/spirodisplay.h | 113 +------------ main/displays/updatedisplay.cpp | 114 ++++++++++++++ main/displays/updatedisplay.h | 124 ++------------- main/ota.cpp | 52 ++++++ main/ota.h | 40 +---- 15 files changed, 671 insertions(+), 577 deletions(-) create mode 100644 main/displays/menus/otamenu.cpp create mode 100644 main/displays/menus/selectotabuildmenu.cpp diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 8bba364..1d64070 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -311,6 +311,8 @@ set(sources displays/menus/mosfetsmenu.cpp displays/menus/motorfeedbackdebugmenu.cpp displays/menus/motorstatedebugmenu.cpp + displays/menus/otamenu.cpp + displays/menus/selectotabuildmenu.cpp displays/menus/presetsmenu.cpp displays/menus/profilesmenu.cpp displays/menus/selectbatterytypemenu.cpp diff --git a/main/displays/gameoflifedisplay.cpp b/main/displays/gameoflifedisplay.cpp index e69de29..72b771b 100644 --- a/main/displays/gameoflifedisplay.cpp +++ b/main/displays/gameoflifedisplay.cpp @@ -0,0 +1,126 @@ +#include "gameoflifedisplay.h" + +// 3rdparty lib includes +#include +#include +#include +#include + +void GameOfLifeDisplay::start() +{ + m_grid = std::make_unique>(); + m_newgrid = std::make_unique>(); +} + +void GameOfLifeDisplay::initScreen() +{ + espgui::tft.setRotation(3); + espgui::tft.fillScreen(TFT_BLACK); +} + +void GameOfLifeDisplay::redraw() +{ + if (gen == 0) + { + espgui::tft.fillScreen(TFT_BLACK); + initGrid(); + } + + computeCA(); + drawGrid(); + + *m_grid = *m_newgrid; + + if (++gen == 500) + gen = 0; +} + +void GameOfLifeDisplay::stop() +{ + espgui::tft.setRotation(0); + m_grid = nullptr; + m_newgrid = nullptr; +} + +void GameOfLifeDisplay::confirm() +{ + +} + +void GameOfLifeDisplay::back() +{ + +} + +void GameOfLifeDisplay::drawGrid() +{ + uint16_t color = TFT_WHITE; + for (int16_t x = 1; x < GRIDX - 1; x++) { + for (int16_t y = 1; y < GRIDY - 1; y++) { + if (((*m_grid)[index(x,y)]) != ((*m_newgrid)[index(x,y)])) { + if ((*m_newgrid)[index(x,y)] == 1) + color = 0xFFFF; //random(0xFFFF); + else + color = 0; + espgui::tft.fillRect(CELLXY * x, CELLXY * y, CELLXY, CELLXY, color); + } + } + } +} + +void GameOfLifeDisplay::initGrid() +{ + for (int16_t x = 0; x < GRIDX; x++) { + for (int16_t y = 0; y < GRIDY; y++) { + (*m_newgrid)[index(x,y)] = 0; + + if (x == 0 || x == GRIDX - 1 || y == 0 || y == GRIDY - 1) + (*m_grid)[index(x,y)] = 0; + else + { + if (cpputils::randomNumber(4, espcpputils::esp_random_device{}) == 1) + (*m_grid)[index(x,y)] = 1; + else + (*m_grid)[index(x,y)] = 0; + } + + } + } +} + +int GameOfLifeDisplay::getNumberOfNeighbors(int x, int y) +{ + int n{}; + for (auto xOffset : {-1,0,1}) + for (auto yOffset : {-1,0,1}) + { + if (xOffset == 0 && yOffset == 0) + continue; + + const auto new_x = x+xOffset; + const auto new_y = y+yOffset; + + if (new_x >= 0 && new_y >= 0 && + new_x < GRIDX && new_y < GRIDY) + n += (*m_grid)[index(new_x, new_y)]; + } + + return n; +} + +void GameOfLifeDisplay::computeCA() +{ + for (int16_t x = 1; x < GRIDX; x++) { + for (int16_t y = 1; y < GRIDY; y++) { + int neighbors = getNumberOfNeighbors(x, y); + if ((*m_grid)[index(x,y)] == true && (neighbors == 2 || neighbors == 3 )) + (*m_newgrid)[index(x,y)] = true; + else if ((*m_grid)[index(x,y)] == 1) + (*m_newgrid)[index(x,y)] = false; + if ((*m_grid)[index(x,y)] == false && (neighbors == 3)) + (*m_newgrid)[index(x,y)] = true; + else if ((*m_grid)[index(x,y)] == 0) + (*m_newgrid)[index(x,y)] = false; + } + } +} diff --git a/main/displays/gameoflifedisplay.h b/main/displays/gameoflifedisplay.h index 62b0be4..fe627f9 100644 --- a/main/displays/gameoflifedisplay.h +++ b/main/displays/gameoflifedisplay.h @@ -4,23 +4,22 @@ #include #include -// 3rdparty lib includes -#include -#include - // local includes #include "display.h" -#include "actions/switchscreenaction.h" -namespace { -class GameOfLifeDisplay : public Display, public ConfirmActionInterface>, public BackActionInterface> +class GameOfLifeDisplay : public espgui::Display { + using Base = espgui::Display; + public: void start() override; void initScreen() override; void redraw() override; void stop() override; + void confirm() override; + void back() override; + private: //Draws the grid on the display @@ -71,114 +70,3 @@ private: int gen = 0; }; - -void GameOfLifeDisplay::start() -{ - m_grid = std::make_unique>(); - m_newgrid = std::make_unique>(); -} - -void GameOfLifeDisplay::initScreen() -{ - tft.setRotation(3); - tft.fillScreen(TFT_BLACK); -} - -void GameOfLifeDisplay::redraw() -{ - if (gen == 0) - { - tft.fillScreen(TFT_BLACK); - initGrid(); - } - - computeCA(); - drawGrid(); - - *m_grid = *m_newgrid; - - if (++gen == 500) - gen = 0; -} - -void GameOfLifeDisplay::stop() -{ - tft.setRotation(0); - m_grid = nullptr; - m_newgrid = nullptr; -} - -void GameOfLifeDisplay::drawGrid() -{ - uint16_t color = TFT_WHITE; - for (int16_t x = 1; x < GRIDX - 1; x++) { - for (int16_t y = 1; y < GRIDY - 1; y++) { - if (((*m_grid)[index(x,y)]) != ((*m_newgrid)[index(x,y)])) { - if ((*m_newgrid)[index(x,y)] == 1) - color = 0xFFFF; //random(0xFFFF); - else - color = 0; - tft.fillRect(CELLXY * x, CELLXY * y, CELLXY, CELLXY, color); - } - } - } -} - -void GameOfLifeDisplay::initGrid() -{ - for (int16_t x = 0; x < GRIDX; x++) { - for (int16_t y = 0; y < GRIDY; y++) { - (*m_newgrid)[index(x,y)] = 0; - - if (x == 0 || x == GRIDX - 1 || y == 0 || y == GRIDY - 1) - (*m_grid)[index(x,y)] = 0; - else - { - if (cpputils::randomNumber(4, espcpputils::esp_random_device{}) == 1) - (*m_grid)[index(x,y)] = 1; - else - (*m_grid)[index(x,y)] = 0; - } - - } - } -} - -int GameOfLifeDisplay::getNumberOfNeighbors(int x, int y) -{ - int n{}; - for (auto xOffset : {-1,0,1}) - for (auto yOffset : {-1,0,1}) - { - if (xOffset == 0 && yOffset == 0) - continue; - - const auto new_x = x+xOffset; - const auto new_y = y+yOffset; - - if (new_x >= 0 && new_y >= 0 && - new_x < GRIDX && new_y < GRIDY) - n += (*m_grid)[index(new_x, new_y)]; - } - - return n; -} - -void GameOfLifeDisplay::computeCA() -{ - for (int16_t x = 1; x < GRIDX; x++) { - for (int16_t y = 1; y < GRIDY; y++) { - int neighbors = getNumberOfNeighbors(x, y); - if ((*m_grid)[index(x,y)] == true && (neighbors == 2 || neighbors == 3 )) - (*m_newgrid)[index(x,y)] = true; - else if ((*m_grid)[index(x,y)] == 1) - (*m_newgrid)[index(x,y)] = false; - if ((*m_grid)[index(x,y)] == false && (neighbors == 3)) - (*m_newgrid)[index(x,y)] = true; - else if ((*m_grid)[index(x,y)] == 0) - (*m_newgrid)[index(x,y)] = false; - } - } -} - -} diff --git a/main/displays/menus/otamenu.cpp b/main/displays/menus/otamenu.cpp new file mode 100644 index 0000000..422fafc --- /dev/null +++ b/main/displays/menus/otamenu.cpp @@ -0,0 +1,46 @@ +#include "otamenu.h" + +// 3rdparty lib includes +#include "actioninterface.h" +#include "actions/dummyaction.h" +#include "actions/switchscreenaction.h" +#include "icons/back.h" + +// local includes +#include "utils.h" +#include "icons/update.h" +#include "icons/presets.h" +#include "buildserver.h" +#include "displays/menus/selectotabuildmenu.h" +#include "displays/updatedisplay.h" +#include "displays/menus/selectbuildservermenu.h" +#include "displays/menus/mainmenu.h" + +namespace { + +class RedownloadJsonAction : public virtual espgui::ActionInterface +{ +public: + void triggered() override + { + redownload = true; + } +}; + +} // namespace + +using namespace espgui; + +OtaMenu::OtaMenu() +{ + constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&bobbyicons::presets>>>(); + constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&bobbyicons::update>>>(); + constructMenuItem, SwitchScreenAction>>(); + constructMenuItem, RedownloadJsonAction>>(); + constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); +} + +void OtaMenu::back() +{ + switchScreen(); +} diff --git a/main/displays/menus/otamenu.h b/main/displays/menus/otamenu.h index 30dbacb..1e07b27 100644 --- a/main/displays/menus/otamenu.h +++ b/main/displays/menus/otamenu.h @@ -1,40 +1,17 @@ #pragma once -// local includes +// 3rdparty lib includes #include "menudisplay.h" -#include "actioninterface.h" -#include "utils.h" -#include "actions/dummyaction.h" -#include "icons/back.h" -#include "icons/update.h" -#include "icons/presets.h" + +// local includes #include "texts.h" -#include "buildserver.h" - -using namespace espgui; - -namespace { - -class RedownloadJsonAction : public virtual ActionInterface { -public: - void triggered() override { - redownload = true; - } -}; class OtaMenu : - public MenuDisplay, - public StaticText, - public BackActionInterface> + public espgui::MenuDisplay, + public espgui::StaticText { public: - OtaMenu() - { - constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&bobbyicons::presets>>>(); - constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&bobbyicons::update>>>(); - constructMenuItem, SwitchScreenAction>>(); - constructMenuItem, RedownloadJsonAction>>(); - constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); - } + OtaMenu(); + + void back() override; }; -} // namespace diff --git a/main/displays/menus/selectotabuildmenu.cpp b/main/displays/menus/selectotabuildmenu.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/displays/menus/selectotabuildmenu.h b/main/displays/menus/selectotabuildmenu.h index 5398579..3c9c051 100644 --- a/main/displays/menus/selectotabuildmenu.h +++ b/main/displays/menus/selectotabuildmenu.h @@ -18,11 +18,6 @@ #define MESSAGE(text) constructMenuItem, DefaultFont, StaticColor, DummyAction>>() -// forward declares -namespace { -class OtaMenu; -} // namespace - using namespace espgui; namespace { diff --git a/main/displays/pingpongdisplay.cpp b/main/displays/pingpongdisplay.cpp index e69de29..abd76a7 100644 --- a/main/displays/pingpongdisplay.cpp +++ b/main/displays/pingpongdisplay.cpp @@ -0,0 +1,175 @@ +#include "pingpongdisplay.h" + +// 3rdparty lib includes +#include +#include +#include +#include + +// local includes +#include "displays/menus/demosmenu.h" + +PingPongDisplay::PingPongDisplay() : + lpaddle_y(cpputils::randomNumber(0, h - paddle_h, espcpputils::esp_random_device{})), + rpaddle_y(cpputils::randomNumber(0, h - paddle_h, espcpputils::esp_random_device{})), + // ball is placed on the center of the left paddle + ball_y(lpaddle_y + (paddle_h / 2)) +{ + calc_target_y(); +} + +void PingPongDisplay::initScreen() +{ + espgui::tft.fillScreen(TFT_BLACK); + espgui::tft.setRotation(1); + + midline(); +} + +void PingPongDisplay::redraw() +{ + lpaddle(); + rpaddle(); + + midline(); + + ball(); +} + +void PingPongDisplay::stop() +{ + espgui::tft.setRotation(0); +} + +void PingPongDisplay::confirm() +{ + espgui::switchScreen(); +} + +void PingPongDisplay::back() +{ + espgui::switchScreen(); +} + +void PingPongDisplay::midline() +{ + // If the ball is not on the line then don't redraw the line + if ((ball_x dashline_x+dashline_w)) return; + + espgui::tft.startWrite(); + + // Quick way to draw a dashed line + espgui::tft.setAddrWindow(dashline_x, 0, dashline_w, h); + + for (int16_t i = 0; i < dashline_n; i+=2) + { + espgui::tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels + espgui::tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels + } + + espgui::tft.endWrite(); +} + +void PingPongDisplay::lpaddle() +{ + if (lpaddle_d == 1) + { + espgui::tft.fillRect(lpaddle_x, lpaddle_y, paddle_w, 1, BLACK); + } + else if (lpaddle_d == -1) + { + espgui::tft.fillRect(lpaddle_x, lpaddle_y + paddle_h - 1, paddle_w, 1, BLACK); + } + + lpaddle_y = lpaddle_y + lpaddle_d; + + if (ball_dx == 1) + lpaddle_d = 0; + else + { + if (lpaddle_y + paddle_h / 2 == target_y) lpaddle_d = 0; + else if (lpaddle_y + paddle_h / 2 > target_y) lpaddle_d = -1; + else lpaddle_d = 1; + } + + if (lpaddle_y + paddle_h >= h && lpaddle_d == 1) lpaddle_d = 0; + else if (lpaddle_y <= 0 && lpaddle_d == -1) lpaddle_d = 0; + + espgui::tft.fillRect(lpaddle_x, lpaddle_y, paddle_w, paddle_h, WHITE); +} + +void PingPongDisplay::rpaddle() +{ + if (rpaddle_d == 1) + espgui::tft.fillRect(rpaddle_x, rpaddle_y, paddle_w, 1, BLACK); + else if (rpaddle_d == -1) + espgui::tft.fillRect(rpaddle_x, rpaddle_y + paddle_h - 1, paddle_w, 1, BLACK); + + rpaddle_y = rpaddle_y + rpaddle_d; + + if (ball_dx == -1) + rpaddle_d = 0; + else + { + if (rpaddle_y + paddle_h / 2 == target_y) rpaddle_d = 0; + else if (rpaddle_y + paddle_h / 2 > target_y) rpaddle_d = -1; + else rpaddle_d = 1; + } + + if (rpaddle_y + paddle_h >= h && rpaddle_d == 1) + rpaddle_d = 0; + else if (rpaddle_y <= 0 && rpaddle_d == -1) + rpaddle_d = 0; + + espgui::tft.fillRect(rpaddle_x, rpaddle_y, paddle_w, paddle_h, WHITE); +} + +void PingPongDisplay::calc_target_y() +{ + int16_t target_x; + int16_t reflections; + int16_t y; + + if (ball_dx == 1) + target_x = w - ball_w; + else + target_x = -1 * (w - ball_w); + + y = abs(target_x * (ball_dy / ball_dx) + ball_y); + + reflections = floor(y / h); + + if (reflections % 2 == 0) + target_y = y % h; + else + target_y = h - (y % h); +} + +void PingPongDisplay::ball() +{ + ball_x = ball_x + ball_dx; + ball_y = ball_y + ball_dy; + + if (ball_dx == -1 && ball_x == paddle_w && ball_y + ball_h >= lpaddle_y && ball_y <= lpaddle_y + paddle_h) { + ball_dx = ball_dx * -1; + dly = cpputils::randomNumber(5, espcpputils::esp_random_device{}); // change speed of ball after paddle contact + calc_target_y(); + } else if (ball_dx == 1 && ball_x + ball_w == w - paddle_w && ball_y + ball_h >= rpaddle_y && ball_y <= rpaddle_y + paddle_h) { + ball_dx = ball_dx * -1; + dly = cpputils::randomNumber(5, espcpputils::esp_random_device{}); // change speed of ball after paddle contact + calc_target_y(); + } else if ((ball_dx == 1 && ball_x >= w) || (ball_dx == -1 && ball_x + ball_w < 0)) { + dly = 5; + } + + if (ball_y > h - ball_w || ball_y < 0) { + ball_dy = ball_dy * -1; + ball_y += ball_dy; // Keep in bounds + } + + //tft.fillRect(oldball_x, oldball_y, ball_w, ball_h, BLACK); + espgui::tft.drawRect(oldball_x, oldball_y, ball_w, ball_h, BLACK); // Less TFT refresh aliasing than line above for large balls + espgui::tft.fillRect( ball_x, ball_y, ball_w, ball_h, WHITE); + oldball_x = ball_x; + oldball_y = ball_y; +} diff --git a/main/displays/pingpongdisplay.h b/main/displays/pingpongdisplay.h index 9fc412d..2fd554e 100644 --- a/main/displays/pingpongdisplay.h +++ b/main/displays/pingpongdisplay.h @@ -4,15 +4,9 @@ #include // 3rdparty lib includes -#include -#include - -// local includes #include "display.h" -#include "actions/switchscreenaction.h" -namespace { -class PingPongDisplay : public Display, public ConfirmActionInterface>, public BackActionInterface> +class PingPongDisplay : public espgui::Display { public: PingPongDisplay(); @@ -21,6 +15,9 @@ public: void redraw() override; void stop() override; + void confirm() override; + void back() override; + private: void midline(); void lpaddle(); @@ -74,160 +71,3 @@ private: static const constexpr auto WHITE = 0xFFFF; static const constexpr auto GREY = 0x5AEB; }; - -PingPongDisplay::PingPongDisplay() : - lpaddle_y(cpputils::randomNumber(0, h - paddle_h, espcpputils::esp_random_device{})), - rpaddle_y(cpputils::randomNumber(0, h - paddle_h, espcpputils::esp_random_device{})), - // ball is placed on the center of the left paddle - ball_y(lpaddle_y + (paddle_h / 2)) -{ - calc_target_y(); -} - -void PingPongDisplay::initScreen() -{ - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - - midline(); -} - -void PingPongDisplay::redraw() -{ - lpaddle(); - rpaddle(); - - midline(); - - ball(); -} - -void PingPongDisplay::stop() -{ - tft.setRotation(0); -} - -void PingPongDisplay::midline() -{ - // If the ball is not on the line then don't redraw the line - if ((ball_x dashline_x+dashline_w)) return; - - tft.startWrite(); - - // Quick way to draw a dashed line - tft.setAddrWindow(dashline_x, 0, dashline_w, h); - - for(int16_t i = 0; i < dashline_n; i+=2) { - tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels - tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels - } - - tft.endWrite(); -} - -void PingPongDisplay::lpaddle() -{ - if (lpaddle_d == 1) - { - tft.fillRect(lpaddle_x, lpaddle_y, paddle_w, 1, BLACK); - } - else if (lpaddle_d == -1) - { - tft.fillRect(lpaddle_x, lpaddle_y + paddle_h - 1, paddle_w, 1, BLACK); - } - - lpaddle_y = lpaddle_y + lpaddle_d; - - if (ball_dx == 1) - lpaddle_d = 0; - else - { - if (lpaddle_y + paddle_h / 2 == target_y) lpaddle_d = 0; - else if (lpaddle_y + paddle_h / 2 > target_y) lpaddle_d = -1; - else lpaddle_d = 1; - } - - if (lpaddle_y + paddle_h >= h && lpaddle_d == 1) lpaddle_d = 0; - else if (lpaddle_y <= 0 && lpaddle_d == -1) lpaddle_d = 0; - - tft.fillRect(lpaddle_x, lpaddle_y, paddle_w, paddle_h, WHITE); -} - -void PingPongDisplay::rpaddle() -{ - if (rpaddle_d == 1) { - tft.fillRect(rpaddle_x, rpaddle_y, paddle_w, 1, BLACK); - } - else if (rpaddle_d == -1) { - tft.fillRect(rpaddle_x, rpaddle_y + paddle_h - 1, paddle_w, 1, BLACK); - } - - rpaddle_y = rpaddle_y + rpaddle_d; - - if (ball_dx == -1) rpaddle_d = 0; - else { - if (rpaddle_y + paddle_h / 2 == target_y) rpaddle_d = 0; - else if (rpaddle_y + paddle_h / 2 > target_y) rpaddle_d = -1; - else rpaddle_d = 1; - } - - if (rpaddle_y + paddle_h >= h && rpaddle_d == 1) rpaddle_d = 0; - else if (rpaddle_y <= 0 && rpaddle_d == -1) rpaddle_d = 0; - - tft.fillRect(rpaddle_x, rpaddle_y, paddle_w, paddle_h, WHITE); -} - -void PingPongDisplay::calc_target_y() -{ - int16_t target_x; - int16_t reflections; - int16_t y; - - if (ball_dx == 1) { - target_x = w - ball_w; - } - else { - target_x = -1 * (w - ball_w); - } - - y = abs(target_x * (ball_dy / ball_dx) + ball_y); - - reflections = floor(y / h); - - if (reflections % 2 == 0) { - target_y = y % h; - } - else { - target_y = h - (y % h); - } -} - -void PingPongDisplay::ball() -{ - ball_x = ball_x + ball_dx; - ball_y = ball_y + ball_dy; - - if (ball_dx == -1 && ball_x == paddle_w && ball_y + ball_h >= lpaddle_y && ball_y <= lpaddle_y + paddle_h) { - ball_dx = ball_dx * -1; - dly = cpputils::randomNumber(5, espcpputils::esp_random_device{}); // change speed of ball after paddle contact - calc_target_y(); - } else if (ball_dx == 1 && ball_x + ball_w == w - paddle_w && ball_y + ball_h >= rpaddle_y && ball_y <= rpaddle_y + paddle_h) { - ball_dx = ball_dx * -1; - dly = cpputils::randomNumber(5, espcpputils::esp_random_device{}); // change speed of ball after paddle contact - calc_target_y(); - } else if ((ball_dx == 1 && ball_x >= w) || (ball_dx == -1 && ball_x + ball_w < 0)) { - dly = 5; - } - - if (ball_y > h - ball_w || ball_y < 0) { - ball_dy = ball_dy * -1; - ball_y += ball_dy; // Keep in bounds - } - - //tft.fillRect(oldball_x, oldball_y, ball_w, ball_h, BLACK); - tft.drawRect(oldball_x, oldball_y, ball_w, ball_h, BLACK); // Less TFT refresh aliasing than line above for large balls - tft.fillRect( ball_x, ball_y, ball_w, ball_h, WHITE); - oldball_x = ball_x; - oldball_y = ball_y; -} -} diff --git a/main/displays/spirodisplay.cpp b/main/displays/spirodisplay.cpp index e69de29..7475771 100644 --- a/main/displays/spirodisplay.cpp +++ b/main/displays/spirodisplay.cpp @@ -0,0 +1,120 @@ +#include "spirodisplay.h" + +// 3rdparty lib includes +#include +#include +#include +#include + +// local includes +#include "displays/menus/demosmenu.h" + +void SpiroDisplay::initScreen() +{ + Base::initScreen(); + espgui::tft.setRotation(3); +} + +void SpiroDisplay::redraw() +{ + for (int j = 0; j < std::max(1, n); j++) + { + if (i == 0) + { + espgui::tft.fillScreen(TFT_BLACK); + n = cpputils::randomNumber(2, 23, espcpputils::esp_random_device{}); + r = cpputils::randomNumber(20, 100, espcpputils::esp_random_device{}); + colour = 0; //rainbow(); + } + + if (i < (360 * n)) + { + sx = std::cos((i / n - 90) * DEG2RAD); + sy = std::sin((i / n - 90) * DEG2RAD); + x0 = sx * (120 - r) + 159; + yy0 = sy * (120 - r) + 119; + + + sy = std::cos(((i % 360) - 90) * DEG2RAD); + sx = std::sin(((i % 360) - 90) * DEG2RAD); + x1 = sx * r + x0; + yy1 = sy * r + yy0; + espgui::tft.drawPixel(x1, yy1, rainbow(map(i%360,0,360,0,127))); //colour); + } + + if (i == (360 * n)) + { + r = cpputils::randomNumber(20, 100, espcpputils::esp_random_device{});//r = r / random(2,4); + } + + if (i >= (360 * n)) + { + auto new_i = i - (360 * n); + + sx = std::cos((new_i / n - 90) * DEG2RAD); + sy = std::sin((new_i / n - 90) * DEG2RAD); + x0 = sx * (120 - r) + 159; + yy0 = sy * (120 - r) + 119; + + + sy = std::cos(((new_i % 360) - 90) * DEG2RAD); + sx = std::sin(((new_i % 360) - 90) * DEG2RAD); + x1 = sx * r + x0; + yy1 = sy * r + yy0; + espgui::tft.drawPixel(x1, yy1, rainbow(map(new_i%360,0,360,0,127))); //colour); + } + + i++; + if (i == 2* (360 * n)) + i = 0; + } +} + +void SpiroDisplay::stop() +{ + espgui::tft.setRotation(0); +} + +unsigned int SpiroDisplay::rainbow(int value) +{ + // Value is expected to be in range 0-127 + // The value is converted to a spectrum colour from 0 = blue through to red = blue + //int value = random (128); + byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte green = 0;// Green is the middle 6 bits + byte blue = 0; // Blue is the bottom 5 bits + + byte quadrant = value / 32; + + if (quadrant == 0) { + blue = 31; + green = 2 * (value % 32); + red = 0; + } + if (quadrant == 1) { + blue = 31 - (value % 32); + green = 63; + red = 0; + } + if (quadrant == 2) { + blue = 0; + green = 63; + red = value % 32; + } + if (quadrant == 3) { + blue = 0; + green = 63 - 2 * (value % 32); + red = 31; + } + return (red << 11) + (green << 5) + blue; +} + +void SpiroDisplay::confirm() +{ + espgui::switchScreen(); +} + +void SpiroDisplay::back() +{ + espgui::switchScreen(); +} diff --git a/main/displays/spirodisplay.h b/main/displays/spirodisplay.h index 95019ac..67dd2b6 100644 --- a/main/displays/spirodisplay.h +++ b/main/displays/spirodisplay.h @@ -3,22 +3,22 @@ // system includes #include -// 3rdparty lib includes -#include -#include - // local includes #include "display.h" #include "actions/switchscreenaction.h" -namespace { -class SpiroDisplay : public Display, public DummyConfirm, public BackActionInterface> +class SpiroDisplay : public espgui::Display { + using Base = espgui::Display; + public: void initScreen() override; void redraw() override; void stop() override; + void confirm() override; + void back() override; + private: constexpr static auto DEG2RAD = 0.0174532925; @@ -30,104 +30,3 @@ private: long i{0}; int n{}, r{}, colour{}; }; - -void SpiroDisplay::initScreen() -{ - tft.fillScreen(TFT_BLACK); - tft.setRotation(3); -} - -void SpiroDisplay::redraw() -{ - for (int j = 0; j < std::max(1, n); j++) - { - if (i == 0) - { - tft.fillScreen(TFT_BLACK); - n = cpputils::randomNumber(2, 23, espcpputils::esp_random_device{}); - r = cpputils::randomNumber(20, 100, espcpputils::esp_random_device{}); - colour = 0; //rainbow(); - } - - if (i < (360 * n)) - { - sx = std::cos((i / n - 90) * DEG2RAD); - sy = std::sin((i / n - 90) * DEG2RAD); - x0 = sx * (120 - r) + 159; - yy0 = sy * (120 - r) + 119; - - - sy = std::cos(((i % 360) - 90) * DEG2RAD); - sx = std::sin(((i % 360) - 90) * DEG2RAD); - x1 = sx * r + x0; - yy1 = sy * r + yy0; - tft.drawPixel(x1, yy1, rainbow(map(i%360,0,360,0,127))); //colour); - } - - if (i == (360 * n)) - { - r = cpputils::randomNumber(20, 100, espcpputils::esp_random_device{});//r = r / random(2,4); - } - - if (i >= (360 * n)) - { - auto new_i = i - (360 * n); - - sx = std::cos((new_i / n - 90) * DEG2RAD); - sy = std::sin((new_i / n - 90) * DEG2RAD); - x0 = sx * (120 - r) + 159; - yy0 = sy * (120 - r) + 119; - - - sy = std::cos(((new_i % 360) - 90) * DEG2RAD); - sx = std::sin(((new_i % 360) - 90) * DEG2RAD); - x1 = sx * r + x0; - yy1 = sy * r + yy0; - tft.drawPixel(x1, yy1, rainbow(map(new_i%360,0,360,0,127))); //colour); - } - - i++; - if (i == 2* (360 * n)) - i = 0; - } -} - -void SpiroDisplay::stop() -{ - tft.setRotation(0); -} - -unsigned int SpiroDisplay::rainbow(int value) -{ - // Value is expected to be in range 0-127 - // The value is converted to a spectrum colour from 0 = blue through to red = blue - //int value = random (128); - byte red = 0; // Red is the top 5 bits of a 16 bit colour value - byte green = 0;// Green is the middle 6 bits - byte blue = 0; // Blue is the bottom 5 bits - - byte quadrant = value / 32; - - if (quadrant == 0) { - blue = 31; - green = 2 * (value % 32); - red = 0; - } - if (quadrant == 1) { - blue = 31 - (value % 32); - green = 63; - red = 0; - } - if (quadrant == 2) { - blue = 0; - green = 63; - red = value % 32; - } - if (quadrant == 3) { - blue = 0; - green = 63 - 2 * (value % 32); - red = 31; - } - return (red << 11) + (green << 5) + blue; -} -} diff --git a/main/displays/updatedisplay.cpp b/main/displays/updatedisplay.cpp index e69de29..f4015ae 100644 --- a/main/displays/updatedisplay.cpp +++ b/main/displays/updatedisplay.cpp @@ -0,0 +1,114 @@ +#include "updatedisplay.h" + +// system includes +#include +#include + +// esp-idf includes +#include + +// 3rdparty lib includes +#include +#include +#ifdef FEATURE_OTA +#include +#include +#endif + +// local includes +#include "globals.h" +#include "texts.h" +#include "ota.h" +#include "displays/menus/otamenu.h" + +#ifdef FEATURE_OTA +void UpdateDisplay::initScreen() +{ + Base::initScreen(); + + espgui::tft.setTextFont(4); + espgui::tft.setTextColor(TFT_YELLOW); + + espgui::tft.drawString(TEXT_UPDATE, 5, 5, 4); + + espgui::tft.fillRect(0, 34, espgui::tft.width(), 3, TFT_WHITE); + + espgui::tft.setTextColor(TFT_WHITE, TFT_BLACK); + + espgui::tft.drawString("Status:", 20, m_statusLabel.y()); + m_statusLabel.start(); + + espgui::tft.drawString("Progress:", 20, m_progressLabel.y()); + m_progressLabel.start(); + + espgui::tft.drawString("Total:", 20, m_totalLabel.y()); + m_totalLabel.start(); + + m_messageLabel.start(); + + m_progressBar.start(); + + if (const esp_app_desc_t *app_desc = esp_ota_get_app_description()) + { + espgui::tft.setTextColor(TFT_ORANGE, TFT_BLACK); + espgui::tft.drawString(app_desc->version, 20, 250); + espgui::tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + + m_newVersionLabel.start(); +} + +void UpdateDisplay::redraw() +{ + Base::redraw(); + + if (asyncOta) + { + m_statusLabel.redraw(toString(asyncOta->status())); + const auto progress = asyncOta->progress(); + m_progressLabel.redraw(std::to_string(progress)); + if (const auto totalSize = asyncOta->totalSize(); totalSize && *totalSize > 0) + { + m_totalLabel.redraw(std::to_string(*totalSize)); + m_progressBar.redraw(float(progress) / *totalSize * 100); + } + else + { + m_totalLabel.clear(); + m_progressBar.redraw(0); + } + m_messageLabel.redraw(asyncOta->message()); + + if (const auto &appDesc = asyncOta->appDesc()) + { + espgui::tft.setTextColor(TFT_GREEN, TFT_BLACK); + m_newVersionLabel.redraw(appDesc->version); + espgui::tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + else + m_newVersionLabel.clear(); + } + else + { + m_statusLabel.clear(); + m_progressLabel.clear(); + m_totalLabel.clear(); + m_messageLabel.clear(); + + m_progressBar.redraw(0); + + m_newVersionLabel.clear(); + } +} + +void UpdateDisplay::confirm() +{ + if (const auto result = triggerOta(stringSettings.otaUrl); !result) + ESP_LOGE("BOBBY", "triggerOta() failed with %.*s", result.error().size(), result.error().data()); +} + +void UpdateDisplay::back() +{ + espgui::switchScreen(); +} +#endif diff --git a/main/displays/updatedisplay.h b/main/displays/updatedisplay.h index 6e0a60c..087381f 100644 --- a/main/displays/updatedisplay.h +++ b/main/displays/updatedisplay.h @@ -1,136 +1,30 @@ #pragma once -// system includes -#include -#include - -// esp-idf includes -#include - // 3rdparty lib includes -#ifdef FEATURE_OTA -#include -#include -#endif // local includes #include "display.h" -#include "actions/switchscreenaction.h" -#include "globals.h" -#include "texts.h" #include "widgets/label.h" #include "widgets/progressbar.h" -#include "ota.h" -namespace { -class OtaMenu; -} - -namespace { #ifdef FEATURE_OTA -class UpdateDisplay : public Display, public BackActionInterface> +class UpdateDisplay : public espgui::Display { + using Base = espgui::Display; public: - void start() override; void initScreen() override; void redraw() override; void confirm() override; + void back() override; private: - Label m_statusLabel{120, 75}; - Label m_progressLabel{120, 100}; - Label m_totalLabel{120, 125}; - Label m_messageLabel{20, 150}; + espgui::Label m_statusLabel{120, 75}; + espgui::Label m_progressLabel{120, 100}; + espgui::Label m_totalLabel{120, 125}; + espgui::Label m_messageLabel{20, 150}; - ProgressBar m_progressBar{20, 200, 200, 10, 0, 100}; + espgui::ProgressBar m_progressBar{20, 200, 200, 10, 0, 100}; - Label m_newVersionLabel{20, 275}; + espgui::Label m_newVersionLabel{20, 275}; }; - -void UpdateDisplay::start() -{ -} - -void UpdateDisplay::initScreen() -{ - tft.fillScreen(TFT_BLACK); - tft.setTextFont(4); - tft.setTextColor(TFT_YELLOW); - - tft.drawString(TEXT_UPDATE, 5, 5, 4); - - tft.fillRect(0, 34, tft.width(), 3, TFT_WHITE); - - tft.setTextColor(TFT_WHITE, TFT_BLACK); - - tft.drawString("Status:", 20, m_statusLabel.y()); - m_statusLabel.start(); - - tft.drawString("Progress:", 20, m_progressLabel.y()); - m_progressLabel.start(); - - tft.drawString("Total:", 20, m_totalLabel.y()); - m_totalLabel.start(); - - m_messageLabel.start(); - - m_progressBar.start(); - - if (const esp_app_desc_t *app_desc = esp_ota_get_app_description()) - { - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.drawString(app_desc->version, 20, 250); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - - m_newVersionLabel.start(); -} - -void UpdateDisplay::redraw() -{ - if (asyncOta) - { - m_statusLabel.redraw(toString(asyncOta->status())); - const auto progress = asyncOta->progress(); - m_progressLabel.redraw(std::to_string(progress)); - if (const auto totalSize = asyncOta->totalSize(); totalSize && *totalSize > 0) - { - m_totalLabel.redraw(std::to_string(*totalSize)); - m_progressBar.redraw(float(progress) / *totalSize * 100); - } - else - { - m_totalLabel.clear(); - m_progressBar.redraw(0); - } - m_messageLabel.redraw(asyncOta->message()); - - if (const auto &appDesc = asyncOta->appDesc()) - { - tft.setTextColor(TFT_GREEN, TFT_BLACK); - m_newVersionLabel.redraw(appDesc->version); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - else - m_newVersionLabel.clear(); - } - else - { - m_statusLabel.clear(); - m_progressLabel.clear(); - m_totalLabel.clear(); - m_messageLabel.clear(); - - m_progressBar.redraw(0); - - m_newVersionLabel.clear(); - } -} - -void UpdateDisplay::confirm() -{ - if (const auto result = triggerOta(stringSettings.otaUrl); !result) - ESP_LOGE("BOBBY", "triggerOta() failed with %.*s", result.error().size(), result.error().data()); -} #endif -} diff --git a/main/ota.cpp b/main/ota.cpp index e69de29..1ec404d 100644 --- a/main/ota.cpp +++ b/main/ota.cpp @@ -0,0 +1,52 @@ +#include "ota.h" + +// esp-idf includes +#include + +// 3rdparty lib includes +#include + +#ifdef FEATURE_OTA +extern cpputils::DelayedConstruction asyncOta; +extern bool asyncOtaTaskStarted; + +namespace { +constexpr const char * const TAG = "BOBBYOTA"; +} // namespace + +void initOta() +{ +} + +void handleOta() +{ + if (asyncOta) + asyncOta->update(); +} + +tl::expected triggerOta(std::string_view url) +{ + ESP_LOGI(TAG, "%.*s", url.size(), url.data()); + + if (!asyncOta) + asyncOta.construct(); + + if (!asyncOtaTaskStarted) + { + if (const auto result = asyncOta->startTask(); !result) + { + ESP_LOGE(TAG, "starting OTA task failed: %.*s", result.error().size(), result.error().data()); + return tl::make_unexpected(fmt::format("starting OTA task failed: {}", result.error())); + } + + asyncOtaTaskStarted = true; + } + + if (const auto result = asyncOta->trigger(url, {}, {}, {}); !result) + return tl::make_unexpected(std::move(result).error()); + + wifi_stack::delete_scan_result(); + + return {}; +} +#endif diff --git a/main/ota.h b/main/ota.h index 233fca5..8ad7c47 100644 --- a/main/ota.h +++ b/main/ota.h @@ -8,45 +8,11 @@ // local includes -namespace { #ifdef FEATURE_OTA cpputils::DelayedConstruction asyncOta; bool asyncOtaTaskStarted{}; -void initOta() -{ -} - -void handleOta() -{ - if (asyncOta) - asyncOta->update(); -} - -tl::expected triggerOta(std::string_view url) -{ - ESP_LOGI(TAG, "%.*s", url.size(), url.data()); - - if (!asyncOta) - asyncOta.construct(); - - if (!asyncOtaTaskStarted) - { - if (const auto result = asyncOta->startTask(); !result) - { - ESP_LOGE(TAG, "starting OTA task failed: %.*s", result.error().size(), result.error().data()); - return tl::make_unexpected(fmt::format("starting OTA task failed: {}", result.error())); - } - - asyncOtaTaskStarted = true; - } - - if (const auto result = asyncOta->trigger(url, {}, {}, {}); !result) - return tl::make_unexpected(std::move(result).error()); - - wifi_stack::delete_scan_result(); - - return {}; -} +void initOta(); +void handleOta(); +tl::expected triggerOta(std::string_view url); #endif -}