diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 2cc9f6cb6..d9293eee8 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -153,7 +153,6 @@ set(CPPSRC ui_baseband_stats_view.cpp ui_sd_card_status_view.cpp ui_sd_card_debug.cpp - ui_console.cpp ui_receiver.cpp ui_record_view.cpp ui_textentry.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 99d16502b..b4a168bad 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -3654,30 +3654,6 @@ ui_closecall.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_closecall.cpp.s .PHONY : ui_closecall.cpp.s -ui_console.obj: ui_console.cpp.obj -.PHONY : ui_console.obj - -# target to build an object file -ui_console.cpp.obj: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_console.cpp.obj -.PHONY : ui_console.cpp.obj - -ui_console.i: ui_console.cpp.i -.PHONY : ui_console.i - -# target to preprocess a source file -ui_console.cpp.i: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_console.cpp.i -.PHONY : ui_console.cpp.i - -ui_console.s: ui_console.cpp.s -.PHONY : ui_console.s - -# target to generate assembly for a file -ui_console.cpp.s: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_console.cpp.s -.PHONY : ui_console.cpp.s - ui_debug.obj: ui_debug.cpp.obj .PHONY : ui_debug.obj @@ -4585,9 +4561,6 @@ help: @echo "... ui_closecall.obj" @echo "... ui_closecall.i" @echo "... ui_closecall.s" - @echo "... ui_console.obj" - @echo "... ui_console.i" - @echo "... ui_console.s" @echo "... ui_debug.obj" @echo "... ui_debug.i" @echo "... ui_debug.s" diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 6501dcc48..2e96ac48b 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -26,9 +26,8 @@ //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: ui_lcr, make arrays for litterals (checkboxes and buttons) -//TODO: Frequency manager //TODO: Weird LCR AFSK scrambling ? +//TODO: Frequency manager //TODO: SD card wiper //TODO: Draw on touchscreen and transmit as spectrum paint //TODO: Use progressbars diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp index b90030e2a..40c591623 100644 --- a/firmware/application/string_format.hpp +++ b/firmware/application/string_format.hpp @@ -30,7 +30,6 @@ using namespace lpc43xx; // TODO: Allow l=0 to not fill/justify? Already using this way in ui_spectrum.hpp... - std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_hex(const uint32_t n, const int32_t l = 0); diff --git a/firmware/application/ui_alphanum.cpp b/firmware/application/ui_alphanum.cpp index 0e46111cb..b44dab7f1 100644 --- a/firmware/application/ui_alphanum.cpp +++ b/firmware/application/ui_alphanum.cpp @@ -48,6 +48,7 @@ AlphanumView::AlphanumView( ) { _max_len = max_len; _lowercase = false; + size_t n; static constexpr Style style_alpha { .font = font::fixed_8x16, @@ -63,6 +64,11 @@ AlphanumView::AlphanumView( txtidx = strlen(txt); memcpy(txtinput, txt, max_len + 1); + n = txtidx; + while (n && (txtinput[n - 1] == ' ')) { + txtinput[--n] = 0; + txtidx--; + } add_child(&text_input); @@ -70,7 +76,7 @@ AlphanumView::AlphanumView( this->on_button(button); }; - size_t n = 0; + n = 0; for(auto& button : buttons) { button.on_select = button_fn; button.set_parent_rect({ @@ -88,7 +94,7 @@ AlphanumView::AlphanumView( set_uppercase(); add_child(&button_lowercase); - button_lowercase.on_select = [this, &nav, txt, max_len](Button&) { + button_lowercase.on_select = [this, &nav, max_len](Button&) { if (_lowercase == true) { _lowercase = false; button_lowercase.set_text("UC"); @@ -191,12 +197,12 @@ void AlphanumView::char_add(const char c) { void AlphanumView::char_delete() { if (txtidx) { txtidx--; - txtinput[txtidx] = ' '; + txtinput[txtidx] = 0; } } void AlphanumView::update_text() { - text_input.set(txtinput); + text_input.set(std::string(txtinput) + std::string(_max_len - strlen(txtinput), ' ')); move_cursor(); } diff --git a/firmware/application/ui_console.cpp b/firmware/application/ui_console.cpp deleted file mode 100644 index 28b9f2985..000000000 --- a/firmware/application/ui_console.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ - -#include "ui_console.hpp" - -#include "portapack.hpp" -using namespace portapack; - -namespace ui { - -void Console::clear() { - display.fill_rectangle( - screen_rect(), - Color::black() - ); - pos = { 0, 0 }; - display.scroll_set_position(0); -} - -void Console::write(const std::string& message) { - const Style& s = style(); - const Font& font = s.font; - const auto rect = screen_rect(); - for(const auto c : message) { - if( c == '\n' ) { - crlf(); - } else { - const auto glyph = font.glyph(c); - const auto advance = glyph.advance(); - if( (pos.x + advance.x) > rect.width() ) { - crlf(); - } - const Point pos_glyph { - rect.pos.x + pos.x, - display.scroll_area_y(pos.y) - }; - display.draw_glyph(pos_glyph, glyph, s.foreground, s.background); - pos.x += advance.x; - } - } -} - -void Console::writeln(const std::string& message) { - write(message); - crlf(); -} - -void Console::paint(Painter& painter) { - // Do nothing. - (void)painter; -} - -void Console::on_show() { - const auto screen_r = screen_rect(); - display.scroll_set_area(screen_r.top(), screen_r.bottom()); - - clear(); -} - -void Console::on_hide() { - /* TODO: Clear region to eliminate brief flash of content at un-shifted - * position? - */ - display.scroll_disable(); -} - -void Console::crlf() { - const Style& s = style(); - const auto sr = screen_rect(); - const auto line_height = s.font.line_height(); - pos.x = 0; - pos.y += line_height; - const int32_t y_excess = pos.y + line_height - sr.height(); - if( y_excess > 0 ) { - display.scroll(-y_excess); - pos.y -= y_excess; - - const Rect dirty { sr.left(), display.scroll_area_y(pos.y), sr.width(), line_height }; - display.fill_rectangle(dirty, s.background); - } -} - -} /* namespace ui */ diff --git a/firmware/application/ui_console.hpp b/firmware/application/ui_console.hpp deleted file mode 100644 index db49acc7e..000000000 --- a/firmware/application/ui_console.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2014 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 __UI_CONSOLE_H__ -#define __UI_CONSOLE_H__ - -#include "ui.hpp" -#include "ui_painter.hpp" -#include "ui_widget.hpp" - -#include - -namespace ui { - -class Console : public Widget { -public: - void clear(); - void write(const std::string& message); - void writeln(const std::string& message); - - void paint(Painter& painter) override; - - void on_show() override; - void on_hide() override; - -private: - Point pos { 0, 0 }; - - void crlf(); -}; - -} /* namespace ui */ - -#endif/*__UI_CONSOLE_H__*/ diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index adee5fd8c..8d3df4e9b 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -281,42 +281,35 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { on_left = [&nav](){ nav.pop(); }; } -char hexify(char in) { - if (in > 9) in += 7; - return in + 0x30; -} - -DebugLCRView::DebugLCRView(NavigationView& nav, char * lcrstring, uint8_t checksum) { - char cstr[15] = "Checksum: 0x "; +DebugLCRView::DebugLCRView(NavigationView& nav, std::string lcr_string, uint8_t checksum) { + + std::string debug_text; add_children({ { - &text_lcr1, - &text_lcr2, - &text_lcr3, - &text_lcr4, - &text_lcr5, - &text_checksum, - &button_done + &console, + &button_exit } }); - - std::string b = std::string(lcrstring); - - text_lcr1.set(b.substr(8+(0*26),26)); - if (strlen(lcrstring) > 34) text_lcr2.set(b.substr(8+(1*26),26)); - if (strlen(lcrstring) > 34+26) text_lcr3.set(b.substr(8+(2*26),26)); - if (strlen(lcrstring) > 34+26+26) text_lcr4.set(b.substr(8+(3*26),26)); - if (strlen(lcrstring) > 34+26+26+26) text_lcr5.set(b.substr(8+(4*26),26)); - - cstr[12] = hexify(checksum >> 4); - cstr[13] = hexify(checksum & 15); - - text_checksum.set(cstr); - - button_done.on_select = [&nav](Button&){ nav.pop(); }; -} + for(const auto c : lcr_string) { + if ((c < 32) || (c > 126)) + debug_text += "[" + to_string_dec_uint(c) + "]"; + else + debug_text += c; + } + + debug_text += "\n\n"; + debug_text += "Length: " + to_string_dec_uint(lcr_string.length()) + '\n'; + debug_text += "Checksum: " + to_string_dec_uint(checksum) + '\n'; + + console.write(debug_text); + + button_exit.on_select = [this, &nav](Button&){ + nav.pop(); + }; +} + void DebugLCRView::focus() { - button_done.focus(); + button_exit.focus(); } } /* namespace ui */ diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 2dca74fea..e3914cfd6 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -240,40 +240,20 @@ private: class DebugLCRView : public View { public: - DebugLCRView(NavigationView& nav, char* lcrstring, uint8_t checksum); + DebugLCRView(NavigationView& nav, std::string lcrstring, uint8_t checksum); void focus() override; + + std::string title() const override { return "LCR debug"; }; private: - Text text_lcr1 { - { 16, 32, 208, 8 }, - "" - }; - Text text_lcr2 { - { 16, 32+16, 208, 8 }, - "" - }; - Text text_lcr3 { - { 16, 32+16+16, 208, 8 }, - "" - }; - Text text_lcr4 { - { 16, 32+16+16+16, 208, 8 }, - "" - }; - Text text_lcr5 { - { 16, 32+16+16+16+16, 208, 8 }, - "" + Console console { + { 8, 16, 224, 240 } }; - Text text_checksum { - { 16, 32+16+16+16+16+16+32, 208, 8 }, - "" - }; - - Button button_done { - { 72, 240, 96, 24 }, - "Done" + Button button_exit { + { 72, 264, 96, 32 }, + "Exit" }; }; diff --git a/firmware/application/ui_handwrite.cpp b/firmware/application/ui_handwrite.cpp index b972deaf0..2173a6256 100644 --- a/firmware/application/ui_handwrite.cpp +++ b/firmware/application/ui_handwrite.cpp @@ -47,12 +47,18 @@ HandWriteView::HandWriteView( ) { const char special_chars[5] = {'\'', '.', '?', '!', '='}; _max_len = max_len; + size_t n; // Handwriting alphabet definition here handwriting = &handwriting_unistroke; txtidx = strlen(txt); memcpy(txtinput, txt, max_len + 1); + n = txtidx; + while (n && (txtinput[n - 1] == ' ')) { + txtinput[--n] = 0; + txtidx--; + } add_children({ { &text_input, @@ -64,7 +70,7 @@ HandWriteView::HandWriteView( this->on_button(button); }; - size_t n = 0; + n = 0; for(auto& button : num_buttons) { add_child(&button); button.on_select = button_fn; diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index ca8f58706..e1aac9bb4 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -67,7 +67,7 @@ void LCRView::generate_message() { } // Compose LCR message - memset(lcr_message, 0, 256); + memset(lcr_message, 0, 512); memcpy(lcr_message, lcr_init, 8); strcat(lcr_message, rgsb); // Address @@ -76,7 +76,7 @@ void LCRView::generate_message() { for (i = 0; i < 5; i++) { if (checkboxes[i].value() == true) { strcat(lcr_message, "AM="); - strcat(lcr_message, to_string_dec_uint(i, 1).c_str()); + strcat(lcr_message, to_string_dec_uint(i + 1, 1).c_str()); strcat(lcr_message, " AF=\""); strcat(lcr_message, litteral[i]); strcat(lcr_message, "\" CL=0 "); @@ -86,8 +86,6 @@ void LCRView::generate_message() { strcat(lcr_message, ec_lut[options_ec.selected_index()]); strcat(lcr_message, " SAB=0"); - memcpy(lcr_string, lcr_message, 256); - // Checksum checksum = 0; i = 7; // Skip modem sync @@ -119,6 +117,7 @@ void LCRView::generate_message() { } lcr_message_data[dp] = new_byte | (pp & 1); } + lcr_message_data[dp++] = 0; lcr_message_data[dp] = 0; } else { // Alt format @@ -129,9 +128,10 @@ void LCRView::generate_message() { if ((cur_byte >> cp) & 1) pp++; } lcr_message_data[dp * 2] = cur_byte; - lcr_message_data[(dp * 2) + 1] = pp & 1; + lcr_message_data[(dp * 2) + 1] = 0xFE | (pp & 1); } lcr_message_data[dp * 2] = 0; + lcr_message_data[(dp * 2) + 1] = 0; } //if (persistent_memory::afsk_config() & 1) { @@ -350,7 +350,7 @@ LCRView::LCRView(NavigationView& nav) { for(auto& button : buttons) { button.on_select = button_setam_fn; button.id = n; - label = "AM " + to_string_dec_uint(n, 1);; + label = "AM " + to_string_dec_uint(n + 1, 1);; button.set_text(label); button.set_parent_rect({ static_cast(48), @@ -373,6 +373,19 @@ LCRView::LCRView(NavigationView& nav) { n++; } + n = 0; + for(auto& rectangle : rectangles) { + rectangle.set_parent_rect({ + static_cast(104 - 2), + static_cast(n * 32 + 68 - 2), + 56 + 4, 16 + 4 + }); + rectangle.set_color(ui::Color::grey()); + rectangle.set_outline(true); + add_child(&rectangle); + n++; + } + button_setrgsb.set_text(rgsb); options_ec.set_selected_index(0); // Auto checkboxes[0].set_value(true); @@ -388,9 +401,9 @@ LCRView::LCRView(NavigationView& nav) { nav.push(); }; - button_lcrdebug.on_select = [this,&nav](Button&) { + button_lcrdebug.on_select = [this, &nav](Button&) { generate_message(); - nav.push(lcr_string, checksum); + nav.push(std::string(lcr_message), checksum); }; button_transmit.on_select = [this](Button&) { diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 860bafcca..5fe698a7f 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -64,9 +64,8 @@ private: }; char litteral[5][8]; char rgsb[5]; - char lcr_message[256]; - char lcr_string[256]; // For debugging, can remove - char lcr_message_data[256]; + char lcr_message[512]; + char lcr_message_data[512]; char checksum = 0; rf::Frequency f; uint8_t repeat_index; @@ -116,6 +115,7 @@ private: std::array buttons; std::array checkboxes; + std::array rectangles; Text text_recap { { 8, 6, 18 * 8, 16 }, diff --git a/firmware/application/ui_xylos.cpp b/firmware/application/ui_xylos.cpp index ceec2e5b1..0a4b33b2a 100644 --- a/firmware/application/ui_xylos.cpp +++ b/firmware/application/ui_xylos.cpp @@ -247,7 +247,7 @@ void XylosView::on_txdone(const int n) { start_tx(); } } else { - progress.set_value(n * 5); + progress.set_value(n); } } } @@ -296,6 +296,8 @@ XylosView::XylosView(NavigationView& nav) { options_freq.set_selected_index(5); tempo_cligno.set_value(5); + progress.set_max(20); + options_ra.set_selected_index(1); // R1 OFF checkbox_wcsubfamily.set_value(true); diff --git a/firmware/baseband/proc_afsk.cpp b/firmware/baseband/proc_afsk.cpp index 3de231a39..82c664489 100644 --- a/firmware/baseband/proc_afsk.cpp +++ b/firmware/baseband/proc_afsk.cpp @@ -43,7 +43,7 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { if (configured == true) { cur_byte = message_data[byte_pos]; ext_byte = message_data[byte_pos + 1]; - if (!cur_byte) { + if (!(cur_byte | ext_byte)) { if (repeat_counter < afsk_repeat) { bit_pos = 0; byte_pos = 0; @@ -62,18 +62,18 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { } } - if (afsk_alt_format) { - // 0bbbbbbbbp - // Start, 8-bit data, parity - gbyte = 0; - gbyte = cur_byte << 1; - gbyte |= (ext_byte & 1); - } else { + if (!afsk_alt_format) { // 0bbbbbbbp1 // Start, 7-bit data, parity, stop gbyte = 0; gbyte = cur_byte << 1; gbyte |= 1; + } else { + // 0bbbbbbbbp + // Start, 8-bit data, parity + gbyte = 0; + gbyte = cur_byte << 1; + gbyte |= (ext_byte & 1); } cur_bit = (gbyte >> (9 - bit_pos)) & 1; @@ -120,7 +120,7 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { void AFSKProcessor::on_message(const Message* const p) { const auto message = *reinterpret_cast(p); if (message.id == Message::ID::AFSKConfigure) { - memcpy(message_data, message.message_data, 256); + memcpy(message_data, message.message_data, 512); afsk_samples_per_bit = message.afsk_samples_per_bit; afsk_phase_inc_mark = message.afsk_phase_inc_mark; afsk_phase_inc_space = message.afsk_phase_inc_space; @@ -128,6 +128,7 @@ void AFSKProcessor::on_message(const Message* const p) { afsk_bw = message.afsk_bw; afsk_alt_format = message.afsk_alt_format; + sample_count = afsk_samples_per_bit; repeat_counter = 0; bit_pos = 0; byte_pos = 0; diff --git a/firmware/baseband/proc_afsk.hpp b/firmware/baseband/proc_afsk.hpp index c748bf472..3a2e46397 100644 --- a/firmware/baseband/proc_afsk.hpp +++ b/firmware/baseband/proc_afsk.hpp @@ -43,12 +43,13 @@ private: uint8_t afsk_repeat; uint32_t afsk_bw; bool afsk_alt_format; - char message_data[256]; + char message_data[512]; uint8_t repeat_counter = 0; int8_t re, im; uint8_t s; - uint8_t bit_pos = 0, byte_pos = 0; + uint8_t bit_pos = 0; + uint16_t byte_pos = 0; char cur_byte = 0; char ext_byte = 0; uint16_t gbyte; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index a07b1c426..c81a1724e 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -539,7 +539,7 @@ public: afsk_bw(afsk_bw), afsk_alt_format(afsk_alt_format) { - memcpy(message_data, data, 256); + memcpy(message_data, data, 512); } uint32_t afsk_samples_per_bit; @@ -548,7 +548,7 @@ public: uint8_t afsk_repeat; uint32_t afsk_bw; bool afsk_alt_format; - char message_data[256]; + char message_data[512]; }; class FIFOSignalMessage : public Message { diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 021a9f7ff..d25b2cdad 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -253,16 +253,33 @@ Rectangle::Rectangle( { } +Rectangle::Rectangle( +) : Widget { } +{ +} + void Rectangle::set_color(const Color c) { color = c; set_dirty(); } +void Rectangle::set_outline(const bool outline) { + _outline = outline; + set_dirty(); +} + void Rectangle::paint(Painter& painter) { - painter.fill_rectangle( - screen_rect(), - color - ); + if (!_outline) { + painter.fill_rectangle( + screen_rect(), + color + ); + } else { + painter.draw_rectangle( + screen_rect(), + color + ); + } } /* Text ******************************************************************/ @@ -423,6 +440,90 @@ void ProgressBar::paint(Painter& painter) { painter.draw_rectangle(rect, s.foreground); } +/* Console ***************************************************************/ + +Console::Console( + Rect parent_rect +) : Widget { parent_rect } +{ + display.scroll_set_position(0); +} + +void Console::clear() { + display.fill_rectangle( + screen_rect(), + Color::black() + ); + pos = { 0, 0 }; +} + +void Console::write(std::string message) { + if (visible) { + const Style& s = style(); + const Font& font = s.font; + const auto rect = screen_rect(); + for(const auto c : message) { + if( c == '\n' ) { + crlf(); + } else { + const auto glyph = font.glyph(c); + const auto advance = glyph.advance(); + if( (pos.x + advance.x) > rect.width() ) { + crlf(); + } + const Point pos_glyph { + rect.pos.x + pos.x, + display.scroll_area_y(pos.y) + }; + display.draw_glyph(pos_glyph, glyph, s.foreground, s.background); + pos.x += advance.x; + } + } + buffer = message; + } else { + buffer += message; + } +} + +void Console::writeln(std::string message) { + write(message); + crlf(); +} + +void Console::paint(Painter& painter) { + write(buffer); +} + +void Console::on_show() { + const auto screen_r = screen_rect(); + display.scroll_set_area(screen_r.top(), screen_r.bottom()); + clear(); + visible = true; +} + +void Console::on_hide() { + /* TODO: Clear region to eliminate brief flash of content at un-shifted + * position? + */ + display.scroll_disable(); +} + +void Console::crlf() { + const Style& s = style(); + const auto sr = screen_rect(); + const auto line_height = s.font.line_height(); + pos.x = 0; + pos.y += line_height; + const int32_t y_excess = pos.y + line_height - sr.height(); + if( y_excess > 0 ) { + display.scroll(-y_excess); + pos.y -= y_excess; + + const Rect dirty { sr.left(), display.scroll_area_y(pos.y), sr.width(), line_height }; + display.fill_rectangle(dirty, s.background); + } +} + /* Checkbox **************************************************************/ Checkbox::Checkbox( diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 4af3b3528..7d3f6aaa8 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -173,13 +173,16 @@ class Rectangle : public Widget { public: Rectangle(Color c); Rectangle(Rect parent_rect, Color c); + Rectangle(); void paint(Painter& painter) override; void set_color(const Color c); + void set_outline(const bool outline); private: Color color; + bool _outline = false; }; class Text : public Widget { @@ -225,6 +228,27 @@ private: uint16_t _max = 100; }; +class Console : public Widget { +public: + Console(Rect parent_rect); + + void clear(); + void write(std::string message); + void writeln(std::string message); + + void paint(Painter& painter) override; + + void on_show() override; + void on_hide() override; + +private: + bool visible = false; + Point pos { 0, 0 }; + std::string buffer; + + void crlf(); +}; + class Checkbox : public Widget { public: std::function on_select; diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 59dd8e63d..152517da4 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ diff --git a/sdcard/baseband-tx.bin b/sdcard/baseband-tx.bin deleted file mode 100644 index d7f2a1b1d..000000000 Binary files a/sdcard/baseband-tx.bin and /dev/null differ diff --git a/sdcard/baseband.bin b/sdcard/baseband.bin deleted file mode 100644 index a877db80c..000000000 Binary files a/sdcard/baseband.bin and /dev/null differ diff --git a/sdcard/yosemitesam.wav b/sdcard/yosemitesam.wav new file mode 100644 index 000000000..5fc5a72e4 Binary files /dev/null and b/sdcard/yosemitesam.wav differ