diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 587692d8..052bbe25 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -160,11 +160,11 @@ set(CPPSRC ui_alphanum.cpp ui_spectrum.cpp ui_about.cpp - ui_jammer.cpp + # ui_jammer.cpp ui_handwrite.cpp ui_afsksetup.cpp - ui_closecall.cpp - ui_soundboard.cpp + # ui_closecall.cpp + # ui_soundboard.cpp ui_rds.cpp ui_lcr.cpp ui_xylos.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 1ec2c7c2..e16a202a 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -3654,30 +3654,6 @@ ui_channel.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_channel.cpp.s .PHONY : ui_channel.cpp.s -ui_closecall.obj: ui_closecall.cpp.obj -.PHONY : ui_closecall.obj - -# target to build an object file -ui_closecall.cpp.obj: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_closecall.cpp.obj -.PHONY : ui_closecall.cpp.obj - -ui_closecall.i: ui_closecall.cpp.i -.PHONY : ui_closecall.i - -# target to preprocess a source file -ui_closecall.cpp.i: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_closecall.cpp.i -.PHONY : ui_closecall.cpp.i - -ui_closecall.s: ui_closecall.cpp.s -.PHONY : ui_closecall.s - -# target to generate assembly for a file -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_debug.obj: ui_debug.cpp.obj .PHONY : ui_debug.obj @@ -3798,30 +3774,6 @@ ui_handwrite.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_handwrite.cpp.s .PHONY : ui_handwrite.cpp.s -ui_jammer.obj: ui_jammer.cpp.obj -.PHONY : ui_jammer.obj - -# target to build an object file -ui_jammer.cpp.obj: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_jammer.cpp.obj -.PHONY : ui_jammer.cpp.obj - -ui_jammer.i: ui_jammer.cpp.i -.PHONY : ui_jammer.i - -# target to preprocess a source file -ui_jammer.cpp.i: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_jammer.cpp.i -.PHONY : ui_jammer.cpp.i - -ui_jammer.s: ui_jammer.cpp.s -.PHONY : ui_jammer.s - -# target to generate assembly for a file -ui_jammer.cpp.s: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_jammer.cpp.s -.PHONY : ui_jammer.cpp.s - ui_lcr.obj: ui_lcr.cpp.obj .PHONY : ui_lcr.obj @@ -4062,30 +4014,6 @@ ui_setup.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_setup.cpp.s .PHONY : ui_setup.cpp.s -ui_soundboard.obj: ui_soundboard.cpp.obj -.PHONY : ui_soundboard.obj - -# target to build an object file -ui_soundboard.cpp.obj: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_soundboard.cpp.obj -.PHONY : ui_soundboard.cpp.obj - -ui_soundboard.i: ui_soundboard.cpp.i -.PHONY : ui_soundboard.i - -# target to preprocess a source file -ui_soundboard.cpp.i: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_soundboard.cpp.i -.PHONY : ui_soundboard.cpp.i - -ui_soundboard.s: ui_soundboard.cpp.s -.PHONY : ui_soundboard.s - -# target to generate assembly for a file -ui_soundboard.cpp.s: - cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_soundboard.cpp.s -.PHONY : ui_soundboard.cpp.s - ui_spectrum.obj: ui_spectrum.cpp.obj .PHONY : ui_spectrum.obj @@ -4609,9 +4537,6 @@ help: @echo "... ui_channel.obj" @echo "... ui_channel.i" @echo "... ui_channel.s" - @echo "... ui_closecall.obj" - @echo "... ui_closecall.i" - @echo "... ui_closecall.s" @echo "... ui_debug.obj" @echo "... ui_debug.i" @echo "... ui_debug.s" @@ -4627,9 +4552,6 @@ help: @echo "... ui_handwrite.obj" @echo "... ui_handwrite.i" @echo "... ui_handwrite.s" - @echo "... ui_jammer.obj" - @echo "... ui_jammer.i" - @echo "... ui_jammer.s" @echo "... ui_lcr.obj" @echo "... ui_lcr.i" @echo "... ui_lcr.s" @@ -4660,9 +4582,6 @@ help: @echo "... ui_setup.obj" @echo "... ui_setup.i" @echo "... ui_setup.s" - @echo "... ui_soundboard.obj" - @echo "... ui_soundboard.i" - @echo "... ui_soundboard.s" @echo "... ui_spectrum.obj" @echo "... ui_spectrum.i" @echo "... ui_spectrum.s" diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index 08d493cb..c030bde0 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -78,18 +78,17 @@ void WFMConfig::apply() const { audio::set_rate(audio::Rate::Hz_48000); } -void set_xylos_data(const char ccir_message[]) { - const XylosConfigureMessage message { - ccir_message +void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count) { + const CCIRConfigureMessage message { + samples_per_tone, + tone_count }; send_message(&message); } -void set_afsk_data(const char message_data[], const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, - const uint32_t afsk_phase_inc_space, const uint8_t afsk_repeat, const uint32_t afsk_bw, - const bool afsk_alt_format) { +void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space, + const uint8_t afsk_repeat, const uint32_t afsk_bw, const bool afsk_alt_format) { const AFSKConfigureMessage message { - message_data, afsk_samples_per_bit, afsk_phase_inc_mark, afsk_phase_inc_space, @@ -97,7 +96,7 @@ void set_afsk_data(const char message_data[], const uint32_t afsk_samples_per_bi afsk_bw, afsk_alt_format }; - send_message(&message); + send_message(&message); } void set_pwmrssi(int32_t avg, bool enabled) { @@ -109,14 +108,15 @@ void set_pwmrssi(int32_t avg, bool enabled) { send_message(&message); } -void set_ook_data(const char ook_bitstream[], uint32_t stream_length, uint32_t samples_per_bit, uint8_t repeat) { +void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat, + const uint32_t pause_symbols) { const OOKConfigureMessage message { - ook_bitstream, stream_length, samples_per_bit, - repeat + repeat, + pause_symbols }; - send_message(&message); + send_message(&message); } static bool baseband_image_running = false; diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 80a38b4a..5e91fceb 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -52,12 +52,12 @@ struct WFMConfig { void apply() const; }; -void set_xylos_data(const char ccir_message[]); +void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count); void set_pwmrssi(int32_t avg, bool enabled); -void set_afsk_data(const char message_data[], const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, - const uint32_t afsk_phase_inc_space, const uint8_t afsk_repeat, const uint32_t afsk_bw, - const bool afsk_alt_format); -void set_ook_data(const char ook_bitstream[], uint32_t stream_length, uint32_t samples_per_bit, uint8_t repeat); +void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space, + const uint8_t afsk_repeat, const uint32_t afsk_bw, const bool afsk_alt_format); +void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat, + const uint32_t pause_symbols); void run_image(const portapack::spi_flash::image_tag_t image_tag); void shutdown(); diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 1b130989..16afe649 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -37,20 +37,20 @@ //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: Bodet :) //TODO: Whistler //TODO: LCR full message former (see norm) -//TODO: AFSK NRZI, parity and format +//TODO: AFSK NRZI //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: 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 //BUG: Description doesn't show up first time going to system>module info (UI drawn on top) diff --git a/firmware/application/ui_encoders.cpp b/firmware/application/ui_encoders.cpp index f3e8c10e..2ad0e27a 100644 --- a/firmware/application/ui_encoders.cpp +++ b/firmware/application/ui_encoders.cpp @@ -36,7 +36,7 @@ using namespace portapack; namespace ui { void EncodersView::focus() { - bitfields[0].focus(); + bitfield.focus(); } EncodersView::~EncodersView() { @@ -45,48 +45,56 @@ EncodersView::~EncodersView() { } void EncodersView::generate_frame() { - uint8_t i; + size_t i; - debug_text = encoder_def->sync; + debug_text.clear(); i = 0; for (auto c : encoder_def->word_def) { - if (c <= 'J') - debug_text += encoder_def->bit_format.at(bitfields[i++].value()); + if (c < 'S') + debug_text += encoder_def->bit_format.at(bitfield.value(i)); + else if (c == 'S') + debug_text += encoder_def->sync; + i++; } - if (visible()) parent()->set_dirty(); + //if (visible()) parent()->set_dirty(); // Might be called before on_show ? } -void EncodersView::paint(Painter& painter) { +void EncodersView::draw_waveform() { float x = 0, x_inc; Coord y, prev_y = 1; - uint8_t prelude_length = encoder_def->sync.length(); + uint8_t prelude_length = 0; //encoder_def->sync.length(); - painter.fill_rectangle( { 0, 160, 240, 24 }, Color::black() ); + // Clear + painter_->fill_rectangle( { 0, 160, 240, 24 }, Color::black() ); x_inc = 230.0 / (debug_text.length() - prelude_length); - for (auto c : debug_text.substr(prelude_length)) { + for (auto c : debug_text) { //.substr(prelude_length) if (c == '0') y = 23; else y = 0; - if (prev_y != y) painter.draw_rectangle( { (Coord)x, 160, 1, 24 }, Color::yellow() ); - painter.draw_rectangle( { (Coord)x, 160 + y, ceil(x_inc), 1 }, Color::yellow() ); + if (prev_y != y) painter_->draw_rectangle( { (Coord)x, 160, 1, 24 }, Color::yellow() ); + painter_->draw_rectangle( { (Coord)x, 160 + y, ceil(x_inc), 1 }, Color::yellow() ); prev_y = y; x += x_inc; } } +void EncodersView::paint(Painter& painter) { + painter_ = &painter; +} + void EncodersView::update_progress() { char str[16]; - text_status.set(" "); + // text_status.set(" "); - //if (tx_mode == SINGLE) { + if (tx_mode == SINGLE) { strcpy(str, to_string_dec_uint(repeat_index).c_str()); strcat(str, "/"); strcat(str, to_string_dec_uint(encoder_def->repeat_min).c_str()); @@ -101,11 +109,11 @@ void EncodersView::update_progress() { strcat(str, "/"); strcat(str, to_string_dec_uint(scan_count).c_str()); text_status.set(str); - progress.set_value(scan_progress); + progress.set_value(scan_progress);*/ } else { text_status.set("Ready"); progress.set_value(0); - }*/ + } } void EncodersView::on_txdone(int n) { @@ -186,9 +194,9 @@ void EncodersView::start_tx(const bool scan) { n++; } - ook_bitstream_length = n - 1; + ook_bitstream_length = n; // - 1; - transmitter_model.set_tuning_frequency(433920000); // TODO: Change ! + transmitter_model.set_tuning_frequency(433920000); // TODO: Make modifiable ! transmitter_model.set_baseband_configuration({ .mode = 0, .sampling_rate = 2280000U, @@ -200,44 +208,34 @@ void EncodersView::start_tx(const bool scan) { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); + memcpy(shared_memory.tx_data, ook_bitstream, 64); + baseband::set_ook_data( - ook_bitstream, ook_bitstream_length, // 2280000/2 = 1140000Hz = 0,877192982us // numberfield_clk.value() / encoder_def->clk_per_symbol // 455000 / 12 = 37917Hz = 26,37339452us 1140000 / ((numberfield_clk.value() * 1000) / encoder_def->clk_per_symbol), - encoder_def->repeat_min + encoder_def->repeat_min, + encoder_def->pause_symbols ); } -void EncodersView::on_bitfield() { - generate_frame(); -} - void EncodersView::on_type_change(size_t index) { std::string word_format; - size_t data_length; - size_t address_length; + //size_t data_length; + //size_t address_length; enc_type = index; - + encoder_def = &encoder_defs[enc_type]; - + numberfield_clk.set_value(encoder_def->default_frequency / 1000); - size_t n = 0; - for (auto& bitfield : bitfields) { - if (n < encoder_def->word_length) { - bitfield.hidden(false); - bitfield.set_range(0, encoder_def->bit_states - 1); - } else { - bitfield.hidden(true); - } - n++; - } + bitfield.set_length(encoder_def->word_length); + bitfield.set_range(0, encoder_def->address_bit_states - 1); - word_format = encoder_def->word_format; + /*word_format = encoder_def->word_format; size_t address_start = word_format.find_first_of("A"); size_t data_start = word_format.find_first_of("D"); size_t format_length = word_format.length(); @@ -274,7 +272,7 @@ void EncodersView::on_type_change(size_t index) { text_format_d.set(std::string(data_length, 'D')); } else { text_format_d.hidden(true); - } + }*/ generate_frame(); } @@ -285,6 +283,13 @@ void EncodersView::on_show() { } EncodersView::EncodersView(NavigationView& nav) { + using name_t = std::string; + using value_t = int32_t; + using option_t = std::pair; + using options_t = std::vector; + options_t enc_options; + size_t i; + baseband::run_image(portapack::spi_flash::image_tag_ook); encoder_def = &encoder_defs[0]; @@ -302,14 +307,27 @@ EncodersView::EncodersView(NavigationView& nav) { &numberfield_wordduration, &text_us2, &text_bitfield, - &text_format_a, - &text_format_d, + &bitfield, + //&text_format_a, // DEBUG + //&text_format_d, // DEBUG &text_waveform, &text_status, &progress, &button_transmit } }); + for (i = 0; i < ENC_TYPES_COUNT; i++) + enc_options.emplace_back(std::make_pair(encoder_defs[i].name, i)); + + options_enctype.set_options(enc_options); + options_enctype.set_selected_index(0); + + bitfield.on_change = [this]() { + this->generate_frame(); + }; + + button_transmit.set_style(&style_val); + options_enctype.on_change = [this](size_t index, int32_t value) { (void)value; this->on_type_change(index); @@ -339,30 +357,7 @@ EncodersView::EncodersView(NavigationView& nav) { } }; - const auto bitfield_fn = [this](int32_t value) { - (void)value; - this->on_bitfield(); - }; - - size_t n = 0; - for (auto& bitfield : bitfields) { - bitfield.on_change = bitfield_fn; - bitfield.id = n; - bitfield.set_value(0); - bitfield.set_parent_rect({ - static_cast(16 + 8 * n), - static_cast(80), - 8, 16 - }); - add_child(&bitfield); - n++; - } - - //options_enctype.set_selected_index(0); - - button_transmit.set_style(&style_val); - - button_transmit.on_select = [this](Button&) { + button_transmit.on_select = [this, &nav](Button&) { if (tx_mode == IDLE) start_tx(false); }; } diff --git a/firmware/application/ui_encoders.hpp b/firmware/application/ui_encoders.hpp index 1f963a4e..a417a36c 100644 --- a/firmware/application/ui_encoders.hpp +++ b/firmware/application/ui_encoders.hpp @@ -28,6 +28,8 @@ namespace ui { +#define ENC_TYPES_COUNT 13 + class EncodersView : public View { public: EncodersView(NavigationView& nav); @@ -41,97 +43,179 @@ public: private: struct encoder_def_t { - uint8_t bit_states; - uint16_t clk_per_bit; - uint16_t clk_per_symbol; + std::string name; + uint8_t address_bit_states; // Often 0, 1, [f, [4]] + uint8_t data_bit_states; // Often 0, 1 + uint16_t clk_per_bit; // Oscillator periods per bit + uint16_t clk_per_symbol; // Oscillator periods per bit fragment std::vector bit_format; - uint8_t word_length; + uint8_t word_length; // Total # of bits std::string word_def; std::string word_format; - std::string sync; - uint32_t default_frequency; + std::string sync; // Like bit_format + uint32_t default_frequency; // Default encoder clk frequency uint8_t repeat_min; + uint32_t pause_symbols; }; // S = Sync - // 0~9 A~J = Address/data bits - const encoder_def_t encoder_defs[11] = { - // PT2260: Data bits can only be 0 or 1 ! - { 3, 1024, 128, + // 0~9 A~R = Address/data bits + const encoder_def_t encoder_defs[ENC_TYPES_COUNT] = { + // PT2260 + { + "xx2260", + 3, 2, + 1024, 128, { "10001000", "11101110", "10001110" }, 12, "0123456789ABS", "AAAAAAAAAADD", "10000000000000000000000000000000", - 200000, 1 }, + 200000, 1, + 10 // ? + }, // PT2262 - { 3, 32, 4, + { + "xx2262", + 3, 2, + 32, 4, { "10001000", "11101110", "10001110" }, - 12, "0123456789ABS", "AAAAAAAAADDD", + 12, "0123456789ABS", "AAAAAADDDDDD", "10000000000000000000000000000000", - 30000, 4 }, + 30000, 4, + 10 // ? + }, + + // 16bit? + { + "16bit?", + 2, 2, + 32, 8, + { "1110", "1000" }, // Opposite ? + 16, "0123456789ABCDEFS", "AAAAAAAAAAAAAAAA", + "10000000000000000000000000000000", + 114000, 50, + 10 // ? + }, + + // RT1527 + { + "xx1527", + 2, 2, + 128, 32, + { "1000", "1110" }, + 12, "0123456789ABS", "AAAAAAAADD", + "10000000000000000000000000000000", + 100000, 4, + 10 // ? + }, // HK526E - { 2, 24, 8, + { + "xx526 ", + 2, 2, + 24, 8, { "110", "100" }, - 12, "0123456789AB", "AAAAAAAAAAAA", + 12, "0123456789AB", "AAAAAAAADDDD", "", - 20000, 4 }, + 20000, 4, + 10 // ? + }, // HT12E - { 2, 3, 1, + { + "xx12E ", + 2, 2, + 3, 1, { "011", "001" }, 12, "S0123456789AB", "AAAAAAAADDDD", "0000000000000000000000000000000000001", - 3000, 4 }, + 3000, 4, + 10 // ? + }, // VD5026 13 bits ? - { 4, 128, 8, + { + "xx5026", + 4, 4, + 128, 8, { "1000000010000000", "1111111011111110", "1111111010000000", "1000000011111110" }, 12, "S0123456789AB", "AAAAAAAADDDD", "000000000000000000000000000000000000000000000001", // ? - 100000, 4 }, + 100000, 4, + 10 // ? + }, // UM3750 - { 2, 96, 32, + { + "UM3750", + 2, 2, + 96, 32, { "011", "001" }, 12, "S0123456789AB", "AAAAAAAAAAAA", "1", - 100000, 4 }, + 100000, 4, + 10 // ? + }, // UM3758 - { 3, 96, 16, + { + "UM3758", + 3, 2, + 96, 16, { "011011", "001001", "011001" }, 18, "S0123456789ABCDEFGH", "AAAAAAAAAADDDDDDDD", "1", - 160000, 4 }, + 160000, 4, + 10 // ? + }, // BA5104 - { 2, 3072, 768, + { + "BA5104", + 2, 2, + 3072, 768, { "1000", "1110" }, 9, "S012345678", "DDAAAAAAA", "", - 455000, 4 }, + 455000, 4, + 10 // ? + }, // MC145026 - { 3, 16, 1, + { + "145026", + 3, 2, + 16, 1, { "0111111101111111", "0100000001000000", "0111111101000000" }, 9, "S012345678", "AAAAADDDD", "000000000000000000", - 455000, 2 }, + 455000, 2, + 10 // ? + }, // HT6xxx - { 3, 198, 33, + { + "HT6xxx", + 3, 2, + 198, 33, { "011011", "001001", "001011" }, 18, "S0123456789ABCDEFGH", "AAAAAAAAAAAADDDDDD", "0000000000000000000000000000000000001011001011001", - 100000, 3 }, + 100000, 3, + 10 // ? + }, // TC9148 - { 2, 48, 12, + { + "TC9148", + 2, 2, + 48, 12, { "1000", "1110", }, 12, "0123456789AB", "DDDDDDDDDDDD", "", - 455000, 3 } + 455000, 3, + 10 // ? + } }; enum tx_modes { @@ -140,6 +224,7 @@ private: SCAN }; + Painter * painter_; uint8_t enc_type = 0; const encoder_def_t * encoder_def; tx_modes tx_mode = IDLE; @@ -151,6 +236,7 @@ private: //rf::Frequency f; uint8_t repeat_index; + void draw_waveform(); void on_bitfield(); void on_type_change(size_t index); void generate_frame(); @@ -158,17 +244,6 @@ private: void start_tx(const bool scan); void on_txdone(int n); - radio::Configuration ook_radio_config = { - 0, - 2280000, - 2500000, // ? - rf::Direction::Transmit, - true, - 0, - 0, - 1, - }; - const Style style_val { .font = font::fixed_8x16, .background = Color::green(), @@ -191,7 +266,11 @@ private: .foreground = Color::blue(), }; - std::array bitfields; + SymField bitfield { + { 16 + 8, 80 }, + 12, + { 0, 1 } + }; Text text_enctype { { 2 * 8, 3 * 8, 8 * 8, 16 }, @@ -199,19 +278,8 @@ private: }; OptionsField options_enctype { { 2 * 8, 5 * 8 }, - 8, + 6, { - { "PT2260 ", 0 }, - { "PT2262 ", 1 }, - { "HK526E ", 2 }, - { "HT12E ", 3 }, - { "VD5026 ", 4 }, - { "UM3750 ", 5 }, - { "UM3758 ", 6 }, - { "BA5104 ", 7 }, - { "MC145026", 8 }, - { "HT6xxx ", 9 }, - { "TC9148 ", 10 } } }; @@ -267,8 +335,8 @@ private: { 2 * 8, 8 * 8, 5 * 8, 16 }, "Word:" }; - Text text_format_a; - Text text_format_d; + //Text text_format_a; // DEBUG + //Text text_format_d; // DEBUG Text text_waveform { { 1 * 8, 16 * 8, 9 * 8, 16 }, diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index 8dc4e34e..f79d5abf 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -251,7 +251,7 @@ void LCRView::start_tx(const bool scan) { transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency()); transmitter_model.set_baseband_configuration({ .mode = 0, - .sampling_rate = 2280000U, + .sampling_rate = 1536000, .decimation_factor = 1, }); transmitter_model.set_rf_amp(true); @@ -259,12 +259,13 @@ void LCRView::start_tx(const bool scan) { transmitter_model.set_vga(40); transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); + + memcpy(shared_memory.tx_data, lcr_message_data, 300); baseband::set_afsk_data( - lcr_message_data, - 228000 / portapack::persistent_memory::afsk_bitrate(), - portapack::persistent_memory::afsk_mark_freq() * (0x40000 * 256) / (228000 / 25), - portapack::persistent_memory::afsk_space_freq() * (0x40000 * 256) / (228000 / 25), + (153600 * 5) / portapack::persistent_memory::afsk_bitrate(), + portapack::persistent_memory::afsk_mark_freq() * 437 * 5, //(0x40000 * 256) / (153600 / 25), + portapack::persistent_memory::afsk_space_freq() * 437 * 5, //(0x40000 * 256) / (153600 / 25), afsk_repeats, portapack::persistent_memory::afsk_bw() * 115, // See proc_fsk_lcr.cpp afsk_format diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 57e7203d..aba9e24b 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -34,8 +34,8 @@ #include "ui_setup.hpp" #include "ui_debug.hpp" -#include "ui_soundboard.hpp" // DEBUG -#include "ui_closecall.hpp" // DEBUG +//#include "ui_soundboard.hpp" // DEBUG +//#include "ui_closecall.hpp" // DEBUG #include "ui_freqman.hpp" // DEBUG #include "ui_encoders.hpp" @@ -46,7 +46,7 @@ #include "ui_lcr.hpp" #include "analog_audio_app.hpp" #include "ui_audiotx.hpp" // DEBUG -#include "ui_jammer.hpp" // DEBUG +//#include "ui_jammer.hpp" // DEBUG #include "analog_audio_app.hpp" #include "ais_app.hpp" @@ -238,13 +238,13 @@ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { /* SystemMenuView ********************************************************/ SystemMenuView::SystemMenuView(NavigationView& nav) { - add_items<14>({ { + add_items<12>({ { { "Play dead", ui::Color::red(), [&nav](){ nav.push(false); } }, { "Receiver RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, { "Capture RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, - { "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, + //{ "Close Call RX", ui::Color::cyan(), [&nav](){ nav.push(); } }, { "Numbers station TX", ui::Color::purple(), [&nav](){ nav.push(); } }, //nav.push(); - { "Pokemon GO Away TX", ui::Color::blue(), [&nav](){ 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(); } }, diff --git a/firmware/application/ui_xylos.cpp b/firmware/application/ui_xylos.cpp index 0a4b33b2..d5e33cfd 100644 --- a/firmware/application/ui_xylos.cpp +++ b/firmware/application/ui_xylos.cpp @@ -173,7 +173,8 @@ void XylosView::start_tx() { transmitter_model.set_baseband_bandwidth(1750000); transmitter_model.enable(); - baseband::set_xylos_data(ccir_message); + memcpy(shared_memory.tx_data, ccir_message, 21); + baseband::set_ccir_data(CCIR_TONELENGTH, 20); } // ASCII to frequency LUT index diff --git a/firmware/application/ui_xylos.hpp b/firmware/application/ui_xylos.hpp index 287578d5..9b97a0e5 100644 --- a/firmware/application/ui_xylos.hpp +++ b/firmware/application/ui_xylos.hpp @@ -35,6 +35,8 @@ //#include "receiver_model.hpp" #include "portapack.hpp" +#define CCIR_TONELENGTH (15360*2)-1 // 1536000/10/10 + namespace ui { /* diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 1586c7ca..4f273c26 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -326,19 +326,26 @@ set(MODE_CPPSRC ) DeclareTargets(PSPE wideband_spectrum) -### Jammer +### OOK set(MODE_CPPSRC - proc_jammer.cpp + proc_ook.cpp ) -DeclareTargets(PJAM jammer) +DeclareTargets(POOK ook) + +### Jammer + +#set(MODE_CPPSRC +# proc_jammer.cpp +#) +#DeclareTargets(PJAM jammer) ### Audio transmit -set(MODE_CPPSRC - proc_audiotx.cpp -) -DeclareTargets(PATX audio_tx) +#set(MODE_CPPSRC +# proc_audiotx.cpp +#) +#DeclareTargets(PATX audio_tx) ### AFSK @@ -349,17 +356,17 @@ DeclareTargets(PAFS afsk) ### Epar -set(MODE_CPPSRC - proc_epar.cpp -) -DeclareTargets(PEPR epar) +#set(MODE_CPPSRC +# proc_epar.cpp +#) +#DeclareTargets(PEPR epar) ### Play audio -set(MODE_CPPSRC - proc_playaudio.cpp -) -DeclareTargets(PPAU play_audio) +#set(MODE_CPPSRC +# proc_playaudio.cpp +#) +#DeclareTargets(PPAU play_audio) ### Xylos @@ -375,13 +382,6 @@ set(MODE_CPPSRC ) DeclareTargets(PRDS rds) -### OOK - -set(MODE_CPPSRC - proc_ook.cpp -) -DeclareTargets(POOK ook) - ### HackRF "factory" firmware add_custom_command( diff --git a/firmware/baseband/proc_afsk.cpp b/firmware/baseband/proc_afsk.cpp index 624072f1..b4754596 100644 --- a/firmware/baseband/proc_afsk.cpp +++ b/firmware/baseband/proc_afsk.cpp @@ -34,14 +34,15 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { if (!configured) return; for (size_t i = 0; i= (5 - 1)) { + s = 0; + if (sample_count >= afsk_samples_per_bit) { if (configured) { - cur_byte = message_data[byte_pos]; - ext_byte = message_data[byte_pos + 1]; + cur_byte = shared_memory.tx_data[byte_pos]; + ext_byte = shared_memory.tx_data[byte_pos + 1]; if (!(cur_byte | ext_byte)) { // End of data @@ -49,8 +50,8 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { // Repeat bit_pos = 0; byte_pos = 0; - cur_byte = message_data[0]; - ext_byte = message_data[1]; + cur_byte = shared_memory.tx_data[0]; + ext_byte = shared_memory.tx_data[1]; message.n = repeat_counter + 1; shared_memory.application_queue.push(message); repeat_counter++; @@ -98,6 +99,8 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { } else { s--; } + + //tone_phase += 432759; // 1981Hz tone_sample = (sine_table_i8[(tone_phase & 0x03FC0000) >> 18]); @@ -120,13 +123,12 @@ 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, 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; - afsk_repeat = message.afsk_repeat - 1; - afsk_bw = message.afsk_bw; - afsk_format = message.afsk_format; + afsk_samples_per_bit = message.samples_per_bit; + afsk_phase_inc_mark = message.phase_inc_mark; + afsk_phase_inc_space = message.phase_inc_space; + afsk_repeat = message.repeat - 1; + afsk_bw = message.bw; + afsk_format = message.format; s = 0; sample_count = afsk_samples_per_bit; diff --git a/firmware/baseband/proc_afsk.hpp b/firmware/baseband/proc_afsk.hpp index 19d8bb40..74d056a7 100644 --- a/firmware/baseband/proc_afsk.hpp +++ b/firmware/baseband/proc_afsk.hpp @@ -35,7 +35,7 @@ public: private: bool configured = false; - BasebandThread baseband_thread { 2280000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; + BasebandThread baseband_thread { 1536000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; uint32_t afsk_samples_per_bit; uint32_t afsk_phase_inc_mark; @@ -43,7 +43,6 @@ private: uint8_t afsk_repeat; uint32_t afsk_bw; uint8_t afsk_format; - char message_data[512]; uint8_t repeat_counter = 0; int8_t re, im; diff --git a/firmware/baseband/proc_ook.cpp b/firmware/baseband/proc_ook.cpp index 73a1ae56..eaca0da4 100644 --- a/firmware/baseband/proc_ook.cpp +++ b/firmware/baseband/proc_ook.cpp @@ -35,31 +35,38 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) { for (size_t i = 0; i= samples_per_bit) { if (configured) { - cur_bit = (bitstream[bit_pos >> 3] << (bit_pos & 7)) & 0x80; - - bit_pos++; - - if (bit_pos >= stream_size) { + if (bit_pos >= length) { // End of data - if (repeat_counter < repeat) { - // Repeat - bit_pos = 0; - cur_bit = bitstream[0] & 0x80; - message.n = repeat_counter + 1; - shared_memory.application_queue.push(message); - repeat_counter++; - } else { - // Stop + if (pause_counter == 0) { + pause_counter = pause; cur_bit = 0; - message.n = 0; - shared_memory.application_queue.push(message); - configured = false; + } else if (pause_counter == 1) { + if (repeat_counter < repeat) { + // Repeat + bit_pos = 0; + cur_bit = shared_memory.tx_data[0] & 0x80; + message.n = repeat_counter + 1; + shared_memory.application_queue.push(message); + repeat_counter++; + } else { + // Stop + cur_bit = 0; + message.n = 0; + shared_memory.application_queue.push(message); + configured = false; + } + pause_counter = 0; + } else { + pause_counter--; } + } else { + cur_bit = (shared_memory.tx_data[bit_pos >> 3] << (bit_pos & 7)) & 0x80; + bit_pos++; } } @@ -71,13 +78,17 @@ void OOKProcessor::execute(const buffer_c8_t& buffer) { s--; } - if (cur_bit) phase += 100; // ? - - sphase = phase + (64 << 18); + if (cur_bit) { + phase = (phase + 200); // What ? + sphase = phase + (64 << 18); - re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]); - im = (sine_table_i8[(phase & 0x03FC0000) >> 18]); - + re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]); + im = (sine_table_i8[(phase & 0x03FC0000) >> 18]); + } else { + re = 0; + im = 0; + } + buffer.p[i] = {(int8_t)re, (int8_t)im}; } } @@ -86,12 +97,12 @@ void OOKProcessor::on_message(const Message* const p) { const auto message = *reinterpret_cast(p); if (message.id == Message::ID::OOKConfigure) { - //memcpy(bitstream, message.ook_bitstream, 64); - samples_per_bit = message.samples_per_bit; - stream_size = message.stream_length; repeat = message.repeat - 1; + length = message.stream_length - 1; + pause = message.pause_symbols + 1; + pause_counter = 0; s = 0; sample_count = samples_per_bit; repeat_counter = 0; diff --git a/firmware/baseband/proc_ook.hpp b/firmware/baseband/proc_ook.hpp index 400ec049..65218873 100644 --- a/firmware/baseband/proc_ook.hpp +++ b/firmware/baseband/proc_ook.hpp @@ -39,17 +39,17 @@ private: uint32_t samples_per_bit; uint8_t repeat; - char bitstream[64]; + uint32_t length; + uint32_t pause; + uint32_t pause_counter = 0; uint8_t repeat_counter = 0; int8_t re, im; uint8_t s = 0; - uint16_t bit_pos = 0; uint8_t cur_bit = 0; uint32_t sample_count; - uint32_t stream_size; - uint32_t phase, sphase; + uint32_t tone_phase, phase, sphase; int32_t tone_sample, sig, frq; TXDoneMessage message; diff --git a/firmware/baseband/proc_xylos.cpp b/firmware/baseband/proc_xylos.cpp index 0b64c186..c77c3285 100644 --- a/firmware/baseband/proc_xylos.cpp +++ b/firmware/baseband/proc_xylos.cpp @@ -43,13 +43,13 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { // Just occupy channel with carrier if (sample_count >= CCIR_SILENCE) { silence = false; - sample_count = CCIR_TONELENGTH; + sample_count = samples_per_tone; } else { sample_count++; } } else { - if (sample_count >= CCIR_TONELENGTH) { - digit = xylosdata[byte_pos++]; + if (sample_count >= samples_per_tone) { + digit = shared_memory.tx_data[byte_pos++]; if ((digit == 0xFF) || (byte_pos >= 21)) { configured = false; message.n = 25; // End of message code @@ -103,12 +103,12 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) { } void XylosProcessor::on_message(const Message* const p) { - const auto message = *reinterpret_cast(p); - if (message.id == Message::ID::XylosConfigure) { - memcpy(xylosdata, message.ccir_message, 21); + const auto message = *reinterpret_cast(p); + if (message.id == Message::ID::CCIRConfigure) { byte_pos = 0; digit = 0; - sample_count = CCIR_TONELENGTH; + samples_per_tone = message.samples_per_tone; + sample_count = samples_per_tone; as = 0; silence = true; configured = true; diff --git a/firmware/baseband/proc_xylos.hpp b/firmware/baseband/proc_xylos.hpp index 124ce985..f6c226fc 100644 --- a/firmware/baseband/proc_xylos.hpp +++ b/firmware/baseband/proc_xylos.hpp @@ -28,7 +28,6 @@ //#include "audio_output.hpp" -#define CCIR_TONELENGTH (15360*2)-1 // 1536000/10/10 #define CCIR_PHASEINC (436.91/2) // (65536*1024)/1536000*10 #define CCIR_SILENCE (122880)-1 // 400ms @@ -62,12 +61,12 @@ private: (uint32_t)(1055*CCIR_PHASEINC) }; - char xylosdata[21]; + uint32_t samples_per_tone; int8_t re, im; uint8_t s, as = 0, ai; uint8_t byte_pos = 0; uint8_t digit = 0; - uint32_t sample_count = CCIR_TONELENGTH; + uint32_t sample_count = 0; uint32_t tone_phase, phase, sphase; int32_t tone_sample, frq; bool silence = true; diff --git a/firmware/bootstrap/bootstrap.bin b/firmware/bootstrap/bootstrap.bin index c234f8ae..78405864 100755 Binary files a/firmware/bootstrap/bootstrap.bin and b/firmware/bootstrap/bootstrap.bin differ diff --git a/firmware/bootstrap/bootstrap.c b/firmware/bootstrap/bootstrap.c index 862b861f..00870638 100644 --- a/firmware/bootstrap/bootstrap.c +++ b/firmware/bootstrap/bootstrap.c @@ -92,16 +92,12 @@ int main(void) { LPC_GPIO->DIR[2] = (1 << 8) | (1 << 2) | (1 << 1); /* Indicate M4 is working */ - LPC_GPIO->SET[2] = (1 << 1); + LPC_GPIO->SET[2] = (1 << 2); #endif configure_spifi(); - /* NOTE: MEMMAP registers are ORed with the shadow address to create the - * actual address. - */ - LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x40000; + LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x80000; - /* Change M0APP_RST to 0 */ LPC_RGU->RESET_CTRL[1] = 0; while(1) { diff --git a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld index 24951182..ae9bfec3 100755 --- a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld +++ b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld @@ -23,7 +23,7 @@ __process_stack_size__ = 0x1000; /* main() stack */ MEMORY { - flash : org = 0x00000000, len = 256k /* SPIFI flash @ 0x140????? */ + flash : org = 0x00000000, len = 256k /* SPIFI flash @ 0x140????? */ ram : org = 0x20000000, len = 64k /* AHB SRAM @ 0x20000000 */ } diff --git a/firmware/common/lcd_ili9341.cpp b/firmware/common/lcd_ili9341.cpp index 8826d717..612e2780 100644 --- a/firmware/common/lcd_ili9341.cpp +++ b/firmware/common/lcd_ili9341.cpp @@ -291,7 +291,7 @@ void ILI9341::render_box(const ui::Point p, const ui::Size s, const ui::Color* l // RLE_4 BMP loader (delta not implemented) void ILI9341::drawBMP(const ui::Point p, const uint8_t * bitmap, const bool transparency) { - const bmp_t * bmp_header = (const bmp_t *)bitmap; + const bmp_header_t * bmp_header = (const bmp_header_t *)bitmap; uint32_t data_idx; uint8_t by, c, count, transp_idx = 0; ui::Color line_buffer[240]; @@ -303,13 +303,14 @@ void ILI9341::drawBMP(const ui::Point p, const uint8_t * bitmap, const bool tran (bmp_header->compression != 2)) return; data_idx = bmp_header->image_data; + const bmp_palette_t * bmp_palette = (const bmp_palette_t *)&bitmap[bmp_header->BIH_size + 14]; // Convert palette and find pure magenta index (alpha color key) for (c = 0; c < 16; c++) { - palette[c] = ui::Color(bmp_header->palette[c].R, bmp_header->palette[c].G, bmp_header->palette[c].B); - if ((bmp_header->palette[c].R == 0xFF) && - (bmp_header->palette[c].G == 0x00) && - (bmp_header->palette[c].B == 0xFF)) transp_idx = c; + palette[c] = ui::Color(bmp_palette->color[c].R, bmp_palette->color[c].G, bmp_palette->color[c].B); + if ((bmp_palette->color[c].R == 0xFF) && + (bmp_palette->color[c].G == 0x00) && + (bmp_palette->color[c].B == 0xFF)) transp_idx = c; } if (!transparency) { diff --git a/firmware/common/lcd_ili9341.hpp b/firmware/common/lcd_ili9341.hpp index 534d6da2..06f0dac3 100644 --- a/firmware/common/lcd_ili9341.hpp +++ b/firmware/common/lcd_ili9341.hpp @@ -111,7 +111,7 @@ private: }; #pragma pack(push, 1) - struct bmp_t { + struct bmp_header_t { uint16_t signature; uint32_t size; uint16_t reserved_1; @@ -128,15 +128,20 @@ private: uint32_t v_res; uint32_t colors_count; uint32_t icolors_count; - struct palette { + }; + #pragma pack(pop) + + #pragma pack(push, 1) + struct bmp_palette_t { + struct color_t { uint8_t B; uint8_t G; uint8_t R; uint8_t A; - } palette[16]; + } color[16]; }; #pragma pack(pop) - + scroll_t scroll_state; void draw_pixels(const ui::Rect r, const ui::Color* const colors, const size_t count); diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index fd3bc1ac..a0c1cab4 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -67,7 +67,7 @@ public: TXDone = 20, Retune = 21, - XylosConfigure = 22, + CCIRConfigure = 22, AFSKConfigure = 23, PWMRSSIConfigure = 24, OOKConfigure = 25, @@ -473,7 +473,7 @@ public: class TXDoneMessage : public Message { public: - TXDoneMessage( + constexpr TXDoneMessage( ) : Message { ID::TXDone } { } @@ -485,7 +485,7 @@ public: class PWMRSSIConfigureMessage : public Message { public: - PWMRSSIConfigureMessage( + constexpr PWMRSSIConfigureMessage( const bool enabled, const uint32_t freq, const int32_t avg @@ -501,93 +501,96 @@ public: const int32_t avg; }; -class XylosConfigureMessage : public Message { +class CCIRConfigureMessage : public Message { public: - XylosConfigureMessage( - const char data[] - ) : Message { ID::XylosConfigure } + constexpr CCIRConfigureMessage( + const uint32_t samples_per_tone, + const uint16_t tone_count + ) : Message { ID::CCIRConfigure }, + samples_per_tone(samples_per_tone), + tone_count(tone_count) { - memcpy(ccir_message, data, 21); } - char ccir_message[21]; -}; - -class OOKConfigureMessage : public Message { -public: - OOKConfigureMessage( - const char data[], - const uint32_t stream_length, - const uint32_t samples_per_bit, - const uint8_t repeat - ) : Message { ID::OOKConfigure }, - stream_length(stream_length), - samples_per_bit(samples_per_bit), - repeat(repeat) - { - memcpy(ook_bitstream, data, 64); - } - - char ook_bitstream[64]; - uint32_t stream_length; - uint32_t samples_per_bit; - uint8_t repeat; + const uint32_t samples_per_tone; + const uint16_t tone_count; }; class RetuneMessage : public Message { public: - RetuneMessage( - ) : Message { ID::Retune } + constexpr RetuneMessage( + const int64_t freq + ) : Message { ID::Retune }, + freq(freq) { } - int64_t freq = 0; + const int64_t freq = 0; }; class AFSKConfigureMessage : public Message { public: - AFSKConfigureMessage( - const char data[], - const uint32_t afsk_samples_per_bit, - const uint32_t afsk_phase_inc_mark, - const uint32_t afsk_phase_inc_space, - const uint8_t afsk_repeat, - const uint32_t afsk_bw, - const uint8_t afsk_format + constexpr AFSKConfigureMessage( + const uint32_t samples_per_bit, + const uint32_t phase_inc_mark, + const uint32_t phase_inc_space, + const uint8_t repeat, + const uint32_t bw, + const uint8_t format ) : Message { ID::AFSKConfigure }, - afsk_samples_per_bit(afsk_samples_per_bit), - afsk_phase_inc_mark(afsk_phase_inc_mark), - afsk_phase_inc_space(afsk_phase_inc_space), - afsk_repeat(afsk_repeat), - afsk_bw(afsk_bw), - afsk_format(afsk_format) + samples_per_bit(samples_per_bit), + phase_inc_mark(phase_inc_mark), + phase_inc_space(phase_inc_space), + repeat(repeat), + bw(bw), + format(format) { - memcpy(message_data, data, 512); } - uint32_t afsk_samples_per_bit; - uint32_t afsk_phase_inc_mark; - uint32_t afsk_phase_inc_space; - uint8_t afsk_repeat; - uint32_t afsk_bw; - uint8_t afsk_format; - char message_data[512]; + const uint32_t samples_per_bit; + const uint32_t phase_inc_mark; + const uint32_t phase_inc_space; + const uint8_t repeat; + const uint32_t bw; + const uint8_t format; +}; + +class OOKConfigureMessage : public Message { +public: + constexpr OOKConfigureMessage( + const uint32_t stream_length, + const uint32_t samples_per_bit, + const uint8_t repeat, + const uint32_t pause_symbols + ) : Message { ID::OOKConfigure }, + stream_length(stream_length), + samples_per_bit(samples_per_bit), + repeat(repeat), + pause_symbols(pause_symbols) + { + } + + const uint32_t stream_length; + const uint32_t samples_per_bit; + const uint8_t repeat; + const uint32_t pause_symbols; }; class FIFOSignalMessage : public Message { public: - FIFOSignalMessage( + constexpr FIFOSignalMessage( ) : Message { ID::FIFOSignal } { } - char signaltype = 0; + const char signaltype = 0; }; class FIFODataMessage : public Message { public: - FIFODataMessage( - ) : Message { ID::FIFOData } + constexpr FIFODataMessage( + ) : Message { ID::FIFOData }, + data ( nullptr ) { } diff --git a/firmware/common/portapack_shared_memory.hpp b/firmware/common/portapack_shared_memory.hpp index 45359aaa..882c7d1b 100644 --- a/firmware/common/portapack_shared_memory.hpp +++ b/firmware/common/portapack_shared_memory.hpp @@ -51,8 +51,7 @@ struct SharedMemory { JammerRange jammer_ranges[16]; - char epardata[13]; - int32_t excursion; + char tx_data[512] { 0 }; }; extern SharedMemory& shared_memory; diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index c2378c84..ad8ddcaa 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -103,16 +103,16 @@ struct region_t { constexpr region_t bootstrap { .offset = 0x00000, - .size = 0x8000, + .size = 0x10000, }; constexpr region_t images { - .offset = 0x8000, - .size = 0x38000, + .offset = 0x10000, + .size = 0x40000, }; constexpr region_t application { - .offset = 0x40000, + .offset = 0x80000, .size = 0x40000, }; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 0a49853b..e5506f5c 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * 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_widget.hpp" #include "ui_painter.hpp" #include "portapack.hpp" @@ -1026,10 +1048,6 @@ void NumberField::set_value(int32_t new_value, bool trigger_change) { } } -void NumberField::set_value(int32_t new_value) { - set_value(new_value, true); -} - void NumberField::set_range(const int32_t min, const int32_t max) { range.first = min; range.second = max; @@ -1081,4 +1099,129 @@ int32_t NumberField::clip_value(int32_t value) { return value; } +/* SymField **************************************************************/ + +SymField::SymField( + Point parent_pos, + size_t length, + range_t range +) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, + range { range }, + length_ { length } +{ + set_focusable(true); +} + +uint32_t SymField::value(const uint32_t index) { + return values_[index]; +} + +void SymField::set_value(const uint32_t index, int32_t new_value) { + new_value = clip_value(new_value); + + if( new_value != values_[index] ) { + values_[index] = new_value; + if( on_change ) { + on_change(); + } + set_dirty(); + } +} + +void SymField::set_length(const uint32_t new_length) { + if (new_length <= 30) { + prev_length_ = length_; + length_ = new_length; + erase_prev_ = true; + set_dirty(); + } +} + +void SymField::set_range(const int32_t min, const int32_t max) { + size_t n; + + range.first = min; + range.second = max; + for (n = 0; n < length_; n++) + set_value(n, values_[n]); +} + +void SymField::paint(Painter& painter) { + size_t n; + Point pt_draw = screen_pos(); + + if (erase_prev_) { + painter.fill_rectangle( { pt_draw, { prev_length_ * 8, 16 } }, Color::black() ); + erase_prev_ = false; + } + + for (n = 0; n < length_; n++) { + const auto text = to_string_dec_uint(values_[n], 1); + + const auto paint_style = (has_focus() && (n == selected_)) ? style().invert() : style(); + + painter.draw_string( + pt_draw, + paint_style, + text + ); + + pt_draw.x += 8; + } +} + +bool SymField::on_key(const KeyEvent key) { + switch (key) { + case KeyEvent::Select: + if( on_select ) { + on_select(*this); + return true; + } + break; + + case KeyEvent::Left: + if (selected_ > 0) { + selected_--; + set_dirty(); + return true; + } + break; + + case KeyEvent::Right: + if (selected_ < (length_ - 1)) { + selected_++; + set_dirty(); + return true; + } + break; + + default: + break; + } + + return false; +} + +bool SymField::on_encoder(const EncoderEvent delta) { + set_value(selected_, values_[selected_] + delta); + return true; +} + +bool SymField::on_touch(const TouchEvent event) { + if( event.type == TouchEvent::Type::Start ) { + focus(); + } + return true; +} + +int32_t SymField::clip_value(int32_t value) { + if( value > range.second ) { + value = range.second; + } + if( value < range.first ) { + value = range.first; + } + return value; +} + } /* namespace ui */ diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 85e630ef..b67608fa 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek * * This file is part of PortaPack. * @@ -411,7 +412,7 @@ public: NumberField(Point parent_pos, size_t length, range_t range, int32_t step, char fill_char); NumberField( - ) : NumberField { { }, 1, { 0, 1 }, 1, ' ' } + ) : NumberField { { 0, 0 }, 1, { 0, 1 }, 1, ' ' } { } @@ -419,8 +420,7 @@ public: NumberField(NumberField&&) = delete; int32_t value() const; - void set_value(int32_t new_value); - void set_value(int32_t new_value, bool trigger_change); + void set_value(int32_t new_value, bool trigger_change = true); void set_range(const int32_t min, const int32_t max); void paint(Painter& painter) override; @@ -439,6 +439,39 @@ private: int32_t clip_value(int32_t value); }; +class SymField : public Widget { +public: + std::function on_select; + std::function on_change; + + using range_t = std::pair; + + SymField(Point parent_pos, size_t length, range_t range); + + SymField(const SymField&) = delete; + SymField(SymField&&) = delete; + + uint32_t value(const uint32_t index); + void set_value(const uint32_t index, int32_t new_value); + void set_length(const uint32_t new_length); + void set_range(const int32_t min, const int32_t max); + + void paint(Painter& painter) override; + + bool on_key(const KeyEvent key) override; + bool on_encoder(const EncoderEvent delta) override; + bool on_touch(const TouchEvent event) override; + +private: + range_t range; + int32_t values_[30] = { 0 }; + uint32_t selected_ = 0; + size_t length_, prev_length_; + bool erase_prev_ = false; + + int32_t clip_value(int32_t value); +}; + } /* namespace ui */ #endif/*__UI_WIDGET_H__*/ diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 40420022..ea3669b6 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ diff --git a/firmware/tools/make_spi_image.py b/firmware/tools/make_spi_image.py index 57cf8a92..2098a267 100755 --- a/firmware/tools/make_spi_image.py +++ b/firmware/tools/make_spi_image.py @@ -56,12 +56,12 @@ images = ( { 'name': 'bootstrap', 'data': bootstrap_image, - 'size': 0x8000, + 'size': 0x10000, }, { 'name': 'baseband', 'data': baseband_image, - 'size': 0x38000, + 'size': 0x70000, }, { 'name': 'application', @@ -75,7 +75,7 @@ spi_image_default_byte = bytearray((255,)) for image in images: if len(image['data']) > image['size']: - raise RuntimeError('data for image "%(name)s" is longer than 0x%(size)x bytes' % image) + raise RuntimeError('data for image "%(name)s" is longer than 0x%(size)x bytes 0x%(sz)x' % {'name':image['name'], 'size':image['size'], 'sz':len(image['data'])}) pad_size = image['size'] - len(image['data']) padded_data = image['data'] + (spi_image_default_byte * pad_size) spi_image += padded_data