From b15b78103938628fd01918c9cdf6012b73973688 Mon Sep 17 00:00:00 2001 From: dqs105 Date: Wed, 16 Sep 2020 19:27:56 +0800 Subject: [PATCH 1/4] Added options for enabling CLKOUT. - CLKOUT can be enabled in Radio settings and status bar. - Fixed a typo(I believe) in ui_navigation. --- firmware/application/apps/ui_settings.cpp | 9 ++++++ firmware/application/apps/ui_settings.hpp | 12 +++++-- firmware/application/clock_manager.cpp | 14 +++++++++ firmware/application/clock_manager.hpp | 2 ++ firmware/application/ui_navigation.cpp | 31 ++++++++++++++++--- firmware/application/ui_navigation.hpp | 3 +- .../common/portapack_persistent_memory.cpp | 15 +++++++++ .../common/portapack_persistent_memory.hpp | 3 ++ 8 files changed, 80 insertions(+), 9 deletions(-) diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 3f5708b3..3d919bbe 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -144,6 +144,7 @@ SetRadioView::SetRadioView( } add_children({ + &check_clkout, &labels_bias, &check_bias, &button_done, @@ -156,6 +157,14 @@ SetRadioView::SetRadioView( form_init(model); + check_clkout.set_value(portapack::persistent_memory::clkout_enabled()); + check_clkout.on_select = [this](Checkbox&, bool v) { + clock_manager.enable_clock_output(v); + portapack::persistent_memory::set_clkout_enabled(v); + StatusRefreshMessage message { }; + EventDispatcher::send_message(message); + }; + check_bias.set_value(portapack::get_antenna_bias()); check_bias.on_select = [this](Checkbox&, bool v) { portapack::set_antenna_bias(v); diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index 076ede03..4b9f99d4 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -147,8 +147,14 @@ private: }; Labels labels_correction { - { { 2 * 8, 4 * 16 }, "Frequency correction:", Color::light_grey() }, - { { 6 * 8, 5 * 16 }, "PPM", Color::light_grey() }, + { { 2 * 8, 3 * 16 }, "Frequency correction:", Color::light_grey() }, + { { 6 * 8, 4 * 16 }, "PPM", Color::light_grey() }, + }; + + Checkbox check_clkout { + { 28, (6 * 16 - 4) }, + 4, + "Enable 10MHz CLKOUT" }; Labels labels_bias { @@ -159,7 +165,7 @@ private: }; NumberField field_ppm { - { 2 * 8, 5 * 16 }, + { 2 * 8, 4 * 16 }, 3, { -50, 50 }, 1, diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index 088cf17f..ec08452b 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -463,3 +463,17 @@ void ClockManager::stop_audio_pll() { cgu::pll0audio::power_down(); while( cgu::pll0audio::is_locked() ); } + +void ClockManager::enable_clock_output(bool enable) { + if(enable) { + clock_generator.enable_output(clock_generator_output_clkout); + clock_generator.set_ms_frequency(clock_generator_output_clkout, 10000000, si5351_vco_f, 0); + } else { + clock_generator.disable_output(clock_generator_output_clkout); + } + + if(enable) + clock_generator.set_clock_control(clock_generator_output_clkout, si5351_clock_control_common[clock_generator_output_clkout].ms_src(get_reference_clock_generator_pll(reference.source)).clk_pdn(ClockControl::ClockPowerDown::Power_On)); + else + clock_generator.set_clock_control(clock_generator_output_clkout, ClockControl::power_off()); +} diff --git a/firmware/application/clock_manager.hpp b/firmware/application/clock_manager.hpp index 98af620a..0c88bab5 100644 --- a/firmware/application/clock_manager.hpp +++ b/firmware/application/clock_manager.hpp @@ -79,6 +79,8 @@ public: Reference get_reference() const; + void enable_clock_output(bool enable); + private: I2C& i2c0; si5351::Si5351& clock_generator; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index ca6a6334..57ffd403 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -113,7 +113,7 @@ SystemStatusView::SystemStatusView( &button_camera, &button_sleep, &button_bias_tee, - &image_clock_status, + &button_clock_status, &sd_card_status_view, }); @@ -168,6 +168,10 @@ SystemStatusView::SystemStatusView( DisplaySleepMessage message; EventDispatcher::send_message(message); }; + + button_clock_status.on_select = [this](ImageButton&) { + this->on_clk(); + }; } void SystemStatusView::refresh() { @@ -188,11 +192,16 @@ void SystemStatusView::refresh() { } if (portapack::clock_manager.get_reference().source == ClockManager::ReferenceSource::External) { - image_clock_status.set_bitmap(&bitmap_icon_clk_ext); - button_bias_tee.set_foreground(ui::Color::green()); + button_clock_status.set_bitmap(&bitmap_icon_clk_ext); +// button_bias_tee.set_foreground(ui::Color::green()); Typo? } else { - image_clock_status.set_bitmap(&bitmap_icon_clk_int); - button_bias_tee.set_foreground(ui::Color::light_grey()); + button_clock_status.set_bitmap(&bitmap_icon_clk_int); +// button_bias_tee.set_foreground(ui::Color::green()); + } + if(portapack::persistent_memory::clkout_enabled()) { + button_clock_status.set_foreground(ui::Color::green()); + } else { + button_clock_status.set_foreground(ui::Color::light_grey()); } set_dirty(); @@ -302,6 +311,18 @@ void SystemStatusView::on_camera() { } } +void SystemStatusView::on_clk() { + bool v = portapack::persistent_memory::clkout_enabled(); + if(v) { + v = false; + } else { + v = true; + } + portapack::clock_manager.enable_clock_output(v); + portapack::persistent_memory::set_clkout_enabled(v); + refresh(); +} + void SystemStatusView::on_title() { if(nav_.is_top()) nav_.push(); diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 7edf6a9d..1537ce4e 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -180,7 +180,7 @@ private: Color::dark_grey() }; - Image image_clock_status { + ImageButton button_clock_status { { 27 * 8, 0 * 16, 2 * 8, 1 * 16 }, &bitmap_icon_clk_int, Color::light_grey(), @@ -198,6 +198,7 @@ private: void on_camera(); void on_title(); void refresh(); + void on_clk(); MessageHandlerRegistration message_handler_refresh { Message::ID::StatusRefresh, diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 1ee81ffa..97b9e006 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -63,6 +63,10 @@ using modem_repeat_range_t = range_t; constexpr modem_repeat_range_t modem_repeat_range { 1, 99 }; constexpr int32_t modem_repeat_reset_value { 5 }; +using clkout_config_range_t = range_t; +constexpr clkout_config_range_t clkout_config_range { 0, 1 }; +constexpr uint32_t clkout_config_reset_value { 0 }; + /* struct must pack the same way on M4 and M0 cores. */ struct data_t { int64_t tuned_frequency; @@ -91,6 +95,8 @@ struct data_t { uint32_t pocsag_ignore_address; int32_t tone_mix; + + uint32_t clkout_config; // TODO: Add custom frequency output? }; static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region"); @@ -287,5 +293,14 @@ void set_pocsag_ignore_address(uint32_t address) { data->pocsag_ignore_address = address; } +bool clkout_enabled() { + clkout_config_range.reset_if_outside(data->clkout_config, clkout_config_reset_value); + return (bool)(data->clkout_config & 1); +} + +void set_clkout_enabled(bool enable) { + data->clkout_config = (uint32_t)enable; +} + } /* namespace persistent_memory */ } /* namespace portapack */ diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index be740edb..6422567a 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -93,6 +93,9 @@ void set_pocsag_last_address(uint32_t address); uint32_t pocsag_ignore_address(); void set_pocsag_ignore_address(uint32_t address); +bool clkout_enabled(); +void set_clkout_enabled(bool enable); + } /* namespace persistent_memory */ } /* namespace portapack */ From 66a841e079f268c2cfa8d47899d2a7e92b31cace Mon Sep 17 00:00:00 2001 From: dqs105 Date: Thu, 17 Sep 2020 12:47:34 +0800 Subject: [PATCH 2/4] combine clkout_config => ui_config --- firmware/common/portapack_persistent_memory.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 97b9e006..e7fcbba6 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -63,10 +63,6 @@ using modem_repeat_range_t = range_t; constexpr modem_repeat_range_t modem_repeat_range { 1, 99 }; constexpr int32_t modem_repeat_reset_value { 5 }; -using clkout_config_range_t = range_t; -constexpr clkout_config_range_t clkout_config_range { 0, 1 }; -constexpr uint32_t clkout_config_reset_value { 0 }; - /* struct must pack the same way on M4 and M0 cores. */ struct data_t { int64_t tuned_frequency; @@ -89,14 +85,12 @@ struct data_t { uint32_t playdead_sequence; // UI - uint32_t ui_config; + uint32_t ui_config; uint32_t pocsag_last_address; uint32_t pocsag_ignore_address; int32_t tone_mix; - - uint32_t clkout_config; // TODO: Add custom frequency output? }; static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region"); @@ -294,12 +288,11 @@ void set_pocsag_ignore_address(uint32_t address) { } bool clkout_enabled() { - clkout_config_range.reset_if_outside(data->clkout_config, clkout_config_reset_value); - return (bool)(data->clkout_config & 1); + return (data->ui_config & 0x08000000UL); } void set_clkout_enabled(bool enable) { - data->clkout_config = (uint32_t)enable; + data->ui_config = (data->ui_config & ~0x08000000UL) | (enable << 27); } } /* namespace persistent_memory */ From 699504a7033d9cc74cb2923fa56bdaf1041eb32d Mon Sep 17 00:00:00 2001 From: dqs105 Date: Wed, 14 Oct 2020 20:35:51 +0800 Subject: [PATCH 3/4] Removed trailing spaces. --- firmware/common/portapack_persistent_memory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index e7fcbba6..b25cc894 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -85,7 +85,7 @@ struct data_t { uint32_t playdead_sequence; // UI - uint32_t ui_config; + uint32_t ui_config; uint32_t pocsag_last_address; uint32_t pocsag_ignore_address; @@ -292,7 +292,7 @@ bool clkout_enabled() { } void set_clkout_enabled(bool enable) { - data->ui_config = (data->ui_config & ~0x08000000UL) | (enable << 27); + data->ui_config = (data->ui_config & ~0x08000000UL) | (enable << 27); } } /* namespace persistent_memory */ From 7ca322fed4ec123a20d5a5e68aa667de26d18a02 Mon Sep 17 00:00:00 2001 From: dqs105 Date: Sat, 24 Oct 2020 00:24:05 +0800 Subject: [PATCH 4/4] Added options for tuning CLKOUT freq. - Now we have variable CLKOUT. - CLKOUT can be set between 10kHz and 60MHz. (The output signal will become mostly sine shape when reaching 50MHz.) - Click on freq setting field to change tuning step. --- firmware/application/apps/ui_settings.cpp | 31 +++++++++++++++++++ firmware/application/apps/ui_settings.hpp | 25 +++++++++++++-- firmware/application/clock_manager.cpp | 7 ++++- .../common/portapack_persistent_memory.cpp | 19 ++++++++++++ .../common/portapack_persistent_memory.hpp | 2 ++ 5 files changed, 80 insertions(+), 4 deletions(-) diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 3d919bbe..c6ccb817 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -145,6 +145,9 @@ SetRadioView::SetRadioView( add_children({ &check_clkout, + &field_clkout_freq, + &labels_clkout_khz, + &value_freq_step, &labels_bias, &check_bias, &button_done, @@ -165,6 +168,31 @@ SetRadioView::SetRadioView( EventDispatcher::send_message(message); }; + field_clkout_freq.set_value(portapack::persistent_memory::clkout_freq()); + value_freq_step.set_style(&style_text); + + field_clkout_freq.on_select = [this](NumberField&) { + freq_step_khz++; + if(freq_step_khz > 3) { + freq_step_khz = 0; + } + switch(freq_step_khz) { + case 0: + value_freq_step.set(" |"); + break; + case 1: + value_freq_step.set(" | "); + break; + case 2: + value_freq_step.set(" | "); + break; + case 3: + value_freq_step.set("| "); + break; + } + field_clkout_freq.set_step(pow(10, freq_step_khz)); + }; + check_bias.set_value(portapack::get_antenna_bias()); check_bias.on_select = [this](Checkbox&, bool v) { portapack::set_antenna_bias(v); @@ -175,6 +203,8 @@ SetRadioView::SetRadioView( button_done.on_select = [this, &nav](Button&){ const auto model = this->form_collect(); portapack::persistent_memory::set_correction_ppb(model.ppm * 1000); + portapack::persistent_memory::set_clkout_freq(model.freq); + clock_manager.enable_clock_output(portapack::persistent_memory::clkout_enabled()); nav.pop(); }; } @@ -190,6 +220,7 @@ void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) { SetFrequencyCorrectionModel SetRadioView::form_collect() { return { .ppm = static_cast(field_ppm.value()), + .freq = static_cast(field_clkout_freq.value()), }; } diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index 4b9f99d4..c66ccd2b 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -114,6 +114,7 @@ private: struct SetFrequencyCorrectionModel { int8_t ppm; + uint32_t freq; }; class SetRadioView : public View { @@ -130,6 +131,7 @@ private: .background = Color::black(), .foreground = Color::light_grey(), }; + uint8_t freq_step_khz = 3; Text label_source { { 0, 1 * 16, 17 * 8, 16 }, @@ -152,9 +154,26 @@ private: }; Checkbox check_clkout { - { 28, (6 * 16 - 4) }, - 4, - "Enable 10MHz CLKOUT" + { 18, (6 * 16 - 4) }, + 13, + "Enable CLKOUT" + }; + + NumberField field_clkout_freq { + { 20 * 8, 6 * 16 }, + 5, + { 10, 60000 }, + 1000, + ' ' + }; + + Labels labels_clkout_khz { + { { 26 * 8, 6 * 16 }, "kHz", Color::light_grey() } + }; + + Text value_freq_step { + { 21 * 8, (7 * 16 ), 4 * 8, 16 }, + "| " }; Labels labels_bias { diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index ec08452b..93eecc13 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -21,6 +21,7 @@ #include "clock_manager.hpp" +#include "portapack_persistent_memory.hpp" #include "portapack_io.hpp" #include "hackrf_hal.hpp" @@ -467,7 +468,11 @@ void ClockManager::stop_audio_pll() { void ClockManager::enable_clock_output(bool enable) { if(enable) { clock_generator.enable_output(clock_generator_output_clkout); - clock_generator.set_ms_frequency(clock_generator_output_clkout, 10000000, si5351_vco_f, 0); + if(portapack::persistent_memory::clkout_freq() < 1000) { + clock_generator.set_ms_frequency(clock_generator_output_clkout, portapack::persistent_memory::clkout_freq() * 128000, si5351_vco_f, 7); + } else { + clock_generator.set_ms_frequency(clock_generator_output_clkout, portapack::persistent_memory::clkout_freq() * 1000, si5351_vco_f, 0); + } } else { clock_generator.disable_output(clock_generator_output_clkout); } diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index b25cc894..48486f1a 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -63,6 +63,10 @@ using modem_repeat_range_t = range_t; constexpr modem_repeat_range_t modem_repeat_range { 1, 99 }; constexpr int32_t modem_repeat_reset_value { 5 }; +using clkout_freq_range_t = range_t; +constexpr clkout_freq_range_t clkout_freq_range { 10, 60000 }; +constexpr uint32_t clkout_freq_reset_value { 10000 }; + /* struct must pack the same way on M4 and M0 cores. */ struct data_t { int64_t tuned_frequency; @@ -295,5 +299,20 @@ void set_clkout_enabled(bool enable) { data->ui_config = (data->ui_config & ~0x08000000UL) | (enable << 27); } +uint32_t clkout_freq() { + uint16_t freq = (data->ui_config & 0x000FFFF0) >> 4; + if(freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum) { + data->ui_config = (data->ui_config & ~0x000FFFF0) | clkout_freq_reset_value << 4; + return clkout_freq_reset_value; + } + else { + return freq; + } +} + +void set_clkout_freq(uint32_t freq) { + data->ui_config = (data->ui_config & ~0x000FFFF0) | (clkout_freq_range.clip(freq) << 4); +} + } /* namespace persistent_memory */ } /* namespace portapack */ diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 6422567a..c05489b0 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -95,6 +95,8 @@ void set_pocsag_ignore_address(uint32_t address); bool clkout_enabled(); void set_clkout_enabled(bool enable); +uint32_t clkout_freq(); +void set_clkout_freq(uint32_t freq); } /* namespace persistent_memory */ } /* namespace portapack */