mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-13 19:54:39 +00:00
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:
parent
eff96276c3
commit
90feadd9f5
@ -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
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
93
firmware/application/modems.cpp
Normal file
93
firmware/application/modems.cpp
Normal 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 */
|
@ -24,38 +24,65 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#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__*/
|
@ -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<FrequencyKeypadView>(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
|
||||
|
@ -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 };
|
||||
|
@ -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<std::string> litterals, size_t option_ec) {
|
||||
|
@ -67,13 +67,13 @@ ReplayThread::~ReplayThread() {
|
||||
msg_t ReplayThread::static_fn(void* arg) {
|
||||
auto obj = static_cast<ReplayThread*>(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<File::Error> 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();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
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<name_t, value_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
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<FrequencyKeypadView>(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<FrequencyKeypadView>(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();
|
||||
};
|
||||
|
@ -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"
|
||||
|
@ -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 <stdio.h>
|
||||
|
||||
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<std::string> 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()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -361,7 +361,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
|
||||
{ "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } },
|
||||
{ "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push<ReceiverMenuView>(); } },
|
||||
{ "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>(); } },
|
||||
{ "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>(); } },
|
||||
|
@ -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;
|
||||
|
@ -35,88 +35,60 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
|
||||
// Tone synthesis at 2.28M/10 = 228kHz
|
||||
if (s >= (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
|
||||
|
@ -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 { };
|
||||
};
|
||||
|
@ -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() };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<complex16_t, 512> iq { }; // 2048
|
||||
std::array<complex16_t, 512> iq { }; // 2048 doesn't fit in allocated RAM
|
||||
const buffer_c16_t iq_buffer {
|
||||
iq.data(),
|
||||
iq.size()
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<StreamBuffer*>* 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);
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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<int32_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<int32_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<int32_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<int32_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<int32_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<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 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 */
|
||||
|
@ -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 */
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user