From f1166205b069ac43a278c678f78b6c3596bfad71 Mon Sep 17 00:00:00 2001 From: furrtek Date: Sat, 5 Sep 2015 20:17:43 +0200 Subject: [PATCH] Checkboxes, more AFSK options --- firmware/application/ui_afsksetup.cpp | 15 +++ firmware/application/ui_afsksetup.hpp | 16 ++- firmware/application/ui_debug.cpp | 12 +- firmware/application/ui_debug.hpp | 4 - firmware/application/ui_lcr.cpp | 109 +++++++++++---- firmware/application/ui_lcr.hpp | 42 ++++-- .../common/portapack_persistent_memory.cpp | 8 +- .../common/portapack_persistent_memory.hpp | 4 +- firmware/common/ui_widget.cpp | 127 ++++++++++++++++++ firmware/common/ui_widget.hpp | 41 ++++++ 10 files changed, 317 insertions(+), 61 deletions(-) diff --git a/firmware/application/ui_afsksetup.cpp b/firmware/application/ui_afsksetup.cpp index 4e0e6266..7fd85f90 100644 --- a/firmware/application/ui_afsksetup.cpp +++ b/firmware/application/ui_afsksetup.cpp @@ -79,9 +79,16 @@ AFSKSetupView::AFSKSetupView( &field_mark, &text_space, &field_space, + &checkbox_lsb, + &checkbox_parity, + &checkbox_datasize, &button_done } }); + if (persistent_memory::afsk_config() & 1) checkbox_lsb.set_value(true); + if (persistent_memory::afsk_config() & 2) checkbox_parity.set_value(true); + if (persistent_memory::afsk_config() & 4) checkbox_datasize.set_value(true); + updfreq(persistent_memory::tuned_frequency()); field_mark.set_value(persistent_memory::afsk_mark_freq()*100); @@ -112,8 +119,16 @@ AFSKSetupView::AFSKSetupView( }; button_done.on_select = [this,&nav](Button&){ + uint8_t afsk_config = 0; + persistent_memory::set_afsk_mark(field_mark.value()/100); persistent_memory::set_afsk_space(field_space.value()/100); + + if (checkbox_lsb.value() == true) afsk_config |= 1; + if (checkbox_parity.value() == true) afsk_config |= 2; + if (checkbox_datasize.value() == true) afsk_config |= 4; + persistent_memory::set_afsk_config(afsk_config); + nav.pop(); }; } diff --git a/firmware/application/ui_afsksetup.hpp b/firmware/application/ui_afsksetup.hpp index c9f36b06..15e11282 100644 --- a/firmware/application/ui_afsksetup.hpp +++ b/firmware/application/ui_afsksetup.hpp @@ -43,7 +43,6 @@ public: void paint(Painter& painter) override; private: - //rf::Frequency f = 162950000; TransmitterModel& transmitter_model; Text text_title { @@ -84,8 +83,21 @@ private: ' ' }; + Checkbox checkbox_lsb { + { 8, 150 }, + "LSB first" + }; + Checkbox checkbox_parity { + { 8, 180 }, + "Even parity" + }; + Checkbox checkbox_datasize { + { 8, 210 }, + "8 bits" + }; + Button button_done { - { 72, 200, 96, 48 }, + { 72, 250, 96, 48 }, "Save" }; }; diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index d917d434..05cc1ce2 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -230,8 +230,6 @@ void DebugSDView::focus() { button_done.focus(); } -// LCR debug view - void DebugLCRView::paint(Painter& painter) { const Point offset = { static_cast(32), @@ -260,7 +258,6 @@ DebugLCRView::DebugLCRView(NavigationView& nav, char* lcrstring, uint8_t checksu &text_lcr3, &text_lcr4, &text_lcr5, - &text_lcr6, &text_checksum, &button_done } }); @@ -268,11 +265,10 @@ DebugLCRView::DebugLCRView(NavigationView& nav, char* lcrstring, uint8_t checksu std::string b = std::string(lcrstring); text_lcr1.set(b.substr(8+(0*26),26)); - text_lcr2.set(b.substr(8+(1*26),26)); - text_lcr3.set(b.substr(8+(2*26),26)); - text_lcr4.set(b.substr(8+(3*26),26)); - text_lcr5.set(b.substr(8+(4*26),26)); - text_lcr6.set(b.substr(8+(5*26),26)); + if (strlen(b > 34)) text_lcr2.set(b.substr(8+(1*26),26)); + if (strlen(b > 34+26)) text_lcr3.set(b.substr(8+(2*26),26)); + if (strlen(b > 34+26+26)) text_lcr4.set(b.substr(8+(3*26),26)); + if (strlen(b > 34+26+26+26)) text_lcr5.set(b.substr(8+(4*26),26)); cstr[12] = hexify(checksum >> 4); cstr[13] = hexify(checksum & 15); diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index b85fb7a1..8ce1ba1f 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -217,10 +217,6 @@ private: { 16, 32+16+16+16+16, 208, 8 }, "" }; - Text text_lcr6 { - { 16, 32+16+16+16+16+16, 208, 8 }, - "" - }; Text text_checksum { { 16, 32+16+16+16+16+16+32, 208, 8 }, diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index 4b89f6e9..6c0ff4d1 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -50,7 +50,7 @@ using namespace hackrf::one; namespace ui { void LCRView::focus() { - button_setam_a.focus(); + button_setrgsb.focus(); } LCRView::~LCRView() { @@ -58,40 +58,56 @@ LCRView::~LCRView() { } void LCRView::make_frame() { - char eom[3] = { 3, 0, 0 }; - uint8_t i; + char eom[3] = { 3, 0, 0 }; // EOM and space for checksum + uint8_t i, pm; uint16_t dp; uint8_t cp, pp, cur_byte, new_byte; - // Testing: 7 char pad for litterals + // Pad litterals right to 7 chars (not required ?) for (i = 0; i < 5; i++) { while (strlen(litteral[i]) < 7) { strcat(litteral[i], " "); } } - // Recreate LCR frame + // Make LCR frame memset(lcrframe, 0, 256); - lcrframe[0] = 127; + lcrframe[0] = 127; // Modem sync lcrframe[1] = 127; lcrframe[2] = 127; lcrframe[3] = 127; lcrframe[4] = 127; lcrframe[5] = 127; lcrframe[6] = 127; - lcrframe[7] = 15; + lcrframe[7] = 15; // SOM strcat(lcrframe, rgsb); - strcat(lcrframe, "PA AM=1 AF=\""); - strcat(lcrframe, litteral[0]); - strcat(lcrframe, "\" CL=0 AM=2 AF=\""); - strcat(lcrframe, litteral[1]); - strcat(lcrframe, "\" CL=0 AM=3 AF=\""); - strcat(lcrframe, litteral[2]); - strcat(lcrframe, "\" CL=0 AM=4 AF=\""); - strcat(lcrframe, litteral[3]); - strcat(lcrframe, "\" CL=0 AM=5 AF=\""); - strcat(lcrframe, litteral[4]); - strcat(lcrframe, "\" CL=0 EC=A SAB=0"); //TODO: EC=A,J,N + strcat(lcrframe, "PA "); + if (checkbox_am_a.value() == true) { + strcat(lcrframe, "AM=1 AF=\""); + strcat(lcrframe, litteral[0]); + strcat(lcrframe, "\" CL=0 "); + } + if (checkbox_am_b.value() == true) { + strcat(lcrframe, "AM=2 AF=\""); + strcat(lcrframe, litteral[1]); + strcat(lcrframe, "\" CL=0 "); + } + if (checkbox_am_c.value() == true) { + strcat(lcrframe, "AM=3 AF=\""); + strcat(lcrframe, litteral[2]); + strcat(lcrframe, "\" CL=0 "); + } + if (checkbox_am_d.value() == true) { + strcat(lcrframe, "AM=4 AF=\""); + strcat(lcrframe, litteral[3]); + strcat(lcrframe, "\" CL=0 "); + } + if (checkbox_am_e.value() == true) { + strcat(lcrframe, "AM=5 AF=\""); + strcat(lcrframe, litteral[4]); + strcat(lcrframe, "\" CL=0 "); + } + strcat(lcrframe, "EC=A SAB=0"); //TODO: EC=A,J,N memcpy(lcrstring, lcrframe, 256); @@ -102,21 +118,47 @@ void LCRView::make_frame() { checksum ^= lcrframe[i]; i++; } - checksum ^= 3; + checksum ^= eom[0]; // EOM checksum &= 0x7F; eom[1] = checksum; strcat(lcrframe, eom); - for (dp=0;dp>cp)&1) pp++; - new_byte |= ((cur_byte>>cp)&1)<<(7-cp); + if (persistent_memory::afsk_config() & 2) + pm = 0; // Even parity + else + pm = 1; // Odd parity + + if (persistent_memory::afsk_config() & 1) { + // LSB first + for (dp=0;dp>cp)&1) pp++; + new_byte |= ((cur_byte>>cp)&1)<<(6-cp); + } + // 8/7 bit + if (persistent_memory::afsk_config() & 4) + lcrframe_f[dp] = new_byte; + else + lcrframe_f[dp] = (new_byte<<1)|(pp&1); + } + } else { + // MSB first + for (dp=0;dp>cp)&1) pp++; + } + // 8/7 bit + if (persistent_memory::afsk_config() & 4) + lcrframe_f[dp] = cur_byte; + else + lcrframe_f[dp] = (cur_byte<<1)|(pp&1); } - lcrframe_f[dp] = new_byte|(pp&1); } } @@ -128,7 +170,7 @@ void LCRView::paint(Painter& painter) { }; Point offset = { - static_cast(72), + static_cast(104), static_cast(72) }; @@ -195,10 +237,15 @@ LCRView::LCRView( &text_recap, &button_setrgsb, &button_txsetup, + &checkbox_am_a, &button_setam_a, + &checkbox_am_b, &button_setam_b, + &checkbox_am_c, &button_setam_c, + &checkbox_am_d, &button_setam_d, + &checkbox_am_e, &button_setam_e, &text_status, &button_lcrdebug, @@ -207,6 +254,12 @@ LCRView::LCRView( &button_exit } }); + checkbox_am_a.set_value(true); + checkbox_am_b.set_value(true); + checkbox_am_c.set_value(true); + checkbox_am_d.set_value(true); + checkbox_am_e.set_value(true); + // Recap: tx freq @ bps auto fstr = to_string_dec_int(persistent_memory::tuned_frequency() / 1000, 6); auto bstr = to_string_dec_int(persistent_memory::afsk_bitrate(), 4); diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 85b26b6b..9e25609d 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -62,11 +62,11 @@ private: char checksum = 0; char lcrframe[256]; char lcrframe_f[256]; - rf::Frequency f = 162950000; + rf::Frequency f; TransmitterModel& transmitter_model; Text text_status { - { 136, 128, 64, 16 }, + { 172, 196, 64, 16 }, "Ready" }; @@ -83,34 +83,50 @@ private: { 120, 24, 96, 32 }, "TX setup" }; - + + Checkbox checkbox_am_a { + { 16, 68 }, + "" + }; Button button_setam_a { - { 16, 64, 48, 32 }, + { 48, 64, 48, 32 }, "AM 1" }; - + Checkbox checkbox_am_b { + { 16, 68+40 }, + "" + }; Button button_setam_b { - { 16, 64+40, 48, 32 }, + { 48, 64+40, 48, 32 }, "AM 2" }; - + Checkbox checkbox_am_c { + { 16, 68+40+40 }, + "" + }; Button button_setam_c { - { 16, 64+40+40, 48, 32 }, + { 48, 64+40+40, 48, 32 }, "AM 3" }; - + Checkbox checkbox_am_d { + { 16, 68+40+40+40 }, + "" + }; Button button_setam_d { - { 16, 64+40+40+40, 48, 32 }, + { 48, 64+40+40+40, 48, 32 }, "AM 4" }; - + Checkbox checkbox_am_e { + { 16, 68+40+40+40+40 }, + "" + }; Button button_setam_e { - { 16, 64+40+40+40+40, 48, 32 }, + { 48, 64+40+40+40+40, 48, 32 }, "AM 5" }; Button button_lcrdebug { - { 152, 224, 64, 32 }, + { 166, 224, 56, 32 }, "DEBUG" }; diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 4c133cec..f6cf2b1a 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -72,9 +72,9 @@ struct data_t { // AFSK modem int32_t afsk_mark_freq; - int32_t afsk_space_freq; + int32_t afsk_space_freq; // Todo: optimize size, only 256 bytes of NVRAM ! int32_t afsk_bitrate; - uint8_t afsk_config; + uint32_t afsk_config; // Play dead unlock bool playing_dead; @@ -130,11 +130,11 @@ void set_afsk_bitrate(const int32_t new_value) { data->afsk_bitrate = afsk_bitrate_range.clip(new_value); } -uint8_t afsk_config() { +uint32_t afsk_config() { return data->afsk_config; } -void set_afsk_config(const uint8_t new_value) { +void set_afsk_config(const uint32_t new_value) { data->afsk_config = new_value; } diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 08aabe06..7734792c 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -46,8 +46,8 @@ void set_afsk_space(const int32_t new_value); int32_t afsk_bitrate(); void set_afsk_bitrate(const int32_t new_value); -uint8_t afsk_config(); -void set_afsk_config(const uint8_t new_value); +uint32_t afsk_config(); +void set_afsk_config(const uint32_t new_value); bool playing_dead(); void set_playing_dead(const bool new_value); diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index a193e9a1..eb43b46a 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -21,6 +21,7 @@ #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "portapack.hpp" #include #include @@ -349,6 +350,132 @@ void Text::paint(Painter& painter) { ); } +/* Checkbox **************************************************************/ + +void Checkbox::set_text(const std::string value) { + text_ = value; + set_dirty(); +} + +std::string Checkbox::text() const { + return text_; +} + +void Checkbox::set_value(const bool value) { + value_ = value; + set_dirty(); +} + +bool Checkbox::value() const { + return value_; +} + +void Checkbox::paint(Painter& painter) { + const auto r = screen_rect(); + + const auto paint_style = (has_focus() || flags.highlighted) ? style().invert() : style(); + + painter.draw_rectangle({ r.pos.x, r.pos.y, 24, 24 }, style().foreground); + + painter.fill_rectangle( + { + static_cast(r.pos.x + 1), static_cast(r.pos.y + 1), + static_cast(24 - 2), static_cast(24 - 2) + }, + style().background + ); + + painter.draw_rectangle({ r.pos.x+2, r.pos.y+2, 24-4, 24-4 }, paint_style.background); + + if (value_ == true) { + // Check + portapack::display.draw_line( {r.pos.x+2, r.pos.y+14}, {r.pos.x+6, r.pos.y+18}, ui::Color::green()); + portapack::display.draw_line( {r.pos.x+6, r.pos.y+18}, {r.pos.x+20, r.pos.y+4}, ui::Color::green()); + } else { + // Cross + portapack::display.draw_line( {r.pos.x+1, r.pos.y+1}, {r.pos.x+24-2, r.pos.y+24-2}, ui::Color::red()); + portapack::display.draw_line( {r.pos.x+24-2, r.pos.y+1}, {r.pos.x+1, r.pos.y+24-2}, ui::Color::red()); + } + + const auto label_r = paint_style.font.size_of(text_); + painter.draw_string( + { + static_cast(r.pos.x + 24 + 4), + static_cast(r.pos.y + (24 - label_r.h) / 2) + }, + paint_style, + text_ + ); +} + +bool Checkbox::on_key(const KeyEvent key) { + if( key == KeyEvent::Select ) { + value_ = not value_; + set_dirty(); + + if( on_select ) { + on_select(*this); + + return true; + } + } + + return false; +} + +bool Checkbox::on_touch(const TouchEvent event) { + switch(event.type) { + case TouchEvent::Type::Start: + flags.highlighted = true; + set_dirty(); + return true; + + + case TouchEvent::Type::End: + flags.highlighted = false; + value_ = not value_; + set_dirty(); + if( on_select ) { + on_select(*this); + } + return true; + + default: + return false; + } +#if 0 + switch(event.type) { + case TouchEvent::Type::Start: + flags.highlighted = true; + set_dirty(); + return true; + + case TouchEvent::Type::Move: + { + const bool new_highlighted = screen_rect().contains(event.point); + if( flags.highlighted != new_highlighted ) { + flags.highlighted = new_highlighted; + set_dirty(); + } + } + return true; + + case TouchEvent::Type::End: + if( flags.highlighted ) { + flags.highlighted = false; + set_dirty(); + if( on_select ) { + on_select(*this); + } + } + return true; + + default: + return false; + } +#endif +} + /* Button ****************************************************************/ void Button::set_text(const std::string value) { diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 341aa0c8..24050481 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -56,6 +56,12 @@ public: ) : parent_rect { } { } + + constexpr Widget( + Point parent_point + ) : parent_rect { parent_point, { 24, 24 } } + { + } constexpr Widget( Rect parent_rect @@ -209,6 +215,41 @@ private: std::string text; }; +class Checkbox : public Widget { +public: + std::function on_select; + + Checkbox( + Point parent_point, + std::string text + ) : Widget { parent_point }, + text_ { text } + { + flags.focusable = true; + } + + Checkbox( + ) : Checkbox { { }, { } } + { + } + + void set_text(const std::string value); + void set_style(const Style* new_style); + std::string text() const; + void set_value(const bool value); + bool value() const; + + void paint(Painter& painter) override; + + bool on_key(const KeyEvent key) override; + bool on_touch(const TouchEvent event) override; + +private: + std::string text_; + bool value_ = false; + const Style* style_ { nullptr }; +}; + class Button : public Widget { public: std::function on_select;