diff --git a/Desktop_Test/Desktop_Test.ino b/Desktop_Test/Desktop_Test.ino index ed2c5f2..01658af 100644 --- a/Desktop_Test/Desktop_Test.ino +++ b/Desktop_Test/Desktop_Test.ino @@ -26,6 +26,22 @@ void setup() { Serial.begin(115200); Serial.println("Initializing..."); + CALIBRATION_IDLE _calibration_idle; + + // Calibration phase, measure idle baseline over 3 seconds + Serial.println("Calibrating CPU baseline... please wait 3 seconds"); + uint32_t calibration_start = xTaskGetIdleRunTimeCounter(); + vTaskDelay(pdMS_TO_TICKS(3000)); + uint32_t calibration_end = xTaskGetIdleRunTimeCounter(); + + // Calculate average idle iterations per millisecond during calibration + _calibration_idle.max_idle_iterations = (calibration_end - calibration_start) / 3000; + + Serial.print("Baseline calibrated. Max idle iterations per ms: "); + Serial.println(_calibration_idle.max_idle_iterations); + + _calibration_idle.idle_count_last = xTaskGetIdleRunTimeCounter(); + // Create shared state _display_state = new DISPLAY_STATE(); _display_state->update_display.store(false); @@ -43,7 +59,7 @@ void setup() { EventManager::getInstance().init(); // Initialize system manager with shell and tft references - sm->init(_display_state, _shell, th); + sm->init(_display_state, _shell, th, _calibration_idle); // Initialize components (they subscribe to events) im->init(_display_state, th); diff --git a/Desktop_Test/GLOBALS.h b/Desktop_Test/GLOBALS.h index 223eb49..8a78712 100644 --- a/Desktop_Test/GLOBALS.h +++ b/Desktop_Test/GLOBALS.h @@ -39,4 +39,9 @@ struct APPLICATION_EVENT { struct DISPLAY_STATE { std::atomic update_display; +}; + +struct CALIBRATION_IDLE { + uint32_t max_idle_iterations = 0; + uint32_t idle_count_last = 0; }; \ No newline at end of file diff --git a/Desktop_Test/example_programs.h b/Desktop_Test/example_programs.h index 35cae38..bc844d4 100644 --- a/Desktop_Test/example_programs.h +++ b/Desktop_Test/example_programs.h @@ -49,13 +49,10 @@ class TextEditorProgram : public Program { public: void run() override { Serial.println("Text editor started!"); - + // You have full access to the window and can draw to it while (_running) { - // Handle text editing logic here - // Draw to the window content area using _tft - - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(1)); } } }; @@ -68,7 +65,7 @@ public: while (_running) { // Calculator logic here - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(1)); } } }; @@ -81,67 +78,70 @@ public: while (_running) { // Game logic and rendering - vTaskDelay(pdMS_TO_TICKS(50)); // 20 FPS + vTaskDelay(pdMS_TO_TICKS(1)); // 20 FPS } } }; // Example Program 5: Settings class SettingsProgram : public Program { +private: + uint32_t max_idle_iterations; + public: void run() override { - Serial.println("Settings started!"); + _window->x += 150; + _window->width -= 50; + //_window->sprite.setPsram(true); + //_window->sprite.createSprite(10, 10); + //_window->sprite.setColorDepth(16); + Serial.println("Settings started!"); WindowContentText ram_usage; WindowContentText ram_usage_label; WindowContentText cpu_usage; WindowContentText cpu_usage_label; - ram_usage_label.size = 2; ram_usage_label.text = "RAM usage"; ram_usage_label.x = _window->x + 10; ram_usage_label.y = _window->y + 50; - ram_usage.size = 2; ram_usage.x = _window->x + 10; ram_usage.y = _window->y + 70; - cpu_usage_label.size = 2; cpu_usage_label.text = "CPU usage:"; cpu_usage_label.x = _window->x + 10; cpu_usage_label.y = _window->y + 90; - cpu_usage.size = 2; cpu_usage.x = _window->x + 10; cpu_usage.y = _window->y + 110; - _window->window_content_text.push_back(ram_usage_label); _window->window_content_text.push_back(ram_usage); _window->window_content_text.push_back(cpu_usage_label); _window->window_content_text.push_back(cpu_usage); - + // Variables for metrics size_t total_ram; size_t free_ram; size_t used_ram; float ram_percent; - float cpu_percent; + float cpu_percent = 0.0f; // For CPU calculation - uint32_t idle_count_last = 0; + 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; free_ram = internal_free + psram_free; used_ram = total_ram - free_ram; @@ -150,26 +150,40 @@ public: // CPU Usage - measure idle task iterations idle_count_current = xTaskGetIdleRunTimeCounter(); - if (idle_count_last > 0) { + if (idle_count_last > 0 && max_idle_iterations > 0) { uint32_t idle_delta = idle_count_current - idle_count_last; - // The more idle iterations, the less CPU is used - // Scale based on your measurement interval (100ms) - // Tune the divisor based on your specific system - cpu_percent = 100.0f - (idle_delta / 10000.0f); + + // 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; - if (cpu_percent > 100) cpu_percent = 100; } else { cpu_percent = 0.0f; } idle_count_last = idle_count_current; - - _window->window_content_text[1].text = std::to_string(used_ram); - _window->window_content_text[3].text = std::to_string(cpu_percent); - - vTaskDelay(pdMS_TO_TICKS(5)); - + + _window->window_content_text[1].text = std::to_string(ram_percent); + _window->window_content_text[3].text = std::to_string((int)cpu_percent) + "%"; + + 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; } diff --git a/Desktop_Test/program.cpp b/Desktop_Test/program.cpp index 7587741..f969f7a 100644 --- a/Desktop_Test/program.cpp +++ b/Desktop_Test/program.cpp @@ -12,7 +12,7 @@ Program::~Program() { close(); } -void Program::init(int id, std::string name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state) { +void Program::init(int id, std::string name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state, CALIBRATION_IDLE calibration_idle) { _id = id; _name = name; _window = window; @@ -20,6 +20,7 @@ void Program::init(int id, std::string name, Window* window, Shell* shell, TFT_H _tft = tft; _display_state = display_state; _running = true; + _calibration_idle = calibration_idle; // Create the task xTaskCreatePinnedToCore(task_wrapper, _name.c_str(), 4096, this, 1, &_task_handle, 0); diff --git a/Desktop_Test/program.h b/Desktop_Test/program.h index 360060c..ab7d81d 100644 --- a/Desktop_Test/program.h +++ b/Desktop_Test/program.h @@ -4,6 +4,7 @@ #include "GLOBALS.h" #include #include +#include // Forward declarations class Shell; @@ -66,6 +67,7 @@ struct Window { std::string title; std::vector window_decorations; std::vector window_content_text; + LGFX_Sprite sprite; }; // Base Program class - all programs inherit from this @@ -79,6 +81,7 @@ protected: int _id; std::string _name; bool _running; + CALIBRATION_IDLE _calibration_idle; static void task_wrapper(void* pvParameters); @@ -87,7 +90,7 @@ public: virtual ~Program(); // Initialize the program with its window and shell reference - void init(int id, std::string name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state); + void init(int id, std::string name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state, CALIBRATION_IDLE calibration_idle); // Override this in your specific programs virtual void run() = 0; diff --git a/Desktop_Test/shell.cpp b/Desktop_Test/shell.cpp index cd367bf..ffac721 100644 --- a/Desktop_Test/shell.cpp +++ b/Desktop_Test/shell.cpp @@ -256,8 +256,6 @@ void Shell::draw_task_bar(int color) { // Button tft->draw_box(6, 298, 50, 18, color); - Serial.println(task_bar_items.size()); - for (TaskBarItem item : task_bar_items) { if (item.focused) { tft->draw_box(item.place_x - 2, item.place_y - 2, item.width + 3, item.height + 3, COL_BLACK); @@ -373,6 +371,7 @@ int Shell::handle_desktop_click(CLICK_EVENT event) { win->minimized = false; win->title = item.name; win->window_content_text = {}; + win->sprite = LGFX_Sprite(&tft->tft); // Spawn program using the program_class bool result = _system_manager->spawn_program(win, item.program_class); diff --git a/Desktop_Test/system_manager.cpp b/Desktop_Test/system_manager.cpp index 95c754e..478c51b 100644 --- a/Desktop_Test/system_manager.cpp +++ b/Desktop_Test/system_manager.cpp @@ -4,10 +4,11 @@ #include "example_programs.h" #include -void SystemManager::init(DISPLAY_STATE* display_state, Shell* shell, TFT_Handler* tft) { +void SystemManager::init(DISPLAY_STATE* display_state, Shell* shell, TFT_Handler* tft, CALIBRATION_IDLE calibration_idle) { _display_state = display_state; _shell = shell; _tft = tft; + _calibration_idle = calibration_idle; // Register all available programs register_program("CounterProgram"); @@ -37,7 +38,7 @@ bool SystemManager::spawn_program(Window* window, const std::string& program_cla // Assign ID and initialize window->id = _next_program_id; - program->init(_next_program_id, window->title, window, _shell, _tft, _display_state); + program->init(_next_program_id, window->title, window, _shell, _tft, _display_state, _calibration_idle); _next_program_id++; _programs.push_back(program); diff --git a/Desktop_Test/system_manager.h b/Desktop_Test/system_manager.h index 469a012..0714902 100644 --- a/Desktop_Test/system_manager.h +++ b/Desktop_Test/system_manager.h @@ -4,6 +4,7 @@ #include #include #include +#include "GLOBALS.h" // Forward declarations class Shell; @@ -15,6 +16,7 @@ private: Shell* _shell; TFT_Handler* _tft; int _next_program_id = 1; + CALIBRATION_IDLE _calibration_idle; // Factory function type: creates a new instance of a Program using ProgramFactory = std::function; @@ -25,7 +27,7 @@ private: public: std::vector _programs; - void init(DISPLAY_STATE* display_state, Shell* shell, TFT_Handler* tft); + void init(DISPLAY_STATE* display_state, Shell* shell, TFT_Handler* tft, CALIBRATION_IDLE calibration_idle); // Register a program type with a factory function template