diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index da499d264..7f39c5815 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -133,7 +133,6 @@ file(GLOB I2CDEV_SOURCES ${COMMON}/i2cdev_*.cpp) set(CPPSRC main.cpp shell.cpp - ${COMMON}/acars_packet.cpp ${COMMON}/adsb.cpp ${COMMON}/adsb_frame.cpp ${COMMON}/ais_baseband.cpp @@ -269,7 +268,6 @@ set(CPPSRC ui/ui_tone_key.cpp ui/ui_transmitter.cpp ui/ui_bmpview.cpp - apps/acars_app.cpp apps/ais_app.cpp apps/analog_audio_app.cpp # apps/analog_tv_app.cpp diff --git a/firmware/application/apps/acars_app.cpp b/firmware/application/external/acars_rx/acars_app.cpp similarity index 52% rename from firmware/application/apps/acars_app.cpp rename to firmware/application/external/acars_rx/acars_app.cpp index a8a5e1f9c..d7b5079d0 100644 --- a/firmware/application/apps/acars_app.cpp +++ b/firmware/application/external/acars_rx/acars_app.cpp @@ -20,45 +20,26 @@ * Boston, MA 02110-1301, USA. */ -#include "acars_app.hpp" - #include "baseband_api.hpp" #include "portapack_persistent_memory.hpp" #include "file_path.hpp" +#include "audio.hpp" +#include "acars_app.hpp" using namespace portapack; -using namespace acars; #include "string_format.hpp" #include "utility.hpp" -void ACARSLogger::log_raw_data(const acars::Packet& packet, const uint32_t frequency) { - (void)frequency; - std::string entry{}; //= "Raw: F:" + to_string_dec_uint(frequency) + "Hz "; - entry.reserve(256); - - // Raw hex dump of all the bytes - // for (size_t c = 0; c < packet.length(); c += 32) - // entry += to_string_hex(packet.read(c, 32), 8) + " "; +namespace ui::external_app::acars_rx { - 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_str(std::string msg) { + log_file.write_entry(msg); } -/*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) : nav_{nav} { - baseband::run_image(portapack::spi_flash::image_tag_acars); + baseband::run_prepared_image(portapack::memory::map::m4_code.base()); add_children({&rssi, &channel, @@ -66,6 +47,7 @@ ACARSAppView::ACARSAppView(NavigationView& nav) &field_lna, &field_vga, &field_frequency, + &field_volume, &check_log, &console}); @@ -79,6 +61,9 @@ ACARSAppView::ACARSAppView(NavigationView& nav) logger = std::make_unique(); if (logger) logger->append(logs_dir / u"ACARS.TXT"); + + audio::set_rate(audio::Rate::Hz_24000); + audio::output::start(); } ACARSAppView::~ACARSAppView() { @@ -90,29 +75,31 @@ void ACARSAppView::focus() { field_frequency.focus(); } -void ACARSAppView::on_packet(const acars::Packet& packet) { +void ACARSAppView::on_packet(const ACARSPacketMessage* packet) { std::string console_info; - /*if (!packet.is_valid()) { - console_info = to_string_datetime(packet.received_at(), HMS); - console_info += " INVALID"; - - console.writeln(console_info); - } else { - console_info = to_string_datetime(packet.received_at(), HMS); - console_info += ":" + to_string_bin(packet.read(0, 32), 32); - //console_info += " REG:" + packet.registration_number(); - - console.writeln(console_info); - }*/ - - packet_counter++; - if (packet_counter % 10 == 0) - console.writeln("Block #" + to_string_dec_uint(packet_counter)); - - // Log raw data whatever it contains - if (logger && logging) - logger->log_raw_data(packet, receiver_model.target_frequency()); + if (packet->state == 255) { + // got a packet, parse it, and display + rtc::RTC datetime; + rtc_time::now(datetime); + // todo parity error recovery + console_info = to_string_datetime(datetime, HMS); + console_info += ": "; + console_info += packet->message; + console.writeln(console_info); + // Log raw data whatever it contains + if (logger && logging) + logger->log_str(console_info); + } else { + // debug message arrived + console_info = "State: "; + console_info += to_string_dec_int(packet->state); + console_info += " lastbyte: "; + console_info += to_string_dec_uint(packet->message[0]); + console.writeln(console_info); + if (logger && logging) + logger->log_str(console_info); + } } -} /* namespace ui */ +} // namespace ui::external_app::acars_rx \ No newline at end of file diff --git a/firmware/application/apps/acars_app.hpp b/firmware/application/external/acars_rx/acars_app.hpp similarity index 82% rename from firmware/application/apps/acars_app.hpp rename to firmware/application/external/acars_rx/acars_app.hpp index fd6886952..ac99e7045 100644 --- a/firmware/application/apps/acars_app.hpp +++ b/firmware/application/external/acars_rx/acars_app.hpp @@ -31,23 +31,19 @@ #include "ui_rssi.hpp" #include "log_file.hpp" -#include "acars_packet.hpp" +namespace ui::external_app::acars_rx { class ACARSLogger { public: Optional append(const std::filesystem::path& filename) { return log_file.append(filename); } - - void log_raw_data(const acars::Packet& packet, const uint32_t frequency); - // void log_decoded(const acars::Packet& packet, const std::string text); + void log_str(std::string msg); private: LogFile log_file{}; }; -namespace ui { - class ACARSAppView : public View { public: ACARSAppView(NavigationView& nav); @@ -55,12 +51,12 @@ class ACARSAppView : public View { void focus() override; - std::string title() const override { return "ACARS (WIP)"; }; + std::string title() const override { return "ACARS"; }; private: NavigationView& nav_; RxRadioState radio_state_{ - 131550000 /* frequency */, + 131825000 /* frequency */, 1750000 /* bandwidth */, 2457600 /* sampling rate */ }; @@ -85,7 +81,7 @@ class ACARSAppView : public View { {0 * 8, 0 * 8}, nav_}; Checkbox check_log{ - {22 * 8, 21}, + {16 * 8, 1 * 16}, 3, "LOG", true}; @@ -93,19 +89,21 @@ class ACARSAppView : public View { Console console{ {0, 3 * 16, 240, 256}}; + AudioVolumeField field_volume{ + {28 * 8, 1 * 16}}; + std::unique_ptr logger{}; - void on_packet(const acars::Packet& packet); + void on_packet(const ACARSPacketMessage* packet); MessageHandlerRegistration message_handler_packet{ Message::ID::ACARSPacket, [this](Message* const p) { const auto message = static_cast(p); - const acars::Packet packet{message->packet}; - this->on_packet(packet); + this->on_packet(message); }}; }; -} /* namespace ui */ +} // namespace ui::external_app::acars_rx -#endif /*__ACARS_APP_H__*/ +#endif /*__ACARS_APP_H__*/ \ No newline at end of file diff --git a/firmware/application/external/acars_rx/main.cpp b/firmware/application/external/acars_rx/main.cpp new file mode 100644 index 000000000..50b53c1e5 --- /dev/null +++ b/firmware/application/external/acars_rx/main.cpp @@ -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(); +} +} // 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 +}; +} diff --git a/firmware/application/external/external.cmake b/firmware/application/external/external.cmake index cefa1e010..6d2ac2afd 100644 --- a/firmware/application/external/external.cmake +++ b/firmware/application/external/external.cmake @@ -102,6 +102,11 @@ set(EXTCPPSRC external/random_password/ui_random_password.cpp external/random_password/sha512.cpp external/random_password/sha512.h + + #acars + external/acars_rx/main.cpp + external/acars_rx/acars_app.cpp + ) set(EXTAPPLIST @@ -129,4 +134,5 @@ set(EXTAPPLIST morse_tx sstvtx random_password + #acars_rx ) diff --git a/firmware/application/external/external.ld b/firmware/application/external/external.ld index f93a617ed..d3cb0f8a9 100644 --- a/firmware/application/external/external.ld +++ b/firmware/application/external/external.ld @@ -47,6 +47,7 @@ MEMORY ram_external_app_morse_tx(rwx) : org = 0xADC60000, len = 32k ram_external_app_sstvtx(rwx) : org = 0xADC70000, len = 32k ram_external_app_random_password(rwx) : org = 0xADC80000, len = 32k + ram_external_app_acars_rx(rwx) : org = 0xADC90000, len = 32k } SECTIONS @@ -197,4 +198,13 @@ SECTIONS *(*ui*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 + + + + } diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index cd0b7620a..b09245ba4 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -86,7 +86,6 @@ #include "ui_battinfo.hpp" #include "ui_external_items_menu_loader.hpp" -// #include "acars_app.hpp" #include "ais_app.hpp" #include "analog_audio_app.hpp" // #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()}, //{"about", "About", HOME, Color::cyan(), nullptr, new ViewFactory()}, /* RX ********************************************************************/ - //{"acars", "ACARS", RX, Color::yellow(), &bitmap_icon_adsb, new ViewFactory()}, {"adsbrx", "ADS-B", RX, Color::green(), &bitmap_icon_adsb, new ViewFactory()}, {"ais", "AIS Boats", RX, Color::green(), &bitmap_icon_ais, new ViewFactory()}, {"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory()}, diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 990dc8fa6..5c320c03c 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -314,12 +314,6 @@ endmacro() set(add_to_firmware TRUE) -### ACARS RX - -set(MODE_CPPSRC - proc_acars.cpp -) -DeclareTargets(PACA acars) ### 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 set(add_to_firmware FALSE) + +### ACARS RX + +set(MODE_CPPSRC + proc_acars.cpp +) +DeclareTargets(PACA acars) + + ### AFSK RX set(MODE_CPPSRC diff --git a/firmware/baseband/proc_acars.cpp b/firmware/baseband/proc_acars.cpp index 023112e5b..af0b8bc35 100644 --- a/firmware/baseband/proc_acars.cpp +++ b/firmware/baseband/proc_acars.cpp @@ -20,18 +20,27 @@ * Boston, MA 02110-1301, USA. */ -#include "proc_acars.hpp" - #include "portapack_shared_memory.hpp" - +#include "proc_acars.hpp" #include "dsp_fir_taps.hpp" +#include "audio_dma.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() { + audio::dma::init_audio_out(); decim_0.configure(taps_11k0_decim_0.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(); } @@ -45,6 +54,9 @@ void ACARSProcessor::execute(const buffer_c8_t& buffer) { /* 38.4kHz, 32 samples */ 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++) { if (mf.execute_once(decimator_out.p[i])) { clock_recovery(mf.get_output()); @@ -52,24 +64,134 @@ void ACARSProcessor::execute(const buffer_c8_t& buffer) { } } -void ACARSProcessor::consume_symbol( - const float raw_symbol) { +void ACARSProcessor::add_bit(uint8_t bit) { + decode_data = decode_data << 1 | bit; + decode_count_bit++; +} + +uint16_t ACARSProcessor::update_crc(uint8_t dataByte) { + (void)dataByte; + 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; - // const auto decoded_symbol = acars_decode(sliced_symbol); - // DEBUG - packet.add(sliced_symbol); - if (packet.size() == 256) { - payload_handler(packet); - packet.clear(); + 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(); } - // packet_builder.execute(decoded_symbol); + 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( - const baseband::Packet& packet) { - const ACARSPacketMessage message{packet}; +void ACARSProcessor::payload_handler() { + message.state = 255; // to indicate this is an actual payload, not a debug packet shared_memory.application_queue.push(message); } @@ -77,4 +199,4 @@ int main() { EventDispatcher event_dispatcher{std::make_unique()}; event_dispatcher.run(); return 0; -} +} \ No newline at end of file diff --git a/firmware/baseband/proc_acars.hpp b/firmware/baseband/proc_acars.hpp index ddd1c0a11..c732516f2 100644 --- a/firmware/baseband/proc_acars.hpp +++ b/firmware/baseband/proc_acars.hpp @@ -46,11 +46,15 @@ #include "baseband_packet.hpp" #include "message.hpp" +#include "dsp_demodulate.hpp" +#include "audio_output.hpp" #include #include #include +#include "crc.hpp" + // AIS: // IN: 2457600/8/8 = 38400 // Offset: 2457600/4 = 614400 (614400/8/8 = 9600) @@ -101,6 +105,14 @@ constexpr std::array, 16> rect_taps_38k4_4k8_1t_2k4_p{{ {4.4194173824e-02f, -4.4194173824e-02f}, }}; +typedef enum { WSYN, + SYN2, + SOH1, + TXT, + CRC1, + CRC2, + END } Acarsstate; + class ACARSProcessor : public BasebandProcessor { public: ACARSProcessor(); @@ -124,24 +136,32 @@ class ACARSProcessor : public BasebandProcessor { 2400, {0.0555f}, [this](const float symbol) { this->consume_symbol(symbol); }}; - symbol_coding::ACARSDecoder acars_decode{}; - /*PacketBuilder packet_builder { - { 0b011010000110100010000000, 24, 1 }, // SYN, SYN, SOH - { }, - { 128 }, - [this](const baseband::Packet& packet) { - this->payload_handler(packet); - } - };*/ - baseband::Packet packet{}; + + uint16_t update_crc(uint8_t dataByte); + void consume_symbol(const float symbol); + void payload_handler(); + void add_bit(uint8_t bit); + void reset(); + void sendDebug(); + + std::array audio{}; + 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. */ BasebandThread baseband_thread{ baseband_fs, this, baseband::Direction::Receive, /*auto_start*/ false}; RSSIThread rssi_thread{}; - - void consume_symbol(const float symbol); - void payload_handler(const baseband::Packet& packet); }; -#endif /*__PROC_ACARS_H__*/ +#endif /*__PROC_ACARS_H__*/ \ No newline at end of file diff --git a/firmware/common/acars_packet.cpp b/firmware/common/acars_packet.cpp deleted file mode 100644 index 653b1b627..000000000 --- a/firmware/common/acars_packet.cpp +++ /dev/null @@ -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 - -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 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 diff --git a/firmware/common/acars_packet.hpp b/firmware/common/acars_packet.hpp deleted file mode 100644 index 322e64c83..000000000 --- a/firmware/common/acars_packet.hpp +++ /dev/null @@ -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 -#include -#include - -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; - using CRCReader = FieldReader; - - 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__*/ diff --git a/firmware/common/crc.hpp b/firmware/common/crc.hpp index c278ca93e..ac8125966 100644 --- a/firmware/common/crc.hpp +++ b/firmware/common/crc.hpp @@ -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__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 8da28d042..a619816ca 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -32,7 +32,6 @@ #include "baseband_packet.hpp" -#include "acars_packet.hpp" #include "adsb_frame.hpp" #include "ert_packet.hpp" #include "pocsag_packet.hpp" @@ -379,13 +378,12 @@ class POCSAGStatsMessage : public Message { class ACARSPacketMessage : public Message { public: - constexpr ACARSPacketMessage( - const baseband::Packet& packet) - : Message{ID::ACARSPacket}, - packet{packet} { - } - - baseband::Packet packet; + constexpr ACARSPacketMessage() + : Message{ID::ACARSPacket} {} + uint8_t msg_len = 0; + char message[250] = {0}; // contains the whole packet + uint8_t crc[2] = {0}; + uint8_t state = 0; // for debug }; class ADSBFrameMessage : public Message {