From 857fba6309274a8a25c4119b85b786e495c7a258 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 21 Apr 2016 11:36:07 -0700 Subject: [PATCH 01/64] Change justification of spectrum right tick label. --- firmware/application/ui_spectrum.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index 4362db679..a3b7c896b 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -114,6 +114,7 @@ void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) { (magnitude_n >= 6) ? "M" : (magnitude_n >= 3) ? "k" : ""; const std::string label = to_string_dec_uint(tick_offset) + zero_pad + unit; + const auto label_width = style().font.size_of(label).w; const Coord offset_low = r.left() + x_center - pixel_offset; const Rect tick_low { offset_low, r.top(), 1, r.height() }; @@ -123,7 +124,7 @@ void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) { const Coord offset_high = r.left() + x_center + pixel_offset; const Rect tick_high { offset_high, r.top(), 1, r.height() }; painter.fill_rectangle(tick_high, Color::white()); - painter.draw_string({ offset_high + 2, r.top() }, style(), label ); + painter.draw_string({ offset_high - 2 - label_width, r.top() }, style(), label ); tick_offset += tick_interval; } From ee51d7fa67269da2a07009d82a4efc13ce573274 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 21 Apr 2016 11:45:37 -0700 Subject: [PATCH 02/64] Make room in capture mode for other controls. --- firmware/application/capture_app.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 8888f9f0f..fa3dab6ce 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -94,7 +94,7 @@ public: std::string title() const override { return "Capture"; }; private: - static constexpr ui::Dim header_height = 2 * 16; + static constexpr ui::Dim header_height = 3 * 16; static constexpr uint32_t sampling_rate = 4000000; static constexpr uint32_t baseband_bandwidth = 2500000; @@ -108,7 +108,7 @@ private: void on_vga_changed(int32_t v_db); ImageButton button_start_stop { - { 0 * 8, 0, 2 * 8, 1 * 16 }, + { 0 * 8, 2 * 16, 2 * 8, 1 * 16 }, &bitmap_record, Color::red(), Color::black() From 09a39f780adf75b06a11ca9904e8981ab0ae239d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 21 Apr 2016 11:45:57 -0700 Subject: [PATCH 03/64] Show capture file name. --- firmware/application/capture_app.cpp | 2 ++ firmware/application/capture_app.hpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 617d4e6b2..d8aae140c 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -38,6 +38,7 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { &field_frequency, &field_lna, &field_vga, + &text_record_filename, &waterfall, } }); @@ -106,6 +107,7 @@ void CaptureAppView::on_start_stop() { button_start_stop.set_bitmap(&bitmap_record); } else { const auto filename = next_filename_matching_pattern("BBD_????.C16"); + text_record_filename.set(filename); if( filename.empty() ) { return; } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index fa3dab6ce..4e93bb1c4 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -114,6 +114,11 @@ private: Color::black() }; + Text text_record_filename { + { 3 * 8, 2 * 16, 12 * 8, 16 }, + "", + }; + RSSI rssi { { 21 * 8, 0, 6 * 8, 4 }, }; From 28ca45326dd05a9be2c831c6a93abcd50bd3a35f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 21 Apr 2016 11:54:39 -0700 Subject: [PATCH 04/64] Fix capture mode baseband_fs value. --- firmware/baseband/proc_capture.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/proc_capture.hpp b/firmware/baseband/proc_capture.hpp index 008c10d20..9a8ee0f4e 100644 --- a/firmware/baseband/proc_capture.hpp +++ b/firmware/baseband/proc_capture.hpp @@ -41,7 +41,8 @@ public: void on_message(const Message* const message) override; private: - static constexpr size_t baseband_fs = 2457600; + // TODO: Repeated value needs to be transmitted from application side. + static constexpr size_t baseband_fs = 4000000; static constexpr auto spectrum_rate_hz = 50.0f; std::array dst; From 051a63a222feaba74be0d9099b5e83cf2046eb63 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 21 Apr 2016 11:55:03 -0700 Subject: [PATCH 05/64] Fix and clean up calculation of filter passband in capture mode. --- firmware/baseband/proc_capture.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/firmware/baseband/proc_capture.cpp b/firmware/baseband/proc_capture.cpp index f069c2063..e061e524c 100644 --- a/firmware/baseband/proc_capture.cpp +++ b/firmware/baseband/proc_capture.cpp @@ -34,18 +34,13 @@ CaptureProcessor::CaptureProcessor() { constexpr size_t decim_1_input_fs = decim_0_output_fs; constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; - const auto& channel_filter = decim_1_filter; - constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_decimation = 1; - const size_t channel_filter_output_fs = channel_filter_input_fs / channel_decimation; - decim_0.configure(decim_0_filter.taps, 33554432); decim_1.configure(decim_1_filter.taps, 131072); - channel_filter_pass_f = channel_filter.pass_frequency_normalized * channel_filter_input_fs; - channel_filter_stop_f = channel_filter.stop_frequency_normalized * channel_filter_input_fs; + channel_filter_pass_f = decim_1_filter.pass_frequency_normalized * decim_1_input_fs; + channel_filter_stop_f = decim_1_filter.stop_frequency_normalized * decim_1_input_fs; - spectrum_interval_samples = channel_filter_output_fs / spectrum_rate_hz; + spectrum_interval_samples = decim_1_output_fs / spectrum_rate_hz; spectrum_samples = 0; channel_spectrum.set_decimation_factor(1); From c6505369344bbf44de38e0b4683b4595dff97c94 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 10:01:17 -0700 Subject: [PATCH 06/64] Hide remove_widget() in set_options_widget(). --- firmware/application/analog_audio_app.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 5e4593b4d..7dd4c6d37 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -208,6 +208,8 @@ void AnalogAudioView::remove_options_widget() { } void AnalogAudioView::set_options_widget(std::unique_ptr new_widget) { + remove_options_widget(); + if( new_widget ) { options_widget = std::move(new_widget); add_child(options_widget.get()); @@ -215,9 +217,6 @@ void AnalogAudioView::set_options_widget(std::unique_ptr new_widget) { } void AnalogAudioView::on_show_options_frequency() { - // TODO: This approach of managing options views is error-prone and unsustainable! - remove_options_widget(); - field_frequency.set_style(&style_options_group); auto widget = std::make_unique(options_view_rect, &style_options_group); @@ -235,9 +234,6 @@ void AnalogAudioView::on_show_options_frequency() { } void AnalogAudioView::on_show_options_rf_gain() { - // TODO: This approach of managing options views is error-prone and unsustainable! - remove_options_widget(); - field_lna.set_style(&style_options_group); auto widget = std::make_unique(options_view_rect, &style_options_group); @@ -251,9 +247,6 @@ void AnalogAudioView::on_show_options_rf_gain() { } void AnalogAudioView::on_show_options_modulation() { - // TODO: This approach of managing options views is error-prone and unsustainable! - remove_options_widget(); - const auto modulation = static_cast(receiver_model.modulation()); if( modulation == ReceiverModel::Mode::AMAudio ) { options_modulation.set_style(&style_options_group); From 760c73a7beee4cda095a94d84303cba62ceaf253 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 10:16:42 -0700 Subject: [PATCH 07/64] Move field.set_style()s after all participating widgets' styles are reset. --- firmware/application/analog_audio_app.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 7dd4c6d37..f6fd732ec 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -217,8 +217,6 @@ void AnalogAudioView::set_options_widget(std::unique_ptr new_widget) { } void AnalogAudioView::on_show_options_frequency() { - field_frequency.set_style(&style_options_group); - auto widget = std::make_unique(options_view_rect, &style_options_group); widget->set_step(receiver_model.frequency_step()); @@ -231,11 +229,10 @@ void AnalogAudioView::on_show_options_frequency() { }; set_options_widget(std::move(widget)); + field_frequency.set_style(&style_options_group); } void AnalogAudioView::on_show_options_rf_gain() { - field_lna.set_style(&style_options_group); - auto widget = std::make_unique(options_view_rect, &style_options_group); widget->set_rf_amp(receiver_model.rf_amp()); @@ -244,19 +241,20 @@ void AnalogAudioView::on_show_options_rf_gain() { }; set_options_widget(std::move(widget)); + field_lna.set_style(&style_options_group); } void AnalogAudioView::on_show_options_modulation() { const auto modulation = static_cast(receiver_model.modulation()); if( modulation == ReceiverModel::Mode::AMAudio ) { - options_modulation.set_style(&style_options_group); auto widget = std::make_unique(options_view_rect, &style_options_group); set_options_widget(std::move(widget)); + options_modulation.set_style(&style_options_group); } if( modulation == ReceiverModel::Mode::NarrowbandFMAudio ) { - options_modulation.set_style(&style_options_group); auto widget = std::make_unique(options_view_rect, &style_options_group); set_options_widget(std::move(widget)); + options_modulation.set_style(&style_options_group); } } From 61b5faf8b5d1212efbed1f4acc0bf14a514b7cc0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 10:22:47 -0700 Subject: [PATCH 08/64] Clean up AnalogAudioView::on_show_options_modulation(). --- firmware/application/analog_audio_app.cpp | 25 +++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index f6fd732ec..60502ff41 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -245,17 +245,24 @@ void AnalogAudioView::on_show_options_rf_gain() { } void AnalogAudioView::on_show_options_modulation() { + std::unique_ptr widget; + const auto modulation = static_cast(receiver_model.modulation()); - if( modulation == ReceiverModel::Mode::AMAudio ) { - auto widget = std::make_unique(options_view_rect, &style_options_group); - set_options_widget(std::move(widget)); - options_modulation.set_style(&style_options_group); - } - if( modulation == ReceiverModel::Mode::NarrowbandFMAudio ) { - auto widget = std::make_unique(options_view_rect, &style_options_group); - set_options_widget(std::move(widget)); - options_modulation.set_style(&style_options_group); + switch(modulation) { + case ReceiverModel::Mode::AMAudio: + widget = std::make_unique(options_view_rect, &style_options_group); + break; + + case ReceiverModel::Mode::NarrowbandFMAudio: + widget = std::make_unique(options_view_rect, &style_options_group); + break; + + default: + break; } + + set_options_widget(std::move(widget)); + options_modulation.set_style(&style_options_group); } void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) { From 27a14233093d89163c5b0fc26865b71475620902 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 11:18:35 -0700 Subject: [PATCH 09/64] De-constexpr a few UI constructors. Because it was silly. --- firmware/application/ui_audio.hpp | 2 +- firmware/application/ui_channel.hpp | 2 +- firmware/application/ui_debug.hpp | 2 +- firmware/application/ui_rssi.hpp | 2 +- firmware/common/ui_widget.hpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/application/ui_audio.hpp b/firmware/application/ui_audio.hpp index cecacc7ac..00d7f908c 100644 --- a/firmware/application/ui_audio.hpp +++ b/firmware/application/ui_audio.hpp @@ -34,7 +34,7 @@ namespace ui { class Audio : public Widget { public: - constexpr Audio( + Audio( const Rect parent_rect ) : Widget { parent_rect }, rms_db_ { -120 }, diff --git a/firmware/application/ui_channel.hpp b/firmware/application/ui_channel.hpp index 97ac61c8b..3b7f49691 100644 --- a/firmware/application/ui_channel.hpp +++ b/firmware/application/ui_channel.hpp @@ -34,7 +34,7 @@ namespace ui { class Channel : public Widget { public: - constexpr Channel( + Channel( const Rect parent_rect ) : Widget { parent_rect }, max_db_ { -120 } diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 779461cc7..e6297c14f 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -84,7 +84,7 @@ private: class TemperatureWidget : public Widget { public: - explicit constexpr TemperatureWidget( + explicit TemperatureWidget( Rect parent_rect ) : Widget { parent_rect } { diff --git a/firmware/application/ui_rssi.hpp b/firmware/application/ui_rssi.hpp index b8f8259e0..5c4570391 100644 --- a/firmware/application/ui_rssi.hpp +++ b/firmware/application/ui_rssi.hpp @@ -34,7 +34,7 @@ namespace ui { class RSSI : public Widget { public: - constexpr RSSI( + RSSI( const Rect parent_rect ) : Widget { parent_rect }, min_ { 0 }, diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 4a3e080c7..1b99d282e 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -51,12 +51,12 @@ private: class Widget { public: - constexpr Widget( + Widget( ) : parent_rect { } { } - constexpr Widget( + Widget( Rect parent_rect ) : parent_rect { parent_rect } { From f2453dd63938fef67b41d4019ebfcd0c9d8755b2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 11:57:46 -0700 Subject: [PATCH 10/64] Consolidate bitmaps for reuse. --- firmware/application/bitmap.hpp | 156 ++++++++++++++++++ firmware/application/capture_app.hpp | 48 +----- firmware/application/ui_navigation.hpp | 48 +----- .../application/ui_sd_card_status_view.cpp | 37 +---- 4 files changed, 163 insertions(+), 126 deletions(-) create mode 100644 firmware/application/bitmap.hpp diff --git a/firmware/application/bitmap.hpp b/firmware/application/bitmap.hpp new file mode 100644 index 000000000..79906dfbd --- /dev/null +++ b/firmware/application/bitmap.hpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __BITMAP_HPP__ +#define __BITMAP_HPP__ + +#include "ui.hpp" + +namespace ui { + +static constexpr uint8_t bitmap_record_data[] = { + 0x00, 0x00, + 0x00, 0x00, + 0xc0, 0x03, + 0xf0, 0x0f, + 0xf8, 0x1f, + 0xf8, 0x1f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xf8, 0x1f, + 0xf8, 0x1f, + 0xf0, 0x0f, + 0xc0, 0x03, + 0x00, 0x00, + 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_record { + { 16, 16 }, bitmap_record_data +}; + +static constexpr uint8_t bitmap_stop_data[] = { + 0x00, 0x00, + 0x00, 0x00, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0xfc, 0x3f, + 0x00, 0x00, + 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_stop { + { 16, 16 }, bitmap_stop_data +}; + +static constexpr uint8_t bitmap_sleep_data[] = { + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x04, + 0x00, 0x08, + 0x00, 0x18, + 0x00, 0x18, + 0x00, 0x38, + 0x00, 0x3c, + 0x00, 0x3c, + 0x00, 0x3e, + 0x84, 0x1f, + 0xf8, 0x1f, + 0xf0, 0x0f, + 0xc0, 0x03, + 0x00, 0x00, + 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sleep { + { 16, 16 }, bitmap_sleep_data +}; + +static constexpr uint8_t bitmap_camera_data[] = { + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0xcc, 0x03, + 0xe8, 0x07, + 0xfc, 0x3f, + 0x3c, 0x3c, + 0x9c, 0x39, + 0xdc, 0x3b, + 0xdc, 0x3b, + 0x9c, 0x39, + 0x3c, 0x3c, + 0xfc, 0x3f, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_camera { + { 16, 16 }, bitmap_camera_data +}; + +static constexpr uint8_t bitmap_sd_card_ok_data[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sd_card_ok { + { 16, 16 }, bitmap_sd_card_ok_data +}; + +static constexpr uint8_t bitmap_sd_card_unknown_data[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, + 0x38, 0x1c, 0x98, 0x19, 0xf8, 0x19, 0xf8, 0x1c, + 0x78, 0x1e, 0x78, 0x1e, 0xf8, 0x1f, 0x78, 0x1e, + 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sd_card_unknown { + { 16, 16 }, bitmap_sd_card_unknown_data +}; + +static constexpr uint8_t bitmap_sd_card_error_data[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, + 0xf8, 0x1f, 0xd8, 0x1b, 0x98, 0x19, 0x38, 0x1c, + 0x78, 0x1e, 0x38, 0x1c, 0x98, 0x19, 0xd8, 0x1b, + 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sd_card_error { + { 16, 16 }, bitmap_sd_card_error_data +}; + +} /* namespace ui */ + +#endif/*__BITMAP_HPP__*/ diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 4e93bb1c4..91bf8ba8e 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -27,6 +27,8 @@ #include "ui_receiver.hpp" #include "ui_spectrum.hpp" +#include "bitmap.hpp" + #include "audio_thread.hpp" #include @@ -34,52 +36,6 @@ namespace ui { -static constexpr uint8_t bitmap_record_data[] = { - 0x00, 0x00, - 0x00, 0x00, - 0xc0, 0x03, - 0xf0, 0x0f, - 0xf8, 0x1f, - 0xf8, 0x1f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xf8, 0x1f, - 0xf8, 0x1f, - 0xf0, 0x0f, - 0xc0, 0x03, - 0x00, 0x00, - 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_record { - { 16, 16 }, bitmap_record_data -}; - -static constexpr uint8_t bitmap_stop_data[] = { - 0x00, 0x00, - 0x00, 0x00, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0xfc, 0x3f, - 0x00, 0x00, - 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_stop { - { 16, 16 }, bitmap_stop_data -}; - class CaptureAppView : public View { public: CaptureAppView(NavigationView& nav); diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 004ddc0d4..be5fb3c46 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -32,57 +32,13 @@ #include "ui_audio.hpp" #include "ui_sd_card_status_view.hpp" +#include "bitmap.hpp" + #include #include namespace ui { -static constexpr uint8_t bitmap_sleep_data[] = { - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x04, - 0x00, 0x08, - 0x00, 0x18, - 0x00, 0x18, - 0x00, 0x38, - 0x00, 0x3c, - 0x00, 0x3c, - 0x00, 0x3e, - 0x84, 0x1f, - 0xf8, 0x1f, - 0xf0, 0x0f, - 0xc0, 0x03, - 0x00, 0x00, - 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_sleep { - { 16, 16 }, bitmap_sleep_data -}; - -static constexpr uint8_t bitmap_camera_data[] = { - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0xcc, 0x03, - 0xe8, 0x07, - 0xfc, 0x3f, - 0x3c, 0x3c, - 0x9c, 0x39, - 0xdc, 0x3b, - 0xdc, 0x3b, - 0x9c, 0x39, - 0x3c, 0x3c, - 0xfc, 0x3f, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_camera { - { 16, 16 }, bitmap_camera_data -}; - class SystemStatusView : public View { public: std::function on_back; diff --git a/firmware/application/ui_sd_card_status_view.cpp b/firmware/application/ui_sd_card_status_view.cpp index 567d9d994..a0ed49b44 100644 --- a/firmware/application/ui_sd_card_status_view.cpp +++ b/firmware/application/ui_sd_card_status_view.cpp @@ -24,45 +24,14 @@ #include #include +#include "bitmap.hpp" + namespace ui { /* SDCardStatusView *****************************************************/ namespace detail { -static constexpr uint8_t bitmap_sd_card_ok_data[] = { - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, - 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, - 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, - 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_sd_card_ok { - { 16, 16 }, bitmap_sd_card_ok_data -}; - -static constexpr uint8_t bitmap_sd_card_unknown_data[] = { - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, - 0x38, 0x1c, 0x98, 0x19, 0xf8, 0x19, 0xf8, 0x1c, - 0x78, 0x1e, 0x78, 0x1e, 0xf8, 0x1f, 0x78, 0x1e, - 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_sd_card_unknown { - { 16, 16 }, bitmap_sd_card_unknown_data -}; - -static constexpr uint8_t bitmap_sd_card_error_data[] = { - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, - 0xf8, 0x1f, 0xd8, 0x1b, 0x98, 0x19, 0x38, 0x1c, - 0x78, 0x1e, 0x38, 0x1c, 0x98, 0x19, 0xd8, 0x1b, - 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, -}; - -static constexpr Bitmap bitmap_sd_card_error { - { 16, 16 }, bitmap_sd_card_error_data -}; - const Bitmap& bitmap_sd_card(const sd_card::Status status) { switch(status) { case sd_card::Status::IOError: @@ -113,7 +82,7 @@ const Color color_sd_card(const sd_card::Status status) { SDCardStatusView::SDCardStatusView( const Rect parent_rect -) : Image { parent_rect, &detail::bitmap_sd_card_unknown, detail::color_sd_card_unknown, Color::black() } +) : Image { parent_rect, &bitmap_sd_card_unknown, detail::color_sd_card_unknown, Color::black() } { } From b8196ee2be190a5c4a4b0710f9b9728c912fe767 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 12:08:01 -0700 Subject: [PATCH 11/64] Rename capture UI record objects and functions. --- firmware/application/capture_app.cpp | 14 +++++++------- firmware/application/capture_app.hpp | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index d8aae140c..3bb106763 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -32,7 +32,7 @@ namespace ui { CaptureAppView::CaptureAppView(NavigationView& nav) { add_children({ { - &button_start_stop, + &button_record, &rssi, &channel, &field_frequency, @@ -66,8 +66,8 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { this->on_vga_changed(v_db); }; - button_start_stop.on_select = [this](ImageButton&) { - this->on_start_stop(); + button_record.on_select = [this](ImageButton&) { + this->on_record(); }; receiver_model.set_baseband_configuration({ @@ -98,13 +98,13 @@ void CaptureAppView::set_parent_rect(const Rect new_parent_rect) { } void CaptureAppView::focus() { - button_start_stop.focus(); + button_record.focus(); } -void CaptureAppView::on_start_stop() { +void CaptureAppView::on_record() { if( capture_thread ) { capture_thread.reset(); - button_start_stop.set_bitmap(&bitmap_record); + button_record.set_bitmap(&bitmap_record); } else { const auto filename = next_filename_matching_pattern("BBD_????.C16"); text_record_filename.set(filename); @@ -113,7 +113,7 @@ void CaptureAppView::on_start_stop() { } capture_thread = std::make_unique(filename); - button_start_stop.set_bitmap(&bitmap_stop); + button_record.set_bitmap(&bitmap_stop); } } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 91bf8ba8e..6eda1a72f 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -57,13 +57,13 @@ private: std::unique_ptr capture_thread; - void on_start_stop(); + void on_record(); void on_tuning_frequency_changed(rf::Frequency f); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - ImageButton button_start_stop { + ImageButton button_record { { 0 * 8, 2 * 16, 2 * 8, 1 * 16 }, &bitmap_record, Color::red(), From a6538bc48bc591d474bfbecb744173d337f7e340 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 12:15:51 -0700 Subject: [PATCH 12/64] Rename AudioThread -> CaptureThread. ...since it's doing baseband capturing too, and doesn't really know what kind of data it's moving. --- firmware/application/Makefile | 2 +- firmware/application/analog_audio_app.cpp | 4 ++-- firmware/application/analog_audio_app.hpp | 4 ++-- firmware/application/capture_app.cpp | 2 +- firmware/application/capture_app.hpp | 4 ++-- .../{audio_thread.cpp => capture_thread.cpp} | 4 ++-- .../{audio_thread.hpp => capture_thread.hpp} | 16 ++++++++-------- firmware/application/event_m0.cpp | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) rename firmware/application/{audio_thread.cpp => capture_thread.cpp} (92%) rename firmware/application/{audio_thread.hpp => capture_thread.hpp} (91%) diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 05a2fd5e6..5efd06ceb 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -184,7 +184,7 @@ CPPSRC = main.cpp \ file.cpp \ log_file.cpp \ png_writer.cpp \ - audio_thread.cpp \ + capture_thread.cpp \ manchester.cpp \ string_format.cpp \ temperature_logger.cpp \ diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 60502ff41..ce7dc4bf4 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -281,7 +281,7 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { audio::output::mute(); - audio_thread.reset(); + capture_thread.reset(); const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); receiver_model.set_baseband_configuration({ @@ -295,7 +295,7 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { if( !is_wideband_spectrum_mode ) { const auto filename = next_filename_matching_pattern("AUD_????.S16"); if( !filename.empty() ) { - audio_thread = std::make_unique(filename); + capture_thread = std::make_unique(filename); } audio::output::unmute(); } diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index dace3245a..b72443e56 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -27,7 +27,7 @@ #include "ui_receiver.hpp" #include "ui_spectrum.hpp" -#include "audio_thread.hpp" +#include "capture_thread.hpp" #include "ui_font_fixed_8x16.hpp" @@ -144,7 +144,7 @@ private: spectrum::WaterfallWidget waterfall; - std::unique_ptr audio_thread; + std::unique_ptr capture_thread; void on_tuning_frequency_changed(rf::Frequency f); void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 3bb106763..478dcedd3 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -112,7 +112,7 @@ void CaptureAppView::on_record() { return; } - capture_thread = std::make_unique(filename); + capture_thread = std::make_unique(filename); button_record.set_bitmap(&bitmap_stop); } } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 6eda1a72f..cb5ceeb0a 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -29,7 +29,7 @@ #include "bitmap.hpp" -#include "audio_thread.hpp" +#include "capture_thread.hpp" #include #include @@ -55,7 +55,7 @@ private: static constexpr uint32_t sampling_rate = 4000000; static constexpr uint32_t baseband_bandwidth = 2500000; - std::unique_ptr capture_thread; + std::unique_ptr capture_thread; void on_record(); diff --git a/firmware/application/audio_thread.cpp b/firmware/application/capture_thread.cpp similarity index 92% rename from firmware/application/audio_thread.cpp rename to firmware/application/capture_thread.cpp index eed061095..a441350a2 100644 --- a/firmware/application/audio_thread.cpp +++ b/firmware/application/capture_thread.cpp @@ -19,6 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#include "audio_thread.hpp" +#include "capture_thread.hpp" -Thread* AudioThread::thread = nullptr; +Thread* CaptureThread::thread = nullptr; diff --git a/firmware/application/audio_thread.hpp b/firmware/application/capture_thread.hpp similarity index 91% rename from firmware/application/audio_thread.hpp rename to firmware/application/capture_thread.hpp index 37802fe82..077731edd 100644 --- a/firmware/application/audio_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __AUDIO_THREAD_H__ -#define __AUDIO_THREAD_H__ +#ifndef __CAPTURE_THREAD_H__ +#define __CAPTURE_THREAD_H__ #include "ch.h" @@ -55,18 +55,18 @@ private: FIFO* const fifo; }; -class AudioThread { +class CaptureThread { public: - AudioThread( + CaptureThread( std::string file_path ) : file_path { std::move(file_path) }, write_buffer { std::make_unique>() } { // Need significant stack for FATFS - thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, AudioThread::static_fn, this); + thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, CaptureThread::static_fn, this); } - ~AudioThread() { + ~CaptureThread() { chThdTerminate(thread); chEvtSignal(thread, EVT_FIFO_HIGHWATER); const auto success = chThdWait(thread); @@ -95,7 +95,7 @@ private: static Thread* thread; static msg_t static_fn(void* arg) { - auto obj = static_cast(arg); + auto obj = static_cast(arg); return obj->run(); } @@ -142,4 +142,4 @@ private: } }; -#endif/*__AUDIO_THREAD_H__*/ +#endif/*__CAPTURE_THREAD_H__*/ diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index af12bee1f..28aaeb501 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -31,7 +31,7 @@ #include "irq_controls.hpp" -#include "audio_thread.hpp" +#include "capture_thread.hpp" #include "ch.h" @@ -46,7 +46,7 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - AudioThread::check_fifo_isr(); + CaptureThread::check_fifo_isr(); EventDispatcher::events_flag_isr(EVT_MASK_APPLICATION); chSysUnlockFromIsr(); From adf573be20a30e4a74f5faee0262b25d695a97d7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 12:30:02 -0700 Subject: [PATCH 13/64] Add simple record UI to audio app. --- firmware/application/analog_audio_app.cpp | 40 ++++++++++++++++++++--- firmware/application/analog_audio_app.hpp | 19 ++++++++++- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index ce7dc4bf4..cb8684cd2 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -84,6 +84,8 @@ AnalogAudioView::AnalogAudioView( &field_vga, &options_modulation, &field_volume, + &button_record, + &text_record_filename, &waterfall, } }); @@ -136,6 +138,10 @@ AnalogAudioView::AnalogAudioView( this->on_headphone_volume_changed(v); }; + button_record.on_select = [this](ImageButton&) { + this->on_record(); + }; + audio::output::start(); update_modulation(static_cast(modulation)); @@ -281,7 +287,7 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { audio::output::mute(); - capture_thread.reset(); + record_stop(); const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); receiver_model.set_baseband_configuration({ @@ -293,12 +299,36 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { receiver_model.enable(); if( !is_wideband_spectrum_mode ) { - const auto filename = next_filename_matching_pattern("AUD_????.S16"); - if( !filename.empty() ) { - capture_thread = std::make_unique(filename); - } audio::output::unmute(); } } +bool AnalogAudioView::is_recording() const { + return (bool)capture_thread; +} + +void AnalogAudioView::on_record() { + if( is_recording() ) { + record_stop(); + } else { + record_start(); + } +} + +void AnalogAudioView::record_start() { + const auto filename = next_filename_matching_pattern("AUD_????.S16"); + text_record_filename.set(filename); + if( filename.empty() ) { + return; + } + + capture_thread = std::make_unique(filename); + button_record.set_bitmap(&bitmap_stop); +} + +void AnalogAudioView::record_stop() { + capture_thread.reset(); + button_record.set_bitmap(&bitmap_record); +} + } /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index b72443e56..4f988823c 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -93,7 +93,7 @@ public: void focus() override; private: - static constexpr ui::Dim header_height = 2 * 16; + static constexpr ui::Dim header_height = 3 * 16; const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }; @@ -142,6 +142,18 @@ private: std::unique_ptr options_widget; + ImageButton button_record { + { 0 * 8, 2 * 16, 2 * 8, 1 * 16 }, + &bitmap_record, + Color::red(), + Color::black() + }; + + Text text_record_filename { + { 3 * 8, 2 * 16, 12 * 8, 16 }, + "", + }; + spectrum::WaterfallWidget waterfall; std::unique_ptr capture_thread; @@ -164,6 +176,11 @@ private: void set_options_widget(std::unique_ptr new_widget); void update_modulation(const ReceiverModel::Mode modulation); + + void on_record(); + bool is_recording() const; + void record_start(); + void record_stop(); }; } /* namespace ui */ From 8b8b3947921fb6b2747398b32b63096214f53f36 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Apr 2016 16:21:31 -0700 Subject: [PATCH 14/64] Hide FIFO hack inside StreamOutput. First step in a long refactor and evolution of the capture code. --- firmware/application/capture_thread.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 077731edd..d9977da07 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -38,8 +38,7 @@ using namespace hackrf::one; class StreamOutput { public: StreamOutput( - FIFO* const fifo - ) : fifo { fifo } + ) : fifo { reinterpret_cast*>(shared_memory.FIFO_HACK) } { } @@ -104,12 +103,7 @@ private: return false; } - auto fifo = reinterpret_cast*>(shared_memory.FIFO_HACK); - if( !fifo ) { - return false; - } - - StreamOutput stream { fifo }; + StreamOutput stream; while( !chThdShouldTerminate() ) { chEvtWaitAny(EVT_FIFO_HIGHWATER); From 7436dea51a53ef1862d1e5b54ba3e39e3265497f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Apr 2016 14:54:15 -0700 Subject: [PATCH 15/64] Add CaptureConfig structure and message. --- firmware/common/message.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index effb11267..44d0e5cf9 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -61,6 +61,7 @@ public: ChannelSpectrumConfig = 14, SpectrumStreamingConfig = 15, DisplaySleep = 16, + CaptureConfig = 17, MAX }; @@ -409,6 +410,22 @@ public: const iir_biquad_config_t audio_hpf_config; }; +struct CaptureConfig { + FIFO* fifo { nullptr }; +}; + +class CaptureConfigMessage : public Message { +public: + constexpr CaptureConfigMessage( + CaptureConfig* const config + ) : Message { ID::CaptureConfig }, + config { config } + { + } + + CaptureConfig* const config; +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From 67eb62ec12078498ea6f33c532f74a3668b019c4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Apr 2016 14:55:59 -0700 Subject: [PATCH 16/64] Provide AudioOutput::set_stream(). Assign when wanting to capture audio stream. --- firmware/baseband/audio_output.cpp | 4 ++-- firmware/baseband/audio_output.hpp | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index 05d56d204..8bb1520ac 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -96,8 +96,8 @@ void AudioOutput::fill_audio_buffer(const buffer_f32_t& audio, const bool send_t audio_buffer.p[i].left = audio_buffer.p[i].right = sample_saturated; audio_int[i] = sample_saturated; } - if( send_to_fifo ) { - stream.write(audio_int.data(), audio_buffer.count * sizeof(audio_int[0])); + if( stream && send_to_fifo ) { + stream->write(audio_int.data(), audio_buffer.count * sizeof(audio_int[0])); } feed_audio_stats(audio); diff --git a/firmware/baseband/audio_output.hpp b/firmware/baseband/audio_output.hpp index 3837684a5..6462e061f 100644 --- a/firmware/baseband/audio_output.hpp +++ b/firmware/baseband/audio_output.hpp @@ -32,6 +32,7 @@ #include "audio_stats_collector.hpp" #include +#include class AudioOutput { public: @@ -44,6 +45,10 @@ public: void write(const buffer_s16_t& audio); void write(const buffer_f32_t& audio); + void set_stream(std::unique_ptr new_stream) { + stream = std::move(new_stream); + } + private: static constexpr float k = 32768.0f; static constexpr float ki = 1.0f / k; @@ -54,7 +59,7 @@ private: IIRBiquadFilter deemph; FMSquelch squelch; - StreamInput stream { 14 }; + std::unique_ptr stream; AudioStatsCollector audio_stats; From d5e21ce9727f499bf4e95d55bb8c80e346e386e3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Apr 2016 15:07:44 -0700 Subject: [PATCH 17/64] Use CaptureConfig to share state between cores. Remove awful FIFO_HACK. TODO: Lots of repeated code... TODO: Capture thread is signalled too frequently. --- firmware/application/capture_thread.hpp | 43 +++++++++++++-------- firmware/application/event_m0.cpp | 2 - firmware/baseband/proc_am_audio.cpp | 12 ++++++ firmware/baseband/proc_am_audio.hpp | 1 + firmware/baseband/proc_capture.cpp | 14 ++++++- firmware/baseband/proc_capture.hpp | 2 + firmware/baseband/proc_nfm_audio.cpp | 12 ++++++ firmware/baseband/proc_nfm_audio.hpp | 1 + firmware/baseband/proc_wfm_audio.cpp | 12 ++++++ firmware/baseband/proc_wfm_audio.hpp | 1 + firmware/baseband/stream_input.hpp | 10 +---- firmware/common/portapack_shared_memory.hpp | 1 - 12 files changed, 82 insertions(+), 29 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index d9977da07..357c77204 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -37,21 +37,28 @@ using namespace hackrf::one; class StreamOutput { public: - StreamOutput( - ) : fifo { reinterpret_cast*>(shared_memory.FIFO_HACK) } - { + StreamOutput() { + shared_memory.baseband_queue.push_and_wait( + CaptureConfigMessage { &config } + ); + } + + ~StreamOutput() { + shared_memory.baseband_queue.push_and_wait( + CaptureConfigMessage { nullptr } + ); } size_t available() { - return fifo->len(); + return config.fifo->len(); } size_t read(void* const data, const size_t length) { - return fifo->out(reinterpret_cast(data), length); + return config.fifo->out(reinterpret_cast(data), length); } private: - FIFO* const fifo; + CaptureConfig config; }; class CaptureThread { @@ -66,21 +73,25 @@ public: } ~CaptureThread() { - chThdTerminate(thread); - chEvtSignal(thread, EVT_FIFO_HIGHWATER); - const auto success = chThdWait(thread); + const auto thread_tmp = thread; - if( !success ) { - led_tx.on(); + if( thread_tmp ) { + thread = nullptr; + chThdTerminate(thread_tmp); + chEvtSignal(thread_tmp, EVT_FIFO_HIGHWATER); + const auto success = chThdWait(thread_tmp); + + if( !success ) { + led_tx.on(); + } } } static void check_fifo_isr() { - if( (shared_memory.FIFO_HACK != nullptr) && (thread != nullptr) ) { - auto fifo = reinterpret_cast*>(shared_memory.FIFO_HACK); - if( fifo->len() >= write_size ) { - chEvtSignalI(thread, EVT_FIFO_HIGHWATER); - } + // TODO: Prevent over-signalling by transmitting a set of + // flags from the baseband core. + if( thread ) { + chEvtSignalI(thread, EVT_FIFO_HIGHWATER); } } diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 28aaeb501..2ed05b187 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -255,6 +255,4 @@ void EventDispatcher::init_message_queues() { new (&shared_memory.application_queue) MessageQueue( shared_memory.application_queue_data, SharedMemory::application_queue_k ); - - shared_memory.FIFO_HACK = nullptr; } diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 0a4b5fafe..9af3295e5 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -63,6 +63,10 @@ void NarrowbandAMAudio::on_message(const Message* const message) { configure(*reinterpret_cast(message)); break; + case Message::ID::CaptureConfig: + capture_config(*reinterpret_cast(message)); + break; + default: break; } @@ -93,3 +97,11 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { configured = true; } + +void NarrowbandAMAudio::capture_config(const CaptureConfigMessage& message) { + if( message.config ) { + audio_output.set_stream(std::make_unique(14, *message.config)); + } else { + audio_output.set_stream(nullptr); + } +} diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index af94c4163..051f17034 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -72,6 +72,7 @@ private: bool configured { false }; void configure(const AMConfigureMessage& message); + void capture_config(const CaptureConfigMessage& message); buffer_f32_t demodulate(const buffer_c16_t& channel); }; diff --git a/firmware/baseband/proc_capture.cpp b/firmware/baseband/proc_capture.cpp index e061e524c..e0b0455ab 100644 --- a/firmware/baseband/proc_capture.cpp +++ b/firmware/baseband/proc_capture.cpp @@ -44,8 +44,6 @@ CaptureProcessor::CaptureProcessor() { spectrum_samples = 0; channel_spectrum.set_decimation_factor(1); - - stream = std::make_unique(15); } void CaptureProcessor::execute(const buffer_c8_t& buffer) { @@ -76,7 +74,19 @@ void CaptureProcessor::on_message(const Message* const message) { channel_spectrum.on_message(message); break; + case Message::ID::CaptureConfig: + capture_config(*reinterpret_cast(message)); + break; + default: break; } } + +void CaptureProcessor::capture_config(const CaptureConfigMessage& message) { + if( message.config ) { + stream = std::make_unique(15, *message.config); + } else { + stream.reset(); + } +} diff --git a/firmware/baseband/proc_capture.hpp b/firmware/baseband/proc_capture.hpp index 9a8ee0f4e..e975d99cf 100644 --- a/firmware/baseband/proc_capture.hpp +++ b/firmware/baseband/proc_capture.hpp @@ -61,6 +61,8 @@ private: SpectrumCollector channel_spectrum; size_t spectrum_interval_samples = 0; size_t spectrum_samples = 0; + + void capture_config(const CaptureConfigMessage& message); }; #endif/*__PROC_CAPTURE_HPP__*/ diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 3fd546b93..bdf4421a8 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -53,6 +53,10 @@ void NarrowbandFMAudio::on_message(const Message* const message) { configure(*reinterpret_cast(message)); break; + case Message::ID::CaptureConfig: + capture_config(*reinterpret_cast(message)); + break; + default: break; } @@ -81,3 +85,11 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { configured = true; } + +void NarrowbandFMAudio::capture_config(const CaptureConfigMessage& message) { + if( message.config ) { + audio_output.set_stream(std::make_unique(14, *message.config)); + } else { + audio_output.set_stream(nullptr); + } +} diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index dbae4f5fd..164e0b457 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -66,6 +66,7 @@ private: bool configured { false }; void configure(const NBFMConfigureMessage& message); + void capture_config(const CaptureConfigMessage& message); }; #endif/*__PROC_NFM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 4246a5559..c6f1e1165 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -81,6 +81,10 @@ void WidebandFMAudio::on_message(const Message* const message) { configure(*reinterpret_cast(message)); break; + case Message::ID::CaptureConfig: + capture_config(*reinterpret_cast(message)); + break; + default: break; } @@ -110,3 +114,11 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { configured = true; } + +void WidebandFMAudio::capture_config(const CaptureConfigMessage& message) { + if( message.config ) { + audio_output.set_stream(std::make_unique(15, *message.config)); + } else { + audio_output.set_stream(nullptr); + } +} diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 15f5bf36c..9752f90a0 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -68,6 +68,7 @@ private: bool configured { false }; void configure(const WFMConfigureMessage& message); + void capture_config(const CaptureConfigMessage& message); }; #endif/*__PROC_WFM_AUDIO_H__*/ diff --git a/firmware/baseband/stream_input.hpp b/firmware/baseband/stream_input.hpp index 1b1ec552a..e82214776 100644 --- a/firmware/baseband/stream_input.hpp +++ b/firmware/baseband/stream_input.hpp @@ -32,18 +32,12 @@ class StreamInput { public: - StreamInput(const size_t K) : + StreamInput(const size_t K, CaptureConfig& config) : K { K }, data { std::make_unique(1UL << K) }, fifo { data.get(), K } { - // TODO: Send stream creation message. - shared_memory.FIFO_HACK = &fifo; - } - - ~StreamInput() { - // TODO: Send stream distruction message. - shared_memory.FIFO_HACK = nullptr; + config.fifo = &fifo; } size_t write(const void* const data, const size_t length) { diff --git a/firmware/common/portapack_shared_memory.hpp b/firmware/common/portapack_shared_memory.hpp index 612a3b276..b7b97f390 100644 --- a/firmware/common/portapack_shared_memory.hpp +++ b/firmware/common/portapack_shared_memory.hpp @@ -40,7 +40,6 @@ struct SharedMemory { uint8_t baseband_queue_data[1 << baseband_queue_k]; MessageQueue application_queue; uint8_t application_queue_data[1 << application_queue_k]; - void* FIFO_HACK; // TODO: M0 should directly configure and control DMA channel that is // acquiring ADC samples. From 3103e9b80eeba7ab739fdf215b556ff82adb674d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Apr 2016 17:26:54 -0700 Subject: [PATCH 18/64] Remove unused EventDispatcher::thread_record. --- firmware/application/event_m0.cpp | 1 - firmware/application/event_m0.hpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 2ed05b187..1b34f44fb 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -59,7 +59,6 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { MessageHandlerMap EventDispatcher::message_map_; Thread* EventDispatcher::thread_event_loop = nullptr; -Thread* EventDispatcher::thread_record = nullptr; EventDispatcher::EventDispatcher( ui::Widget* const top_widget, diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 69dcede23..414a3a620 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -73,8 +73,6 @@ public: return message_map_; } - static Thread* thread_record; - private: static MessageHandlerMap message_map_; static Thread* thread_event_loop; From c585f3d4eaf5a4dfb303d8273e6450245f7d844f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Apr 2016 17:28:31 -0700 Subject: [PATCH 19/64] Rename EVT_FIFO_HIGHWATER -> EVT_MASK_CAPTURE_THREAD. --- firmware/application/capture_thread.hpp | 7 +++---- firmware/application/event_m0.hpp | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 357c77204..68806f588 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -78,7 +78,7 @@ public: if( thread_tmp ) { thread = nullptr; chThdTerminate(thread_tmp); - chEvtSignal(thread_tmp, EVT_FIFO_HIGHWATER); + chEvtSignal(thread_tmp, EVT_MASK_CAPTURE_THREAD); const auto success = chThdWait(thread_tmp); if( !success ) { @@ -91,13 +91,12 @@ public: // TODO: Prevent over-signalling by transmitting a set of // flags from the baseband core. if( thread ) { - chEvtSignalI(thread, EVT_FIFO_HIGHWATER); + chEvtSignalI(thread, EVT_MASK_CAPTURE_THREAD); } } private: static constexpr size_t write_size = 16384; - static constexpr eventmask_t EVT_FIFO_HIGHWATER = 1; const std::string file_path; std::unique_ptr> write_buffer; @@ -117,7 +116,7 @@ private: StreamOutput stream; while( !chThdShouldTerminate() ) { - chEvtWaitAny(EVT_FIFO_HIGHWATER); + chEvtWaitAny(EVT_MASK_CAPTURE_THREAD); while( stream.available() >= write_buffer->size() ) { if( !transfer(stream, write_buffer.get()) ) { diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 414a3a620..34b988e89 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -43,6 +43,7 @@ constexpr auto EVT_MASK_SWITCHES = EVENT_MASK(3); constexpr auto EVT_MASK_ENCODER = EVENT_MASK(4); constexpr auto EVT_MASK_TOUCH = EVENT_MASK(5); constexpr auto EVT_MASK_APPLICATION = EVENT_MASK(6); +constexpr auto EVT_MASK_CAPTURE_THREAD = EVENT_MASK(7); class EventDispatcher { public: From ed3ac5249fefd21f82aa312cdf21a444405b2b99 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Apr 2016 21:55:45 -0700 Subject: [PATCH 20/64] Move MessageQueue::signal into .cpp file. --- firmware/common/message_queue.cpp | 15 +++++++++++++++ firmware/common/message_queue.hpp | 16 +--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/firmware/common/message_queue.cpp b/firmware/common/message_queue.cpp index 54e9a2332..3001127d8 100644 --- a/firmware/common/message_queue.cpp +++ b/firmware/common/message_queue.cpp @@ -20,3 +20,18 @@ */ #include "message_queue.hpp" + +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + +#if defined(LPC43XX_M0) +void MessageQueue::signal() { + creg::m0apptxevent::assert(); +} +#endif + +#if defined(LPC43XX_M4) +void MessageQueue::signal() { + creg::m4txevent::assert(); +} +#endif diff --git a/firmware/common/message_queue.hpp b/firmware/common/message_queue.hpp index 76404be06..cd2bacd78 100644 --- a/firmware/common/message_queue.hpp +++ b/firmware/common/message_queue.hpp @@ -27,9 +27,6 @@ #include "message.hpp" #include "fifo.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - #include class MessageQueue { @@ -111,18 +108,7 @@ private: return success; } - -#if defined(LPC43XX_M0) - void signal() { - creg::m0apptxevent::assert(); - } -#endif - -#if defined(LPC43XX_M4) - void signal() { - creg::m4txevent::assert(); - } -#endif + void signal(); }; #endif/*__MESSAGE_QUEUE_H__*/ From 06621969059f61dceaa6d14701f6bec8e3844199 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Apr 2016 13:06:46 -0700 Subject: [PATCH 21/64] Fix audio codec I2C reliability for some HackRF units. --- firmware/application/portapack.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 12bae2243..0aabc219b 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -106,9 +106,23 @@ void init() { } /* Configure other pins */ + /* Glitch filter operates at 3ns instead of 50ns due to the WM8731 + * returning an ACK very fast (170ns) and confusing the I2C state + * machine into thinking there was a bus error. It looks like the + * MCU sees SDA fall before SCL falls, indicating a START at the + * point an ACK is expected. With the glitch filter off or set to + * 3ns, it's probably still a bit tight timing-wise, but improves + * reliability on some problem units. + */ LPC_SCU->SFSI2C0 = - (1U << 3) - | (1U << 11) + (1U << 0) // SCL: 3ns glitch + | (0U << 2) // SCL: Standard/Fast mode + | (1U << 3) // SCL: Input enabled + | (0U << 7) // SCL: Enable input glitch filter + | (1U << 8) // SDA: 3ns glitch + | (0U << 10) // SDA: Standard/Fast mode + | (1U << 11) // SDA: Input enabled + | (0U << 15) // SDA: Enable input glitch filter ; power.init(); From 93ecf9ef82112e0cac54d88dbde2e2bd7d09ca55 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Apr 2016 16:16:04 -0700 Subject: [PATCH 22/64] Remove unused ldscript. --- .../ARMCMx/LPC43xx_M4/ld/LPC4357_M4_flash.ld | 146 ------------------ 1 file changed, 146 deletions(-) delete mode 100644 firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC4357_M4_flash.ld diff --git a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC4357_M4_flash.ld b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC4357_M4_flash.ld deleted file mode 100644 index cf5eb049f..000000000 --- a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC4357_M4_flash.ld +++ /dev/null @@ -1,146 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - Copyright (C) 2014 Jared Boone, ShareBrained Technology - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* - * LPC43xx M4 memory setup. - */ -__main_stack_size__ = 0x1000; /* Exceptions/interrupts stack */ -__process_stack_size__ = 0x6000; /* main() stack */ - -MEMORY -{ - flash : org = 0x00000000, len = 512k /* Flash bank A @ 0x1a000000 */ - ram : org = 0x10080000, len = 40k /* Local SRAM @ 0x10080000 */ -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -ENTRY(ResetHandler) - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - .textalign : ONLY_IF_RO - { - . = ALIGN(8); - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .stacks : - { - . = ALIGN(8); - __main_stack_base__ = .; - . += __main_stack_size__; - . = ALIGN(8); - __main_stack_end__ = .; - __process_stack_base__ = .; - __main_thread_stack_base__ = .; - . += __process_stack_size__; - . = ALIGN(8); - __process_stack_end__ = .; - __main_thread_stack_end__ = .; - } > ram - - .data ALIGN(4) : ALIGN(4) - { - . = ALIGN(4); - PROVIDE(_data = .); - *(.data) - *(.data.*) - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss ALIGN(4) : ALIGN(4) - { - . = ALIGN(4); - PROVIDE(_bss_start = .); - *(.bss) - *(.bss.*) - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__; From 01fc6b9bc921b0cbd089cf375a2bb79b27253901 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Apr 2016 16:17:53 -0700 Subject: [PATCH 23/64] Remove redundant values in I2C struct. --- .../os/hal/platforms/LPC43xx/i2c_lld.c | 17 +++++++++-------- .../os/hal/platforms/LPC43xx/i2c_lld.h | 8 -------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.c b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.c index fa7ffd380..5d0fbb834 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.c +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.c @@ -187,15 +187,15 @@ static void i2c_lld_abort_operation(I2CDriver *i2cp) { } static bool_t i2c_lld_tx_not_done(I2CDriver *i2cp) { - return i2cp->txidx < i2cp->txbytes; + return i2cp->txbytes > 0; } static bool_t i2c_lld_rx_not_done(I2CDriver *i2cp) { - return i2cp->rxbuf && i2cp->rxbytes; + return i2cp->rxbytes > 0; } static bool_t i2c_lld_rx_last_byte(I2CDriver *i2cp) { - return i2cp->rxidx == (i2cp->rxbytes - 1); + return i2cp->rxbytes == 1; } /** @@ -249,7 +249,8 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { case I2C_MASTER_TX_DATA_ACK: /* 0x28 */ if (i2c_lld_tx_not_done(i2cp)) { //i2c_periph_transmit_byte(dp, i2cp->txbuf[i2cp->txidx++]); - dp->DAT = i2cp->txbuf[i2cp->txidx++]; + dp->DAT = *i2cp->txbuf++; + i2cp->txbytes--; dp->CONCLR = I2C_CONCLR_SIC; } else { if (i2c_lld_rx_not_done(i2cp)) { @@ -266,7 +267,8 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_MASTER_RX_DATA_ACK: /* 0x50 */ - i2cp->rxbuf[i2cp->rxidx++] = i2c_periph_read_byte(dp); + *i2cp->rxbuf++ = i2c_periph_read_byte(dp); + i2cp->rxbytes--; /* fall through */ case I2C_MASTER_RX_ADDR_ACK: /* 0x40 */ if (i2c_lld_rx_last_byte(i2cp)) { @@ -277,7 +279,8 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_MASTER_RX_DATA_NACK: /* 0x58 */ - i2cp->rxbuf[i2cp->rxidx] = i2c_periph_read_byte(dp); + *i2cp->rxbuf++ = i2c_periph_read_byte(dp); + i2cp->rxbytes--; i2c_periph_stop(dp); wakeup_isr(i2cp, RDY_OK); /* fall through */ @@ -474,10 +477,8 @@ static msg_t i2c_lld_master_start(I2CDriver *i2cp, uint_fast8_t addr_r, i2cp->addr_r = addr_r; i2cp->txbuf = txbuf; i2cp->txbytes = txbytes; - i2cp->txidx = 0; i2cp->rxbuf = rxbuf; i2cp->rxbytes = rxbytes; - i2cp->rxidx = 0; /* Atomic check on the timer in order to make sure that a timeout didn't happen outside the critical zone.*/ diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.h b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.h index 3db4a8031..71e4c5d05 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.h +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/i2c_lld.h @@ -169,10 +169,6 @@ struct I2CDriver { * @brief Number of bytes of data to send. */ size_t txbytes; - /** - * @brief Current index in buffer when sending data. - */ - size_t txidx; /** * @brief Pointer to the buffer to put received data. */ @@ -181,10 +177,6 @@ struct I2CDriver { * @brief Number of bytes of data to receive. */ size_t rxbytes; - /** - * @brief Current index in buffer when receiving data. - */ - size_t rxidx; /** * @brief Pointer to the I2Cx registers block. */ From 91ee2dbb6784e15213304b7accf6a28ccf04efbf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Apr 2016 22:26:30 -0700 Subject: [PATCH 24/64] Move FIFO and write size to CaptureConfig structure. Now configured from baseband, where write size and appropriate FIFO size is known. --- firmware/application/analog_audio_app.cpp | 2 +- firmware/application/capture_app.cpp | 2 +- firmware/application/capture_thread.cpp | 1 + firmware/application/capture_thread.hpp | 46 ++++++++++++++++------- firmware/application/event_m0.cpp | 3 +- firmware/application/event_m0.hpp | 7 ++++ firmware/baseband/proc_am_audio.cpp | 2 +- firmware/baseband/proc_capture.cpp | 2 +- firmware/baseband/proc_nfm_audio.cpp | 2 +- firmware/baseband/proc_wfm_audio.cpp | 2 +- firmware/baseband/stream_input.hpp | 13 ++++--- firmware/common/message.hpp | 13 ++++++- firmware/common/message_queue.hpp | 8 ++-- 13 files changed, 71 insertions(+), 32 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index cb8684cd2..d68556b18 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -322,7 +322,7 @@ void AnalogAudioView::record_start() { return; } - capture_thread = std::make_unique(filename); + capture_thread = std::make_unique(filename, 12, 2); button_record.set_bitmap(&bitmap_stop); } diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 478dcedd3..d5df1ee22 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -112,7 +112,7 @@ void CaptureAppView::on_record() { return; } - capture_thread = std::make_unique(filename); + capture_thread = std::make_unique(filename, 14, 1); button_record.set_bitmap(&bitmap_stop); } } diff --git a/firmware/application/capture_thread.cpp b/firmware/application/capture_thread.cpp index a441350a2..e39d63121 100644 --- a/firmware/application/capture_thread.cpp +++ b/firmware/application/capture_thread.cpp @@ -21,4 +21,5 @@ #include "capture_thread.hpp" +FIFO* StreamOutput::fifo = nullptr; Thread* CaptureThread::thread = nullptr; diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 68806f588..e43fbcfa4 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -37,13 +37,19 @@ using namespace hackrf::one; class StreamOutput { public: - StreamOutput() { + StreamOutput( + const size_t write_size_log2, + const size_t buffer_count_log2 + ) : config { write_size_log2, buffer_count_log2 } + { shared_memory.baseband_queue.push_and_wait( CaptureConfigMessage { &config } ); + fifo = config.fifo; } ~StreamOutput() { + fifo = nullptr; shared_memory.baseband_queue.push_and_wait( CaptureConfigMessage { nullptr } ); @@ -57,6 +63,8 @@ public: return config.fifo->out(reinterpret_cast(data), length); } + static FIFO* fifo; + private: CaptureConfig config; }; @@ -64,9 +72,13 @@ private: class CaptureThread { public: CaptureThread( - std::string file_path - ) : file_path { std::move(file_path) }, - write_buffer { std::make_unique>() } + std::string file_path, + size_t write_size_log2, + size_t buffer_count_log2 + ) : write_size_log2 { write_size_log2 }, + write_size { 1U << write_size_log2 }, + buffer_count_log2 { buffer_count_log2 }, + file_path { std::move(file_path) } { // Need significant stack for FATFS thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, CaptureThread::static_fn, this); @@ -90,16 +102,17 @@ public: static void check_fifo_isr() { // TODO: Prevent over-signalling by transmitting a set of // flags from the baseband core. - if( thread ) { + const auto fifo = StreamOutput::fifo; + if( fifo ) { chEvtSignalI(thread, EVT_MASK_CAPTURE_THREAD); } } private: - static constexpr size_t write_size = 16384; - + const size_t write_size_log2; + const size_t write_size; + const size_t buffer_count_log2; const std::string file_path; - std::unique_ptr> write_buffer; File file; static Thread* thread; @@ -113,12 +126,17 @@ private: return false; } - StreamOutput stream; + const auto write_buffer = std::make_unique(write_size); + if( !write_buffer ) { + return false; + } + + StreamOutput stream { write_size_log2, buffer_count_log2 }; while( !chThdShouldTerminate() ) { chEvtWaitAny(EVT_MASK_CAPTURE_THREAD); - while( stream.available() >= write_buffer->size() ) { + while( stream.available() >= write_size ) { if( !transfer(stream, write_buffer.get()) ) { return false; } @@ -128,14 +146,14 @@ private: return true; } - bool transfer(StreamOutput& stream, std::array* const write_buffer) { + bool transfer(StreamOutput& stream, uint8_t* const write_buffer) { bool success = false; led_usb.on(); - const auto bytes_to_write = stream.read(write_buffer->data(), write_buffer->size()); - if( bytes_to_write == write_buffer->size() ) { - if( file.write(write_buffer->data(), write_buffer->size()) ) { + const auto bytes_to_write = stream.read(write_buffer, write_size); + if( bytes_to_write == write_size ) { + if( file.write(write_buffer, write_size) ) { success = true; } } diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 1b34f44fb..e82faa3b1 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -22,7 +22,6 @@ #include "event_m0.hpp" #include "portapack.hpp" -#include "portapack_shared_memory.hpp" #include "sd_card.hpp" @@ -47,7 +46,7 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { chSysLockFromIsr(); CaptureThread::check_fifo_isr(); - EventDispatcher::events_flag_isr(EVT_MASK_APPLICATION); + EventDispatcher::check_fifo_isr(); chSysUnlockFromIsr(); creg::m4txevent::clear(); diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 34b988e89..f793eaf79 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -28,6 +28,7 @@ #include "ui_painter.hpp" #include "portapack.hpp" +#include "portapack_shared_memory.hpp" #include "message.hpp" @@ -58,6 +59,12 @@ public: void set_display_sleep(const bool sleep); + static inline void check_fifo_isr() { + if( !shared_memory.application_queue.is_empty() ) { + events_flag_isr(EVT_MASK_APPLICATION); + } + } + static inline void events_flag(const eventmask_t events) { if( thread_event_loop ) { chEvtSignal(thread_event_loop, events); diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 9af3295e5..865ea260f 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -100,7 +100,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { void NarrowbandAMAudio::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - audio_output.set_stream(std::make_unique(14, *message.config)); + audio_output.set_stream(std::make_unique(*message.config)); } else { audio_output.set_stream(nullptr); } diff --git a/firmware/baseband/proc_capture.cpp b/firmware/baseband/proc_capture.cpp index e0b0455ab..bcb30dd92 100644 --- a/firmware/baseband/proc_capture.cpp +++ b/firmware/baseband/proc_capture.cpp @@ -85,7 +85,7 @@ void CaptureProcessor::on_message(const Message* const message) { void CaptureProcessor::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - stream = std::make_unique(15, *message.config); + stream = std::make_unique(*message.config); } else { stream.reset(); } diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index bdf4421a8..190ed4b08 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -88,7 +88,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { void NarrowbandFMAudio::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - audio_output.set_stream(std::make_unique(14, *message.config)); + audio_output.set_stream(std::make_unique(*message.config)); } else { audio_output.set_stream(nullptr); } diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index c6f1e1165..1db24b4cd 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -117,7 +117,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { void WidebandFMAudio::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - audio_output.set_stream(std::make_unique(15, *message.config)); + audio_output.set_stream(std::make_unique(*message.config)); } else { audio_output.set_stream(nullptr); } diff --git a/firmware/baseband/stream_input.hpp b/firmware/baseband/stream_input.hpp index e82214776..db5f353d1 100644 --- a/firmware/baseband/stream_input.hpp +++ b/firmware/baseband/stream_input.hpp @@ -22,18 +22,21 @@ #ifndef __STREAM_INPUT_H__ #define __STREAM_INPUT_H__ -#include "portapack_shared_memory.hpp" - +#include "message.hpp" #include "fifo.hpp" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + #include #include #include class StreamInput { public: - StreamInput(const size_t K, CaptureConfig& config) : - K { K }, + StreamInput(CaptureConfig& config) : + K { config.write_size_log2 + config.buffer_count_log2 }, + event_bytes_mask { (1UL << config.write_size_log2) - 1 }, data { std::make_unique(1UL << K) }, fifo { data.get(), K } { @@ -58,7 +61,7 @@ public: private: const size_t K; - const uint64_t event_bytes_mask = (1ULL << (K - 2)) - 1; + const uint64_t event_bytes_mask; uint64_t bytes_written = 0; std::unique_ptr data; FIFO fifo; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 44d0e5cf9..1c906c611 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -411,7 +411,18 @@ public: }; struct CaptureConfig { - FIFO* fifo { nullptr }; + const size_t write_size_log2; + const size_t buffer_count_log2; + FIFO* fifo; + + constexpr CaptureConfig( + const size_t write_size_log2, + const size_t buffer_count_log2 + ) : write_size_log2 { write_size_log2 }, + buffer_count_log2 { buffer_count_log2 }, + fifo { nullptr } + { + } }; class CaptureConfigMessage : public Message { diff --git a/firmware/common/message_queue.hpp b/firmware/common/message_queue.hpp index cd2bacd78..3e0a1cbb4 100644 --- a/firmware/common/message_queue.hpp +++ b/firmware/common/message_queue.hpp @@ -70,6 +70,10 @@ public: } } + bool is_empty() const { + return fifo.is_empty(); + } + private: FIFO fifo; Mutex mutex_write; @@ -92,10 +96,6 @@ private: return fifo.len(); } - bool is_empty() const { - return fifo.is_empty(); - } - bool push(const void* const buf, const size_t len) { chMtxLock(&mutex_write); const auto result = fifo.in_r(buf, len); From f250f30ada8f00a7ad6e5bc1f67e7088ecbd21f8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Apr 2016 22:37:58 -0700 Subject: [PATCH 25/64] Update compiler to GCC-ARM 2016q1 (20160330) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a6c0b9f8..53af9c24d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ notifications: - "Firmware download : https://portapack-h1-builds.s3.amazonaws.com/%{repository_slug}/%{build_number}/%{build_number}.1/firmware/portapack-h1-firmware-%{commit}.tar.bz2" before_script: - - wget https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 -O /tmp/gcc-arm.tar.bz2 + - wget https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q1-update/+download/gcc-arm-none-eabi-5_3-2016q1-20160330-linux.tar.bz2 -O /tmp/gcc-arm.tar.bz2 - tar -xf /tmp/gcc-arm.tar.bz2 - - export PATH=$PWD/gcc-arm-none-eabi-5_2-2015q4/bin:$PATH + - export PATH=$PWD/gcc-arm-none-eabi-5_3-2016q1/bin:$PATH - export CC="arm-none-eabi-gcc" - export CXX="arm-none-eabi-g++" From 4a348e2c6cb3ec3ef19cbba1b2c5db366842368a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:12:21 -0700 Subject: [PATCH 26/64] Revise CaptureThread loop to not get stuck if SD write speed too slow. --- firmware/application/capture_thread.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index e43fbcfa4..d3b6841bc 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -134,12 +134,12 @@ private: StreamOutput stream { write_size_log2, buffer_count_log2 }; while( !chThdShouldTerminate() ) { - chEvtWaitAny(EVT_MASK_CAPTURE_THREAD); - - while( stream.available() >= write_size ) { + if( stream.available() >= write_size ) { if( !transfer(stream, write_buffer.get()) ) { return false; } + } else { + chEvtWaitAny(EVT_MASK_CAPTURE_THREAD); } } From ca5dadab93d43607626467ce2f050a9b2732a462 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:13:50 -0700 Subject: [PATCH 27/64] Set CaptureThread::thread to null after thread is released. Was having a timing problem where ISR was still trying to signal thread after thread was nulled. --- firmware/application/capture_thread.hpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index d3b6841bc..b48cb1ece 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -85,13 +85,11 @@ public: } ~CaptureThread() { - const auto thread_tmp = thread; - - if( thread_tmp ) { + if( thread ) { + chThdTerminate(thread); + chEvtSignal(thread, EVT_MASK_CAPTURE_THREAD); + const auto success = chThdWait(thread); thread = nullptr; - chThdTerminate(thread_tmp); - chEvtSignal(thread_tmp, EVT_MASK_CAPTURE_THREAD); - const auto success = chThdWait(thread_tmp); if( !success ) { led_tx.on(); From 3e0831801216c95620bfbbd7754c33808dbc33eb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:31:37 -0700 Subject: [PATCH 28/64] Pass CaptureConfig to StreamInput as pointer. --- firmware/baseband/proc_am_audio.cpp | 2 +- firmware/baseband/proc_capture.cpp | 2 +- firmware/baseband/proc_nfm_audio.cpp | 2 +- firmware/baseband/proc_wfm_audio.cpp | 2 +- firmware/baseband/stream_input.hpp | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 865ea260f..f4cb2facc 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -100,7 +100,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { void NarrowbandAMAudio::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - audio_output.set_stream(std::make_unique(*message.config)); + audio_output.set_stream(std::make_unique(message.config)); } else { audio_output.set_stream(nullptr); } diff --git a/firmware/baseband/proc_capture.cpp b/firmware/baseband/proc_capture.cpp index bcb30dd92..56f6a948f 100644 --- a/firmware/baseband/proc_capture.cpp +++ b/firmware/baseband/proc_capture.cpp @@ -85,7 +85,7 @@ void CaptureProcessor::on_message(const Message* const message) { void CaptureProcessor::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - stream = std::make_unique(*message.config); + stream = std::make_unique(message.config); } else { stream.reset(); } diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 190ed4b08..122115fa2 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -88,7 +88,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { void NarrowbandFMAudio::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - audio_output.set_stream(std::make_unique(*message.config)); + audio_output.set_stream(std::make_unique(message.config)); } else { audio_output.set_stream(nullptr); } diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 1db24b4cd..98de47b88 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -117,7 +117,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { void WidebandFMAudio::capture_config(const CaptureConfigMessage& message) { if( message.config ) { - audio_output.set_stream(std::make_unique(*message.config)); + audio_output.set_stream(std::make_unique(message.config)); } else { audio_output.set_stream(nullptr); } diff --git a/firmware/baseband/stream_input.hpp b/firmware/baseband/stream_input.hpp index db5f353d1..7b93f94fe 100644 --- a/firmware/baseband/stream_input.hpp +++ b/firmware/baseband/stream_input.hpp @@ -34,13 +34,13 @@ using namespace lpc43xx; class StreamInput { public: - StreamInput(CaptureConfig& config) : - K { config.write_size_log2 + config.buffer_count_log2 }, - event_bytes_mask { (1UL << config.write_size_log2) - 1 }, + StreamInput(CaptureConfig* const config) : + K { config->write_size_log2 + config->buffer_count_log2 }, + event_bytes_mask { (1UL << config->write_size_log2) - 1 }, data { std::make_unique(1UL << K) }, fifo { data.get(), K } { - config.fifo = &fifo; + config->fifo = &fifo; } size_t write(const void* const data, const size_t length) { From d2cf129fd58c08e9bfdacacd0d29e0fb18d28e6a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:32:06 -0700 Subject: [PATCH 29/64] Retain CaptureConfig pointer in StreamInput. --- firmware/baseband/stream_input.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/baseband/stream_input.hpp b/firmware/baseband/stream_input.hpp index 7b93f94fe..5752a2f9e 100644 --- a/firmware/baseband/stream_input.hpp +++ b/firmware/baseband/stream_input.hpp @@ -35,6 +35,7 @@ using namespace lpc43xx; class StreamInput { public: StreamInput(CaptureConfig* const config) : + config { config }, K { config->write_size_log2 + config->buffer_count_log2 }, event_bytes_mask { (1UL << config->write_size_log2) - 1 }, data { std::make_unique(1UL << K) }, @@ -60,6 +61,7 @@ public: } private: + CaptureConfig* const config; const size_t K; const uint64_t event_bytes_mask; uint64_t bytes_written = 0; From d63136c52ecc760c18f37ebed68d6d9847201abf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:32:29 -0700 Subject: [PATCH 30/64] Remove unused StreamInput::written(). --- firmware/baseband/stream_input.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/firmware/baseband/stream_input.hpp b/firmware/baseband/stream_input.hpp index 5752a2f9e..8a8107492 100644 --- a/firmware/baseband/stream_input.hpp +++ b/firmware/baseband/stream_input.hpp @@ -56,10 +56,6 @@ public: return written; } - uint64_t written() const { - return bytes_written; - } - private: CaptureConfig* const config; const size_t K; From 1789868b8a6311d6490f02b082cefdc9991c44ea Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:40:50 -0700 Subject: [PATCH 31/64] Track bytes from baseband and dropped when entering capture FIFO. --- firmware/baseband/stream_input.hpp | 2 ++ firmware/common/message.hpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/firmware/baseband/stream_input.hpp b/firmware/baseband/stream_input.hpp index 8a8107492..cb4bbe4e1 100644 --- a/firmware/baseband/stream_input.hpp +++ b/firmware/baseband/stream_input.hpp @@ -52,6 +52,8 @@ public: if( (bytes_written & event_bytes_mask) < (last_bytes_written & event_bytes_mask) ) { creg::m4txevent::assert(); } + config->baseband_bytes_received += length; + config->baseband_bytes_dropped = config->baseband_bytes_received - bytes_written; return written; } diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 1c906c611..bd53d352c 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -413,6 +413,8 @@ public: struct CaptureConfig { const size_t write_size_log2; const size_t buffer_count_log2; + uint64_t baseband_bytes_received; + uint64_t baseband_bytes_dropped; FIFO* fifo; constexpr CaptureConfig( @@ -420,6 +422,8 @@ struct CaptureConfig { const size_t buffer_count_log2 ) : write_size_log2 { write_size_log2 }, buffer_count_log2 { buffer_count_log2 }, + baseband_bytes_received { 0 }, + baseband_bytes_dropped { 0 }, fifo { nullptr } { } From dc1ba7e6f3317826fff555d2293f02cc80597bde Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:44:44 -0700 Subject: [PATCH 32/64] Move CaptureThread::write_size into run(). --- firmware/application/capture_thread.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index b48cb1ece..e77a9b518 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -76,7 +76,6 @@ public: size_t write_size_log2, size_t buffer_count_log2 ) : write_size_log2 { write_size_log2 }, - write_size { 1U << write_size_log2 }, buffer_count_log2 { buffer_count_log2 }, file_path { std::move(file_path) } { @@ -108,7 +107,6 @@ public: private: const size_t write_size_log2; - const size_t write_size; const size_t buffer_count_log2; const std::string file_path; File file; @@ -124,6 +122,7 @@ private: return false; } + const size_t write_size = 1U << write_size_log2; const auto write_buffer = std::make_unique(write_size); if( !write_buffer ) { return false; @@ -133,7 +132,7 @@ private: while( !chThdShouldTerminate() ) { if( stream.available() >= write_size ) { - if( !transfer(stream, write_buffer.get()) ) { + if( !transfer(stream, write_buffer.get(), write_size) ) { return false; } } else { @@ -144,7 +143,7 @@ private: return true; } - bool transfer(StreamOutput& stream, uint8_t* const write_buffer) { + bool transfer(StreamOutput& stream, uint8_t* const write_buffer, const size_t write_size) { bool success = false; led_usb.on(); From 75159fcc0081fc4f83a4d78016700745358d3255 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:52:11 -0700 Subject: [PATCH 33/64] Use static StreamOutput::fifo for accessor methods. --- firmware/application/capture_thread.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index e77a9b518..9f9a0da1a 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -56,11 +56,11 @@ public: } size_t available() { - return config.fifo->len(); + return fifo->len(); } size_t read(void* const data, const size_t length) { - return config.fifo->out(reinterpret_cast(data), length); + return fifo->out(reinterpret_cast(data), length); } static FIFO* fifo; From 7430e315783e8d3f94bff359a4169f8570e0e032 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 10:56:50 -0700 Subject: [PATCH 34/64] Extract CaptureConfig from StreamOutput to CaptureThread. So capture stats can be exposed by CaptureThread. --- firmware/application/capture_thread.hpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 9f9a0da1a..f8fc9ec7f 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -38,14 +38,13 @@ using namespace hackrf::one; class StreamOutput { public: StreamOutput( - const size_t write_size_log2, - const size_t buffer_count_log2 - ) : config { write_size_log2, buffer_count_log2 } + CaptureConfig* const config + ) : config { config } { shared_memory.baseband_queue.push_and_wait( - CaptureConfigMessage { &config } + CaptureConfigMessage { config } ); - fifo = config.fifo; + fifo = config->fifo; } ~StreamOutput() { @@ -66,7 +65,7 @@ public: static FIFO* fifo; private: - CaptureConfig config; + CaptureConfig* const config; }; class CaptureThread { @@ -75,8 +74,7 @@ public: std::string file_path, size_t write_size_log2, size_t buffer_count_log2 - ) : write_size_log2 { write_size_log2 }, - buffer_count_log2 { buffer_count_log2 }, + ) : config { write_size_log2, buffer_count_log2 }, file_path { std::move(file_path) } { // Need significant stack for FATFS @@ -106,8 +104,7 @@ public: } private: - const size_t write_size_log2; - const size_t buffer_count_log2; + CaptureConfig config; const std::string file_path; File file; static Thread* thread; @@ -122,13 +119,13 @@ private: return false; } - const size_t write_size = 1U << write_size_log2; + const size_t write_size = 1U << config.write_size_log2; const auto write_buffer = std::make_unique(write_size); if( !write_buffer ) { return false; } - StreamOutput stream { write_size_log2, buffer_count_log2 }; + StreamOutput stream { &config }; while( !chThdShouldTerminate() ) { if( stream.available() >= write_size ) { From 8188b44439aaf2802966344ba91e9419d2de55e4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 12:02:17 -0700 Subject: [PATCH 35/64] Add Signal for per-second tick callbacks. --- firmware/application/Makefile | 1 + firmware/application/event_m0.cpp | 3 +++ firmware/application/time.cpp | 32 ++++++++++++++++++++++++++++ firmware/application/time.hpp | 35 +++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 firmware/application/time.cpp create mode 100644 firmware/application/time.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 5efd06ceb..cf50b8e1e 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -181,6 +181,7 @@ CPPSRC = main.cpp \ ../common/ert_packet.cpp \ capture_app.cpp \ sd_card.cpp \ + time.cpp \ file.cpp \ log_file.cpp \ png_writer.cpp \ diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index e82faa3b1..388695ef5 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -24,6 +24,7 @@ #include "portapack.hpp" #include "sd_card.hpp" +#include "time.hpp" #include "message.hpp" #include "message_queue.hpp" @@ -145,6 +146,8 @@ void EventDispatcher::handle_rtc_tick() { sd_card::poll_inserted(); portapack::temperature_logger.second_tick(); + + time::on_tick_second(); } ui::Widget* EventDispatcher::touch_widget(ui::Widget* const w, ui::TouchEvent event) { diff --git a/firmware/application/time.cpp b/firmware/application/time.cpp new file mode 100644 index 000000000..10ba7f3b0 --- /dev/null +++ b/firmware/application/time.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 "time.hpp" + +namespace time { + +Signal<> signal_tick_second; + +void on_tick_second() { + signal_tick_second.emit(); +} + +} /* namespace time */ diff --git a/firmware/application/time.hpp b/firmware/application/time.hpp new file mode 100644 index 000000000..470c894d7 --- /dev/null +++ b/firmware/application/time.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __TIME_H__ +#define __TIME_H__ + +#include "signal.hpp" + +namespace time { + +extern Signal<> signal_tick_second; + +void on_tick_second(); + +} /* namespace time */ + +#endif/*__TIME_H__*/ From 11d15ec5b5f314c4941429bbd673a106655c30d5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 12:03:43 -0700 Subject: [PATCH 36/64] Add second tick handler for CaptureThread. --- firmware/application/capture_app.cpp | 11 +++++++++++ firmware/application/capture_app.hpp | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index d5df1ee22..50a1d1f89 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -25,6 +25,7 @@ using namespace portapack; #include "file.hpp" +#include "time.hpp" #include "utility.hpp" @@ -77,9 +78,14 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { }); receiver_model.set_baseband_bandwidth(baseband_bandwidth); receiver_model.enable(); + + signal_token_tick_second = time::signal_tick_second += [this]() { + this->on_tick_second(); + }; } CaptureAppView::~CaptureAppView() { + time::signal_tick_second -= signal_token_tick_second; receiver_model.disable(); } @@ -117,6 +123,11 @@ void CaptureAppView::on_record() { } } +void CaptureAppView::on_tick_second() { + if( capture_thread ) { + } +} + void CaptureAppView::on_tuning_frequency_changed(rf::Frequency f) { receiver_model.set_tuning_frequency(f); } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index cb5ceeb0a..4fb6414a4 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -30,6 +30,7 @@ #include "bitmap.hpp" #include "capture_thread.hpp" +#include "signal.hpp" #include #include @@ -57,7 +58,10 @@ private: std::unique_ptr capture_thread; + SignalToken signal_token_tick_second; + void on_record(); + void on_tick_second(); void on_tuning_frequency_changed(rf::Frequency f); void on_lna_changed(int32_t v_db); From a72a3489cf94afdd8a297583bc50d93f59bd6ff6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 12:04:02 -0700 Subject: [PATCH 37/64] Expose percent of data dropped during capture. --- firmware/common/message.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index bd53d352c..6dc511723 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -427,6 +427,10 @@ struct CaptureConfig { fifo { nullptr } { } + + size_t dropped_percent() const { + return baseband_bytes_dropped * 100U / baseband_bytes_received; + } }; class CaptureConfigMessage : public Message { From 6ee886b90e19a10203b92823a3dea364d6c4c018 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 12:06:47 -0700 Subject: [PATCH 38/64] Expose capture state to the UI. --- firmware/application/capture_thread.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index f8fc9ec7f..b2787f935 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -94,6 +94,10 @@ public: } } + const CaptureConfig& state() const { + return config; + } + static void check_fifo_isr() { // TODO: Prevent over-signalling by transmitting a set of // flags from the baseband core. From be9f3362dad6efdafbd64cc06bf7801aeec5af8e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 12:07:31 -0700 Subject: [PATCH 39/64] Display percent of data dropped during capture to SD card. --- firmware/application/capture_app.cpp | 7 +++++++ firmware/application/capture_app.hpp | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 50a1d1f89..354c61e03 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -29,6 +29,8 @@ using namespace portapack; #include "utility.hpp" +#include "string_format.hpp" + namespace ui { CaptureAppView::CaptureAppView(NavigationView& nav) { @@ -40,6 +42,7 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { &field_lna, &field_vga, &text_record_filename, + &text_record_dropped, &waterfall, } }); @@ -114,6 +117,7 @@ void CaptureAppView::on_record() { } else { const auto filename = next_filename_matching_pattern("BBD_????.C16"); text_record_filename.set(filename); + text_record_dropped.set(""); if( filename.empty() ) { return; } @@ -125,6 +129,9 @@ void CaptureAppView::on_record() { void CaptureAppView::on_tick_second() { if( capture_thread ) { + const auto dropped_percent = std::min(99U, capture_thread->state().dropped_percent()); + const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "\%"; + text_record_dropped.set(s); } } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 4fb6414a4..3c7e25193 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -79,6 +79,11 @@ private: "", }; + Text text_record_dropped { + { 16 * 8, 2 * 16, 3 * 8, 16 }, + "", + }; + RSSI rssi { { 21 * 8, 0, 6 * 8, 4 }, }; From dc8c34487f06884dc4d200a7190464ce68d9f039 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Apr 2016 12:16:37 -0700 Subject: [PATCH 40/64] Speed dropped_percent() common case, ensure dropped>0 returns >0%. --- firmware/common/message.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 6dc511723..f1b20a4e6 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "baseband_packet.hpp" #include "ert_packet.hpp" @@ -429,7 +430,12 @@ struct CaptureConfig { } size_t dropped_percent() const { - return baseband_bytes_dropped * 100U / baseband_bytes_received; + if( baseband_bytes_dropped == 0 ) { + return 0; + } else { + const size_t percent = baseband_bytes_dropped * 100U / baseband_bytes_received; + return std::max(1U, percent); + } } }; From 12b8a1b2a9b1ab299393ae00feb5d6239e4ffe16 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Apr 2016 11:27:12 -0700 Subject: [PATCH 41/64] Change next-file naming functions to work on filename stems. This paves the way for writing metadata files with similar prefixes, and avoids confusing numbering of capture files with different extensions (e.g. BAD_0000.S16 and BBD_0000.S8). --- firmware/application/analog_audio_app.cpp | 8 +++--- firmware/application/analog_audio_app.hpp | 2 +- firmware/application/capture_app.cpp | 8 +++--- firmware/application/capture_app.hpp | 2 +- firmware/application/file.cpp | 35 ++++++++++------------- firmware/application/file.hpp | 2 +- firmware/application/ui_navigation.cpp | 6 ++-- 7 files changed, 29 insertions(+), 34 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index d68556b18..3ba17582b 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -316,13 +316,13 @@ void AnalogAudioView::on_record() { } void AnalogAudioView::record_start() { - const auto filename = next_filename_matching_pattern("AUD_????.S16"); - text_record_filename.set(filename); - if( filename.empty() ) { + const auto filename_stem = next_filename_stem_matching_pattern("AUD_????"); + text_record_filename.set(filename_stem); + if( filename_stem.empty() ) { return; } - capture_thread = std::make_unique(filename, 12, 2); + capture_thread = std::make_unique(filename_stem + ".S16", 12, 2); button_record.set_bitmap(&bitmap_stop); } diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 4f988823c..6e127fe3b 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -150,7 +150,7 @@ private: }; Text text_record_filename { - { 3 * 8, 2 * 16, 12 * 8, 16 }, + { 3 * 8, 2 * 16, 8 * 8, 16 }, "", }; diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 354c61e03..e14e8e508 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -115,14 +115,14 @@ void CaptureAppView::on_record() { capture_thread.reset(); button_record.set_bitmap(&bitmap_record); } else { - const auto filename = next_filename_matching_pattern("BBD_????.C16"); - text_record_filename.set(filename); + const auto filename_stem = next_filename_stem_matching_pattern("BBD_????"); + text_record_filename.set(filename_stem); text_record_dropped.set(""); - if( filename.empty() ) { + if( filename_stem.empty() ) { return; } - capture_thread = std::make_unique(filename, 14, 1); + capture_thread = std::make_unique(filename_stem + ".C16", 14, 1); button_record.set_bitmap(&bitmap_stop); } } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 3c7e25193..31aa33940 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -75,7 +75,7 @@ private: }; Text text_record_filename { - { 3 * 8, 2 * 16, 12 * 8, 16 }, + { 3 * 8, 2 * 16, 8 * 8, 16 }, "", }; diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp index 288f5bde2..871c246ff 100644 --- a/firmware/application/file.cpp +++ b/firmware/application/file.cpp @@ -94,22 +94,16 @@ static std::string find_last_file_matching_pattern(const std::string& pattern) { return last_match; } -static std::string increment_filename_ordinal(const std::string& filename) { - std::string result { filename }; +static std::string remove_filename_extension(const std::string& filename) { + const auto extension_index = filename.find_last_of('.'); + return filename.substr(0, extension_index); +} + +static std::string increment_filename_stem_ordinal(const std::string& filename_stem) { + std::string result { filename_stem }; auto it = result.rbegin(); - // Back up past extension. - for(; it != result.rend(); ++it) { - if( *it == '.' ) { - ++it; - break; - } - } - if( it == result.rend() ) { - return { }; - } - // Increment decimal number before the extension. for(; it != result.rend(); ++it) { const auto c = *it; @@ -128,15 +122,16 @@ static std::string increment_filename_ordinal(const std::string& filename) { return result; } -std::string next_filename_matching_pattern(const std::string& filename_pattern) { - auto filename = find_last_file_matching_pattern(filename_pattern); - if( filename.empty() ) { - filename = filename_pattern; - std::replace(std::begin(filename), std::end(filename), '?', '0'); +std::string next_filename_stem_matching_pattern(const std::string& filename_stem_pattern) { + const auto filename = find_last_file_matching_pattern(filename_stem_pattern + ".*"); + auto filename_stem = remove_filename_extension(filename); + if( filename_stem.empty() ) { + filename_stem = filename_stem_pattern; + std::replace(std::begin(filename_stem), std::end(filename_stem), '?', '0'); } else { - filename = increment_filename_ordinal(filename); + filename_stem = increment_filename_stem_ordinal(filename_stem); } - return filename; + return filename_stem; } namespace std { diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp index 71e454be8..7a45af5dc 100644 --- a/firmware/application/file.hpp +++ b/firmware/application/file.hpp @@ -57,7 +57,7 @@ private: FIL f; }; -std::string next_filename_matching_pattern(const std::string& filename_pattern); +std::string next_filename_stem_matching_pattern(const std::string& filename_stem_pattern); namespace std { namespace filesystem { diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 002a8f471..14f4cc6f8 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -81,12 +81,12 @@ void SystemStatusView::set_title(const std::string new_value) { } void SystemStatusView::on_camera() { - const auto filename = next_filename_matching_pattern("SCR_????.PNG"); - if( filename.empty() ) { + const auto filename_stem = next_filename_stem_matching_pattern("SCR_????"); + if( filename_stem.empty() ) { return; } - PNGWriter png { filename }; + PNGWriter png { filename_stem + ".PNG" }; for(int i=0; i<320; i++) { std::array row; From 18e40562b5b1c4a801e9787e02d3397f44b9540a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Apr 2016 11:27:31 -0700 Subject: [PATCH 42/64] Oops, 128K is not enough. --- .../os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld index 6331b9bd1..249511821 100755 --- a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld +++ b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M0/ld/LPC43xx_M0.ld @@ -23,7 +23,7 @@ __process_stack_size__ = 0x1000; /* main() stack */ MEMORY { - flash : org = 0x00000000, len = 128k /* SPIFI flash @ 0x140????? */ + flash : org = 0x00000000, len = 256k /* SPIFI flash @ 0x140????? */ ram : org = 0x20000000, len = 64k /* AHB SRAM @ 0x20000000 */ } From a6d41547a09c6101a4a9a3bdf39f357c063e31d9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 11:09:39 -0700 Subject: [PATCH 43/64] Make CaptureAppView capture functions same as AnalogAudioView. --- firmware/application/capture_app.cpp | 38 ++++++++++++++++++---------- firmware/application/capture_app.hpp | 4 +++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index e14e8e508..ee9fe331d 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -110,23 +110,35 @@ void CaptureAppView::focus() { button_record.focus(); } -void CaptureAppView::on_record() { - if( capture_thread ) { - capture_thread.reset(); - button_record.set_bitmap(&bitmap_record); - } else { - const auto filename_stem = next_filename_stem_matching_pattern("BBD_????"); - text_record_filename.set(filename_stem); - text_record_dropped.set(""); - if( filename_stem.empty() ) { - return; - } +bool CaptureAppView::is_recording() const { + return (bool)capture_thread; +} - capture_thread = std::make_unique(filename_stem + ".C16", 14, 1); - button_record.set_bitmap(&bitmap_stop); +void CaptureAppView::on_record() { + if( is_recording() ) { + record_stop(); + } else { + record_start(); } } +void CaptureAppView::record_start() { + const auto filename_stem = next_filename_stem_matching_pattern("BBD_????"); + text_record_filename.set(filename_stem); + text_record_dropped.set(""); + if( filename_stem.empty() ) { + return; + } + + capture_thread = std::make_unique(filename_stem + ".C16", 14, 1); + button_record.set_bitmap(&bitmap_stop); +} + +void CaptureAppView::record_stop() { + capture_thread.reset(); + button_record.set_bitmap(&bitmap_record); +} + void CaptureAppView::on_tick_second() { if( capture_thread ) { const auto dropped_percent = std::min(99U, capture_thread->state().dropped_percent()); diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 31aa33940..de92712bb 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -61,6 +61,10 @@ private: SignalToken signal_token_tick_second; void on_record(); + bool is_recording() const; + void record_start(); + void record_stop(); + void on_tick_second(); void on_tuning_frequency_changed(rf::Frequency f); From 24192b4043d64d426611acf19d079f10b976ce22 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 11:25:04 -0700 Subject: [PATCH 44/64] Capture: Write simple metadata for baseband and audio files. Will probably turn the audio metadata file into .wav data, eventually. --- firmware/application/analog_audio_app.cpp | 22 ++++++++++++++++++++++ firmware/application/analog_audio_app.hpp | 1 + firmware/application/capture_app.cpp | 9 +++++++++ firmware/application/capture_app.hpp | 1 + 4 files changed, 33 insertions(+) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 3ba17582b..32d198b02 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -30,6 +30,8 @@ using namespace portapack; #include "utility.hpp" +#include "string_format.hpp" + namespace ui { /* AMOptionsView *********************************************************/ @@ -322,6 +324,8 @@ void AnalogAudioView::record_start() { return; } + write_metadata_file(filename_stem + ".TXT"); + capture_thread = std::make_unique(filename_stem + ".S16", 12, 2); button_record.set_bitmap(&bitmap_stop); } @@ -331,4 +335,22 @@ void AnalogAudioView::record_stop() { button_record.set_bitmap(&bitmap_record); } +void AnalogAudioView::write_metadata_file(const std::string& filename) { + // TODO: This doesn't belong here! There's a better way. + const auto modulation = static_cast(receiver_model.modulation()); + size_t sampling_rate = 0; + switch(modulation) { + case ReceiverModel::Mode::AMAudio: sampling_rate = 12000; break; + case ReceiverModel::Mode::NarrowbandFMAudio: sampling_rate = 24000; break; + case ReceiverModel::Mode::WidebandFMAudio: sampling_rate = 48000; break; + default: + return; + } + + File file; + file.open_for_writing(filename); + file.puts("sample_rate=" + to_string_dec_uint(sampling_rate) + "\n"); + file.puts("center_frequency=" + to_string_dec_uint(receiver_model.tuning_frequency()) + "\n"); +} + } /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 6e127fe3b..9ceecc88b 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -181,6 +181,7 @@ private: bool is_recording() const; void record_start(); void record_stop(); + void write_metadata_file(const std::string& filename); }; } /* namespace ui */ diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index ee9fe331d..8658cd418 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -130,6 +130,8 @@ void CaptureAppView::record_start() { return; } + write_metadata_file(filename_stem + ".TXT"); + capture_thread = std::make_unique(filename_stem + ".C16", 14, 1); button_record.set_bitmap(&bitmap_stop); } @@ -139,6 +141,13 @@ void CaptureAppView::record_stop() { button_record.set_bitmap(&bitmap_record); } +void CaptureAppView::write_metadata_file(const std::string& filename) { + File file; + file.open_for_writing(filename); + file.puts("sample_rate=" + to_string_dec_uint(sampling_rate) + "\n"); + file.puts("center_frequency=" + to_string_dec_uint(receiver_model.tuning_frequency()) + "\n"); +} + void CaptureAppView::on_tick_second() { if( capture_thread ) { const auto dropped_percent = std::min(99U, capture_thread->state().dropped_percent()); diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index de92712bb..030b6e7c7 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -64,6 +64,7 @@ private: bool is_recording() const; void record_start(); void record_stop(); + void write_metadata_file(const std::string& filename); void on_tick_second(); From 4d6fccd8ea901a22cd7b6892fbcd8cb2f91c6bd9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 13:56:54 -0700 Subject: [PATCH 45/64] Extract RecordView from AnalogAudioApp, CaptureApp. --- firmware/application/Makefile | 1 + firmware/application/analog_audio_app.cpp | 56 ++-------- firmware/application/analog_audio_app.hpp | 24 +---- firmware/application/capture_app.cpp | 68 +----------- firmware/application/capture_app.hpp | 40 ++----- firmware/application/ui_record_view.cpp | 124 ++++++++++++++++++++++ firmware/application/ui_record_view.hpp | 96 +++++++++++++++++ 7 files changed, 241 insertions(+), 168 deletions(-) create mode 100644 firmware/application/ui_record_view.cpp create mode 100644 firmware/application/ui_record_view.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index cf50b8e1e..5f0c9e006 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -167,6 +167,7 @@ CPPSRC = main.cpp \ ui_sd_card_debug.cpp \ ui_console.cpp \ ui_receiver.cpp \ + ui_record_view.cpp \ ui_spectrum.cpp \ recent_entries.cpp \ receiver_model.cpp \ diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 32d198b02..948e6d5a5 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -86,8 +86,7 @@ AnalogAudioView::AnalogAudioView( &field_vga, &options_modulation, &field_volume, - &button_record, - &text_record_filename, + &record_view, &waterfall, } }); @@ -140,10 +139,6 @@ AnalogAudioView::AnalogAudioView( this->on_headphone_volume_changed(v); }; - button_record.on_select = [this](ImageButton&) { - this->on_record(); - }; - audio::output::start(); update_modulation(static_cast(modulation)); @@ -289,7 +284,7 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { audio::output::mute(); - record_stop(); + record_view.stop(); const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); receiver_model.set_baseband_configuration({ @@ -300,57 +295,20 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); receiver_model.enable(); - if( !is_wideband_spectrum_mode ) { - audio::output::unmute(); - } -} - -bool AnalogAudioView::is_recording() const { - return (bool)capture_thread; -} - -void AnalogAudioView::on_record() { - if( is_recording() ) { - record_stop(); - } else { - record_start(); - } -} - -void AnalogAudioView::record_start() { - const auto filename_stem = next_filename_stem_matching_pattern("AUD_????"); - text_record_filename.set(filename_stem); - if( filename_stem.empty() ) { - return; - } - - write_metadata_file(filename_stem + ".TXT"); - - capture_thread = std::make_unique(filename_stem + ".S16", 12, 2); - button_record.set_bitmap(&bitmap_stop); -} - -void AnalogAudioView::record_stop() { - capture_thread.reset(); - button_record.set_bitmap(&bitmap_record); -} - -void AnalogAudioView::write_metadata_file(const std::string& filename) { // TODO: This doesn't belong here! There's a better way. - const auto modulation = static_cast(receiver_model.modulation()); size_t sampling_rate = 0; switch(modulation) { case ReceiverModel::Mode::AMAudio: sampling_rate = 12000; break; case ReceiverModel::Mode::NarrowbandFMAudio: sampling_rate = 24000; break; case ReceiverModel::Mode::WidebandFMAudio: sampling_rate = 48000; break; default: - return; + break; } + record_view.set_sampling_rate(sampling_rate); - File file; - file.open_for_writing(filename); - file.puts("sample_rate=" + to_string_dec_uint(sampling_rate) + "\n"); - file.puts("center_frequency=" + to_string_dec_uint(receiver_model.tuning_frequency()) + "\n"); + if( !is_wideband_spectrum_mode ) { + audio::output::unmute(); + } } } /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 9ceecc88b..1498cbc1a 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -26,8 +26,7 @@ #include "ui_receiver.hpp" #include "ui_spectrum.hpp" - -#include "capture_thread.hpp" +#include "ui_record_view.hpp" #include "ui_font_fixed_8x16.hpp" @@ -142,22 +141,13 @@ private: std::unique_ptr options_widget; - ImageButton button_record { - { 0 * 8, 2 * 16, 2 * 8, 1 * 16 }, - &bitmap_record, - Color::red(), - Color::black() - }; - - Text text_record_filename { - { 3 * 8, 2 * 16, 8 * 8, 16 }, - "", + RecordView record_view { + { 0 * 8, 2 * 16, 30 * 8, 1 * 16 }, + "AUD_????", ".S16", 12, 2, }; spectrum::WaterfallWidget waterfall; - std::unique_ptr capture_thread; - void on_tuning_frequency_changed(rf::Frequency f); void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); void on_rf_amp_changed(bool v); @@ -176,12 +166,6 @@ private: void set_options_widget(std::unique_ptr new_widget); void update_modulation(const ReceiverModel::Mode modulation); - - void on_record(); - bool is_recording() const; - void record_start(); - void record_stop(); - void write_metadata_file(const std::string& filename); }; } /* namespace ui */ diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 8658cd418..e03d94763 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -24,25 +24,16 @@ #include "portapack.hpp" using namespace portapack; -#include "file.hpp" -#include "time.hpp" - -#include "utility.hpp" - -#include "string_format.hpp" - namespace ui { CaptureAppView::CaptureAppView(NavigationView& nav) { add_children({ { - &button_record, &rssi, &channel, &field_frequency, &field_lna, &field_vga, - &text_record_filename, - &text_record_dropped, + &record_view, &waterfall, } }); @@ -70,10 +61,6 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { this->on_vga_changed(v_db); }; - button_record.on_select = [this](ImageButton&) { - this->on_record(); - }; - receiver_model.set_baseband_configuration({ .mode = toUType(ReceiverModel::Mode::Capture), .sampling_rate = sampling_rate, @@ -82,13 +69,10 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { receiver_model.set_baseband_bandwidth(baseband_bandwidth); receiver_model.enable(); - signal_token_tick_second = time::signal_tick_second += [this]() { - this->on_tick_second(); - }; + record_view.set_sampling_rate(sampling_rate / 8); } CaptureAppView::~CaptureAppView() { - time::signal_tick_second -= signal_token_tick_second; receiver_model.disable(); } @@ -107,53 +91,7 @@ void CaptureAppView::set_parent_rect(const Rect new_parent_rect) { } void CaptureAppView::focus() { - button_record.focus(); -} - -bool CaptureAppView::is_recording() const { - return (bool)capture_thread; -} - -void CaptureAppView::on_record() { - if( is_recording() ) { - record_stop(); - } else { - record_start(); - } -} - -void CaptureAppView::record_start() { - const auto filename_stem = next_filename_stem_matching_pattern("BBD_????"); - text_record_filename.set(filename_stem); - text_record_dropped.set(""); - if( filename_stem.empty() ) { - return; - } - - write_metadata_file(filename_stem + ".TXT"); - - capture_thread = std::make_unique(filename_stem + ".C16", 14, 1); - button_record.set_bitmap(&bitmap_stop); -} - -void CaptureAppView::record_stop() { - capture_thread.reset(); - button_record.set_bitmap(&bitmap_record); -} - -void CaptureAppView::write_metadata_file(const std::string& filename) { - File file; - file.open_for_writing(filename); - file.puts("sample_rate=" + to_string_dec_uint(sampling_rate) + "\n"); - file.puts("center_frequency=" + to_string_dec_uint(receiver_model.tuning_frequency()) + "\n"); -} - -void CaptureAppView::on_tick_second() { - if( capture_thread ) { - const auto dropped_percent = std::min(99U, capture_thread->state().dropped_percent()); - const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "\%"; - text_record_dropped.set(s); - } + record_view.focus(); } void CaptureAppView::on_tuning_frequency_changed(rf::Frequency f) { diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index 030b6e7c7..e16ad17b9 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -25,13 +25,9 @@ #include "ui_widget.hpp" #include "ui_navigation.hpp" #include "ui_receiver.hpp" +#include "ui_record_view.hpp" #include "ui_spectrum.hpp" -#include "bitmap.hpp" - -#include "capture_thread.hpp" -#include "signal.hpp" - #include #include @@ -56,39 +52,10 @@ private: static constexpr uint32_t sampling_rate = 4000000; static constexpr uint32_t baseband_bandwidth = 2500000; - std::unique_ptr capture_thread; - - SignalToken signal_token_tick_second; - - void on_record(); - bool is_recording() const; - void record_start(); - void record_stop(); - void write_metadata_file(const std::string& filename); - - void on_tick_second(); - void on_tuning_frequency_changed(rf::Frequency f); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - ImageButton button_record { - { 0 * 8, 2 * 16, 2 * 8, 1 * 16 }, - &bitmap_record, - Color::red(), - Color::black() - }; - - Text text_record_filename { - { 3 * 8, 2 * 16, 8 * 8, 16 }, - "", - }; - - Text text_record_dropped { - { 16 * 8, 2 * 16, 3 * 8, 16 }, - "", - }; - RSSI rssi { { 21 * 8, 0, 6 * 8, 4 }, }; @@ -109,6 +76,11 @@ private: { 18 * 8, 0 * 16 } }; + RecordView record_view { + { 0 * 8, 2 * 16, 30 * 8, 1 * 16 }, + "BBD_????", ".C16", 14, 1, + }; + spectrum::WaterfallWidget waterfall; }; diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp new file mode 100644 index 000000000..dc83d42d5 --- /dev/null +++ b/firmware/application/ui_record_view.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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_record_view.hpp" + +#include "portapack.hpp" +using namespace portapack; + +#include "file.hpp" +#include "time.hpp" + +#include "string_format.hpp" +#include "utility.hpp" + +namespace ui { + +RecordView::RecordView( + const Rect parent_rect, + std::string filename_stem_pattern, + std::string filename_extension, + const size_t buffer_size_k, + const size_t buffer_count_k +) : View { parent_rect }, + filename_stem_pattern { filename_stem_pattern }, + filename_extension { filename_extension }, + buffer_size_k { buffer_size_k }, + buffer_count_k { buffer_count_k } +{ + add_children({ { + &button_record, + &text_record_filename, + &text_record_dropped, + } }); + + button_record.on_select = [this](ImageButton&) { + this->toggle(); + }; + + signal_token_tick_second = time::signal_tick_second += [this]() { + this->on_tick_second(); + }; +} + +RecordView::~RecordView() { + time::signal_tick_second -= signal_token_tick_second; +} + +void RecordView::focus() { + button_record.focus(); +} + +bool RecordView::is_active() const { + return (bool)capture_thread; +} + +void RecordView::toggle() { + if( is_active() ) { + stop(); + } else { + start(); + } +} + +void RecordView::start() { + stop(); + + if( sampling_rate == 0 ) { + return; + } + + const auto filename_stem = next_filename_stem_matching_pattern(filename_stem_pattern); + text_record_filename.set(filename_stem); + text_record_dropped.set(""); + if( filename_stem.empty() ) { + return; + } + + write_metadata_file(filename_stem + ".TXT"); + + capture_thread = std::make_unique(filename_stem + filename_extension, buffer_size_k, buffer_count_k); + button_record.set_bitmap(&bitmap_stop); +} + +void RecordView::stop() { + if( is_active() ) { + capture_thread.reset(); + button_record.set_bitmap(&bitmap_record); + } +} + +void RecordView::write_metadata_file(const std::string& filename) { + File file; + file.open_for_writing(filename); + file.puts("sample_rate=" + to_string_dec_uint(sampling_rate) + "\n"); + file.puts("center_frequency=" + to_string_dec_uint(receiver_model.tuning_frequency()) + "\n"); +} + +void RecordView::on_tick_second() { + if( is_active() ) { + const auto dropped_percent = std::min(99U, capture_thread->state().dropped_percent()); + const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "\%"; + text_record_dropped.set(s); + } +} + +} /* namespace ui */ diff --git a/firmware/application/ui_record_view.hpp b/firmware/application/ui_record_view.hpp new file mode 100644 index 000000000..6367c3ac0 --- /dev/null +++ b/firmware/application/ui_record_view.hpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * 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 __UI_RECORD_VIEW_H__ +#define __UI_RECORD_VIEW_H__ + +#include "ui_widget.hpp" + +#include "capture_thread.hpp" +#include "signal.hpp" + +#include "bitmap.hpp" + +#include + +namespace ui { + +class RecordView : public View { +public: + RecordView( + const Rect parent_rect, + std::string filename_stem_pattern, + std::string filename_extension, + const size_t buffer_size_k, + const size_t buffer_count_k + ); + ~RecordView(); + + void focus() override; + + void set_sampling_rate(const size_t new_sampling_rate) { + if( new_sampling_rate != sampling_rate ) { + stop(); + sampling_rate = new_sampling_rate; + } + } + + void start(); + void stop(); + + bool is_active() const; + +private: + void toggle(); + void write_metadata_file(const std::string& filename); + + void on_tick_second(); + + const std::string filename_stem_pattern; + const std::string filename_extension; + const size_t buffer_size_k; + const size_t buffer_count_k; + size_t sampling_rate { 0 }; + SignalToken signal_token_tick_second; + + ImageButton button_record { + { 0 * 8, 0 * 16, 2 * 8, 1 * 16 }, + &bitmap_record, + Color::red(), + Color::black() + }; + + Text text_record_filename { + { 3 * 8, 0 * 16, 8 * 8, 16 }, + "", + }; + + Text text_record_dropped { + { 16 * 8, 0 * 16, 3 * 8, 16 }, + "", + }; + + std::unique_ptr capture_thread; +}; + +} /* namespace ui */ + +#endif/*__UI_RECORD_VIEW_H__*/ From 0d6103916d80ab449b7e19bc216c974a7c8fb12d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 15:09:34 -0700 Subject: [PATCH 46/64] Converge File object with std::fstream. Simplify LogFile. LogFile no longer watches SD card presence and tries to open/close files dynamically. --- firmware/application/ais_app.cpp | 2 +- firmware/application/capture_thread.hpp | 8 ++-- firmware/application/ert_app.cpp | 2 +- firmware/application/file.cpp | 50 ++++++++++------------- firmware/application/file.hpp | 23 ++++++++--- firmware/application/log_file.cpp | 28 ++----------- firmware/application/log_file.hpp | 10 +---- firmware/application/tpms_app.cpp | 2 +- firmware/application/ui_record_view.cpp | 3 +- firmware/application/ui_sd_card_debug.cpp | 16 ++++---- firmware/common/png_writer.cpp | 3 +- 11 files changed, 59 insertions(+), 88 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 7fde92a4b..a6508c917 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -136,7 +136,7 @@ AISLogger::AISLogger( void AISLogger::on_packet(const ais::Packet& packet) { // TODO: Unstuff here, not in baseband! - if( log_file.is_ready() ) { + if( log_file.is_open() ) { std::string entry; entry.reserve((packet.length() + 3) / 4); diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index b2787f935..1568ebc83 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -110,7 +110,6 @@ public: private: CaptureConfig config; const std::string file_path; - File file; static Thread* thread; static msg_t static_fn(void* arg) { @@ -119,7 +118,8 @@ private: } msg_t run() { - if( !file.open_for_writing(file_path) ) { + File file { file_path, File::openmode::out | File::openmode::binary | File::openmode::trunc }; + if( !file.is_open() ) { return false; } @@ -133,7 +133,7 @@ private: while( !chThdShouldTerminate() ) { if( stream.available() >= write_size ) { - if( !transfer(stream, write_buffer.get(), write_size) ) { + if( !transfer(stream, file, write_buffer.get(), write_size) ) { return false; } } else { @@ -144,7 +144,7 @@ private: return true; } - bool transfer(StreamOutput& stream, uint8_t* const write_buffer, const size_t write_size) { + bool transfer(StreamOutput& stream, File& file, uint8_t* const write_buffer, const size_t write_size) { bool success = false; led_usb.on(); diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 938aef9d4..bbdf5848c 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -66,7 +66,7 @@ ERTLogger::ERTLogger( } void ERTLogger::on_packet(const ert::Packet& packet) { - if( log_file.is_ready() ) { + if( log_file.is_open() ) { const auto formatted = packet.symbols_formatted(); log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); } diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp index 871c246ff..ff523de81 100644 --- a/firmware/application/file.cpp +++ b/firmware/application/file.cpp @@ -23,40 +23,32 @@ #include -File::~File() { - close(); -} - -bool File::open_for_writing(const std::string& file_path) { - const auto open_result = f_open(&f, file_path.c_str(), FA_WRITE | FA_OPEN_ALWAYS); - return (open_result == FR_OK); -} - -bool File::open_for_reading(const std::string& file_path) { - const auto open_result = f_open(&f, file_path.c_str(), FA_READ | FA_OPEN_EXISTING); - return (open_result == FR_OK); -} - -bool File::open_for_append(const std::string& file_path) { - if( open_for_writing(file_path) ) { - const auto seek_result = f_lseek(&f, f_size(&f)); - if( seek_result == FR_OK ) { - return true; - } else { - close(); - } +File::File(const std::string& filename, openmode mode) { + BYTE fatfs_mode = 0; + if( mode & openmode::in ) { + fatfs_mode |= FA_READ; + } + if( mode & openmode::out ) { + fatfs_mode |= FA_WRITE; + } + if( mode & openmode::trunc ) { + fatfs_mode |= FA_CREATE_ALWAYS; + } + if( mode & openmode::ate ) { + fatfs_mode |= FA_OPEN_ALWAYS; } - return false; + if( f_open(&f, filename.c_str(), fatfs_mode) == FR_OK ) { + if( mode & openmode::ate ) { + if( f_lseek(&f, f_size(&f)) != FR_OK ) { + f_close(&f); + } + } + } } -bool File::close() { +File::~File() { f_close(&f); - return true; -} - -bool File::is_ready() { - return f_error(&f) == 0; } bool File::read(void* const data, const size_t bytes_to_read) { diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp index 7a45af5dc..b4b0c74f8 100644 --- a/firmware/application/file.hpp +++ b/firmware/application/file.hpp @@ -32,14 +32,21 @@ class File { public: + enum openmode { + app = 0x100, + binary = 0x200, + in = FA_READ, + out = FA_WRITE, + trunc = FA_CREATE_ALWAYS, + ate = FA_OPEN_ALWAYS, + }; + + File(const std::string& filename, openmode mode); ~File(); - bool open_for_writing(const std::string& file_path); - bool open_for_reading(const std::string& file_path); - bool open_for_append(const std::string& file_path); - bool close(); - - bool is_ready(); + bool is_open() const { + return f_error(&f) == 0; + } bool read(void* const data, const size_t bytes_to_read); bool write(const void* const data, const size_t bytes_to_write); @@ -57,6 +64,10 @@ private: FIL f; }; +inline constexpr File::openmode operator|(File::openmode a, File::openmode b) { + return File::openmode(static_cast(a) | static_cast(b)); +} + std::string next_filename_stem_matching_pattern(const std::string& filename_stem_pattern); namespace std { diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index e87cce36b..06e56246c 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -23,28 +23,14 @@ #include "string_format.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - LogFile::LogFile( const std::string& file_path -) : file_path { file_path } +) : file { file_path, File::openmode::out | File::openmode::ate } { - file.open_for_append(file_path); - - sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { - this->on_sd_card_status(status); - }; } -LogFile::~LogFile() { - sd_card::status_signal -= sd_card_status_signal_token; - - file.close(); -} - -bool LogFile::is_ready() { - return file.is_ready(); +bool LogFile::is_open() const { + return file.is_open(); } bool LogFile::write_entry(const rtc::RTC& datetime, const std::string& entry) { @@ -55,11 +41,3 @@ bool LogFile::write_entry(const rtc::RTC& datetime, const std::string& entry) { bool LogFile::write(const std::string& message) { return file.puts(message) && file.sync(); } - -void LogFile::on_sd_card_status(const sd_card::Status status) { - if( status == sd_card::Status::Mounted ) { - file.open_for_append(file_path); - } else { - file.close(); - } -} diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp index 30883b0f8..70a1651cd 100644 --- a/firmware/application/log_file.hpp +++ b/firmware/application/log_file.hpp @@ -25,7 +25,6 @@ #include #include "file.hpp" -#include "sd_card.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -33,22 +32,15 @@ using namespace lpc43xx; class LogFile { public: LogFile(const std::string& file_path); - ~LogFile(); - bool is_ready(); + bool is_open() const; bool write_entry(const rtc::RTC& datetime, const std::string& entry); private: - const std::string file_path; - File file; - SignalToken sd_card_status_signal_token; - bool write(const std::string& message); - - void on_sd_card_status(const sd_card::Status status); }; #endif/*__LOG_FILE_H__*/ diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index c80bfb9d7..abe274503 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -62,7 +62,7 @@ TPMSLogger::TPMSLogger( void TPMSLogger::on_packet(const tpms::Packet& packet, const uint32_t target_frequency) { const auto hex_formatted = packet.symbols_formatted(); - if( log_file.is_ready() ) { + if( log_file.is_open() ) { // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! const auto tuning_frequency_str = to_string_dec_uint(target_frequency, 10); diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index dc83d42d5..07f40f172 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -107,8 +107,7 @@ void RecordView::stop() { } void RecordView::write_metadata_file(const std::string& filename) { - File file; - file.open_for_writing(filename); + File file { filename, File::openmode::out | File::openmode::trunc }; file.puts("sample_rate=" + to_string_dec_uint(sampling_rate) + "\n"); file.puts("center_frequency=" + to_string_dec_uint(receiver_model.tuning_frequency()) + "\n"); } diff --git a/firmware/application/ui_sd_card_debug.cpp b/firmware/application/ui_sd_card_debug.cpp index 25d9ba5de..28d164e21 100644 --- a/firmware/application/ui_sd_card_debug.cpp +++ b/firmware/application/ui_sd_card_debug.cpp @@ -133,15 +133,15 @@ private: return Result::FailHeap; } - File file; - if( !file.open_for_writing(filename) ) { + File file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc }; + if( !file.is_open() ) { return Result::FailFileOpenWrite; } lfsr_word_t v = 1; const halrtcnt_t test_start = halGetCounterValue(); - while( !chThdShouldTerminate() && file.is_ready() && (_stats.write_bytes < bytes_to_write) ) { + while( !chThdShouldTerminate() && file.is_open() && (_stats.write_bytes < bytes_to_write) ) { lfsr_fill(v, reinterpret_cast(buffer->data()), sizeof(*buffer.get()) / sizeof(lfsr_word_t) @@ -164,7 +164,7 @@ private: } } - file.close(); + file.sync(); const halrtcnt_t test_end = halGetCounterValue(); _stats.write_test_duration = test_end - test_start; @@ -178,15 +178,15 @@ private: return Result::FailHeap; } - File file; - if( !file.open_for_reading(filename) ) { + File file { filename, File::openmode::in | File::openmode::binary }; + if( !file.is_open() ) { return Result::FailFileOpenRead; } lfsr_word_t v = 1; const halrtcnt_t test_start = halGetCounterValue(); - while( !chThdShouldTerminate() && file.is_ready() && (_stats.read_bytes < bytes_to_read) ) { + while( !chThdShouldTerminate() && file.is_open() && (_stats.read_bytes < bytes_to_read) ) { const halrtcnt_t read_start = halGetCounterValue(); if( !file.read(buffer->data(), buffer->size()) ) { break; @@ -211,7 +211,7 @@ private: } } - file.close(); + file.sync(); const halrtcnt_t test_end = halGetCounterValue(); _stats.read_test_duration = test_end - test_start; diff --git a/firmware/common/png_writer.cpp b/firmware/common/png_writer.cpp index 15e1b8aac..c1d592440 100644 --- a/firmware/common/png_writer.cpp +++ b/firmware/common/png_writer.cpp @@ -51,9 +51,8 @@ static constexpr std::array png_iend { { PNGWriter::PNGWriter( const std::string& filename -) +) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc } { - file.open_for_writing(filename); file.write(png_file_header); file.write(png_ihdr_screen_capture); From a2a2de9a236a07ba99b7e0cd6292bdf70e2dabe8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 15:13:54 -0700 Subject: [PATCH 47/64] Increase CaptureThread stack, now that File is created in new thread. --- firmware/application/capture_thread.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 1568ebc83..0d09f2e52 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -78,7 +78,7 @@ public: file_path { std::move(file_path) } { // Need significant stack for FATFS - thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, CaptureThread::static_fn, this); + thread = chThdCreateFromHeap(NULL, 2048, NORMALPRIO + 10, CaptureThread::static_fn, this); } ~CaptureThread() { From b5fbab8e29990aaab06a9f111054c1b4287af747 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 16:26:49 -0700 Subject: [PATCH 48/64] Pass a File into CaptureThread. Groundwork for having a general output-stream interface. --- firmware/application/capture_thread.hpp | 17 ++++++----------- firmware/application/ui_record_view.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 0d09f2e52..5dc29b008 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -71,11 +71,11 @@ private: class CaptureThread { public: CaptureThread( - std::string file_path, + std::unique_ptr file, size_t write_size_log2, size_t buffer_count_log2 ) : config { write_size_log2, buffer_count_log2 }, - file_path { std::move(file_path) } + file { std::move(file) } { // Need significant stack for FATFS thread = chThdCreateFromHeap(NULL, 2048, NORMALPRIO + 10, CaptureThread::static_fn, this); @@ -109,7 +109,7 @@ public: private: CaptureConfig config; - const std::string file_path; + std::unique_ptr file; static Thread* thread; static msg_t static_fn(void* arg) { @@ -118,11 +118,6 @@ private: } msg_t run() { - File file { file_path, File::openmode::out | File::openmode::binary | File::openmode::trunc }; - if( !file.is_open() ) { - return false; - } - const size_t write_size = 1U << config.write_size_log2; const auto write_buffer = std::make_unique(write_size); if( !write_buffer ) { @@ -133,7 +128,7 @@ private: while( !chThdShouldTerminate() ) { if( stream.available() >= write_size ) { - if( !transfer(stream, file, write_buffer.get(), write_size) ) { + if( !transfer(stream, write_buffer.get(), write_size) ) { return false; } } else { @@ -144,14 +139,14 @@ private: return true; } - bool transfer(StreamOutput& stream, File& file, uint8_t* const write_buffer, const size_t write_size) { + bool transfer(StreamOutput& stream, uint8_t* const write_buffer, const size_t write_size) { bool success = false; led_usb.on(); const auto bytes_to_write = stream.read(write_buffer, write_size); if( bytes_to_write == write_size ) { - if( file.write(write_buffer, write_size) ) { + if( file->write(write_buffer, write_size) ) { success = true; } } diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index 07f40f172..04c71ef86 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -95,7 +95,13 @@ void RecordView::start() { write_metadata_file(filename_stem + ".TXT"); - capture_thread = std::make_unique(filename_stem + filename_extension, buffer_size_k, buffer_count_k); + capture_thread = std::make_unique( + std::make_unique( + filename_stem + filename_extension, + File::openmode::out | File::openmode::binary | File::openmode::trunc + ), + buffer_size_k, buffer_count_k + ); button_record.set_bitmap(&bitmap_stop); } From 6a17be1f2c187d765a379d8134ee6c76b28f3d10 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 16:34:50 -0700 Subject: [PATCH 49/64] Abstract CaptureThread target class into Writer, implement RawFileWriter. --- firmware/application/capture_thread.hpp | 29 +++++++++++++++++++++---- firmware/application/ui_record_view.cpp | 5 ++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 5dc29b008..c68fc8e18 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -35,6 +35,27 @@ using namespace hackrf::one; #include +class Writer { +public: + virtual bool write(const void* const write_buffer, const size_t write_size) = 0; +}; + +class RawFileWriter : public Writer { +public: + RawFileWriter( + const std::string& filename + ) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc } + { + } + + bool write(const void* const write_buffer, const size_t write_size) override { + return file.write(write_buffer, write_size); + } + +private: + File file; +}; + class StreamOutput { public: StreamOutput( @@ -71,11 +92,11 @@ private: class CaptureThread { public: CaptureThread( - std::unique_ptr file, + std::unique_ptr writer, size_t write_size_log2, size_t buffer_count_log2 ) : config { write_size_log2, buffer_count_log2 }, - file { std::move(file) } + writer { std::move(writer) } { // Need significant stack for FATFS thread = chThdCreateFromHeap(NULL, 2048, NORMALPRIO + 10, CaptureThread::static_fn, this); @@ -109,7 +130,7 @@ public: private: CaptureConfig config; - std::unique_ptr file; + std::unique_ptr writer; static Thread* thread; static msg_t static_fn(void* arg) { @@ -146,7 +167,7 @@ private: const auto bytes_to_write = stream.read(write_buffer, write_size); if( bytes_to_write == write_size ) { - if( file->write(write_buffer, write_size) ) { + if( writer->write(write_buffer, write_size) ) { success = true; } } diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index 04c71ef86..b37678ff0 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -96,9 +96,8 @@ void RecordView::start() { write_metadata_file(filename_stem + ".TXT"); capture_thread = std::make_unique( - std::make_unique( - filename_stem + filename_extension, - File::openmode::out | File::openmode::binary | File::openmode::trunc + std::make_unique( + filename_stem + filename_extension ), buffer_size_k, buffer_count_k ); From 2be105853eb2ac2d7e2bbfb077fa6e7ea60d753f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Apr 2016 16:55:52 -0700 Subject: [PATCH 50/64] Shrink CaptureThread stack, undid earlier increase. Moved File into Writer abstraction, passed in now, not created on stack. --- firmware/application/capture_thread.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index c68fc8e18..d0116490f 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -99,7 +99,7 @@ public: writer { std::move(writer) } { // Need significant stack for FATFS - thread = chThdCreateFromHeap(NULL, 2048, NORMALPRIO + 10, CaptureThread::static_fn, this); + thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, CaptureThread::static_fn, this); } ~CaptureThread() { From 0445a842db1b1c727d547fc03f888638c8a64c5e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 1 May 2016 11:07:50 -0700 Subject: [PATCH 51/64] Rename args on Writer interface. --- firmware/application/capture_thread.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index d0116490f..16c4b99e4 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -37,7 +37,7 @@ using namespace hackrf::one; class Writer { public: - virtual bool write(const void* const write_buffer, const size_t write_size) = 0; + virtual bool write(const void* const buffer, const size_t bytes) = 0; }; class RawFileWriter : public Writer { @@ -48,8 +48,8 @@ public: { } - bool write(const void* const write_buffer, const size_t write_size) override { - return file.write(write_buffer, write_size); + bool write(const void* const buffer, const size_t bytes) override { + return file.write(buffer, bytes); } private: From c5cae1034e1b617606f76158383eef30a74094aa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 1 May 2016 11:29:19 -0700 Subject: [PATCH 52/64] Forgot virtual destructor on interface class. So my Files weren't getting closed properly! --- firmware/application/capture_thread.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 16c4b99e4..8dddc5301 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -38,6 +38,7 @@ using namespace hackrf::one; class Writer { public: virtual bool write(const void* const buffer, const size_t bytes) = 0; + virtual ~Writer() { }; }; class RawFileWriter : public Writer { From 80f94cbc2955ef76638990f492803c89c36417f7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 1 May 2016 11:29:44 -0700 Subject: [PATCH 53/64] Add File seek support. --- firmware/application/file.cpp | 11 +++++++++++ firmware/application/file.hpp | 2 ++ 2 files changed, 13 insertions(+) diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp index ff523de81..18e75005e 100644 --- a/firmware/application/file.cpp +++ b/firmware/application/file.cpp @@ -63,6 +63,17 @@ bool File::write(const void* const data, const size_t bytes_to_write) { return (result == FR_OK) && (bytes_written == bytes_to_write); } +uint64_t File::seek(const uint64_t new_position) { + const auto old_position = f_tell(&f); + if( f_lseek(&f, new_position) != FR_OK ) { + f_close(&f); + } + if( f_tell(&f) != new_position ) { + f_close(&f); + } + return old_position; +} + bool File::puts(const std::string& string) { const auto result = f_puts(string.c_str(), &f); return (result >= 0); diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp index b4b0c74f8..6be0f9ddb 100644 --- a/firmware/application/file.hpp +++ b/firmware/application/file.hpp @@ -51,6 +51,8 @@ public: bool read(void* const data, const size_t bytes_to_read); bool write(const void* const data, const size_t bytes_to_write); + uint64_t seek(const uint64_t new_position); + template bool write(const std::array& data) { return write(data.data(), N); From fa8105266cc3c0f17431221841e8905586102be7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 1 May 2016 11:31:20 -0700 Subject: [PATCH 54/64] WAVFileWriter saves WAV files! --- firmware/application/capture_thread.hpp | 85 +++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 8dddc5301..151bb21f2 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -57,6 +57,91 @@ private: File file; }; +class WAVFileWriter : public Writer { +public: + WAVFileWriter( + const std::string& filename, + size_t sampling_rate + ) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc }, + header { sampling_rate } + { + update_header(); + } + + ~WAVFileWriter() { + update_header(); + } + + bool write(const void* const buffer, const size_t bytes) override { + const auto success = file.write(buffer, bytes) ; + if( success ) { + bytes_written += bytes; + } + return success; + } + +private: + struct fmt_pcm_t { + constexpr fmt_pcm_t( + const uint32_t sampling_rate + ) : nSamplesPerSec { sampling_rate }, + nAvgBytesPerSec { nSamplesPerSec * nBlockAlign } + { + } + + private: + const uint8_t ckID[4] { 'f', 'm', 't', ' ' }; + const uint32_t cksize { 16 }; + const uint16_t wFormatTag { 0x0001 }; + const uint16_t nChannels { 1 }; + const uint32_t nSamplesPerSec; + const uint32_t nAvgBytesPerSec; + const uint16_t nBlockAlign { 2 }; + const uint16_t wBitsPerSample { 16 }; + }; + + struct data_t { + void set_size(const uint32_t value) { + cksize = value; + } + + private: + const uint8_t ckID[4] { 'd', 'a', 't', 'a' }; + uint32_t cksize { 0 }; + }; + + struct header_t { + constexpr header_t( + const uint32_t sampling_rate + ) : fmt { sampling_rate } + { + } + + void set_data_size(const uint32_t value) { + data.set_size(value); + cksize = sizeof(header_t) + value - 8; + } + + private: + const uint8_t riff_id[4] { 'R', 'I', 'F', 'F' }; + uint32_t cksize { 0 }; + const uint8_t wave_id[4] { 'W', 'A', 'V', 'E' }; + fmt_pcm_t fmt; + data_t data; + }; + + File file; + header_t header; + uint64_t bytes_written { 0 }; + + void update_header() { + header.set_data_size(bytes_written); + const auto old_position = file.seek(0); + file.write(&header, sizeof(header)); + file.seek(old_position); + } +}; + class StreamOutput { public: StreamOutput( From 68faccfd10db398263c251daef43db37959c38e4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 11:22:14 -0700 Subject: [PATCH 55/64] Update Writer default destructor syntax. --- firmware/application/capture_thread.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 151bb21f2..e6e489322 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -38,7 +38,7 @@ using namespace hackrf::one; class Writer { public: virtual bool write(const void* const buffer, const size_t bytes) = 0; - virtual ~Writer() { }; + virtual ~Writer() = default; }; class RawFileWriter : public Writer { From 3f36d8b7bf6773982c38e175e597ecf415b9a2df Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 11:44:37 -0700 Subject: [PATCH 56/64] Push record file type support into RecordView. --- firmware/application/analog_audio_app.hpp | 2 +- firmware/application/capture_app.hpp | 2 +- firmware/application/ui_record_view.cpp | 38 +++++++++++++++++------ firmware/application/ui_record_view.hpp | 9 ++++-- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 1498cbc1a..ebef06e3e 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -143,7 +143,7 @@ private: RecordView record_view { { 0 * 8, 2 * 16, 30 * 8, 1 * 16 }, - "AUD_????", ".S16", 12, 2, + "AUD_????", RecordView::FileType::WAV, 12, 2, }; spectrum::WaterfallWidget waterfall; diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index e16ad17b9..bc896f9e5 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -78,7 +78,7 @@ private: RecordView record_view { { 0 * 8, 2 * 16, 30 * 8, 1 * 16 }, - "BBD_????", ".C16", 14, 1, + "BBD_????", RecordView::FileType::RawS16, 14, 1, }; spectrum::WaterfallWidget waterfall; diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index b37678ff0..52e3e5486 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -35,12 +35,12 @@ namespace ui { RecordView::RecordView( const Rect parent_rect, std::string filename_stem_pattern, - std::string filename_extension, + const FileType file_type, const size_t buffer_size_k, const size_t buffer_count_k ) : View { parent_rect }, filename_stem_pattern { filename_stem_pattern }, - filename_extension { filename_extension }, + file_type { file_type }, buffer_size_k { buffer_size_k }, buffer_count_k { buffer_count_k } { @@ -93,15 +93,33 @@ void RecordView::start() { return; } - write_metadata_file(filename_stem + ".TXT"); + std::unique_ptr writer; + switch(file_type) { + case FileType::WAV: + writer = std::make_unique( + filename_stem + ".WAV", + sampling_rate + ); + break; - capture_thread = std::make_unique( - std::make_unique( - filename_stem + filename_extension - ), - buffer_size_k, buffer_count_k - ); - button_record.set_bitmap(&bitmap_stop); + case FileType::RawS16: + write_metadata_file(filename_stem + ".TXT"); + writer = std::make_unique( + filename_stem + ".C16" + ); + break; + + default: + break; + }; + + if( writer ) { + capture_thread = std::make_unique( + std::move(writer), + buffer_size_k, buffer_count_k + ); + button_record.set_bitmap(&bitmap_stop); + } } void RecordView::stop() { diff --git a/firmware/application/ui_record_view.hpp b/firmware/application/ui_record_view.hpp index 6367c3ac0..c133f19e1 100644 --- a/firmware/application/ui_record_view.hpp +++ b/firmware/application/ui_record_view.hpp @@ -35,10 +35,15 @@ namespace ui { class RecordView : public View { public: + enum FileType { + RawS16 = 2, + WAV = 3, + }; + RecordView( const Rect parent_rect, std::string filename_stem_pattern, - std::string filename_extension, + FileType file_type, const size_t buffer_size_k, const size_t buffer_count_k ); @@ -65,7 +70,7 @@ private: void on_tick_second(); const std::string filename_stem_pattern; - const std::string filename_extension; + const FileType file_type; const size_t buffer_size_k; const size_t buffer_count_k; size_t sampling_rate { 0 }; From 2e6230e29cb6983265b526850761818166dc83af Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 11:47:44 -0700 Subject: [PATCH 57/64] Rearrange UI code RecordView::start() to keep consistent in failure. --- firmware/application/ui_record_view.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index 52e3e5486..d92a0fa66 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -82,13 +82,14 @@ void RecordView::toggle() { void RecordView::start() { stop(); + text_record_filename.set(""); + text_record_dropped.set(""); + if( sampling_rate == 0 ) { return; } const auto filename_stem = next_filename_stem_matching_pattern(filename_stem_pattern); - text_record_filename.set(filename_stem); - text_record_dropped.set(""); if( filename_stem.empty() ) { return; } @@ -114,11 +115,12 @@ void RecordView::start() { }; if( writer ) { + text_record_filename.set(filename_stem); + button_record.set_bitmap(&bitmap_stop); capture_thread = std::make_unique( std::move(writer), buffer_size_k, buffer_count_k ); - button_record.set_bitmap(&bitmap_stop); } } From 97af4585b005514abeb2149b3f573fff6b4541aa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 12:26:53 -0700 Subject: [PATCH 58/64] Missing #includes. --- firmware/application/ui_record_view.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/application/ui_record_view.hpp b/firmware/application/ui_record_view.hpp index c133f19e1..0c8c24bb6 100644 --- a/firmware/application/ui_record_view.hpp +++ b/firmware/application/ui_record_view.hpp @@ -29,6 +29,8 @@ #include "bitmap.hpp" +#include +#include #include namespace ui { From 697df07501577b15d5a4e23c969f50260591ed81 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 12:34:42 -0700 Subject: [PATCH 59/64] Move Writer implementations to ui_record_view.cpp. --- firmware/application/capture_thread.hpp | 107 +----------------------- firmware/application/ui_record_view.cpp | 103 +++++++++++++++++++++++ 2 files changed, 106 insertions(+), 104 deletions(-) diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index e6e489322..792af1957 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -24,8 +24,6 @@ #include "ch.h" -#include "file.hpp" - #include "event_m0.hpp" #include "portapack_shared_memory.hpp" @@ -33,7 +31,9 @@ #include "hackrf_gpio.hpp" using namespace hackrf::one; -#include +#include +#include +#include class Writer { public: @@ -41,107 +41,6 @@ public: virtual ~Writer() = default; }; -class RawFileWriter : public Writer { -public: - RawFileWriter( - const std::string& filename - ) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc } - { - } - - bool write(const void* const buffer, const size_t bytes) override { - return file.write(buffer, bytes); - } - -private: - File file; -}; - -class WAVFileWriter : public Writer { -public: - WAVFileWriter( - const std::string& filename, - size_t sampling_rate - ) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc }, - header { sampling_rate } - { - update_header(); - } - - ~WAVFileWriter() { - update_header(); - } - - bool write(const void* const buffer, const size_t bytes) override { - const auto success = file.write(buffer, bytes) ; - if( success ) { - bytes_written += bytes; - } - return success; - } - -private: - struct fmt_pcm_t { - constexpr fmt_pcm_t( - const uint32_t sampling_rate - ) : nSamplesPerSec { sampling_rate }, - nAvgBytesPerSec { nSamplesPerSec * nBlockAlign } - { - } - - private: - const uint8_t ckID[4] { 'f', 'm', 't', ' ' }; - const uint32_t cksize { 16 }; - const uint16_t wFormatTag { 0x0001 }; - const uint16_t nChannels { 1 }; - const uint32_t nSamplesPerSec; - const uint32_t nAvgBytesPerSec; - const uint16_t nBlockAlign { 2 }; - const uint16_t wBitsPerSample { 16 }; - }; - - struct data_t { - void set_size(const uint32_t value) { - cksize = value; - } - - private: - const uint8_t ckID[4] { 'd', 'a', 't', 'a' }; - uint32_t cksize { 0 }; - }; - - struct header_t { - constexpr header_t( - const uint32_t sampling_rate - ) : fmt { sampling_rate } - { - } - - void set_data_size(const uint32_t value) { - data.set_size(value); - cksize = sizeof(header_t) + value - 8; - } - - private: - const uint8_t riff_id[4] { 'R', 'I', 'F', 'F' }; - uint32_t cksize { 0 }; - const uint8_t wave_id[4] { 'W', 'A', 'V', 'E' }; - fmt_pcm_t fmt; - data_t data; - }; - - File file; - header_t header; - uint64_t bytes_written { 0 }; - - void update_header() { - header.set_data_size(bytes_written); - const auto old_position = file.seek(0); - file.write(&header, sizeof(header)); - file.seek(old_position); - } -}; - class StreamOutput { public: StreamOutput( diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index d92a0fa66..3f905f063 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -30,6 +30,109 @@ using namespace portapack; #include "string_format.hpp" #include "utility.hpp" +#include + +class RawFileWriter : public Writer { +public: + RawFileWriter( + const std::string& filename + ) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc } + { + } + + bool write(const void* const buffer, const size_t bytes) override { + return file.write(buffer, bytes); + } + +private: + File file; +}; + +class WAVFileWriter : public Writer { +public: + WAVFileWriter( + const std::string& filename, + size_t sampling_rate + ) : file { filename, File::openmode::out | File::openmode::binary | File::openmode::trunc }, + header { sampling_rate } + { + update_header(); + } + + ~WAVFileWriter() { + update_header(); + } + + bool write(const void* const buffer, const size_t bytes) override { + const auto success = file.write(buffer, bytes) ; + if( success ) { + bytes_written += bytes; + } + return success; + } + +private: + struct fmt_pcm_t { + constexpr fmt_pcm_t( + const uint32_t sampling_rate + ) : nSamplesPerSec { sampling_rate }, + nAvgBytesPerSec { nSamplesPerSec * nBlockAlign } + { + } + + private: + const uint8_t ckID[4] { 'f', 'm', 't', ' ' }; + const uint32_t cksize { 16 }; + const uint16_t wFormatTag { 0x0001 }; + const uint16_t nChannels { 1 }; + const uint32_t nSamplesPerSec; + const uint32_t nAvgBytesPerSec; + const uint16_t nBlockAlign { 2 }; + const uint16_t wBitsPerSample { 16 }; + }; + + struct data_t { + void set_size(const uint32_t value) { + cksize = value; + } + + private: + const uint8_t ckID[4] { 'd', 'a', 't', 'a' }; + uint32_t cksize { 0 }; + }; + + struct header_t { + constexpr header_t( + const uint32_t sampling_rate + ) : fmt { sampling_rate } + { + } + + void set_data_size(const uint32_t value) { + data.set_size(value); + cksize = sizeof(header_t) + value - 8; + } + + private: + const uint8_t riff_id[4] { 'R', 'I', 'F', 'F' }; + uint32_t cksize { 0 }; + const uint8_t wave_id[4] { 'W', 'A', 'V', 'E' }; + fmt_pcm_t fmt; + data_t data; + }; + + File file; + header_t header; + uint64_t bytes_written { 0 }; + + void update_header() { + header.set_data_size(bytes_written); + const auto old_position = file.seek(0); + file.write(&header, sizeof(header)); + file.seek(old_position); + } +}; + namespace ui { RecordView::RecordView( From eeb464524295ffb384df1db5e9e775eb4132f141 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 12:50:49 -0700 Subject: [PATCH 60/64] Move lots of capture_thread code to .cpp. --- firmware/application/capture_thread.cpp | 104 +++++++++++++++++++++++ firmware/application/capture_thread.hpp | 107 +----------------------- 2 files changed, 108 insertions(+), 103 deletions(-) diff --git a/firmware/application/capture_thread.cpp b/firmware/application/capture_thread.cpp index e39d63121..867faeea1 100644 --- a/firmware/application/capture_thread.cpp +++ b/firmware/application/capture_thread.cpp @@ -21,5 +21,109 @@ #include "capture_thread.hpp" +#include "portapack_shared_memory.hpp" + +#include "hackrf_gpio.hpp" +using namespace hackrf::one; + +// StreamOutput /////////////////////////////////////////////////////////// + +class StreamOutput { +public: + StreamOutput(CaptureConfig* const config); + ~StreamOutput(); + + size_t available() { + return fifo->len(); + } + + size_t read(void* const data, const size_t length) { + return fifo->out(reinterpret_cast(data), length); + } + + static FIFO* fifo; + +private: + CaptureConfig* const config; +}; + FIFO* StreamOutput::fifo = nullptr; + +StreamOutput::StreamOutput( + CaptureConfig* const config +) : config { config } +{ + shared_memory.baseband_queue.push_and_wait( + CaptureConfigMessage { config } + ); + fifo = config->fifo; +} + +StreamOutput::~StreamOutput() { + fifo = nullptr; + shared_memory.baseband_queue.push_and_wait( + CaptureConfigMessage { nullptr } + ); +} + +// CaptureThread ////////////////////////////////////////////////////////// + Thread* CaptureThread::thread = nullptr; + +CaptureThread::CaptureThread( + std::unique_ptr writer, + size_t write_size_log2, + size_t buffer_count_log2 +) : config { write_size_log2, buffer_count_log2 }, + writer { std::move(writer) } +{ + // Need significant stack for FATFS + thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, CaptureThread::static_fn, this); +} + +CaptureThread::~CaptureThread() { + if( thread ) { + chThdTerminate(thread); + chEvtSignal(thread, EVT_MASK_CAPTURE_THREAD); + const auto success = chThdWait(thread); + thread = nullptr; + + if( !success ) { + led_tx.on(); + } + } +} + +void CaptureThread::check_fifo_isr() { + // TODO: Prevent over-signalling by transmitting a set of + // flags from the baseband core. + const auto fifo = StreamOutput::fifo; + if( fifo ) { + chEvtSignalI(thread, EVT_MASK_CAPTURE_THREAD); + } +} + +msg_t CaptureThread::run() { + const size_t write_size = 1U << config.write_size_log2; + const auto write_buffer = std::make_unique(write_size); + if( !write_buffer ) { + return false; + } + + StreamOutput stream { &config }; + + while( !chThdShouldTerminate() ) { + if( stream.available() >= write_size ) { + if( stream.read(write_buffer.get(), write_size) != write_size ) { + return false; + } + if( !writer->write(write_buffer.get(), write_size) ) { + return false; + } + } else { + chEvtWaitAny(EVT_MASK_CAPTURE_THREAD); + } + } + + return true; +} diff --git a/firmware/application/capture_thread.hpp b/firmware/application/capture_thread.hpp index 792af1957..c4bdbb1c5 100644 --- a/firmware/application/capture_thread.hpp +++ b/firmware/application/capture_thread.hpp @@ -26,11 +26,6 @@ #include "event_m0.hpp" -#include "portapack_shared_memory.hpp" - -#include "hackrf_gpio.hpp" -using namespace hackrf::one; - #include #include #include @@ -41,77 +36,20 @@ public: virtual ~Writer() = default; }; -class StreamOutput { -public: - StreamOutput( - CaptureConfig* const config - ) : config { config } - { - shared_memory.baseband_queue.push_and_wait( - CaptureConfigMessage { config } - ); - fifo = config->fifo; - } - - ~StreamOutput() { - fifo = nullptr; - shared_memory.baseband_queue.push_and_wait( - CaptureConfigMessage { nullptr } - ); - } - - size_t available() { - return fifo->len(); - } - - size_t read(void* const data, const size_t length) { - return fifo->out(reinterpret_cast(data), length); - } - - static FIFO* fifo; - -private: - CaptureConfig* const config; -}; - class CaptureThread { public: CaptureThread( std::unique_ptr writer, size_t write_size_log2, size_t buffer_count_log2 - ) : config { write_size_log2, buffer_count_log2 }, - writer { std::move(writer) } - { - // Need significant stack for FATFS - thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, CaptureThread::static_fn, this); - } - - ~CaptureThread() { - if( thread ) { - chThdTerminate(thread); - chEvtSignal(thread, EVT_MASK_CAPTURE_THREAD); - const auto success = chThdWait(thread); - thread = nullptr; - - if( !success ) { - led_tx.on(); - } - } - } + ); + ~CaptureThread(); const CaptureConfig& state() const { return config; } - static void check_fifo_isr() { - // TODO: Prevent over-signalling by transmitting a set of - // flags from the baseband core. - const auto fifo = StreamOutput::fifo; - if( fifo ) { - chEvtSignalI(thread, EVT_MASK_CAPTURE_THREAD); - } - } + static void check_fifo_isr(); private: CaptureConfig config; @@ -123,44 +61,7 @@ private: return obj->run(); } - msg_t run() { - const size_t write_size = 1U << config.write_size_log2; - const auto write_buffer = std::make_unique(write_size); - if( !write_buffer ) { - return false; - } - - StreamOutput stream { &config }; - - while( !chThdShouldTerminate() ) { - if( stream.available() >= write_size ) { - if( !transfer(stream, write_buffer.get(), write_size) ) { - return false; - } - } else { - chEvtWaitAny(EVT_MASK_CAPTURE_THREAD); - } - } - - return true; - } - - bool transfer(StreamOutput& stream, uint8_t* const write_buffer, const size_t write_size) { - bool success = false; - - led_usb.on(); - - const auto bytes_to_write = stream.read(write_buffer, write_size); - if( bytes_to_write == write_size ) { - if( writer->write(write_buffer, write_size) ) { - success = true; - } - } - - led_usb.off(); - - return success; - } + msg_t run(); }; #endif/*__CAPTURE_THREAD_H__*/ From 56a7b841cb31bfa8186f03dc01189176852244e9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 2 May 2016 12:51:52 -0700 Subject: [PATCH 61/64] Remove CaptureThread LED control. --- firmware/application/capture_thread.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/firmware/application/capture_thread.cpp b/firmware/application/capture_thread.cpp index 867faeea1..6bccea57b 100644 --- a/firmware/application/capture_thread.cpp +++ b/firmware/application/capture_thread.cpp @@ -23,9 +23,6 @@ #include "portapack_shared_memory.hpp" -#include "hackrf_gpio.hpp" -using namespace hackrf::one; - // StreamOutput /////////////////////////////////////////////////////////// class StreamOutput { @@ -85,12 +82,8 @@ CaptureThread::~CaptureThread() { if( thread ) { chThdTerminate(thread); chEvtSignal(thread, EVT_MASK_CAPTURE_THREAD); - const auto success = chThdWait(thread); + chThdWait(thread); thread = nullptr; - - if( !success ) { - led_tx.on(); - } } } From 72cc6569ca43d5cdd12a2494c8dcf54b40ed4648 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 6 May 2016 15:04:53 -0700 Subject: [PATCH 62/64] Use UM10503 (user manual) suggestion for SD delay config. --- .../chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c index 2f09f9742..e54830129 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c @@ -580,6 +580,11 @@ void sdc_lld_start(SDCDriver *sdcp) { sdio_reset(); sdio_reset_card(); + // UM10503 recommendation + LPC_SCU->SDDELAY = + (0x8 << 0) + | (0xf << 8) + ; LPC_SDMMC->CTRL = (1U << 4) /* INT_ENABLE */ | (1U << 25) /* USE_INTERNAL_DMAC */ From ab73d6155eaa4cd80dc8360172020f04a8c62aaf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 8 May 2016 14:59:03 -0700 Subject: [PATCH 63/64] Improve arrow key next focus algorithm. --- firmware/common/ui_focus.cpp | 144 +++++++++++++++-------------------- 1 file changed, 63 insertions(+), 81 deletions(-) diff --git a/firmware/common/ui_focus.cpp b/firmware/common/ui_focus.cpp index 08310039f..92547d354 100644 --- a/firmware/common/ui_focus.cpp +++ b/firmware/common/ui_focus.cpp @@ -85,67 +85,78 @@ static void widget_collect_visible(Widget* const w, TestFn test, test_collection } } +static int32_t rect_distances( + const KeyEvent direction, + const Rect& rect_start, + const Rect& rect_end +) { + Coord on_axis_max, on_axis_min; + + switch(direction) { + case KeyEvent::Right: + on_axis_max = rect_end.left(); + on_axis_min = rect_start.right(); + break; + + case KeyEvent::Left: + on_axis_max = rect_start.left(); + on_axis_min = rect_end.right(); + break; + + case KeyEvent::Down: + on_axis_max = rect_end.top(); + on_axis_min = rect_start.bottom(); + break; + + case KeyEvent::Up: + on_axis_max = rect_start.top(); + on_axis_min = rect_end.bottom(); + break; + + default: + return -1; + } + + Coord on_axis_distance = on_axis_max - on_axis_min; + if( on_axis_distance < 0 ) { + return -1; + } + + Coord perpendicular_axis_start, perpendicular_axis_end; + + switch(direction) { + case KeyEvent::Right: + case KeyEvent::Left: + perpendicular_axis_start = rect_start.center().y; + perpendicular_axis_end = rect_end.center().y; + break; + + case KeyEvent::Up: + case KeyEvent::Down: + perpendicular_axis_start = rect_start.center().x; + perpendicular_axis_end = rect_end.center().x; + break; + + default: + return -1; + } + + return (std::abs(perpendicular_axis_end - perpendicular_axis_start) + 1) * (on_axis_distance + 1); +} + void FocusManager::update( Widget* const top_widget, const KeyEvent event ) { if( focus_widget() ) { const auto focus_screen_rect = focus_widget()->screen_rect(); - const auto center = focus_screen_rect.center(); - const auto test_fn = [¢er, event](ui::Widget* const w) -> test_result_t { + const auto test_fn = [&focus_screen_rect, event](ui::Widget* const w) -> test_result_t { // if( w->visible() && w->focusable() ) { if( w->focusable() ) { - const Point delta = w->screen_rect().center() - center; - - /* Heuristic to compute closeness. */ - /* TODO: Look at metric involving overlap of current - * widget rectangle in the direction of movement, with - * all the prospective widgets. - */ - switch(event) { - case KeyEvent::Right: - if( delta.x > 0 ) { - if( delta.y == 0 ) { - return { w, delta.x }; - } else { - return { w, delta.x * abs(delta.y) + 1000 }; - } - } - break; - - case KeyEvent::Left: - if( delta.x < 0 ) { - if( delta.y == 0 ) { - return { w, -delta.x }; - } else { - return { w, -delta.x * abs(delta.y) + 1000 }; - } - } - break; - - case KeyEvent::Down: - if( delta.y > 0 ) { - if( delta.x == 0 ) { - return { w, delta.y }; - } else { - return { w, delta.y * abs(delta.x) + 1000 }; - } - } - break; - - case KeyEvent::Up: - if( delta.y < 0 ) { - if( delta.x == 0 ) { - return { w, -delta.y }; - } else { - return { w, -delta.y * abs(delta.x) + 1000 }; - } - } - break; - - default: - break; + const auto distance = rect_distances(event, focus_screen_rect, w->screen_rect()); + if( distance >= 0 ) { + return { w, distance }; } } @@ -167,34 +178,5 @@ void FocusManager::update( } } } -#if 0 -void FocusManager::update( - Widget* const top_widget, - const TouchEvent event -) { - const auto test_fn = [event](Widget* const w) -> test_result_t { - if( w->focusable() ) { - const auto r = w->screen_rect(); - if( r.contains(event) ) { - return { w, 0 }; - } - } - return { nullptr, { } }; - }; - - test_collection_t collection; - widget_collect_visible( - top_widget, test_fn, - collection - ); - - if( !collection.empty() ) { - // Take the last object in the collection, it will be rendered last, - // therefore appear "on top". - const auto touched = collection.back().first; - touched->on_touch(event); - } -} -#endif } /* namespace ui */ From dc2944d5e90c5840c26b1868a06d49b752a99fd5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 8 May 2016 14:59:26 -0700 Subject: [PATCH 64/64] Make Widget::screen_rect() const. Because I can. --- firmware/common/ui_widget.cpp | 2 +- firmware/common/ui_widget.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 788b7abf7..abc040c37 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -56,7 +56,7 @@ Size Widget::size() const { return parent_rect.size; } -Rect Widget::screen_rect() { +Rect Widget::screen_rect() const { return parent() ? (parent_rect + parent()->screen_pos()) : parent_rect; } diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 1b99d282e..eb45de44e 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -69,7 +69,7 @@ public: Point screen_pos(); Size size() const; - Rect screen_rect(); + Rect screen_rect() const; virtual void set_parent_rect(const Rect new_parent_rect); Widget* parent() const;