mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-02-28 21:47:21 +00: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_about.cpp
|
||||||
ui_adsb_rx.cpp
|
ui_adsb_rx.cpp
|
||||||
ui_adsb_tx.cpp
|
ui_adsb_tx.cpp
|
||||||
|
ui_afsk_rx.cpp
|
||||||
ui_alphanum.cpp
|
ui_alphanum.cpp
|
||||||
ui_aprstx.cpp
|
ui_aprs_tx.cpp
|
||||||
ui_audio.cpp
|
ui_audio.cpp
|
||||||
ui_baseband_stats_view.cpp
|
ui_baseband_stats_view.cpp
|
||||||
ui_bht_tx.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);
|
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,
|
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 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_samples_per_bit,
|
||||||
afsk_phase_inc_mark,
|
afsk_phase_inc_mark,
|
||||||
afsk_phase_inc_space,
|
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() {
|
void kill_afsk() {
|
||||||
const AFSKConfigureMessage message {
|
const AFSKTxConfigureMessage message {
|
||||||
0,
|
0,
|
||||||
0,
|
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,
|
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 uint8_t afsk_repeat, const uint32_t afsk_bw, const uint8_t symbol_count);
|
||||||
void kill_afsk();
|
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,
|
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);
|
||||||
void set_fsk_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint32_t shift,
|
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:
|
* B(2,4) means:
|
||||||
* Alphabet size = 2 (binary)
|
* Alphabet size = 2 (binary)
|
||||||
* Code length = 4
|
* 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 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 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
|
* The resulting bits are XORed together to produce the new bit pushed in the shift register
|
||||||
*
|
*
|
||||||
* 0001 (init)
|
* 0001 (init)
|
||||||
@ -52,9 +52,28 @@
|
|||||||
* AND 1001
|
* AND 1001
|
||||||
* 1000 XOR'd -> 1
|
* 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))
|
if ((n < 3) || (n > 16))
|
||||||
length = 3;
|
length = 3;
|
||||||
else
|
else
|
||||||
@ -62,6 +81,8 @@ void de_bruijn::init(const uint32_t n) {
|
|||||||
|
|
||||||
poly = de_bruijn_polys[length - 3];
|
poly = de_bruijn_polys[length - 3];
|
||||||
shift_register = 1;
|
shift_register = 1;
|
||||||
|
|
||||||
|
return (1U << length) + (length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t de_bruijn::compute(const uint32_t steps) {
|
uint32_t de_bruijn::compute(const uint32_t steps) {
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#ifndef __DE_BRUIJN_H__
|
#ifndef __DE_BRUIJN_H__
|
||||||
#define __DE_BRUIJN_H__
|
#define __DE_BRUIJN_H__
|
||||||
|
|
||||||
// Starts at n = 3
|
// n from 3 to 16
|
||||||
const uint32_t de_bruijn_polys[14] {
|
const uint32_t de_bruijn_polys[14] {
|
||||||
0b0000000000000101,
|
0b0000000000000101,
|
||||||
0b0000000000001001,
|
0b0000000000001001,
|
||||||
@ -45,7 +45,7 @@ const uint32_t de_bruijn_polys[14] {
|
|||||||
|
|
||||||
struct de_bruijn {
|
struct de_bruijn {
|
||||||
public:
|
public:
|
||||||
void init(const uint32_t n);
|
size_t init(const uint32_t n);
|
||||||
uint32_t compute(const uint32_t steps);
|
uint32_t compute(const uint32_t steps);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -64,16 +64,6 @@ private:
|
|||||||
bool ignore { false };
|
bool ignore { false };
|
||||||
uint32_t last_address = 0xFFFFFFFF;
|
uint32_t last_address = 0xFFFFFFFF;
|
||||||
pocsag::POCSAGState pocsag_state { };
|
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 {
|
RFAmpField field_rf_amp {
|
||||||
{ 13 * 8, 0 * 16 }
|
{ 13 * 8, 0 * 16 }
|
||||||
@ -138,6 +128,14 @@ private:
|
|||||||
|
|
||||||
uint32_t target_frequency() const;
|
uint32_t target_frequency() const;
|
||||||
void set_target_frequency(const uint32_t new_value);
|
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 */
|
} /* 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.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ui_aprstx.hpp"
|
#include "ui_aprs_tx.hpp"
|
||||||
#include "ui_alphanum.hpp"
|
#include "ui_alphanum.hpp"
|
||||||
|
|
||||||
#include "aprs.hpp"
|
#include "aprs.hpp"
|
@ -32,9 +32,7 @@ namespace ui {
|
|||||||
EncodersConfigView::EncodersConfigView(
|
EncodersConfigView::EncodersConfigView(
|
||||||
NavigationView& nav, Rect parent_rect
|
NavigationView& nav, Rect parent_rect
|
||||||
) {
|
) {
|
||||||
using name_t = std::string;
|
using option_t = std::pair<std::string, int32_t>;
|
||||||
using value_t = int32_t;
|
|
||||||
using option_t = std::pair<name_t, value_t>;
|
|
||||||
std::vector<option_t> enc_options;
|
std::vector<option_t> enc_options;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -47,9 +45,8 @@ EncodersConfigView::EncodersConfigView(
|
|||||||
add_children({
|
add_children({
|
||||||
&labels,
|
&labels,
|
||||||
&options_enctype,
|
&options_enctype,
|
||||||
&numberfield_clk,
|
&field_clk,
|
||||||
&numberfield_bitduration,
|
&field_frameduration,
|
||||||
&numberfield_wordduration,
|
|
||||||
&symfield_word,
|
&symfield_word,
|
||||||
&text_format,
|
&text_format,
|
||||||
&waveform
|
&waveform
|
||||||
@ -71,31 +68,19 @@ EncodersConfigView::EncodersConfigView(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Selecting input clock changes symbol and word duration
|
// 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
|
// value is in kHz, new_value is in us
|
||||||
int32_t new_value = 1000000 / ((value * 1000) / encoder_def->clk_per_symbol);
|
int32_t new_value = (encoder_def->clk_per_symbol * 1000000) / (value * 1000);
|
||||||
if (new_value != numberfield_bitduration.value()) {
|
if (new_value != field_frameduration.value())
|
||||||
numberfield_bitduration.set_value(new_value, false);
|
field_frameduration.set_value(new_value * encoder_def->word_length, 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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Selecting word duration changes input clock and symbol duration
|
// Selecting word duration changes input clock and symbol duration
|
||||||
numberfield_wordduration.on_change = [this](int32_t value) {
|
field_frameduration.on_change = [this](int32_t value) {
|
||||||
int32_t new_value = value / encoder_def->word_length;
|
// value is in us, new_value is in kHz
|
||||||
if (new_value != numberfield_bitduration.value()) {
|
int32_t new_value = (value * 1000) / (encoder_def->word_length * encoder_def->clk_per_symbol);
|
||||||
numberfield_bitduration.set_value(new_value, false);
|
if (new_value != field_clk.value())
|
||||||
numberfield_clk.set_value(1000000 / (((float)new_value * 1000) / encoder_def->clk_per_symbol), false);
|
field_clk.set_value(1000000 / new_value, false);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,16 +89,13 @@ void EncodersConfigView::focus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EncodersConfigView::on_type_change(size_t index) {
|
void EncodersConfigView::on_type_change(size_t index) {
|
||||||
std::string word_format, format_string = "";
|
std::string format_string = "";
|
||||||
size_t word_length;
|
size_t word_length;
|
||||||
char symbol_type;
|
char symbol_type;
|
||||||
//size_t address_length;
|
|
||||||
|
|
||||||
//enc_type = index;
|
|
||||||
|
|
||||||
encoder_def = &encoder_defs[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
|
// SymField setup
|
||||||
word_length = encoder_def->word_length;
|
word_length = encoder_def->word_length;
|
||||||
@ -139,16 +121,14 @@ void EncodersConfigView::on_type_change(size_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EncodersConfigView::on_show() {
|
void EncodersConfigView::on_show() {
|
||||||
// TODO: Remove ?
|
options_enctype.set_selected_index(0);
|
||||||
//options_enctype.set_selected_index(enc_type);
|
on_type_change(0);
|
||||||
//on_type_change(enc_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncodersConfigView::draw_waveform() {
|
void EncodersConfigView::draw_waveform() {
|
||||||
size_t length = frame_symbols.length();
|
size_t length = frame_symbols.length();
|
||||||
size_t n;
|
|
||||||
|
for (size_t n = 0; n < length; n++) {
|
||||||
for (n = 0; n < length; n++) {
|
|
||||||
if (frame_symbols[n] == '0')
|
if (frame_symbols[n] == '0')
|
||||||
waveform_buffer[n] = 0;
|
waveform_buffer[n] = 0;
|
||||||
else
|
else
|
||||||
@ -179,7 +159,7 @@ uint8_t EncodersConfigView::repeat_min() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EncodersConfigView::samples_per_bit() {
|
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() {
|
uint32_t EncodersConfigView::pause_symbols() {
|
||||||
@ -199,20 +179,26 @@ EncodersScanView::EncodersScanView(
|
|||||||
add_children({
|
add_children({
|
||||||
&labels,
|
&labels,
|
||||||
&field_debug,
|
&field_debug,
|
||||||
&text_debug
|
&text_debug,
|
||||||
|
&text_length
|
||||||
});
|
});
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
field_debug.on_change = [this](int32_t value) {
|
field_debug.on_change = [this](int32_t value) {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
de_bruijn debruijn_seq;
|
de_bruijn debruijn_seq;
|
||||||
debruijn_seq.init(value);
|
length = debruijn_seq.init(value);
|
||||||
|
|
||||||
l = 1;
|
l = 1;
|
||||||
l <<= value;
|
l <<= value;
|
||||||
l--;
|
l--;
|
||||||
if (l > 25)
|
if (l > 25)
|
||||||
l = 25;
|
l = 25;
|
||||||
text_debug.set(to_string_bin(debruijn_seq.compute(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) {
|
if (!txdone) {
|
||||||
// Repeating...
|
// Repeating...
|
||||||
//repeat_index = n + 1;
|
repeat_index = n + 1;
|
||||||
|
|
||||||
/*if (tx_mode == SCAN) {
|
/*if (tx_mode == SCAN) {
|
||||||
scan_progress++;
|
scan_progress++;
|
||||||
@ -299,8 +285,9 @@ void EncodersView::on_txdone(int n, const bool txdone) {
|
|||||||
|
|
||||||
void EncodersView::start_tx(const bool scan) {
|
void EncodersView::start_tx(const bool scan) {
|
||||||
(void)scan;
|
(void)scan;
|
||||||
uint8_t* ook_bitstream = shared_memory.bb_data.data;
|
uint8_t byte = 0;
|
||||||
uint32_t ook_bitstream_length;
|
size_t bitstream_length =0;
|
||||||
|
uint8_t * bitstream = shared_memory.bb_data.data;
|
||||||
|
|
||||||
repeat_min = view_config.repeat_min();
|
repeat_min = view_config.repeat_min();
|
||||||
|
|
||||||
@ -324,17 +311,14 @@ void EncodersView::start_tx(const bool scan) {
|
|||||||
|
|
||||||
view_config.generate_frame();
|
view_config.generate_frame();
|
||||||
|
|
||||||
// Clear bitstream
|
|
||||||
memset(ook_bitstream, 0, 256);
|
|
||||||
|
|
||||||
size_t n = 0;
|
|
||||||
for (auto c : view_config.frame_symbols) {
|
for (auto c : view_config.frame_symbols) {
|
||||||
|
byte <<= 1;
|
||||||
if (c != '0')
|
if (c != '0')
|
||||||
ook_bitstream[n >> 3] |= (1 << (7 - (n & 7)));
|
byte |= 1;
|
||||||
n++;
|
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_sampling_rate(OOK_SAMPLERATE);
|
||||||
transmitter_model.set_rf_amp(true);
|
transmitter_model.set_rf_amp(true);
|
||||||
@ -342,10 +326,7 @@ void EncodersView::start_tx(const bool scan) {
|
|||||||
transmitter_model.enable();
|
transmitter_model.enable();
|
||||||
|
|
||||||
baseband::set_ook_data(
|
baseband::set_ook_data(
|
||||||
ook_bitstream_length,
|
bitstream_length,
|
||||||
// 2280000/2 = 1140000Hz = 0,877192982us
|
|
||||||
// numberfield_clk.value() / encoder_def->clk_per_fragment
|
|
||||||
// 455000 / 12 = 37917Hz = 26,37339452us
|
|
||||||
view_config.samples_per_bit(),
|
view_config.samples_per_bit(),
|
||||||
repeat_min,
|
repeat_min,
|
||||||
view_config.pause_symbols()
|
view_config.pause_symbols()
|
||||||
|
@ -67,12 +67,10 @@ private:
|
|||||||
{ { 1 * 8, 0 }, "Type:", Color::light_grey() },
|
{ { 1 * 8, 0 }, "Type:", Color::light_grey() },
|
||||||
{ { 16 * 8, 0 }, "Clk:", Color::light_grey() },
|
{ { 16 * 8, 0 }, "Clk:", Color::light_grey() },
|
||||||
{ { 24 * 8, 0 }, "kHz", Color::light_grey() },
|
{ { 24 * 8, 0 }, "kHz", Color::light_grey() },
|
||||||
{ { 16 * 8, 2 * 8 }, "Bit:", Color::light_grey() },
|
{ { 14 * 8, 2 * 8 }, "Frame:", Color::light_grey() },
|
||||||
{ { 25 * 8, 2 * 8 }, "us", Color::light_grey() },
|
{ { 26 * 8, 2 * 8 }, "us", Color::light_grey() },
|
||||||
{ { 15 * 8, 4 * 8 }, "Word:", Color::light_grey() },
|
{ { 2 * 8, 4 * 8 }, "Symbols:", Color::light_grey() },
|
||||||
{ { 26 * 8, 4 * 8 }, "us", Color::light_grey() },
|
{ { 1 * 8, 11 * 8 }, "Waveform:", Color::light_grey() }
|
||||||
{ { 2 * 8, 6 * 8 }, "Word:", Color::light_grey() },
|
|
||||||
{ { 1 * 8, 13 * 8 }, "Waveform:", Color::light_grey() }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField options_enctype { // Options are loaded at runtime
|
OptionsField options_enctype { // Options are loaded at runtime
|
||||||
@ -82,7 +80,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField numberfield_clk {
|
NumberField field_clk {
|
||||||
{ 21 * 8, 0 },
|
{ 21 * 8, 0 },
|
||||||
3,
|
3,
|
||||||
{ 1, 500 },
|
{ 1, 500 },
|
||||||
@ -90,16 +88,8 @@ private:
|
|||||||
' '
|
' '
|
||||||
};
|
};
|
||||||
|
|
||||||
NumberField numberfield_bitduration {
|
NumberField field_frameduration {
|
||||||
{ 21 * 8, 2 * 8 },
|
{ 21 * 8, 2 * 8 },
|
||||||
4,
|
|
||||||
{ 50, 9999 },
|
|
||||||
1,
|
|
||||||
' '
|
|
||||||
};
|
|
||||||
|
|
||||||
NumberField numberfield_wordduration {
|
|
||||||
{ 21 * 8, 4 * 8 },
|
|
||||||
5,
|
5,
|
||||||
{ 300, 99999 },
|
{ 300, 99999 },
|
||||||
100,
|
100,
|
||||||
@ -107,18 +97,18 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SymField symfield_word {
|
SymField symfield_word {
|
||||||
{ 2 * 8, 8 * 8 },
|
{ 2 * 8, 6 * 8 },
|
||||||
20,
|
20,
|
||||||
SymField::SYMFIELD_DEF
|
SymField::SYMFIELD_DEF
|
||||||
};
|
};
|
||||||
|
|
||||||
Text text_format {
|
Text text_format {
|
||||||
{ 2 * 8, 10 * 8, 24 * 8, 16 },
|
{ 2 * 8, 8 * 8, 24 * 8, 16 },
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
Waveform waveform {
|
Waveform waveform {
|
||||||
{ 0, 16 * 8, 240, 32 },
|
{ 0, 14 * 8, 240, 32 },
|
||||||
waveform_buffer,
|
waveform_buffer,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -136,7 +126,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels {
|
Labels labels {
|
||||||
{ { 1 * 8, 1 * 8 }, "Test", Color::light_grey() }
|
{ { 1 * 8, 1 * 8 }, "Coming soon...", Color::light_grey() }
|
||||||
};
|
};
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
@ -153,6 +143,12 @@ private:
|
|||||||
{ 1 * 8, 8 * 8, 24 * 8, 16 },
|
{ 1 * 8, 8 * 8, 24 * 8, 16 },
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
Text text_length {
|
||||||
|
{ 1 * 8, 10 * 8, 24 * 8, 16 },
|
||||||
|
""
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class EncodersView : public View {
|
class EncodersView : public View {
|
||||||
@ -192,7 +188,7 @@ private:
|
|||||||
.foreground = Color::blue(),
|
.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 };
|
EncodersConfigView view_config { nav_, view_rect };
|
||||||
EncodersScanView view_scan { nav_, view_rect };
|
EncodersScanView view_scan { nav_, view_rect };
|
||||||
|
@ -177,9 +177,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_audio_level {
|
MessageHandlerRegistration message_handler_audio_level {
|
||||||
Message::ID::AudioLevel,
|
Message::ID::AudioLevelReport,
|
||||||
[this](const Message* const p) {
|
[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;
|
this->audio_level = message->value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
#include "ui_about.hpp"
|
#include "ui_about.hpp"
|
||||||
#include "ui_adsb_tx.hpp"
|
#include "ui_adsb_tx.hpp"
|
||||||
#include "ui_adsb_rx.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_bht_tx.hpp"
|
||||||
#include "ui_coasterp.hpp"
|
#include "ui_coasterp.hpp"
|
||||||
#include "ui_siggen.hpp"
|
#include "ui_siggen.hpp"
|
||||||
@ -282,9 +283,9 @@ void NavigationView::focus() {
|
|||||||
|
|
||||||
ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
|
ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
|
||||||
add_items({
|
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>(); } },
|
{ "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); } },
|
{ "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>(); } },
|
{ "ERT: Utility Meters", ui::Color::green(), &bitmap_icon_ert, [&nav](){ nav.push<ERTAppView>(); } },
|
||||||
{ "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push<POCSAGAppView>(); } },
|
{ "POCSAG", ui::Color::green(), &bitmap_icon_pocsag, [&nav](){ nav.push<POCSAGAppView>(); } },
|
||||||
|
@ -294,7 +294,14 @@ DeclareTargets(PADT adsbtx)
|
|||||||
set(MODE_CPPSRC
|
set(MODE_CPPSRC
|
||||||
proc_afsk.cpp
|
proc_afsk.cpp
|
||||||
)
|
)
|
||||||
DeclareTargets(PAFS afsk)
|
DeclareTargets(PAFT afsktx)
|
||||||
|
|
||||||
|
### AFSK RX
|
||||||
|
|
||||||
|
set(MODE_CPPSRC
|
||||||
|
proc_afskrx.cpp
|
||||||
|
)
|
||||||
|
DeclareTargets(PAFR afskrx)
|
||||||
|
|
||||||
### AIS
|
### AIS
|
||||||
|
|
||||||
|
@ -93,9 +93,9 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AFSKProcessor::on_message(const Message* const msg) {
|
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) {
|
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_DELTA_COEF;
|
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) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2016 Furrtek
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -20,90 +21,93 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "proc_afskrx.hpp"
|
#include "proc_afskrx.hpp"
|
||||||
#include "sine_table.hpp"
|
|
||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
|
|
||||||
using namespace lpc43xx;
|
#include "event_m4.hpp"
|
||||||
|
|
||||||
void AFSKRXProcessor::execute(const buffer_c8_t& buffer) {
|
#include <cstdint>
|
||||||
if( !configured ) {
|
#include <cstddef>
|
||||||
return;
|
|
||||||
}
|
void AFSKRxProcessor::execute(const buffer_c8_t& buffer) {
|
||||||
/* Called every 2048/3072000 second -- 1500Hz. */
|
// This is called at 1500Hz
|
||||||
|
|
||||||
|
if (!configured) return;
|
||||||
|
|
||||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
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 decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
|
||||||
const auto channel_out = channel_filter.execute(decim_1_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;
|
for (size_t c = 0; c < audio.count; c++) {
|
||||||
const auto audio_present_now = squelch.execute(audio);
|
|
||||||
audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0);
|
const int32_t sample_int = audio.p[c] * 32768.0f;
|
||||||
const bool audio_present = (audio_present_history != 0);
|
const int32_t audio_sample = __SSAT(sample_int, 16);
|
||||||
*/
|
|
||||||
//if( !audio_present ) {
|
/*slicer_sr <<= 1;
|
||||||
// Zero audio buffer.
|
slicer_sr |= (audio_sample < 0); // Do we need hysteresis ?
|
||||||
/*for(size_t i=0; i<audio.count; i++) {
|
|
||||||
if ((i % 3) > 1)
|
// Detect transitions to adjust clock
|
||||||
audio.p[i] = 4096;
|
if ((slicer_sr ^ (slicer_sr >> 1)) & 1) {
|
||||||
|
if (sphase < (0x8000u - sphase_delta_half))
|
||||||
|
sphase += sphase_delta_eighth;
|
||||||
else
|
else
|
||||||
audio.p[i] = -4096;
|
sphase -= sphase_delta_eighth;
|
||||||
}*/
|
|
||||||
//}
|
|
||||||
|
|
||||||
//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++;
|
|
||||||
}
|
}
|
||||||
if (sign != prev_sign) {
|
|
||||||
if (freq_timer < 15) // 48
|
sphase += sphase_delta;*/
|
||||||
bit = 0;
|
|
||||||
else
|
// Symbol time elapsed
|
||||||
bit++;
|
//if (sphase >= 0x10000u) {
|
||||||
freq_timer = 0;
|
// sphase &= 0xFFFFu;
|
||||||
}
|
|
||||||
prev_sign = sign;
|
rx_data <<= 1;
|
||||||
if (freq_timer < 1000) freq_timer++; // TODO: Limit in a more intelligent way
|
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(
|
void AFSKRxProcessor::on_message(const Message* const message) {
|
||||||
const double data
|
if (message->id == Message::ID::AFSKRxConfigure)
|
||||||
) {
|
configure(*reinterpret_cast<const AFSKRxConfigureMessage*>(message));
|
||||||
/*AFSKDataMessage message;
|
}
|
||||||
message.data = 'T';
|
|
||||||
shared_memory.application_queue.push(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) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2016 Furrtek
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -23,46 +24,59 @@
|
|||||||
#define __PROC_AFSKRX_H__
|
#define __PROC_AFSKRX_H__
|
||||||
|
|
||||||
#include "baseband_processor.hpp"
|
#include "baseband_processor.hpp"
|
||||||
|
#include "baseband_thread.hpp"
|
||||||
|
#include "rssi_thread.hpp"
|
||||||
|
|
||||||
#include "dsp_decimate.hpp"
|
#include "dsp_decimate.hpp"
|
||||||
#include "dsp_demodulate.hpp"
|
#include "dsp_demodulate.hpp"
|
||||||
|
|
||||||
#include "audio_output.hpp"
|
#include "fifo.hpp"
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
|
||||||
class AFSKRXProcessor : public BasebandProcessor {
|
class AFSKRxProcessor : public BasebandProcessor {
|
||||||
public:
|
public:
|
||||||
void execute(const buffer_c8_t& buffer) override;
|
void execute(const buffer_c8_t& buffer) override;
|
||||||
|
|
||||||
|
void on_message(const Message* const message) override;
|
||||||
|
|
||||||
private:
|
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 {
|
const buffer_c16_t dst_buffer {
|
||||||
dst.data(),
|
dst.data(),
|
||||||
dst.size()
|
dst.size()
|
||||||
};
|
};
|
||||||
const buffer_f32_t work_audio_buffer {
|
std::array<float, 32> audio { };
|
||||||
(float*)dst.data(),
|
const buffer_f32_t audio_buffer {
|
||||||
sizeof(dst) / sizeof(float)
|
audio.data(),
|
||||||
|
audio.size()
|
||||||
};
|
};
|
||||||
|
|
||||||
dsp::decimate::FIRAndDecimateComplex channel_filter;
|
// Can't use FIFO class here since it only allows power-of-two sizes
|
||||||
dsp::demodulate::FM demod; // 48000 5000
|
std::array<int32_t, 24000/1200> delay_line { 0 };
|
||||||
|
|
||||||
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0;
|
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0 { };
|
||||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1;
|
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||||
|
dsp::decimate::FIRAndDecimateComplex channel_filter { };
|
||||||
|
|
||||||
|
dsp::demodulate::FM demod { };
|
||||||
|
|
||||||
AudioOutput audio_output;
|
uint32_t bitrate { };
|
||||||
|
uint32_t sphase { 0 };
|
||||||
uint16_t bit_timer = 0, freq_timer = 0;
|
uint32_t sphase_delta { 0 };
|
||||||
uint16_t sc;
|
uint32_t sphase_delta_half { 0 };
|
||||||
uint8_t audc, spur, sign, prev_sign, bit = 0;
|
uint32_t sphase_delta_eighth { 0 };
|
||||||
|
uint32_t rx_data { 0 };
|
||||||
int16_t aud[128];
|
uint32_t bit_count { 0 };
|
||||||
|
|
||||||
void data_handler(const double data);
|
|
||||||
|
|
||||||
bool configured { false };
|
bool configured { false };
|
||||||
void configure(const NBFMConfigureMessage& message);
|
void configure(const AFSKRxConfigureMessage& message);
|
||||||
|
|
||||||
|
AFSKDataMessage data_message { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif/*__PROC_TPMS_H__*/
|
#endif/*__PROC_TPMS_H__*/
|
||||||
|
@ -59,7 +59,7 @@ private:
|
|||||||
|
|
||||||
int8_t re { 0 }, im { 0 };
|
int8_t re { 0 }, im { 0 };
|
||||||
|
|
||||||
AudioLevelMessage level_message { };
|
AudioLevelReportMessage level_message { };
|
||||||
TXDoneMessage txdone_message { };
|
TXDoneMessage txdone_message { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,12 +71,13 @@ public:
|
|||||||
CaptureThreadDone = 18,
|
CaptureThreadDone = 18,
|
||||||
ReplayConfig = 19,
|
ReplayConfig = 19,
|
||||||
ReplayThreadDone = 20,
|
ReplayThreadDone = 20,
|
||||||
|
AFSKRxConfigure = 21,
|
||||||
|
|
||||||
TXDone = 30,
|
TXDone = 30,
|
||||||
Retune = 31,
|
Retune = 31,
|
||||||
|
|
||||||
TonesConfigure = 32,
|
TonesConfigure = 32,
|
||||||
AFSKConfigure = 33,
|
AFSKTxConfigure = 33,
|
||||||
PWMRSSIConfigure = 34,
|
PWMRSSIConfigure = 34,
|
||||||
OOKConfigure = 35,
|
OOKConfigure = 35,
|
||||||
RDSConfigure = 36,
|
RDSConfigure = 36,
|
||||||
@ -93,11 +94,12 @@ public:
|
|||||||
|
|
||||||
POCSAGPacket = 50,
|
POCSAGPacket = 50,
|
||||||
ADSBFrame = 51,
|
ADSBFrame = 51,
|
||||||
|
AFSKData = 52,
|
||||||
|
|
||||||
RequestSignal = 52,
|
RequestSignal = 60,
|
||||||
FIFOData = 53,
|
FIFOData = 61,
|
||||||
|
|
||||||
AudioLevel = 54,
|
AudioLevelReport = 70,
|
||||||
MAX
|
MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -331,6 +333,18 @@ public:
|
|||||||
adsb::ADSBFrame frame;
|
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 {
|
class ShutdownMessage : public Message {
|
||||||
public:
|
public:
|
||||||
constexpr ShutdownMessage(
|
constexpr ShutdownMessage(
|
||||||
@ -598,7 +612,17 @@ public:
|
|||||||
bool done = false;
|
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 {
|
class PWMRSSIConfigureMessage : public Message {
|
||||||
public:
|
public:
|
||||||
@ -665,10 +689,10 @@ public:
|
|||||||
uint32_t range = 0;
|
uint32_t range = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AudioLevelMessage : public Message {
|
class AudioLevelReportMessage : public Message {
|
||||||
public:
|
public:
|
||||||
constexpr AudioLevelMessage(
|
constexpr AudioLevelReportMessage(
|
||||||
) : Message { ID::AudioLevel }
|
) : Message { ID::AudioLevelReport }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,16 +753,16 @@ public:
|
|||||||
const uint32_t tone_delta;
|
const uint32_t tone_delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AFSKConfigureMessage : public Message {
|
class AFSKTxConfigureMessage : public Message {
|
||||||
public:
|
public:
|
||||||
constexpr AFSKConfigureMessage(
|
constexpr AFSKTxConfigureMessage(
|
||||||
const uint32_t samples_per_bit,
|
const uint32_t samples_per_bit,
|
||||||
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 fm_delta,
|
const uint32_t fm_delta,
|
||||||
const uint8_t symbol_count
|
const uint8_t symbol_count
|
||||||
) : Message { ID::AFSKConfigure },
|
) : Message { ID::AFSKTxConfigure },
|
||||||
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),
|
||||||
|
@ -64,6 +64,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
constexpr image_tag_t image_tag_adsb_rx { 'P', 'A', 'D', 'R' };
|
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_ais { 'P', 'A', 'I', 'S' };
|
||||||
constexpr image_tag_t image_tag_am_audio { 'P', 'A', 'M', 'A' };
|
constexpr image_tag_t image_tag_am_audio { 'P', 'A', 'M', 'A' };
|
||||||
constexpr image_tag_t image_tag_capture { 'P', 'C', 'A', 'P' };
|
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_jammer { 'P', 'J', 'A', 'M' };
|
||||||
constexpr image_tag_t image_tag_audio_tx { 'P', 'A', 'T', 'X' };
|
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_tones { 'P', 'T', 'O', 'N' };
|
||||||
constexpr image_tag_t image_tag_rds { 'P', 'R', 'D', 'S' };
|
constexpr image_tag_t image_tag_rds { 'P', 'R', 'D', 'S' };
|
||||||
constexpr image_tag_t image_tag_ook { 'P', 'O', 'O', 'K' };
|
constexpr image_tag_t image_tag_ook { 'P', 'O', 'O', 'K' };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user