From 62310ad9a980bb37fb52776528a30a38bb91e329 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Mon, 4 Sep 2023 17:46:07 +0200 Subject: [PATCH] Config mode (#1433) * Allow code to run without a token * Reverted submodule change by mistake * WIP force tcxo * Added check to hide if not an R9 * Fixed comments * Updated name * Fixed crashing on TCXO switching * Fixed the reboot issue * Updated boot order * Cleaned up comments * added new recovery mode * added IO * implemented cpld mode change * whitespace change * renamed config mode * inverted logic * removed r9 dependency * added disable external tcxo option to config mode * fixed CLKIN detection for r9 * integrated tcxo setting into clock selection Co-authored-by @jLynx --- firmware/application/CMakeLists.txt | 1 + firmware/application/apps/ui_settings.cpp | 5 + firmware/application/apps/ui_settings.hpp | 5 + firmware/application/clock_manager.cpp | 12 +- firmware/application/config_mode.cpp | 127 ++++++++++++++++++ firmware/application/config_mode.hpp | 37 +++++ firmware/application/main.cpp | 9 ++ firmware/application/portapack.cpp | 7 +- .../common/portapack_persistent_memory.cpp | 34 ++++- .../common/portapack_persistent_memory.hpp | 7 + 10 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 firmware/application/config_mode.cpp create mode 100644 firmware/application/config_mode.hpp diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 26d7acaf..e003acbf 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -316,6 +316,7 @@ set(CPPSRC # ui_replay_view.cpp # ui_script.cpp ui_sd_card_debug.cpp + config_mode.cpp ${CPLD_20150901_DATA_CPP} ${CPLD_20170522_DATA_CPP} ${HACKRF_CPLD_DATA_CPP} diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 56759acc..51cc3bb5 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -169,6 +169,8 @@ SetRadioView::SetRadioView( &button_save, &button_cancel}); + add_children({&disable_external_tcxo}); + SetFrequencyCorrectionModel model{ static_cast(pmem::correction_ppb() / 1000), 0}; @@ -221,10 +223,13 @@ SetRadioView::SetRadioView( send_system_refresh(); }; + disable_external_tcxo.set_value(pmem::config_disable_external_tcxo()); + button_save.on_select = [this, &nav](Button&) { const auto model = this->form_collect(); pmem::set_correction_ppb(model.ppm * 1000); pmem::set_clkout_freq(model.freq); + pmem::set_config_disable_external_tcxo(disable_external_tcxo.value()); clock_manager.enable_clock_output(pmem::clkout_enabled()); nav.pop(); }; diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index a9b7ddca..cad6f4dd 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -185,6 +185,11 @@ class SetRadioView : public View { 5, "Turn on bias voltage"}; + Checkbox disable_external_tcxo{ + {18, 14 * 16}, + 5, + "Disable external TCXO"}; + Button button_save{ {2 * 8, 16 * 16, 12 * 8, 32}, "Save"}; diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index 9f5c654b..32b92ce5 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -325,12 +325,18 @@ uint32_t ClockManager::measure_gp_clkin_frequency() { } bool ClockManager::loss_of_signal() { - return hackrf_r9 - ? clock_generator.plla_loss_of_signal() - : clock_generator.clkin_loss_of_signal(); + if (hackrf_r9) { + const auto frequency = measure_gp_clkin_frequency(); + return (frequency < 9850000) || (frequency > 10150000); + } else { + return clock_generator.clkin_loss_of_signal(); + } } ClockManager::ReferenceSource ClockManager::detect_reference_source() { + if (portapack::persistent_memory::config_disable_external_tcxo()) + return ReferenceSource::Xtal; + if (loss_of_signal()) { // No external reference. Turn on PortaPack reference (if present). portapack_tcxo_enable(); diff --git a/firmware/application/config_mode.cpp b/firmware/application/config_mode.cpp new file mode 100644 index 00000000..2d57176d --- /dev/null +++ b/firmware/application/config_mode.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2023 Bernd Herzog + * + * 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 "config_mode.hpp" +#include "core_control.hpp" +#include "hackrf_gpio.hpp" +#include "portapack_hal.hpp" + +void config_mode_blink_until_dfu(); + +void config_mode_set() { + portapack::persistent_memory::set_config_mode_storage(CONFIG_MODE_GUARD_VALUE); +} + +bool config_mode_should_enter() { + return portapack::persistent_memory::config_mode_storage() == CONFIG_MODE_GUARD_VALUE; +} + +void config_mode_clear() { + portapack::persistent_memory::set_config_mode_storage(CONFIG_MODE_NORMAL_VALUE); +} + +uint32_t blink_patterns[] = { + 0x00000000, // 0 Off + 0xFFFFFFFF, // 1 On + 0xF0F0F0F0, // 2 blink fast + 0x00FF00FF, // 3 blink slow + 0xFFF3FFF3 // 4 inverse blink slow +}; + +void config_mode_run() { + configure_pins_portapack(); + portapack::gpio_dfu.input(); + + config_mode_blink_until_dfu(); + + auto last_dfu_btn = portapack::gpio_dfu.read(); + portapack::persistent_memory::cache::init(); + + int32_t counter = 0; + int8_t blink_pattern_value = portapack::persistent_memory::config_cpld() + + (portapack::persistent_memory::config_disable_external_tcxo() ? 5 : 0); + + while (true) { + auto dfu_btn = portapack::gpio_dfu.read(); + auto dfu_clicked = last_dfu_btn == true && dfu_btn == false; + last_dfu_btn = dfu_btn; + + if (dfu_clicked) { + int8_t value = portapack::persistent_memory::config_cpld() + + (portapack::persistent_memory::config_disable_external_tcxo() ? 5 : 0); + + blink_pattern_value = value = (value + 1) % 10; + + portapack::persistent_memory::set_config_cpld(value % 5); + portapack::persistent_memory::set_config_disable_external_tcxo((value / 5) == 1); + + portapack::persistent_memory::cache::persist(); + } + + auto tx_blink_pattern = blink_patterns[blink_pattern_value % 5]; + auto rx_blink_pattern = blink_patterns[blink_pattern_value / 5]; + + auto tx_value = ((tx_blink_pattern >> ((counter >> 0) & 31)) & 0x1) == 0x1; + if (tx_value) { + hackrf::one::led_tx.on(); + } else { + hackrf::one::led_tx.off(); + } + + auto rx_value = ((rx_blink_pattern >> ((counter >> 0) & 31)) & 0x1) == 0x1; + if (rx_value) { + hackrf::one::led_rx.on(); + } else { + hackrf::one::led_rx.off(); + } + + chThdSleepMilliseconds(100); + counter++; + } +} + +void config_mode_blink_until_dfu() { + while (true) { + hackrf::one::led_tx.on(); + hackrf::one::led_rx.on(); + hackrf::one::led_usb.on(); + chThdSleepMilliseconds(10); + + hackrf::one::led_tx.off(); + hackrf::one::led_rx.off(); + hackrf::one::led_usb.off(); + chThdSleepMilliseconds(115); + + auto dfu_btn = portapack::gpio_dfu.read(); + if (dfu_btn) + break; + } + + while (true) { + chThdSleepMilliseconds(10); + + auto dfu_btn = portapack::gpio_dfu.read(); + if (!dfu_btn) + break; + } + + chThdSleepMilliseconds(10); +} \ No newline at end of file diff --git a/firmware/application/config_mode.hpp b/firmware/application/config_mode.hpp new file mode 100644 index 00000000..b3945ac5 --- /dev/null +++ b/firmware/application/config_mode.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 Bernd Herzog + * + * 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 __CONFIG_MODE_H__ +#define __CONFIG_MODE_H__ + +#include "ch.h" + +#include "portapack.hpp" +#include "portapack_shared_memory.hpp" +#include "portapack_persistent_memory.hpp" + +void config_mode_set(); +bool config_mode_should_enter(); +void config_mode_clear(); + +void config_mode_run(); + +#endif /* __CONFIG_MODE_H__ */ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 10322834..eaad76cb 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -115,6 +115,7 @@ Continuous (Fox-oring) #include "portapack.hpp" #include "portapack_shared_memory.hpp" +#include "config_mode.hpp" #include "message_queue.hpp" @@ -161,9 +162,17 @@ static void event_loop() { } int main(void) { + if (config_mode_should_enter()) { + config_mode_clear(); + config_mode_run(); + } + + config_mode_set(); + first_if.init(); /* To avoid initial short Ant_DC_Bias pulse ,we need quick set up GP01_RFF507X =1 */ if (portapack::init()) { portapack::display.init(); + config_mode_clear(); // sdcStart(&SDCD1, nullptr); // Commented out as now happens in portapack.cpp diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 0c1f961e..86c4c486 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -408,6 +408,10 @@ bool init() { portapack::io.init(); + /* Cache some configuration data from persistent memory. */ + persistent_memory::cache::init(); + chThdSleepMilliseconds(10); + clock_manager.init_clock_generator(); i2c0.stop(); @@ -467,9 +471,6 @@ bool init() { controls_init(); chThdSleepMilliseconds(10); - /* Cache some configuration data from persistent memory. */ - persistent_memory::cache::init(); - clock_manager.set_reference_ppb(persistent_memory::correction_ppb()); clock_manager.enable_if_clocks(); clock_manager.enable_codec_clocks(); diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 9ed3328b..98e1e83a 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -142,7 +142,7 @@ static_assert(sizeof(ui_config2_t) == sizeof(uint32_t)); struct misc_config_t { bool mute_audio : 1; bool disable_speaker : 1; - bool UNUSED_2 : 1; + bool config_disable_external_tcxo : 1; bool UNUSED_3 : 1; bool UNUSED_4 : 1; bool UNUSED_5 : 1; @@ -226,6 +226,9 @@ struct data_t { // Additional UI settings. ui_config2_t ui_config2; + // recovery mode magic value storage + uint32_t config_mode_storage; + constexpr data_t() : structure_version(data_structure_version_enum::VERSION_CURRENT), target_frequency(target_frequency_reset_value), @@ -273,7 +276,8 @@ struct data_t { UNUSED_8(0), headphone_volume_cb(-600), misc_config(), - ui_config2() { + ui_config2(), + config_mode_storage(CONFIG_MODE_NORMAL_VALUE) { } }; @@ -363,6 +367,7 @@ void defaults() { set_config_backlight_timer(backlight_config_t{}); set_config_splash(true); + set_config_disable_external_tcxo(false); set_encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL); set_config_speaker_disable(true); // Disable AK4951 speaker by default (in case of OpenSourceSDRLab H2) @@ -380,6 +385,10 @@ void defaults() { void init() { const auto switches_state = get_switches_state(); + + // ignore for valid check + auto config_mode_backup = config_mode_storage(); + set_config_mode_storage(CONFIG_MODE_NORMAL_VALUE); if (!(switches_state[(size_t)ui::KeyEvent::Left] && switches_state[(size_t)ui::KeyEvent::Right]) && backup_ram->is_valid()) { // Copy valid persistent data into cache. cached_backup_ram = *backup_ram; @@ -395,6 +404,7 @@ void init() { // Copy defaults into cache. defaults(); } + set_config_mode_storage(config_mode_backup); } void persist() { @@ -550,6 +560,10 @@ bool config_speaker_disable() { return data->misc_config.disable_speaker; } +bool config_disable_external_tcxo() { + return data->misc_config.config_disable_external_tcxo; +} + bool stealth_mode() { return data->ui_config.stealth_mode; } @@ -611,6 +625,10 @@ void set_config_speaker_disable(bool v) { data->misc_config.disable_speaker = v; } +void set_config_disable_external_tcxo(bool v) { + data->misc_config.config_disable_external_tcxo = v; +} + void set_stealth_mode(bool v) { data->ui_config.stealth_mode = v; } @@ -840,6 +858,16 @@ void set_encoder_dial_sensitivity(uint8_t v) { data->encoder_dial_sensitivity = v; } +// Recovery mode magic value storage +static data_t* data_direct_access = reinterpret_cast(memory::map::backup_ram.base()); + +uint32_t config_mode_storage() { + return data_direct_access->config_mode_storage; +} +void set_config_mode_storage(uint32_t v) { + data_direct_access->config_mode_storage = v; +} + // PMem to sdcard settings bool should_use_sdcard_for_pmem() { @@ -965,6 +993,8 @@ bool debug_dump() { // misc_config bits pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute())); pmem_dump_file.write_line("misc_config config_speaker_disable: " + to_string_dec_int(config_speaker_disable())); + pmem_dump_file.write_line("ui_config config_disable_external_tcxo: " + to_string_dec_uint(config_disable_external_tcxo())); + // receiver_model pmem_dump_file.write_line("\n[Receiver Model]"); pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(receiver_model.target_frequency())); diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 2bbf7751..c430533f 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -173,6 +173,7 @@ void set_stealth_mode(const bool v); uint8_t config_cpld(); void set_config_cpld(uint8_t i); +bool config_disable_external_tcxo(); bool config_splash(); bool config_converter(); bool config_updown_converter(); @@ -193,6 +194,7 @@ void set_gui_return_icon(bool v); void set_load_app_settings(bool v); void set_save_app_settings(bool v); void set_show_bigger_qr_code(bool v); +void set_config_disable_external_tcxo(bool v); void set_config_splash(bool v); bool config_converter(); bool config_updown_converter(); @@ -218,6 +220,11 @@ void set_disable_touchscreen(bool v); uint8_t config_encoder_dial_sensitivity(); void set_encoder_dial_sensitivity(uint8_t v); +#define CONFIG_MODE_GUARD_VALUE 2001 +#define CONFIG_MODE_NORMAL_VALUE 1999 +uint32_t config_mode_storage(); +void set_config_mode_storage(uint32_t v); + uint32_t pocsag_last_address(); void set_pocsag_last_address(uint32_t address);