diff --git a/firmware/application/adsb.cpp b/firmware/application/adsb.cpp index d1e8ccabd..9f4f504d7 100644 --- a/firmware/application/adsb.cpp +++ b/firmware/application/adsb.cpp @@ -26,37 +26,38 @@ namespace adsb { -void make_frame_mode_s(uint8_t * adsb_frame, uint32_t ICAO_address) { - adsb_frame[0] = 0x8D; // DF and CA +void make_frame_mode_s(uint8_t * const adsb_frame, const uint32_t ICAO_address) { + adsb_frame[0] = (17 << 3) | 5; // DF and CA adsb_frame[1] = ICAO_address >> 16; adsb_frame[2] = (ICAO_address >> 8) & 0xFF; adsb_frame[3] = ICAO_address & 0xFF; + + memset(&adsb_frame[4], 0, 10); } -void generate_frame_id(uint8_t * adsb_frame, uint32_t ICAO_address, char * callsign) { - uint8_t c, s; - char ch; +void generate_frame_id(uint8_t * const adsb_frame, const uint32_t ICAO_address, char * const callsign) { std::string callsign_formatted(8, '_'); uint64_t callsign_coded = 0; + uint32_t c, s; + char ch; make_frame_mode_s(adsb_frame, ICAO_address); - adsb_frame[4] = 0x20; // TC + adsb_frame[4] = 4 << 3; // TC = 4: Aircraft ID - // Translate and code callsign + // Translate and encode callsign for (c = 0; c < 8; c++) { ch = callsign[c]; - for (s = 0; s < 64; s++) { + + for (s = 0; s < 64; s++) if (ch == icao_id_lut[s]) break; - } - if (s < 64) { - ch = icao_id_lut[s]; - } else { - ch = ' '; + + if (s >= 64) { + ch = ' '; // Invalid character s = 32; } callsign_coded |= ((uint64_t)s << ((7 - c) * 6)); - callsign_formatted[c] = ch; + callsign[c] = ch; } // Insert callsign in frame @@ -66,7 +67,17 @@ void generate_frame_id(uint8_t * adsb_frame, uint32_t ICAO_address, char * calls ADSB_generate_CRC(adsb_frame); } -void generate_frame_pos(uint8_t * adsb_frame, uint32_t ICAO_address, uint32_t altitude, float latitude, float longitude) { +void generate_frame_emergency(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint8_t code) { + make_frame_mode_s(adsb_frame, ICAO_address); + + adsb_frame[4] = (28 << 3) + 1; // TC = 28 (Emergency), subtype = 1 (Emergency) + adsb_frame[5] = code << 5; + + ADSB_generate_CRC(adsb_frame); +} + +void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude, + const float latitude, const float longitude) { uint8_t c, time_parity; uint32_t altitude_coded; uint32_t LAT, LON; @@ -76,7 +87,7 @@ void generate_frame_pos(uint8_t * adsb_frame, uint32_t ICAO_address, uint32_t al make_frame_mode_s(adsb_frame, ICAO_address); - adsb_frame[4] = 0x58; // TC, SS and NICsb + adsb_frame[4] = 11 << 3; // TC = 11: Airborne position altitude_coded = (altitude + 1000) / 25; // Can be coded in 100ft steps also @@ -105,7 +116,7 @@ void generate_frame_pos(uint8_t * adsb_frame, uint32_t ICAO_address, uint32_t al adsb_frame[6] = ((altitude_coded & 0x00F) << 4) | (LAT >> 15); // Then 0, even/odd, and the 2 LAT-CPR MSBs } -void ADSB_generate_CRC(uint8_t * in_frame) { +void ADSB_generate_CRC(uint8_t * const in_frame) { uint8_t adsb_crc[14]; // Temp buffer uint8_t b, c, s, bitn; const uint32_t crc_poly = 0x1205FFF; @@ -126,10 +137,10 @@ void ADSB_generate_CRC(uint8_t * in_frame) { } } } + // Insert CRC in frame - for (c = 0; c < 3; c++) - in_frame[c + 11] = adsb_crc[c + 11]; - + memcpy(&in_frame[11], &adsb_crc[11], 3); + } } /* namespace adsb */ diff --git a/firmware/application/adsb.hpp b/firmware/application/adsb.hpp index b2f134d1b..c982e645d 100644 --- a/firmware/application/adsb.hpp +++ b/firmware/application/adsb.hpp @@ -30,12 +30,14 @@ namespace adsb { const char icao_id_lut[65] = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ##### ###############0123456789######"; - void make_frame_mode_s(uint8_t * adsb_frame, uint32_t ICAO_address); + void make_frame_mode_s(uint8_t * const adsb_frame, const uint32_t ICAO_address); - void generate_frame_id(uint8_t * adsb_frame, uint32_t ICAO_address, char * callsign); - void generate_frame_pos(uint8_t * adsb_frame, uint32_t ICAO_address, uint32_t altitude, float latitude, float longitude); + void generate_frame_id(uint8_t * const adsb_frame, const uint32_t ICAO_address, char * const callsign); + void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude, + const float latitude, const float longitude); + void generate_frame_emergency(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint8_t code); - void ADSB_generate_CRC(uint8_t * in_message); + void ADSB_generate_CRC(uint8_t * const in_message); } /* namespace adsb */ diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index a1f7149c2..0d2faf9f9 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -82,7 +82,7 @@ void WFMConfig::apply() const { void set_tones_data(const uint32_t bw, const uint32_t pre_silence, const uint16_t tone_count, const bool dual_tone, const bool audio_out) { const TonesConfigureMessage message { - (uint32_t)(262144 * bw) / 1536000, + bw, pre_silence, tone_count, dual_tone, diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 9f55f77f3..047b72441 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -25,7 +25,7 @@ //BUG: Set description in frequency save makes everything go crazy //BUG: Distorted audio in WFM receiver -//BUG: (fixed ?) Bad console scroll init +//BUG: (fixed ?) POCSAG: Bad console scroll init //BUG: POCSAG misses alphanum messages, cuts them off sometimes //BUG: Check AFSK transmit end, skips last bits ? //BUG: RDS doesn't stop baseband when stopping tx ? diff --git a/firmware/application/ui_adsbtx.cpp b/firmware/application/ui_adsbtx.cpp index d5a54f6e2..3042025a1 100644 --- a/firmware/application/ui_adsbtx.cpp +++ b/firmware/application/ui_adsbtx.cpp @@ -38,7 +38,7 @@ using namespace portapack; namespace ui { void ADSBTxView::focus() { - button_transmit.focus(); + sym_icao.focus(); } ADSBTxView::~ADSBTxView() { @@ -52,11 +52,8 @@ void ADSBTxView::paint(Painter& painter) { } void ADSBTxView::generate_frame() { - uint8_t c; + uint32_t c; std::string str_debug; - - if (options_format.selected_index() == 2) - button_transmit.hidden(true); generate_frame_id(adsb_frame, sym_icao.value_hex_u64(), callsign); @@ -64,9 +61,8 @@ void ADSBTxView::generate_frame() { // Convert to binary (1 bit per byte, faster for baseband code) for (c = 0; c < 112; c++) { - if ((adsb_frame[c >> 3] << (c & 7)) & 0x80) { + if ((adsb_frame[c >> 3] << (c & 7)) & 0x80) adsb_bin[c] = 0xFF; - } } // Display for debug @@ -79,11 +75,11 @@ void ADSBTxView::generate_frame() { str_debug += to_string_hex(adsb_frame[c + 7], 2); text_frame_b.set(str_debug); - //text_message.set(callsign_formatted); + button_callsign.set_text(callsign); } void ADSBTxView::start_tx() { - transmitter_model.set_tuning_frequency(452000000); // FOR TESTING - DEBUG + transmitter_model.set_tuning_frequency(434000000); // FOR TESTING - DEBUG transmitter_model.set_sampling_rate(2000000U); transmitter_model.set_rf_amp(true); transmitter_model.set_lna(40); @@ -96,7 +92,7 @@ void ADSBTxView::start_tx() { } void ADSBTxView::on_txdone(const int n) { - size_t sr; + //size_t sr; if (n == 200) { transmitter_model.disable(); @@ -112,6 +108,7 @@ void ADSBTxView::on_txdone(const int n) { ADSBTxView::ADSBTxView(NavigationView& nav) { (void)nav; + uint32_t c; baseband::run_image(portapack::spi_flash::image_tag_adsb_tx); @@ -134,6 +131,9 @@ ADSBTxView::ADSBTxView(NavigationView& nav) { &field_lon_degrees, &field_lon_minutes, &field_lon_seconds, + &check_emergency, + &text_squawk, + &field_squawk, &text_frame_a, &text_frame_b, &button_transmit @@ -161,6 +161,9 @@ ADSBTxView::ADSBTxView(NavigationView& nav) { field_lon_minutes.set_value(0); field_lon_seconds.set_value(0); + for (c = 0; c < 4; c++) + field_squawk.set_value(c, 0); + button_transmit.set_style(&style_val); generate_frame(); diff --git a/firmware/application/ui_adsbtx.hpp b/firmware/application/ui_adsbtx.hpp index 996c54d6c..3c60048f6 100644 --- a/firmware/application/ui_adsbtx.hpp +++ b/firmware/application/ui_adsbtx.hpp @@ -79,11 +79,11 @@ private: }; OptionsField options_format { { 10 * 8, 1 * 16 }, - 10, + 9, { { "17: ADS-B", 17 }, { "18: TIS-B", 18 }, - { "19: Don't.", 19 }, + { "19: MIL ", 19 }, } }; @@ -94,7 +94,7 @@ private: SymField sym_icao { { 10 * 8, 2 * 16 }, 6, - true // Hex + SymField::SYMFIELD_HEX }; Text text_callsign { @@ -145,12 +145,28 @@ private: { 19 * 8, 7 * 16 }, 2, { 0, 59 }, 1, ' ' }; + Checkbox check_emergency { + { 2 * 8, 9 * 16 - 4 }, + 9, + "Emergency", + false + }; + Text text_squawk { + { 15 * 8, 9 * 16, 6 * 8, 16 }, + "Squawk" + }; + SymField field_squawk { + { 22 * 8, 9 * 16 }, + 4, + SymField::SYMFIELD_OCT + }; + Text text_frame_a { - { 4 * 8, 12 * 16, 14 * 8, 16 }, + { 2 * 8, 13 * 16, 14 * 8, 16 }, "-" }; Text text_frame_b { - { 4 * 8, 13 * 16, 14 * 8, 16 }, + { 2 * 8, 14 * 16, 14 * 8, 16 }, "-" }; diff --git a/firmware/application/ui_encoders.hpp b/firmware/application/ui_encoders.hpp index dc4fd3b89..f91ac7047 100644 --- a/firmware/application/ui_encoders.hpp +++ b/firmware/application/ui_encoders.hpp @@ -167,7 +167,8 @@ private: }; SymField symfield_word { { 2 * 8, 12 * 8 }, - 20 + 20, + SymField::SYMFIELD_DEF }; Text text_format { { 2 * 8, 14 * 8, 24 * 8, 16 }, diff --git a/firmware/application/ui_numbers.hpp b/firmware/application/ui_numbers.hpp index 1075648a5..7be75e51d 100644 --- a/firmware/application/ui_numbers.hpp +++ b/firmware/application/ui_numbers.hpp @@ -132,7 +132,7 @@ private: SymField symfield_code { { 20, 5 * 16 }, 25, - false + SymField::SYMFIELD_DEF }; Checkbox check_armed { diff --git a/firmware/application/ui_rds.hpp b/firmware/application/ui_rds.hpp index bcdc0ecb7..320c726bb 100644 --- a/firmware/application/ui_rds.hpp +++ b/firmware/application/ui_rds.hpp @@ -181,7 +181,7 @@ private: SymField sym_pi_code { { 4 * 8, 32 + 8 }, 4, - true + SymField::SYMFIELD_HEX }; Text text_coverage { diff --git a/firmware/baseband/proc_tones.cpp b/firmware/baseband/proc_tones.cpp index 003d1607a..8104143d2 100644 --- a/firmware/baseband/proc_tones.cpp +++ b/firmware/baseband/proc_tones.cpp @@ -128,7 +128,7 @@ void TonesProcessor::on_message(const Message* const p) { tone_durations[c] = shared_memory.bb_data.tones_data.tone_defs[c].duration; } message_length = message.tone_count; - fm_delta = message.fm_delta * 32768; + fm_delta = message.fm_delta * (0xFFFFFFFFULL / 1536000); audio_out = message.audio_out; dual_tone = message.dual_tone; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index b2464c06f..17ea133d0 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -1160,37 +1160,36 @@ int32_t NumberField::clip_value(int32_t value) { /* SymField **************************************************************/ -SymField::SymField( - Point parent_pos, - size_t length -) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, - length_ { length } -{ - set_focusable(true); -} - SymField::SymField( Point parent_pos, size_t length, - bool hex + symfield_type type ) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, length_ { length }, - hex_ { hex } + type_ { type } { - uint8_t c; + uint32_t c; - // Hex field auto-init - for (c = 0; c < length; c++) - set_symbol_list(c, "0123456789ABCDEF"); + // Auto-init + if (type == SYMFIELD_OCT) { + for (c = 0; c < length; c++) + set_symbol_list(c, "01234567"); + } else if (type == SYMFIELD_DEC) { + for (c = 0; c < length; c++) + set_symbol_list(c, "0123456789"); + } else if (type == SYMFIELD_HEX) { + for (c = 0; c < length; c++) + set_symbol_list(c, "0123456789ABCDEF"); + } set_focusable(true); } uint64_t SymField::value_hex_u64() { - uint8_t c; + uint32_t c; uint64_t v = 0; - if (hex_) { + if (type_ != SYMFIELD_DEF) { for (c = 0; c < length_; c++) v += values_[c] << (4 * (length_ - 1 - c)); return v; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index dc6758a0a..fea00dc3b 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -475,8 +475,14 @@ public: std::function on_select { }; std::function on_change { }; - SymField(Point parent_pos, size_t length); - SymField(Point parent_pos, size_t length, bool hex); + enum symfield_type { + SYMFIELD_OCT, + SYMFIELD_DEC, + SYMFIELD_HEX, + SYMFIELD_DEF // User DEFined + }; + + SymField(Point parent_pos, size_t length, symfield_type type); SymField(const SymField&) = delete; SymField(SymField&&) = delete; @@ -499,7 +505,7 @@ private: uint32_t selected_ = 0; size_t length_, prev_length_ = 0; bool erase_prev_ = false; - bool hex_ = false; + symfield_type type_ { }; int32_t clip_value(const uint32_t index, const uint32_t value); }; diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index a5024266c..700b474c6 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ