add screensaver and optimize performance
Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.30)
|
|||||||
|
|
||||||
if (DEFINED ENV{IDF_PATH})
|
if (DEFINED ENV{IDF_PATH})
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(espidf_system_control)
|
project(system_control)
|
||||||
return()
|
return()
|
||||||
else ()
|
else ()
|
||||||
set(MAJOR_VERSION 0)
|
set(MAJOR_VERSION 0)
|
||||||
|
10
components/bob/CMakeLists.txt
Normal file
10
components/bob/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
if (DEFINED ENV{IDF_PATH})
|
||||||
|
idf_component_register(SRCS
|
||||||
|
bob.c
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
PRIV_REQUIRES
|
||||||
|
bt
|
||||||
|
ruth
|
||||||
|
)
|
||||||
|
return()
|
||||||
|
endif ()
|
8
components/bob/bob.c
Normal file
8
components/bob/bob.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "bob.h"
|
||||||
|
|
||||||
|
#include "persistence.h"
|
||||||
|
|
||||||
|
void bob_init(void)
|
||||||
|
{
|
||||||
|
persistence_init("system_control");
|
||||||
|
}
|
10
components/bob/include/bob.h
Normal file
10
components/bob/include/bob.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
void bob_init(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,5 +1,6 @@
|
|||||||
if (DEFINED ENV{IDF_PATH})
|
if (DEFINED ENV{IDF_PATH})
|
||||||
idf_component_register(SRCS
|
idf_component_register(SRCS
|
||||||
|
src/common/InactivityTracker.cpp
|
||||||
src/common/Menu.cpp
|
src/common/Menu.cpp
|
||||||
src/common/ScrollBar.cpp
|
src/common/ScrollBar.cpp
|
||||||
src/common/Widget.cpp
|
src/common/Widget.cpp
|
||||||
@@ -7,6 +8,7 @@ if (DEFINED ENV{IDF_PATH})
|
|||||||
src/ui/LightMenu.cpp
|
src/ui/LightMenu.cpp
|
||||||
src/ui/LightSettingsMenu.cpp
|
src/ui/LightSettingsMenu.cpp
|
||||||
src/ui/MainMenu.cpp
|
src/ui/MainMenu.cpp
|
||||||
|
src/ui/ScreenSaver.cpp
|
||||||
src/ui/SettingsMenu.cpp
|
src/ui/SettingsMenu.cpp
|
||||||
src/ui/SplashScreen.cpp
|
src/ui/SplashScreen.cpp
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
@@ -21,6 +23,7 @@ cmake_minimum_required(VERSION 3.30)
|
|||||||
project(insa)
|
project(insa)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC
|
add_library(${PROJECT_NAME} STATIC
|
||||||
|
src/common/InactivityTracker.cpp
|
||||||
src/common/Menu.cpp
|
src/common/Menu.cpp
|
||||||
src/common/ScrollBar.cpp
|
src/common/ScrollBar.cpp
|
||||||
src/common/Widget.cpp
|
src/common/Widget.cpp
|
||||||
@@ -28,6 +31,7 @@ add_library(${PROJECT_NAME} STATIC
|
|||||||
src/ui/LightMenu.cpp
|
src/ui/LightMenu.cpp
|
||||||
src/ui/LightSettingsMenu.cpp
|
src/ui/LightSettingsMenu.cpp
|
||||||
src/ui/MainMenu.cpp
|
src/ui/MainMenu.cpp
|
||||||
|
src/ui/ScreenSaver.cpp
|
||||||
src/ui/SettingsMenu.cpp
|
src/ui/SettingsMenu.cpp
|
||||||
src/ui/SplashScreen.cpp
|
src/ui/SplashScreen.cpp
|
||||||
)
|
)
|
||||||
|
20
components/insa/include/common/InactivityTracker.h
Normal file
20
components/insa/include/common/InactivityTracker.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class InactivityTracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InactivityTracker(uint64_t timeoutMs, std::function<void()> onTimeout);
|
||||||
|
|
||||||
|
void update(uint64_t dt);
|
||||||
|
void reset();
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_timeoutMs;
|
||||||
|
uint64_t m_elapsedTime;
|
||||||
|
bool m_enabled;
|
||||||
|
std::function<void()> m_onTimeout;
|
||||||
|
};
|
@@ -72,6 +72,8 @@ class Menu : public Widget
|
|||||||
*/
|
*/
|
||||||
void addText(uint8_t id, const std::string &text);
|
void addText(uint8_t id, const std::string &text);
|
||||||
|
|
||||||
|
void addTextCounter(uint8_t id, const std::string &text, const uint8_t value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a selection menu item (dropdown/list selection) to the menu
|
* @brief Adds a selection menu item (dropdown/list selection) to the menu
|
||||||
* @param id Unique identifier for this menu item (must be unique within the menu)
|
* @param id Unique identifier for this menu item (must be unique within the menu)
|
||||||
|
37
components/insa/include/ui/ScreenSaver.h
Normal file
37
components/insa/include/ui/ScreenSaver.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MenuOptions.h"
|
||||||
|
#include "common/Widget.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ScreenSaver final : public Widget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ScreenSaver(menu_options_t *options);
|
||||||
|
|
||||||
|
void update(uint64_t dt) override;
|
||||||
|
void render() override;
|
||||||
|
void onButtonClicked(ButtonType button) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Star
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float speed;
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_options_t *m_options;
|
||||||
|
uint64_t m_animationCounter;
|
||||||
|
std::vector<Star> m_stars;
|
||||||
|
|
||||||
|
static constexpr int NUM_STARS = 10;
|
||||||
|
static constexpr float SPEED_MULTIPLIER = 0.02f;
|
||||||
|
static constexpr float Z_NEAR = 0.1f;
|
||||||
|
static constexpr float Z_FAR = 10.0f;
|
||||||
|
|
||||||
|
void initStars();
|
||||||
|
void resetStar(Star &star);
|
||||||
|
};
|
35
components/insa/src/common/InactivityTracker.cpp
Normal file
35
components/insa/src/common/InactivityTracker.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "common/InactivityTracker.h"
|
||||||
|
|
||||||
|
InactivityTracker::InactivityTracker(uint64_t timeoutMs, std::function<void()> onTimeout)
|
||||||
|
: m_timeoutMs(timeoutMs), m_elapsedTime(0), m_enabled(true), m_onTimeout(onTimeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTracker::update(uint64_t dt)
|
||||||
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_elapsedTime += dt;
|
||||||
|
|
||||||
|
if (m_elapsedTime >= m_timeoutMs && m_onTimeout)
|
||||||
|
{
|
||||||
|
m_onTimeout();
|
||||||
|
m_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTracker::reset()
|
||||||
|
{
|
||||||
|
m_elapsedTime = 0;
|
||||||
|
m_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTracker::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
m_enabled = enabled;
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
@@ -9,7 +9,8 @@ namespace MenuItemTypes
|
|||||||
constexpr uint8_t TEXT = 0;
|
constexpr uint8_t TEXT = 0;
|
||||||
constexpr uint8_t SELECTION = 1;
|
constexpr uint8_t SELECTION = 1;
|
||||||
constexpr uint8_t TOGGLE = 2;
|
constexpr uint8_t TOGGLE = 2;
|
||||||
}
|
constexpr uint8_t TEXT_COUNTER = 3;
|
||||||
|
} // namespace MenuItemTypes
|
||||||
|
|
||||||
// UI layout constants
|
// UI layout constants
|
||||||
namespace UIConstants
|
namespace UIConstants
|
||||||
@@ -23,14 +24,12 @@ constexpr int SELECTION_MARGIN = 10;
|
|||||||
constexpr int CORNER_RADIUS = 3;
|
constexpr int CORNER_RADIUS = 3;
|
||||||
constexpr int LINE_SPACING = 14;
|
constexpr int LINE_SPACING = 14;
|
||||||
constexpr int BOTTOM_OFFSET = 10;
|
constexpr int BOTTOM_OFFSET = 10;
|
||||||
}
|
} // namespace UIConstants
|
||||||
|
|
||||||
Menu::Menu(menu_options_t *options) : Widget(options->u8g2), m_options(options)
|
Menu::Menu(menu_options_t *options) : Widget(options->u8g2), m_options(options)
|
||||||
{
|
{
|
||||||
// Set up button callback using lambda to forward to member function
|
// Set up button callback using lambda to forward to member function
|
||||||
m_options->onButtonClicked = [this](const ButtonType button) {
|
m_options->onButtonClicked = [this](const ButtonType button) { onButtonClicked(button); };
|
||||||
onButtonClicked(button);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::~Menu()
|
Menu::~Menu()
|
||||||
@@ -183,6 +182,13 @@ void Menu::renderWidget(const MenuItem *item, const uint8_t *font, const int x,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MenuItemTypes::TEXT_COUNTER: {
|
||||||
|
const std::string formattedValue = "(" + item->getValue() + ") >";
|
||||||
|
const u8g2_uint_t textWidth = u8g2_GetStrWidth(u8g2, formattedValue.c_str());
|
||||||
|
u8g2_DrawStr(u8g2, u8g2->width - textWidth - UIConstants::SELECTION_MARGIN, y, formattedValue.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MenuItemTypes::SELECTION: {
|
case MenuItemTypes::SELECTION: {
|
||||||
// Format selection value with angle brackets
|
// Format selection value with angle brackets
|
||||||
const std::string formattedValue = "< " + item->getValue() + " >";
|
const std::string formattedValue = "< " + item->getValue() + " >";
|
||||||
@@ -308,12 +314,24 @@ void Menu::onPressedBack() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Menu::addText(uint8_t id, const std::string &text)
|
void Menu::addText(uint8_t id, const std::string &text)
|
||||||
|
{
|
||||||
|
addTextCounter(id, text, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::addTextCounter(uint8_t id, const std::string &text, const uint8_t value)
|
||||||
{
|
{
|
||||||
auto callback = [this](const MenuItem &menuItem, const ButtonType button) -> void {
|
auto callback = [this](const MenuItem &menuItem, const ButtonType button) -> void {
|
||||||
onButtonPressed(menuItem, button);
|
onButtonPressed(menuItem, button);
|
||||||
};
|
};
|
||||||
|
if (value > 0)
|
||||||
|
{
|
||||||
|
m_items.emplace_back(id, MenuItemTypes::TEXT_COUNTER, text, std::to_string(value), callback);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
m_items.emplace_back(id, MenuItemTypes::TEXT, text, callback);
|
m_items.emplace_back(id, MenuItemTypes::TEXT, text, callback);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Menu::addSelection(uint8_t id, const std::string &text, const std::vector<std::string> &values, const int index)
|
void Menu::addSelection(uint8_t id, const std::string &text, const std::vector<std::string> &values, const int index)
|
||||||
{
|
{
|
||||||
|
@@ -14,7 +14,7 @@ constexpr uint8_t SETTINGS = 2;
|
|||||||
MainMenu::MainMenu(menu_options_t *options) : Menu(options), m_options(options)
|
MainMenu::MainMenu(menu_options_t *options) : Menu(options), m_options(options)
|
||||||
{
|
{
|
||||||
addText(MainMenuItem::LIGHT, "Lichtsteuerung");
|
addText(MainMenuItem::LIGHT, "Lichtsteuerung");
|
||||||
addText(MainMenuItem::EXTERNAL_DEVICES, "Externe Geraete");
|
addTextCounter(MainMenuItem::EXTERNAL_DEVICES, "ext. Geraete", 0);
|
||||||
addText(MainMenuItem::SETTINGS, "Einstellungen");
|
addText(MainMenuItem::SETTINGS, "Einstellungen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
93
components/insa/src/ui/ScreenSaver.cpp
Normal file
93
components/insa/src/ui/ScreenSaver.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include "ui/ScreenSaver.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
ScreenSaver::ScreenSaver(menu_options_t *options) : Widget(options->u8g2), m_options(options), m_animationCounter(0)
|
||||||
|
{
|
||||||
|
initStars();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSaver::initStars()
|
||||||
|
{
|
||||||
|
m_stars.resize(NUM_STARS);
|
||||||
|
|
||||||
|
for (auto &star : m_stars)
|
||||||
|
{
|
||||||
|
resetStar(star);
|
||||||
|
star.z = Z_NEAR + (static_cast<float>(rand()) / RAND_MAX) * (Z_FAR - Z_NEAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSaver::resetStar(Star &star)
|
||||||
|
{
|
||||||
|
star.x = (static_cast<float>(rand()) / RAND_MAX - 0.5f) * 2.0f;
|
||||||
|
star.y = (static_cast<float>(rand()) / RAND_MAX - 0.5f) * 2.0f;
|
||||||
|
star.z = Z_FAR;
|
||||||
|
star.speed = 0.5f + (static_cast<float>(rand()) / RAND_MAX) * 1.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSaver::update(const uint64_t dt)
|
||||||
|
{
|
||||||
|
m_animationCounter += dt;
|
||||||
|
|
||||||
|
if (m_animationCounter > 8)
|
||||||
|
{
|
||||||
|
m_animationCounter = 0;
|
||||||
|
|
||||||
|
for (auto &star : m_stars)
|
||||||
|
{
|
||||||
|
star.z -= star.speed * SPEED_MULTIPLIER;
|
||||||
|
|
||||||
|
if (star.z < Z_NEAR)
|
||||||
|
{
|
||||||
|
resetStar(star);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSaver::render()
|
||||||
|
{
|
||||||
|
// Verwende Page-Buffer Mode statt Full-Buffer für bessere Performance
|
||||||
|
// Schwarzer Hintergrund
|
||||||
|
u8g2_SetDrawColor(u8g2, 0);
|
||||||
|
u8g2_DrawBox(u8g2, 0, 0, u8g2->width, u8g2->height);
|
||||||
|
u8g2_SetDrawColor(u8g2, 1);
|
||||||
|
|
||||||
|
const int centerX = u8g2->width / 2;
|
||||||
|
const int centerY = u8g2->height / 2;
|
||||||
|
|
||||||
|
// Zeichne nur sichtbare Sterne (Clipping)
|
||||||
|
for (const auto &star : m_stars)
|
||||||
|
{
|
||||||
|
// 3D zu 2D Projektion
|
||||||
|
int screenX = centerX + static_cast<int>((star.x / star.z) * centerX);
|
||||||
|
int screenY = centerY + static_cast<int>((star.y / star.z) * centerY);
|
||||||
|
|
||||||
|
// Frühe Prüfung für Performance
|
||||||
|
if (screenX < -5 || screenX >= u8g2->width + 5 || screenY < -5 || screenY >= u8g2->height + 5)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vereinfachte Sterndarstellung für bessere Performance
|
||||||
|
int size = static_cast<int>((1.0f - (star.z - Z_NEAR) / (Z_FAR - Z_NEAR)) * 2.0f);
|
||||||
|
|
||||||
|
if (size <= 0)
|
||||||
|
{
|
||||||
|
u8g2_DrawPixel(u8g2, screenX, screenY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Verwende u8g2_DrawCircle für größere Sterne (schneller)
|
||||||
|
u8g2_DrawCircle(u8g2, screenX, screenY, size, U8G2_DRAW_ALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSaver::onButtonClicked(ButtonType button)
|
||||||
|
{
|
||||||
|
if (m_options && m_options->popScreen)
|
||||||
|
{
|
||||||
|
m_options->popScreen();
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,7 @@ void SplashScreen::update(const uint64_t dt)
|
|||||||
{
|
{
|
||||||
counter += dt;
|
counter += dt;
|
||||||
#ifndef ESP32
|
#ifndef ESP32
|
||||||
if (counter > 20)
|
if (counter > 3000)
|
||||||
#else
|
#else
|
||||||
if (counter > 10)
|
if (counter > 10)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2,6 +2,8 @@ if (DEFINED ENV{IDF_PATH})
|
|||||||
idf_component_register(SRCS
|
idf_component_register(SRCS
|
||||||
persistence.c
|
persistence.c
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
|
PRIV_REQUIRES
|
||||||
|
nvs_flash
|
||||||
)
|
)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif ()
|
||||||
|
@@ -1,8 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
VALUE_TYPE_STRING,
|
||||||
|
VALUE_TYPE_INT32,
|
||||||
|
} persistence_value_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *name;
|
void *handle;
|
||||||
|
|
||||||
void (*save)(const char *key, const char *value);
|
void (*save)(const char *key, const char *value);
|
||||||
} persistence_t;
|
} persistence_t;
|
||||||
|
|
||||||
|
void *persistence_init(const char *namespace_name);
|
||||||
|
void persistence_save(persistence_value_t value_type, const char *key, const void *value);
|
||||||
|
void *persistence_load(persistence_value_t value_type, const char *key, void *out);
|
||||||
|
void persistence_deinit();
|
||||||
|
@@ -1,3 +1,116 @@
|
|||||||
//
|
#include "persistence.h"
|
||||||
// Created by Siegmund, Peter on 14.06.25.
|
|
||||||
//
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
static const char *TAG = "persistence";
|
||||||
|
|
||||||
|
static nvs_handle_t persistence_handle;
|
||||||
|
static SemaphoreHandle_t persistence_mutex;
|
||||||
|
|
||||||
|
void *persistence_init(const char *namespace_name)
|
||||||
|
{
|
||||||
|
esp_err_t ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(nvs_open(namespace_name, NVS_READWRITE, &persistence_handle));
|
||||||
|
|
||||||
|
persistence_mutex = xSemaphoreCreateMutex();
|
||||||
|
if (persistence_mutex == NULL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to create mutex");
|
||||||
|
}
|
||||||
|
return &persistence_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void persistence_save(persistence_value_t value_type, const char *key, const void *value)
|
||||||
|
{
|
||||||
|
if (persistence_mutex != NULL)
|
||||||
|
{
|
||||||
|
if (xSemaphoreTake(persistence_mutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
switch (value_type)
|
||||||
|
{
|
||||||
|
case VALUE_TYPE_STRING:
|
||||||
|
err = nvs_set_str(persistence_handle, key, (char *)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT32:
|
||||||
|
err = nvs_set_i32(persistence_handle, key, *(int32_t *)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unsupported value type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_commit(persistence_handle));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Error saving key %s: %s", key, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(persistence_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *persistence_load(persistence_value_t value_type, const char *key, void *out)
|
||||||
|
{
|
||||||
|
if (persistence_mutex != NULL)
|
||||||
|
{
|
||||||
|
if (xSemaphoreTake(persistence_mutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
switch (value_type)
|
||||||
|
{
|
||||||
|
case VALUE_TYPE_STRING:
|
||||||
|
err = nvs_get_str(persistence_handle, key, (char *)out, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT32:
|
||||||
|
err = nvs_get_i32(persistence_handle, key, (int32_t *)out);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unsupported value type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Error loading key %s: %s", key, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(persistence_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void persistence_deinit()
|
||||||
|
{
|
||||||
|
if (persistence_mutex != NULL)
|
||||||
|
{
|
||||||
|
vSemaphoreDelete(persistence_mutex);
|
||||||
|
persistence_mutex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(persistence_handle);
|
||||||
|
}
|
||||||
|
@@ -4,7 +4,8 @@ idf_component_register(SRCS
|
|||||||
"button_handling.c"
|
"button_handling.c"
|
||||||
"hal/u8g2_esp32_hal.c"
|
"hal/u8g2_esp32_hal.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
REQUIRES
|
PRIV_REQUIRES
|
||||||
|
bob
|
||||||
insa
|
insa
|
||||||
ruth
|
ruth
|
||||||
u8g2
|
u8g2
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
#include "u8g2.h"
|
#include "u8g2.h"
|
||||||
|
|
||||||
#include "button_handling.h"
|
#include "button_handling.h"
|
||||||
|
#include "common/InactivityTracker.h"
|
||||||
|
#include "ui/ScreenSaver.h"
|
||||||
#include "ui/SplashScreen.h"
|
#include "ui/SplashScreen.h"
|
||||||
|
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
@@ -28,6 +30,7 @@ uint8_t received_signal;
|
|||||||
|
|
||||||
std::shared_ptr<Widget> m_widget;
|
std::shared_ptr<Widget> m_widget;
|
||||||
std::vector<std::shared_ptr<Widget>> m_history;
|
std::vector<std::shared_ptr<Widget>> m_history;
|
||||||
|
std::unique_ptr<InactivityTracker> m_inactivityTracker;
|
||||||
|
|
||||||
extern QueueHandle_t buttonQueue;
|
extern QueueHandle_t buttonQueue;
|
||||||
|
|
||||||
@@ -88,10 +91,16 @@ static void init_ui(void)
|
|||||||
.persistence = nullptr,
|
.persistence = nullptr,
|
||||||
};
|
};
|
||||||
m_widget = std::make_shared<SplashScreen>(&options);
|
m_widget = std::make_shared<SplashScreen>(&options);
|
||||||
|
m_inactivityTracker = std::make_unique<InactivityTracker>(60000, []() {
|
||||||
|
auto screensaver = std::make_shared<ScreenSaver>(&options);
|
||||||
|
options.pushScreen(screensaver);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_button(uint8_t button)
|
static void handle_button(uint8_t button)
|
||||||
{
|
{
|
||||||
|
m_inactivityTracker->reset();
|
||||||
|
|
||||||
if (m_widget)
|
if (m_widget)
|
||||||
{
|
{
|
||||||
switch (button)
|
switch (button)
|
||||||
@@ -133,19 +142,24 @@ void app_task(void *args)
|
|||||||
setup_buttons();
|
setup_buttons();
|
||||||
init_ui();
|
init_ui();
|
||||||
|
|
||||||
|
auto oldTime = esp_timer_get_time();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
u8g2_ClearBuffer(&u8g2);
|
u8g2_ClearBuffer(&u8g2);
|
||||||
|
|
||||||
auto oldTime = esp_timer_get_time();
|
|
||||||
if (m_widget != nullptr)
|
if (m_widget != nullptr)
|
||||||
{
|
{
|
||||||
auto currentTime = esp_timer_get_time();
|
auto currentTime = esp_timer_get_time();
|
||||||
auto delta = currentTime - oldTime;
|
auto delta = currentTime - oldTime;
|
||||||
oldTime = currentTime;
|
oldTime = currentTime;
|
||||||
|
|
||||||
m_widget->update(delta);
|
uint64_t deltaMs = delta / 1000;
|
||||||
|
|
||||||
|
m_widget->update(deltaMs);
|
||||||
m_widget->render();
|
m_widget->render();
|
||||||
|
|
||||||
|
m_inactivityTracker->update(deltaMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8g2_SendBuffer(&u8g2);
|
u8g2_SendBuffer(&u8g2);
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master do not need buffer
|
#define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master do not need buffer
|
||||||
#define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master do not need buffer
|
#define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master do not need buffer
|
||||||
#define I2C_MASTER_FREQ_HZ 50000 // I2C master clock frequency
|
#define I2C_MASTER_FREQ_HZ 400000 // I2C master clock frequency
|
||||||
#define ACK_CHECK_EN 0x1 // I2C master will check ack from slave
|
#define ACK_CHECK_EN 0x1 // I2C master will check ack from slave
|
||||||
#define ACK_CHECK_DIS 0x0 // I2C master will not check ack from slave
|
#define ACK_CHECK_DIS 0x0 // I2C master will not check ack from slave
|
||||||
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#include "app_task.h"
|
#include "app_task.h"
|
||||||
|
#include "bob.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
@@ -7,7 +9,9 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
xTaskCreatePinnedToCore(app_task, "main_loop", 4096, NULL, 5, NULL, tskIDLE_PRIORITY + 1);
|
bob_init();
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(app_task, "main_loop", 4096, NULL, tskIDLE_PRIORITY + 1, NULL, portNUM_PROCESSORS - 1);
|
||||||
}
|
}
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user