diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 363b8381..e0568b3a 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -24,12 +24,12 @@ //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: Two players tic-tac-toe //TODO: Breakout game //TODO: SD card wiper //TODO: Draw on touchscreen and transmit as spectrum paint //TODO: Use progressbars //TODO: Setting: Prefered input method -//TODO: LCR emergency clear all //TODO: LCR receiver //TODO: Xylos receiver //TODO: Morse coder diff --git a/firmware/application/ui_alphanum.cpp b/firmware/application/ui_alphanum.cpp index 33578b10..eb38732c 100644 --- a/firmware/application/ui_alphanum.cpp +++ b/firmware/application/ui_alphanum.cpp @@ -36,6 +36,10 @@ using namespace hackrf::one; namespace ui { +void AlphanumView::paint(Painter& painter) { + move_cursor(); +} + AlphanumView::AlphanumView( NavigationView& nav, char txt[], @@ -56,8 +60,8 @@ AlphanumView::AlphanumView( .foreground = Color::black(), }; - txtidx = 0; - memcpy(txtinput, txt, max_len+1); + txtidx = strlen(txt); + memcpy(txtinput, txt, max_len + 1); add_child(&text_input); @@ -71,7 +75,7 @@ AlphanumView::AlphanumView( button.on_select = button_fn; button.set_parent_rect({ static_cast((n % 5) * button_w), - static_cast((n / 5) * button_h + 18), + static_cast((n / 5) * button_h + 24), button_w, button_h }); if ((n < 10) || (n == 39)) @@ -97,7 +101,7 @@ AlphanumView::AlphanumView( add_child(&button_done); button_done.on_select = [this, &nav, txt, max_len](Button&) { - memcpy(txt, txtinput, max_len+1); + memcpy(txt, txtinput, max_len + 1); on_changed(this->value()); nav.pop(); }; @@ -105,6 +109,22 @@ AlphanumView::AlphanumView( update_text(); } +void AlphanumView::move_cursor() { + Point cursor_pos; + + cursor_pos.x = text_input.screen_rect().pos.x + (txtidx * 8); + cursor_pos.y = text_input.screen_rect().pos.y + 16; + + portapack::display.fill_rectangle( + {{text_input.screen_rect().pos.x, cursor_pos.y}, {text_input.screen_rect().size.w, 4}}, + Color::black() + ); + portapack::display.fill_rectangle( + {cursor_pos, {8, 4}}, + Color::white() + ); +} + void AlphanumView::set_uppercase() { const char* const key_caps = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. !<"; @@ -121,7 +141,7 @@ void AlphanumView::set_uppercase() { void AlphanumView::set_lowercase() { - const char* const key_caps = "0123456789abcdefghijklmnopqrstuvwxyz. !<"; + const char* const key_caps = "0123456789abcdefghijklmnopqrstuvwxyz:=?<"; size_t n = 0; for(auto& button : buttons) { @@ -139,6 +159,7 @@ void AlphanumView::focus() { } char * AlphanumView::value() { + txtinput[txtidx] = 0; return txtinput; } @@ -168,6 +189,7 @@ void AlphanumView::char_delete() { void AlphanumView::update_text() { text_input.set(txtinput); + move_cursor(); } } diff --git a/firmware/application/ui_alphanum.hpp b/firmware/application/ui_alphanum.hpp index 42b20672..9f1c8fd3 100644 --- a/firmware/application/ui_alphanum.hpp +++ b/firmware/application/ui_alphanum.hpp @@ -40,27 +40,27 @@ public: AlphanumView(NavigationView& nav, char txt[], uint8_t max_len); + void paint(Painter& painter) override; void focus() override; char * value(); - - uint8_t txtidx; - - void char_add(const char c); - void char_delete(); private: uint8_t _max_len; + uint8_t txtidx; bool _lowercase = false; static constexpr size_t button_w = 240 / 5; static constexpr size_t button_h = 28; - char txtinput[21]; + char txtinput[25] = {0}; + void char_add(const char c); + void char_delete(); void set_lowercase(); void set_uppercase(); + void move_cursor(); Text text_input { - { 8, 0, 200, 16 } + { 8, 0, 224, 16 } }; std::array buttons; diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index fd333957..ceb4dd04 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -79,7 +80,6 @@ void LCRView::make_frame() { lcrframe[6] = 127; lcrframe[7] = 15; // SOM - strcpy(rgsb, RGSB_list[adr_code.value()]); button_setrgsb.set_text(rgsb); strcat(lcrframe, rgsb); @@ -133,15 +133,15 @@ void LCRView::make_frame() { //if (persistent_memory::afsk_config() & 1) { // LSB first - for (dp=0;dp>cp)&1) pp++; - new_byte |= (((cur_byte>>cp)&1)<<(7-cp)); + for (cp = 0; cp < 7; cp++) { + if ((cur_byte >> cp) & 1) pp++; + new_byte |= (((cur_byte >> cp) & 1) << (7 - cp)); } - lcrframe_f[dp] = new_byte|(pp&1); + lcrframe_f[dp] = new_byte | (pp & 1); } /*} else { // MSB first @@ -169,7 +169,7 @@ void LCRView::paint(Painter& painter) { Point offset = { static_cast(104), - static_cast(72) + static_cast(68) }; for (i = 0; i < 5; i++) { @@ -178,38 +178,141 @@ void LCRView::paint(Painter& painter) { style_orange, litteral[i] ); - offset.y += 40; + offset.y += 32; } } +void LCRView::start_tx() { + char str[16]; + + if (scanning) { + scan_index = 0; + strcpy(rgsb, RGSB_list[0]); + } + + make_frame(); + + transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency()); + + shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate(); + shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x40000*256)/2280; + shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x40000*256)/2280; + + shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8; + + memset(shared_memory.lcrdata, 0, 256); + memcpy(shared_memory.lcrdata, lcrframe_f, 256); + + shared_memory.afsk_transmit_done = false; + shared_memory.afsk_repeat = 5; //(portapack::persistent_memory::afsk_config() >> 8) & 0xFF; + + EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); + + EventDispatcher::message_map().register_handler(Message::ID::TXDone, + [this](Message* const p) { + char str[16]; + + if (abort_scan) { + text_status.set(" "); + strcpy(str, "Abort @"); + strcat(str, rgsb); + //strcat(str, to_string_dec_int((portapack::persistent_memory::afsk_config() >> 8) & 0xFF).c_str()); + text_status.set(str); + progress.set_value(0); + transmitter_model.disable(); + txing = false; + scanning = false; + abort_scan = false; + button_scan.set_style(&style_val); + button_scan.set_text("SCAN"); + return; + } + + const auto message = static_cast(p); + if (message->n > 0) { + if (scanning) { + scan_progress += 0.555f; + progress.set_value(scan_progress); + } else { + text_status.set(" "); + strcpy(str, to_string_dec_int(6 - message->n).c_str()); + strcat(str, "/5"); + //strcat(str, to_string_dec_int((portapack::persistent_memory::afsk_config() >> 8) & 0xFF).c_str()); + text_status.set(str); + progress.set_value((6 - message->n) * 20); + } + } else { + if (scanning && (scan_index < 36)) { + transmitter_model.disable(); + + // Next address + strcpy(rgsb, RGSB_list[scan_index]); + make_frame(); + + memset(shared_memory.lcrdata, 0, 256); + memcpy(shared_memory.lcrdata, lcrframe_f, 256); + shared_memory.afsk_transmit_done = false; + shared_memory.afsk_repeat = 5; + + text_status.set(" "); + strcpy(str, to_string_dec_int(scan_index).c_str()); + strcat(str, "/36"); + text_status.set(str); + scan_progress += 0.694f; + progress.set_value(scan_progress); + + scan_index++; + transmitter_model.enable(); + } else { + text_status.set("Ready "); + progress.set_value(0); + transmitter_model.disable(); + txing = false; + scanning = false; + button_scan.set_style(&style_val); + button_scan.set_text("SCAN"); + } + } + } + ); + + if (scanning) { + text_status.set(" "); + strcat(str, "1/36"); + text_status.set(str); + progress.set_value(1); + scan_index++; + } else { + strcpy(str, "1/5 "); + //strcat(str, to_string_dec_int(shared_memory.afsk_repeat).c_str()); + text_status.set(str); + progress.set_value(20); + } + + txing = true; + transmitter_model.enable(); +} + LCRView::LCRView( NavigationView& nav ) { char finalstr[24] = {0}; - static constexpr Style style_val { - .font = font::fixed_8x16, - .background = Color::green(), - .foreground = Color::black(), - }; - transmitter_model.set_baseband_configuration({ .mode = 3, .sampling_rate = 2280000, // Is this right ? .decimation_factor = 1, }); - transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency()); - memset(litteral, 0, 5*8); + memset(litteral, 0, 5 * 8); memset(rgsb, 0, 5); - strcpy(rgsb, RGSB_list[adr_code.value()]); + strcpy(rgsb, RGSB_list[0]); button_setrgsb.set_text(rgsb); add_children({ { &text_recap, - &adr_code, &button_setrgsb, &button_txsetup, &checkbox_am_a, @@ -223,155 +326,93 @@ LCRView::LCRView( &checkbox_am_e, &button_setam_e, &text_status, + &progress, &button_lcrdebug, &button_transmit, - &button_transmit_scan, - &button_exit + &button_scan, + &button_clear } }); 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); + checkbox_am_b.set_value(false); + checkbox_am_c.set_value(false); + checkbox_am_d.set_value(false); + checkbox_am_e.set_value(false); // Recap: tx freq @ bps auto fstr = to_string_dec_int(portapack::persistent_memory::tuned_frequency() / 1000, 6); auto bstr = to_string_dec_int(portapack::persistent_memory::afsk_bitrate(), 4); - strcat(finalstr, fstr.c_str()); strcat(finalstr, " @ "); strcat(finalstr, bstr.c_str()); strcat(finalstr, "bps"); - text_recap.set(finalstr); button_transmit.set_style(&style_val); - button_transmit_scan.set_style(&style_val); + button_scan.set_style(&style_val); - button_setrgsb.on_select = [this,&nav](Button&){ + button_setrgsb.on_select = [this,&nav](Button&) { auto an_view = nav.push(rgsb, 4); an_view->on_changed = [this](char *rgsb) { button_setrgsb.set_text(rgsb); }; }; - button_setam_a.on_select = [this,&nav](Button&){ + button_setam_a.on_select = [this,&nav](Button&) { auto an_view = nav.push(litteral[0], 7); an_view->on_changed = [this](char *) {}; }; - button_setam_b.on_select = [this,&nav](Button&){ + button_setam_b.on_select = [this,&nav](Button&) { auto an_view = nav.push(litteral[1], 7); an_view->on_changed = [this](char *) {}; }; - button_setam_c.on_select = [this,&nav](Button&){ + button_setam_c.on_select = [this,&nav](Button&) { auto an_view = nav.push(litteral[2], 7); an_view->on_changed = [this](char *) {}; }; - button_setam_d.on_select = [this,&nav](Button&){ + button_setam_d.on_select = [this,&nav](Button&) { auto an_view = nav.push(litteral[3], 7); an_view->on_changed = [this](char *) {}; }; - button_setam_e.on_select = [this,&nav](Button&){ + button_setam_e.on_select = [this,&nav](Button&) { auto an_view = nav.push(litteral[4], 7); an_view->on_changed = [this](char *) {}; }; - button_lcrdebug.on_select = [this,&nav](Button&){ + button_txsetup.on_select = [&nav](Button&) { + nav.push(); + }; + + button_lcrdebug.on_select = [this,&nav](Button&) { make_frame(); nav.push(lcrstring, checksum); }; - button_transmit.on_select = [this,&transmitter_model](Button&){ - make_frame(); - - shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate(); - shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x40000*256)/2280; - shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x40000*256)/2280; - - shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8; - - memset(shared_memory.lcrdata, 0, 256); - memcpy(shared_memory.lcrdata, lcrframe_f, 256); - - shared_memory.afsk_transmit_done = false; - shared_memory.afsk_repeat = 5; //(portapack::persistent_memory::afsk_config() >> 8) & 0xFF; - - EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); - - EventDispatcher::message_map().register_handler(Message::ID::TXDone, - [this,&transmitter_model](Message* const p) { - char str[8]; - const auto message = static_cast(p); - if (message->n > 0) { - text_status.set(" "); - strcpy(str, to_string_dec_int(message->n).c_str()); - strcat(str, "/"); - strcat(str, to_string_dec_int((portapack::persistent_memory::afsk_config() >> 8) & 0xFF).c_str()); - text_status.set(str); - } else { - text_status.set("Done ! "); - transmitter_model.disable(); - } - } - ); - - char str[8]; - strcpy(str, "0/"); - strcat(str, to_string_dec_int(shared_memory.afsk_repeat).c_str()); - text_status.set(str); - - transmitter_model.enable(); + button_transmit.on_select = [this](Button&) { + if (txing == false) start_tx(); }; - /* - button_transmit_scan.on_select() = [this,&transmitter_model](Button&){ - make_frame(); - - shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate(); - shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x40000*256)/2280; - shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x40000*256)/2280; - - shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8; - - memset(shared_memory.lcrdata, 0, 256); - memcpy(shared_memory.lcrdata, lcrframe_f, 256); - - shared_memory.afsk_transmit_done = false; - shared_memory.afsk_repeat = 5; //(portapack::persistent_memory::afsk_config() >> 8) & 0xFF; - - EventDispatcher::message_map().unregister_handler(Message::ID::TXDone); - - EventDispatcher::message_map().register_handler(Message::ID::TXDone, - [this,&transmitter_model](Message* const p) { - char str[8]; - const auto message = static_cast(p); - if (message->n > 0) { - text_status.set(" "); - strcpy(str, to_string_dec_int(message->n).c_str()); - strcat(str, "/"); - strcat(str, to_string_dec_int((portapack::persistent_memory::afsk_config() >> 8) & 0xFF).c_str()); - text_status.set(str); - } else { - text_status.set("Done ! "); - transmitter_model.disable(); - } - } - ); - - char str[8]; - strcpy(str, "0/"); - strcat(str, to_string_dec_int(shared_memory.afsk_repeat).c_str()); - text_status.set(str); - - transmitter_model.enable(); - }; - */ - button_txsetup.on_select = [&nav](Button&){ - nav.push(); + + button_scan.on_select = [this](Button&) { + if (txing == false) { + scanning = true; + scan_progress = 0; + button_scan.set_style(&style_cancel); + button_scan.set_text("ABORT"); + start_tx(); + } else { + abort_scan = true; + } }; - button_exit.on_select = [&nav](Button&){ - nav.pop(); + button_clear.on_select = [this, &nav](Button&) { + memset(litteral, 0, 5 * 8); + 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); + set_dirty(); + start_tx(); }; } diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 11cfb8eb..ed19d11e 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -38,13 +39,16 @@ class LCRView : public View { public: LCRView(NavigationView& nav); ~LCRView(); + std::string title() const override { return "LCR transmit"; }; - void make_frame(); void focus() override; void paint(Painter& painter) override; private: - uint8_t adri = 22; + bool txing = false; + bool scanning = false; + bool abort_scan = false; + double scan_progress; const char RGSB_list[37][5] = { "EAA0", "EAB0", "EAC0", "EAD0", "EbA0", "EbB0", "EbC0", "EbD0", @@ -64,10 +68,20 @@ private: char lcrframe[256]; char lcrframe_f[256]; rf::Frequency f; - - Text text_status { - { 168, 196, 64, 16 }, - "Ready" + int scan_index; + + void make_frame(); + void start_tx(); + + const Style style_val { + .font = font::fixed_8x16, + .background = Color::green(), + .foreground = Color::black(), + }; + const Style style_cancel { + .font = font::fixed_8x16, + .background = Color::red(), + .foreground = Color::black(), }; Text text_recap { @@ -88,72 +102,84 @@ private: "Set RGSB" }; Button button_txsetup { - { 120, 24, 96, 32 }, + { 128, 24, 96, 32 }, "TX setup" }; Checkbox checkbox_am_a { - { 16, 68 }, + { 16, 64 }, 0, "" }; Button button_setam_a { - { 48, 64, 48, 32 }, + { 48, 64, 48, 24 }, "AM 1" }; + Checkbox checkbox_am_b { - { 16, 68+40 }, + { 16, 96 }, 0, "" }; Button button_setam_b { - { 48, 64+40, 48, 32 }, + { 48, 96, 48, 24 }, "AM 2" }; + Checkbox checkbox_am_c { - { 16, 68+40+40 }, + { 16, 128 }, 0, - " " + "" }; Button button_setam_c { - { 48, 64+40+40, 48, 32 }, + { 48, 128, 48, 24 }, "AM 3" }; + Checkbox checkbox_am_d { - { 16, 68+40+40+40 }, + { 16, 160 }, 0, "" }; Button button_setam_d { - { 48, 64+40+40+40, 48, 32 }, + { 48, 160, 48, 24 }, "AM 4" }; + Checkbox checkbox_am_e { - { 16, 68+40+40+40+40 }, + { 16, 192 }, 0, "" }; Button button_setam_e { - { 48, 64+40+40+40+40, 48, 32 }, + { 48, 192, 48, 24 }, "AM 5" }; Button button_lcrdebug { - { 166, 224, 56, 32 }, + { 168, 216, 56, 24 }, "DEBUG" }; + Text text_status { + { 16, 224, 128, 16 }, + "Ready" + }; + ProgressBar progress { + { 16, 224 + 20, 208, 16 } + }; + Button button_transmit { - { 24, 270, 48, 32 }, + { 16, 270, 64, 32 }, "TX" }; - Button button_transmit_scan { - { 76, 270, 72, 32 }, - "SCAN TX" + Button button_scan { + { 88, 270, 64, 32 }, + "SCAN" }; - Button button_exit { - { 176, 270, 48, 32 }, - "Exit" + Button button_clear { + { 160, 270, 64, 32 }, + "CLEAR" }; }; diff --git a/firmware/application/ui_xylos.cpp b/firmware/application/ui_xylos.cpp index 0494b790..21c644d7 100644 --- a/firmware/application/ui_xylos.cpp +++ b/firmware/application/ui_xylos.cpp @@ -113,7 +113,7 @@ XylosRXView::XylosRXView( void XylosView::focus() { - city_code.focus(); + options_ra.focus(); } XylosView::~XylosView() { diff --git a/firmware/application/ui_xylos.hpp b/firmware/application/ui_xylos.hpp index 1999000d..5601d016 100644 --- a/firmware/application/ui_xylos.hpp +++ b/firmware/application/ui_xylos.hpp @@ -148,8 +148,6 @@ public: ~XylosView(); std::string title() const override { return "Xylos transmit"; }; - void start_tx(); - void upd_message(); void focus() override; void paint(Painter& painter) override; @@ -160,6 +158,9 @@ private: const rf::Frequency xylos_freqs[7] = { 31325000, 31387500, 31437500, 31475000, 31687500, 31975000, 88000000 }; char ccirmessage[21]; + void start_tx(); + void upd_message(); + const Style style_val { .font = font::fixed_8x16, .background = Color::green(), diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 0c1ec1bf..a853a72c 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ