diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 06f54ffe4..7d4980d83 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -23,17 +23,15 @@ // Color bitmaps generated with: // Gimp image > indexed colors (16), then "xxd -i *.bmp" -//TEST: ADS-B tx manchester encoder, velocity and squawk frames +//TEST: ADS-B tx velocity and squawk frames //TEST: Menuview refresh, seems to blink a lot //TEST: Check AFSK transmit end, skips last bits ? //TEST: Imperial in whipcalc -//BUG: ADSB transmit baseband code works only if stuck in a loop (txdone message makes everything go nuts) //BUG: CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay //BUG: REPLAY See what's wrong with quality (format, or need for interpolation filter ?) //BUG: SCANNER Lock on frequency, if frequency jump, still locked on first one //BUG: SCANNER Multiple slices -//BUG: REPLAY freezes when SD card not present //BUG: RDS doesn't stop baseband when stopping tx ? //TODO: REPLAY Convert C16 to C8 on M0 core diff --git a/firmware/application/ui_adsb_tx.cpp b/firmware/application/ui_adsb_tx.cpp index 3bc377b4d..53f51b1e6 100644 --- a/firmware/application/ui_adsb_tx.cpp +++ b/firmware/application/ui_adsb_tx.cpp @@ -118,6 +118,8 @@ ADSBPositionView::ADSBPositionView(NavigationView& nav) { } void ADSBPositionView::collect_frames(const uint32_t ICAO_address, std::vector& frame_list) { + if (!enabled) return; + ADSBFrame temp_frame; encode_frame_pos(temp_frame, ICAO_address, geopos.altitude(), @@ -149,6 +151,8 @@ ADSBCallsignView::ADSBCallsignView(NavigationView& nav) { } void ADSBCallsignView::collect_frames(const uint32_t ICAO_address, std::vector& frame_list) { + if (!enabled) return; + ADSBFrame temp_frame; encode_frame_id(temp_frame, ICAO_address, callsign); @@ -175,6 +179,8 @@ ADSBSpeedView::ADSBSpeedView() { } void ADSBSpeedView::collect_frames(const uint32_t ICAO_address, std::vector& frame_list) { + if (!enabled) return; + ADSBFrame temp_frame; encode_frame_velo(temp_frame, ICAO_address, field_speed.value(), @@ -193,6 +199,8 @@ ADSBSquawkView::ADSBSquawkView() { } void ADSBSquawkView::collect_frames(const uint32_t ICAO_address, std::vector& frame_list) { + if (!enabled) return; + ADSBFrame temp_frame; (void)ICAO_address; @@ -201,83 +209,35 @@ void ADSBSquawkView::collect_frames(const uint32_t ICAO_address, std::vector frames +) : frames_ { std::move(frames) } +{ + thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ADSBTXThread::static_fn, this); } -ADSBTxView::~ADSBTxView() { - transmitter_model.disable(); - baseband::shutdown(); +ADSBTXThread::~ADSBTXThread() { + if( thread ) { + chThdTerminate(thread); + chThdWait(thread); + thread = nullptr; + } } -void ADSBTxView::generate_frames() { - const uint32_t ICAO_address = sym_icao.value_hex_u64(); - - /* This scheme kinda sucks. Each "tab"'s collect_frames method - * is called to generate its related frame(s). Getting values - * from each widget of each tab would be better ? - * */ - view_position.collect_frames(ICAO_address, frames); - view_callsign.collect_frames(ICAO_address, frames); - view_speed.collect_frames(ICAO_address, frames); - view_squawk.collect_frames(ICAO_address, frames); - - // DEBUG: Show how many frames were generated - text_frame.set(to_string_dec_uint(frames.size()) + " frame(s)."); - - //memset(bin_ptr, 0, 240); - - //auto raw_ptr = frames[0].get_raw_data(); - - // The preamble isn't manchester encoded - //memcpy(bin_ptr, adsb_preamble, 16); - - // Convert to binary with manchester encoding (1 byte per bit, faster for baseband code) - /*for (c = 0; c < 112; c++) { - if ((raw_ptr[c >> 3] << (c & 7)) & 0x80) { - bin_ptr[(c * 2) + 16] = 1; - bin_ptr[(c * 2) + 16 + 1] = 0; - } else { - bin_ptr[(c * 2) + 16] = 0; - bin_ptr[(c * 2) + 16 + 1] = 1; - } - }*/ - - /*manchester_encode(bin_ptr + 16, raw_ptr, 112, 0); - - // Display in hex for debug - text_frame.set(to_string_hex_array(frames[0].get_raw_data(), 14)); - - button_callsign.set_text(callsign);*/ +msg_t ADSBTXThread::static_fn(void* arg) { + auto obj = static_cast(arg); + obj->run(); + return 0; } -void ADSBTxView::start_tx() { - generate_frames(); - - transmitter_model.set_sampling_rate(4000000U); - transmitter_model.set_rf_amp(true); - transmitter_model.set_baseband_bandwidth(10000000); - transmitter_model.enable(); - - baseband::set_adsb(); -} - -void ADSBTxView::on_txdone(const bool v) { - (void)v; - /*if (v) { - transmitter_model.disable(); - tx_view.set_transmitting(false); - }*/ -} - -void ADSBTxView::rotate_frames() { +void ADSBTXThread::run() { uint8_t * bin_ptr = shared_memory.bb_data.data; uint8_t * raw_ptr; uint32_t frame_index = 0; //, plane_index = 0; - uint32_t c; //, regen = 0; + //uint32_t regen = 0; //float offs = 0; - for (;;) { + while( !chThdShouldTerminate() ) { /*if (!regen) { regen = 10; @@ -294,28 +254,24 @@ void ADSBTxView::rotate_frames() { offs += 0.001; }*/ - memset(bin_ptr, 0, 240); + memset(bin_ptr, 0, 256); // 112 bits * 2 parts = 224 should be enough - raw_ptr = frames[frame_index].get_raw_data(); + raw_ptr = frames_[frame_index].get_raw_data(); + // The preamble isn't manchester encoded memcpy(bin_ptr, adsb_preamble, 16); // Convert to binary (1 byte per bit, faster for baseband code) - for (c = 0; c < 112; c++) { - if ((raw_ptr[c >> 3] << (c & 7)) & 0x80) { - bin_ptr[(c * 2) + 16] = 1; - bin_ptr[(c * 2) + 16 + 1] = 0; - } else { - bin_ptr[(c * 2) + 16] = 0; - bin_ptr[(c * 2) + 16 + 1] = 1; - } - } - + manchester_encode(bin_ptr + 16, raw_ptr, 112, 0); + + // Display in hex for debug + //text_frame.set(to_string_hex_array(frames[0].get_raw_data(), 14)); + baseband::set_adsb(); chThdSleepMilliseconds(50); - if (frame_index == frames.size()) { + if (frame_index == frames_.size()) { frame_index = 0; //if (regen) // regen--; @@ -325,6 +281,46 @@ void ADSBTxView::rotate_frames() { } } +void ADSBTxView::focus() { + tab_view.focus(); +} + +ADSBTxView::~ADSBTxView() { + transmitter_model.disable(); + baseband::shutdown(); +} + +void ADSBTxView::generate_frames() { + const uint32_t ICAO_address = sym_icao.value_hex_u64(); + + frames.clear(); + + /* This scheme kinda sucks. Each "tab"'s collect_frames method + * is called to generate its related frame(s). Getting values + * from each widget of each tab would be better ? + * */ + view_position.collect_frames(ICAO_address, frames); + view_callsign.collect_frames(ICAO_address, frames); + view_speed.collect_frames(ICAO_address, frames); + view_squawk.collect_frames(ICAO_address, frames); + + // Show how many frames were generated + //text_frame.set(to_string_dec_uint(frames.size()) + " frame(s)."); +} + +void ADSBTxView::start_tx() { + generate_frames(); + + transmitter_model.set_sampling_rate(4000000U); + transmitter_model.set_rf_amp(true); + transmitter_model.set_baseband_bandwidth(10000000); + transmitter_model.enable(); + + baseband::set_adsb(); + + tx_thread = std::make_unique(frames); +} + ADSBTxView::ADSBTxView( NavigationView& nav ) : nav_ { nav } @@ -349,11 +345,16 @@ ADSBTxView::ADSBTxView( view_speed.set_parent_rect(view_rect); view_squawk.set_parent_rect(view_rect); + tx_view.on_edit_frequency = [this, &nav]() { + auto new_view = nav.push(receiver_model.tuning_frequency()); + new_view->on_changed = [this](rf::Frequency f) { + transmitter_model.set_tuning_frequency(f); + }; + }; + tx_view.on_start = [this]() { start_tx(); tx_view.set_transmitting(true); - // Disable for DEBUG - //rotate_frames(); }; tx_view.on_stop = [this]() { diff --git a/firmware/application/ui_adsb_tx.hpp b/firmware/application/ui_adsb_tx.hpp index ab5bd97f2..98011d7fc 100644 --- a/firmware/application/ui_adsb_tx.hpp +++ b/firmware/application/ui_adsb_tx.hpp @@ -152,6 +152,25 @@ private: }; }; +class ADSBTXThread { +public: + ADSBTXThread(std::vector frames); + ~ADSBTXThread(); + + ADSBTXThread(const ADSBTXThread&) = delete; + ADSBTXThread(ADSBTXThread&&) = delete; + ADSBTXThread& operator=(const ADSBTXThread&) = delete; + ADSBTXThread& operator=(ADSBTXThread&&) = delete; + +private: + std::vector frames_ { }; + Thread* thread { nullptr }; + + static msg_t static_fn(void* arg); + + void run(); +}; + class ADSBTxView : public View { public: ADSBTxView(NavigationView& nav); @@ -203,8 +222,6 @@ private: void start_tx(); void generate_frames(); - void rotate_frames(); - void on_txdone(const bool v); ADSBPositionView view_position { nav_ }; ADSBCallsignView view_callsign { nav_ }; @@ -239,13 +256,7 @@ private: 0 }; - MessageHandlerRegistration message_handler_tx_done { - Message::ID::TXDone, - [this](const Message* const p) { - const auto message = *reinterpret_cast(p); - this->on_txdone(message.done); - } - }; + std::unique_ptr tx_thread { }; }; } /* namespace ui */ diff --git a/firmware/baseband/proc_adsbtx.cpp b/firmware/baseband/proc_adsbtx.cpp index 27d2eb86d..52fc0d779 100644 --- a/firmware/baseband/proc_adsbtx.cpp +++ b/firmware/baseband/proc_adsbtx.cpp @@ -36,65 +36,24 @@ void ADSBTXProcessor::execute(const buffer_c8_t& buffer) { // Or ./dump1090 --freq 434000000 --gain 20 --interactive --net --net-http-port 8080 --net-beast if (!configured) return; - - /*if (terminate) { - for (size_t i = 0; i < buffer.count; i++) { + + for (size_t i = 0; i < buffer.count; i++) { + if (bit_pos >= (240 << 1)) { + configured = false; + cur_bit = 0; + } else { + cur_bit = shared_memory.bb_data.data[bit_pos >> 1]; + bit_pos++; + } + + if (cur_bit) { + // Crude AM + buffer.p[i] = am_lut[phase & 3]; + phase++; + } else { buffer.p[i] = { 0, 0 }; } - terminate--; - if (!terminate) { - message.done = true; - shared_memory.application_queue.push(message); - configured = false; - return; - } - } else {*/ - - for (size_t i = 0; i < buffer.count; i++) { - - /*if (active) { - if (!sample) { - sample = 300; - if (bit_pos >= 112) { - active = false; // Stop - cur_bit = 0; - } else { - cur_bit = shared_memory.bb_data.data[bit_pos]; - bit_pos++; - } - } else - sample--; - - if (!preamble) { - if (sample == 150) - cur_bit ^= 1; // Invert - } - } else {*/ - /*cur_bit = 0; - if (bit_pos >= 16384) { - configured = false; - message.done = true; - shared_memory.application_queue.push(message); - }*/ - if (bit_pos >= (240 << 1)) { - configured = false; - terminate = 100; - cur_bit = 0; - } else { - cur_bit = shared_memory.bb_data.data[bit_pos >> 1]; - bit_pos++; - } - //} - - if (cur_bit) { - // Crude AM - buffer.p[i] = am_lut[phase & 3]; - phase++; - } else { - buffer.p[i] = { 0, 0 }; - } - } - //} + } } void ADSBTXProcessor::on_message(const Message* const p) { @@ -103,9 +62,7 @@ void ADSBTXProcessor::on_message(const Message* const p) { if (message.id == Message::ID::ADSBConfigure) { bit_pos = 0; phase = 0; - active = true; configured = true; - terminate = 0; } } diff --git a/firmware/baseband/proc_adsbtx.hpp b/firmware/baseband/proc_adsbtx.hpp index 2567dc696..6d2b8d358 100644 --- a/firmware/baseband/proc_adsbtx.hpp +++ b/firmware/baseband/proc_adsbtx.hpp @@ -44,8 +44,6 @@ private: { 0, -127 } }; - bool active { }; - uint32_t terminate { }; uint32_t bit_pos { 0 }; uint32_t cur_bit { 0 }; uint32_t phase { 0 }; diff --git a/firmware/common/manchester.cpp b/firmware/common/manchester.cpp index 100710db0..8c02ad201 100644 --- a/firmware/common/manchester.cpp +++ b/firmware/common/manchester.cpp @@ -70,13 +70,16 @@ FormattedSymbols format_symbols( return { hex_data, hex_error }; } -void manchester_encode(uint8_t * dest, uint8_t * src, size_t length, const size_t sense) { - uint_fast8_t part = sense ? 0 : 0xFF; +void manchester_encode(uint8_t * dest, uint8_t * src, const size_t length, const size_t sense) { + uint8_t part = sense ? 0 : 0xFF; for (size_t c = 0; c < length; c++) { if ((src[c >> 3] << (c & 7)) & 0x80) { *(dest++) = part; *(dest++) = ~part; + } else { + *(dest++) = ~part; + *(dest++) = part; } } } diff --git a/firmware/common/manchester.hpp b/firmware/common/manchester.hpp index 72f3cc8c3..ca2f1e431 100644 --- a/firmware/common/manchester.hpp +++ b/firmware/common/manchester.hpp @@ -67,6 +67,6 @@ FormattedSymbols format_symbols( const ManchesterDecoder& decoder ); -void manchester_encode(uint8_t * dest, uint8_t * src, size_t length, const size_t sense = 0); +void manchester_encode(uint8_t * dest, uint8_t * src, const size_t length, const size_t sense = 0); #endif/*__MANCHESTER_H__*/