diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index ca639cb6a..c948443f5 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -281,13 +281,13 @@ void capture_stop() { send_message(&message); } -void replay_start(CaptureConfig* const config) { - CaptureConfigMessage message { config }; +void replay_start(ReplayConfig* const config) { + ReplayConfigMessage message { config }; send_message(&message); } void replay_stop() { - CaptureConfigMessage message { nullptr }; + ReplayConfigMessage message { nullptr }; send_message(&message); } diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 3a1c34fb9..c7cfc1d52 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -86,7 +86,7 @@ void spectrum_streaming_stop(); void capture_start(CaptureConfig* const config); void capture_stop(); -void replay_start(CaptureConfig* const config); +void replay_start(ReplayConfig* const config); void replay_stop(); } /* namespace baseband */ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 6c2fd90d9..34774bf81 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -23,6 +23,7 @@ // Color bitmaps generated with: // Gimp image > indexed colors (16), then "xxd -i *.bmp" +//BUG: Replay freezes when SD card not present //TODO: CTCSS detector //BUG: RDS doesn't stop baseband when stopping tx ? //BUG: Check AFSK transmit end, skips last bits ? diff --git a/firmware/application/pocsag_app.cpp b/firmware/application/pocsag_app.cpp index 6040d3c50..034685a32 100644 --- a/firmware/application/pocsag_app.cpp +++ b/firmware/application/pocsag_app.cpp @@ -147,10 +147,10 @@ void POCSAGAppView::on_packet(const POCSAGPacketMessage * message) { else { pocsag_decode_batch(message->packet, &pocsag_state); - if ((ignore) && (pocsag_state.out_type == ADDRESS) && (pocsag_state.address == sym_ignore.value_dec_u32())) { + if ((ignore) && (pocsag_state.address == sym_ignore.value_dec_u32())) { // Ignore (inform, but no log) - console.write("\n\x1B\x03" + to_string_time(message->packet.timestamp()) + - " Ignored address " + to_string_dec_uint(pocsag_state.address)); + //console.write("\n\x1B\x03" + to_string_time(message->packet.timestamp()) + + // " Ignored address " + to_string_dec_uint(pocsag_state.address)); return; } @@ -179,9 +179,7 @@ void POCSAGAppView::on_packet(const POCSAGPacketMessage * message) { } else if (pocsag_state.out_type == MESSAGE) { if (pocsag_state.address != last_address) { // New message - console.writeln(console_info); - console.write(pocsag_state.output); last_address = pocsag_state.address; diff --git a/firmware/application/replay_app.cpp b/firmware/application/replay_app.cpp index c84ec945e..7459a48db 100644 --- a/firmware/application/replay_app.cpp +++ b/firmware/application/replay_app.cpp @@ -29,7 +29,6 @@ using namespace portapack; #include "portapack_persistent_memory.hpp" -using namespace portapack; namespace ui { @@ -46,14 +45,14 @@ ReplayAppView::ReplayAppView( return; } - //baseband::run_image(portapack::spi_flash::image_tag_replay); + baseband::run_image(portapack::spi_flash::image_tag_replay); add_children({ &field_frequency, &field_frequency_step, &field_rf_amp, &replay_view, - &waterfall, + //&waterfall, }); replay_view.set_file_list(file_list); @@ -91,16 +90,17 @@ ReplayAppView::~ReplayAppView() { void ReplayAppView::on_hide() { // TODO: Terrible kludge because widget system doesn't notify Waterfall that // it's being shown or hidden. - waterfall.on_hide(); + + //waterfall.on_hide(); View::on_hide(); } -void ReplayAppView::set_parent_rect(const Rect new_parent_rect) { +/*void ReplayAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); const ui::Rect waterfall_rect { 0, header_height, new_parent_rect.width(), static_cast(new_parent_rect.height() - header_height) }; waterfall.set_parent_rect(waterfall_rect); -} +}*/ void ReplayAppView::focus() { field_frequency.focus(); diff --git a/firmware/application/replay_app.hpp b/firmware/application/replay_app.hpp index b5f7ebd67..4c21e4518 100644 --- a/firmware/application/replay_app.hpp +++ b/firmware/application/replay_app.hpp @@ -41,11 +41,11 @@ public: void on_hide() override; - void set_parent_rect(const Rect new_parent_rect) override; + //void set_parent_rect(const Rect new_parent_rect) override; void focus() override; - std::string title() const override { return "Replay (beta)"; }; + std::string title() const override { return "Replay (broken)"; }; private: NavigationView& nav_; @@ -79,7 +79,7 @@ private: 16384, 3 }; - spectrum::WaterfallWidget waterfall { }; + //spectrum::WaterfallWidget waterfall { }; }; } /* namespace ui */ diff --git a/firmware/application/replay_thread.cpp b/firmware/application/replay_thread.cpp index c2c4e5b70..804c34c25 100644 --- a/firmware/application/replay_thread.cpp +++ b/firmware/application/replay_thread.cpp @@ -25,8 +25,12 @@ #include "baseband_api.hpp" #include "buffer_exchange.hpp" +// DEBUG: +#include "hackrf_gpio.hpp" +using namespace hackrf::one; + struct BasebandReplay { - BasebandReplay(CaptureConfig* const config) { + BasebandReplay(ReplayConfig* const config) { baseband::replay_start(config); } @@ -63,13 +67,13 @@ ReplayThread::~ReplayThread() { msg_t ReplayThread::static_fn(void* arg) { auto obj = static_cast(arg); const auto error = obj->run(); - if( error.is_valid() && obj->error_callback ) { + /*if( error.is_valid() && obj->error_callback ) { obj->error_callback(error.value()); } else { if( obj->success_callback ) { obj->success_callback(); } - } + }*/ return 0; } @@ -78,12 +82,15 @@ Optional ReplayThread::run() { BufferExchange buffers { &config }; while( !chThdShouldTerminate() ) { - auto buffer = buffers.get(); - auto read_result = reader->read(buffer->data(), buffer->size()); + //auto buffer = buffers.get(); + buffers.get(); + /*auto read_result = reader->read(buffer->data(), buffer->size()); if( read_result.is_error() ) { return read_result.error(); } - buffers.put(buffer); + buffers.put(buffer);*/ + chThdSleep(50); + //led_tx.toggle(); } return { }; diff --git a/firmware/application/replay_thread.hpp b/firmware/application/replay_thread.hpp index 87d9b6082..1ffbb4611 100644 --- a/firmware/application/replay_thread.hpp +++ b/firmware/application/replay_thread.hpp @@ -50,12 +50,12 @@ public: ReplayThread& operator=(const ReplayThread&) = delete; ReplayThread& operator=(ReplayThread&&) = delete; - const CaptureConfig& state() const { + const ReplayConfig& state() const { return config; } private: - CaptureConfig config; + ReplayConfig config; std::unique_ptr reader; std::function success_callback; std::function error_callback; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index a8134a085..3a4ea93a7 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -360,7 +360,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { { "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push(); } }, { "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push(); } }, { "Capture", ui::Color::blue(), &bitmap_icon_capture, [&nav](){ nav.push(); } }, - { "Replay", ui::Color::grey(), &bitmap_icon_replay, [&nav](){ nav.push(); } }, // ReplayAppView + { "Replay", ui::Color::blue(), &bitmap_icon_replay, [&nav](){ nav.push(); } }, // ReplayAppView { "Audio transmitters", ui::Color::green(), &bitmap_icon_audiotx, [&nav](){ nav.push(); } }, { "Code transmitters", ui::Color::green(), &bitmap_icon_codetx, [&nav](){ nav.push(); } }, { "SSTV transmitter", ui::Color::dark_green(), &bitmap_icon_sstv, [&nav](){ nav.push(); } }, diff --git a/firmware/application/ui_replay_view.cpp b/firmware/application/ui_replay_view.cpp index d31a6b9d7..c4e00100b 100644 --- a/firmware/application/ui_replay_view.cpp +++ b/firmware/application/ui_replay_view.cpp @@ -72,13 +72,13 @@ ReplayView::ReplayView( this->toggle(); }; - signal_token_tick_second = rtc_time::signal_tick_second += [this]() { + /*signal_token_tick_second = rtc_time::signal_tick_second += [this]() { this->on_tick_second(); - }; + };*/ } ReplayView::~ReplayView() { - rtc_time::signal_tick_second -= signal_token_tick_second; + //rtc_time::signal_tick_second -= signal_token_tick_second; } void ReplayView::focus() { @@ -97,7 +97,6 @@ void ReplayView::set_file_list(const std::vector& file_li options_files.set_options(file_options); options_files.set_selected_index(0); // First file on_file_changed(file_options[0].second); - } bool ReplayView::is_active() const { @@ -136,8 +135,8 @@ void ReplayView::start() { update_status_display(); radio::enable({ - 460000000, //target_frequency(), - 4000000, //sampling_rate, + 434000000, //target_frequency(), + sampling_rate, 2500000, //baseband_bandwidth, rf::Direction::Transmit, receiver_model.rf_amp(), diff --git a/firmware/application/ui_replay_view.hpp b/firmware/application/ui_replay_view.hpp index b0ff71a61..6333d6494 100644 --- a/firmware/application/ui_replay_view.hpp +++ b/firmware/application/ui_replay_view.hpp @@ -59,7 +59,7 @@ private: using option_t = std::pair; using options_t = std::vector; - static constexpr uint32_t sampling_rate = 4000000; + static constexpr uint32_t sampling_rate = 500000; void toggle(); @@ -72,7 +72,7 @@ private: const size_t read_size; const size_t buffer_count; - SignalToken signal_token_tick_second { }; + //SignalToken signal_token_tick_second { }; options_t file_options { }; Rectangle rect_background { diff --git a/firmware/baseband/proc_replay.cpp b/firmware/baseband/proc_replay.cpp index 9cf936a54..652c52140 100644 --- a/firmware/baseband/proc_replay.cpp +++ b/firmware/baseband/proc_replay.cpp @@ -39,15 +39,21 @@ void ReplayProcessor::execute(const buffer_c8_t& buffer) { //const auto& decimator_out = decim_1_out; //const auto& channel = decimator_out; - if( stream ) { - const size_t bytes_to_read = buffer.count; // ? - const auto result = stream->read(iq_buffer.p, bytes_to_read); - } - - //feed_channel_stats(channel); + size_t pos = 0; - for (size_t i = 0; i < buffer.count; i++) { - buffer.p[i] = { iq_buffer.p[i].real() >> 8, iq_buffer.p[i].imag() >> 8}; + for (size_t c = 0; c < 4; c++) { + if( stream ) { + const size_t bytes_to_read = sizeof(*buffer.p) * buffer.count / 4; // ? + const auto result = stream->read(iq_buffer.p, bytes_to_read); + } + + //feed_channel_stats(channel); + + for (size_t i = 0; i < (buffer.count / 4); i++) { + buffer.p[pos] = { iq_buffer.p[i].real() >> 8, iq_buffer.p[i].imag() >> 8 }; + pos++; + //buffer.p[i] = { iq_buffer.p[i].real(), iq_buffer.p[i].imag() }; + } } /*spectrum_samples += channel.count; diff --git a/firmware/baseband/proc_replay.hpp b/firmware/baseband/proc_replay.hpp index 2e15c0892..9b1fbb2ff 100644 --- a/firmware/baseband/proc_replay.hpp +++ b/firmware/baseband/proc_replay.hpp @@ -46,13 +46,13 @@ public: private: // TODO: Repeated value needs to be transmitted from application side. - static constexpr size_t baseband_fs = 4000000; + static constexpr size_t baseband_fs = 500000; //static constexpr auto spectrum_rate_hz = 50.0f; BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit }; //RSSIThread rssi_thread { NORMALPRIO + 10 }; - std::array iq { }; + std::array iq { }; // 2048 const buffer_c16_t iq_buffer { iq.data(), iq.size() diff --git a/firmware/baseband/stream_input.cpp b/firmware/baseband/stream_input.cpp index f383be9c6..ead2d40de 100644 --- a/firmware/baseband/stream_input.cpp +++ b/firmware/baseband/stream_input.cpp @@ -57,7 +57,7 @@ size_t StreamInput::write(const void* const data, const size_t length) { if( active_buffer->is_full() ) { if( !fifo_buffers_full.in(active_buffer) ) { - // FIFO is fuil of buffers, there's no place for this one. + // FIFO is full of buffers, there's no place for this one. // Bail out of the loop, and try submitting the buffer in the // next pass. // This should never happen if the number of buffers is less diff --git a/firmware/baseband/stream_output.cpp b/firmware/baseband/stream_output.cpp index 4d1d8b282..b4ea06ec7 100644 --- a/firmware/baseband/stream_output.cpp +++ b/firmware/baseband/stream_output.cpp @@ -40,29 +40,30 @@ StreamOutput::StreamOutput(ReplayConfig* const config) : } } -size_t StreamOutput::read(const void* const data, const size_t length) { - const uint8_t* p = static_cast(data); - size_t written = 0; +size_t StreamOutput::read(void* const data, const size_t length) { + uint8_t* p = static_cast(data); + size_t read = 0; - while( written < length ) { + while( read < length ) { if( !active_buffer ) { - // We need an empty buffer... - if( !fifo_buffers_empty.out(active_buffer) ) { + // We need a full buffer... + if( !fifo_buffers_full.out(active_buffer) ) { // ...but none are available. Samples were dropped. + //active_buffer = nullptr; // Testing ! Jumpstart + creg::m4txevent::assert(); break; } } - const auto remaining = length - written; - written += active_buffer->write(&p[written], remaining); + const auto remaining = length - read; + read += active_buffer->read(&p[read], remaining); + //buffer->empty(); - if( active_buffer->is_full() ) { - if( !fifo_buffers_full.in(active_buffer) ) { - // FIFO is fuil of buffers, there's no place for this one. - // Bail out of the loop, and try submitting the buffer in the + if( active_buffer->is_empty() ) { + if( !fifo_buffers_empty.in(active_buffer) ) { + // FIFO is completly empty. + // Bail out of the loop, and try retrieving the buffer in the // next pass. - // This should never happen if the number of buffers is less - // than the capacity of the FIFO. break; } active_buffer = nullptr; @@ -70,7 +71,7 @@ size_t StreamOutput::read(const void* const data, const size_t length) { } } - config->baseband_bytes_sent += length; + config->baseband_bytes_received += length; - return written; + return read; } diff --git a/firmware/baseband/stream_output.hpp b/firmware/baseband/stream_output.hpp index ae9de5d02..4b468f2d2 100644 --- a/firmware/baseband/stream_output.hpp +++ b/firmware/baseband/stream_output.hpp @@ -40,7 +40,7 @@ public: StreamOutput& operator=(const StreamOutput&) = delete; StreamOutput& operator=(StreamOutput&&) = delete; - size_t read(const void* const data, const size_t length); + size_t read(void* const data, const size_t length); private: static constexpr size_t buffer_count_max_log2 = 3; diff --git a/firmware/common/buffer_exchange.cpp b/firmware/common/buffer_exchange.cpp index 37bc47f1c..2fb7aff69 100644 --- a/firmware/common/buffer_exchange.cpp +++ b/firmware/common/buffer_exchange.cpp @@ -21,17 +21,32 @@ #include "buffer_exchange.hpp" +// DEBUG: +#include "hackrf_gpio.hpp" +using namespace hackrf::one; + BufferExchange* BufferExchange::obj { nullptr }; BufferExchange::BufferExchange( CaptureConfig* const config -) : config { config } +) // : config_capture { config } { obj = this; + direction = CAPTURE; fifo_buffers_for_baseband = config->fifo_buffers_empty; fifo_buffers_for_application = config->fifo_buffers_full; } +BufferExchange::BufferExchange( + ReplayConfig* const config +) // : config_replay { config } +{ + obj = this; + direction = REPLAY; + fifo_buffers_for_baseband = config->fifo_buffers_full; + fifo_buffers_for_application = config->fifo_buffers_empty; +} + BufferExchange::~BufferExchange() { obj = nullptr; fifo_buffers_for_baseband = nullptr; @@ -42,6 +57,9 @@ StreamBuffer* BufferExchange::get(FIFO* fifo) { while(true) { StreamBuffer* p { nullptr }; fifo->out(p); + + led_tx.on(); // DEBUG + if( p ) { return p; } diff --git a/firmware/common/buffer_exchange.hpp b/firmware/common/buffer_exchange.hpp index 7029f6063..19e6befaa 100644 --- a/firmware/common/buffer_exchange.hpp +++ b/firmware/common/buffer_exchange.hpp @@ -30,6 +30,7 @@ class BufferExchange { public: BufferExchange(CaptureConfig* const config); + BufferExchange(ReplayConfig* const config); ~BufferExchange(); BufferExchange(const BufferExchange&) = delete; @@ -72,16 +73,25 @@ public: } private: - CaptureConfig* const config; + //CaptureConfig* const config_capture; + //ReplayConfig* const config_replay; FIFO* fifo_buffers_for_baseband { nullptr }; FIFO* fifo_buffers_for_application { nullptr }; Thread* thread { nullptr }; static BufferExchange* obj; + + enum { + CAPTURE, + REPLAY + } direction { }; void check_fifo_isr() { - if( !empty() ) { + //if (!empty() && (direction == CAPTURE)) { + if (!empty()) wakeup_isr(); - } + //} else if (!empty() && (direction == REPLAY)) { + // wakeup_isr(); + //} } void wakeup_isr() { diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 5ff82bbdd..a6b66dcfd 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -458,10 +458,21 @@ public: used_ += copy_size; return copy_size; } + + size_t read(void* p, const size_t count) { + const auto copy_size = std::min(used_, count); + memcpy(p, &data_[used_ - copy_size], copy_size); + used_ -= copy_size; + return copy_size; + } bool is_full() const { return used_ >= capacity_; } + + bool is_empty() const { + return used_ == 0; + } void* data() const { return data_; @@ -525,7 +536,7 @@ public: struct ReplayConfig { const size_t read_size; const size_t buffer_count; - uint64_t baseband_bytes_sent; + uint64_t baseband_bytes_received; FIFO* fifo_buffers_empty; FIFO* fifo_buffers_full; @@ -534,7 +545,7 @@ struct ReplayConfig { const size_t buffer_count ) : read_size { read_size }, buffer_count { buffer_count }, - baseband_bytes_sent { 0 }, + baseband_bytes_received { 0 }, fifo_buffers_empty { nullptr }, fifo_buffers_full { nullptr } { diff --git a/firmware/portapack-h1-havoc.bin b/firmware/portapack-h1-havoc.bin index 848199395..ca0b1beae 100644 Binary files a/firmware/portapack-h1-havoc.bin and b/firmware/portapack-h1-havoc.bin differ