mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-08-09 23:22:33 -04:00
acars to ext but disabled (#2288)
This commit is contained in:
parent
b9771b2350
commit
09c2c43be0
14 changed files with 353 additions and 295 deletions
|
@ -133,7 +133,6 @@ file(GLOB I2CDEV_SOURCES ${COMMON}/i2cdev_*.cpp)
|
||||||
set(CPPSRC
|
set(CPPSRC
|
||||||
main.cpp
|
main.cpp
|
||||||
shell.cpp
|
shell.cpp
|
||||||
${COMMON}/acars_packet.cpp
|
|
||||||
${COMMON}/adsb.cpp
|
${COMMON}/adsb.cpp
|
||||||
${COMMON}/adsb_frame.cpp
|
${COMMON}/adsb_frame.cpp
|
||||||
${COMMON}/ais_baseband.cpp
|
${COMMON}/ais_baseband.cpp
|
||||||
|
@ -269,7 +268,6 @@ set(CPPSRC
|
||||||
ui/ui_tone_key.cpp
|
ui/ui_tone_key.cpp
|
||||||
ui/ui_transmitter.cpp
|
ui/ui_transmitter.cpp
|
||||||
ui/ui_bmpview.cpp
|
ui/ui_bmpview.cpp
|
||||||
apps/acars_app.cpp
|
|
||||||
apps/ais_app.cpp
|
apps/ais_app.cpp
|
||||||
apps/analog_audio_app.cpp
|
apps/analog_audio_app.cpp
|
||||||
# apps/analog_tv_app.cpp
|
# apps/analog_tv_app.cpp
|
||||||
|
|
|
@ -20,45 +20,26 @@
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "acars_app.hpp"
|
|
||||||
|
|
||||||
#include "baseband_api.hpp"
|
#include "baseband_api.hpp"
|
||||||
#include "portapack_persistent_memory.hpp"
|
#include "portapack_persistent_memory.hpp"
|
||||||
#include "file_path.hpp"
|
#include "file_path.hpp"
|
||||||
|
#include "audio.hpp"
|
||||||
|
|
||||||
|
#include "acars_app.hpp"
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
using namespace acars;
|
|
||||||
|
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
void ACARSLogger::log_raw_data(const acars::Packet& packet, const uint32_t frequency) {
|
namespace ui::external_app::acars_rx {
|
||||||
(void)frequency;
|
|
||||||
std::string entry{}; //= "Raw: F:" + to_string_dec_uint(frequency) + "Hz ";
|
|
||||||
entry.reserve(256);
|
|
||||||
|
|
||||||
// Raw hex dump of all the bytes
|
void ACARSLogger::log_str(std::string msg) {
|
||||||
// for (size_t c = 0; c < packet.length(); c += 32)
|
log_file.write_entry(msg);
|
||||||
// entry += to_string_hex(packet.read(c, 32), 8) + " ";
|
|
||||||
|
|
||||||
for (size_t c = 0; c < 256; c += 32)
|
|
||||||
entry += to_string_bin(packet.read(c, 32), 32);
|
|
||||||
|
|
||||||
log_file.write_entry(packet.received_at(), entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void ACARSLogger::log_decoded(
|
|
||||||
const acars::Packet& packet,
|
|
||||||
const std::string text) {
|
|
||||||
|
|
||||||
log_file.write_entry(packet.timestamp(), text);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
|
|
||||||
ACARSAppView::ACARSAppView(NavigationView& nav)
|
ACARSAppView::ACARSAppView(NavigationView& nav)
|
||||||
: nav_{nav} {
|
: nav_{nav} {
|
||||||
baseband::run_image(portapack::spi_flash::image_tag_acars);
|
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
|
||||||
|
|
||||||
add_children({&rssi,
|
add_children({&rssi,
|
||||||
&channel,
|
&channel,
|
||||||
|
@ -66,6 +47,7 @@ ACARSAppView::ACARSAppView(NavigationView& nav)
|
||||||
&field_lna,
|
&field_lna,
|
||||||
&field_vga,
|
&field_vga,
|
||||||
&field_frequency,
|
&field_frequency,
|
||||||
|
&field_volume,
|
||||||
&check_log,
|
&check_log,
|
||||||
&console});
|
&console});
|
||||||
|
|
||||||
|
@ -79,6 +61,9 @@ ACARSAppView::ACARSAppView(NavigationView& nav)
|
||||||
logger = std::make_unique<ACARSLogger>();
|
logger = std::make_unique<ACARSLogger>();
|
||||||
if (logger)
|
if (logger)
|
||||||
logger->append(logs_dir / u"ACARS.TXT");
|
logger->append(logs_dir / u"ACARS.TXT");
|
||||||
|
|
||||||
|
audio::set_rate(audio::Rate::Hz_24000);
|
||||||
|
audio::output::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
ACARSAppView::~ACARSAppView() {
|
ACARSAppView::~ACARSAppView() {
|
||||||
|
@ -90,29 +75,31 @@ void ACARSAppView::focus() {
|
||||||
field_frequency.focus();
|
field_frequency.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ACARSAppView::on_packet(const acars::Packet& packet) {
|
void ACARSAppView::on_packet(const ACARSPacketMessage* packet) {
|
||||||
std::string console_info;
|
std::string console_info;
|
||||||
|
|
||||||
/*if (!packet.is_valid()) {
|
if (packet->state == 255) {
|
||||||
console_info = to_string_datetime(packet.received_at(), HMS);
|
// got a packet, parse it, and display
|
||||||
console_info += " INVALID";
|
rtc::RTC datetime;
|
||||||
|
rtc_time::now(datetime);
|
||||||
console.writeln(console_info);
|
// todo parity error recovery
|
||||||
} else {
|
console_info = to_string_datetime(datetime, HMS);
|
||||||
console_info = to_string_datetime(packet.received_at(), HMS);
|
console_info += ": ";
|
||||||
console_info += ":" + to_string_bin(packet.read(0, 32), 32);
|
console_info += packet->message;
|
||||||
//console_info += " REG:" + packet.registration_number();
|
console.writeln(console_info);
|
||||||
|
// Log raw data whatever it contains
|
||||||
console.writeln(console_info);
|
if (logger && logging)
|
||||||
}*/
|
logger->log_str(console_info);
|
||||||
|
} else {
|
||||||
packet_counter++;
|
// debug message arrived
|
||||||
if (packet_counter % 10 == 0)
|
console_info = "State: ";
|
||||||
console.writeln("Block #" + to_string_dec_uint(packet_counter));
|
console_info += to_string_dec_int(packet->state);
|
||||||
|
console_info += " lastbyte: ";
|
||||||
// Log raw data whatever it contains
|
console_info += to_string_dec_uint(packet->message[0]);
|
||||||
if (logger && logging)
|
console.writeln(console_info);
|
||||||
logger->log_raw_data(packet, receiver_model.target_frequency());
|
if (logger && logging)
|
||||||
|
logger->log_str(console_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} // namespace ui::external_app::acars_rx
|
|
@ -31,23 +31,19 @@
|
||||||
#include "ui_rssi.hpp"
|
#include "ui_rssi.hpp"
|
||||||
#include "log_file.hpp"
|
#include "log_file.hpp"
|
||||||
|
|
||||||
#include "acars_packet.hpp"
|
namespace ui::external_app::acars_rx {
|
||||||
|
|
||||||
class ACARSLogger {
|
class ACARSLogger {
|
||||||
public:
|
public:
|
||||||
Optional<File::Error> append(const std::filesystem::path& filename) {
|
Optional<File::Error> append(const std::filesystem::path& filename) {
|
||||||
return log_file.append(filename);
|
return log_file.append(filename);
|
||||||
}
|
}
|
||||||
|
void log_str(std::string msg);
|
||||||
void log_raw_data(const acars::Packet& packet, const uint32_t frequency);
|
|
||||||
// void log_decoded(const acars::Packet& packet, const std::string text);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LogFile log_file{};
|
LogFile log_file{};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
|
|
||||||
class ACARSAppView : public View {
|
class ACARSAppView : public View {
|
||||||
public:
|
public:
|
||||||
ACARSAppView(NavigationView& nav);
|
ACARSAppView(NavigationView& nav);
|
||||||
|
@ -55,12 +51,12 @@ class ACARSAppView : public View {
|
||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "ACARS (WIP)"; };
|
std::string title() const override { return "ACARS"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
RxRadioState radio_state_{
|
RxRadioState radio_state_{
|
||||||
131550000 /* frequency */,
|
131825000 /* frequency */,
|
||||||
1750000 /* bandwidth */,
|
1750000 /* bandwidth */,
|
||||||
2457600 /* sampling rate */
|
2457600 /* sampling rate */
|
||||||
};
|
};
|
||||||
|
@ -85,7 +81,7 @@ class ACARSAppView : public View {
|
||||||
{0 * 8, 0 * 8},
|
{0 * 8, 0 * 8},
|
||||||
nav_};
|
nav_};
|
||||||
Checkbox check_log{
|
Checkbox check_log{
|
||||||
{22 * 8, 21},
|
{16 * 8, 1 * 16},
|
||||||
3,
|
3,
|
||||||
"LOG",
|
"LOG",
|
||||||
true};
|
true};
|
||||||
|
@ -93,19 +89,21 @@ class ACARSAppView : public View {
|
||||||
Console console{
|
Console console{
|
||||||
{0, 3 * 16, 240, 256}};
|
{0, 3 * 16, 240, 256}};
|
||||||
|
|
||||||
|
AudioVolumeField field_volume{
|
||||||
|
{28 * 8, 1 * 16}};
|
||||||
|
|
||||||
std::unique_ptr<ACARSLogger> logger{};
|
std::unique_ptr<ACARSLogger> logger{};
|
||||||
|
|
||||||
void on_packet(const acars::Packet& packet);
|
void on_packet(const ACARSPacketMessage* packet);
|
||||||
|
|
||||||
MessageHandlerRegistration message_handler_packet{
|
MessageHandlerRegistration message_handler_packet{
|
||||||
Message::ID::ACARSPacket,
|
Message::ID::ACARSPacket,
|
||||||
[this](Message* const p) {
|
[this](Message* const p) {
|
||||||
const auto message = static_cast<const ACARSPacketMessage*>(p);
|
const auto message = static_cast<const ACARSPacketMessage*>(p);
|
||||||
const acars::Packet packet{message->packet};
|
this->on_packet(message);
|
||||||
this->on_packet(packet);
|
|
||||||
}};
|
}};
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} // namespace ui::external_app::acars_rx
|
||||||
|
|
||||||
#endif /*__ACARS_APP_H__*/
|
#endif /*__ACARS_APP_H__*/
|
82
firmware/application/external/acars_rx/main.cpp
vendored
Normal file
82
firmware/application/external/acars_rx/main.cpp
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Bernd Herzog
|
||||||
|
*
|
||||||
|
* 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.hpp"
|
||||||
|
#include "acars_app.hpp"
|
||||||
|
#include "ui_navigation.hpp"
|
||||||
|
#include "external_app.hpp"
|
||||||
|
|
||||||
|
namespace ui::external_app::acars_rx {
|
||||||
|
void initialize_app(ui::NavigationView& nav) {
|
||||||
|
nav.push<ACARSAppView>();
|
||||||
|
}
|
||||||
|
} // namespace ui::external_app::acars_rx
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
__attribute__((section(".external_app.app_acars_rx.application_information"), used)) application_information_t _application_information_acars_rx = {
|
||||||
|
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||||
|
/*.externalAppEntry = */ ui::external_app::acars_rx::initialize_app,
|
||||||
|
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||||
|
/*.app_version = */ VERSION_MD5,
|
||||||
|
|
||||||
|
/*.app_name = */ "ACARS",
|
||||||
|
/*.bitmap_data = */ {
|
||||||
|
0x80,
|
||||||
|
0x01,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xE0,
|
||||||
|
0x07,
|
||||||
|
0xF8,
|
||||||
|
0x1F,
|
||||||
|
0xFE,
|
||||||
|
0x7F,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xC0,
|
||||||
|
0x03,
|
||||||
|
0xE0,
|
||||||
|
0x07,
|
||||||
|
0xF0,
|
||||||
|
0x0F,
|
||||||
|
0xF8,
|
||||||
|
0x1F,
|
||||||
|
},
|
||||||
|
/*.icon_color = */ ui::Color::orange().v,
|
||||||
|
/*.menu_location = */ app_location_t::RX,
|
||||||
|
|
||||||
|
/*.m4_app_tag = portapack::spi_flash::image_tag_acars */ {'P', 'A', 'C', 'A'},
|
||||||
|
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||||
|
};
|
||||||
|
}
|
6
firmware/application/external/external.cmake
vendored
6
firmware/application/external/external.cmake
vendored
|
@ -102,6 +102,11 @@ set(EXTCPPSRC
|
||||||
external/random_password/ui_random_password.cpp
|
external/random_password/ui_random_password.cpp
|
||||||
external/random_password/sha512.cpp
|
external/random_password/sha512.cpp
|
||||||
external/random_password/sha512.h
|
external/random_password/sha512.h
|
||||||
|
|
||||||
|
#acars
|
||||||
|
external/acars_rx/main.cpp
|
||||||
|
external/acars_rx/acars_app.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(EXTAPPLIST
|
set(EXTAPPLIST
|
||||||
|
@ -129,4 +134,5 @@ set(EXTAPPLIST
|
||||||
morse_tx
|
morse_tx
|
||||||
sstvtx
|
sstvtx
|
||||||
random_password
|
random_password
|
||||||
|
#acars_rx
|
||||||
)
|
)
|
||||||
|
|
10
firmware/application/external/external.ld
vendored
10
firmware/application/external/external.ld
vendored
|
@ -47,6 +47,7 @@ MEMORY
|
||||||
ram_external_app_morse_tx(rwx) : org = 0xADC60000, len = 32k
|
ram_external_app_morse_tx(rwx) : org = 0xADC60000, len = 32k
|
||||||
ram_external_app_sstvtx(rwx) : org = 0xADC70000, len = 32k
|
ram_external_app_sstvtx(rwx) : org = 0xADC70000, len = 32k
|
||||||
ram_external_app_random_password(rwx) : org = 0xADC80000, len = 32k
|
ram_external_app_random_password(rwx) : org = 0xADC80000, len = 32k
|
||||||
|
ram_external_app_acars_rx(rwx) : org = 0xADC90000, len = 32k
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
|
@ -197,4 +198,13 @@ SECTIONS
|
||||||
*(*ui*external_app*random_password*);
|
*(*ui*external_app*random_password*);
|
||||||
} > ram_external_app_random_password
|
} > ram_external_app_random_password
|
||||||
|
|
||||||
|
.external_app_acars_rx : ALIGN(4) SUBALIGN(4)
|
||||||
|
{
|
||||||
|
KEEP(*(.external_app.app_acars_rx.application_information));
|
||||||
|
*(*ui*external_app*acars_rx*);
|
||||||
|
} > ram_external_app_acars_rx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,6 @@
|
||||||
#include "ui_battinfo.hpp"
|
#include "ui_battinfo.hpp"
|
||||||
#include "ui_external_items_menu_loader.hpp"
|
#include "ui_external_items_menu_loader.hpp"
|
||||||
|
|
||||||
// #include "acars_app.hpp"
|
|
||||||
#include "ais_app.hpp"
|
#include "ais_app.hpp"
|
||||||
#include "analog_audio_app.hpp"
|
#include "analog_audio_app.hpp"
|
||||||
// #include "analog_tv_app.hpp" //moved to ext
|
// #include "analog_tv_app.hpp" //moved to ext
|
||||||
|
@ -157,7 +156,6 @@ const NavigationView::AppList NavigationView::appList = {
|
||||||
{nullptr, "Debug", HOME, Color::light_grey(), &bitmap_icon_debug, new ViewFactory<DebugMenuView>()},
|
{nullptr, "Debug", HOME, Color::light_grey(), &bitmap_icon_debug, new ViewFactory<DebugMenuView>()},
|
||||||
//{"about", "About", HOME, Color::cyan(), nullptr, new ViewFactory<AboutView>()},
|
//{"about", "About", HOME, Color::cyan(), nullptr, new ViewFactory<AboutView>()},
|
||||||
/* RX ********************************************************************/
|
/* RX ********************************************************************/
|
||||||
//{"acars", "ACARS", RX, Color::yellow(), &bitmap_icon_adsb, new ViewFactory<ACARSAppView>()},
|
|
||||||
{"adsbrx", "ADS-B", RX, Color::green(), &bitmap_icon_adsb, new ViewFactory<ADSBRxView>()},
|
{"adsbrx", "ADS-B", RX, Color::green(), &bitmap_icon_adsb, new ViewFactory<ADSBRxView>()},
|
||||||
{"ais", "AIS Boats", RX, Color::green(), &bitmap_icon_ais, new ViewFactory<AISAppView>()},
|
{"ais", "AIS Boats", RX, Color::green(), &bitmap_icon_ais, new ViewFactory<AISAppView>()},
|
||||||
{"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSRXView>()},
|
{"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSRXView>()},
|
||||||
|
|
|
@ -314,12 +314,6 @@ endmacro()
|
||||||
|
|
||||||
set(add_to_firmware TRUE)
|
set(add_to_firmware TRUE)
|
||||||
|
|
||||||
### ACARS RX
|
|
||||||
|
|
||||||
set(MODE_CPPSRC
|
|
||||||
proc_acars.cpp
|
|
||||||
)
|
|
||||||
DeclareTargets(PACA acars)
|
|
||||||
|
|
||||||
### ADS-B RX
|
### ADS-B RX
|
||||||
|
|
||||||
|
@ -579,6 +573,15 @@ DeclareTargets(PUSB sd_over_usb)
|
||||||
### Place external app and disabled images below so they don't get added to the firmware
|
### Place external app and disabled images below so they don't get added to the firmware
|
||||||
set(add_to_firmware FALSE)
|
set(add_to_firmware FALSE)
|
||||||
|
|
||||||
|
|
||||||
|
### ACARS RX
|
||||||
|
|
||||||
|
set(MODE_CPPSRC
|
||||||
|
proc_acars.cpp
|
||||||
|
)
|
||||||
|
DeclareTargets(PACA acars)
|
||||||
|
|
||||||
|
|
||||||
### AFSK RX
|
### AFSK RX
|
||||||
|
|
||||||
set(MODE_CPPSRC
|
set(MODE_CPPSRC
|
||||||
|
|
|
@ -20,18 +20,27 @@
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "proc_acars.hpp"
|
|
||||||
|
|
||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
|
#include "proc_acars.hpp"
|
||||||
#include "dsp_fir_taps.hpp"
|
#include "dsp_fir_taps.hpp"
|
||||||
|
#include "audio_dma.hpp"
|
||||||
|
|
||||||
#include "event_m4.hpp"
|
#include "event_m4.hpp"
|
||||||
|
|
||||||
|
#define SYN 0x16
|
||||||
|
#define SOH 0x01
|
||||||
|
#define STX 0x02
|
||||||
|
#define ETX 0x83
|
||||||
|
#define ETB 0x97
|
||||||
|
#define DLE 0x7f
|
||||||
|
|
||||||
ACARSProcessor::ACARSProcessor() {
|
ACARSProcessor::ACARSProcessor() {
|
||||||
|
audio::dma::init_audio_out();
|
||||||
decim_0.configure(taps_11k0_decim_0.taps);
|
decim_0.configure(taps_11k0_decim_0.taps);
|
||||||
decim_1.configure(taps_11k0_decim_1.taps);
|
decim_1.configure(taps_11k0_decim_1.taps);
|
||||||
packet.clear();
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
audio_output.configure(false);
|
||||||
baseband_thread.start();
|
baseband_thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +54,9 @@ void ACARSProcessor::execute(const buffer_c8_t& buffer) {
|
||||||
/* 38.4kHz, 32 samples */
|
/* 38.4kHz, 32 samples */
|
||||||
feed_channel_stats(decimator_out);
|
feed_channel_stats(decimator_out);
|
||||||
|
|
||||||
|
auto audio = demod.execute(decimator_out, audio_buffer);
|
||||||
|
audio_output.write(audio);
|
||||||
|
|
||||||
for (size_t i = 0; i < decimator_out.count; i++) {
|
for (size_t i = 0; i < decimator_out.count; i++) {
|
||||||
if (mf.execute_once(decimator_out.p[i])) {
|
if (mf.execute_once(decimator_out.p[i])) {
|
||||||
clock_recovery(mf.get_output());
|
clock_recovery(mf.get_output());
|
||||||
|
@ -52,24 +64,134 @@ void ACARSProcessor::execute(const buffer_c8_t& buffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ACARSProcessor::consume_symbol(
|
void ACARSProcessor::add_bit(uint8_t bit) {
|
||||||
const float raw_symbol) {
|
decode_data = decode_data << 1 | bit;
|
||||||
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
decode_count_bit++;
|
||||||
// const auto decoded_symbol = acars_decode(sliced_symbol);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
packet.add(sliced_symbol);
|
|
||||||
if (packet.size() == 256) {
|
|
||||||
payload_handler(packet);
|
|
||||||
packet.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// packet_builder.execute(decoded_symbol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ACARSProcessor::payload_handler(
|
uint16_t ACARSProcessor::update_crc(uint8_t dataByte) {
|
||||||
const baseband::Packet& packet) {
|
(void)dataByte;
|
||||||
const ACARSPacketMessage message{packet};
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACARSProcessor::sendDebug() {
|
||||||
|
// if (curr_state <= 1) return;
|
||||||
|
message.state = curr_state;
|
||||||
|
shared_memory.application_queue.push(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACARSProcessor::reset() {
|
||||||
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
curr_state = WSYN;
|
||||||
|
message.msg_len = 0;
|
||||||
|
memset(message.message, 0, 250);
|
||||||
|
message.crc[0] = 0;
|
||||||
|
message.crc[1] = 0;
|
||||||
|
parity_errors = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACARSProcessor::consume_symbol(const float raw_symbol) {
|
||||||
|
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
||||||
|
|
||||||
|
add_bit(sliced_symbol);
|
||||||
|
if (curr_state == WSYN && decode_count_bit == 8) {
|
||||||
|
if ((decode_data & 0xff) == SYN) {
|
||||||
|
curr_state = SYN2;
|
||||||
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
} else {
|
||||||
|
decode_count_bit -= 1; // just drop the first bit
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (curr_state == SYN2 && decode_count_bit == 8) {
|
||||||
|
if ((decode_data & 0xff) == SYN) {
|
||||||
|
curr_state = SOH1;
|
||||||
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
sendDebug();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// here i don't have the right packets. so reset
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
if (curr_state == SOH1 && decode_count_bit == 8) {
|
||||||
|
if ((decode_data & 0xff) == SOH) {
|
||||||
|
reset();
|
||||||
|
curr_state = TXT;
|
||||||
|
sendDebug();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message.message[0] = (decode_data & 0xff); // debug
|
||||||
|
reset();
|
||||||
|
sendDebug();
|
||||||
|
}
|
||||||
|
if (curr_state == TXT && decode_count_bit == 8) {
|
||||||
|
uint8_t ch = (decode_data & 0xff);
|
||||||
|
message.message[message.msg_len++] = ch;
|
||||||
|
|
||||||
|
if (!ParityCheck::parity_check(ch)) {
|
||||||
|
// parity error
|
||||||
|
parity_errors++;
|
||||||
|
if (parity_errors > 4) {
|
||||||
|
reset(); // too many parity errors, skip packet
|
||||||
|
sendDebug();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == ETX || ch == ETB) {
|
||||||
|
curr_state = CRC1;
|
||||||
|
sendDebug();
|
||||||
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message.msg_len > 240) {
|
||||||
|
reset();
|
||||||
|
sendDebug();
|
||||||
|
}
|
||||||
|
if (message.msg_len > 20 && ch == DLE) {
|
||||||
|
message.msg_len -= 3;
|
||||||
|
message.crc[0] = message.message[message.msg_len];
|
||||||
|
message.crc[1] = message.message[message.msg_len + 1];
|
||||||
|
curr_state = CRC2;
|
||||||
|
sendDebug();
|
||||||
|
// to hack the path:
|
||||||
|
decode_data = message.crc[1];
|
||||||
|
} else {
|
||||||
|
decode_count_bit = 0;
|
||||||
|
decode_data = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (curr_state == CRC1 && decode_count_bit == 8) {
|
||||||
|
message.crc[0] = (decode_data & 0xff);
|
||||||
|
curr_state = CRC2;
|
||||||
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
sendDebug();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr_state == CRC2 && decode_count_bit == 8) {
|
||||||
|
message.crc[1] = (decode_data & 0xff);
|
||||||
|
// send it to app cpu, and it'll take care of the rest
|
||||||
|
payload_handler();
|
||||||
|
reset();
|
||||||
|
curr_state = END;
|
||||||
|
decode_data = 0;
|
||||||
|
decode_count_bit = 0;
|
||||||
|
sendDebug();
|
||||||
|
}
|
||||||
|
if (curr_state == END && decode_count_bit == 8) {
|
||||||
|
reset();
|
||||||
|
sendDebug();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACARSProcessor::payload_handler() {
|
||||||
|
message.state = 255; // to indicate this is an actual payload, not a debug packet
|
||||||
shared_memory.application_queue.push(message);
|
shared_memory.application_queue.push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,11 +46,15 @@
|
||||||
#include "baseband_packet.hpp"
|
#include "baseband_packet.hpp"
|
||||||
|
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
|
#include "dsp_demodulate.hpp"
|
||||||
|
#include "audio_output.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
|
#include "crc.hpp"
|
||||||
|
|
||||||
// AIS:
|
// AIS:
|
||||||
// IN: 2457600/8/8 = 38400
|
// IN: 2457600/8/8 = 38400
|
||||||
// Offset: 2457600/4 = 614400 (614400/8/8 = 9600)
|
// Offset: 2457600/4 = 614400 (614400/8/8 = 9600)
|
||||||
|
@ -101,6 +105,14 @@ constexpr std::array<std::complex<float>, 16> rect_taps_38k4_4k8_1t_2k4_p{{
|
||||||
{4.4194173824e-02f, -4.4194173824e-02f},
|
{4.4194173824e-02f, -4.4194173824e-02f},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
typedef enum { WSYN,
|
||||||
|
SYN2,
|
||||||
|
SOH1,
|
||||||
|
TXT,
|
||||||
|
CRC1,
|
||||||
|
CRC2,
|
||||||
|
END } Acarsstate;
|
||||||
|
|
||||||
class ACARSProcessor : public BasebandProcessor {
|
class ACARSProcessor : public BasebandProcessor {
|
||||||
public:
|
public:
|
||||||
ACARSProcessor();
|
ACARSProcessor();
|
||||||
|
@ -124,24 +136,32 @@ class ACARSProcessor : public BasebandProcessor {
|
||||||
2400,
|
2400,
|
||||||
{0.0555f},
|
{0.0555f},
|
||||||
[this](const float symbol) { this->consume_symbol(symbol); }};
|
[this](const float symbol) { this->consume_symbol(symbol); }};
|
||||||
symbol_coding::ACARSDecoder acars_decode{};
|
|
||||||
/*PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder {
|
uint16_t update_crc(uint8_t dataByte);
|
||||||
{ 0b011010000110100010000000, 24, 1 }, // SYN, SYN, SOH
|
void consume_symbol(const float symbol);
|
||||||
{ },
|
void payload_handler();
|
||||||
{ 128 },
|
void add_bit(uint8_t bit);
|
||||||
[this](const baseband::Packet& packet) {
|
void reset();
|
||||||
this->payload_handler(packet);
|
void sendDebug();
|
||||||
}
|
|
||||||
};*/
|
std::array<float, 32> audio{};
|
||||||
baseband::Packet packet{};
|
const buffer_f32_t audio_buffer{
|
||||||
|
audio.data(),
|
||||||
|
audio.size()};
|
||||||
|
dsp::demodulate::AM demod{};
|
||||||
|
AudioOutput audio_output{};
|
||||||
|
|
||||||
|
Acarsstate curr_state = WSYN;
|
||||||
|
|
||||||
|
uint32_t decode_data = 0;
|
||||||
|
uint8_t decode_count_bit = 0;
|
||||||
|
ACARSPacketMessage message{};
|
||||||
|
uint8_t parity_errors = 0;
|
||||||
|
|
||||||
/* NB: Threads should be the last members in the class definition. */
|
/* NB: Threads should be the last members in the class definition. */
|
||||||
BasebandThread baseband_thread{
|
BasebandThread baseband_thread{
|
||||||
baseband_fs, this, baseband::Direction::Receive, /*auto_start*/ false};
|
baseband_fs, this, baseband::Direction::Receive, /*auto_start*/ false};
|
||||||
RSSIThread rssi_thread{};
|
RSSIThread rssi_thread{};
|
||||||
|
|
||||||
void consume_symbol(const float symbol);
|
|
||||||
void payload_handler(const baseband::Packet& packet);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__PROC_ACARS_H__*/
|
#endif /*__PROC_ACARS_H__*/
|
|
@ -1,107 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
|
||||||
* Copyright (C) 2018 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 "acars_packet.hpp"
|
|
||||||
|
|
||||||
#include "crc.hpp"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
namespace acars {
|
|
||||||
|
|
||||||
size_t Packet::length() const {
|
|
||||||
return packet_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Packet::is_valid() const {
|
|
||||||
return true; // length_valid() && crc_ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
Timestamp Packet::received_at() const {
|
|
||||||
return packet_.timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Packet::block_id() const {
|
|
||||||
return field_.read(96, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Packet::registration_number() const {
|
|
||||||
std::string result;
|
|
||||||
result.reserve(7);
|
|
||||||
|
|
||||||
const size_t character_length = 8;
|
|
||||||
for (size_t i = 16; i < (16 + 7 * character_length); i += character_length) {
|
|
||||||
result += (field_.read(i, character_length) & 0x7F);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Packet::read(const size_t start_bit, const size_t length) const {
|
|
||||||
return field_.read(start_bit, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*std::string Packet::text(
|
|
||||||
const size_t start_bit,
|
|
||||||
const size_t character_count
|
|
||||||
) const {
|
|
||||||
std::string result;
|
|
||||||
result.reserve(character_count);
|
|
||||||
|
|
||||||
const size_t character_length = 6;
|
|
||||||
const size_t end_bit = start_bit + character_count * character_length;
|
|
||||||
for(size_t i=start_bit; i<end_bit; i+=character_length) {
|
|
||||||
result += char_to_ascii(field_.read(i, character_length));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
bool Packet::crc_ok() const {
|
|
||||||
CRCReader field_crc{packet_};
|
|
||||||
CRC<16> acars_fcs{0x1021, 0x0000, 0x0000};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < data_length(); i += 8) {
|
|
||||||
acars_fcs.process_byte(field_crc.read(i, 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (acars_fcs.checksum() == (unsigned)field_crc.read(data_length(), fcs_length));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Packet::data_and_fcs_length() const {
|
|
||||||
return length() - 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Packet::data_length() const {
|
|
||||||
return data_and_fcs_length() - fcs_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Packet::length_valid() const {
|
|
||||||
const size_t extra_bits = data_and_fcs_length() & 7;
|
|
||||||
if (extra_bits != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace acars
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
|
||||||
* Copyright (C) 2018 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 __ACARS_PACKET_H__
|
|
||||||
#define __ACARS_PACKET_H__
|
|
||||||
|
|
||||||
#include "baseband_packet.hpp"
|
|
||||||
#include "field_reader.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace acars {
|
|
||||||
|
|
||||||
class Packet {
|
|
||||||
public:
|
|
||||||
constexpr Packet(
|
|
||||||
const baseband::Packet& packet)
|
|
||||||
: packet_{packet},
|
|
||||||
field_{packet_} {
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t length() const;
|
|
||||||
|
|
||||||
bool is_valid() const;
|
|
||||||
|
|
||||||
Timestamp received_at() const;
|
|
||||||
|
|
||||||
uint8_t block_id() const;
|
|
||||||
std::string registration_number() const;
|
|
||||||
|
|
||||||
uint32_t read(const size_t start_bit, const size_t length) const;
|
|
||||||
// std::string text(const size_t start_bit, const size_t character_count) const;
|
|
||||||
|
|
||||||
bool crc_ok() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using Reader = FieldReader<baseband::Packet, BitRemapByteReverse>;
|
|
||||||
using CRCReader = FieldReader<baseband::Packet, BitRemapNone>;
|
|
||||||
|
|
||||||
const baseband::Packet packet_;
|
|
||||||
const Reader field_;
|
|
||||||
|
|
||||||
const size_t fcs_length = 16;
|
|
||||||
|
|
||||||
size_t data_and_fcs_length() const;
|
|
||||||
size_t data_length() const;
|
|
||||||
|
|
||||||
bool length_valid() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace acars */
|
|
||||||
|
|
||||||
#endif /*__ACARS_PACKET_H__*/
|
|
|
@ -190,4 +190,21 @@ class Adler32 {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const unsigned char parity_numbits[256] = {
|
||||||
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||||
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||||
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||||
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||||
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||||
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||||
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||||
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
|
||||||
|
|
||||||
|
class ParityCheck {
|
||||||
|
public:
|
||||||
|
static bool parity_check(uint8_t ch, uint8_t pbitpos = 1) {
|
||||||
|
return ((parity_numbits[ch] & pbitpos) != 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*__CRC_H__*/
|
#endif /*__CRC_H__*/
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
#include "baseband_packet.hpp"
|
#include "baseband_packet.hpp"
|
||||||
|
|
||||||
#include "acars_packet.hpp"
|
|
||||||
#include "adsb_frame.hpp"
|
#include "adsb_frame.hpp"
|
||||||
#include "ert_packet.hpp"
|
#include "ert_packet.hpp"
|
||||||
#include "pocsag_packet.hpp"
|
#include "pocsag_packet.hpp"
|
||||||
|
@ -379,13 +378,12 @@ class POCSAGStatsMessage : public Message {
|
||||||
|
|
||||||
class ACARSPacketMessage : public Message {
|
class ACARSPacketMessage : public Message {
|
||||||
public:
|
public:
|
||||||
constexpr ACARSPacketMessage(
|
constexpr ACARSPacketMessage()
|
||||||
const baseband::Packet& packet)
|
: Message{ID::ACARSPacket} {}
|
||||||
: Message{ID::ACARSPacket},
|
uint8_t msg_len = 0;
|
||||||
packet{packet} {
|
char message[250] = {0}; // contains the whole packet
|
||||||
}
|
uint8_t crc[2] = {0};
|
||||||
|
uint8_t state = 0; // for debug
|
||||||
baseband::Packet packet;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ADSBFrameMessage : public Message {
|
class ADSBFrameMessage : public Message {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue