diff --git a/firmware/application/apps/ui_debug.cpp b/firmware/application/apps/ui_debug.cpp index e3a7f48e..daa986f4 100644 --- a/firmware/application/apps/ui_debug.cpp +++ b/firmware/application/apps/ui_debug.cpp @@ -74,91 +74,6 @@ void DebugMemoryView::focus() { button_done.focus(); } -/* TemperatureWidget *****************************************************/ - -void TemperatureWidget::paint(Painter& painter) { - const auto logger = portapack::temperature_logger; - - const auto rect = screen_rect(); - const Color color_background{0, 0, 64}; - const Color color_foreground = Theme::getInstance()->fg_green->foreground; - const Color color_reticle{128, 128, 128}; - - const auto graph_width = static_cast(logger.capacity()) * bar_width; - const Rect graph_rect{ - rect.left() + (rect.width() - graph_width) / 2, rect.top() + 8, - graph_width, rect.height()}; - const Rect frame_rect{ - graph_rect.left() - 1, graph_rect.top() - 1, - graph_rect.width() + 2, graph_rect.height() + 2}; - painter.draw_rectangle(frame_rect, color_reticle); - painter.fill_rectangle(graph_rect, color_background); - - const auto history = logger.history(); - for (size_t i = 0; i < history.size(); i++) { - const Coord x = graph_rect.right() - (history.size() - i) * bar_width; - const auto sample = history[i]; - const auto temp = temperature(sample); - const auto y = screen_y(temp, graph_rect); - const Dim bar_height = graph_rect.bottom() - y; - painter.fill_rectangle({x, y, bar_width, bar_height}, color_foreground); - } - - if (!history.empty()) { - const auto sample = history.back(); - const auto temp = temperature(sample); - const auto last_y = screen_y(temp, graph_rect); - const Coord x = graph_rect.right() + 8; - const Coord y = last_y - 8; - - painter.draw_string({x, y}, style(), temperature_str(temp)); - } - - const auto display_temp_max = display_temp_min + (graph_rect.height() / display_temp_scale); - for (auto temp = display_temp_min; temp <= display_temp_max; temp += 10) { - const int32_t tick_length = 6; - const auto tick_x = graph_rect.left() - tick_length; - const auto tick_y = screen_y(temp, graph_rect); - painter.fill_rectangle({tick_x, tick_y, tick_length, 1}, color_reticle); - const auto text_x = graph_rect.left() - temp_len * 8 - 8; - const auto text_y = tick_y - 8; - painter.draw_string({text_x, text_y}, style(), temperature_str(temp)); - } -} - -TemperatureWidget::temperature_t TemperatureWidget::temperature(const sample_t sensor_value) const { - // Scaling is different for MAX2837 vs MAX2839 so it's now done in the respective chip-specific module - return sensor_value; -} - -std::string TemperatureWidget::temperature_str(const temperature_t temperature) const { - return to_string_dec_int(temperature, temp_len - 2) + STR_DEGREES_C; -} - -Coord TemperatureWidget::screen_y( - const temperature_t temperature, - const Rect& rect) const { - int y_raw = rect.bottom() - ((temperature - display_temp_min) * display_temp_scale); - const auto y_limit = std::min(rect.bottom(), std::max(rect.top(), y_raw)); - return y_limit; -} - -/* TemperatureView *******************************************************/ - -TemperatureView::TemperatureView(NavigationView& nav) { - add_children({ - &text_title, - &temperature_widget, - &button_done, - }); - - button_done.on_select = [&nav](Button&) { nav.pop(); }; -} - -void TemperatureView::focus() { - button_done.focus(); -} - /* RegistersWidget *******************************************************/ RegistersWidget::RegistersWidget( @@ -507,12 +422,9 @@ void DebugMenuView::on_populate() { {"Debug Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { portapack::persistent_memory::debug_dump(); }}, {"M0 Stack Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { stack_dump(); }}, {"Memory Dump", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push(); }}, - //{"Memory Usage", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push(); }}, {"Peripherals", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, {"Pers. Memory", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_memory, [this]() { nav_.push(); }}, - //{ "Radio State", ui::Theme::getInstance()->bg_darkest->foreground, nullptr, [this](){ nav_.push(); } }, {"SD Card", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_sdcard, [this]() { nav_.push(); }}, - {"Temperature", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_temperature, [this]() { nav_.push(); }}, {"Touch Test", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_notepad, [this]() { nav_.push(); }}, {"Reboot", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_setup, [this]() { nav_.push(); }}, {"Ext Module", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push(); }}, diff --git a/firmware/application/apps/ui_debug.hpp b/firmware/application/apps/ui_debug.hpp index 3247f5d8..6c7b0c43 100644 --- a/firmware/application/apps/ui_debug.hpp +++ b/firmware/application/apps/ui_debug.hpp @@ -86,53 +86,6 @@ class DebugMemoryView : public View { "Done"}; }; -class TemperatureWidget : public Widget { - public: - explicit TemperatureWidget( - Rect parent_rect) - : Widget{parent_rect} { - } - - void paint(Painter& painter) override; - - private: - using sample_t = uint32_t; - using temperature_t = int32_t; - - temperature_t temperature(const sample_t sensor_value) const; - Coord screen_y(const temperature_t temperature, const Rect& screen_rect) const; - - std::string temperature_str(const temperature_t temperature) const; - - static constexpr temperature_t display_temp_min = -10; // Accomodate negative values, present in cold startup cases - static constexpr temperature_t display_temp_scale = 3; - static constexpr int bar_width = 1; - static constexpr int temp_len = 5; // Now scale shows up to 5 chars ("-10ºC") -}; - -class TemperatureView : public View { - public: - explicit TemperatureView(NavigationView& nav); - - void focus() override; - - std::string title() const override { return "Temperature"; }; - - private: - Text text_title{ - {76, 16, 240, 16}, - "Temperature", - }; - - TemperatureWidget temperature_widget{ - {0, 40, 240, 180}, - }; - - Button button_done{ - {72, 264, 96, 24}, - "Done"}; -}; - typedef enum { CT_PMEM, CT_RFFC5072, diff --git a/firmware/application/apps/ui_flash_utility.cpp b/firmware/application/apps/ui_flash_utility.cpp index 2eb935f9..55d5a23b 100644 --- a/firmware/application/apps/ui_flash_utility.cpp +++ b/firmware/application/apps/ui_flash_utility.cpp @@ -95,7 +95,7 @@ FlashUtilityView::FlashUtilityView(NavigationView& nav) menu_view.add_item({filename.string().substr(0, max_filename_length), color, - &bitmap_icon_temperature, + &bitmap_icon_peripherals_details, [this, path](KeyEvent) { this->firmware_selected(path); }}); diff --git a/firmware/application/bitmap.hpp b/firmware/application/bitmap.hpp index f8105b58..704d727c 100644 --- a/firmware/application/bitmap.hpp +++ b/firmware/application/bitmap.hpp @@ -2531,44 +2531,6 @@ static constexpr Bitmap bitmap_icon_batt_icon{ {16, 16}, bitmap_icon_batt_icon_data}; -static constexpr uint8_t bitmap_icon_temperature_data[] = { - 0x00, - 0x01, - 0x80, - 0x01, - 0x80, - 0x05, - 0xC0, - 0x0D, - 0x40, - 0x0D, - 0xD0, - 0x1F, - 0x70, - 0x15, - 0xB0, - 0x1A, - 0x58, - 0x35, - 0xB8, - 0x3A, - 0x58, - 0x34, - 0x28, - 0x28, - 0x18, - 0x30, - 0x30, - 0x18, - 0x60, - 0x0C, - 0xC0, - 0x07, -}; -static constexpr Bitmap bitmap_icon_temperature{ - {16, 16}, - bitmap_icon_temperature_data}; - static constexpr uint8_t bitmap_tab_edge_data[] = { 0x00, 0x01, diff --git a/firmware/application/external/external.cmake b/firmware/application/external/external.cmake index b3fbb4f3..a00626b2 100644 --- a/firmware/application/external/external.cmake +++ b/firmware/application/external/external.cmake @@ -130,6 +130,10 @@ set(EXTCPPSRC #remote external/remote/main.cpp external/remote/ui_remote.cpp + + #mcu_temperature + external/mcu_temperature/main.cpp + external/mcu_temperature/mcu_temperature.cpp ) set(EXTAPPLIST @@ -164,4 +168,5 @@ set(EXTAPPLIST shoppingcart_lock flippertx remote + mcu_temperature ) diff --git a/firmware/application/external/external.ld b/firmware/application/external/external.ld index 0e054cf5..560dfb40 100644 --- a/firmware/application/external/external.ld +++ b/firmware/application/external/external.ld @@ -54,6 +54,7 @@ MEMORY ram_external_app_flippertx(rwx) : org = 0xADCD0000, len = 32k ram_external_app_ook_editor(rwx) : org = 0xADCE0000, len = 32k ram_external_app_remote(rwx) : org = 0xADCF0000, len = 32k + ram_external_app_mcu_temperature(rwx) : org = 0xADD00000, len = 32k } SECTIONS @@ -244,4 +245,10 @@ SECTIONS KEEP(*(.external_app.app_remote.application_information)); *(*ui*external_app*remote*); } > ram_external_app_remote + + .external_app_mcu_temperature : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.external_app.app_mcu_temperature.application_information)); + *(*ui*external_app*mcu_temperature*); + } > ram_external_app_mcu_temperature } diff --git a/firmware/application/external/mcu_temperature/main.cpp b/firmware/application/external/mcu_temperature/main.cpp new file mode 100644 index 00000000..64b1ba13 --- /dev/null +++ b/firmware/application/external/mcu_temperature/main.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ui.hpp" +#include "mcu_temperature.hpp" +#include "ui_navigation.hpp" +#include "external_app.hpp" + +namespace ui::external_app::mcu_temperature { +void initialize_app(ui::NavigationView& nav) { + nav.push(); +} +} // namespace ui::external_app::mcu_temperature + +extern "C" { + +__attribute__((section(".external_app.app_mcu_temperature.application_information"), used)) application_information_t _application_information_mcu_temperature = { + /*.memory_location = */ (uint8_t*)0x00000000, + /*.externalAppEntry = */ ui::external_app::mcu_temperature::initialize_app, + /*.header_version = */ CURRENT_HEADER_VERSION, + /*.app_version = */ VERSION_MD5, + + /*.app_name = */ "Temperature", + /*.bitmap_data = */ { + 0x00, + 0x00, + 0x20, + 0x00, + 0x70, + 0x3E, + 0x88, + 0x00, + 0x88, + 0x00, + 0x88, + 0x3E, + 0x88, + 0x00, + 0x88, + 0x00, + 0x88, + 0x3E, + 0x88, + 0x00, + 0x04, + 0x01, + 0x74, + 0x01, + 0x04, + 0x01, + 0x88, + 0x00, + 0x70, + 0x00, + 0x00, + 0x00, + }, + /*.icon_color = */ ui::Color::cyan().v, + /*.menu_location = */ app_location_t::DEBUG, + /*.desired_menu_position = */ -1, + + /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time +}; +} \ No newline at end of file diff --git a/firmware/application/external/mcu_temperature/mcu_temperature.cpp b/firmware/application/external/mcu_temperature/mcu_temperature.cpp new file mode 100644 index 00000000..aee90308 --- /dev/null +++ b/firmware/application/external/mcu_temperature/mcu_temperature.cpp @@ -0,0 +1,91 @@ +#include "mcu_temperature.hpp" + +#include "ui_painter.hpp" + +#include "portapack.hpp" + +using namespace portapack; +namespace ui::external_app::mcu_temperature { + +void McuTemperatureWidget::paint(Painter& painter) { + const auto logger = portapack::temperature_logger; + + const auto rect = screen_rect(); + const Color color_background{0, 0, 64}; + const Color color_foreground = Theme::getInstance()->fg_green->foreground; + const Color color_reticle{128, 128, 128}; + + const auto graph_width = static_cast(logger.capacity()) * bar_width; + const Rect graph_rect{ + rect.left() + (rect.width() - graph_width) / 2, rect.top() + 8, + graph_width, rect.height()}; + const Rect frame_rect{ + graph_rect.left() - 1, graph_rect.top() - 1, + graph_rect.width() + 2, graph_rect.height() + 2}; + painter.draw_rectangle(frame_rect, color_reticle); + painter.fill_rectangle(graph_rect, color_background); + + const auto history = logger.history(); + for (size_t i = 0; i < history.size(); i++) { + const Coord x = graph_rect.right() - (history.size() - i) * bar_width; + const auto sample = history[i]; + const auto temp = temperature(sample); + const auto y = screen_y(temp, graph_rect); + const Dim bar_height = graph_rect.bottom() - y; + painter.fill_rectangle({x, y, bar_width, bar_height}, color_foreground); + } + + if (!history.empty()) { + const auto sample = history.back(); + const auto temp = temperature(sample); + const auto last_y = screen_y(temp, graph_rect); + const Coord x = graph_rect.right() + 8; + const Coord y = last_y - 8; + + painter.draw_string({x, y}, style(), temperature_str(temp)); + } + + const auto display_temp_max = display_temp_min + (graph_rect.height() / display_temp_scale); + for (auto temp = display_temp_min; temp <= display_temp_max; temp += 10) { + const int32_t tick_length = 6; + const auto tick_x = graph_rect.left() - tick_length; + const auto tick_y = screen_y(temp, graph_rect); + painter.fill_rectangle({tick_x, tick_y, tick_length, 1}, color_reticle); + const auto text_x = graph_rect.left() - temp_len * 8 - 8; + const auto text_y = tick_y - 8; + painter.draw_string({text_x, text_y}, style(), temperature_str(temp)); + } +} + +McuTemperatureWidget::temperature_t McuTemperatureWidget::temperature(const sample_t sensor_value) const { + // Scaling is different for MAX2837 vs MAX2839 so it's now done in the respective chip-specific module + return sensor_value; +} + +std::string McuTemperatureWidget::temperature_str(const temperature_t temperature) const { + return to_string_dec_int(temperature, temp_len - 2) + STR_DEGREES_C; +} + +Coord McuTemperatureWidget::screen_y( + const temperature_t temperature, + const Rect& rect) const { + int y_raw = rect.bottom() - ((temperature - display_temp_min) * display_temp_scale); + const auto y_limit = std::min(rect.bottom(), std::max(rect.top(), y_raw)); + return y_limit; +} + +McuTemperatureView::McuTemperatureView(NavigationView& nav) { + add_children({ + &text_title, + &temperature_widget, + &button_done, + }); + + button_done.on_select = [&nav](Button&) { nav.pop(); }; +} + +void McuTemperatureView::focus() { + button_done.focus(); +} + +} // namespace ui::external_app::mcu_temperature \ No newline at end of file diff --git a/firmware/application/external/mcu_temperature/mcu_temperature.hpp b/firmware/application/external/mcu_temperature/mcu_temperature.hpp new file mode 100644 index 00000000..a8cbb617 --- /dev/null +++ b/firmware/application/external/mcu_temperature/mcu_temperature.hpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __MCU_TEMPERATURE_H__ +#define __MCU_TEMPERATURE_H__ + +#include "ui.hpp" +#include "ui_widget.hpp" +#include "ui_painter.hpp" +#include "ui_menu.hpp" +#include "ui_navigation.hpp" + +#include "rffc507x.hpp" +#include "portapack.hpp" +#include "memory_map.hpp" +#include "irq_controls.hpp" + +#include +#include + +namespace ui::external_app::mcu_temperature { + +class McuTemperatureWidget : public Widget { + public: + explicit McuTemperatureWidget( + Rect parent_rect) + : Widget{parent_rect} { + } + + void paint(Painter& painter) override; + + private: + using sample_t = uint32_t; + using temperature_t = int32_t; + + temperature_t temperature(const sample_t sensor_value) const; + Coord screen_y(const temperature_t temperature, const Rect& screen_rect) const; + + std::string temperature_str(const temperature_t temperature) const; + + static constexpr temperature_t display_temp_min = -10; // Accomodate negative values, present in cold startup cases + static constexpr temperature_t display_temp_scale = 3; + static constexpr int bar_width = 1; + static constexpr int temp_len = 5; // Now scale shows up to 5 chars ("-10ºC") +}; + +class McuTemperatureView : public View { + public: + explicit McuTemperatureView(NavigationView& nav); + + void focus() override; + + std::string title() const override { return "Temperature"; }; + + private: + Text text_title{ + {76, 16, 240, 16}, + "Temperature", + }; + + McuTemperatureWidget temperature_widget{ + {0, 40, 240, 180}, + }; + + Button button_done{ + {72, 264, 96, 24}, + "Done"}; +}; + +} // namespace ui::external_app::mcu_temperature + +#endif /*__MCU_TEMPERATURE_H__*/ diff --git a/firmware/application/external/remote/ui_remote.hpp b/firmware/application/external/remote/ui_remote.hpp index fa35102f..e61834f4 100644 --- a/firmware/application/external/remote/ui_remote.hpp +++ b/firmware/application/external/remote/ui_remote.hpp @@ -84,7 +84,7 @@ class RemoteIcons { &bitmap_icon_sonde, &bitmap_icon_stealth, &bitmap_icon_tetra, - &bitmap_icon_temperature}; + &bitmap_icon_peripherals_details}; }; // TODO: Use RGB colors instead? diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index bfe1913c..ddf36d1b 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -174,7 +174,7 @@ const NavigationView::AppList NavigationView::appList = { {"wavview", "Wav View", UTILITIES, Color::yellow(), &bitmap_icon_soundboard, new ViewFactory()}, // Dangerous apps. - {nullptr, "Flash Utility", UTILITIES, Color::red(), &bitmap_icon_temperature, new ViewFactory()}, + {nullptr, "Flash Utility", UTILITIES, Color::red(), &bitmap_icon_peripherals_details, new ViewFactory()}, {nullptr, "Wipe SD card", UTILITIES, Color::red(), &bitmap_icon_tools_wipesd, new ViewFactory()}, }; diff --git a/firmware/graphics/temperature.png b/firmware/graphics/temperature.png new file mode 100644 index 00000000..e77b6704 Binary files /dev/null and b/firmware/graphics/temperature.png differ