diff --git a/firmware/application/bitmap.hpp b/firmware/application/bitmap.hpp index 2a727780..cb427052 100644 --- a/firmware/application/bitmap.hpp +++ b/firmware/application/bitmap.hpp @@ -27,24 +27,28 @@ namespace ui { -/* -00000000 00000000 00000000 -11110001 11100111 10111110 -10001010 00001000 00001000 -10001010 00001000 00001000 -11110001 11000111 00001000 -10010000 00100000 10001000 -10001000 00100000 10001000 -10001011 11001111 00111110 -00000000 00000000 00000000 -11111100 01111000 01111000 -10000100 01001000 01001000 -10000100 01001000 01001000 -10000100 01001000 01001000 -10000100 01001000 01001000 -10000100 01001000 01001000 -10000111 11001111 11001110 -*/ +static constexpr uint8_t bitmap_more_data[] = { + 0x00, 0x00, + 0xC0, 0x03, + 0xC0, 0x03, + 0xC0, 0x03, + 0xC0, 0x03, + 0xC0, 0x03, + 0xC0, 0x03, + 0xC0, 0x03, + 0xC6, 0x63, + 0xCF, 0xF3, + 0xDE, 0x7B, + 0xFC, 0x3F, + 0xF8, 0x1F, + 0xF0, 0x0F, + 0xE0, 0x07, + 0xC0, 0x03 +}; + +static constexpr Bitmap bitmap_more { + { 16, 16 }, bitmap_more_data +}; static constexpr uint8_t bitmap_rssipwm_data[] = { 0x00, 0x00, 0x00, diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 2e96ac48..7157060e 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -26,31 +26,37 @@ //BUG: No audio in about when shown second time //BUG: Description doesn't show up first time going to system>module info (UI drawn on top) +//TODO: Check AFSK transmit end, skips last bits ? //TODO: Weird LCR AFSK scrambling ? +//TODO: Use msgpack ! //TODO: Frequency manager -//TODO: SD card wiper -//TODO: Draw on touchscreen and transmit as spectrum paint -//TODO: Use progressbars -//TODO: LCR receiver -//TODO: Xylos receiver //TODO: Morse coder -//TODO: Playdead amnesia and login -//TODO: Touch screen calibration -//TODO: Check jammer bandwidths -//TODO: GSM channel detector + +//Multimon-style stuff: //TODO: AFSK receiver +//TODO: Xylos receiver + +//TODO: Check jammer bandwidths +//TODO: Closecall wide range fix +//TODO: SD card wiper +//TODO: Use progressbars +//TODO: GSM channel detector //TODO: SIGFOX RX/TX -//TODO: Show MD5 mismatches for modules not found, etc... -//TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule -//TODO: Check bw setting in LCR TX //TODO: Bodet :) //TODO: Whistler + +//TODO: LCR full message former (see norm) +//TODO: AFSK NRZI, parity and format +//TODO: TX power setting + +//TODO: Playdead amnesia and login //TODO: Setup: Play dead by default ? Enable/disable ? //TODO: Hide statusview when playing dead //TODO: Persistent playdead ! -//TODO: LCR full message former (see norm) -//TODO: AFSK NRZI -//TODO: TX power setting +//TODO: Show MD5 mismatches for modules not found, etc... +//TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule + +//TODO: Draw on touchscreen and transmit as spectrum paint //TODO: Two players tic-tac-toe #include "ch.h" diff --git a/firmware/application/ui_menu.cpp b/firmware/application/ui_menu.cpp index 30ec2c26..9a102497 100644 --- a/firmware/application/ui_menu.cpp +++ b/firmware/application/ui_menu.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -20,10 +21,11 @@ */ #include "ui_menu.hpp" +#include "time.hpp" namespace ui { -/* MenuViewItem **********************************************************/ +/* MenuItemView **********************************************************/ void MenuItemView::select() { if( item.on_select ) { @@ -72,27 +74,67 @@ void MenuItemView::paint(Painter& painter) { /* MenuView **************************************************************/ +MenuView::MenuView() { + set_focusable(true); + + add_child(&arrow_more); + signal_token_tick_second = time::signal_tick_second += [this]() { + this->on_tick_second(); + }; + + arrow_more.set_parent_rect( { 216, 320 - 16 - 24, 16, 16 } ); + arrow_more.set_focusable(false); +} + MenuView::~MenuView() { /* TODO: Double-check this */ - for(auto child : children_) { + for (auto child : children_) { delete child; } } +void MenuView::on_tick_second() { + if (more_ && blink_) + arrow_more.set_foreground(Color::white()); + else + arrow_more.set_foreground(Color::black()); + + blink_ = !blink_; + + arrow_more.set_dirty(); +} + void MenuView::add_item(const MenuItem item) { add_child(new MenuItemView { item }); } void MenuView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); + update_items(); +} +void MenuView::update_items() { constexpr size_t item_height = 24; size_t i = 0; - for(auto child : children_) { - child->set_parent_rect({ - { 0, static_cast(i * item_height) }, - { size().w, item_height } - }); + Coord y_pos; + + if (MENU_MAX + offset_ < (children_.size() - 1)) + more_ = true; + else + more_ = false; + + for (auto child : children_) { + if (i) { // Skip arrow widget + y_pos = (i - 1 - offset_) * item_height; + child->set_parent_rect({ + { 0, y_pos }, + { size().w, item_height } + }); + if ((y_pos < 0) || (y_pos >= (320 - 16 - 24 - 16))) + child->hidden(true); + else + child->hidden(false); + } i++; } } @@ -101,7 +143,7 @@ MenuItemView* MenuView::item_view(size_t index) const { /* TODO: Terrible cast! Take it as a sign I must be doing something * shamefully wrong here, right? */ - return static_cast(children_[index]); + return static_cast(children_[index + 1]); // Skip arrow widget } size_t MenuView::highlighted() const { @@ -109,9 +151,19 @@ size_t MenuView::highlighted() const { } bool MenuView::set_highlighted(const size_t new_value) { - if( new_value >= children_.size() ) { + if( new_value >= (children_.size() - 1) ) { // Skip arrow widget return false; } + + if ((new_value - offset_ + 1) >= MENU_MAX) { + // Shift MenuView up + offset_ = new_value - MENU_MAX + 1; + update_items(); + } else if (new_value < offset_) { + // Shift MenuView down + offset_ = new_value; + update_items(); + } item_view(highlighted())->unhighlight(); highlighted_ = new_value; diff --git a/firmware/application/ui_menu.hpp b/firmware/application/ui_menu.hpp index 9740bc1f..7e426486 100644 --- a/firmware/application/ui_menu.hpp +++ b/firmware/application/ui_menu.hpp @@ -25,11 +25,15 @@ #include "ui.hpp" #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "bitmap.hpp" +#include "signal.hpp" #include #include #include +#define MENU_MAX 11 + namespace ui { struct MenuItem { @@ -64,23 +68,20 @@ class MenuView : public View { public: std::function on_left; - MenuView() { - set_focusable(true); - } - + MenuView(); ~MenuView(); void add_item(const MenuItem item); template void add_items(const std::array& items) { - for(const auto& item : items) { + for (const auto& item : items) { add_item(item); } } void set_parent_rect(const Rect new_parent_rect) override; - + MenuItemView* item_view(size_t index) const; size_t highlighted() const; @@ -93,7 +94,22 @@ public: //bool on_touch(const TouchEvent event) override; private: + void update_items(); + void on_tick_second(); + + SignalToken signal_token_tick_second; + + Image arrow_more { + { 216, 320 - 16 - 24, 16, 16 }, + &bitmap_more, + Color::white(), + Color::black() + }; + + bool blink_ = false; + bool more_ = false; size_t highlighted_ { 0 }; + size_t offset_ { 0 }; }; } /* namespace ui */ diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 30e45aaf..c53d5043 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -33,7 +34,6 @@ #include "ui_setup.hpp" #include "ui_debug.hpp" -#include "ui_handwrite.hpp" // DEBUG #include "ui_soundboard.hpp" // DEBUG #include "ui_closecall.hpp" // DEBUG #include "ui_freqman.hpp" // DEBUG @@ -238,36 +238,35 @@ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { /* SystemMenuView ********************************************************/ SystemMenuView::SystemMenuView(NavigationView& nav) { - add_items<11>({ { - { "Play dead", ui::Color::red(), [&nav](){ nav.push(false); } }, + add_items<14>({ { + { "Play dead", ui::Color::red(), [&nav](){ nav.push(false); } }, { "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, - { "Capture RX", ui::Color::orange(), [&nav](){ nav.push(); } }, + { "Capture RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, { "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, - //{ "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ nav.push(); } }, + { "Numbers station TX", ui::Color::purple(), [&nav](){ nav.push(); } }, //nav.push(); + { "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ nav.push(); } }, //{ "Soundboard TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, SoundBoard); } }, //{ "Audio TX", ui::Color::yellow(), [&nav](){ nav.push(md5_baseband_tx, AudioTX); } }, //{ "Frequency manager", ui::Color::white(), [&nav](){ nav.push(); } }, //{ "EPAR TX", ui::Color::green(), [&nav](){ nav.push(md5_baseband_tx, EPAR); } }, { "Xylos TX", ui::Color::green(), [&nav](){ nav.push(); } }, - { "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push(); } }, - { "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(); } }, - //{ "Capture", ui::Color::white(), [&nav](){ nav.push(); } }, + { "TEDI/LCR TX", ui::Color::yellow(), [&nav](){ nav.push(); } }, + { "OOK encoder TX", ui::Color::orange(), [&nav](){ nav.push(); } }, + { "RDS TX", ui::Color::red(), [&nav](){ nav.push(); } }, //{ "Analyze", ui::Color::white(), [&nav](){ nav.push(); } }, - { "Setup", ui::Color::white(), [&nav](){ nav.push(); } }, - { "Debug", ui::Color::white(), [&nav](){ nav.push(); } }, - { "HackRF", ui::Color::white(), [&nav](){ nav.push(); } }, - { "About", ui::Color::white(), [&nav](){ nav.push(); } } + { "Setup", ui::Color::white(), [&nav](){ nav.push(); } }, + { "Debug", ui::Color::white(), [&nav](){ nav.push(); } }, + { "HackRF", ui::Color::white(), [&nav](){ nav.push(); } }, + { "About", ui::Color::white(), [&nav](){ nav.push(); } } } }); //{ "Nordic/BTLE RX", ui::Color::cyan(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, //{ "Jammer", ui::Color::white(), [&nav](){ nav.push(md5_baseband, new JammerView(nav)); } }, //{ "Audio file TX", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, - //{ "Encoder TX", ui::Color::green(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, //{ "Whistle", ui::Color::purple(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband, new WhistleView { nav, transmitter_model }}); } }, //{ "SIGFOX RX", ui::Color::orange(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband, new SIGFRXView { nav, receiver_model }}); } }, //{ "Xylos RX", ui::Color::green(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband_tx, new XylosRXView { nav, receiver_model }}); } }, //{ "AFSK RX", ui::Color::cyan(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband, new AFSKRXView { nav, receiver_model }}); } }, - //{ "Numbers station", ui::Color::purple(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband_tx, new NumbersStationView { nav, transmitter_model }}); } }, } diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 152517da..11aba67d 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ