mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Started writing (copying...) AFSK RX
Encoders: removed bit duration setting (frame duration is more useful)
This commit is contained in:
parent
cd6a1a7f3f
commit
42439d1885
@ -163,8 +163,9 @@ set(CPPSRC
|
||||
ui_about.cpp
|
||||
ui_adsb_rx.cpp
|
||||
ui_adsb_tx.cpp
|
||||
ui_afsk_rx.cpp
|
||||
ui_alphanum.cpp
|
||||
ui_aprstx.cpp
|
||||
ui_aprs_tx.cpp
|
||||
ui_audio.cpp
|
||||
ui_baseband_stats_view.cpp
|
||||
ui_bht_tx.cpp
|
||||
|
@ -117,9 +117,16 @@ void set_sstv_data(const uint8_t vis_code, const uint32_t pixel_duration) {
|
||||
send_message(&message);
|
||||
}
|
||||
|
||||
void set_afsk(const uint32_t bitrate) {
|
||||
const AFSKRxConfigureMessage message {
|
||||
bitrate
|
||||
};
|
||||
send_message(&message);
|
||||
}
|
||||
|
||||
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 uint8_t symbol_count) {
|
||||
const AFSKConfigureMessage message {
|
||||
const AFSKTxConfigureMessage message {
|
||||
afsk_samples_per_bit,
|
||||
afsk_phase_inc_mark,
|
||||
afsk_phase_inc_space,
|
||||
@ -131,7 +138,7 @@ void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phas
|
||||
}
|
||||
|
||||
void kill_afsk() {
|
||||
const AFSKConfigureMessage message {
|
||||
const AFSKTxConfigureMessage message {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -67,6 +67,7 @@ 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 uint8_t symbol_count);
|
||||
void kill_afsk();
|
||||
void set_afsk(const uint32_t bitrate);
|
||||
void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat,
|
||||
const uint32_t pause_symbols);
|
||||
void set_fsk_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint32_t shift,
|
||||
|
@ -26,10 +26,10 @@
|
||||
* B(2,4) means:
|
||||
* Alphabet size = 2 (binary)
|
||||
* Code length = 4
|
||||
* The length of the bitstream is (2 ^ 4) - 1 = 15
|
||||
* The length of the bitstream is (2 ^ 4) + (4 - 1) = 19 bits
|
||||
* The primitive polynomials come from the de_bruijn_polys[] array (one for each code length)
|
||||
* The shift register is init with 1 and shifted left each step
|
||||
* The polynomial is kept on the right, and ANDed with the corresponding shift register bits
|
||||
* The polynomial is kept on the right, and used as a AND mask applied on the corresponding shift register bits
|
||||
* The resulting bits are XORed together to produce the new bit pushed in the shift register
|
||||
*
|
||||
* 0001 (init)
|
||||
@ -52,9 +52,28 @@
|
||||
* AND 1001
|
||||
* 1000 XOR'd -> 1
|
||||
* ...
|
||||
* After 16 steps: (0+) 000111101011001000
|
||||
* Each of the 16 possible values appears in the sequence:
|
||||
* -0000-111101011001000 0
|
||||
* 0-0001-11101011001000 1
|
||||
* 0000111101011-0010-00 2
|
||||
* 00-0011-1101011001000 3
|
||||
* 00001111010110-0100-0 4
|
||||
* 00001111-0101-1001000 5
|
||||
* 0000111101-0110-01000 6
|
||||
* 000-0111-101011001000 7
|
||||
* 000011110101100-1000- 8
|
||||
* 000011110101-1001-000 9
|
||||
* 0000111-1010-11001000 10
|
||||
* 000011110-1011-001000 11
|
||||
* 00001111010-1100-1000 12
|
||||
* 000011-1101-011001000 13
|
||||
* 00001-1110-1011001000 14
|
||||
* 0000-1111-01011001000 15
|
||||
*/
|
||||
|
||||
void de_bruijn::init(const uint32_t n) {
|
||||
size_t de_bruijn::init(const uint32_t n) {
|
||||
// Cap
|
||||
if ((n < 3) || (n > 16))
|
||||
length = 3;
|
||||
else
|
||||
@ -62,6 +81,8 @@ void de_bruijn::init(const uint32_t n) {
|
||||
|
||||
poly = de_bruijn_polys[length - 3];
|
||||
shift_register = 1;
|
||||
|
||||
return (1U << length) + (length - 1);
|
||||
}
|
||||
|
||||
uint32_t de_bruijn::compute(const uint32_t steps) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __DE_BRUIJN_H__
|
||||
#define __DE_BRUIJN_H__
|
||||
|
||||
// Starts at n = 3
|
||||
// n from 3 to 16
|
||||
const uint32_t de_bruijn_polys[14] {
|
||||
0b0000000000000101,
|
||||
0b0000000000001001,
|
||||
@ -45,7 +45,7 @@ const uint32_t de_bruijn_polys[14] {
|
||||
|
||||
struct de_bruijn {
|
||||
public:
|
||||
void init(const uint32_t n);
|
||||
size_t init(const uint32_t n);
|
||||
uint32_t compute(const uint32_t steps);
|
||||
|
||||
private:
|
||||
|
@ -64,16 +64,6 @@ private:
|
||||
bool ignore { false };
|
||||
uint32_t last_address = 0xFFFFFFFF;
|
||||
pocsag::POCSAGState pocsag_state { };
|
||||
|
||||
MessageHandlerRegistration message_handler_packet {
|
||||
Message::ID::POCSAGPacket,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const POCSAGPacketMessage*>(p);
|
||||
this->on_packet(message);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr ui::Dim header_height = 1 * 16;
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 13 * 8, 0 * 16 }
|
||||
@ -138,6 +128,14 @@ private:
|
||||
|
||||
uint32_t target_frequency() const;
|
||||
void set_target_frequency(const uint32_t new_value);
|
||||
|
||||
MessageHandlerRegistration message_handler_packet {
|
||||
Message::ID::POCSAGPacket,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const POCSAGPacketMessage*>(p);
|
||||
this->on_packet(message);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
92
firmware/application/ui_afsk_rx.cpp
Normal file
92
firmware/application/ui_afsk_rx.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 Furrtek
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ui_afsk_rx.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
|
||||
//#include "string_format.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
void AFSKRxView::focus() {
|
||||
field_frequency.focus();
|
||||
}
|
||||
|
||||
void AFSKRxView::update_freq(rf::Frequency f) {
|
||||
receiver_model.set_tuning_frequency(f);
|
||||
}
|
||||
|
||||
void AFSKRxView::on_bitrate_changed(const uint32_t new_bitrate) {
|
||||
baseband::set_afsk(new_bitrate);
|
||||
}
|
||||
|
||||
AFSKRxView::AFSKRxView(NavigationView& nav) {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_afsk_rx);
|
||||
|
||||
add_children({
|
||||
&rssi,
|
||||
&channel,
|
||||
&field_rf_amp,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&field_frequency,
|
||||
&options_bitrate,
|
||||
&console
|
||||
});
|
||||
|
||||
//receiver_model.set_sampling_rate(3072000);
|
||||
//receiver_model.set_baseband_bandwidth(1750000);
|
||||
//receiver_model.enable();
|
||||
|
||||
field_frequency.set_value(receiver_model.tuning_frequency());
|
||||
field_frequency.set_step(receiver_model.frequency_step());
|
||||
field_frequency.on_change = [this](rf::Frequency f) {
|
||||
update_freq(f);
|
||||
};
|
||||
field_frequency.on_edit = [this, &nav]() {
|
||||
// TODO: Provide separate modal method/scheme?
|
||||
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
||||
new_view->on_changed = [this](rf::Frequency f) {
|
||||
update_freq(f);
|
||||
field_frequency.set_value(f);
|
||||
};
|
||||
};
|
||||
|
||||
options_bitrate.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
on_bitrate_changed(v);
|
||||
};
|
||||
options_bitrate.set_selected_index(1); // 1200bps
|
||||
}
|
||||
|
||||
void AFSKRxView::on_data(uint_fast8_t byte) {
|
||||
std::string str_byte(1, byte);
|
||||
console.write(str_byte);
|
||||
}
|
||||
|
||||
AFSKRxView::~AFSKRxView() {
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
96
firmware/application/ui_afsk_rx.hpp
Normal file
96
firmware/application/ui_afsk_rx.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef __UI_AFSK_RX_H__
|
||||
#define __UI_AFSK_RX_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class AFSKRxView : public View {
|
||||
public:
|
||||
AFSKRxView(NavigationView& nav);
|
||||
~AFSKRxView();
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "AFSK RX (beta)"; };
|
||||
|
||||
private:
|
||||
void on_data(uint_fast8_t byte);
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 13 * 8, 0 * 16 }
|
||||
};
|
||||
LNAGainField field_lna {
|
||||
{ 15 * 8, 0 * 16 }
|
||||
};
|
||||
VGAGainField field_vga {
|
||||
{ 18 * 8, 0 * 16 }
|
||||
};
|
||||
RSSI rssi {
|
||||
{ 21 * 8, 0, 6 * 8, 4 },
|
||||
};
|
||||
Channel channel {
|
||||
{ 21 * 8, 5, 6 * 8, 4 },
|
||||
};
|
||||
|
||||
FrequencyField field_frequency {
|
||||
{ 0 * 8, 0 * 8 },
|
||||
};
|
||||
OptionsField options_bitrate {
|
||||
{ 12 * 8, 21 },
|
||||
7,
|
||||
{
|
||||
{ "600bps ", 600 },
|
||||
{ "1200bps", 1200 },
|
||||
{ "2400bps", 2400 }
|
||||
}
|
||||
};
|
||||
|
||||
Console console {
|
||||
{ 0, 4 * 16, 240, 240 }
|
||||
};
|
||||
|
||||
void update_freq(rf::Frequency f);
|
||||
|
||||
void on_bitrate_changed(const uint32_t new_bitrate);
|
||||
|
||||
void on_data_afsk(const AFSKDataMessage& message);
|
||||
|
||||
MessageHandlerRegistration message_handler_packet {
|
||||
Message::ID::AFSKData,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const AFSKDataMessage*>(p);
|
||||
this->on_data(message->byte);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_AFSK_RX_H__*/
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ui_afskrx.hpp"
|
||||
|
||||
#include "ui_spectrum.hpp"
|
||||
#include "ui_console.hpp"
|
||||
|
||||
#include "event_m0.hpp"
|
||||
#include "ff.h"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
AFSKRXView::AFSKRXView(
|
||||
NavigationView& nav
|
||||
)
|
||||
{
|
||||
add_children({
|
||||
&button_done,
|
||||
&text_rx
|
||||
});
|
||||
|
||||
button_done.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
receiver_model.set_baseband_configuration({
|
||||
.mode = 6,
|
||||
.sampling_rate = 3072000,
|
||||
.decimation_factor = 4,
|
||||
});
|
||||
receiver_model.set_baseband_bandwidth(1750000);
|
||||
}
|
||||
|
||||
AFSKRXView::~AFSKRXView() {
|
||||
receiver_model.disable();
|
||||
}
|
||||
|
||||
void AFSKRXView::on_show() {
|
||||
EventDispatcher::message_map().register_handler(Message::ID::AFSKData,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const AFSKDataMessage*>(p);
|
||||
this->on_data_afsk(*message);
|
||||
}
|
||||
);
|
||||
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
void AFSKRXView::on_hide() {
|
||||
EventDispatcher::message_map().unregister_handler(Message::ID::AFSKData);
|
||||
}
|
||||
|
||||
void AFSKRXView::on_data_afsk(const AFSKDataMessage& message) {
|
||||
Coord oy,ny;
|
||||
|
||||
//text_rx.set(to_string_dec_int(abs(message.data), 8, '0'));
|
||||
|
||||
portapack::display.fill_rectangle({0,160-64,240,128},{32,32,32});
|
||||
|
||||
oy = 160;
|
||||
for (int c=0;c<128;c++) {
|
||||
ny = 160-(message.data[c]>>10);
|
||||
portapack::display.draw_line({static_cast<Coord>(c),oy},{static_cast<Coord>(c+1),ny},{255,127,0});
|
||||
oy = ny;
|
||||
}
|
||||
|
||||
/*auto payload = message.packet.payload;
|
||||
auto payload_length = message.packet.bits_received;
|
||||
|
||||
std::string hex_data;
|
||||
std::string hex_error;
|
||||
uint8_t byte_data = 0;
|
||||
uint8_t byte_error = 0;
|
||||
for(size_t i=0; i<payload_length; i+=2) {
|
||||
const auto bit_data = payload[i+1];
|
||||
const auto bit_error = (payload[i+0] == payload[i+1]);
|
||||
|
||||
byte_data <<= 1;
|
||||
byte_data |= bit_data ? 1 : 0;
|
||||
|
||||
byte_error <<= 1;
|
||||
byte_error |= bit_error ? 1 : 0;
|
||||
|
||||
if( ((i >> 1) & 7) == 7 ) {
|
||||
hex_data += to_string_hex(byte_data, 2);
|
||||
hex_error += to_string_hex(byte_error, 2);
|
||||
}
|
||||
}
|
||||
|
||||
auto console = reinterpret_cast<Console*>(widget_content.get());
|
||||
console->writeln(hex_data.substr(0, 240 / 8));
|
||||
|
||||
if( !f_error(&fil_tpms) ) {
|
||||
rtc::RTC datetime;
|
||||
rtcGetTime(&RTCD1, &datetime);
|
||||
std::string timestamp =
|
||||
to_string_dec_uint(datetime.year(), 4) +
|
||||
to_string_dec_uint(datetime.month(), 2, '0') +
|
||||
to_string_dec_uint(datetime.day(), 2, '0') +
|
||||
to_string_dec_uint(datetime.hour(), 2, '0') +
|
||||
to_string_dec_uint(datetime.minute(), 2, '0') +
|
||||
to_string_dec_uint(datetime.second(), 2, '0');
|
||||
|
||||
const auto tuning_frequency = receiver_model.tuning_frequency();
|
||||
// TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue!
|
||||
const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10);
|
||||
|
||||
std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_data + "/" + hex_error + "\r\n";
|
||||
f_puts(log.c_str(), &fil_tpms);
|
||||
f_sync(&fil_tpms);
|
||||
}*/
|
||||
}
|
||||
|
||||
void AFSKRXView::focus() {
|
||||
button_done.focus();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __UI_AFSKRX_H__
|
||||
#define __UI_AFSKRX_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_console.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "receiver_model.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
namespace ui {
|
||||
|
||||
class AFSKRXView : public View {
|
||||
public:
|
||||
AFSKRXView(NavigationView& nav);
|
||||
~AFSKRXView();
|
||||
|
||||
void focus() override;
|
||||
|
||||
void on_show() override;
|
||||
void on_hide() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Widget> widget_content;
|
||||
|
||||
Button button_done {
|
||||
{ 4 * 8, 0 * 16, 3 * 8, 16 },
|
||||
" < "
|
||||
};
|
||||
|
||||
Text text_rx {
|
||||
{ 1 * 8, 2 * 16, 28 * 8, 16 },
|
||||
"Ready..."
|
||||
};
|
||||
|
||||
void on_tuning_frequency_changed(rf::Frequency f);
|
||||
void on_edit_frequency();
|
||||
|
||||
void on_data_afsk(const AFSKDataMessage& message);
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_RECEIVER_H__*/
|
@ -20,7 +20,7 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ui_aprstx.hpp"
|
||||
#include "ui_aprs_tx.hpp"
|
||||
#include "ui_alphanum.hpp"
|
||||
|
||||
#include "aprs.hpp"
|
@ -32,9 +32,7 @@ namespace ui {
|
||||
EncodersConfigView::EncodersConfigView(
|
||||
NavigationView& nav, Rect parent_rect
|
||||
) {
|
||||
using name_t = std::string;
|
||||
using value_t = int32_t;
|
||||
using option_t = std::pair<name_t, value_t>;
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
std::vector<option_t> enc_options;
|
||||
size_t i;
|
||||
|
||||
@ -47,9 +45,8 @@ EncodersConfigView::EncodersConfigView(
|
||||
add_children({
|
||||
&labels,
|
||||
&options_enctype,
|
||||
&numberfield_clk,
|
||||
&numberfield_bitduration,
|
||||
&numberfield_wordduration,
|
||||
&field_clk,
|
||||
&field_frameduration,
|
||||
&symfield_word,
|
||||
&text_format,
|
||||
&waveform
|
||||
@ -71,31 +68,19 @@ EncodersConfigView::EncodersConfigView(
|
||||
};
|
||||
|
||||
// Selecting input clock changes symbol and word duration
|
||||
numberfield_clk.on_change = [this](int32_t value) {
|
||||
field_clk.on_change = [this](int32_t value) {
|
||||
// value is in kHz, new_value is in us
|
||||
int32_t new_value = 1000000 / ((value * 1000) / encoder_def->clk_per_symbol);
|
||||
if (new_value != numberfield_bitduration.value()) {
|
||||
numberfield_bitduration.set_value(new_value, false);
|
||||
numberfield_wordduration.set_value(new_value * encoder_def->word_length, false);
|
||||
}
|
||||
};
|
||||
|
||||
// Selecting symbol duration changes input clock and word duration
|
||||
numberfield_bitduration.on_change = [this](int32_t value) {
|
||||
int32_t new_value = 1000000 / (((float)value * 1000) / encoder_def->clk_per_symbol);
|
||||
if (new_value != numberfield_clk.value()) {
|
||||
numberfield_clk.set_value(new_value, false);
|
||||
numberfield_wordduration.set_value(value * encoder_def->word_length, false);
|
||||
}
|
||||
int32_t new_value = (encoder_def->clk_per_symbol * 1000000) / (value * 1000);
|
||||
if (new_value != field_frameduration.value())
|
||||
field_frameduration.set_value(new_value * encoder_def->word_length, false);
|
||||
};
|
||||
|
||||
// Selecting word duration changes input clock and symbol duration
|
||||
numberfield_wordduration.on_change = [this](int32_t value) {
|
||||
int32_t new_value = value / encoder_def->word_length;
|
||||
if (new_value != numberfield_bitduration.value()) {
|
||||
numberfield_bitduration.set_value(new_value, false);
|
||||
numberfield_clk.set_value(1000000 / (((float)new_value * 1000) / encoder_def->clk_per_symbol), false);
|
||||
}
|
||||
field_frameduration.on_change = [this](int32_t value) {
|
||||
// value is in us, new_value is in kHz
|
||||
int32_t new_value = (value * 1000) / (encoder_def->word_length * encoder_def->clk_per_symbol);
|
||||
if (new_value != field_clk.value())
|
||||
field_clk.set_value(1000000 / new_value, false);
|
||||
};
|
||||
}
|
||||
|
||||
@ -104,16 +89,13 @@ void EncodersConfigView::focus() {
|
||||
}
|
||||
|
||||
void EncodersConfigView::on_type_change(size_t index) {
|
||||
std::string word_format, format_string = "";
|
||||
std::string format_string = "";
|
||||
size_t word_length;
|
||||
char symbol_type;
|
||||
//size_t address_length;
|
||||
|
||||
//enc_type = index;
|
||||
|
||||
encoder_def = &encoder_defs[index];
|
||||
|
||||
numberfield_clk.set_value(encoder_def->default_speed / 1000);
|
||||
field_clk.set_value(encoder_def->default_speed / 1000);
|
||||
|
||||
// SymField setup
|
||||
word_length = encoder_def->word_length;
|
||||
@ -139,16 +121,14 @@ void EncodersConfigView::on_type_change(size_t index) {
|
||||
}
|
||||
|
||||
void EncodersConfigView::on_show() {
|
||||
// TODO: Remove ?
|
||||
//options_enctype.set_selected_index(enc_type);
|
||||
//on_type_change(enc_type);
|
||||
options_enctype.set_selected_index(0);
|
||||
on_type_change(0);
|
||||
}
|
||||
|
||||
void EncodersConfigView::draw_waveform() {
|
||||
size_t length = frame_symbols.length();
|
||||
size_t n;
|
||||
|
||||
for (n = 0; n < length; n++) {
|
||||
|
||||
for (size_t n = 0; n < length; n++) {
|
||||
if (frame_symbols[n] == '0')
|
||||
waveform_buffer[n] = 0;
|
||||
else
|
||||
@ -179,7 +159,7 @@ uint8_t EncodersConfigView::repeat_min() {
|
||||
}
|
||||
|
||||
uint32_t EncodersConfigView::samples_per_bit() {
|
||||
return OOK_SAMPLERATE / ((numberfield_clk.value() * 1000) / encoder_def->clk_per_fragment);
|
||||
return OOK_SAMPLERATE / ((field_clk.value() * 1000) / encoder_def->clk_per_fragment);
|
||||
}
|
||||
|
||||
uint32_t EncodersConfigView::pause_symbols() {
|
||||
@ -199,20 +179,26 @@ EncodersScanView::EncodersScanView(
|
||||
add_children({
|
||||
&labels,
|
||||
&field_debug,
|
||||
&text_debug
|
||||
&text_debug,
|
||||
&text_length
|
||||
});
|
||||
|
||||
// DEBUG
|
||||
field_debug.on_change = [this](int32_t value) {
|
||||
uint32_t l;
|
||||
size_t length;
|
||||
|
||||
de_bruijn debruijn_seq;
|
||||
debruijn_seq.init(value);
|
||||
length = debruijn_seq.init(value);
|
||||
|
||||
l = 1;
|
||||
l <<= value;
|
||||
l--;
|
||||
if (l > 25)
|
||||
l = 25;
|
||||
text_debug.set(to_string_bin(debruijn_seq.compute(l), 25));
|
||||
|
||||
text_length.set(to_string_dec_uint(length));
|
||||
};
|
||||
}
|
||||
|
||||
@ -256,7 +242,7 @@ void EncodersView::on_txdone(int n, const bool txdone) {
|
||||
|
||||
if (!txdone) {
|
||||
// Repeating...
|
||||
//repeat_index = n + 1;
|
||||
repeat_index = n + 1;
|
||||
|
||||
/*if (tx_mode == SCAN) {
|
||||
scan_progress++;
|
||||
@ -299,8 +285,9 @@ void EncodersView::on_txdone(int n, const bool txdone) {
|
||||
|
||||
void EncodersView::start_tx(const bool scan) {
|
||||
(void)scan;
|
||||
uint8_t* ook_bitstream = shared_memory.bb_data.data;
|
||||
uint32_t ook_bitstream_length;
|
||||
uint8_t byte = 0;
|
||||
size_t bitstream_length =0;
|
||||
uint8_t * bitstream = shared_memory.bb_data.data;
|
||||
|
||||
repeat_min = view_config.repeat_min();
|
||||
|
||||
@ -324,17 +311,14 @@ void EncodersView::start_tx(const bool scan) {
|
||||
|
||||
view_config.generate_frame();
|
||||
|
||||
// Clear bitstream
|
||||
memset(ook_bitstream, 0, 256);
|
||||
|
||||
size_t n = 0;
|
||||
for (auto c : view_config.frame_symbols) {
|
||||
byte <<= 1;
|
||||
if (c != '0')
|
||||
ook_bitstream[n >> 3] |= (1 << (7 - (n & 7)));
|
||||
n++;
|
||||
byte |= 1;
|
||||
if ((bitstream_length & 7) == 7)
|
||||
bitstream[bitstream_length >> 3] = byte;
|
||||
bitstream_length++;
|
||||
}
|
||||
|
||||
ook_bitstream_length = n;
|
||||
|
||||
transmitter_model.set_sampling_rate(OOK_SAMPLERATE);
|
||||
transmitter_model.set_rf_amp(true);
|
||||
@ -342,10 +326,7 @@ void EncodersView::start_tx(const bool scan) {
|
||||
transmitter_model.enable();
|
||||
|
||||
baseband::set_ook_data(
|
||||
ook_bitstream_length,
|
||||
// 2280000/2 = 1140000Hz = 0,877192982us
|
||||
// numberfield_clk.value() / encoder_def->clk_per_fragment
|
||||
// 455000 / 12 = 37917Hz = 26,37339452us
|
||||
bitstream_length,
|
||||
view_config.samples_per_bit(),
|
||||
repeat_min,
|
||||
view_config.pause_symbols()
|
||||
|
@ -67,12 +67,10 @@ private:
|
||||
{ { 1 * 8, 0 }, "Type:", Color::light_grey() },
|
||||
{ { 16 * 8, 0 }, "Clk:", Color::light_grey() },
|
||||
{ { 24 * 8, 0 }, "kHz", Color::light_grey() },
|
||||
{ { 16 * 8, 2 * 8 }, "Bit:", Color::light_grey() },
|
||||
{ { 25 * 8, 2 * 8 }, "us", Color::light_grey() },
|
||||
{ { 15 * 8, 4 * 8 }, "Word:", Color::light_grey() },
|
||||
{ { 26 * 8, 4 * 8 }, "us", Color::light_grey() },
|
||||
{ { 2 * 8, 6 * 8 }, "Word:", Color::light_grey() },
|
||||
{ { 1 * 8, 13 * 8 }, "Waveform:", Color::light_grey() }
|
||||
{ { 14 * 8, 2 * 8 }, "Frame:", Color::light_grey() },
|
||||
{ { 26 * 8, 2 * 8 }, "us", Color::light_grey() },
|
||||
{ { 2 * 8, 4 * 8 }, "Symbols:", Color::light_grey() },
|
||||
{ { 1 * 8, 11 * 8 }, "Waveform:", Color::light_grey() }
|
||||
};
|
||||
|
||||
OptionsField options_enctype { // Options are loaded at runtime
|
||||
@ -82,7 +80,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
NumberField numberfield_clk {
|
||||
NumberField field_clk {
|
||||
{ 21 * 8, 0 },
|
||||
3,
|
||||
{ 1, 500 },
|
||||
@ -90,16 +88,8 @@ private:
|
||||
' '
|
||||
};
|
||||
|
||||
NumberField numberfield_bitduration {
|
||||
NumberField field_frameduration {
|
||||
{ 21 * 8, 2 * 8 },
|
||||
4,
|
||||
{ 50, 9999 },
|
||||
1,
|
||||
' '
|
||||
};
|
||||
|
||||
NumberField numberfield_wordduration {
|
||||
{ 21 * 8, 4 * 8 },
|
||||
5,
|
||||
{ 300, 99999 },
|
||||
100,
|
||||
@ -107,18 +97,18 @@ private:
|
||||
};
|
||||
|
||||
SymField symfield_word {
|
||||
{ 2 * 8, 8 * 8 },
|
||||
{ 2 * 8, 6 * 8 },
|
||||
20,
|
||||
SymField::SYMFIELD_DEF
|
||||
};
|
||||
|
||||
Text text_format {
|
||||
{ 2 * 8, 10 * 8, 24 * 8, 16 },
|
||||
{ 2 * 8, 8 * 8, 24 * 8, 16 },
|
||||
""
|
||||
};
|
||||
|
||||
Waveform waveform {
|
||||
{ 0, 16 * 8, 240, 32 },
|
||||
{ 0, 14 * 8, 240, 32 },
|
||||
waveform_buffer,
|
||||
0,
|
||||
0,
|
||||
@ -136,7 +126,7 @@ public:
|
||||
|
||||
private:
|
||||
Labels labels {
|
||||
{ { 1 * 8, 1 * 8 }, "Test", Color::light_grey() }
|
||||
{ { 1 * 8, 1 * 8 }, "Coming soon...", Color::light_grey() }
|
||||
};
|
||||
|
||||
// DEBUG
|
||||
@ -153,6 +143,12 @@ private:
|
||||
{ 1 * 8, 8 * 8, 24 * 8, 16 },
|
||||
""
|
||||
};
|
||||
|
||||
// DEBUG
|
||||
Text text_length {
|
||||
{ 1 * 8, 10 * 8, 24 * 8, 16 },
|
||||
""
|
||||
};
|
||||
};
|
||||
|
||||
class EncodersView : public View {
|
||||
@ -192,7 +188,7 @@ private:
|
||||
.foreground = Color::blue(),
|
||||
};
|
||||
|
||||
Rect view_rect = { 0, 5 * 8, 240, 168 };
|
||||
Rect view_rect = { 0, 4 * 8, 240, 168 };
|
||||
|
||||
EncodersConfigView view_config { nav_, view_rect };
|
||||
EncodersScanView view_scan { nav_, view_rect };
|
||||
|
@ -177,9 +177,9 @@ private:
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_audio_level {
|
||||
Message::ID::AudioLevel,
|
||||
Message::ID::AudioLevelReport,
|
||||
[this](const Message* const p) {
|
||||
const auto message = static_cast<const AudioLevelMessage*>(p);
|
||||
const auto message = static_cast<const AudioLevelReportMessage*>(p);
|
||||
this->audio_level = message->value;
|
||||
}
|
||||
};
|
||||
|
@ -33,7 +33,8 @@
|
||||
#include "ui_about.hpp"
|
||||
#include "ui_adsb_tx.hpp"
|
||||
#include "ui_adsb_rx.hpp"
|
||||
#include "ui_aprstx.hpp"
|
||||
#include "ui_aprs_tx.hpp"
|
||||
#include "ui_afsk_rx.hpp"
|
||||
#include "ui_bht_tx.hpp"
|
||||
#include "ui_coasterp.hpp"
|
||||
#include "ui_siggen.hpp"
|
||||
@ -282,9 +283,9 @@ void NavigationView::focus() {
|
||||
|
||||
ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
|
||||
add_items({
|
||||
{ "ADS-B: Planes", ui::Color::green(),&bitmap_icon_adsb, [&nav](){ nav.push<ADSBRxView>(); }, },
|
||||
{ "ADS-B: Planes", ui::Color::green(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBRxView>(); }, },
|
||||
{ "AIS: Boats", ui::Color::green(), &bitmap_icon_ais, [&nav](){ nav.push<AISAppView>(); } },
|
||||
{ "APRS", ui::Color::grey(), &bitmap_icon_aprs, [&nav](){ nav.push<NotImplementedView>(); } },
|
||||
{ "APRS", ui::Color::orange(),&bitmap_icon_aprs, [&nav](){ nav.push<AFSKRxView>(); } },
|
||||
{ "Audio", ui::Color::green(), &bitmap_icon_speaker, [&nav](){ nav.push<AnalogAudioView>(false); } },
|
||||
{ "ERT: Utility Meters", ui::Color::green(), &bitmap_icon_ert, [&nav](){ nav.push<ERTAppView>(); } },
|
||||
{ "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push<POCSAGAppView>(); } },
|
||||
|
@ -294,7 +294,14 @@ DeclareTargets(PADT adsbtx)
|
||||
set(MODE_CPPSRC
|
||||
proc_afsk.cpp
|
||||
)
|
||||
DeclareTargets(PAFS afsk)
|
||||
DeclareTargets(PAFT afsktx)
|
||||
|
||||
### AFSK RX
|
||||
|
||||
set(MODE_CPPSRC
|
||||
proc_afskrx.cpp
|
||||
)
|
||||
DeclareTargets(PAFR afskrx)
|
||||
|
||||
### AIS
|
||||
|
||||
|
@ -93,9 +93,9 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
}
|
||||
|
||||
void AFSKProcessor::on_message(const Message* const msg) {
|
||||
const auto message = *reinterpret_cast<const AFSKConfigureMessage*>(msg);
|
||||
const auto message = *reinterpret_cast<const AFSKTxConfigureMessage*>(msg);
|
||||
|
||||
if (message.id == Message::ID::AFSKConfigure) {
|
||||
if (message.id == Message::ID::AFSKTxConfigure) {
|
||||
if (message.samples_per_bit) {
|
||||
afsk_samples_per_bit = message.samples_per_bit;
|
||||
afsk_phase_inc_mark = message.phase_inc_mark * AFSK_DELTA_COEF;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@ -20,90 +21,93 @@
|
||||
*/
|
||||
|
||||
#include "proc_afskrx.hpp"
|
||||
#include "sine_table.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
using namespace lpc43xx;
|
||||
#include "event_m4.hpp"
|
||||
|
||||
void AFSKRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
if( !configured ) {
|
||||
return;
|
||||
}
|
||||
/* Called every 2048/3072000 second -- 1500Hz. */
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
void AFSKRxProcessor::execute(const buffer_c8_t& buffer) {
|
||||
// This is called at 1500Hz
|
||||
|
||||
if (!configured) return;
|
||||
|
||||
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 channel_out = channel_filter.execute(decim_1_out, dst_buffer);
|
||||
|
||||
auto audio = demod.execute(channel_out, work_audio_buffer);
|
||||
feed_channel_stats(channel_out);
|
||||
|
||||
auto audio = demod.execute(channel_out, audio_buffer);
|
||||
|
||||
/*static uint64_t audio_present_history = 0;
|
||||
const auto audio_present_now = squelch.execute(audio);
|
||||
audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0);
|
||||
const bool audio_present = (audio_present_history != 0);
|
||||
*/
|
||||
//if( !audio_present ) {
|
||||
// Zero audio buffer.
|
||||
/*for(size_t i=0; i<audio.count; i++) {
|
||||
if ((i % 3) > 1)
|
||||
audio.p[i] = 4096;
|
||||
for (size_t c = 0; c < audio.count; c++) {
|
||||
|
||||
const int32_t sample_int = audio.p[c] * 32768.0f;
|
||||
const int32_t audio_sample = __SSAT(sample_int, 16);
|
||||
|
||||
/*slicer_sr <<= 1;
|
||||
slicer_sr |= (audio_sample < 0); // Do we need hysteresis ?
|
||||
|
||||
// Detect transitions to adjust clock
|
||||
if ((slicer_sr ^ (slicer_sr >> 1)) & 1) {
|
||||
if (sphase < (0x8000u - sphase_delta_half))
|
||||
sphase += sphase_delta_eighth;
|
||||
else
|
||||
audio.p[i] = -4096;
|
||||
}*/
|
||||
//}
|
||||
|
||||
//audio_hpf.execute_in_place(audio);
|
||||
|
||||
for(size_t i=0; i<audio.count; i++) {
|
||||
if (spur > 10) {
|
||||
if (audio.p[i] > 2000)
|
||||
sign = 1;
|
||||
if (audio.p[i] < -2000)
|
||||
sign = 0;
|
||||
spur = 0;
|
||||
} else {
|
||||
spur++;
|
||||
sphase -= sphase_delta_eighth;
|
||||
}
|
||||
if (sign != prev_sign) {
|
||||
if (freq_timer < 15) // 48
|
||||
bit = 0;
|
||||
else
|
||||
bit++;
|
||||
freq_timer = 0;
|
||||
}
|
||||
prev_sign = sign;
|
||||
if (freq_timer < 1000) freq_timer++; // TODO: Limit in a more intelligent way
|
||||
|
||||
sphase += sphase_delta;*/
|
||||
|
||||
// Symbol time elapsed
|
||||
//if (sphase >= 0x10000u) {
|
||||
// sphase &= 0xFFFFu;
|
||||
|
||||
rx_data <<= 1;
|
||||
rx_data |= 1;
|
||||
|
||||
bit_count++;
|
||||
if (bit_count == 8) {
|
||||
data_message.byte = rx_data;
|
||||
shared_memory.application_queue.push(data_message);
|
||||
bit_count = 0;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
if (bit_timer >= 40) {
|
||||
bit_timer = 0;
|
||||
// Check bit state here !
|
||||
} else {
|
||||
bit_timer++;
|
||||
}
|
||||
|
||||
if (sc >= 600) {
|
||||
sc = 0;
|
||||
//AFSKDataMessage message;
|
||||
//memcpy(message.data,aud,128*2);
|
||||
//shared_memory.application_queue.push(message);
|
||||
audc = 0;
|
||||
} else {
|
||||
sc++;
|
||||
}
|
||||
|
||||
if (audc < 4) {
|
||||
memcpy(aud+(audc*32),audio.p,32*2);
|
||||
audc++;
|
||||
}
|
||||
|
||||
audio_output.write(audio);
|
||||
}
|
||||
|
||||
void AFSKRXProcessor::data_handler(
|
||||
const double data
|
||||
) {
|
||||
/*AFSKDataMessage message;
|
||||
message.data = 'T';
|
||||
shared_memory.application_queue.push(message);*/
|
||||
void AFSKRxProcessor::on_message(const Message* const message) {
|
||||
if (message->id == Message::ID::AFSKRxConfigure)
|
||||
configure(*reinterpret_cast<const AFSKRxConfigureMessage*>(message));
|
||||
}
|
||||
|
||||
void AFSKRxProcessor::configure(const AFSKRxConfigureMessage& message) {
|
||||
constexpr size_t decim_0_input_fs = baseband_fs;
|
||||
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor;
|
||||
|
||||
constexpr size_t decim_1_input_fs = decim_0_output_fs;
|
||||
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor;
|
||||
|
||||
constexpr size_t channel_filter_input_fs = decim_1_output_fs;
|
||||
const size_t channel_filter_output_fs = channel_filter_input_fs / 2;
|
||||
|
||||
const size_t demod_input_fs = channel_filter_output_fs;
|
||||
|
||||
decim_0.configure(taps_16k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_16k0_decim_1.taps, 131072);
|
||||
channel_filter.configure(taps_16k0_channel.taps, 2);
|
||||
demod.configure(demod_input_fs, 5000);
|
||||
|
||||
bitrate = message.bitrate;
|
||||
sphase_delta = 0x10000u * bitrate / 24000;
|
||||
sphase_delta_half = sphase_delta / 2; // Just for speed
|
||||
sphase_delta_eighth = sphase_delta / 8;
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<AFSKRxProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@ -23,46 +24,59 @@
|
||||
#define __PROC_AFSKRX_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "fifo.hpp"
|
||||
#include "message.hpp"
|
||||
|
||||
class AFSKRXProcessor : public BasebandProcessor {
|
||||
class AFSKRxProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
std::array<complex16_t, 512> dst;
|
||||
static constexpr size_t baseband_fs = 3072000;
|
||||
|
||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||
|
||||
std::array<complex16_t, 512> dst { };
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
const buffer_f32_t work_audio_buffer {
|
||||
(float*)dst.data(),
|
||||
sizeof(dst) / sizeof(float)
|
||||
std::array<float, 32> audio { };
|
||||
const buffer_f32_t audio_buffer {
|
||||
audio.data(),
|
||||
audio.size()
|
||||
};
|
||||
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter;
|
||||
dsp::demodulate::FM demod; // 48000 5000
|
||||
// Can't use FIFO class here since it only allows power-of-two sizes
|
||||
std::array<int32_t, 24000/1200> delay_line { 0 };
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0;
|
||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1;
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0 { };
|
||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter { };
|
||||
|
||||
dsp::demodulate::FM demod { };
|
||||
|
||||
AudioOutput audio_output;
|
||||
|
||||
uint16_t bit_timer = 0, freq_timer = 0;
|
||||
uint16_t sc;
|
||||
uint8_t audc, spur, sign, prev_sign, bit = 0;
|
||||
|
||||
int16_t aud[128];
|
||||
|
||||
void data_handler(const double data);
|
||||
uint32_t bitrate { };
|
||||
uint32_t sphase { 0 };
|
||||
uint32_t sphase_delta { 0 };
|
||||
uint32_t sphase_delta_half { 0 };
|
||||
uint32_t sphase_delta_eighth { 0 };
|
||||
uint32_t rx_data { 0 };
|
||||
uint32_t bit_count { 0 };
|
||||
|
||||
bool configured { false };
|
||||
void configure(const NBFMConfigureMessage& message);
|
||||
void configure(const AFSKRxConfigureMessage& message);
|
||||
|
||||
AFSKDataMessage data_message { 0 };
|
||||
};
|
||||
|
||||
#endif/*__PROC_TPMS_H__*/
|
||||
|
@ -59,7 +59,7 @@ private:
|
||||
|
||||
int8_t re { 0 }, im { 0 };
|
||||
|
||||
AudioLevelMessage level_message { };
|
||||
AudioLevelReportMessage level_message { };
|
||||
TXDoneMessage txdone_message { };
|
||||
};
|
||||
|
||||
|
@ -71,12 +71,13 @@ public:
|
||||
CaptureThreadDone = 18,
|
||||
ReplayConfig = 19,
|
||||
ReplayThreadDone = 20,
|
||||
AFSKRxConfigure = 21,
|
||||
|
||||
TXDone = 30,
|
||||
Retune = 31,
|
||||
|
||||
TonesConfigure = 32,
|
||||
AFSKConfigure = 33,
|
||||
AFSKTxConfigure = 33,
|
||||
PWMRSSIConfigure = 34,
|
||||
OOKConfigure = 35,
|
||||
RDSConfigure = 36,
|
||||
@ -93,11 +94,12 @@ public:
|
||||
|
||||
POCSAGPacket = 50,
|
||||
ADSBFrame = 51,
|
||||
AFSKData = 52,
|
||||
|
||||
RequestSignal = 52,
|
||||
FIFOData = 53,
|
||||
RequestSignal = 60,
|
||||
FIFOData = 61,
|
||||
|
||||
AudioLevel = 54,
|
||||
AudioLevelReport = 70,
|
||||
MAX
|
||||
};
|
||||
|
||||
@ -331,6 +333,18 @@ public:
|
||||
adsb::ADSBFrame frame;
|
||||
};
|
||||
|
||||
class AFSKDataMessage : public Message {
|
||||
public:
|
||||
constexpr AFSKDataMessage(
|
||||
const uint_fast8_t byte
|
||||
) : Message { ID::AFSKData },
|
||||
byte { byte }
|
||||
{
|
||||
}
|
||||
|
||||
uint_fast8_t byte;
|
||||
};
|
||||
|
||||
class ShutdownMessage : public Message {
|
||||
public:
|
||||
constexpr ShutdownMessage(
|
||||
@ -598,7 +612,17 @@ public:
|
||||
bool done = false;
|
||||
};
|
||||
|
||||
|
||||
class AFSKRxConfigureMessage : public Message {
|
||||
public:
|
||||
constexpr AFSKRxConfigureMessage(
|
||||
const uint32_t bitrate
|
||||
) : Message { ID::AFSKRxConfigure },
|
||||
bitrate(bitrate)
|
||||
{
|
||||
}
|
||||
|
||||
const uint32_t bitrate;
|
||||
};
|
||||
|
||||
class PWMRSSIConfigureMessage : public Message {
|
||||
public:
|
||||
@ -665,10 +689,10 @@ public:
|
||||
uint32_t range = 0;
|
||||
};
|
||||
|
||||
class AudioLevelMessage : public Message {
|
||||
class AudioLevelReportMessage : public Message {
|
||||
public:
|
||||
constexpr AudioLevelMessage(
|
||||
) : Message { ID::AudioLevel }
|
||||
constexpr AudioLevelReportMessage(
|
||||
) : Message { ID::AudioLevelReport }
|
||||
{
|
||||
}
|
||||
|
||||
@ -729,16 +753,16 @@ public:
|
||||
const uint32_t tone_delta;
|
||||
};
|
||||
|
||||
class AFSKConfigureMessage : public Message {
|
||||
class AFSKTxConfigureMessage : public Message {
|
||||
public:
|
||||
constexpr AFSKConfigureMessage(
|
||||
constexpr AFSKTxConfigureMessage(
|
||||
const uint32_t samples_per_bit,
|
||||
const uint32_t phase_inc_mark,
|
||||
const uint32_t phase_inc_space,
|
||||
const uint8_t repeat,
|
||||
const uint32_t fm_delta,
|
||||
const uint8_t symbol_count
|
||||
) : Message { ID::AFSKConfigure },
|
||||
) : Message { ID::AFSKTxConfigure },
|
||||
samples_per_bit(samples_per_bit),
|
||||
phase_inc_mark(phase_inc_mark),
|
||||
phase_inc_space(phase_inc_space),
|
||||
|
@ -64,6 +64,7 @@ private:
|
||||
};
|
||||
|
||||
constexpr image_tag_t image_tag_adsb_rx { 'P', 'A', 'D', 'R' };
|
||||
constexpr image_tag_t image_tag_afsk_rx { 'P', 'A', 'F', 'R' };
|
||||
constexpr image_tag_t image_tag_ais { 'P', 'A', 'I', 'S' };
|
||||
constexpr image_tag_t image_tag_am_audio { 'P', 'A', 'M', 'A' };
|
||||
constexpr image_tag_t image_tag_capture { 'P', 'C', 'A', 'P' };
|
||||
@ -76,7 +77,7 @@ constexpr image_tag_t image_tag_wideband_spectrum { 'P', 'S', 'P', 'E' };
|
||||
|
||||
constexpr image_tag_t image_tag_jammer { 'P', 'J', 'A', 'M' };
|
||||
constexpr image_tag_t image_tag_audio_tx { 'P', 'A', 'T', 'X' };
|
||||
constexpr image_tag_t image_tag_afsk { 'P', 'A', 'F', 'S' };
|
||||
constexpr image_tag_t image_tag_afsk { 'P', 'A', 'F', 'T' };
|
||||
constexpr image_tag_t image_tag_tones { 'P', 'T', 'O', 'N' };
|
||||
constexpr image_tag_t image_tag_rds { 'P', 'R', 'D', 'S' };
|
||||
constexpr image_tag_t image_tag_ook { 'P', 'O', 'O', 'K' };
|
||||
|
Loading…
Reference in New Issue
Block a user