diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 052bbe25b..4bf2ccf17 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -29,7 +29,7 @@ enable_language(C CXX ASM) project(application) # Compiler options here. -set(USE_OPT "-Os --specs=nano.specs") +set(USE_OPT "-Os -g --specs=nano.specs") # C specific options here (added to USE_OPT). set(USE_COPT "-std=gnu99") @@ -150,6 +150,7 @@ set(CPPSRC ui_audio.cpp ui_font_fixed_8x16.cpp ui_setup.cpp + ui_touch_calibration.cpp ui_debug.cpp ui_baseband_stats_view.cpp ui_sd_card_status_view.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index e16a202ae..971d32585 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -4062,6 +4062,30 @@ ui_textentry.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_textentry.cpp.s .PHONY : ui_textentry.cpp.s +ui_touch_calibration.obj: ui_touch_calibration.cpp.obj +.PHONY : ui_touch_calibration.obj + +# target to build an object file +ui_touch_calibration.cpp.obj: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_touch_calibration.cpp.obj +.PHONY : ui_touch_calibration.cpp.obj + +ui_touch_calibration.i: ui_touch_calibration.cpp.i +.PHONY : ui_touch_calibration.i + +# target to preprocess a source file +ui_touch_calibration.cpp.i: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_touch_calibration.cpp.i +.PHONY : ui_touch_calibration.cpp.i + +ui_touch_calibration.s: ui_touch_calibration.cpp.s +.PHONY : ui_touch_calibration.s + +# target to generate assembly for a file +ui_touch_calibration.cpp.s: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_touch_calibration.cpp.s +.PHONY : ui_touch_calibration.cpp.s + ui_xylos.obj: ui_xylos.cpp.obj .PHONY : ui_xylos.obj @@ -4588,6 +4612,9 @@ help: @echo "... ui_textentry.obj" @echo "... ui_textentry.i" @echo "... ui_textentry.s" + @echo "... ui_touch_calibration.obj" + @echo "... ui_touch_calibration.i" + @echo "... ui_touch_calibration.s" @echo "... ui_xylos.obj" @echo "... ui_xylos.i" @echo "... ui_xylos.s" diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 543e55530..814262e6d 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -25,6 +25,9 @@ #include "baseband_api.hpp" +#include "portapack.hpp" +using namespace portapack; + #include namespace ais { @@ -291,6 +294,11 @@ AISAppView::AISAppView(NavigationView&) { add_children({ { &label_channel, &options_channel, + &field_rf_amp, + &field_lna, + &field_vga, + &rssi, + &channel, &recent_entries_view, &recent_entry_detail_view, } }); @@ -304,7 +312,9 @@ AISAppView::AISAppView(NavigationView&) { sampling_rate, baseband_bandwidth, rf::Direction::Receive, - false, 32, 32, + receiver_model.rf_amp(), + static_cast(receiver_model.lna()), + static_cast(receiver_model.vga()), 1, }); diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 19286e6de..b38a21467 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -24,6 +24,9 @@ #include "ui_widget.hpp" #include "ui_navigation.hpp" +#include "ui_receiver.hpp" +#include "ui_rssi.hpp" +#include "ui_channel.hpp" #include "event_m0.hpp" @@ -177,6 +180,26 @@ private: } }; + RFAmpField field_rf_amp { + { 13 * 8, 0 * 16 } + }; + + LNAGainField field_lna { + { 15 * 8, 0 * 16 } + }; + + VGAGainField field_vga { + { 18 * 8, 0 * 16 } + }; + + RSSI rssi { + { 21 * 8, 0, 6 * 8, 4 }, + }; + + Channel channel { + { 21 * 8, 5, 6 * 8, 4 }, + }; + MessageHandlerRegistration message_handler_packet { Message::ID::AISPacket, [this](Message* const p) { diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 872a57c27..417d1ea12 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -119,7 +119,7 @@ AnalogAudioView::AnalogAudioView( }; const auto modulation = receiver_model.modulation(); - options_modulation.set_by_value(modulation); + options_modulation.set_by_value(toUType(modulation)); options_modulation.on_change = [this](size_t, OptionsField::value_t v) { this->on_modulation_changed(static_cast(v)); }; @@ -286,11 +286,8 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { baseband::run_image(image_tag); const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); - receiver_model.set_baseband_configuration({ - .mode = toUType(modulation), - .sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U, - .decimation_factor = 1, - }); + receiver_model.set_modulation(modulation); + receiver_model.set_sampling_rate(is_wideband_spectrum_mode ? 20000000 : 3072000); receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); receiver_model.enable(); diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index c030bde0a..72d9e2a4d 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -99,6 +99,13 @@ void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phas send_message(&message); } +void set_audiotx_data(const uint32_t bw) { + const AudioTXConfigMessage message { + bw + }; + send_message(&message); +} + void set_pwmrssi(int32_t avg, bool enabled) { const PWMRSSIConfigureMessage message { enabled, diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 5e91fcebe..9b6190651 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -53,6 +53,7 @@ struct WFMConfig { }; void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count); +void set_audiotx_data(const uint32_t bw); void set_pwmrssi(int32_t avg, bool enabled); void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space, const uint8_t afsk_repeat, const uint32_t afsk_bw, const bool afsk_alt_format); diff --git a/firmware/application/bitmap.hpp b/firmware/application/bitmap.hpp index cb427052c..47ee91d63 100644 --- a/firmware/application/bitmap.hpp +++ b/firmware/application/bitmap.hpp @@ -244,6 +244,98 @@ static constexpr Bitmap bitmap_sd_card_error { { 16, 16 }, bitmap_sd_card_error_data }; +static constexpr uint8_t bitmap_target_calibrate_data[] = { + 0x02, 0x00, 0x00, 0x40, + 0x07, 0x00, 0x00, 0xe0, + 0x0e, 0x00, 0x00, 0x70, + 0x1c, 0x00, 0x00, 0x38, + + 0x38, 0x00, 0x00, 0x1c, + 0x70, 0x00, 0x00, 0x0e, + 0xe0, 0x00, 0x00, 0x07, + 0xc0, 0x01, 0x80, 0x03, + + 0x80, 0x03, 0xc0, 0x01, + 0x00, 0x07, 0xe0, 0x00, + 0x00, 0x0e, 0x70, 0x00, + 0x00, 0x1c, 0x38, 0x00, + + 0x00, 0x38, 0x1c, 0x00, + 0x00, 0x30, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x0c, 0x00, + 0x00, 0x38, 0x1c, 0x00, + + 0x00, 0x1c, 0x38, 0x00, + 0x00, 0x0e, 0x70, 0x00, + 0x00, 0x07, 0xe0, 0x00, + 0x80, 0x03, 0xc0, 0x01, + + 0xc0, 0x01, 0x80, 0x03, + 0xe0, 0x00, 0x00, 0x07, + 0x70, 0x00, 0x00, 0x0e, + 0x38, 0x00, 0x00, 0x1c, + + 0x1c, 0x00, 0x00, 0x38, + 0x0e, 0x00, 0x00, 0x70, + 0x07, 0x00, 0x00, 0xe0, + 0x02, 0x00, 0x00, 0x40, +}; + +static constexpr Bitmap bitmap_target_calibrate { + { 32, 32 }, bitmap_target_calibrate_data +}; + +static constexpr uint8_t bitmap_target_verify_data[] = { + 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xfc, 0x3f, 0x00, + 0x00, 0x1f, 0xf8, 0x00, + 0xc0, 0x03, 0xc0, 0x03, + + 0xe0, 0x00, 0x00, 0x07, + 0x70, 0x00, 0x00, 0x0e, + 0x38, 0x00, 0x00, 0x1c, + 0x18, 0x00, 0x00, 0x18, + + 0x0c, 0x00, 0x00, 0x30, + 0x0c, 0x00, 0x00, 0x30, + 0x06, 0x00, 0x00, 0x60, + 0x06, 0x00, 0x00, 0x60, + + 0x06, 0x00, 0x00, 0x60, + 0x03, 0x80, 0x01, 0xc0, + 0x03, 0x80, 0x01, 0xc0, + 0x03, 0xe0, 0x07, 0xc0, + + 0x03, 0xe0, 0x07, 0xc0, + 0x03, 0x80, 0x01, 0xc0, + 0x03, 0x80, 0x01, 0xc0, + 0x06, 0x00, 0x00, 0x60, + + 0x06, 0x00, 0x00, 0x60, + 0x06, 0x00, 0x00, 0x60, + 0x0c, 0x00, 0x00, 0x30, + 0x0c, 0x00, 0x00, 0x30, + + 0x18, 0x00, 0x00, 0x18, + 0x38, 0x00, 0x00, 0x1c, + 0x70, 0x00, 0x00, 0x0e, + 0xe0, 0x00, 0x00, 0x07, + + 0xc0, 0x03, 0xc0, 0x03, + 0x00, 0x1f, 0xf8, 0x00, + 0x00, 0xfc, 0x3f, 0x00, + 0x00, 0xe0, 0x07, 0x00, +}; + +static constexpr Bitmap bitmap_target_verify { + { 32, 32 }, bitmap_target_verify_data +}; + } /* namespace ui */ #endif/*__BITMAP_HPP__*/ diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 269b1096c..e5597cd8d 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -23,6 +23,9 @@ #include "baseband_api.hpp" +#include "portapack.hpp" +using namespace portapack; + #include "manchester.hpp" #include "crc.hpp" @@ -124,6 +127,10 @@ ERTAppView::ERTAppView(NavigationView&) { baseband::run_image(portapack::spi_flash::image_tag_ert); add_children({ { + &field_rf_amp, + &field_lna, + &field_vga, + &rssi, &recent_entries_view, } }); @@ -132,7 +139,9 @@ ERTAppView::ERTAppView(NavigationView&) { sampling_rate, baseband_bandwidth, rf::Direction::Receive, - false, 32, 32, + receiver_model.rf_amp(), + static_cast(receiver_model.lna()), + static_cast(receiver_model.vga()), 1, }); @@ -149,12 +158,12 @@ ERTAppView::~ERTAppView() { } void ERTAppView::focus() { - recent_entries_view.focus(); + field_vga.focus(); } void ERTAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); - recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); + recent_entries_view.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }); } void ERTAppView::on_packet(const ert::Packet& packet) { diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index b74d599ed..1d901f453 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -23,6 +23,9 @@ #define __ERT_APP_H__ #include "ui_navigation.hpp" +#include "ui_receiver.hpp" +#include "ui_rssi.hpp" +#include "ui_channel.hpp" #include "event_m0.hpp" @@ -128,6 +131,24 @@ private: ERTRecentEntriesView recent_entries_view { recent }; + static constexpr auto header_height = 1 * 16; + + RFAmpField field_rf_amp { + { 13 * 8, 0 * 16 } + }; + + LNAGainField field_lna { + { 15 * 8, 0 * 16 } + }; + + VGAGainField field_vga { + { 18 * 8, 0 * 16 } + }; + + RSSI rssi { + { 21 * 8, 0, 6 * 8, 4 }, + }; + MessageHandlerRegistration message_handler_packet { Message::ID::ERTPacket, [this](Message* const p) { diff --git a/firmware/application/irq_controls.cpp b/firmware/application/irq_controls.cpp index cb6a2df5c..d57e9a9a6 100644 --- a/firmware/application/irq_controls.cpp +++ b/firmware/application/irq_controls.cpp @@ -58,27 +58,18 @@ static volatile uint32_t touch_phase { 0 }; * Noise will only occur when the panel is being touched. Not ideal, but * an acceptable improvement. */ -static std::array touch_pins_configs { +static std::array touch_pins_configs { /* State machine will pause here until touch is detected. */ - portapack::IO::TouchPinsConfig::WaitTouch, - portapack::IO::TouchPinsConfig::SensePressure, portapack::IO::TouchPinsConfig::SenseX, portapack::IO::TouchPinsConfig::SenseY, - portapack::IO::TouchPinsConfig::SenseX, - portapack::IO::TouchPinsConfig::SenseY, - portapack::IO::TouchPinsConfig::SensePressure, - portapack::IO::TouchPinsConfig::SenseX, - portapack::IO::TouchPinsConfig::SenseY, - portapack::IO::TouchPinsConfig::SenseX, - portapack::IO::TouchPinsConfig::SenseY, }; static touch::Frame temp_frame; static touch::Frame touch_frame; static uint32_t touch_debounce = 0; -static uint32_t touch_debounce_mask = (1U << 1) - 1; +static uint32_t touch_debounce_mask = (1U << 4) - 1; static bool touch_detected = false; static bool touch_cycle = false; @@ -87,22 +78,22 @@ static bool touch_update() { const auto current_phase = touch_pins_configs[touch_phase]; switch(current_phase) { - case portapack::IO::TouchPinsConfig::WaitTouch: + case portapack::IO::TouchPinsConfig::SensePressure: { - /* Debounce touches. */ - const bool touch_raw = (samples.yp < touch::touch_threshold) && (samples.yn < touch::touch_threshold); + const auto z1 = samples.xp - samples.xn; + const auto z2 = samples.yp - samples.yn; + const auto touch_raw = (z1 > touch::touch_threshold) || (z2 > touch::touch_threshold); touch_debounce = (touch_debounce << 1) | (touch_raw ? 1U : 0U); touch_detected = ((touch_debounce & touch_debounce_mask) == touch_debounce_mask); if( !touch_detected && !touch_cycle ) { + temp_frame.pressure = { }; return false; + } else { + temp_frame.pressure += samples; } } break; - case portapack::IO::TouchPinsConfig::SensePressure: - temp_frame.pressure += samples; - break; - case portapack::IO::TouchPinsConfig::SenseX: temp_frame.x += samples; break; diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 655161ebd..35059f5c7 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -116,11 +116,21 @@ void ReceiverModel::set_vga(int32_t v_db) { } uint32_t ReceiverModel::sampling_rate() const { - return baseband_configuration.sampling_rate; + return sampling_rate_; } -uint32_t ReceiverModel::modulation() const { - return baseband_configuration.mode; +void ReceiverModel::set_sampling_rate(uint32_t v) { + sampling_rate_ = v; + update_sampling_rate(); +} + +ReceiverModel::Mode ReceiverModel::modulation() const { + return mode_; +} + +void ReceiverModel::set_modulation(const Mode v) { + mode_ = v; + update_modulation(); } volume_t ReceiverModel::headphone_volume() const { @@ -134,7 +144,7 @@ void ReceiverModel::set_headphone_volume(volume_t v) { uint32_t ReceiverModel::baseband_oversampling() const { // TODO: Rename decimation_factor. - return baseband_configuration.decimation_factor; + return decimation_factor_; } void ReceiverModel::enable() { @@ -146,8 +156,8 @@ void ReceiverModel::enable() { update_lna(); update_vga(); update_baseband_bandwidth(); - update_baseband_configuration(); - update_modulation_configuration(); + update_sampling_rate(); + update_modulation(); update_headphone_volume(); } @@ -161,7 +171,7 @@ void ReceiverModel::disable() { } int32_t ReceiverModel::tuning_offset() { - if( (baseband_configuration.mode == 4) || (baseband_configuration.mode == 10) ) { + if( (modulation() == Mode::SpectrumAnalysis) ) { return 0; } else { return -(sampling_rate() / 4); @@ -192,33 +202,28 @@ void ReceiverModel::update_vga() { radio::set_vga_gain(vga_gain_db_); } -void ReceiverModel::set_baseband_configuration(const BasebandConfiguration config) { - baseband_configuration = config; - update_baseband_configuration(); -} - void ReceiverModel::set_am_configuration(const size_t n) { if( n < am_configs.size() ) { am_config_index = n; - update_modulation_configuration(); + update_modulation(); } } void ReceiverModel::set_nbfm_configuration(const size_t n) { if( n < nbfm_configs.size() ) { nbfm_config_index = n; - update_modulation_configuration(); + update_modulation(); } } void ReceiverModel::set_wfm_configuration(const size_t n) { if( n < wfm_configs.size() ) { wfm_config_index = n; - update_modulation_configuration(); + update_modulation(); } } -void ReceiverModel::update_baseband_configuration() { +void ReceiverModel::update_sampling_rate() { // TODO: Move more low-level radio control stuff to M4. It'll enable tighter // synchronization for things like wideband (sweeping) spectrum analysis, and // protocols that need quick RX/TX turn-around. @@ -236,8 +241,8 @@ void ReceiverModel::update_headphone_volume() { audio::headphone::set_volume(headphone_volume_); } -void ReceiverModel::update_modulation_configuration() { - switch(static_cast(modulation())) { +void ReceiverModel::update_modulation() { + switch(modulation()) { default: case Mode::AMAudio: update_am_configuration(); diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index 34f32ecd6..b94b50951 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -53,13 +53,11 @@ struct BasebandConfiguration { class ReceiverModel { public: - enum class Mode : int32_t { + enum class Mode { AMAudio = 0, NarrowbandFMAudio = 1, WidebandFMAudio = 2, - SpectrumAnalysis = 4, - Capture = 7, - CloseCall = 10, + SpectrumAnalysis = 3, }; rf::Frequency tuning_frequency() const; @@ -84,8 +82,10 @@ public: void set_vga(int32_t v_db); uint32_t sampling_rate() const; + void set_sampling_rate(uint32_t v); - uint32_t modulation() const; + Mode modulation() const; + void set_modulation(Mode v); volume_t headphone_volume() const; void set_headphone_volume(volume_t v); @@ -95,8 +95,6 @@ public: void enable(); void disable(); - void set_baseband_configuration(const BasebandConfiguration config); - size_t am_configuration() const; void set_am_configuration(const size_t n); @@ -114,11 +112,9 @@ private: int32_t lna_gain_db_ { 32 }; uint32_t baseband_bandwidth_ { max2837::filter::bandwidth_minimum }; int32_t vga_gain_db_ { 32 }; - BasebandConfiguration baseband_configuration { - .mode = 1, /* TODO: Enum! */ - .sampling_rate = 3072000, - .decimation_factor = 1, - }; + Mode mode_ { Mode::NarrowbandFMAudio }; + uint32_t sampling_rate_ { 3072000 }; + size_t decimation_factor_ { 1 }; size_t am_config_index = 0; size_t nbfm_config_index = 0; size_t wfm_config_index = 0; @@ -132,10 +128,10 @@ private: void update_lna(); void update_baseband_bandwidth(); void update_vga(); - void update_baseband_configuration(); + void update_sampling_rate(); void update_headphone_volume(); - void update_modulation_configuration(); + void update_modulation(); void update_am_configuration(); void update_nbfm_configuration(); void update_wfm_configuration(); diff --git a/firmware/application/touch.cpp b/firmware/application/touch.cpp index 09f8db8f1..ac48c0539 100644 --- a/firmware/application/touch.cpp +++ b/firmware/application/touch.cpp @@ -21,15 +21,14 @@ #include "touch.hpp" +#include "portapack_persistent_memory.hpp" +using namespace portapack; + +#include "utility.hpp" + namespace touch { -struct Metrics { - const float x; - const float y; - const float r; -}; - -static Metrics calculate_metrics(const Frame& frame) { +Metrics calculate_metrics(const Frame& frame) { /* TODO: Yikes! M0 doesn't have floating point, so this code is * expensive! On the other hand, it seems to be working well (and * fast *enough*?), so maybe leave it alone at least for now. @@ -38,14 +37,14 @@ static Metrics calculate_metrics(const Frame& frame) { const auto x_max = frame.x.xp; const auto x_min = frame.x.xn; const auto x_range = x_max - x_min; - const auto x_position = (frame.x.yp + frame.x.yn) / 2; - const float x_norm = float(x_position - x_min) / x_range; + const float x_position = (frame.x.yp + frame.x.yn) * 0.5f; + const float x_norm = (x_position - x_min) / x_range; const auto y_max = frame.y.yn; const auto y_min = frame.y.yp; const auto y_range = y_max - y_min; - const auto y_position = (frame.y.xp + frame.y.xn) / 2; - const float y_norm = float(y_position - y_min) / y_range; + const float y_position = (frame.y.xp + frame.y.xn) * 0.5f; + const float y_norm = (y_position - y_min) / y_range; const auto z_max = frame.pressure.yp; const auto z_min = frame.pressure.xn; @@ -66,6 +65,28 @@ static Metrics calculate_metrics(const Frame& frame) { }; } +ui::Point Calibration::translate(const DigitizerPoint& p) const { + static constexpr range_t x_range { 0, 240 - 1 }; + static constexpr range_t y_range { 0, 320 - 1 }; + + const int32_t x = (a * p.x + b * p.y + c) / k; + const int32_t y = (d * p.x + e * p.y + f) / k; + const auto x_clipped = x_range.clip(x); + const auto y_clipped = y_range.clip(y); + return { + static_cast(x_clipped), + static_cast(y_clipped) + }; +} + +const Calibration default_calibration() { + /* Values derived from one PortaPack H1 unit. */ + return { + { { { 256, 731 }, { 880, 432 }, { 568, 146 } } }, + { { { 32, 48 }, { 208, 168 }, { 120, 288 } } } + }; +}; + void Manager::feed(const Frame& frame) { // touch_debounce.feed(touch_raw); const auto touch_raw = frame.touch; @@ -81,10 +102,8 @@ void Manager::feed(const Frame& frame) { // TODO: Add touch pressure hysteresis? touch_pressure = (metrics.r < r_touch_threshold); if( touch_pressure ) { - const float x = width_pixels * (metrics.x - calib_x_low) / calib_x_range; - filter_x.feed(x); - const float y = height_pixels * (calib_y_high - metrics.y) / calib_y_range; - filter_y.feed(y); + filter_x.feed(metrics.x * 1024); + filter_y.feed(metrics.y * 1024); } } else { filter_x.reset(); @@ -116,4 +135,8 @@ void Manager::feed(const Frame& frame) { } } +ui::Point Manager::filtered_point() const { + return persistent_memory::touch_calibration().translate({ filter_x.value(), filter_y.value() }); +} + } /* namespace touch */ diff --git a/firmware/application/touch.hpp b/firmware/application/touch.hpp index c814db2c3..bc451e36e 100644 --- a/firmware/application/touch.hpp +++ b/firmware/application/touch.hpp @@ -38,7 +38,7 @@ using sample_t = uint16_t; constexpr sample_t sample_max = 1023; -constexpr sample_t touch_threshold = sample_max * 0.5f; +constexpr sample_t touch_threshold = sample_max / 5; struct Samples { sample_t xp; @@ -106,6 +106,51 @@ struct Frame { bool touch { false }; }; +struct Metrics { + const float x; + const float y; + const float r; +}; + +Metrics calculate_metrics(const Frame& frame); + +struct DigitizerPoint { + int32_t x; + int32_t y; +}; + +struct Calibration { + /* Touch screen calibration matrix, based on article by Carlos E. Vidales: + * http://www.embedded.com/design/system-integration/4023968/How-To-Calibrate-Touch-Screens + */ + + constexpr Calibration( + const std::array& s, + const std::array& d + ) : k { (s[0].x - s[2].x) * (s[1].y - s[2].y) - (s[1].x - s[2].x) * (s[0].y - s[2].y) }, + a { (d[0].x - d[2].x) * (s[1].y - s[2].y) - (d[1].x - d[2].x) * (s[0].y - s[2].y) }, + b { (s[0].x - s[2].x) * (d[1].x - d[2].x) - (d[0].x - d[2].x) * (s[1].x - s[2].x) }, + c { s[0].y * (s[2].x * d[1].x - s[1].x * d[2].x) + s[1].y * (s[0].x * d[2].x - s[2].x * d[0].x) + s[2].y * (s[1].x * d[0].x - s[0].x * d[1].x) }, + d { (d[0].y - d[2].y) * (s[1].y - s[2].y) - (d[1].y - d[2].y) * (s[0].y - s[2].y) }, + e { (s[0].x - s[2].x) * (d[1].y - d[2].y) - (d[0].y - d[2].y) * (s[1].x - s[2].x) }, + f { s[0].y * (s[2].x * d[1].y - s[1].x * d[2].y) + s[1].y * (s[0].x * d[2].y - s[2].x * d[0].y) + s[2].y * (s[1].x * d[0].y - s[0].x * d[1].y) } + { + } + + ui::Point translate(const DigitizerPoint& p) const; + +private: + int32_t k; + int32_t a; + int32_t b; + int32_t c; + int32_t d; + int32_t e; + int32_t f; +}; + +const Calibration default_calibration(); + template class Filter { public: @@ -173,20 +218,9 @@ private: TouchDetected, }; - static constexpr uint32_t width_pixels = 240; - static constexpr uint32_t height_pixels = 320; - - static constexpr float r_touch_threshold = 0x1000; - static constexpr size_t touch_count_threshold { 4 }; - static constexpr uint32_t touch_stable_bound { 4 }; - - static constexpr float calib_x_low = 0.15f; - static constexpr float calib_x_high = 0.98f; - static constexpr float calib_x_range = calib_x_high - calib_x_low; - - static constexpr float calib_y_low = 0.04f; - static constexpr float calib_y_high = 0.80f; //91 - static constexpr float calib_y_range = calib_y_high - calib_y_low; + static constexpr float r_touch_threshold = 640; + static constexpr size_t touch_count_threshold { 3 }; + static constexpr uint32_t touch_stable_bound { 8 }; // Ensure filter length is equal or less than touch_count_threshold, // or coordinates from the last touch will be in the initial averages. @@ -202,12 +236,7 @@ private: && filter_y.stable(touch_stable_bound); } - ui::Point filtered_point() const { - return { - static_cast(filter_x.value()), - static_cast(filter_y.value()) - }; - } + ui::Point filtered_point() const; void touch_started() { fire_event(ui::TouchEvent::Type::Start); diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 0c96971cb..008a920af 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -181,7 +181,7 @@ TPMSAppView::TPMSAppView(NavigationView&) { sampling_rate, baseband_bandwidth, rf::Direction::Receive, - false, + receiver_model.rf_amp(), static_cast(receiver_model.lna()), static_cast(receiver_model.vga()), 1, diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 84aacd61f..fc9e0c350 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -119,7 +119,7 @@ private: } }; - static constexpr ui::Dim header_height = 2 * 16; + static constexpr ui::Dim header_height = 1 * 16; RSSI rssi { { 21 * 8, 0, 6 * 8, 4 }, diff --git a/firmware/application/ui_about.cpp b/firmware/application/ui_about.cpp index 50e8905aa..2dc98d5aa 100644 --- a/firmware/application/ui_about.cpp +++ b/firmware/application/ui_about.cpp @@ -48,8 +48,21 @@ using namespace portapack; namespace ui { void AboutView::on_show() { - about_radio_config.tuning_frequency = 92200000; // 92.2MHz, change ! - radio::enable(about_radio_config); + transmitter_model.set_tuning_frequency(92200000); + transmitter_model.set_baseband_configuration({ + .mode = 0, + .sampling_rate = 1536000, + .decimation_factor = 1, + }); + transmitter_model.set_rf_amp(true); + transmitter_model.set_lna(40); + transmitter_model.set_vga(40); + transmitter_model.set_baseband_bandwidth(1750000); + transmitter_model.enable(); + + baseband::set_audiotx_data( + 0 + ); //audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max); } @@ -352,6 +365,8 @@ AboutView::AboutView( { uint8_t p, c; + baseband::run_image(portapack::spi_flash::image_tag_audio_tx); + add_children({ { &text_title, &text_firmware, @@ -394,7 +409,8 @@ AboutView::AboutView( } AboutView::~AboutView() { - radio::disable(); + transmitter_model.disable(); + baseband::shutdown(); } void AboutView::focus() { diff --git a/firmware/application/ui_about.hpp b/firmware/application/ui_about.hpp index 4619723f9..18f690615 100644 --- a/firmware/application/ui_about.hpp +++ b/firmware/application/ui_about.hpp @@ -48,17 +48,6 @@ private: void draw_demoglyph(ui::Point p, char ch, ui::Color * pal); uint16_t debug_cnt = 0; - radio::Configuration about_radio_config = { - 0, - 1536000, // ? - 2500000, // ? - rf::Direction::Transmit, - true, - 0, - 0, - 1, - }; - typedef struct ymreg_t { uint8_t value; uint8_t cnt; @@ -170,8 +159,6 @@ private: FIFODataMessage datamessage; const auto message = static_cast(p); if (message->signaltype == 1) { - //debug_cnt++; - //if (debug_cnt == 250) for(;;) {} this->render_audio(); datamessage.data = ym_buffer; EventDispatcher::send_message(datamessage); diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index f79d5abf6..b632756b0 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -247,7 +247,6 @@ void LCRView::start_tx(const bool scan) { afsk_format = 0; } - transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency()); transmitter_model.set_baseband_configuration({ .mode = 0, @@ -281,7 +280,7 @@ LCRView::LCRView(NavigationView& nav) { baseband::run_image(portapack::spi_flash::image_tag_afsk); - strcpy(rgsb, &scan_list[options_scanlist.selected_index()].addresses[0]); + strcpy(rgsb, &scan_list[0].addresses[0]); add_children({ { &text_recap, @@ -298,6 +297,8 @@ LCRView::LCRView(NavigationView& nav) { &button_clear } }); + options_scanlist.set_selected_index(0); + const auto button_setam_fn = [this, &nav](Button& button) { this->on_button_setam(nav, button); }; diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 876427442..7d7ba6c92 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -44,7 +44,7 @@ private: const char * addresses; }; - scan_list_t scan_list[2] = { + const scan_list_t scan_list[2] = { { 36, &RGSB_list_Lille[0][0] }, { 23, &RGSB_list_Reims[0][0] } }; @@ -80,9 +80,8 @@ private: tx_modes tx_mode = IDLE; bool abort_scan = false; - uint8_t scan_count; + uint8_t scan_count, scan_index; double scan_progress; - unsigned int scan_index; char litteral[5][8] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }; char rgsb[5] = { 0 }; char lcr_message[512]; @@ -97,20 +96,6 @@ private: void on_txdone(int n); void on_button_setam(NavigationView& nav, Button& button); - radio::Configuration lcr_radio_config = { - 0, - 2280000, - 2500000, // ? - rf::Direction::Transmit, - true, - 0, - 0, - 1, - }; - - // 2: 94 ? - // 9: 85 ? - const Style style_val { .font = font::fixed_8x16, .background = Color::green(), diff --git a/firmware/application/ui_setup.cpp b/firmware/application/ui_setup.cpp index 2caa8edc6..5de60905a 100644 --- a/firmware/application/ui_setup.cpp +++ b/firmware/application/ui_setup.cpp @@ -21,6 +21,8 @@ #include "ui_setup.hpp" +#include "ui_touch_calibration.hpp" + #include "portapack_persistent_memory.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -32,6 +34,7 @@ using namespace portapack; #include "string_format.hpp" #include "portapack_persistent_memory.hpp" #include "ui_font_fixed_8x16.hpp" +#include "cpld_update.hpp" namespace ui { @@ -172,18 +175,6 @@ void AntennaBiasSetupView::focus() { button_done.focus(); } -void SetTouchCalibView::focus() { - button_ok.focus(); -} - -bool SetTouchCalibView::on_touch(const TouchEvent event) { - if (event.type == ui::TouchEvent::Type::Start) { - text_debugx.set(to_string_dec_uint(round(event.point.x), 4)); - text_debugy.set(to_string_dec_uint(round(event.point.y), 4)); - } - return true; -} - SetPlayDeadView::SetPlayDeadView(NavigationView& nav) { add_children({{ &text_sequence, @@ -445,7 +436,7 @@ SetupMenuView::SetupMenuView(NavigationView& nav) { { "Date/Time", ui::Color::white(), [&nav](){ nav.push(); } }, { "Frequency correction", ui::Color::white(), [&nav](){ nav.push(); } }, { "Antenna Bias Voltage", ui::Color::white(), [&nav](){ nav.push(); } }, - { "Touch screen", ui::Color::white(), [&nav](){ nav.push(); } }, + { "Touch screen", ui::Color::white(), [&nav](){ nav.push(); } }, { "Play dead", ui::Color::red(), [&nav](){ nav.push(); } } } }); on_left = [&nav](){ nav.pop(); }; diff --git a/firmware/application/ui_touch_calibration.cpp b/firmware/application/ui_touch_calibration.cpp new file mode 100644 index 000000000..6fe200270 --- /dev/null +++ b/firmware/application/ui_touch_calibration.cpp @@ -0,0 +1,206 @@ +/* + * 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_touch_calibration.hpp" + +#include "irq_controls.hpp" + +#include "portapack_persistent_memory.hpp" +using namespace portapack; + +namespace ui { + +TouchCalibrationView::TouchCalibrationView( + NavigationView& nav +) : nav { nav }, + calibration { touch::default_calibration() } +{ + add_children({ { + &image_calibrate_0, + &image_calibrate_1, + &image_calibrate_2, + &image_verify_0, + &image_verify_1, + &image_verify_2, + &label_calibrate, + &label_verify, + &label_success, + &label_failure, + &button_cancel, + &button_ok, + } }); + + button_cancel.on_select = [this](Button&){ this->on_cancel(); }; + button_ok.on_select = [this](Button&){ this->on_ok(); }; + + set_phase(Phase::Calibrate0); +} + +void TouchCalibrationView::focus() { + button_cancel.focus(); +} + +void TouchCalibrationView::update_target() { + const auto phase_calibrate = (phase == Phase::Calibrate0) || (phase == Phase::Calibrate1) || (phase == Phase::Calibrate2); + const auto phase_verify = (phase == Phase::Verify0) || (phase == Phase::Verify1) || (phase == Phase::Verify2); + + image_calibrate_0.hidden(phase != Phase::Calibrate0); + image_calibrate_1.hidden(phase != Phase::Calibrate1); + image_calibrate_2.hidden(phase != Phase::Calibrate2); + + image_verify_0.hidden(phase != Phase::Verify0); + image_verify_1.hidden(phase != Phase::Verify1); + image_verify_2.hidden(phase != Phase::Verify2); + + label_calibrate.hidden(!phase_calibrate); + label_verify.hidden(!phase_verify); + label_success.hidden(phase != Phase::Success); + label_failure.hidden(phase != Phase::Failure); + + button_ok.hidden((phase != Phase::Success) && (phase != Phase::Failure)); + + /* TODO: Such a hack to get around a poor repaint implementation! This "technique" + * occurs in other places... + */ + set_dirty(); +} + +void TouchCalibrationView::set_phase(const Phase value) { + if( value != phase ) { + phase = value; + update_target(); + } +} + +uint32_t TouchCalibrationView::distance_squared(const Point& touch_point, const Image& target) { + const auto target_point = target.screen_rect().center(); + const int32_t dx = target_point.x - touch_point.x; + const int32_t dy = target_point.y - touch_point.y; + const uint32_t dx2 = dx * dx; + const uint32_t dy2 = dy * dy; + return dx2 + dy2; +} + +void TouchCalibrationView::touch_complete() { + auto next_phase = static_cast(toUType(phase) + 1); + + switch(phase) { + case Phase::Calibrate0: + case Phase::Verify0: + digitizer_points[0] = average; + break; + + case Phase::Calibrate1: + case Phase::Verify1: + digitizer_points[1] = average; + break; + + case Phase::Calibrate2: + case Phase::Verify2: + digitizer_points[2] = average; + break; + + default: + break; + } + + if( phase == Phase::Calibrate2 ) { + const std::array display_points { { + image_calibrate_0.screen_rect().center(), + image_calibrate_1.screen_rect().center(), + image_calibrate_2.screen_rect().center(), + } }; + + calibration = { digitizer_points, display_points }; + } + + if( phase == Phase::Verify2 ) { + const auto calibrated_0 = calibration.translate(digitizer_points[0]); + const auto d_sq_0 = distance_squared(calibrated_0, image_verify_0); + + const auto calibrated_1 = calibration.translate(digitizer_points[1]); + const auto d_sq_1 = distance_squared(calibrated_1, image_verify_1); + + const auto calibrated_2 = calibration.translate(digitizer_points[2]); + const auto d_sq_2 = distance_squared(calibrated_2, image_verify_2); + + if( (d_sq_0 < verify_d_sq_max) && (d_sq_1 < verify_d_sq_max) && (d_sq_2 < verify_d_sq_max) ) { + next_phase = Phase::Success; + } else { + next_phase = Phase::Failure; + } + } + + set_phase(next_phase); +} + +void TouchCalibrationView::on_ok() { + if( phase == Phase::Success ) { + persistent_memory::set_touch_calibration(calibration); + nav.pop(); + } + if( phase == Phase::Failure ) { + set_phase(Phase::Calibrate0); + } +} + +void TouchCalibrationView::on_cancel() { + nav.pop(); +} + +void TouchCalibrationView::on_frame_sync() { + switch(phase) { + case Phase::Calibrate0: + case Phase::Calibrate1: + case Phase::Calibrate2: + case Phase::Verify0: + case Phase::Verify1: + case Phase::Verify2: + break; + + default: + return; + } + + const auto frame = get_touch_frame(); + const auto metrics = touch::calculate_metrics(frame); + const auto x = metrics.x * 1024; + const auto y = metrics.y * 1024; + + if( metrics.r < 640.0f ) { + if( samples_count > 0 ) { + average.x = ((average.x * 7) + x) / 8; + average.y = ((average.y * 7) + y) / 8; + } else { + average.x = x; + average.y = y; + } + + samples_count += 1; + } else { + if( samples_count >= samples_limit ) { + touch_complete(); + } + samples_count = 0; + } +} + +} /* namespace ui */ diff --git a/firmware/application/ui_touch_calibration.hpp b/firmware/application/ui_touch_calibration.hpp new file mode 100644 index 000000000..40329020e --- /dev/null +++ b/firmware/application/ui_touch_calibration.hpp @@ -0,0 +1,158 @@ +/* + * 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_TOUCH_CALIBRATION_HPP__ +#define __UI_TOUCH_CALIBRATION_HPP__ + +#include "ui_widget.hpp" +#include "ui_navigation.hpp" +#include "touch.hpp" + +namespace ui { + +class TouchCalibrationView : public View { +public: + TouchCalibrationView(NavigationView& nav); + + void focus() override; + +private: + enum class Phase { + Init, + Calibrate0, + Calibrate1, + Calibrate2, + Verify0, + Verify1, + Verify2, + Success, + Failure, + }; + + NavigationView& nav; + Phase phase { Phase::Init }; + + void update_target(); + + void set_phase(const Phase value); + + uint32_t distance_squared(const Point& touch_point, const Image& target); + + void touch_complete(); + void on_ok(); + void on_cancel(); + + const uint32_t samples_limit { 40 }; + const uint32_t verify_d_sq_max = 10 * 10; + + uint32_t samples_count { 0 }; + + touch::DigitizerPoint average; + + std::array digitizer_points; + + touch::Calibration calibration; + + Image image_calibrate_0 { + { 32 - 16, 32 - 16, 32, 32 }, + &bitmap_target_calibrate, + Color::white(), + Color::black() + }; + + Image image_calibrate_1 { + { 240 - 32 - 16, (320 - 16) / 2 - 16, 32, 32 }, + &bitmap_target_calibrate, + Color::white(), + Color::black() + }; + + Image image_calibrate_2 { + { 240 / 2 - 16, (320 - 16) - 32 - 16, 32, 32 }, + &bitmap_target_calibrate, + Color::white(), + Color::black() + }; + + Image image_verify_0 { + { 32 - 16, 32 - 16, 32, 32 }, + &bitmap_target_verify, + Color::white(), + Color::black() + }; + + Image image_verify_1 { + { 240 - 32 - 16, (320 - 16) / 2 - 16, 32, 32 }, + &bitmap_target_verify, + Color::white(), + Color::black() + }; + + Image image_verify_2 { + { 240 / 2 - 16, (320 - 16) - 32 - 16, 32, 32 }, + &bitmap_target_verify, + Color::white(), + Color::black() + }; + + Text label_calibrate { + { 16, 5 * 16, 26 * 8, 1 * 16 }, + "Touch targets to calibrate" + }; + + Text label_verify { + { 28, 5 * 16, 23 * 8, 1 * 16 }, + "Touch targets to verify" + }; + + Text label_success { + { 32, 5 * 16, 22 * 8, 1 * 16 }, + "Apply new calibration?" + }; + + Text label_failure { + { 16, 5 * 16, 26 * 8, 1 * 16 }, + "Calibration failed. Retry?" + }; + + Button button_cancel { + { 40, 200, 64, 24 }, + "Cancel" + }; + + Button button_ok { + { 136, 200, 64, 24 }, + "OK" + }; + + void on_frame_sync(); + + MessageHandlerRegistration message_handler_frame_sync { + Message::ID::DisplayFrameSync, + [this](const Message* const) { + this->on_frame_sync(); + } + }; +}; + +} /* namespace ui */ + +#endif/*__UI_TOUCH_CALIBRATION_HPP__*/ diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 4f273c26c..5b9dc8ef6 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -29,7 +29,7 @@ enable_language(C CXX ASM) project(baseband_shared) # Compiler options here. -set(USE_OPT "-O3 -falign-functions=16 -fno-math-errno --specs=nano.specs") +set(USE_OPT "-O3 -g -falign-functions=16 -fno-math-errno --specs=nano.specs") # C specific options here (added to USE_OPT). set(USE_COPT "-std=gnu99") @@ -342,10 +342,10 @@ DeclareTargets(POOK ook) ### Audio transmit -#set(MODE_CPPSRC -# proc_audiotx.cpp -#) -#DeclareTargets(PATX audio_tx) +set(MODE_CPPSRC + proc_audiotx.cpp +) +DeclareTargets(PATX audio_tx) ### AFSK @@ -361,13 +361,6 @@ DeclareTargets(PAFS afsk) #) #DeclareTargets(PEPR epar) -### Play audio - -#set(MODE_CPPSRC -# proc_playaudio.cpp -#) -#DeclareTargets(PPAU play_audio) - ### Xylos set(MODE_CPPSRC diff --git a/firmware/baseband/proc_afsk.cpp b/firmware/baseband/proc_afsk.cpp index b47545963..055c99c48 100644 --- a/firmware/baseband/proc_afsk.cpp +++ b/firmware/baseband/proc_afsk.cpp @@ -119,8 +119,8 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) { } } -void AFSKProcessor::on_message(const Message* const p) { - const auto message = *reinterpret_cast(p); +void AFSKProcessor::on_message(const Message* const msg) { + const auto message = *reinterpret_cast(msg); if (message.id == Message::ID::AFSKConfigure) { afsk_samples_per_bit = message.samples_per_bit; diff --git a/firmware/baseband/proc_afsk.hpp b/firmware/baseband/proc_afsk.hpp index 74d056a78..1db25682b 100644 --- a/firmware/baseband/proc_afsk.hpp +++ b/firmware/baseband/proc_afsk.hpp @@ -30,7 +30,7 @@ class AFSKProcessor : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; - void on_message(const Message* const p) override; + void on_message(const Message* const msg) override; private: bool configured = false; diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index f4bf84f9c..4f8a6cf58 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -24,6 +24,7 @@ #include "baseband_processor.hpp" #include "baseband_thread.hpp" +#include "rssi_thread.hpp" #include "channel_decimator.hpp" #include "matched_filter.hpp" @@ -51,6 +52,7 @@ private: static constexpr size_t baseband_fs = 2457600; BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive }; + RSSIThread rssi_thread { NORMALPRIO + 10 }; std::array dst; const buffer_c16_t dst_buffer { diff --git a/firmware/baseband/proc_audiotx.cpp b/firmware/baseband/proc_audiotx.cpp index 85a40c84c..3b383ab89 100644 --- a/firmware/baseband/proc_audiotx.cpp +++ b/firmware/baseband/proc_audiotx.cpp @@ -23,33 +23,69 @@ #include "proc_audiotx.hpp" #include "portapack_shared_memory.hpp" #include "sine_table.hpp" +//#include "audio_output.hpp" #include "event_m4.hpp" #include void AudioTXProcessor::execute(const buffer_c8_t& buffer){ - - for (size_t i = 0; i>18]*127); //(int8_t)lfsr(sample + i); - if (bc & 0x40) - aphase += 60000; - else - aphase += 90000; + // This is called at 1536000/2048 = 750Hz + + if (!configured) return; + + ai = 0; + for (size_t i = 0; i= 31) { + as = 0; + //audio_fifo.out(&sample, 1); + //preview_audio_buffer.p[ai++] = sample << 8; - //FM - frq = sample * 1000; + //if ((audio_fifo.len() < 1024) && (asked == false)) { + // Ask application to fill up fifo + sigmessage.signaltype = 1; + shared_memory.application_queue.push(sigmessage); + asked = true; + //} + } else { + as++; + } + + + // FM + frq = (int32_t)(sample) * 4 * 2000; phase = (phase + frq); - sphase = phase + (256<<16); + sphase = phase + (256 << 16); re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127); im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127); - buffer.p[i] = {(int8_t)re,(int8_t)im}; + buffer.p[i] = { (int8_t)re, (int8_t)im }; } - bc++; + //AudioOutput::fill_audio_buffer(preview_audio_buffer, true); +} + +void AudioTXProcessor::on_message(const Message* const msg) { + switch(msg->id) { + case Message::ID::AudioTXConfig: + //const auto message = static_cast(msg); + configured = true; + break; + + case Message::ID::FIFOData: + //audio_fifo.in(static_cast(msg)->data, 1024); + asked = false; + break; + + default: + break; + } } int main() { diff --git a/firmware/baseband/proc_audiotx.hpp b/firmware/baseband/proc_audiotx.hpp index 34d30be7f..0bc6ea436 100644 --- a/firmware/baseband/proc_audiotx.hpp +++ b/firmware/baseband/proc_audiotx.hpp @@ -23,22 +23,39 @@ #ifndef __PROC_AUDIOTX_H__ #define __PROC_AUDIOTX_H__ +#include "fifo.hpp" #include "baseband_processor.hpp" -#include "baseband_thread.hpp" - -#include class AudioTXProcessor : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; + void on_message(const Message* const msg) override; + private: + bool configured = false; + + //std::unique_ptr audio_fifo_data = std::make_unique(1UL << 11); + //FIFO audio_fifo = { audio_fifo_data.get(), 11 }; // 43ms @ 48000Hz + + uint8_t as = 0, ai; int8_t re, im; - uint8_t s, as = 0, ai; - uint8_t byte_pos = 0; - uint8_t digit = 0; + int8_t sample; + + int16_t st; + + bool asked = false; + + //int16_t audio_data[64]; + /*const buffer_s16_t preview_audio_buffer { + audio_data, + sizeof(int16_t)*64 + };*/ + + FIFOSignalMessage sigmessage; + uint32_t aphase, phase, sphase; - int32_t sample, frq, bc; + int32_t frq; }; #endif diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index e26b98909..71122606e 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -24,6 +24,7 @@ #include "baseband_processor.hpp" #include "baseband_thread.hpp" +#include "rssi_thread.hpp" #include "channel_decimator.hpp" @@ -63,6 +64,7 @@ private: const float clock_recovery_rate = symbol_rate * 2; BasebandThread baseband_thread { baseband_sampling_rate, this, NORMALPRIO + 20, baseband::Direction::Receive }; + RSSIThread rssi_thread { NORMALPRIO + 10 }; clock_recovery::ClockRecovery clock_recovery { clock_recovery_rate, symbol_rate, { 1.0f / 18.0f }, diff --git a/firmware/baseband/proc_playaudio.cpp b/firmware/baseband/proc_playaudio.cpp deleted file mode 100644 index b66af4322..000000000 --- a/firmware/baseband/proc_playaudio.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * Copyright (C) 2016 Furrtek - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "proc_playaudio.hpp" -#include "portapack_shared_memory.hpp" -#include "sine_table.hpp" -#include "audio_output.hpp" -#include "event_m4.hpp" - -#include - -void PlayAudioProcessor::on_message(const Message* const msg) { - if (msg->id == Message::ID::FIFOData) { - const auto message = static_cast(msg); - memcpy(&audio_fifo[fifo_put], message->data, 1024); - fifo_put = (fifo_put + 1024) & 0x0FFF; - asked = false; - } -} - -void PlayAudioProcessor::execute(const buffer_c8_t& buffer){ - - // This is called at 1536000/2048 = 750Hz - - ai = 0; - for (size_t i = 0; i= 31) { - as = 0; - sample = audio_fifo[fifo_get]; - preview_audio_buffer.p[ai++] = sample << 8; - fifo_get = (fifo_get + 1) & 0x0FFF; - if ((((fifo_put - fifo_get) & 0x0FFF) < 3072) && (asked == false)) { - // Ask application to fill up fifo - sigmessage.signaltype = 1; - shared_memory.application_queue.push(sigmessage); - asked = true; - } - } else { - as++; - } - - sample = ((int8_t)audio_fifo[fifo_get] * 4); - - //FM - frq = sample * 2000; - - phase = (phase + frq); - sphase = phase + (256<<16); - - re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127); - im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127); - - buffer.p[i] = {(int8_t)re,(int8_t)im}; - } - - //AudioOutput::fill_audio_buffer(preview_audio_buffer, true); -} - -int main() { - EventDispatcher event_dispatcher { std::make_unique() }; - event_dispatcher.run(); - return 0; -} diff --git a/firmware/baseband/proc_playaudio.hpp b/firmware/baseband/proc_playaudio.hpp deleted file mode 100644 index b2f614749..000000000 --- a/firmware/baseband/proc_playaudio.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * Copyright (C) 2016 Furrtek - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PROC_PLAYAUDIO_H__ -#define __PROC_PLAYAUDIO_H__ - -#include "baseband_processor.hpp" - -class PlayAudioProcessor : public BasebandProcessor { -public: - void execute(const buffer_c8_t& buffer) override; - void on_message(const Message* const msg) override; - -private: - int8_t audio_fifo[4096]; // Probably too much (=85ms @ 48000Hz) - uint16_t fifo_put, fifo_get; - uint8_t as = 0, ai; - int8_t re, im; - - int16_t st; - - int16_t audio_data[64]; - - bool asked = false; - - const buffer_s16_t preview_audio_buffer { - audio_data, - sizeof(int16_t)*64 - }; - - FIFOSignalMessage sigmessage; - - uint32_t aphase, phase, sphase; - int32_t sample, frq; -}; - -#endif diff --git a/firmware/baseband/proc_rds.cpp b/firmware/baseband/proc_rds.cpp index e06fe39f2..5bf0e82ab 100644 --- a/firmware/baseband/proc_rds.cpp +++ b/firmware/baseband/proc_rds.cpp @@ -28,10 +28,6 @@ #include void RDSProcessor::execute(const buffer_c8_t& buffer) { - uint32_t * rdsdata; - - // TODO - //rdsdata = (uint32_t *)shared_memory.radio_data; for (size_t i = 0; i < buffer.count; i++) { @@ -96,6 +92,14 @@ void RDSProcessor::execute(const buffer_c8_t& buffer) { } } +void RDSProcessor::on_message(const Message* const msg) { + if (msg->id == Message::ID::RDSConfigure) { + //const auto message = *reinterpret_cast(p); + rdsdata = (uint32_t*)shared_memory.tx_data; + configured = true; + } +} + int main() { EventDispatcher event_dispatcher { std::make_unique() }; event_dispatcher.run(); diff --git a/firmware/baseband/proc_rds.hpp b/firmware/baseband/proc_rds.hpp index adbecadd8..c959ad460 100644 --- a/firmware/baseband/proc_rds.hpp +++ b/firmware/baseband/proc_rds.hpp @@ -24,6 +24,7 @@ #define __PROC_RDS_H__ #include "baseband_processor.hpp" +#include "baseband_thread.hpp" #define SAMPLES_PER_BIT 192 #define FILTER_SIZE 576 @@ -32,8 +33,14 @@ class RDSProcessor : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; + + void on_message(const Message* const msg) override; private: + uint32_t * rdsdata; + + BasebandThread baseband_thread { 2280000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; + int8_t re, im; uint8_t mphase, s; uint32_t bit_pos; @@ -49,6 +56,8 @@ private: uint32_t phase, sphase; int32_t sig, frq, frq_im, rdsc; int32_t k; + + bool configured { false }; const int32_t waveform_biphase[576] = { 165,167,168,168,167,166,163,160, diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index f85f19fc7..3958ed75a 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -98,7 +98,7 @@ private: }; static constexpr float channel_rate_in = 307200.0f; - static constexpr size_t channel_decimation = 8; + static constexpr size_t channel_decimation = 2; static constexpr float channel_sample_rate = channel_rate_in / channel_decimation; OOKSlicerMagSquaredInt ook_slicer_5sps { channel_sample_rate / 8400 + 1}; uint32_t slicer_history { 0 }; diff --git a/firmware/bootstrap/CMakeLists.txt b/firmware/bootstrap/CMakeLists.txt index 3e48bc428..7f837998b 100644 --- a/firmware/bootstrap/CMakeLists.txt +++ b/firmware/bootstrap/CMakeLists.txt @@ -1,212 +1,212 @@ -# -# Copyright (C) 2014 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. -# - -############################################################################## -# Build global options -# NOTE: Can be overridden externally. -# - -enable_language(C CXX ASM) - -project(bootstrap) - -# Compiler options here. -set(USE_OPT "-Os -falign-functions=16 -fno-math-errno --specs=nano.specs") - -# C specific options here (added to USE_OPT). -set(USE_COPT "-std=gnu99") - -# C++ specific options here (added to USE_OPT). -set(USE_CPPOPT "-std=c++11 -fno-rtti -fno-exceptions") - -# Enable this if you want the linker to remove unused code and data -set(USE_LINK_GC yes) - -# Linker extra options here. -set(USE_LDOPT) - -# Enable this if you want link time optimizations (LTO) -set(USE_LTO no) - -# If enabled, this option allows to compile the application in THUMB mode. -set(USE_THUMB yes) - -# Enable this if you want to see the full log while compiling. -set(USE_VERBOSE_COMPILE no) - -# -# Build global options -############################################################################## - -############################################################################## -# Architecture or project specific options -# - -# Enables the use of FPU on Cortex-M4 (no, softfp, hard). -set(USE_FPU no) - -# -# Architecture or project specific options -############################################################################## - -############################################################################## -# Project, sources and paths -# - -# Define linker script file here -set(LDSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/m4.ld) - -# C sources that can be compiled in ARM or THUMB mode depending on the global -# setting. -set(CSRC - bootstrap.c -) - -# C++ sources that can be compiled in ARM or THUMB mode depending on the global -# setting. -set(CPPSRC) - -# C sources to be compiled in ARM mode regardless of the global setting. -# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler -# option that results in lower performance and larger code size. -set(ACSRC) - -# C++ sources to be compiled in ARM mode regardless of the global setting. -# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler -# option that results in lower performance and larger code size. -set(ACPPSRC) - -# C sources to be compiled in THUMB mode regardless of the global setting. -# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler -# option that results in lower performance and larger code size. -set(TCSRC) - -# C sources to be compiled in THUMB mode regardless of the global setting. -# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler -# option that results in lower performance and larger code size. -set(TCPPSRC) - -# List ASM source files here -set(ASMSRC startup_ARMCM4.S) - -set(INCDIR - ${CHIBIOS}/os/ports/common/ARMCMx/CMSIS/include - ${CHIBIOS}/os/ports/common/ARMCMx - ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx - ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M4 -) - -# -# Project, sources and paths -############################################################################## - -############################################################################## -# Compiler settings -# - -set(MCU cortex-m4) - -# ARM-specific options here -set(AOPT) - -# THUMB-specific options here -set(TOPT "-mthumb -DTHUMB") - -# Define C warning options here -set(CWARN "-Wall -Wextra -Wstrict-prototypes") - -# Define C++ warning options here -set(CPPWARN "-Wall -Wextra") - -# -# Compiler settings -############################################################################## - -############################################################################## -# Start of default section -# - -# List all default C defines here, like -D_DEBUG=1 -# TODO: Switch -DCRT0_INIT_DATA depending on load from RAM or SPIFI? -# NOTE: _RANDOM_TCC to kill a GCC 4.9.3 error with std::max argument types -set(DDEFS -DLPC43XX -DLPC43XX_M4 -D__START=main -DGIT_REVISION=\"${GIT_REVISION}\") - -# List all default ASM defines here, like -D_DEBUG=1 -set(DADEFS) - -# List all default directories to look for include files here -set(DINCDIR) - -# List the default directory to look for the libraries here -set(DLIBDIR) - -# List all default libraries here -set(DLIBS) - -# -# End of default section -############################################################################## - -############################################################################## -# Start of user section -# - -# List all user C define here, like -D_DEBUG=1 -set(UDEFS) - -# Define ASM defines here -set(UADEFS) - -# List all user directories here -set(UINCDIR) - -# List the user directory to look for the libraries here -set(ULIBDIR) - -# List all user libraries here -set(ULIBS) - -# -# End of user defines -############################################################################## - -set(RULESPATH ${CHIBIOS}/os/ports/GCC/ARMCMx) -include(${RULESPATH}/rules.cmake) - -############################################################################## - -add_executable(${PROJECT_NAME}.elf ${CSRC} ${CPPSRC} ${ASMSRC}) -set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT}) -add_definitions(${DEFS}) -include_directories(. ${INCDIR}) -link_directories(${LLIBDIR}) -target_link_libraries(${PROJECT_NAME}.elf ${LIBS}) - -add_custom_command( - OUTPUT ${PROJECT_NAME}.bin - COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin - DEPENDS ${PROJECT_NAME}.elf -) - -add_custom_target( - bootstrap - DEPENDS ${PROJECT_NAME}.bin -) +# +# Copyright (C) 2014 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. +# + +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +enable_language(C CXX ASM) + +project(bootstrap) + +# Compiler options here. +set(USE_OPT "-Os -g -falign-functions=16 -fno-math-errno --specs=nano.specs") + +# C specific options here (added to USE_OPT). +set(USE_COPT "-std=gnu99") + +# C++ specific options here (added to USE_OPT). +set(USE_CPPOPT "-std=c++11 -fno-rtti -fno-exceptions") + +# Enable this if you want the linker to remove unused code and data +set(USE_LINK_GC yes) + +# Linker extra options here. +set(USE_LDOPT) + +# Enable this if you want link time optimizations (LTO) +set(USE_LTO no) + +# If enabled, this option allows to compile the application in THUMB mode. +set(USE_THUMB yes) + +# Enable this if you want to see the full log while compiling. +set(USE_VERBOSE_COMPILE no) + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Enables the use of FPU on Cortex-M4 (no, softfp, hard). +set(USE_FPU no) + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define linker script file here +set(LDSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/m4.ld) + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +set(CSRC + bootstrap.c +) + +# C++ sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +set(CPPSRC) + +# C sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +set(ACSRC) + +# C++ sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +set(ACPPSRC) + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +set(TCSRC) + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +set(TCPPSRC) + +# List ASM source files here +set(ASMSRC startup_ARMCM4.S) + +set(INCDIR + ${CHIBIOS}/os/ports/common/ARMCMx/CMSIS/include + ${CHIBIOS}/os/ports/common/ARMCMx + ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx + ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M4 +) + +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +set(MCU cortex-m4) + +# ARM-specific options here +set(AOPT) + +# THUMB-specific options here +set(TOPT "-mthumb -DTHUMB") + +# Define C warning options here +set(CWARN "-Wall -Wextra -Wstrict-prototypes") + +# Define C++ warning options here +set(CPPWARN "-Wall -Wextra") + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of default section +# + +# List all default C defines here, like -D_DEBUG=1 +# TODO: Switch -DCRT0_INIT_DATA depending on load from RAM or SPIFI? +# NOTE: _RANDOM_TCC to kill a GCC 4.9.3 error with std::max argument types +set(DDEFS -DLPC43XX -DLPC43XX_M4 -D__START=main -DGIT_REVISION=\"${GIT_REVISION}\") + +# List all default ASM defines here, like -D_DEBUG=1 +set(DADEFS) + +# List all default directories to look for include files here +set(DINCDIR) + +# List the default directory to look for the libraries here +set(DLIBDIR) + +# List all default libraries here +set(DLIBS) + +# +# End of default section +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +set(UDEFS) + +# Define ASM defines here +set(UADEFS) + +# List all user directories here +set(UINCDIR) + +# List the user directory to look for the libraries here +set(ULIBDIR) + +# List all user libraries here +set(ULIBS) + +# +# End of user defines +############################################################################## + +set(RULESPATH ${CHIBIOS}/os/ports/GCC/ARMCMx) +include(${RULESPATH}/rules.cmake) + +############################################################################## + +add_executable(${PROJECT_NAME}.elf ${CSRC} ${CPPSRC} ${ASMSRC}) +set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT}) +add_definitions(${DEFS}) +include_directories(. ${INCDIR}) +link_directories(${LLIBDIR}) +target_link_libraries(${PROJECT_NAME}.elf ${LIBS}) + +add_custom_command( + OUTPUT ${PROJECT_NAME}.bin + COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin + DEPENDS ${PROJECT_NAME}.elf +) + +add_custom_target( + bootstrap + DEPENDS ${PROJECT_NAME}.bin +) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index a0c1cab49..6d1ca045a 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -71,9 +71,11 @@ public: AFSKConfigure = 23, PWMRSSIConfigure = 24, OOKConfigure = 25, + RDSConfigure = 26, + AudioTXConfig = 27, - FIFOSignal = 26, - FIFOData = 27, + FIFOSignal = 28, + FIFOData = 29, MAX }; @@ -516,6 +518,18 @@ public: const uint16_t tone_count; }; +class RDSConfigureMessage : public Message { +public: + constexpr RDSConfigureMessage( + const uint32_t length + ) : Message { ID::RDSConfigure }, + length(length) + { + } + + const uint32_t length = 0; +}; + class RetuneMessage : public Message { public: constexpr RetuneMessage( @@ -528,6 +542,18 @@ public: const int64_t freq = 0; }; +class AudioTXConfigMessage : public Message { +public: + constexpr AudioTXConfigMessage( + const uint32_t bw + ) : Message { ID::AudioTXConfig }, + bw(bw) + { + } + + const uint32_t bw; +}; + class AFSKConfigureMessage : public Message { public: constexpr AFSKConfigureMessage( @@ -576,6 +602,7 @@ public: const uint32_t pause_symbols; }; +// TODO: use streaming buffer instead class FIFOSignalMessage : public Message { public: constexpr FIFOSignalMessage( @@ -583,7 +610,7 @@ public: { } - const char signaltype = 0; + char signaltype = 0; }; class FIFODataMessage : public Message { diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index be4e41a7e..668c805aa 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -36,7 +36,7 @@ using portapack::memory::map::backup_ram; namespace portapack { namespace persistent_memory { -constexpr rf::Frequency tuned_frequency_reset_value { 88000000 }; +constexpr rf::Frequency tuned_frequency_reset_value { 100000000 }; using ppb_range_t = range_t; constexpr ppb_range_t ppb_range { -99000, 99000 }; @@ -57,9 +57,11 @@ constexpr int32_t afsk_bw_reset_value { 15 }; /* struct must pack the same way on M4 and M0 cores. */ struct data_t { - // General config int64_t tuned_frequency; int32_t correction_ppb; + uint32_t touch_calibration_magic; + touch::Calibration touch_calibration; + // AFSK modem int32_t afsk_mark_freq; @@ -99,6 +101,20 @@ void set_correction_ppb(const ppb_t new_value) { portapack::clock_manager.set_reference_ppb(clipped_value); } +static constexpr uint32_t touch_calibration_magic = 0x074af82f; + +void set_touch_calibration(const touch::Calibration& new_value) { + data->touch_calibration = new_value; + data->touch_calibration_magic = touch_calibration_magic; +} + +const touch::Calibration& touch_calibration() { + if( data->touch_calibration_magic != touch_calibration_magic ) { + set_touch_calibration(touch::default_calibration()); + } + return data->touch_calibration; +} + int32_t afsk_mark_freq() { afsk_freq_range.reset_if_outside(data->afsk_mark_freq, afsk_mark_reset_value); return data->afsk_mark_freq; diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 30b6542c8..b8455fa03 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -25,6 +25,7 @@ #include #include "rf_path.hpp" +#include "touch.hpp" namespace portapack { namespace persistent_memory { @@ -37,6 +38,9 @@ void set_tuned_frequency(const rf::Frequency new_value); ppb_t correction_ppb(); void set_correction_ppb(const ppb_t new_value); +void set_touch_calibration(const touch::Calibration& new_value); +const touch::Calibration& touch_calibration(); + int32_t afsk_mark_freq(); void set_afsk_mark(const int32_t new_value); diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index ad8ddcaa5..fa1cfa4f3 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -75,7 +75,6 @@ constexpr image_tag_t image_tag_jammer { 'P', 'J', 'A', 'M' }; constexpr image_tag_t image_tag_audio_tx { 'P', 'A', 'T', 'X' }; constexpr image_tag_t image_tag_afsk { 'P', 'A', 'F', 'S' }; constexpr image_tag_t image_tag_epar { 'P', 'E', 'P', 'R' }; -constexpr image_tag_t image_tag_play_audio { 'P', 'P', 'A', 'U' }; constexpr image_tag_t image_tag_xylos { 'P', 'X', 'Y', 'L' }; constexpr image_tag_t image_tag_rds { 'P', 'R', 'D', 'S' }; constexpr image_tag_t image_tag_ook { 'P', 'O', 'O', 'K' }; diff --git a/firmware/baseband/thread_base.hpp b/firmware/common/thread_base.hpp similarity index 100% rename from firmware/baseband/thread_base.hpp rename to firmware/common/thread_base.hpp diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 72b374679..efa21b337 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ