POCSAG RX saves ignored address

Made AFSK code more generic (not tied to LCR)
Added modem presets and more options in AFSK setup
String-ized and simplified LCR UI code
Simplified AFSK baseband code, made to always work on 16bit words
This commit is contained in:
furrtek 2017-04-21 06:22:31 +01:00
parent eff96276c3
commit 90feadd9f5
28 changed files with 423 additions and 423 deletions

View File

@ -140,7 +140,7 @@ set(CPPSRC
protocols/dcs.cpp protocols/dcs.cpp
protocols/lcr.cpp protocols/lcr.cpp
protocols/rds.cpp protocols/rds.cpp
afsk.cpp modems.cpp
audio.cpp audio.cpp
${COMMON}/bch_code.cpp ${COMMON}/bch_code.cpp
ctcss.cpp ctcss.cpp
@ -183,7 +183,7 @@ set(CPPSRC
ui_record_view.cpp ui_record_view.cpp
ui_replay_view.cpp ui_replay_view.cpp
ui_rssi.cpp ui_rssi.cpp
ui_script.cpp # ui_script.cpp
ui_sd_card_status_view.cpp ui_sd_card_status_view.cpp
ui_sd_wipe.cpp ui_sd_wipe.cpp
# ui_sd_card_debug.cpp # ui_sd_card_debug.cpp

View File

@ -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 */

View File

@ -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, 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 { const AFSKConfigureMessage message {
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_alt_format symbol_count
}; };
send_message(&message); send_message(&message);
} }

View File

@ -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_fifo_data(const int8_t * data);
void set_pwmrssi(int32_t avg, bool enabled); 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, 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 kill_afsk();
void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const 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 uint32_t pause_symbols);

View File

@ -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 */

View File

@ -24,38 +24,65 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#ifndef __AFSK_H__ #ifndef __MODEMS_H__
#define __AFSK_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, NONE = 0,
EVEN, EVEN = 1,
ODD ODD = 2
}; };
struct afsk_formats_t { enum order_enum : uint8_t {
std::string fullname; MSB_FIRST = 0,
std::string shortname; LSB_FIRST = 1
};
struct serial_format_t {
uint8_t data_bits; uint8_t data_bits;
parity_enum parity; parity_enum parity;
uint8_t stop_bits; uint8_t stop_bits;
bool MSB_first; order_enum bit_order;
bool use_LUT;
}; };
const afsk_formats_t afsk_formats[4] = { uint8_t symbol_count();
{ "7-Even-1 R", "7E1", 7, EVEN, 1, false, false },
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 }, { "7E1 LUT ", "7Ea", 7, EVEN, 1, true, true },
{ "7-Odd-1 ", "7o1", 7, ODD, 1, true, false }, { "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__*/

View File

@ -67,6 +67,7 @@ void POCSAGAppView::update_freq(rf::Frequency f) {
} }
POCSAGAppView::POCSAGAppView(NavigationView& nav) { POCSAGAppView::POCSAGAppView(NavigationView& nav) {
uint32_t ignore_address;
baseband::run_image(portapack::spi_flash::image_tag_pocsag); 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) { check_ignore.on_select = [this](Checkbox&, bool v) {
ignore = 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&) { button_setfreq.on_select = [this,&nav](Button&) {
auto new_view = nav.push<FrequencyKeypadView>(target_frequency_); auto new_view = nav.push<FrequencyKeypadView>(target_frequency_);
@ -126,6 +131,10 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
} }
POCSAGAppView::~POCSAGAppView() { POCSAGAppView::~POCSAGAppView() {
// Save ignored address
persistent_memory::set_pocsag_ignore_address(sym_ignore.value_dec_u32());
receiver_model.disable(); receiver_model.disable();
baseband::shutdown(); baseband::shutdown();
} }
@ -162,7 +171,7 @@ void POCSAGAppView::on_packet(const POCSAGPacketMessage * message) {
console_info += " F" + to_string_dec_uint(pocsag_state.function); console_info += " F" + to_string_dec_uint(pocsag_state.function);
// Store last received address for POCSAG TX // 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) { if (pocsag_state.out_type == ADDRESS) {
// Address only // Address only

View File

@ -59,8 +59,6 @@ public:
private: private:
static constexpr uint32_t initial_target_frequency = 466175000; 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 logging { true };
bool ignore { false }; bool ignore { false };

View File

@ -23,8 +23,6 @@
#include "lcr.hpp" #include "lcr.hpp"
#include "string_format.hpp" #include "string_format.hpp"
//#include "portapack_persistent_memory.hpp"
namespace lcr { namespace lcr {
std::string generate_message(std::string rgsb, std::vector<std::string> litterals, size_t option_ec) { std::string generate_message(std::string rgsb, std::vector<std::string> litterals, size_t option_ec) {

View File

@ -67,13 +67,13 @@ ReplayThread::~ReplayThread() {
msg_t ReplayThread::static_fn(void* arg) { msg_t ReplayThread::static_fn(void* arg) {
auto obj = static_cast<ReplayThread*>(arg); auto obj = static_cast<ReplayThread*>(arg);
const auto error = obj->run(); const auto error = obj->run();
/*if( error.is_valid() && obj->error_callback ) { if( error.is_valid() && obj->error_callback ) {
obj->error_callback(error.value()); obj->error_callback(error.value());
} else { } else {
if( obj->success_callback ) { if( obj->success_callback ) {
obj->success_callback(); obj->success_callback();
} }
}*/ }
return 0; return 0;
} }
@ -82,14 +82,13 @@ Optional<File::Error> ReplayThread::run() {
BufferExchange buffers { &config }; BufferExchange buffers { &config };
while( !chThdShouldTerminate() ) { while( !chThdShouldTerminate() ) {
//auto buffer = buffers.get(); auto buffer = buffers.get();
buffers.get();
/*auto read_result = reader->read(buffer->data(), buffer->size()); /*auto read_result = reader->read(buffer->data(), buffer->size());
if( read_result.is_error() ) { if( read_result.is_error() ) {
return read_result.error(); return read_result.error();
} }
buffers.put(buffer);*/ buffers.put(buffer);*/
chThdSleep(50); chThdSleep(50); // DEBUG
//led_tx.toggle(); //led_tx.toggle();
} }

View File

@ -33,7 +33,7 @@
#include <stdio.h> #include <stdio.h>
using namespace portapack; using namespace portapack;
using namespace afsk; using namespace modems;
namespace ui { namespace ui {
@ -42,18 +42,14 @@ void AFSKSetupView::focus() {
} }
void AFSKSetupView::update_freq(rf::Frequency f) { 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); final_str = 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 / 100) % 10000, 4, '0');
strcat(finalstr, mhz.c_str()); button_setfreq.set_text(final_str);
strcat(finalstr, ".");
strcat(finalstr, hz100.c_str());
this->button_setfreq.set_text(finalstr);
} }
AFSKSetupView::AFSKSetupView( AFSKSetupView::AFSKSetupView(
@ -64,57 +60,81 @@ AFSKSetupView::AFSKSetupView(
using value_t = int32_t; using value_t = int32_t;
using option_t = std::pair<name_t, value_t>; using option_t = std::pair<name_t, value_t>;
using options_t = std::vector<option_t>; using options_t = std::vector<option_t>;
options_t format_options; options_t modem_options;
uint8_t rpt;
size_t i; size_t i;
add_children({ add_children({
&labels, &labels,
&button_setfreq, &button_setfreq,
&options_bps, &field_baudrate,
&field_mark, &field_mark,
&field_space, &field_space,
&field_bw, &field_bw,
&field_repeat, &field_repeat,
&options_format, &options_modem,
&button_set_modem,
&sym_format,
&button_save &button_save
}); });
for (i = 0; i < AFSK_MODES_COUNT; i++) for (i = 0; i < MODEM_DEF_COUNT; i++) {
format_options.emplace_back(std::make_pair(afsk_formats[i].fullname, 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_modem.set_options(modem_options);
options_format.set_selected_index(portapack::persistent_memory::afsk_format()); 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); sym_format.set_sym(0, persistent_memory::serial_format().data_bits - 6);
field_space.set_value(portapack::persistent_memory::afsk_space_freq() * 25); sym_format.set_sym(1, persistent_memory::serial_format().parity);
field_bw.set_value(portapack::persistent_memory::afsk_bw()); sym_format.set_sym(2, persistent_memory::serial_format().stop_bits);
rpt = portapack::persistent_memory::afsk_repeats(); sym_format.set_sym(3, persistent_memory::serial_format().bit_order);
if ((rpt > 99) || (!rpt)) rpt = 5;
field_repeat.set_value(rpt);
button_setfreq.on_select = [this,&nav](Button&) { update_freq(persistent_memory::tuned_frequency());
auto new_view = nav.push<FrequencyKeypadView>(portapack::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<FrequencyKeypadView>(persistent_memory::tuned_frequency());
new_view->on_changed = [this](rf::Frequency f) { new_view->on_changed = [this](rf::Frequency f) {
update_freq(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&) { 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()); persistent_memory::set_afsk_mark(field_mark.value());
portapack::persistent_memory::set_afsk_mark(field_mark.value() / 25); persistent_memory::set_afsk_space(field_space.value());
portapack::persistent_memory::set_afsk_space(field_space.value() / 25);
portapack::persistent_memory::set_afsk_bw(field_bw.value());
afsk_config |= (options_format.selected_index() << 16); persistent_memory::set_modem_baudrate(field_baudrate.value());
afsk_config |= (field_repeat.value() << 24); persistent_memory::set_modem_bw(field_bw.value() * 1000);
portapack::persistent_memory::set_afsk_config(afsk_config); 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(); nav.pop();
}; };

View File

@ -20,7 +20,7 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#include "afsk.hpp" #include "modems.hpp"
#include "ui.hpp" #include "ui.hpp"
#include "ui_widget.hpp" #include "ui_widget.hpp"
@ -40,30 +40,27 @@ private:
void update_freq(rf::Frequency f); void update_freq(rf::Frequency f);
Labels labels { Labels labels {
{ { 1 * 8, 4 * 8 }, "Frequency:", Color::light_grey() }, { { 2 * 8, 4 * 8 }, "Frequency:", Color::light_grey() },
{ { 16 * 8, 5 * 8 }, "Speed:", Color::light_grey() }, { { 2 * 8, 11 * 8 }, "Speed: Bps", Color::light_grey() },
{ { 2 * 8, 13 * 8 }, "Mark: Hz", Color::light_grey() }, { { 2 * 8, 13 * 8 }, "Mark: Hz", Color::light_grey() },
{ { 2 * 8, 15 * 8 }, "Space: Hz", Color::light_grey() }, { { 2 * 8, 15 * 8 }, "Space: Hz", Color::light_grey() },
{ { 140, 13 * 8 }, "BW: kHz", Color::light_grey() }, { { 140, 13 * 8 }, "BW: kHz", Color::light_grey() },
{ { 140, 15 * 8 }, "Repeat:", 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 { Button button_setfreq {
{ 8, 48, 104, 32 }, { 13 * 8, 3 * 8, 12 * 8, 32 },
"----.----" "----.----"
}; };
OptionsField options_bps { NumberField field_baudrate {
{ 128, 60 }, { 64, 88 },
7, 5,
{ { 50, 9600 },
{ "600bps ", 600 }, 25,
{ "1200bps", 1200 }, ' '
{ "2400bps", 2400 },
{ "4800bps", 4800 },
{ "9600bps", 9600 }
}
}; };
NumberField field_mark { NumberField field_mark {
@ -98,13 +95,24 @@ private:
' ' ' '
}; };
OptionsField options_format { OptionsField options_modem {
{ 80, 152 }, { 16 * 8, 19 * 8 },
10, 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 { Button button_save {
{ 72, 250, 96, 40 }, { 72, 250, 96, 40 },
"Save" "Save"

View File

@ -24,7 +24,7 @@
#include "ui_afsksetup.hpp" #include "ui_afsksetup.hpp"
#include "ui_debug.hpp" #include "ui_debug.hpp"
#include "afsk.hpp" #include "modems.hpp"
#include "lcr.hpp" #include "lcr.hpp"
#include "baseband_api.hpp" #include "baseband_api.hpp"
#include "string_format.hpp" #include "string_format.hpp"
@ -35,7 +35,7 @@
#include <stdio.h> #include <stdio.h>
using namespace portapack; using namespace portapack;
using namespace afsk; using namespace modems;
namespace ui { namespace ui {
@ -49,7 +49,7 @@ LCRView::~LCRView() {
} }
void LCRView::paint(Painter& painter) { void LCRView::paint(Painter& painter) {
uint8_t i; size_t i;
std::string final_str; std::string final_str;
static constexpr Style style_orange { static constexpr Style style_orange {
@ -75,11 +75,11 @@ void LCRView::paint(Painter& painter) {
button_setrgsb.set_text(rgsb); button_setrgsb.set_text(rgsb);
// Recap: freq @ bps // 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 += '@';
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 += "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); text_recap.set(final_str);
} }
@ -95,25 +95,18 @@ std::vector<std::string> LCRView::parse_litterals() {
} }
void LCRView::update_progress() { void LCRView::update_progress() {
char str[16]; std::string progress_str;
text_status.set(" "); text_status.set(" "); // Clear
if (tx_mode == SINGLE) { if (tx_mode == SINGLE) {
strcpy(str, to_string_dec_uint(repeat_index).c_str()); progress_str = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(persistent_memory::modem_repeat());
strcat(str, "/"); text_status.set(progress_str);
strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str());
text_status.set(str);
progress.set_value(repeat_index); progress.set_value(repeat_index);
} else if (tx_mode == SCAN) { } else if (tx_mode == SCAN) {
strcpy(str, to_string_dec_uint(repeat_index).c_str()); progress_str = to_string_dec_uint(repeat_index) + "/" + to_string_dec_uint(persistent_memory::modem_repeat());
strcat(str, "/"); progress_str += " " + to_string_dec_uint(scan_index + 1) + "/" + to_string_dec_uint(scan_count);
strcat(str, to_string_dec_uint(portapack::persistent_memory::afsk_repeats()).c_str()); text_status.set(progress_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.set_value(scan_progress); progress.set_value(scan_progress);
} else { } else {
text_status.set("Ready"); text_status.set("Ready");
@ -153,10 +146,9 @@ void LCRView::on_txdone(int n) {
} }
void LCRView::start_tx(const bool scan) { void LCRView::start_tx(const bool scan) {
uint8_t afsk_format; uint8_t repeats;
uint8_t afsk_repeats;
afsk_repeats = portapack::persistent_memory::afsk_repeats(); repeats = persistent_memory::modem_repeat();
if (scan) { if (scan) {
if (tx_mode != SCAN) { if (tx_mode != SCAN) {
@ -166,35 +158,20 @@ void LCRView::start_tx(const bool scan) {
repeat_index = 1; repeat_index = 1;
tx_mode = SCAN; tx_mode = SCAN;
rgsb = scan_list[options_scanlist.selected_index()].addresses[0]; rgsb = scan_list[options_scanlist.selected_index()].addresses[0];
progress.set_max(scan_count * afsk_repeats); progress.set_max(scan_count * repeats);
update_progress(); update_progress();
} }
} else { } else {
tx_mode = SINGLE; tx_mode = SINGLE;
repeat_index = 1; repeat_index = 1;
progress.set_max(afsk_repeats); progress.set_max(repeats);
update_progress(); update_progress();
} }
button_setrgsb.set_text(rgsb); 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()) { transmitter_model.set_tuning_frequency(persistent_memory::tuned_frequency());
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_sampling_rate(1536000U); transmitter_model.set_sampling_rate(1536000U);
transmitter_model.set_rf_amp(true); transmitter_model.set_rf_amp(true);
transmitter_model.set_baseband_bandwidth(1750000); 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); memcpy(shared_memory.bb_data.data, lcr_message_data, 300);
baseband::set_afsk_data( baseband::set_afsk_data(
(153600 * 5) / portapack::persistent_memory::afsk_bitrate(), 1536000 / persistent_memory::modem_baudrate(),
portapack::persistent_memory::afsk_mark_freq() * 437 * 5, // (0x40000 * 256) / (153600 / 25), persistent_memory::afsk_mark_freq(),
portapack::persistent_memory::afsk_space_freq() * 437 * 5, // (0x40000 * 256) / (153600 / 25), persistent_memory::afsk_space_freq(),
afsk_repeats, repeats,
portapack::persistent_memory::afsk_bw() * 115, // See proc_afsk.cpp persistent_memory::modem_bw(),
afsk_format modems::symbol_count()
); );
} }

View File

@ -84,7 +84,7 @@ private:
std::string litteral[5] { " " }; std::string litteral[5] { " " };
std::string rgsb { " " }; std::string rgsb { " " };
char lcr_message[512]; char lcr_message[512];
char lcr_message_data[512]; uint16_t lcr_message_data[256];
rf::Frequency f { 0 }; rf::Frequency f { 0 };
uint8_t repeat_index { 0 }; uint8_t repeat_index { 0 };

View File

@ -361,7 +361,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
{ "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } }, { "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } },
{ "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push<ReceiverMenuView>(); } }, { "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push<ReceiverMenuView>(); } },
{ "Capture", ui::Color::blue(), &bitmap_icon_capture, [&nav](){ nav.push<CaptureAppView>(); } }, { "Capture", ui::Color::blue(), &bitmap_icon_capture, [&nav](){ nav.push<CaptureAppView>(); } },
{ "Replay", ui::Color::blue(), &bitmap_icon_replay, [&nav](){ nav.push<ReplayAppView>(); } }, // ReplayAppView { "Replay", ui::Color::grey(), &bitmap_icon_replay, [&nav](){ nav.push<NotImplementedView>(); } }, // ReplayAppView
{ "Audio transmitters", ui::Color::green(), &bitmap_icon_audiotx, [&nav](){ nav.push<TransmitterAudioMenuView>(); } }, { "Audio transmitters", ui::Color::green(), &bitmap_icon_audiotx, [&nav](){ nav.push<TransmitterAudioMenuView>(); } },
{ "Code transmitters", ui::Color::green(), &bitmap_icon_codetx, [&nav](){ nav.push<TransmitterCodedMenuView>(); } }, { "Code transmitters", ui::Color::green(), &bitmap_icon_codetx, [&nav](){ nav.push<TransmitterCodedMenuView>(); } },
{ "SSTV transmitter", ui::Color::dark_green(), &bitmap_icon_sstv, [&nav](){ nav.push<SSTVTXView>(); } }, { "SSTV transmitter", ui::Color::dark_green(), &bitmap_icon_sstv, [&nav](){ nav.push<SSTVTXView>(); } },

View File

@ -151,7 +151,7 @@ POCSAGTXView::POCSAGTXView(
options_type.set_selected_index(0); // Address only options_type.set_selected_index(0); // Address only
// TODO: set_value for whole symfield // 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++) { for (c = 0; c < 7; c++) {
field_address.set_sym(6 - c, reload_address % 10); field_address.set_sym(6 - c, reload_address % 10);
reload_address /= 10; reload_address /= 10;

View File

@ -35,88 +35,60 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
for (size_t i = 0; i<buffer.count; i++) { for (size_t i = 0; i<buffer.count; i++) {
// Tone synthesis at 2.28M/10 = 228kHz if (sample_count >= afsk_samples_per_bit) {
if (s >= (5 - 1)) { if (configured) {
s = 0; cur_word = *word_ptr;
if (sample_count >= afsk_samples_per_bit) { if (!cur_word) {
if (configured) { // End of data
cur_byte = shared_memory.bb_data.data[byte_pos]; if (repeat_counter < afsk_repeat) {
ext_byte = shared_memory.bb_data.data[byte_pos + 1]; // Repeat
bit_pos = 0;
if (!(cur_byte | ext_byte)) { word_ptr = (uint16_t*)shared_memory.bb_data.data;
// End of data cur_word = *word_ptr;
if (repeat_counter < afsk_repeat) { message.progress = repeat_counter + 1;
// Repeat shared_memory.application_queue.push(message);
bit_pos = 0; repeat_counter++;
byte_pos = 0; } else {
cur_byte = shared_memory.bb_data.data[0]; // Stop
ext_byte = shared_memory.bb_data.data[1]; cur_word = 0;
message.progress = repeat_counter + 1; message.progress = 0;
shared_memory.application_queue.push(message); shared_memory.application_queue.push(message);
repeat_counter++; configured = false;
} else {
// Stop
cur_byte = 0;
ext_byte = 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; cur_bit = (cur_word >> (symbol_count - bit_pos)) & 1;
else
tone_phase += afsk_phase_inc_space; if (bit_pos >= symbol_count) {
bit_pos = 0;
word_ptr++;
} else {
bit_pos++;
}
sample_count = 0;
} else { } 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 & 0xFF000000U) >> 24];
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);
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]); delta = tone_sample * fm_delta;
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
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.id == Message::ID::AFSKConfigure) {
if (message.samples_per_bit) { if (message.samples_per_bit) {
afsk_samples_per_bit = message.samples_per_bit; afsk_samples_per_bit = message.samples_per_bit;
afsk_phase_inc_mark = message.phase_inc_mark; afsk_phase_inc_mark = message.phase_inc_mark * AFSK_DELTA_COEF;
afsk_phase_inc_space = message.phase_inc_space; afsk_phase_inc_space = message.phase_inc_space * AFSK_DELTA_COEF;
afsk_repeat = message.repeat - 1; afsk_repeat = message.repeat - 1;
afsk_bw = message.bw; fm_delta = message.fm_delta * (0xFFFFFFULL / 1536000);
afsk_format = message.format; symbol_count = message.symbol_count - 1;
s = 0;
sample_count = afsk_samples_per_bit; sample_count = afsk_samples_per_bit;
repeat_counter = 0; repeat_counter = 0;
bit_pos = 0; bit_pos = 0;
byte_pos = 0; word_ptr = (uint16_t*)shared_memory.bb_data.data;
cur_byte = 0; cur_word = 0;
ext_byte = 0;
cur_bit = 0; cur_bit = 0;
configured = true; configured = true;
} else } else

View File

@ -26,6 +26,9 @@
#include "baseband_processor.hpp" #include "baseband_processor.hpp"
#include "baseband_thread.hpp" #include "baseband_thread.hpp"
#define AFSK_SAMPLERATE 1536000
#define AFSK_DELTA_COEF ((1ULL << 32) / AFSK_SAMPLERATE)
class AFSKProcessor : public BasebandProcessor { class AFSKProcessor : public BasebandProcessor {
public: public:
void execute(const buffer_c8_t& buffer) override; 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_mark { 0 };
uint32_t afsk_phase_inc_space { 0 }; uint32_t afsk_phase_inc_space { 0 };
uint8_t afsk_repeat { 0 }; uint8_t afsk_repeat { 0 };
uint32_t afsk_bw { 0 }; uint32_t fm_delta { 0 };
uint8_t afsk_format { 0 }; uint8_t symbol_count { 0 };
uint8_t repeat_counter { 0 }; uint8_t repeat_counter { 0 };
int8_t re { 0 }, im { 0 };
uint8_t s { 0 };
uint8_t bit_pos { 0 }; uint8_t bit_pos { 0 };
uint16_t byte_pos { 0 }; uint16_t * word_ptr { };
char cur_byte { 0 }; uint16_t cur_word { 0 };
char ext_byte { 0 };
uint16_t gbyte { 0 };
uint8_t cur_bit { 0 }; uint8_t cur_bit { 0 };
uint32_t sample_count { 0 }; uint32_t sample_count { 0 };
uint32_t tone_phase { 0 }, phase { 0 }, sphase { 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 { }; TXDoneMessage message { };
}; };

View File

@ -22,8 +22,6 @@
#include "proc_replay.hpp" #include "proc_replay.hpp"
//#include "dsp_fir_taps.hpp"
#include "event_m4.hpp" #include "event_m4.hpp"
#include "utility.hpp" #include "utility.hpp"
@ -34,16 +32,12 @@ ReplayProcessor::ReplayProcessor() {
void ReplayProcessor::execute(const buffer_c8_t& buffer) { void ReplayProcessor::execute(const buffer_c8_t& buffer) {
/* 2.4576MHz, 2048 samples */ /* 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; size_t pos = 0;
for (size_t c = 0; c < 4; c++) { for (size_t c = 0; c < 4; c++) {
if( stream ) { 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); 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++) { 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 }; buffer.p[pos] = { iq_buffer.p[i].real() >> 8, iq_buffer.p[i].imag() >> 8 };
pos++; pos++;
//buffer.p[i] = { iq_buffer.p[i].real(), iq_buffer.p[i].imag() };
} }
} }

View File

@ -25,11 +25,6 @@
#include "baseband_processor.hpp" #include "baseband_processor.hpp"
#include "baseband_thread.hpp" #include "baseband_thread.hpp"
//#include "rssi_thread.hpp"
//#include "dsp_decimate.hpp"
//#include "spectrum_collector.hpp"
#include "stream_output.hpp" #include "stream_output.hpp"
@ -52,7 +47,7 @@ private:
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit }; BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit };
//RSSIThread rssi_thread { NORMALPRIO + 10 }; //RSSIThread rssi_thread { NORMALPRIO + 10 };
std::array<complex16_t, 512> iq { }; // 2048 std::array<complex16_t, 512> iq { }; // 2048 doesn't fit in allocated RAM
const buffer_c16_t iq_buffer { const buffer_c16_t iq_buffer {
iq.data(), iq.data(),
iq.size() iq.size()

View File

@ -48,7 +48,7 @@ size_t StreamOutput::read(void* const data, const size_t length) {
if( !active_buffer ) { if( !active_buffer ) {
// We need a full buffer... // We need a full buffer...
if( !fifo_buffers_full.out(active_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; break;
} }
} }
@ -59,11 +59,12 @@ size_t StreamOutput::read(void* const data, const size_t length) {
if( active_buffer->is_empty() ) { if( active_buffer->is_empty() ) {
if( !fifo_buffers_empty.in(active_buffer) ) { if( !fifo_buffers_empty.in(active_buffer) ) {
// FIFO is completly empty. // Empty buffers FIFO is already full.
// Bail out of the loop, and try retrieving the buffer in the // This should never happen if the number of buffers is less
// next pass. // than the capacity of the FIFO.
break; break;
} }
// Tell M0 (IRQ) that a buffer has been consumed.
active_buffer = nullptr; active_buffer = nullptr;
creg::m4txevent::assert(); creg::m4txevent::assert();
} }

View File

@ -32,7 +32,7 @@ BufferExchange::BufferExchange(
) // : config_capture { config } ) // : config_capture { config }
{ {
obj = this; 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_baseband = config->fifo_buffers_empty;
fifo_buffers_for_application = config->fifo_buffers_full; fifo_buffers_for_application = config->fifo_buffers_full;
} }
@ -42,7 +42,7 @@ BufferExchange::BufferExchange(
) // : config_replay { config } ) // : config_replay { config }
{ {
obj = this; 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_baseband = config->fifo_buffers_full;
fifo_buffers_for_application = config->fifo_buffers_empty; fifo_buffers_for_application = config->fifo_buffers_empty;
} }
@ -56,14 +56,15 @@ BufferExchange::~BufferExchange() {
StreamBuffer* BufferExchange::get(FIFO<StreamBuffer*>* fifo) { StreamBuffer* BufferExchange::get(FIFO<StreamBuffer*>* fifo) {
while(true) { while(true) {
StreamBuffer* p { nullptr }; StreamBuffer* p { nullptr };
fifo->out(p); fifo->out(p); // This crashes replay
led_tx.on(); // DEBUG //led_tx.on(); // DEBUG
if( p ) { if( p ) {
return p; return p;
} }
// Put thread to sleep, woken up by M4 IRQ
chSysLock(); chSysLock();
thread = chThdSelf(); thread = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED); chSchGoSleepS(THD_STATE_SUSPENDED);

View File

@ -86,12 +86,8 @@ private:
} direction { }; } direction { };
void check_fifo_isr() { void check_fifo_isr() {
//if (!empty() && (direction == CAPTURE)) {
if (!empty()) if (!empty())
wakeup_isr(); wakeup_isr();
//} else if (!empty() && (direction == REPLAY)) {
// wakeup_isr();
//}
} }
void wakeup_isr() { void wakeup_isr() {

View File

@ -111,9 +111,9 @@ public:
return false; return false;
} }
val = _data[_out & mask()]; val = _data[_out & mask()]; // Crashes
smp_wmb(); smp_wmb(); // Ok
_out += 1; _out += 1; // Crashes
return true; return true;
} }

View File

@ -683,15 +683,15 @@ public:
const uint32_t phase_inc_mark, const uint32_t phase_inc_mark,
const uint32_t phase_inc_space, const uint32_t phase_inc_space,
const uint8_t repeat, const uint8_t repeat,
const uint32_t bw, const uint32_t fm_delta,
const uint8_t format const uint8_t symbol_count
) : Message { ID::AFSKConfigure }, ) : Message { ID::AFSKConfigure },
samples_per_bit(samples_per_bit), samples_per_bit(samples_per_bit),
phase_inc_mark(phase_inc_mark), phase_inc_mark(phase_inc_mark),
phase_inc_space(phase_inc_space), phase_inc_space(phase_inc_space),
repeat(repeat), repeat(repeat),
bw(bw), fm_delta(fm_delta),
format(format) symbol_count(symbol_count)
{ {
} }
@ -699,8 +699,8 @@ public:
const uint32_t phase_inc_mark; const uint32_t phase_inc_mark;
const uint32_t phase_inc_space; const uint32_t phase_inc_space;
const uint8_t repeat; const uint8_t repeat;
const uint32_t bw; const uint32_t fm_delta;
const uint8_t format; const uint8_t symbol_count;
}; };
class OOKConfigureMessage : public Message { class OOKConfigureMessage : public Message {

View File

@ -44,17 +44,21 @@ constexpr ppb_range_t ppb_range { -99000, 99000 };
constexpr ppb_t ppb_reset_value { 0 }; constexpr ppb_t ppb_reset_value { 0 };
using afsk_freq_range_t = range_t<int32_t>; using afsk_freq_range_t = range_t<int32_t>;
constexpr afsk_freq_range_t afsk_freq_range { 1, 400 }; constexpr afsk_freq_range_t afsk_freq_range { 1, 4000 };
constexpr int32_t afsk_mark_reset_value { 48 }; constexpr int32_t afsk_mark_reset_value { 1200 };
constexpr int32_t afsk_space_reset_value { 88 }; constexpr int32_t afsk_space_reset_value { 2200 };
using afsk_bitrate_range_t = range_t<int32_t>; using modem_baudrate_range_t = range_t<int32_t>;
constexpr afsk_bitrate_range_t afsk_bitrate_range { 600, 9600 }; constexpr modem_baudrate_range_t modem_baudrate_range { 50, 9600 };
constexpr int32_t afsk_bitrate_reset_value { 1200 }; constexpr int32_t modem_baudrate_reset_value { 1200 };
using afsk_bw_range_t = range_t<int32_t>; using modem_bw_range_t = range_t<int32_t>;
constexpr afsk_bw_range_t afsk_bw_range { 1, 50 }; constexpr modem_bw_range_t modem_bw_range { 1000, 50000 };
constexpr int32_t afsk_bw_reset_value { 15 }; constexpr int32_t modem_bw_reset_value { 15000 };
using modem_repeat_range_t = range_t<int32_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 must pack the same way on M4 and M0 cores. */
struct data_t { struct data_t {
@ -63,13 +67,14 @@ struct data_t {
uint32_t touch_calibration_magic; uint32_t touch_calibration_magic;
touch::Calibration touch_calibration; touch::Calibration touch_calibration;
// Modem
// AFSK modem uint32_t modem_def_index;
serial_format_t serial_format;
int32_t modem_bw;
int32_t afsk_mark_freq; int32_t afsk_mark_freq;
int32_t afsk_space_freq; // Todo: reduce size, only 256 bytes of NVRAM ! int32_t afsk_space_freq;
int32_t afsk_bitrate; int32_t modem_baudrate;
int32_t afsk_bw; int32_t modem_repeat;
uint32_t afsk_config;
// Play dead unlock // Play dead unlock
uint32_t playdead_magic; uint32_t playdead_magic;
@ -78,7 +83,8 @@ struct data_t {
uint32_t ui_config; 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"); 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); data->afsk_space_freq = afsk_freq_range.clip(new_value);
} }
int32_t afsk_bitrate() { int32_t modem_baudrate() {
afsk_bitrate_range.reset_if_outside(data->afsk_bitrate, afsk_bitrate_reset_value); modem_baudrate_range.reset_if_outside(data->modem_baudrate, modem_baudrate_reset_value);
return data->afsk_bitrate; return data->modem_baudrate;
} }
void set_afsk_bitrate(const int32_t new_value) { void set_modem_baudrate(const int32_t new_value) {
data->afsk_bitrate = afsk_bitrate_range.clip(new_value); data->modem_baudrate = modem_baudrate_range.clip(new_value);
} }
int32_t afsk_bw() { int32_t modem_bw() {
afsk_bw_range.reset_if_outside(data->afsk_bw, afsk_bw_reset_value); modem_bw_range.reset_if_outside(data->modem_bw, modem_bw_reset_value);
return data->afsk_bw; return data->modem_bw;
} }
void set_afsk_bw(const int32_t new_value) { void set_modem_bw(const int32_t new_value) {
data->afsk_bw = afsk_bw_range.clip(new_value); data->modem_bw = modem_bw_range.clip(new_value);
} }
uint32_t afsk_config() { uint8_t modem_repeat() {
return data->afsk_config; modem_repeat_range.reset_if_outside(data->modem_repeat, modem_repeat_reset_value);
return data->modem_repeat;
} }
uint8_t afsk_format() { void set_modem_repeat(const uint32_t new_value) {
return ((data->afsk_config >> 16) & 3); data->modem_repeat = modem_repeat_range.clip(new_value);
} }
uint8_t afsk_repeats() { serial_format_t serial_format() {
return (data->afsk_config >> 24); return data->serial_format;
} }
void set_afsk_config(const uint32_t new_value) { void set_serial_format(const serial_format_t new_value) {
data->afsk_config = new_value; data->serial_format = new_value;
} }
static constexpr uint32_t playdead_magic = 0x88d3bb57; 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; data->ui_config = new_value;
} }
uint32_t pocsag_address() { uint32_t pocsag_last_address() {
return data->pocsag_address; return data->pocsag_last_address;
} }
void set_pocsag_address(uint32_t address) { void set_pocsag_last_address(uint32_t address) {
data->pocsag_address = 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 */ } /* namespace persistent_memory */

View File

@ -27,6 +27,9 @@
#include "rf_path.hpp" #include "rf_path.hpp"
#include "touch.hpp" #include "touch.hpp"
#include "modems.hpp"
using namespace modems;
namespace portapack { namespace portapack {
namespace persistent_memory { 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); void set_touch_calibration(const touch::Calibration& new_value);
const touch::Calibration& touch_calibration(); 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(); int32_t afsk_mark_freq();
void set_afsk_mark(const int32_t new_value); void set_afsk_mark(const int32_t new_value);
int32_t afsk_space_freq(); int32_t afsk_space_freq();
void set_afsk_space(const int32_t new_value); void set_afsk_space(const int32_t new_value);
int32_t afsk_bitrate(); int32_t modem_baudrate();
void set_afsk_bitrate(const int32_t new_value); void set_modem_baudrate(const int32_t new_value);
uint32_t afsk_config(); uint8_t modem_repeat();
uint8_t afsk_format(); void set_modem_repeat(const uint32_t new_value);
uint8_t afsk_repeats(); int32_t modem_bw();
void set_afsk_config(const uint32_t new_value); void set_modem_bw(const int32_t new_value);
int32_t afsk_bw();
void set_afsk_bw(const int32_t new_value);
uint32_t playing_dead(); uint32_t playing_dead();
void set_playing_dead(const uint32_t new_value); void set_playing_dead(const uint32_t new_value);
@ -76,8 +79,11 @@ uint16_t ui_config_bloff();
uint8_t ui_config_textentry(); uint8_t ui_config_textentry();
void set_config_textentry(uint8_t new_value); void set_config_textentry(uint8_t new_value);
uint32_t pocsag_address(); uint32_t pocsag_last_address();
void set_pocsag_address(uint32_t 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 persistent_memory */
} /* namespace portapack */ } /* namespace portapack */

Binary file not shown.