diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 35559e76..5f21caab 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -140,7 +140,7 @@ set(CPPSRC protocols/dcs.cpp protocols/lcr.cpp protocols/rds.cpp - afsk.cpp + modems.cpp audio.cpp ${COMMON}/bch_code.cpp ctcss.cpp @@ -183,7 +183,7 @@ set(CPPSRC ui_record_view.cpp ui_replay_view.cpp ui_rssi.cpp - ui_script.cpp + # ui_script.cpp ui_sd_card_status_view.cpp ui_sd_wipe.cpp # ui_sd_card_debug.cpp diff --git a/firmware/application/afsk.cpp b/firmware/application/afsk.cpp deleted file mode 100644 index 59da0316..00000000 --- a/firmware/application/afsk.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 "afsk.hpp" - -#include "portapack_persistent_memory.hpp" - -namespace afsk { - -void generate_data(const std::string & in_message, char * out_data) { - const afsk_formats_t * format_def; - uint8_t pm, pp, bit, cp, cur_byte, new_byte; - uint16_t dp; - - format_def = &afsk_formats[portapack::persistent_memory::afsk_format()]; - - if (format_def->parity == ODD) - pm = 1; // Odd parity - else - pm = 0; // Even parity - - if (format_def->data_bits == 7) { - if (!format_def->use_LUT) { - for (dp = 0; dp < in_message.length(); dp++) { - pp = pm; - new_byte = 0; - cur_byte = in_message[dp]; - for (cp = 0; cp < 7; cp++) { - bit = (cur_byte >> cp) & 1; - pp += bit; - new_byte |= (bit << (7 - cp)); - } - if (format_def->parity != NONE) new_byte |= (pp & 1); - out_data[dp] = new_byte; - } - out_data[dp++] = 0; - out_data[dp] = 0; - } else { - for (dp = 0; dp < in_message.length(); dp++) { - pp = pm; - - cur_byte = in_message[dp]; - - for (cp = 0; cp < 8; cp++) - if ((cur_byte >> cp) & 1) pp++; - - out_data[dp * 2] = cur_byte; - out_data[(dp * 2) + 1] = 0xFE; - if (format_def->parity != NONE) out_data[(dp * 2) + 1] |= (pp & 1); - } - out_data[dp * 2] = 0; - out_data[(dp * 2) + 1] = 0; - } - } else { - /* - for (dp = 0; dp < strlen(in_message); dp++) { - pp = pm; - - // Do not apply LUT on checksum (last byte) ? - if (dp != strlen(in_message) - 1) - cur_byte = alt_lookup[(uint8_t)in_message[dp] & 0x7F]; - else - cur_byte = in_message[dp]; - - for (cp = 0; cp < 8; cp++) - if ((cur_byte >> cp) & 1) pp++; - - out_data[dp * 2] = cur_byte; - out_data[(dp * 2) + 1] = 0xFE | (pp & 1); - } - out_data[dp * 2] = 0; - out_data[(dp * 2) + 1] = 0; - */ - } - - /* - // MSB first - for (dp = 0; dp < strlen(lcr_message); dp++) { - pp = pm; - cur_byte = lcr_message[dp]; - for (cp = 0; cp < 7; cp++) - if ((cur_byte >> cp) & 1) pp++; - lcr_message_data[dp] = (cur_byte << 1) | (pp & 1); - } - }*/ -} - -} /* namespace afsk */ diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index c948443f..59306899 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -116,14 +116,14 @@ void set_sstv_data(const uint8_t vis_code, const uint32_t pixel_duration) { } 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 uint8_t afsk_repeat, const uint32_t afsk_bw, const uint8_t symbol_count) { const AFSKConfigureMessage message { afsk_samples_per_bit, afsk_phase_inc_mark, afsk_phase_inc_space, afsk_repeat, afsk_bw, - afsk_alt_format + symbol_count }; send_message(&message); } diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index c7cfc1d5..e166c56a 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -65,7 +65,7 @@ void set_audiotx_data(const uint32_t divider, const uint32_t bw, const uint32_t void set_fifo_data(const int8_t * data); void set_pwmrssi(int32_t avg, bool enabled); 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 uint8_t afsk_repeat, const uint32_t afsk_bw, const uint8_t symbol_count); void kill_afsk(); void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat, const uint32_t pause_symbols); diff --git a/firmware/application/modems.cpp b/firmware/application/modems.cpp new file mode 100644 index 00000000..e8166b60 --- /dev/null +++ b/firmware/application/modems.cpp @@ -0,0 +1,93 @@ +/* + * 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 "modems.hpp" + +#include "portapack_persistent_memory.hpp" + +using namespace portapack; + +namespace modems { + +uint8_t symbol_count() { + serial_format_t serial_format; + uint8_t count; + + serial_format = persistent_memory::serial_format(); + + count = 1 + serial_format.data_bits; // Start + if (serial_format.parity) count++; + count += serial_format.stop_bits; + + return count; +}; + +void generate_data(const std::string& in_message, uint16_t * out_data) { + serial_format_t serial_format; + uint8_t parity_init, parity, data_bits, bits, bit, cur_byte; + uint16_t ordered_word, bytes; + + serial_format = persistent_memory::serial_format(); + + if (serial_format.parity == ODD) + parity_init = 1; + else + parity_init = 0; + + data_bits = serial_format.data_bits; + + for (bytes = 0; bytes < in_message.length(); bytes++) { + parity = parity_init; + cur_byte = in_message[bytes]; + + if (serial_format.bit_order == MSB_FIRST) { + ordered_word = cur_byte; + for (bits = 0; bits < data_bits; bits++) { + bit = (cur_byte >> bits) & 1; // Get LSB + parity += bit; + } + } else { + ordered_word = 0; + for (bits = 0; bits < data_bits; bits++) { + bit = (cur_byte >> bits) & 1; // Get LSB + parity += bit; + ordered_word |= (bit << ((data_bits - 1) - bits)); // Set MSB + } + } + + if (serial_format.parity) { + ordered_word <<= 1; + ordered_word |= (parity & 1); + } + + for (bits = 0; bits < serial_format.stop_bits; bits++) { + ordered_word <<= 1; + ordered_word |= 1; + } + + out_data[bytes] = ordered_word; + } + + out_data[bytes] = 0; // End marker +} + +} /* namespace modems */ diff --git a/firmware/application/afsk.hpp b/firmware/application/modems.hpp similarity index 52% rename from firmware/application/afsk.hpp rename to firmware/application/modems.hpp index a5fc3678..129f4e39 100644 --- a/firmware/application/afsk.hpp +++ b/firmware/application/modems.hpp @@ -24,38 +24,65 @@ #include #include -#ifndef __AFSK_H__ -#define __AFSK_H__ +#ifndef __MODEMS_H__ +#define __MODEMS_H__ -namespace afsk { +namespace modems { -#define AFSK_MODES_COUNT 4 +#define MODEM_DEF_COUNT 7 -enum parity_enum { +enum parity_enum : uint8_t { NONE = 0, - EVEN, - ODD + EVEN = 1, + ODD = 2 }; -struct afsk_formats_t { - std::string fullname; - std::string shortname; +enum order_enum : uint8_t { + MSB_FIRST = 0, + LSB_FIRST = 1 +}; + +struct serial_format_t { uint8_t data_bits; parity_enum parity; uint8_t stop_bits; - bool MSB_first; - bool use_LUT; + order_enum bit_order; }; -const afsk_formats_t afsk_formats[4] = { - { "7-Even-1 R", "7E1", 7, EVEN, 1, false, false }, +uint8_t symbol_count(); + +enum modulation_enum { + AFSK = 0, + FSK, + PSK, + SSB +}; + +struct modem_def_t { + std::string name; + modulation_enum modulation; + uint16_t mark_freq; + uint16_t space_freq; + uint16_t baudrate; +}; + +const modem_def_t modem_defs[MODEM_DEF_COUNT] = { + { "Bell202", AFSK, 1200, 2200, 1200 }, + { "Bell103", AFSK, 1270, 1070, 300 }, + { "V21", AFSK, 980, 1180, 300 }, + { "V23 M1", AFSK, 1300, 1700, 600 }, + { "V23 M2", AFSK, 1300, 2100, 1200 }, + { "RTTY US", SSB, 2295, 2125, 45 }, + { "RTTY EU", SSB, 2125, 1955, 45 } + + /*{ "7-Even-1 R", "7E1", 7, EVEN, 1, false, false }, { "7E1 LUT ", "7Ea", 7, EVEN, 1, true, true }, { "7-Odd-1 ", "7o1", 7, ODD, 1, true, false }, - { "8-Even-0 ", "8E0", 8, EVEN, 1, true, false } + { "8-Even-0 ", "8E0", 8, EVEN, 1, true, false }*/ }; -void generate_data(const std::string & in_message, char * out_data); +void generate_data(const std::string& in_message, uint16_t * out_data); -} /* namespace afsk */ +} /* namespace modems */ -#endif/*__AFSK_H__*/ +#endif/*__MODEMS_H__*/ diff --git a/firmware/application/pocsag_app.cpp b/firmware/application/pocsag_app.cpp index 034685a3..bf84acf5 100644 --- a/firmware/application/pocsag_app.cpp +++ b/firmware/application/pocsag_app.cpp @@ -67,6 +67,7 @@ void POCSAGAppView::update_freq(rf::Frequency f) { } POCSAGAppView::POCSAGAppView(NavigationView& nav) { + uint32_t ignore_address; baseband::run_image(portapack::spi_flash::image_tag_pocsag); @@ -109,8 +110,12 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) { check_ignore.on_select = [this](Checkbox&, bool v) { ignore = v; }; - for (size_t c = 0; c < 7; c++) - sym_ignore.set_sym(c, default_ignore[c]); + + ignore_address = persistent_memory::pocsag_ignore_address(); + for (size_t c = 0; c < 7; c++) { + sym_ignore.set_sym(6 - c, ignore_address % 10); + ignore_address /= 10; + } button_setfreq.on_select = [this,&nav](Button&) { auto new_view = nav.push(target_frequency_); @@ -126,6 +131,10 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) { } POCSAGAppView::~POCSAGAppView() { + + // Save ignored address + persistent_memory::set_pocsag_ignore_address(sym_ignore.value_dec_u32()); + receiver_model.disable(); baseband::shutdown(); } @@ -162,7 +171,7 @@ void POCSAGAppView::on_packet(const POCSAGPacketMessage * message) { console_info += " F" + to_string_dec_uint(pocsag_state.function); // Store last received address for POCSAG TX - portapack::persistent_memory::set_pocsag_address(pocsag_state.address); + persistent_memory::set_pocsag_last_address(pocsag_state.address); if (pocsag_state.out_type == ADDRESS) { // Address only diff --git a/firmware/application/pocsag_app.hpp b/firmware/application/pocsag_app.hpp index 83d950be..610f01d3 100644 --- a/firmware/application/pocsag_app.hpp +++ b/firmware/application/pocsag_app.hpp @@ -59,8 +59,6 @@ public: private: static constexpr uint32_t initial_target_frequency = 466175000; - static constexpr uint32_t sampling_rate = 3072000; - const uint8_t default_ignore[7] = { 1, 0, 0, 8, 8, 2, 4 }; bool logging { true }; bool ignore { false }; diff --git a/firmware/application/protocols/lcr.cpp b/firmware/application/protocols/lcr.cpp index f1221eec..d7c4453b 100644 --- a/firmware/application/protocols/lcr.cpp +++ b/firmware/application/protocols/lcr.cpp @@ -23,8 +23,6 @@ #include "lcr.hpp" #include "string_format.hpp" -//#include "portapack_persistent_memory.hpp" - namespace lcr { std::string generate_message(std::string rgsb, std::vector litterals, size_t option_ec) { diff --git a/firmware/application/replay_thread.cpp b/firmware/application/replay_thread.cpp index 804c34c2..96b6ff15 100644 --- a/firmware/application/replay_thread.cpp +++ b/firmware/application/replay_thread.cpp @@ -67,13 +67,13 @@ ReplayThread::~ReplayThread() { msg_t ReplayThread::static_fn(void* arg) { auto obj = static_cast(arg); const auto error = obj->run(); - /*if( error.is_valid() && obj->error_callback ) { + if( error.is_valid() && obj->error_callback ) { obj->error_callback(error.value()); } else { if( obj->success_callback ) { obj->success_callback(); } - }*/ + } return 0; } @@ -82,14 +82,13 @@ Optional ReplayThread::run() { BufferExchange buffers { &config }; while( !chThdShouldTerminate() ) { - //auto buffer = buffers.get(); - buffers.get(); + auto buffer = buffers.get(); /*auto read_result = reader->read(buffer->data(), buffer->size()); if( read_result.is_error() ) { return read_result.error(); } buffers.put(buffer);*/ - chThdSleep(50); + chThdSleep(50); // DEBUG //led_tx.toggle(); } diff --git a/firmware/application/ui_afsksetup.cpp b/firmware/application/ui_afsksetup.cpp index ca968624..7e7c1c54 100644 --- a/firmware/application/ui_afsksetup.cpp +++ b/firmware/application/ui_afsksetup.cpp @@ -33,7 +33,7 @@ #include using namespace portapack; -using namespace afsk; +using namespace modems; namespace ui { @@ -42,18 +42,14 @@ void AFSKSetupView::focus() { } void AFSKSetupView::update_freq(rf::Frequency f) { - char finalstr[10] = {0}; + std::string final_str; - portapack::persistent_memory::set_tuned_frequency(f); + persistent_memory::set_tuned_frequency(f); - auto mhz = to_string_dec_int(f / 1000000, 4); - auto hz100 = to_string_dec_int((f / 100) % 10000, 4, '0'); + final_str = to_string_dec_int(f / 1000000, 4) + "."; + final_str += to_string_dec_int((f / 100) % 10000, 4, '0'); - strcat(finalstr, mhz.c_str()); - strcat(finalstr, "."); - strcat(finalstr, hz100.c_str()); - - this->button_setfreq.set_text(finalstr); + button_setfreq.set_text(final_str); } AFSKSetupView::AFSKSetupView( @@ -64,57 +60,81 @@ AFSKSetupView::AFSKSetupView( using value_t = int32_t; using option_t = std::pair; using options_t = std::vector; - options_t format_options; - uint8_t rpt; + options_t modem_options; size_t i; add_children({ &labels, &button_setfreq, - &options_bps, + &field_baudrate, &field_mark, &field_space, &field_bw, &field_repeat, - &options_format, + &options_modem, + &button_set_modem, + &sym_format, &button_save }); - for (i = 0; i < AFSK_MODES_COUNT; i++) - format_options.emplace_back(std::make_pair(afsk_formats[i].fullname, i)); + for (i = 0; i < MODEM_DEF_COUNT; i++) { + if (modem_defs[i].modulation == AFSK) + modem_options.emplace_back(std::make_pair(modem_defs[i].name, i)); + } - options_format.set_options(format_options); - options_format.set_selected_index(portapack::persistent_memory::afsk_format()); + options_modem.set_options(modem_options); + options_modem.set_selected_index(0); - update_freq(portapack::persistent_memory::tuned_frequency()); + sym_format.set_symbol_list(0, "6789"); // Data bits + sym_format.set_symbol_list(1, "NEo"); // Parity + sym_format.set_symbol_list(2, "012"); // Stop bits + sym_format.set_symbol_list(3, "ML"); // MSB/LSB first - field_mark.set_value(portapack::persistent_memory::afsk_mark_freq() * 25); - field_space.set_value(portapack::persistent_memory::afsk_space_freq() * 25); - field_bw.set_value(portapack::persistent_memory::afsk_bw()); - rpt = portapack::persistent_memory::afsk_repeats(); - if ((rpt > 99) || (!rpt)) rpt = 5; - field_repeat.set_value(rpt); + sym_format.set_sym(0, persistent_memory::serial_format().data_bits - 6); + sym_format.set_sym(1, persistent_memory::serial_format().parity); + sym_format.set_sym(2, persistent_memory::serial_format().stop_bits); + sym_format.set_sym(3, persistent_memory::serial_format().bit_order); - button_setfreq.on_select = [this,&nav](Button&) { - auto new_view = nav.push(portapack::persistent_memory::tuned_frequency()); + update_freq(persistent_memory::tuned_frequency()); + + field_mark.set_value(persistent_memory::afsk_mark_freq()); + field_space.set_value(persistent_memory::afsk_space_freq()); + field_bw.set_value(persistent_memory::modem_bw() / 1000); + field_repeat.set_value(persistent_memory::modem_repeat()); + + button_setfreq.on_select = [this, &nav](Button&) { + auto new_view = nav.push(persistent_memory::tuned_frequency()); new_view->on_changed = [this](rf::Frequency f) { update_freq(f); }; }; - options_bps.set_by_value(portapack::persistent_memory::afsk_bitrate()); + field_baudrate.set_value(persistent_memory::modem_baudrate()); + + button_set_modem.on_select = [this, &nav](Button&) { + size_t modem_def_index = options_modem.selected_index(); + + field_mark.set_value(modem_defs[modem_def_index].mark_freq); + field_space.set_value(modem_defs[modem_def_index].space_freq); + field_baudrate.set_value(modem_defs[modem_def_index].baudrate); + }; button_save.on_select = [this,&nav](Button&) { - uint32_t afsk_config = 0; + serial_format_t serial_format; - portapack::persistent_memory::set_afsk_bitrate(options_bps.selected_index_value()); - portapack::persistent_memory::set_afsk_mark(field_mark.value() / 25); - portapack::persistent_memory::set_afsk_space(field_space.value() / 25); - portapack::persistent_memory::set_afsk_bw(field_bw.value()); + persistent_memory::set_afsk_mark(field_mark.value()); + persistent_memory::set_afsk_space(field_space.value()); - afsk_config |= (options_format.selected_index() << 16); - afsk_config |= (field_repeat.value() << 24); - portapack::persistent_memory::set_afsk_config(afsk_config); + persistent_memory::set_modem_baudrate(field_baudrate.value()); + persistent_memory::set_modem_bw(field_bw.value() * 1000); + persistent_memory::set_modem_repeat(field_repeat.value()); + + serial_format.data_bits = sym_format.get_sym(0) + 6; + serial_format.parity = (parity_enum)sym_format.get_sym(1); + serial_format.stop_bits = sym_format.get_sym(2); + serial_format.bit_order = (order_enum)sym_format.get_sym(3); + + persistent_memory::set_serial_format(serial_format); nav.pop(); }; diff --git a/firmware/application/ui_afsksetup.hpp b/firmware/application/ui_afsksetup.hpp index a8fa5c44..858f4f9f 100644 --- a/firmware/application/ui_afsksetup.hpp +++ b/firmware/application/ui_afsksetup.hpp @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include "afsk.hpp" +#include "modems.hpp" #include "ui.hpp" #include "ui_widget.hpp" @@ -40,30 +40,27 @@ private: void update_freq(rf::Frequency f); Labels labels { - { { 1 * 8, 4 * 8 }, "Frequency:", Color::light_grey() }, - { { 16 * 8, 5 * 8 }, "Speed:", Color::light_grey() }, + { { 2 * 8, 4 * 8 }, "Frequency:", Color::light_grey() }, + { { 2 * 8, 11 * 8 }, "Speed: Bps", Color::light_grey() }, { { 2 * 8, 13 * 8 }, "Mark: Hz", Color::light_grey() }, { { 2 * 8, 15 * 8 }, "Space: Hz", Color::light_grey() }, { { 140, 13 * 8 }, "BW: kHz", Color::light_grey() }, { { 140, 15 * 8 }, "Repeat:", Color::light_grey() }, - { { 2 * 8, 19 * 8 }, "Format:", Color::light_grey() } + { { 2 * 8, 19 * 8 }, "Modem preset:", Color::light_grey() }, + { { 2 * 8, 22 * 8 }, "Serial format:", Color::light_grey() } }; Button button_setfreq { - { 8, 48, 104, 32 }, + { 13 * 8, 3 * 8, 12 * 8, 32 }, "----.----" }; - OptionsField options_bps { - { 128, 60 }, - 7, - { - { "600bps ", 600 }, - { "1200bps", 1200 }, - { "2400bps", 2400 }, - { "4800bps", 4800 }, - { "9600bps", 9600 } - } + NumberField field_baudrate { + { 64, 88 }, + 5, + { 50, 9600 }, + 25, + ' ' }; NumberField field_mark { @@ -98,13 +95,24 @@ private: ' ' }; - OptionsField options_format { - { 80, 152 }, - 10, + OptionsField options_modem { + { 16 * 8, 19 * 8 }, + 7, { } }; + SymField sym_format { + { 16 * 8, 22 * 8 }, + 4, + SymField::SYMFIELD_DEF + }; + + Button button_set_modem { + { 24 * 8, 19 * 8 - 4, 5 * 8, 24 }, + "SET" + }; + Button button_save { { 72, 250, 96, 40 }, "Save" diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index 4ecbc07b..07447885 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -24,7 +24,7 @@ #include "ui_afsksetup.hpp" #include "ui_debug.hpp" -#include "afsk.hpp" +#include "modems.hpp" #include "lcr.hpp" #include "baseband_api.hpp" #include "string_format.hpp" @@ -35,7 +35,7 @@ #include using namespace portapack; -using namespace afsk; +using namespace modems; namespace ui { @@ -49,7 +49,7 @@ LCRView::~LCRView() { } void LCRView::paint(Painter& painter) { - uint8_t i; + size_t i; std::string final_str; static constexpr Style style_orange { @@ -75,11 +75,11 @@ void LCRView::paint(Painter& painter) { button_setrgsb.set_text(rgsb); // Recap: freq @ bps - final_str = to_string_dec_int(portapack::persistent_memory::tuned_frequency() / 1000, 6); + final_str = to_string_dec_int(persistent_memory::tuned_frequency() / 1000, 6); final_str += '@'; - final_str += to_string_dec_int(portapack::persistent_memory::afsk_bitrate(), 4); + final_str += to_string_dec_int(persistent_memory::modem_baudrate(), 4); final_str += "bps "; - final_str += afsk_formats[portapack::persistent_memory::afsk_format()].shortname; + //final_str += modem_defs[persistent_memory::modem_def_index()].name; text_recap.set(final_str); } @@ -95,25 +95,18 @@ std::vector LCRView::parse_litterals() { } void LCRView::update_progress() { - char str[16]; + std::string progress_str; - text_status.set(" "); + text_status.set(" "); // Clear if (tx_mode == SINGLE) { - strcpy(str, to_string_dec_uint(repeat_index).c_str()); - strcat(str, "/"); - strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str()); - text_status.set(str); + progress_str = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(persistent_memory::modem_repeat()); + text_status.set(progress_str); progress.set_value(repeat_index); } else if (tx_mode == SCAN) { - strcpy(str, to_string_dec_uint(repeat_index).c_str()); - strcat(str, "/"); - strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str()); - strcat(str, " "); - strcat(str, to_string_dec_uint(scan_index + 1).c_str()); - strcat(str, "/"); - strcat(str, to_string_dec_uint(scan_count).c_str()); - text_status.set(str); + progress_str = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(persistent_memory::modem_repeat()); + progress_str += " " + to_string_dec_uint(scan_index + 1) + "/" + to_string_dec_uint(scan_count); + text_status.set(progress_str); progress.set_value(scan_progress); } else { text_status.set("Ready"); @@ -153,10 +146,9 @@ void LCRView::on_txdone(int n) { } void LCRView::start_tx(const bool scan) { - uint8_t afsk_format; - uint8_t afsk_repeats; + uint8_t repeats; - afsk_repeats = portapack::persistent_memory::afsk_repeats(); + repeats = persistent_memory::modem_repeat(); if (scan) { if (tx_mode != SCAN) { @@ -166,35 +158,20 @@ void LCRView::start_tx(const bool scan) { repeat_index = 1; tx_mode = SCAN; rgsb = scan_list[options_scanlist.selected_index()].addresses[0]; - progress.set_max(scan_count * afsk_repeats); + progress.set_max(scan_count * repeats); update_progress(); } } else { tx_mode = SINGLE; repeat_index = 1; - progress.set_max(afsk_repeats); + progress.set_max(repeats); update_progress(); } button_setrgsb.set_text(rgsb); - afsk::generate_data(lcr::generate_message(rgsb, parse_litterals(), options_ec.selected_index()), lcr_message_data); + modems::generate_data(lcr::generate_message(rgsb, parse_litterals(), options_ec.selected_index()), lcr_message_data); - switch (portapack::persistent_memory::afsk_format()) { - case 0: - case 1: - case 2: - afsk_format = 0; - break; - - case 3: - afsk_format = 1; - break; - - default: - afsk_format = 0; - } - - transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency()); + transmitter_model.set_tuning_frequency(persistent_memory::tuned_frequency()); transmitter_model.set_sampling_rate(1536000U); transmitter_model.set_rf_amp(true); transmitter_model.set_baseband_bandwidth(1750000); @@ -203,12 +180,12 @@ void LCRView::start_tx(const bool scan) { memcpy(shared_memory.bb_data.data, lcr_message_data, 300); baseband::set_afsk_data( - (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_afsk.cpp - afsk_format + 1536000 / persistent_memory::modem_baudrate(), + persistent_memory::afsk_mark_freq(), + persistent_memory::afsk_space_freq(), + repeats, + persistent_memory::modem_bw(), + modems::symbol_count() ); } diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 08fba1be..9862a8bf 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -84,7 +84,7 @@ private: std::string litteral[5] { " " }; std::string rgsb { " " }; char lcr_message[512]; - char lcr_message_data[512]; + uint16_t lcr_message_data[256]; rf::Frequency f { 0 }; uint8_t repeat_index { 0 }; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 89a6881c..b1beee4d 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -361,7 +361,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { { "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push(); } }, { "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push(); } }, { "Capture", ui::Color::blue(), &bitmap_icon_capture, [&nav](){ nav.push(); } }, - { "Replay", ui::Color::blue(), &bitmap_icon_replay, [&nav](){ nav.push(); } }, // ReplayAppView + { "Replay", ui::Color::grey(), &bitmap_icon_replay, [&nav](){ nav.push(); } }, // ReplayAppView { "Audio transmitters", ui::Color::green(), &bitmap_icon_audiotx, [&nav](){ nav.push(); } }, { "Code transmitters", ui::Color::green(), &bitmap_icon_codetx, [&nav](){ nav.push(); } }, { "SSTV transmitter", ui::Color::dark_green(), &bitmap_icon_sstv, [&nav](){ nav.push(); } }, diff --git a/firmware/application/ui_pocsag_tx.cpp b/firmware/application/ui_pocsag_tx.cpp index ca1b5745..d2a9326d 100644 --- a/firmware/application/ui_pocsag_tx.cpp +++ b/firmware/application/ui_pocsag_tx.cpp @@ -151,7 +151,7 @@ POCSAGTXView::POCSAGTXView( options_type.set_selected_index(0); // Address only // TODO: set_value for whole symfield - reload_address = portapack::persistent_memory::pocsag_address(); + reload_address = persistent_memory::pocsag_last_address(); for (c = 0; c < 7; c++) { field_address.set_sym(6 - c, reload_address % 10); reload_address /= 10; diff --git a/firmware/baseband/proc_afsk.cpp b/firmware/baseband/proc_afsk.cpp index 00fdf819..0f33f73d 100644 --- a/firmware/baseband/proc_afsk.cpp +++ b/firmware/baseband/proc_afsk.cpp @@ -35,88 +35,60 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { for (size_t i = 0; i= (5 - 1)) { - s = 0; - - if (sample_count >= afsk_samples_per_bit) { - if (configured) { - cur_byte = shared_memory.bb_data.data[byte_pos]; - ext_byte = shared_memory.bb_data.data[byte_pos + 1]; - - if (!(cur_byte | ext_byte)) { - // End of data - if (repeat_counter < afsk_repeat) { - // Repeat - bit_pos = 0; - byte_pos = 0; - cur_byte = shared_memory.bb_data.data[0]; - ext_byte = shared_memory.bb_data.data[1]; - message.progress = repeat_counter + 1; - shared_memory.application_queue.push(message); - repeat_counter++; - } else { - // Stop - cur_byte = 0; - ext_byte = 0; - message.progress = 0; - shared_memory.application_queue.push(message); - configured = false; - } + if (sample_count >= afsk_samples_per_bit) { + if (configured) { + cur_word = *word_ptr; + + if (!cur_word) { + // End of data + if (repeat_counter < afsk_repeat) { + // Repeat + bit_pos = 0; + word_ptr = (uint16_t*)shared_memory.bb_data.data; + cur_word = *word_ptr; + message.progress = repeat_counter + 1; + shared_memory.application_queue.push(message); + repeat_counter++; + } else { + // Stop + cur_word = 0; + message.progress = 0; + shared_memory.application_queue.push(message); + configured = false; } } - - if (afsk_format == 0) { - // 0bbbbbbbp1 - // Start, 7-bit data, parity, stop - gbyte = (cur_byte << 1) | 1; - } else if (afsk_format == 1) { - // 0bbbbbbbbp - // Start, 8-bit data, parity - gbyte = (cur_byte << 1) | (ext_byte & 1); - } - - cur_bit = (gbyte >> (9 - bit_pos)) & 1; - - if (bit_pos >= 9) { - bit_pos = 0; - if (afsk_format == 0) - byte_pos++; - else if (afsk_format == 1) - byte_pos += 2; - } else { - bit_pos++; - } - - sample_count = 0; - } else { - sample_count++; } - if (cur_bit) - tone_phase += afsk_phase_inc_mark; - else - tone_phase += afsk_phase_inc_space; + + cur_bit = (cur_word >> (symbol_count - bit_pos)) & 1; + + if (bit_pos >= symbol_count) { + bit_pos = 0; + word_ptr++; + } else { + bit_pos++; + } + + sample_count = 0; } else { - s--; + sample_count++; } + + if (cur_bit) + tone_phase += afsk_phase_inc_mark; + else + tone_phase += afsk_phase_inc_space; - //tone_phase += 432759; // 1981Hz - - tone_sample = (sine_table_i8[(tone_phase & 0x03FC0000) >> 18]); - - // FM - // 1<<18 = 262144 - // m = (262144 * a) / 2280000 - // a = 262144 / 2280000 (*1000 = 115, see ui_lcr afsk_bw setting) - frq = tone_sample * afsk_bw; - - phase = (phase + frq); - sphase = phase + (64 << 18); + tone_sample = sine_table_i8[(tone_phase & 0xFF000000U) >> 24]; - re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]); - im = (sine_table_i8[(phase & 0x03FC0000) >> 18]); + delta = tone_sample * fm_delta; - buffer.p[i] = {(int8_t)re, (int8_t)im}; + phase += delta; + sphase = phase + (64 << 24); + + re = (sine_table_i8[(sphase & 0xFF000000U) >> 24]); + im = (sine_table_i8[(phase & 0xFF000000U) >> 24]); + + buffer.p[i] = {re, im}; } } @@ -126,19 +98,17 @@ void AFSKProcessor::on_message(const Message* const msg) { if (message.id == Message::ID::AFSKConfigure) { if (message.samples_per_bit) { 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_phase_inc_mark = message.phase_inc_mark * AFSK_DELTA_COEF; + afsk_phase_inc_space = message.phase_inc_space * AFSK_DELTA_COEF; afsk_repeat = message.repeat - 1; - afsk_bw = message.bw; - afsk_format = message.format; - - s = 0; + fm_delta = message.fm_delta * (0xFFFFFFULL / 1536000); + symbol_count = message.symbol_count - 1; + sample_count = afsk_samples_per_bit; repeat_counter = 0; bit_pos = 0; - byte_pos = 0; - cur_byte = 0; - ext_byte = 0; + word_ptr = (uint16_t*)shared_memory.bb_data.data; + cur_word = 0; cur_bit = 0; configured = true; } else diff --git a/firmware/baseband/proc_afsk.hpp b/firmware/baseband/proc_afsk.hpp index fd28e35a..e021c4e0 100644 --- a/firmware/baseband/proc_afsk.hpp +++ b/firmware/baseband/proc_afsk.hpp @@ -26,6 +26,9 @@ #include "baseband_processor.hpp" #include "baseband_thread.hpp" +#define AFSK_SAMPLERATE 1536000 +#define AFSK_DELTA_COEF ((1ULL << 32) / AFSK_SAMPLERATE) + class AFSKProcessor : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; @@ -41,21 +44,19 @@ private: uint32_t afsk_phase_inc_mark { 0 }; uint32_t afsk_phase_inc_space { 0 }; uint8_t afsk_repeat { 0 }; - uint32_t afsk_bw { 0 }; - uint8_t afsk_format { 0 }; + uint32_t fm_delta { 0 }; + uint8_t symbol_count { 0 }; uint8_t repeat_counter { 0 }; - int8_t re { 0 }, im { 0 }; - uint8_t s { 0 }; uint8_t bit_pos { 0 }; - uint16_t byte_pos { 0 }; - char cur_byte { 0 }; - char ext_byte { 0 }; - uint16_t gbyte { 0 }; + uint16_t * word_ptr { }; + uint16_t cur_word { 0 }; uint8_t cur_bit { 0 }; uint32_t sample_count { 0 }; uint32_t tone_phase { 0 }, phase { 0 }, sphase { 0 }; - int32_t tone_sample { 0 }, sig { 0 }, frq { 0 }; + int32_t tone_sample { 0 }, delta { 0 }; + + int8_t re { 0 }, im { 0 }; TXDoneMessage message { }; }; diff --git a/firmware/baseband/proc_replay.cpp b/firmware/baseband/proc_replay.cpp index 652c5214..af6c3cde 100644 --- a/firmware/baseband/proc_replay.cpp +++ b/firmware/baseband/proc_replay.cpp @@ -22,8 +22,6 @@ #include "proc_replay.hpp" -//#include "dsp_fir_taps.hpp" - #include "event_m4.hpp" #include "utility.hpp" @@ -34,16 +32,12 @@ ReplayProcessor::ReplayProcessor() { void ReplayProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ - //const auto decim_0_out = decim_0.execute(buffer, dst_buffer); - //const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); - //const auto& decimator_out = decim_1_out; - //const auto& channel = decimator_out; size_t pos = 0; for (size_t c = 0; c < 4; c++) { if( stream ) { - const size_t bytes_to_read = sizeof(*buffer.p) * buffer.count / 4; // ? + const size_t bytes_to_read = sizeof(*buffer.p) * buffer.count / 4; const auto result = stream->read(iq_buffer.p, bytes_to_read); } @@ -52,7 +46,6 @@ void ReplayProcessor::execute(const buffer_c8_t& buffer) { for (size_t i = 0; i < (buffer.count / 4); i++) { buffer.p[pos] = { iq_buffer.p[i].real() >> 8, iq_buffer.p[i].imag() >> 8 }; pos++; - //buffer.p[i] = { iq_buffer.p[i].real(), iq_buffer.p[i].imag() }; } } diff --git a/firmware/baseband/proc_replay.hpp b/firmware/baseband/proc_replay.hpp index 9b1fbb2f..37fa4e8e 100644 --- a/firmware/baseband/proc_replay.hpp +++ b/firmware/baseband/proc_replay.hpp @@ -25,11 +25,6 @@ #include "baseband_processor.hpp" #include "baseband_thread.hpp" -//#include "rssi_thread.hpp" - -//#include "dsp_decimate.hpp" - -//#include "spectrum_collector.hpp" #include "stream_output.hpp" @@ -52,7 +47,7 @@ private: BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit }; //RSSIThread rssi_thread { NORMALPRIO + 10 }; - std::array iq { }; // 2048 + std::array iq { }; // 2048 doesn't fit in allocated RAM const buffer_c16_t iq_buffer { iq.data(), iq.size() diff --git a/firmware/baseband/stream_output.cpp b/firmware/baseband/stream_output.cpp index 7d81e607..30f2d651 100644 --- a/firmware/baseband/stream_output.cpp +++ b/firmware/baseband/stream_output.cpp @@ -48,7 +48,7 @@ size_t StreamOutput::read(void* const data, const size_t length) { if( !active_buffer ) { // We need a full buffer... if( !fifo_buffers_full.out(active_buffer) ) { - // ...but none are available. Samples were dropped. + // ...but none are available. Hole in transmission (inform app and stop ?) break; } } @@ -59,11 +59,12 @@ size_t StreamOutput::read(void* const data, const size_t length) { if( active_buffer->is_empty() ) { if( !fifo_buffers_empty.in(active_buffer) ) { - // FIFO is completly empty. - // Bail out of the loop, and try retrieving the buffer in the - // next pass. + // Empty buffers FIFO is already full. + // This should never happen if the number of buffers is less + // than the capacity of the FIFO. break; } + // Tell M0 (IRQ) that a buffer has been consumed. active_buffer = nullptr; creg::m4txevent::assert(); } diff --git a/firmware/common/buffer_exchange.cpp b/firmware/common/buffer_exchange.cpp index 2fb7aff6..6cc107a6 100644 --- a/firmware/common/buffer_exchange.cpp +++ b/firmware/common/buffer_exchange.cpp @@ -32,7 +32,7 @@ BufferExchange::BufferExchange( ) // : config_capture { config } { obj = this; - direction = CAPTURE; + // In capture mode, baseband wants empty buffers, app waits for full buffers fifo_buffers_for_baseband = config->fifo_buffers_empty; fifo_buffers_for_application = config->fifo_buffers_full; } @@ -42,7 +42,7 @@ BufferExchange::BufferExchange( ) // : config_replay { config } { obj = this; - direction = REPLAY; + // In replay mode, baseband wants full buffers, app waits for empty buffers fifo_buffers_for_baseband = config->fifo_buffers_full; fifo_buffers_for_application = config->fifo_buffers_empty; } @@ -56,14 +56,15 @@ BufferExchange::~BufferExchange() { StreamBuffer* BufferExchange::get(FIFO* fifo) { while(true) { StreamBuffer* p { nullptr }; - fifo->out(p); + fifo->out(p); // This crashes replay - led_tx.on(); // DEBUG + //led_tx.on(); // DEBUG if( p ) { return p; } + // Put thread to sleep, woken up by M4 IRQ chSysLock(); thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); diff --git a/firmware/common/buffer_exchange.hpp b/firmware/common/buffer_exchange.hpp index 19e6befa..d3377295 100644 --- a/firmware/common/buffer_exchange.hpp +++ b/firmware/common/buffer_exchange.hpp @@ -86,12 +86,8 @@ private: } direction { }; void check_fifo_isr() { - //if (!empty() && (direction == CAPTURE)) { if (!empty()) wakeup_isr(); - //} else if (!empty() && (direction == REPLAY)) { - // wakeup_isr(); - //} } void wakeup_isr() { diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index 56e82baa..0cf1f6d9 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -111,9 +111,9 @@ public: return false; } - val = _data[_out & mask()]; - smp_wmb(); - _out += 1; + val = _data[_out & mask()]; // Crashes + smp_wmb(); // Ok + _out += 1; // Crashes return true; } diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index a6b66dcf..a04ed06f 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -683,15 +683,15 @@ public: const uint32_t phase_inc_mark, const uint32_t phase_inc_space, const uint8_t repeat, - const uint32_t bw, - const uint8_t format + const uint32_t fm_delta, + const uint8_t symbol_count ) : Message { ID::AFSKConfigure }, samples_per_bit(samples_per_bit), phase_inc_mark(phase_inc_mark), phase_inc_space(phase_inc_space), repeat(repeat), - bw(bw), - format(format) + fm_delta(fm_delta), + symbol_count(symbol_count) { } @@ -699,8 +699,8 @@ public: const uint32_t phase_inc_mark; const uint32_t phase_inc_space; const uint8_t repeat; - const uint32_t bw; - const uint8_t format; + const uint32_t fm_delta; + const uint8_t symbol_count; }; class OOKConfigureMessage : public Message { diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index ba340100..d2d7026b 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -44,17 +44,21 @@ constexpr ppb_range_t ppb_range { -99000, 99000 }; constexpr ppb_t ppb_reset_value { 0 }; using afsk_freq_range_t = range_t; -constexpr afsk_freq_range_t afsk_freq_range { 1, 400 }; -constexpr int32_t afsk_mark_reset_value { 48 }; -constexpr int32_t afsk_space_reset_value { 88 }; +constexpr afsk_freq_range_t afsk_freq_range { 1, 4000 }; +constexpr int32_t afsk_mark_reset_value { 1200 }; +constexpr int32_t afsk_space_reset_value { 2200 }; -using afsk_bitrate_range_t = range_t; -constexpr afsk_bitrate_range_t afsk_bitrate_range { 600, 9600 }; -constexpr int32_t afsk_bitrate_reset_value { 1200 }; +using modem_baudrate_range_t = range_t; +constexpr modem_baudrate_range_t modem_baudrate_range { 50, 9600 }; +constexpr int32_t modem_baudrate_reset_value { 1200 }; -using afsk_bw_range_t = range_t; -constexpr afsk_bw_range_t afsk_bw_range { 1, 50 }; -constexpr int32_t afsk_bw_reset_value { 15 }; +using modem_bw_range_t = range_t; +constexpr modem_bw_range_t modem_bw_range { 1000, 50000 }; +constexpr int32_t modem_bw_reset_value { 15000 }; + +using modem_repeat_range_t = range_t; +constexpr modem_repeat_range_t modem_repeat_range { 1, 99 }; +constexpr int32_t modem_repeat_reset_value { 5 }; /* struct must pack the same way on M4 and M0 cores. */ struct data_t { @@ -63,13 +67,14 @@ struct data_t { uint32_t touch_calibration_magic; touch::Calibration touch_calibration; - - // AFSK modem + // Modem + uint32_t modem_def_index; + serial_format_t serial_format; + int32_t modem_bw; int32_t afsk_mark_freq; - int32_t afsk_space_freq; // Todo: reduce size, only 256 bytes of NVRAM ! - int32_t afsk_bitrate; - int32_t afsk_bw; - uint32_t afsk_config; + int32_t afsk_space_freq; + int32_t modem_baudrate; + int32_t modem_repeat; // Play dead unlock uint32_t playdead_magic; @@ -78,7 +83,8 @@ struct data_t { uint32_t ui_config; - uint32_t pocsag_address; + uint32_t pocsag_last_address; + uint32_t pocsag_ignore_address; }; static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region"); @@ -137,38 +143,39 @@ void set_afsk_space(const int32_t new_value) { data->afsk_space_freq = afsk_freq_range.clip(new_value); } -int32_t afsk_bitrate() { - afsk_bitrate_range.reset_if_outside(data->afsk_bitrate, afsk_bitrate_reset_value); - return data->afsk_bitrate; +int32_t modem_baudrate() { + modem_baudrate_range.reset_if_outside(data->modem_baudrate, modem_baudrate_reset_value); + return data->modem_baudrate; } -void set_afsk_bitrate(const int32_t new_value) { - data->afsk_bitrate = afsk_bitrate_range.clip(new_value); +void set_modem_baudrate(const int32_t new_value) { + data->modem_baudrate = modem_baudrate_range.clip(new_value); } -int32_t afsk_bw() { - afsk_bw_range.reset_if_outside(data->afsk_bw, afsk_bw_reset_value); - return data->afsk_bw; +int32_t modem_bw() { + modem_bw_range.reset_if_outside(data->modem_bw, modem_bw_reset_value); + return data->modem_bw; } -void set_afsk_bw(const int32_t new_value) { - data->afsk_bw = afsk_bw_range.clip(new_value); +void set_modem_bw(const int32_t new_value) { + data->modem_bw = modem_bw_range.clip(new_value); } -uint32_t afsk_config() { - return data->afsk_config; +uint8_t modem_repeat() { + modem_repeat_range.reset_if_outside(data->modem_repeat, modem_repeat_reset_value); + return data->modem_repeat; } -uint8_t afsk_format() { - return ((data->afsk_config >> 16) & 3); +void set_modem_repeat(const uint32_t new_value) { + data->modem_repeat = modem_repeat_range.clip(new_value); } -uint8_t afsk_repeats() { - return (data->afsk_config >> 24); +serial_format_t serial_format() { + return data->serial_format; } -void set_afsk_config(const uint32_t new_value) { - data->afsk_config = new_value; +void set_serial_format(const serial_format_t new_value) { + data->serial_format = new_value; } static constexpr uint32_t playdead_magic = 0x88d3bb57; @@ -241,12 +248,20 @@ void set_ui_config(const uint32_t new_value) { data->ui_config = new_value; } -uint32_t pocsag_address() { - return data->pocsag_address; +uint32_t pocsag_last_address() { + return data->pocsag_last_address; } -void set_pocsag_address(uint32_t address) { - data->pocsag_address = address; +void set_pocsag_last_address(uint32_t address) { + data->pocsag_last_address = address; +} + +uint32_t pocsag_ignore_address() { + return data->pocsag_ignore_address; +} + +void set_pocsag_ignore_address(uint32_t address) { + data->pocsag_ignore_address = address; } } /* namespace persistent_memory */ diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 5471cd7b..ec1a9540 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -27,6 +27,9 @@ #include "rf_path.hpp" #include "touch.hpp" +#include "modems.hpp" + +using namespace modems; namespace portapack { namespace persistent_memory { @@ -42,22 +45,22 @@ void set_correction_ppb(const ppb_t new_value); void set_touch_calibration(const touch::Calibration& new_value); const touch::Calibration& touch_calibration(); +serial_format_t serial_format(); +void set_serial_format(const serial_format_t new_value); + int32_t afsk_mark_freq(); void set_afsk_mark(const int32_t new_value); int32_t afsk_space_freq(); void set_afsk_space(const int32_t new_value); -int32_t afsk_bitrate(); -void set_afsk_bitrate(const int32_t new_value); +int32_t modem_baudrate(); +void set_modem_baudrate(const int32_t new_value); -uint32_t afsk_config(); -uint8_t afsk_format(); -uint8_t afsk_repeats(); -void set_afsk_config(const uint32_t new_value); - -int32_t afsk_bw(); -void set_afsk_bw(const int32_t new_value); +uint8_t modem_repeat(); +void set_modem_repeat(const uint32_t new_value); +int32_t modem_bw(); +void set_modem_bw(const int32_t new_value); uint32_t playing_dead(); void set_playing_dead(const uint32_t new_value); @@ -76,8 +79,11 @@ uint16_t ui_config_bloff(); uint8_t ui_config_textentry(); void set_config_textentry(uint8_t new_value); -uint32_t pocsag_address(); -void set_pocsag_address(uint32_t address); +uint32_t pocsag_last_address(); +void set_pocsag_last_address(uint32_t address); + +uint32_t pocsag_ignore_address(); +void set_pocsag_ignore_address(uint32_t address); } /* namespace persistent_memory */ } /* namespace portapack */ diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index 8288b4af..7586fdca 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ