#include #include "esp32-hal.h" #pragma once #include "program.h" #include "shell.h" #include "tft_handler.h" #include // Example Program 1: Simple counter class CounterProgram : public Program { private: int counter = 0; public: ~CounterProgram() { EventManager::getInstance().unsubscribe(this); } void run() override { Serial.println("Counter program started!"); WindowContentText text; text.x = _window->x + 10; text.y = _window->y + 50; text.size = 2; _window->window_content_text.push_back(text); while (_running) { counter++; Serial.printf("Counter: %d\n", counter); // You can modify the window title if (_window) { if (!_window->minimized) { _window->title = "Counter: " + std::to_string(counter); for (short i = 0; i < _window->window_content_text.size(); i++) { _window->window_content_text[i].text = std::to_string(counter); } _display_state->update_display.store(true); } } vTaskDelay(pdMS_TO_TICKS(1)); } } }; class TextEditorProgram : public Program { public: ~TextEditorProgram() { EventManager::getInstance().unsubscribe(this); } void on_click_event(CLICK_EVENT event) { if (_window->minimized) return; for (WindowContentText& text : _window->window_content_text) { if (event.x >= text.x && event.x <= (text.x + text.width) && event.y >= text.y && event.y <= (text.y + text.height) && (event.event == CLICK_EVENTS::LEFT_CLICK || event.event == CLICK_EVENTS::ENTER)) { if (text.selectable && !text.selected) { for (WindowContentText& temp : _window->window_content_text) temp.selected = false; text.selected = true; } } else if (event.event == CLICK_EVENTS::LEFT_CLICK || event.event == CLICK_EVENTS::ENTER) { if (text.selected) text.selected = false; } if (text.selected && event.event == CLICK_EVENTS::KEYBOARD) { text.text += event.character; } } } void run() override { EventManager::getInstance().subscribe(this); _window->x += 100; _window->width -= 50; WindowContentText text; text.x = _window->x + 5; text.y = _window->y + 60; text.width = 50; text.height = 10; text.size = 2; text.selectable = true; text.selected = false; text.text = "asddsa"; _window->window_content_text.push_back(text); while (_running) { for (WindowContentText text : _window->window_content_text) { if (text.selected) { } } vTaskDelay(pdMS_TO_TICKS(1)); } } }; class InternetTester : public Program { public: ~InternetTester() { EventManager::getInstance().unsubscribe(this); } void run() override { // You have full access to the window and can draw to it while (_running) { vTaskDelay(pdMS_TO_TICKS(1)); } } }; class CalculatorProgram : public Program { public: ~CalculatorProgram() { EventManager::getInstance().unsubscribe(this); } void run() override { while (_running) { // Calculator logic here vTaskDelay(pdMS_TO_TICKS(1)); } } }; class Chatty : public Program { public: ~Chatty() { EventManager::getInstance().unsubscribe(this); } void run() override { Serial.println("Chatty started!"); while (_running) { // Game logic and rendering vTaskDelay(pdMS_TO_TICKS(1)); } } }; class SettingsProgram : public Program { private: uint32_t max_idle_iterations; bool showing_buttons = false; public: ~SettingsProgram() { EventManager::getInstance().unsubscribe(this); } void on_click_event(CLICK_EVENT event) { if (_window->minimized) return; for (short i = 0; i < _window->content_buttons.size(); ++i) { auto c_button = _window->content_buttons[i]; if (event.x >= c_button.x && event.x <= (c_button.x + c_button.width) && event.y >= c_button.y && event.y <= (c_button.y + c_button.height)) { if (c_button.action == "show resources") { for (short j = 0; j < _window->content_buttons.size(); ++j) _window->content_buttons[j].pressed = false; _window->content_buttons[i].pressed = true; _display_state->update_display.store(true); break; } if (c_button.action == "show tasks") { for (short j = 0; j < _window->content_buttons.size(); ++j) _window->content_buttons[j].pressed = false; _window->content_buttons[i].pressed = true; _display_state->update_display.store(true); break; } } } } void run() override { EventManager::getInstance().subscribe(this); _window->x += 150; _window->width -= 50; Serial.println("Settings started!"); WindowContentText main_ram_usage_label; WindowContentText main_ram_usage; WindowContentText cpu_usage_label; WindowContentText cpu_usage; WindowContentText psram_usage_label; WindowContentText psram_usage; main_ram_usage_label.size = 2; main_ram_usage_label.text = "RAM usage:"; main_ram_usage_label.x = _window->x + 5; main_ram_usage_label.y = _window->y + 60; main_ram_usage.size = 2; main_ram_usage.x = _window->x + 7; main_ram_usage.y = _window->y + 80; psram_usage_label.size = 2; psram_usage_label.text = "PSRAM usage:"; psram_usage_label.x = _window->x + 5; psram_usage_label.y = _window->y + 100; psram_usage.size = 2; psram_usage.x = _window->x + 7; psram_usage.y = _window->y + 120; cpu_usage_label.size = 2; cpu_usage_label.text = "CPU usage:"; cpu_usage_label.x = _window->x + 5; cpu_usage_label.y = _window->y + 140; cpu_usage.size = 2; cpu_usage.x = _window->x + 7; cpu_usage.y = _window->y + 160; _window->window_content_text.push_back(main_ram_usage_label); _window->window_content_text.push_back(main_ram_usage); _window->window_content_text.push_back(cpu_usage_label); _window->window_content_text.push_back(cpu_usage); _window->window_content_text.push_back(psram_usage_label); _window->window_content_text.push_back(psram_usage); ContentButton show_resources; show_resources.action = "show resources"; show_resources.x = _window->x + 7; show_resources.y = _window->y + 40; show_resources.width = 80; show_resources.height = 15; show_resources.pressed = true; ContentButton show_tasks; show_tasks.action = "show tasks"; show_tasks.x = _window->x + show_resources.width + 13; show_tasks.y = _window->y + 40; show_tasks.width = 70; show_tasks.height = 15; show_tasks.pressed = false; _window->content_buttons.push_back(show_resources); _window->content_buttons.push_back(show_tasks); // Variables for metrics size_t total_ram; size_t total_psram; size_t free_ram; size_t free_psram; size_t used_ram; size_t used_psram; float ram_percent = 0.0f; float psram_percentage = 0.0f; float cpu_percent = 0.0f; // For CPU calculation uint32_t idle_count_last = _calibration_idle.idle_count_last; max_idle_iterations = _calibration_idle.max_idle_iterations; Serial.printf("idle_count_last: %i\n", idle_count_last); uint32_t idle_count_current = 0; uint counter = 0; while (_running) { counter++; // RAM Calculation (Internal + PSRAM) size_t internal_total = heap_caps_get_total_size(MALLOC_CAP_INTERNAL); size_t internal_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); size_t psram_total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); size_t psram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); total_ram = internal_total;// + psram_total; total_psram = psram_total; free_ram = internal_free;// + psram_free; free_psram = psram_free; used_ram = total_ram - free_ram; used_psram = total_psram - free_psram; ram_percent = (float)used_ram / (float)total_ram * 100.0f; psram_percentage = (float)used_psram / (float)total_psram * 100.0f; // CPU Usage - measure idle task iterations idle_count_current = xTaskGetIdleRunTimeCounter(); if (idle_count_last > 0 && max_idle_iterations > 0) { uint32_t idle_delta = idle_count_current - idle_count_last; // Calculate idle percentage based on baseline // We're measuring over 1ms, so compare to max_idle_iterations float idle_percent = ((float)idle_delta / (float)max_idle_iterations) * 100.0f; // Cap at 100% if (idle_percent > 100.0f) idle_percent = 100.0f; // CPU usage is inverse of idle cpu_percent = 100.0f - idle_percent; if (cpu_percent < 0) cpu_percent = 0; } else { cpu_percent = 0.0f; } idle_count_last = idle_count_current; _window->window_content_text[1].text = std::to_string(ram_percent) + "%"; _window->window_content_text[3].text = std::to_string((int)cpu_percent) + "%"; _window->window_content_text[5].text = std::to_string((int)psram_percentage) + "%"; vTaskDelay(pdMS_TO_TICKS(1)); if (counter == 1000) { /*Serial.printf("internal_total %i\n", internal_total); Serial.printf("internal_free %i\n", internal_free); Serial.printf("psram_total %i\n", psram_total); Serial.printf("psram_free %i\n", psram_free); Serial.printf("total_ram %i\n", total_ram); Serial.printf("free_ram %i\n", free_ram); Serial.printf("used_ram %i\n", used_ram); Serial.printf("ram_percent %f.2\n", ram_percent); Serial.printf("cpu_percent %f.2\n", cpu_percent); Serial.println("===============");*/ _display_state->update_display.store(true); counter = 0; } } } };