diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index dc9e41d5c6e5c88e11c99fffc2f6aafcdb7ac3d2..f551f676ce8fab64c024edb1f4f3d00ed7fbb36c 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -214,7 +214,7 @@ set(CPPSRC ui/ui_tabview.cpp ui/ui_textentry.cpp ui/ui_transmitter.cpp - apps/ui_about.cpp + apps/ui_about_simple.cpp apps/ui_adsb_rx.cpp apps/ui_adsb_tx.cpp apps/ui_afsk_rx.cpp diff --git a/firmware/application/apps/ui_about_simple.cpp b/firmware/application/apps/ui_about_simple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c6f796ed8539e9ad1d171201499878ade3031c9 --- /dev/null +++ b/firmware/application/apps/ui_about_simple.cpp @@ -0,0 +1,75 @@ +#include "ui_about_simple.hpp" + +namespace ui +{ + AboutView::AboutView(NavigationView &nav) + { + add_children({&console, &button_ok}); + + button_ok.on_select = [&nav](Button &) { + nav.pop(); + }; + + console.writeln("\x1B\x07List of contributors:\x1B\x10"); + console.writeln(""); + } + + void AboutView::update() + { + if (++timer > 200) + { + timer = 0; + + switch (++frame) + { + case 1: + // TODO: Generate this automatically from github + // https://github.com/eried/portapack-mayhem/graphs/contributors?to=2022-01-01&from=2020-04-12&type=c + console.writeln("\x1B\x06Mayhem:\x1B\x10"); + console.writeln("eried,euquiq,gregoryfenton"); + console.writeln("johnelder,jwetzell,nnemanjan00"); + console.writeln("N0vaPixel,klockee,jamesshao8"); + console.writeln(""); + break; + + case 2: + // https://github.com/eried/portapack-mayhem/graphs/contributors?to=2020-04-12&from=2015-07-31&type=c + console.writeln("\x1B\x06Havoc:\x1B\x10"); + console.writeln("furrtek,mrmookie,notpike"); + console.writeln("mjwaxios,ImDroided,Giorgiofox"); + console.writeln("F4GEV,z4ziggy,xmycroftx"); + console.writeln("troussos,silascutler"); + console.writeln("nickbouwhuis,msoose,leres"); + console.writeln("joakar,dhoetger,clem-42"); + console.writeln("brianlechthaler,ZeroChaos-..."); + console.writeln(""); + break; + + case 3: + // https://github.com/eried/portapack-mayhem/graphs/contributors?from=2014-07-05&to=2015-07-31&type=c + console.writeln("\x1B\x06PortaPack:\x1B\x10"); + console.writeln("jboone,argilo"); + console.writeln(""); + break; + + case 4: + // https://github.com/mossmann/hackrf/graphs/contributors + console.writeln("\x1B\x06HackRF:\x1B\x10"); + console.writeln("mossmann,dominicgs,bvernoux"); + console.writeln("bgamari,schneider42,miek"); + console.writeln("willcode,hessu,Sec42"); + console.writeln("yhetti,ckuethe,smunaut"); + console.writeln("wishi,mrbubble62,scateu..."); + console.writeln(""); + frame = 0; // Loop + break; + } + } + } + + void AboutView::focus() + { + button_ok.focus(); + } + +} /* namespace ui */ \ No newline at end of file diff --git a/firmware/application/apps/ui_about_simple.hpp b/firmware/application/apps/ui_about_simple.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a059011907ec2d333436566a68c87764375e2095 --- /dev/null +++ b/firmware/application/apps/ui_about_simple.hpp @@ -0,0 +1,40 @@ +#ifndef __UI_ABOUT_SIMPLE_H__ +#define __UI_ABOUT_SIMPLE_H__ + +#include "ui_widget.hpp" +#include "ui_navigation.hpp" +#include "ui_font_fixed_8x16.hpp" + +#include <cstdint> + +namespace ui +{ + class AboutView : public View + { + public: + AboutView(NavigationView &nav); + void focus() override; + std::string title() const override { return "About"; }; + int32_t timer{180}; + short frame{0}; + + private: + void update(); + + Console console{ + {0, 10, 240, 240}}; + + Button button_ok{ + {240/3, 270, 240/3, 24}, + "OK", + }; + + MessageHandlerRegistration message_handler_update{ + Message::ID::DisplayFrameSync, + [this](const Message *const) { + this->update(); + }}; + }; +} // namespace ui + +#endif /*__UI_ABOUT_SIMPLE_H__*/ diff --git a/firmware/application/ui/ui_btngrid.cpp b/firmware/application/ui/ui_btngrid.cpp index 0c756af4e03660247755dfbbc289b055e053756d..2ad7907eb55524615a912563be7d54c0710546f1 100644 --- a/firmware/application/ui/ui_btngrid.cpp +++ b/firmware/application/ui/ui_btngrid.cpp @@ -95,6 +95,15 @@ void BtnGridView::set_parent_rect(const Rect new_parent_rect) { update_items(); } +void BtnGridView::set_arrow_enabled(bool new_value) { + if(new_value){ + add_child(&arrow_more); + } + else{ + remove_child(&arrow_more); + } +}; + void BtnGridView::on_tick_second() { if (more && blink) arrow_more.set_foreground(Color::white()); diff --git a/firmware/application/ui/ui_btngrid.hpp b/firmware/application/ui/ui_btngrid.hpp index 1ce14ccacf7bacd793c990b64ebf6fa6179c3c5e..5f922f78b11a6aca0ed5da85972bcf9c7d121677 100644 --- a/firmware/application/ui/ui_btngrid.hpp +++ b/firmware/application/ui/ui_btngrid.hpp @@ -62,6 +62,7 @@ public: uint32_t highlighted_index(); void set_parent_rect(const Rect new_parent_rect) override; + void set_arrow_enabled(bool new_value); void on_focus() override; void on_blur() override; bool on_key(const KeyEvent event) override; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index e4ee6490babe8bd438cc10dd0ec8b8fc33844d95..a1ace7bed27a4010a56c1c0d3fcdffce12a429e4 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -30,7 +30,7 @@ #include "bmp_modal_warning.hpp" #include "portapack_persistent_memory.hpp" -#include "ui_about.hpp" +#include "ui_about_simple.hpp" #include "ui_adsb_rx.hpp" #include "ui_adsb_tx.hpp" #include "ui_afsk_rx.hpp" @@ -303,7 +303,36 @@ void SystemStatusView::on_camera() { } void SystemStatusView::on_title() { - nav_.push<AboutView>(); + if(nav_.is_top()) + nav_.push<AboutView>(); + else + nav_.pop(); +} + +/* Information View *****************************************************/ + +InformationView::InformationView( + NavigationView& nav +) : nav_ (nav) +{ + static constexpr Style style_infobar { + .font = font::fixed_8x16, + .background = {33, 33, 33}, + .foreground = Color::white(), + }; + + add_children({ + &backdrop, + &version, + <ime + }); + + version.set_style(&style_infobar); + ltime.set_style(&style_infobar); + ltime.set_seconds_enabled(true); + ltime.set_date_enabled(false); + + set_dirty(); } /* Navigation ************************************************************/ @@ -502,6 +531,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { //{ "About", ui::Color::cyan(), nullptr, [&nav](){ nav.push<AboutView>(); } } }); set_max_rows(2); // allow wider buttons + set_arrow_enabled(false); //set_highlighted(1); // Startup selection } @@ -522,6 +552,7 @@ SystemView::SystemView( set_style(&style_default); constexpr ui::Dim status_view_height = 16; + constexpr ui::Dim info_view_height = 16; add_child(&status_view); status_view.set_parent_rect({ @@ -537,13 +568,29 @@ SystemView::SystemView( { 0, status_view_height }, { parent_rect.width(), static_cast<ui::Dim>(parent_rect.height() - status_view_height) } }); + + add_child(&info_view); + info_view.set_parent_rect({ + {0, 19 * 16}, + { parent_rect.width(), info_view_height } + }); + navigation_view.on_view_changed = [this](const View& new_view) { + + if(!this->navigation_view.is_top()){ + remove_child(&info_view); + } + else{ + add_child(&info_view); + } + this->status_view.set_back_enabled(!this->navigation_view.is_top()); this->status_view.set_title_image_enabled(this->navigation_view.is_top()); - this->status_view.set_dirty(); this->status_view.set_title(new_view.title()); + this->status_view.set_dirty(); + }; - + // portapack::persistent_memory::set_playdead_sequence(0x8D1); @@ -557,6 +604,9 @@ SystemView::SystemView( if (portapack::persistent_memory::config_splash()) navigation_view.push<BMPView>(); + status_view.set_back_enabled(false); + status_view.set_title_image_enabled(true); + status_view.set_dirty(); //else // navigation_view.push<SystemMenuView>(); diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 8754d35d9547ddab86454b4d74114facc3b3877e..02aaf1338b7b7a40bac76f590d222e9e659b5568 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -110,7 +110,7 @@ public: void set_title(const std::string new_value); private: - static constexpr auto default_title = " v1.1.1"; // TODO: Move the version somewhere + static constexpr auto default_title = ""; NavigationView& nav_; @@ -208,6 +208,29 @@ private: }; }; +class InformationView : public View { +public: + InformationView(NavigationView& nav); + +private: + static constexpr auto version_string = "v1.1.1"; + NavigationView& nav_; + + Rectangle backdrop { + { 0, 0 * 16, 240, 16 }, + {33, 33, 33} + }; + + Text version { + {2, 0, 11 * 8, 16}, + version_string + }; + + LiveDateTime ltime { + {174, 0, 8 * 8, 16} + }; +}; + class BMPView : public View { public: BMPView(NavigationView& nav); @@ -262,6 +285,7 @@ public: private: SystemStatusView status_view { navigation_view }; + InformationView info_view { navigation_view }; NavigationView navigation_view { }; Context& context_; }; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index c7427d478a058f0aecc0386dfe0b26e826a07728..ee586f840e0537cefea6dff8cc63e5a982ff86de 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -409,10 +409,26 @@ void Labels::paint(Painter& painter) { void LiveDateTime::on_tick_second() { rtcGetTime(&RTCD1, &datetime); + text = ""; - text = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " " + - to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0'); + if(date_enabled){ + text = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " "; + } + text = text + to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0'); + + if(seconds_enabled){ + text += ":"; + + if(init_delay==0) + text += to_string_dec_uint(datetime.second(), 2, '0'); + else + { + // Placeholder while the seconds are not updated + text += "XX"; + init_delay--; + } + } set_dirty(); } @@ -444,6 +460,14 @@ void LiveDateTime::paint(Painter& painter) { ); } +void LiveDateTime::set_date_enabled(bool new_value){ + this->date_enabled = new_value; +} + +void LiveDateTime::set_seconds_enabled(bool new_value) { + this->seconds_enabled = new_value; +} + /* BigFrequency **********************************************************/ BigFrequency::BigFrequency( diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 61ffeb7258125103085e40dbb03f4cd8e8cb192c..51de42773a9539f299ff32ce9696f1325e7cdde2 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -243,7 +243,10 @@ public: ~LiveDateTime(); void paint(Painter& painter) override; - + + void set_seconds_enabled(bool new_value); + void set_date_enabled(bool new_value); + std::string& string() { return text; } @@ -251,6 +254,10 @@ public: private: void on_tick_second(); + uint16_t init_delay = 4; + bool date_enabled = true; + bool seconds_enabled = false; + rtc::RTC datetime { }; SignalToken signal_token_tick_second { }; std::string text { };