diff --git a/.github/workflows/create_stable_release.yml b/.github/workflows/create_stable_release.yml index 53c6e45e..30a74fdd 100644 --- a/.github/workflows/create_stable_release.yml +++ b/.github/workflows/create_stable_release.yml @@ -51,7 +51,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: v1.5.1 + tag_name: ${{ steps.version.outputs.version }} release_name: Mayhem firmware ${{ steps.version.outputs.version }} body: | **Stable release - ${{ steps.version.outputs.version }}** diff --git a/.github/workflows/past_version.txt b/.github/workflows/past_version.txt index 76864c1c..53b5bbb1 100644 --- a/.github/workflows/past_version.txt +++ b/.github/workflows/past_version.txt @@ -1 +1 @@ -v1.5.0 \ No newline at end of file +v1.5.1 diff --git a/.github/workflows/version.txt b/.github/workflows/version.txt index c9b3c015..f1a2e631 100644 --- a/.github/workflows/version.txt +++ b/.github/workflows/version.txt @@ -1 +1 @@ -v1.5.1 \ No newline at end of file +v1.5.3 diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 02764e07..80fc9c56 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -154,6 +154,7 @@ set(CPPSRC ${COMMON}/ui_widget.cpp ${COMMON}/utility.cpp ${COMMON}/wm8731.cpp + app_settings.cpp audio.cpp baseband_api.cpp capture_thread.cpp diff --git a/firmware/application/app_settings.cpp b/firmware/application/app_settings.cpp new file mode 100644 index 00000000..df93a20b --- /dev/null +++ b/firmware/application/app_settings.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * Copyright (C) 2022 Arjan Onwezen + * + * 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 "app_settings.hpp" + +#include "file.hpp" +#include "portapack.hpp" +#include "portapack_persistent_memory.hpp" +#include +#include + +namespace std { + +int app_settings::load(std::string application, AppSettings* settings) { + + if (portapack::persistent_memory::load_app_settings()) { + file_path = folder+"/"+application+".ini"; + + auto error = settings_file.open(file_path); + if (!error.is_valid()) { + auto error = settings_file.read(file_content, std::min((int)settings_file.size(), MAX_FILE_CONTENT_SIZE)); + + settings->baseband_bandwidth=std::app_settings::read_long_long(file_content, "baseband_bandwidth="); + settings->channel_bandwidth=std::app_settings::read_long_long(file_content, "channel_bandwidth="); + settings->lna=std::app_settings::read_long_long(file_content, "lna="); + settings->modulation=std::app_settings::read_long_long(file_content, "modulation="); + settings->rx_amp=std::app_settings::read_long_long(file_content, "rx_amp="); + settings->rx_frequency=std::app_settings::read_long_long(file_content, "rx_frequency="); + settings->sampling_rate=std::app_settings::read_long_long(file_content, "sampling_rate="); + settings->vga=std::app_settings::read_long_long(file_content, "vga="); + settings->tx_amp=std::app_settings::read_long_long(file_content, "tx_amp="); + settings->tx_frequency=std::app_settings::read_long_long(file_content, "tx_frequency="); + settings->tx_gain=std::app_settings::read_long_long(file_content, "tx_gain="); + rc = SETTINGS_OK; + } + else rc = SETTINGS_UNABLE_TO_LOAD; + } + else rc = SETTINGS_DISABLED; + return(rc); +} + +int app_settings::save(std::string application, AppSettings* settings) { + + if (portapack::persistent_memory::save_app_settings()) { + file_path = folder+"/"+application+".ini"; + make_new_directory(folder); + + auto error = settings_file.create(file_path); + if (!error.is_valid()) { + // Save common setting + settings_file.write_line("baseband_bandwidth="+to_string_dec_uint(portapack::receiver_model.baseband_bandwidth())); + settings_file.write_line("channel_bandwidth="+to_string_dec_uint(portapack::transmitter_model.channel_bandwidth())); + settings_file.write_line("lna="+to_string_dec_uint(portapack::receiver_model.lna())); + settings_file.write_line("rx_amp="+to_string_dec_uint(portapack::receiver_model.rf_amp())); + settings_file.write_line("sampling_rate="+to_string_dec_uint(portapack::receiver_model.sampling_rate())); + settings_file.write_line("tx_amp="+to_string_dec_uint(portapack::transmitter_model.rf_amp())); + settings_file.write_line("tx_gain="+to_string_dec_uint(portapack::transmitter_model.tx_gain())); + settings_file.write_line("vga="+to_string_dec_uint(portapack::receiver_model.vga())); + // Save other settings from struct + settings_file.write_line("rx_frequency="+to_string_dec_uint(settings->rx_frequency)); + settings_file.write_line("tx_frequency="+to_string_dec_uint(settings->tx_frequency)); + + rc = SETTINGS_OK; + } + else rc = SETTINGS_UNABLE_TO_SAVE; + } + else rc = SETTINGS_DISABLED; + return(rc); +} + + +long long int app_settings::read_long_long(char* file_content, const char* setting_text) { + auto position = strstr(file_content, (char *)setting_text); + if (position) { + position += strlen((char *)setting_text); + setting_value = strtoll(position, nullptr, 10); + } + return(setting_value); +} + + +} /* namespace std */ diff --git a/firmware/application/app_settings.hpp b/firmware/application/app_settings.hpp new file mode 100644 index 00000000..9a877978 --- /dev/null +++ b/firmware/application/app_settings.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * Copyright (C) 2022 Arjan Onwezen + * + * 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 __APP_SETTINGS_H__ +#define __APP_SETTINGS_H__ + + +#include +#include +#include + +#include "file.hpp" +#include "string_format.hpp" + + +namespace std { +class app_settings { + + + +public: + +#define SETTINGS_OK 0 // settings found +#define SETTINGS_UNABLE_TO_LOAD -1 // settings (file) not found +#define SETTINGS_UNABLE_TO_SAVE -2 // unable to save settings +#define SETTINGS_DISABLED -3 // load/save settings disabled in settings + + + + struct AppSettings { + uint32_t baseband_bandwidth; + uint32_t channel_bandwidth; + uint8_t lna; + uint8_t modulation; + uint8_t rx_amp; + uint32_t rx_frequency; + uint32_t sampling_rate; + uint8_t tx_amp; + uint32_t tx_frequency; + uint8_t tx_gain; + uint8_t vga; + }; + + int load(std::string application, AppSettings* settings); + int save(std::string application, AppSettings* settings); + + +private: + +#define MAX_FILE_CONTENT_SIZE 1000 + + char file_content[MAX_FILE_CONTENT_SIZE] = {}; + std::string file_path = ""; + std::string folder = "SETTINGS"; + int rc = SETTINGS_OK; + File settings_file { }; + long long int setting_value {} ; + + long long int read_long_long(char* file_content, const char* setting_text); + + +}; // class app_settings +} // namespace std + + + +#endif/*__APP_SETTINGS_H__*/ diff --git a/firmware/application/apps/ais_app.cpp b/firmware/application/apps/ais_app.cpp index a5c25a55..1561fee2 100644 --- a/firmware/application/apps/ais_app.cpp +++ b/firmware/application/apps/ais_app.cpp @@ -335,24 +335,23 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } { &recent_entry_detail_view, }); + + // load app settings + auto rc = settings.load("rx_ais", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + target_frequency_ = app_settings.rx_frequency; + } + else target_frequency_ = initial_target_frequency; + recent_entry_detail_view.hidden(true); - target_frequency_ = initial_target_frequency; - - receiver_model.set_tuning_frequency(tuning_frequency()); - receiver_model.set_sampling_rate(sampling_rate); - receiver_model.set_baseband_bandwidth(baseband_bandwidth); - receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias. - -/* radio::enable({ // this can be removed, previous version,no DC-bias control. - tuning_frequency(), - sampling_rate, - baseband_bandwidth, - rf::Direction::Receive, - receiver_model.rf_amp(), - static_cast(receiver_model.lna()), - static_cast(receiver_model.vga()), - }); */ + receiver_model.set_tuning_frequency(tuning_frequency()); + receiver_model.set_sampling_rate(sampling_rate); + receiver_model.set_baseband_bandwidth(baseband_bandwidth); + receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias. options_channel.on_change = [this](size_t, OptionsField::value_t v) { this->on_frequency_changed(v); @@ -373,7 +372,11 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } { } AISAppView::~AISAppView() { -/* radio::disable(); */ + + // save app settings + app_settings.rx_frequency = target_frequency_; + settings.save("rx_ais", &app_settings); + receiver_model.disable(); // to switch off all, including DC bias. baseband::shutdown(); diff --git a/firmware/application/apps/ais_app.hpp b/firmware/application/apps/ais_app.hpp index c6a8a7d5..6d319ba0 100644 --- a/firmware/application/apps/ais_app.hpp +++ b/firmware/application/apps/ais_app.hpp @@ -33,7 +33,7 @@ #include "event_m0.hpp" #include "log_file.hpp" - +#include "app_settings.hpp" #include "ais_packet.hpp" #include "lpc43xx_cpp.hpp" @@ -173,6 +173,11 @@ private: static constexpr uint32_t sampling_rate = 2457600; static constexpr uint32_t baseband_bandwidth = 1750000; + + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + NavigationView& nav_; AISRecentEntries recent { }; diff --git a/firmware/application/apps/analog_audio_app.cpp b/firmware/application/apps/analog_audio_app.cpp index 6c4dec74..422633da 100644 --- a/firmware/application/apps/analog_audio_app.cpp +++ b/firmware/application/apps/analog_audio_app.cpp @@ -129,10 +129,19 @@ AnalogAudioView::AnalogAudioView( &waterfall }); + // load app settings + auto rc = settings.load("rx_audio", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + receiver_model.set_rf_amp(app_settings.rx_amp); + field_frequency.set_value(app_settings.rx_frequency); + } + else field_frequency.set_value(receiver_model.tuning_frequency()); + //Filename Datetime and Frequency record_view.set_filename_date_frequency(true); - field_frequency.set_value(receiver_model.tuning_frequency()); field_frequency.set_step(receiver_model.frequency_step()); field_frequency.on_change = [this](rf::Frequency f) { this->on_tuning_frequency_changed(f); @@ -160,6 +169,7 @@ AnalogAudioView::AnalogAudioView( const auto modulation = receiver_model.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)); }; @@ -183,7 +193,7 @@ AnalogAudioView::AnalogAudioView( audio::output::start(); update_modulation(static_cast(modulation)); - on_modulation_changed(static_cast(modulation)); + on_modulation_changed(static_cast(modulation)); } size_t AnalogAudioView::get_spec_bw_index() { @@ -210,6 +220,11 @@ void AnalogAudioView::set_spec_trigger(uint16_t trigger) { } AnalogAudioView::~AnalogAudioView() { + + // save app settings + app_settings.rx_frequency = field_frequency.value(); + settings.save("rx_audio", &app_settings); + // TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do // both? audio::output::stop(); @@ -397,9 +412,6 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { } } -/*void AnalogAudioView::squelched() { - if (exit_on_squelch) nav_.pop(); -}*/ void AnalogAudioView::handle_coded_squelch(const uint32_t value) { float diff, min_diff = value; diff --git a/firmware/application/apps/analog_audio_app.hpp b/firmware/application/apps/analog_audio_app.hpp index 04795e47..fd6f5bc1 100644 --- a/firmware/application/apps/analog_audio_app.hpp +++ b/firmware/application/apps/analog_audio_app.hpp @@ -29,7 +29,7 @@ #include "ui_spectrum.hpp" #include "ui_record_view.hpp" #include "ui_font_fixed_8x16.hpp" - +#include "app_settings.hpp" #include "tone_key.hpp" @@ -154,6 +154,10 @@ public: private: static constexpr ui::Dim header_height = 3 * 16; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }; const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 }; diff --git a/firmware/application/apps/analog_tv_app.cpp b/firmware/application/apps/analog_tv_app.cpp index b3710573..50a1cb20 100644 --- a/firmware/application/apps/analog_tv_app.cpp +++ b/firmware/application/apps/analog_tv_app.cpp @@ -57,7 +57,18 @@ AnalogTvView::AnalogTvView( &tv }); - field_frequency.set_value(receiver_model.tuning_frequency()); + + // load app settings + auto rc = settings.load("rx_tv", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + receiver_model.set_rf_amp(app_settings.rx_amp); + field_frequency.set_value(app_settings.rx_frequency); + } + else field_frequency.set_value(receiver_model.tuning_frequency()); + + field_frequency.set_step(receiver_model.frequency_step()); field_frequency.on_change = [this](rf::Frequency f) { this->on_tuning_frequency_changed(f); @@ -106,12 +117,15 @@ AnalogTvView::AnalogTvView( } AnalogTvView::~AnalogTvView() { + + // save app settings + app_settings.rx_frequency = field_frequency.value(); + settings.save("rx_tv", &app_settings); + // TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do // both? audio::output::stop(); - receiver_model.disable(); - baseband::shutdown(); } diff --git a/firmware/application/apps/analog_tv_app.hpp b/firmware/application/apps/analog_tv_app.hpp index 81ac8ea5..def1c940 100644 --- a/firmware/application/apps/analog_tv_app.hpp +++ b/firmware/application/apps/analog_tv_app.hpp @@ -29,7 +29,7 @@ #include "ui_receiver.hpp" #include "ui_tv.hpp" #include "ui_record_view.hpp" - +#include "app_settings.hpp" #include "ui_font_fixed_8x16.hpp" #include "tone_key.hpp" @@ -58,6 +58,10 @@ public: private: static constexpr ui::Dim header_height = 3 * 16; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + const Rect options_view_rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }; const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 }; diff --git a/firmware/application/apps/ert_app.cpp b/firmware/application/apps/ert_app.cpp index 91b3e5e1..5ab68fa9 100644 --- a/firmware/application/apps/ert_app.cpp +++ b/firmware/application/apps/ert_app.cpp @@ -105,6 +105,15 @@ ERTAppView::ERTAppView(NavigationView&) { &recent_entries_view, }); + // load app settings + auto rc = settings.load("rx_ert", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + } + + radio::enable({ initial_target_frequency, sampling_rate, @@ -122,6 +131,10 @@ ERTAppView::ERTAppView(NavigationView&) { } ERTAppView::~ERTAppView() { + + // save app settings + settings.save("rx_ert", &app_settings); + radio::disable(); baseband::shutdown(); diff --git a/firmware/application/apps/ert_app.hpp b/firmware/application/apps/ert_app.hpp index 19cf70d0..ea4e11c6 100644 --- a/firmware/application/apps/ert_app.hpp +++ b/firmware/application/apps/ert_app.hpp @@ -28,7 +28,7 @@ #include "ui_channel.hpp" #include "event_m0.hpp" - +#include "app_settings.hpp" #include "log_file.hpp" #include "ert_packet.hpp" @@ -131,6 +131,11 @@ private: ERTRecentEntries recent { }; std::unique_ptr logger { }; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + + const RecentEntriesColumns columns { { { "ID", 10 }, { "Tp", 2 }, diff --git a/firmware/application/apps/lge_app.cpp b/firmware/application/apps/lge_app.cpp index c1f4ea0f..ad3b6d0a 100644 --- a/firmware/application/apps/lge_app.cpp +++ b/firmware/application/apps/lge_app.cpp @@ -39,10 +39,14 @@ using namespace portapack; namespace ui { void LGEView::focus() { - options_trame.focus(); + options_frame.focus(); } LGEView::~LGEView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_lge", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -70,10 +74,10 @@ void LGEView::generate_frame_touche() { std::vector data { 0x46, 0x28, 0x01, 0x45, 0x27, 0x01, 0x44, 0x23 }; console.write("\n\x1B\x07Touche:\x1B\x10"); - generate_lge_frame(0x96, (field_joueur.value() << 8) | field_salle.value(), 0x0001, data); + generate_lge_frame(0x96, (field_player.value() << 8) | field_room.value(), 0x0001, data); } -void LGEView::generate_frame_pseudo() { +void LGEView::generate_frame_nickname() { // 0040.48s: // 30 02 1A 00 19 00 FF 00 02 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 // 04 01 B0 04 7F 1F 11 33 40 1F 22 01 07 00 00 01 07 00 00 63 05 00 00 99 A2 @@ -90,15 +94,15 @@ void LGEView::generate_frame_pseudo() { }; uint32_t c; - //data_header[2] = field_salle.value(); // ? - //data_footer[0] = field_salle.value(); // ? + //data_header[2] = field_room.value(); // ? + //data_footer[0] = field_room.value(); // ? data.insert(data.begin(), data_header.begin(), data_header.end()); - data.push_back(field_joueur.value()); + data.push_back(field_player.value()); c = 0; - for (auto &ch : pseudo) { + for (auto &ch : nickname) { data.push_back(ch); c++; } @@ -108,16 +112,16 @@ void LGEView::generate_frame_pseudo() { while (++c < 16) data.push_back(0x00); - data.push_back(field_equipe.value()); + data.push_back(field_team.value()); data.insert(data.end(), data_footer.begin(), data_footer.end()); - console.write("\n\x1B\x0ESet pseudo:\x1B\x10"); + console.write("\n\x1B\x0ESet nickname:\x1B\x10"); - generate_lge_frame(0x02, 0x001A, field_joueur.value(), data); + generate_lge_frame(0x02, 0x001A, field_player.value(), data); } -void LGEView::generate_frame_equipe() { +void LGEView::generate_frame_team() { // 0041.83s: // 3D 03 FF FF FF FF 02 03 01 52 4F 55 47 45 00 00 00 00 00 00 00 00 00 00 00 00 // 02 56 45 52 54 45 00 00 00 00 00 00 00 00 00 00 00 01 03 42 4C 45 55 45 00 00 @@ -129,10 +133,10 @@ void LGEView::generate_frame_equipe() { data.insert(data.begin(), data_header.begin(), data_header.end()); - data.push_back(field_equipe.value()); + data.push_back(field_team.value()); c = 0; - for (auto &ch : pseudo) { + for (auto &ch : nickname) { data.push_back(ch); c++; } @@ -140,14 +144,14 @@ void LGEView::generate_frame_equipe() { while (c++ < 16) data.push_back(0x00); - data.push_back(field_equipe.value() - 1); // Color ? + data.push_back(field_team.value() - 1); // Color ? - console.write("\n\x1B\x0ASet equipe:\x1B\x10"); + console.write("\n\x1B\x0ASet team:\x1B\x10"); generate_lge_frame(0x03, data); } -void LGEView::generate_frame_broadcast_pseudo() { +void LGEView::generate_frame_broadcast_nickname() { // 0043.86s: // 3D 04 FF FF FF FF 02 03 19 42 52 45 42 49 53 20 00 00 00 00 00 00 00 00 00 04 // 07 50 4F 4E 45 59 20 00 00 00 00 00 00 00 00 00 00 05 1B 41 42 42 59 20 00 00 @@ -159,10 +163,10 @@ void LGEView::generate_frame_broadcast_pseudo() { data.insert(data.begin(), data_header.begin(), data_header.end()); - data.push_back(field_joueur.value()); + data.push_back(field_player.value()); c = 0; - for (auto &ch : pseudo) { + for (auto &ch : nickname) { data.push_back(ch); c++; } @@ -172,9 +176,9 @@ void LGEView::generate_frame_broadcast_pseudo() { while (++c < 16) data.push_back(0x00); - data.push_back(field_equipe.value()); + data.push_back(field_team.value()); - console.write("\n\x1B\x09" "Broadcast pseudo:\x1B\x10"); + console.write("\n\x1B\x09" "Broadcast nickname:\x1B\x10"); generate_lge_frame(0x04, data); } @@ -184,14 +188,14 @@ void LGEView::generate_frame_start() { // 0A 05 FF FF FF FF 02 EC FF FF FF A3 35 std::vector data { 0x02, 0xEC, 0xFF, 0xFF, 0xFF }; - //data[0] = field_salle.value(); // ? + //data[0] = field_room.value(); // ? console.write("\n\x1B\x0DStart:\x1B\x10"); generate_lge_frame(0x05, data); } void LGEView::generate_frame_gameover() { - std::vector data { (uint8_t)field_salle.value() }; + std::vector data { (uint8_t)field_room.value() }; console.write("\n\x1B\x0CGameover:\x1B\x10"); generate_lge_frame(0x0D, data); @@ -203,7 +207,7 @@ void LGEView::generate_frame_collier() { // Custom // 0C 00 13 37 13 37 id flags channel playerid zapduty zaptime checksum CRC CRC // channel: field_channel - // playerid: field_joueur + // playerid: field_player // zapduty: field_power // zaptime: field_duration @@ -218,8 +222,8 @@ void LGEView::generate_frame_collier() { std::vector data { id, flags, - (uint8_t)field_salle.value(), - (uint8_t)field_joueur.value(), + (uint8_t)field_room.value(), + (uint8_t)field_player.value(), (uint8_t)field_power.value(), (uint8_t)(field_duration.value() * 10) }; @@ -285,11 +289,11 @@ LGEView::LGEView(NavigationView& nav) { add_children({ &labels, - &options_trame, - &field_salle, - &button_texte, - &field_equipe, - &field_joueur, + &options_frame, + &field_room, + &button_text, + &field_team, + &field_player, &field_id, &field_power, &field_duration, @@ -300,20 +304,29 @@ LGEView::LGEView(NavigationView& nav) { &tx_view }); - field_salle.set_value(1); - field_equipe.set_value(1); - field_joueur.set_value(1); + // load app settings + auto rc = settings.load("tx_lge", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + + field_room.set_value(1); + field_team.set_value(1); + field_player.set_value(1); field_id.set_value(1); field_power.set_value(1); field_duration.set_value(2); - button_texte.on_select = [this, &nav](Button&) { + button_text.on_select = [this, &nav](Button&) { text_prompt( nav, - pseudo, + nickname, 15, [this](std::string& buffer) { - button_texte.set_text(buffer); + button_text.set_text(buffer); }); }; @@ -326,15 +339,15 @@ LGEView::LGEView(NavigationView& nav) { tx_view.on_start = [this]() { if (tx_mode == IDLE) { - auto i = options_trame.selected_index_value(); + auto i = options_frame.selected_index_value(); if (i == 0) generate_frame_touche(); else if (i == 1) - generate_frame_pseudo(); + generate_frame_nickname(); else if (i == 2) - generate_frame_equipe(); + generate_frame_team(); else if (i == 3) - generate_frame_broadcast_pseudo(); + generate_frame_broadcast_nickname(); else if (i == 4) generate_frame_start(); else if (i == 5) diff --git a/firmware/application/apps/lge_app.hpp b/firmware/application/apps/lge_app.hpp index 99c5014d..75377b29 100644 --- a/firmware/application/apps/lge_app.hpp +++ b/firmware/application/apps/lge_app.hpp @@ -30,6 +30,7 @@ #include "message.hpp" #include "transmitter_model.hpp" #include "portapack.hpp" +#include "app_settings.hpp" namespace ui { @@ -48,15 +49,19 @@ private: SINGLE, ALL }; + + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; tx_modes tx_mode = IDLE; - RFM69 rfm69 { 5, 0x2DD4, true, true }; + RFM69 rfm69 { 5, 0x2DD4, true, true }; uint32_t frame_size { 0 }; uint32_t repeats { 0 }; uint32_t channel_index { 0 }; - std::string pseudo { "ABCDEF" }; + std::string nickname { "ABCDEF" }; rf::Frequency channels[3] = { 868067000, 868183000, 868295000 }; @@ -68,9 +73,9 @@ private: } void generate_lge_frame(const uint8_t command, const uint16_t address_a, const uint16_t address_b, std::vector& data); void generate_frame_touche(); - void generate_frame_pseudo(); - void generate_frame_equipe(); - void generate_frame_broadcast_pseudo(); + void generate_frame_nickname(); + void generate_frame_team(); + void generate_frame_broadcast_nickname(); void generate_frame_start(); void generate_frame_gameover(); void generate_frame_collier(); @@ -79,28 +84,28 @@ private: Labels labels { //{ { 7 * 8, 1 * 8 }, "NO FUN ALLOWED !", Color::red() }, - { { 1 * 8, 1 * 8 }, "Trame:", Color::light_grey() }, - { { 1 * 8, 3 * 8 }, "Salle:", Color::light_grey() }, - { { 14 * 8, 3 * 8 }, "Texte:", Color::light_grey() }, - { { 0 * 8, 5 * 8 }, "Equipe:", Color::light_grey() }, - { { 0 * 8, 7 * 8 }, "Joueur:", Color::light_grey() }, - { { 0 * 8, 10 * 8 }, "Collier:", Color::light_grey() }, + { { 1 * 8, 1 * 8 }, "Frame:", Color::light_grey() }, + { { 2 * 8, 3 * 8 }, "Room:", Color::light_grey() }, + { { 14 * 8, 3 * 8 }, "Text:", Color::light_grey() }, + { { 2 * 8, 5 * 8 }, "Team:", Color::light_grey() }, + { { 0 * 8, 7 * 8 }, "Player:", Color::light_grey() }, + { { 0 * 8, 10 * 8 }, "Vest:", Color::light_grey() }, { { 4 * 8, 12 * 8 }, "ID:", Color::light_grey() }, { { 3 * 8, 14 * 8 }, "Pow: /10", Color::light_grey() }, - { { 1 * 8, 16 * 8 }, "Duree: x100ms", Color::light_grey() } + { { 2 * 8, 16 * 8 }, "Time: x100ms", Color::light_grey() } }; - OptionsField options_trame { + OptionsField options_frame { { 7 * 8, 1 * 8 }, 13, { - { "Touche", 0 }, - { "Set pseudo", 1 }, - { "Set equipe", 2 }, - { "Brdcst pseudo", 3 }, + { "Key", 0 }, + { "Set nickname", 1 }, + { "Set team", 2 }, + { "Brdcst nick", 3 }, { "Start", 4 }, { "Game over", 5 }, - { "Set collier", 6 } + { "Set vest", 6 } } }; @@ -111,7 +116,7 @@ private: true }; - NumberField field_salle { + NumberField field_room { { 7 * 8, 3 * 8 }, 1, { 1, 2 }, @@ -119,12 +124,12 @@ private: '0' }; - Button button_texte { + Button button_text { { 14 * 8, 5 * 8, 16 * 8, 3 * 8 }, "ABCDEF" }; - NumberField field_equipe { + NumberField field_team { { 7 * 8, 5 * 8 }, 1, { 1, 6 }, @@ -132,7 +137,7 @@ private: '0' }; - NumberField field_joueur { + NumberField field_player { { 7 * 8, 7 * 8 }, 2, { 1, 50 }, diff --git a/firmware/application/apps/pocsag_app.cpp b/firmware/application/apps/pocsag_app.cpp index cb5cacfe..d1dcb6b4 100644 --- a/firmware/application/apps/pocsag_app.cpp +++ b/firmware/application/apps/pocsag_app.cpp @@ -77,11 +77,22 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) { &console }); + // load app settings + auto rc = settings.load("rx_pocsag", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + field_frequency.set_value(app_settings.rx_frequency); + } + else field_frequency.set_value(receiver_model.tuning_frequency()); + + receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio); + receiver_model.set_sampling_rate(3072000); receiver_model.set_baseband_bandwidth(1750000); receiver_model.enable(); - field_frequency.set_value(receiver_model.tuning_frequency()); field_frequency.set_step(receiver_model.frequency_step()); field_frequency.on_change = [this](rf::Frequency f) { update_freq(f); @@ -127,6 +138,11 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) { } POCSAGAppView::~POCSAGAppView() { + + // save app settings + app_settings.rx_frequency = field_frequency.value(); + settings.save("rx_pocsag", &app_settings); + audio::output::stop(); // Save ignored address diff --git a/firmware/application/apps/pocsag_app.hpp b/firmware/application/apps/pocsag_app.hpp index b917926c..8ea3c4b9 100644 --- a/firmware/application/apps/pocsag_app.hpp +++ b/firmware/application/apps/pocsag_app.hpp @@ -28,7 +28,7 @@ #include "ui_rssi.hpp" #include "log_file.hpp" - +#include "app_settings.hpp" #include "pocsag.hpp" #include "pocsag_packet.hpp" @@ -60,6 +60,10 @@ public: private: static constexpr uint32_t initial_target_frequency = 466175000; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + bool logging { true }; bool ignore { true }; uint32_t last_address = 0xFFFFFFFF; diff --git a/firmware/application/apps/replay_app.cpp b/firmware/application/apps/replay_app.cpp index 9147c46f..4313b8e7 100644 --- a/firmware/application/apps/replay_app.cpp +++ b/firmware/application/apps/replay_app.cpp @@ -201,6 +201,16 @@ ReplayAppView::ReplayAppView( tx_gain = 35;field_rfgain.set_value(tx_gain); // Initial default value (-12 dB's max ). field_rfamp.set_value(rf_amp ? 14 : 0); // Initial default value True. (TX RF amp on , +14dB's) + field_rfamp.on_change = [this](int32_t v) { // allow initial value change just after opened file. + rf_amp = (bool)v; + }; + field_rfamp.set_value(rf_amp ? 14 : 0); + + field_rfgain.on_change = [this](int32_t v) { // allow initial value change just after opened file. + tx_gain = v; + }; + field_rfgain.set_value(tx_gain); + baseband::run_image(portapack::spi_flash::image_tag_replay); add_children({ diff --git a/firmware/application/apps/soundboard_app.cpp b/firmware/application/apps/soundboard_app.cpp index 2c93822f..97e6ad70 100644 --- a/firmware/application/apps/soundboard_app.cpp +++ b/firmware/application/apps/soundboard_app.cpp @@ -240,6 +240,15 @@ SoundBoardView::SoundBoardView( &button_next_page, &tx_view }); + + // load app settings + auto rc = settings.load("tx_soundboard", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } refresh_list(); @@ -280,6 +289,10 @@ SoundBoardView::SoundBoardView( } SoundBoardView::~SoundBoardView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_soundboard", &app_settings); + stop(); transmitter_model.disable(); baseband::shutdown(); diff --git a/firmware/application/apps/soundboard_app.hpp b/firmware/application/apps/soundboard_app.hpp index ee9e1b12..a8afb73c 100644 --- a/firmware/application/apps/soundboard_app.hpp +++ b/firmware/application/apps/soundboard_app.hpp @@ -30,6 +30,7 @@ #include "lfsr_random.hpp" #include "io_wave.hpp" #include "tone_key.hpp" +#include "app_settings.hpp" namespace ui { @@ -49,6 +50,10 @@ public: private: NavigationView& nav_; + + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; enum tx_modes { NORMAL = 0, diff --git a/firmware/application/apps/tpms_app.cpp b/firmware/application/apps/tpms_app.cpp index 7858d7a2..69e137e9 100644 --- a/firmware/application/apps/tpms_app.cpp +++ b/firmware/application/apps/tpms_app.cpp @@ -151,6 +151,16 @@ TPMSAppView::TPMSAppView(NavigationView&) { &options_type, }); + // load app settings + auto rc = settings.load("rx_tpms", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + options_band.set_by_value(app_settings.rx_frequency); + } + else options_band.set_by_value(receiver_model.tuning_frequency()); + radio::enable({ tuning_frequency(), sampling_rate, @@ -184,6 +194,12 @@ TPMSAppView::TPMSAppView(NavigationView&) { } TPMSAppView::~TPMSAppView() { + + + // save app settings + app_settings.rx_frequency = target_frequency_; + settings.save("rx_tpms", &app_settings); + radio::disable(); baseband::shutdown(); diff --git a/firmware/application/apps/tpms_app.hpp b/firmware/application/apps/tpms_app.hpp index 2d9b670d..9544554f 100644 --- a/firmware/application/apps/tpms_app.hpp +++ b/firmware/application/apps/tpms_app.hpp @@ -27,7 +27,7 @@ #include "ui_receiver.hpp" #include "ui_rssi.hpp" #include "ui_channel.hpp" - +#include "app_settings.hpp" #include "event_m0.hpp" #include "log_file.hpp" @@ -110,6 +110,10 @@ private: static constexpr uint32_t sampling_rate = 2457600; static constexpr uint32_t baseband_bandwidth = 1750000; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + MessageHandlerRegistration message_handler_packet { Message::ID::TPMSPacket, [this](Message* const p) { diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index 1731061f..1ae332ee 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -309,8 +309,12 @@ void ADSBRxView::focus() { } ADSBRxView::~ADSBRxView() { - receiver_model.set_tuning_frequency(prevFreq); + // save app settings + settings.save("rx_adsb", &app_settings); + + //TODO: once all apps keep there own settin previous frequency logic can be removed + receiver_model.set_tuning_frequency(prevFreq); rtc_time::signal_tick_second -= signal_token_tick_second; receiver_model.disable(); baseband::shutdown(); @@ -458,6 +462,21 @@ ADSBRxView::ADSBRxView(NavigationView& nav) { &recent_entries_view }); + + // load app settings + auto rc = settings.load("rx_adsb", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + } + else + { + field_lna.set_value(40); + field_vga.set_value(40); + } + + recent_entries_view.set_parent_rect({ 0, 16, 240, 272 }); recent_entries_view.on_select = [this, &nav](const AircraftRecentEntry& entry) { detailed_entry_key = entry.key(); @@ -478,8 +497,6 @@ ADSBRxView::ADSBRxView(NavigationView& nav) { baseband::set_adsb(); receiver_model.set_tuning_frequency(1090000000); - field_lna.set_value(40); - field_vga.set_value(40); receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis); receiver_model.set_sampling_rate(2000000); receiver_model.set_baseband_bandwidth(2500000); diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index 879e9d8c..e882b8db 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -32,7 +32,7 @@ #include "log_file.hpp" #include "adsb.hpp" #include "message.hpp" - +#include "app_settings.hpp" #include "crc.hpp" using namespace adsb; @@ -372,6 +372,9 @@ private: std::unique_ptr logger { }; void on_frame(const ADSBFrameMessage * message); void on_tick_second(); + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; const RecentEntriesColumns columns { { #if false diff --git a/firmware/application/apps/ui_adsb_tx.cpp b/firmware/application/apps/ui_adsb_tx.cpp index 198d2295..918e744c 100644 --- a/firmware/application/apps/ui_adsb_tx.cpp +++ b/firmware/application/apps/ui_adsb_tx.cpp @@ -284,6 +284,11 @@ void ADSBTxView::focus() { } ADSBTxView::~ADSBTxView() { + + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_adsb", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -334,8 +339,16 @@ ADSBTxView::ADSBTxView( &view_squawk, &text_frame, &tx_view - }); - + }); + + // load app settings + auto rc = settings.load("tx_adsb", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + tx_view.on_edit_frequency = [this, &nav]() { auto new_view = nav.push(receiver_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { diff --git a/firmware/application/apps/ui_adsb_tx.hpp b/firmware/application/apps/ui_adsb_tx.hpp index 0cf07f19..8556f6e8 100644 --- a/firmware/application/apps/ui_adsb_tx.hpp +++ b/firmware/application/apps/ui_adsb_tx.hpp @@ -28,6 +28,7 @@ #include "ui_transmitter.hpp" #include "message.hpp" #include "transmitter_model.hpp" +#include "app_settings.hpp" #include "portapack.hpp" using namespace adsb; @@ -189,6 +190,10 @@ private: -1, -1 };*/ + + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; //tx_modes tx_mode = IDLE; NavigationView& nav_; diff --git a/firmware/application/apps/ui_afsk_rx.cpp b/firmware/application/apps/ui_afsk_rx.cpp index 4b8fc3e7..54792f57 100644 --- a/firmware/application/apps/ui_afsk_rx.cpp +++ b/firmware/application/apps/ui_afsk_rx.cpp @@ -66,6 +66,15 @@ AFSKRxView::AFSKRxView(NavigationView& nav) { &console }); + // load app settings + auto rc = settings.load("rx_afsk", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + } + + // DEBUG record_view.on_error = [&nav](std::string message) { nav.display_modal("Error", message); @@ -164,6 +173,11 @@ void AFSKRxView::on_data(uint32_t value, bool is_data) { } AFSKRxView::~AFSKRxView() { + + // save app settings + app_settings.rx_frequency = field_frequency.value(); + settings.save("rx_afsk", &app_settings); + audio::output::stop(); receiver_model.disable(); baseband::shutdown(); diff --git a/firmware/application/apps/ui_afsk_rx.hpp b/firmware/application/apps/ui_afsk_rx.hpp index 86f0f28f..dccf0e01 100644 --- a/firmware/application/apps/ui_afsk_rx.hpp +++ b/firmware/application/apps/ui_afsk_rx.hpp @@ -27,7 +27,7 @@ #include "ui_navigation.hpp" #include "ui_receiver.hpp" #include "ui_record_view.hpp" // DEBUG - +#include "app_settings.hpp" #include "log_file.hpp" #include "utility.hpp" @@ -57,6 +57,10 @@ public: private: void on_data(uint32_t value, bool is_data); + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + uint8_t console_color { 0 }; uint32_t prev_value { 0 }; std::string str_log { "" }; diff --git a/firmware/application/apps/ui_aprs_rx.cpp b/firmware/application/apps/ui_aprs_rx.cpp index 1bcfd273..c1f16893 100644 --- a/firmware/application/apps/ui_aprs_rx.cpp +++ b/firmware/application/apps/ui_aprs_rx.cpp @@ -98,6 +98,15 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect &console }); + // load app settings + auto rc = settings.load("rx_aprs", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + } + + // DEBUG record_view.on_error = [&nav](std::string message) { nav.display_modal("Error", message); @@ -211,6 +220,10 @@ void APRSRxView::on_show(){ } APRSRxView::~APRSRxView() { + + // save app settings + settings.save("rx_aprs", &app_settings); + audio::output::stop(); receiver_model.disable(); baseband::shutdown(); diff --git a/firmware/application/apps/ui_aprs_rx.hpp b/firmware/application/apps/ui_aprs_rx.hpp index 9ea29559..1a37df92 100644 --- a/firmware/application/apps/ui_aprs_rx.hpp +++ b/firmware/application/apps/ui_aprs_rx.hpp @@ -28,7 +28,7 @@ #include "ui_receiver.hpp" #include "ui_record_view.hpp" // DEBUG #include "ui_geomap.hpp" - +#include "app_settings.hpp" #include "recent_entries.hpp" #include "ui_tabview.hpp" @@ -131,6 +131,7 @@ private: GeoMapView* geomap_view { nullptr }; bool send_updates { false }; + Console console { { 0, 0 * 16, 240, 224 } }; @@ -192,6 +193,11 @@ private: void on_data(uint32_t value, bool is_data); bool reset_console = false; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + + uint8_t console_color { 0 }; std::string str_log { "" }; diff --git a/firmware/application/apps/ui_aprs_tx.cpp b/firmware/application/apps/ui_aprs_tx.cpp index 87ff6927..5d275931 100644 --- a/firmware/application/apps/ui_aprs_tx.cpp +++ b/firmware/application/apps/ui_aprs_tx.cpp @@ -43,6 +43,10 @@ void APRSTXView::focus() { } APRSTXView::~APRSTXView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_aprs", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -66,7 +70,7 @@ void APRSTXView::start_tx() { 1200, 2200, 1, - 10000, //transmitter_model.channel_bandwidth(), + 10000, //APRS uses fixed 10k bandwidth 8 ); } @@ -95,6 +99,15 @@ APRSTXView::APRSTXView(NavigationView& nav) { &tx_view }); + + // load app settings + auto rc = settings.load("tx_aprs", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + button_set.on_select = [this, &nav](Button&) { text_prompt( nav, diff --git a/firmware/application/apps/ui_aprs_tx.hpp b/firmware/application/apps/ui_aprs_tx.hpp index 97032107..16872b11 100644 --- a/firmware/application/apps/ui_aprs_tx.hpp +++ b/firmware/application/apps/ui_aprs_tx.hpp @@ -29,6 +29,7 @@ #include "message.hpp" #include "transmitter_model.hpp" +#include "app_settings.hpp" #include "portapack.hpp" namespace ui { @@ -40,17 +41,14 @@ public: void focus() override; - std::string title() const override { return "APRS TX (beta)"; }; + std::string title() const override { return "APRS TX"; }; private: - /*enum tx_modes { - IDLE = 0, - SINGLE, - SEQUENCE - }; - - tx_modes tx_mode = IDLE;*/ + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + std::string payload { "" }; void start_tx(); @@ -103,7 +101,7 @@ private: TransmitterView tx_view { 16 * 16, 5000, - 10 + 0 // disable setting bandwith, since APRS used fixed 10k bandwidth }; MessageHandlerRegistration message_handler_tx_progress { diff --git a/firmware/application/apps/ui_bht_tx.cpp b/firmware/application/apps/ui_bht_tx.cpp index 6021a240..b70f4d17 100644 --- a/firmware/application/apps/ui_bht_tx.cpp +++ b/firmware/application/apps/ui_bht_tx.cpp @@ -96,9 +96,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) { if (target_system == XYLOS) { if (done) { if (tx_mode == SINGLE) { - if (checkbox_cligno.value()) { + if (checkbox_flashing.value()) { // TODO: Thread ! - chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :( + chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :( view_xylos.flip_relays(); start_tx(); } else @@ -120,9 +120,9 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) { } else { view_EPAR.half = false; if (tx_mode == SINGLE) { - if (checkbox_cligno.value()) { + if (checkbox_flashing.value()) { // TODO: Thread ! - chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :( + chThdSleepMilliseconds(field_speed.value() * 1000); // Dirty :( view_EPAR.flip_relays(); start_tx(); } else @@ -140,6 +140,10 @@ void BHTView::on_tx_progress(const uint32_t progress, const bool done) { } BHTView::~BHTView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_bht", &app_settings); + transmitter_model.disable(); } @@ -150,13 +154,22 @@ BHTView::BHTView(NavigationView& nav) { &view_xylos, &view_EPAR, &checkbox_scan, - &checkbox_cligno, - &field_tempo, + &checkbox_flashing, + &field_speed, &progressbar, &tx_view }); - field_tempo.set_value(1); + // load app settings + auto rc = settings.load("tx_bht", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + + field_speed.set_value(1); tx_view.on_edit_frequency = [this, &nav]() { auto new_view = nav.push(receiver_model.tuning_frequency()); diff --git a/firmware/application/apps/ui_bht_tx.hpp b/firmware/application/apps/ui_bht_tx.hpp index 01e6b48c..17768e2b 100644 --- a/firmware/application/apps/ui_bht_tx.hpp +++ b/firmware/application/apps/ui_bht_tx.hpp @@ -32,6 +32,7 @@ #include "message.hpp" #include "transmitter_model.hpp" #include "encoders.hpp" +#include "app_settings.hpp" #include "portapack.hpp" namespace ui { @@ -50,11 +51,11 @@ public: private: Labels labels { { { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() }, - { { 4 * 8, 3 * 8 }, "Code ville:", Color::light_grey() }, - { { 7 * 8, 5 * 8 }, "Famille:", Color::light_grey() }, - { { 2 * 8, 7 * 8 + 2 }, "Sous-famille:", Color::light_grey() }, - { { 2 * 8, 11 * 8 }, "ID recepteur:", Color::light_grey() }, - { { 2 * 8, 14 * 8 }, "Relais:", Color::light_grey() } + { { 4 * 8, 3 * 8 }, "City code:", Color::light_grey() }, + { { 7 * 8, 5 * 8 }, "Family:", Color::light_grey() }, + { { 2 * 8, 7 * 8 + 2 }, "Subfamily:", Color::light_grey() }, + { { 2 * 8, 11 * 8 }, "Receiver ID:", Color::light_grey() }, + { { 2 * 8, 14 * 8 }, "Relay:", Color::light_grey() } }; NumberField field_header_a { @@ -98,8 +99,8 @@ private: Checkbox checkbox_wcsubfamily { { 20 * 8, 6 * 8 + 6 }, - 6, - "Toutes" + 3, + "All" }; NumberField field_receiver { @@ -111,8 +112,8 @@ private: }; Checkbox checkbox_wcid { { 20 * 8, 10 * 8 + 4 }, - 4, - "Tous" + 3, + "All" }; std::array relay_states { }; @@ -139,9 +140,9 @@ public: private: Labels labels { - { { 4 * 8, 1 * 8 }, "Code ville:", Color::light_grey() }, - { { 8 * 8, 3 * 8 }, "Groupe:", Color::light_grey() }, - { { 8 * 8, 7 * 8 }, "Relais:", Color::light_grey() } + { { 4 * 8, 1 * 8 }, "City code:", Color::light_grey() }, + { { 8 * 8, 3 * 8 }, "Group:", Color::light_grey() }, + { { 8 * 8, 7 * 8 }, "Relay:", Color::light_grey() } }; NumberField field_city { @@ -181,6 +182,10 @@ public: std::string title() const override { return "BHT Xy/EP TX"; }; private: + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + void on_tx_progress(const uint32_t progress, const bool done); void start_tx(); void stop_tx(); @@ -220,12 +225,12 @@ private: "Scan" }; - Checkbox checkbox_cligno { + Checkbox checkbox_flashing { { 16 * 8, 25 * 8 }, - 6, - "Cligno" + 8, + "Flashing" }; - NumberField field_tempo { + NumberField field_speed { { 26 * 8, 25 * 8 + 4 }, 2, { 1, 99 }, diff --git a/firmware/application/apps/ui_btle_rx.cpp b/firmware/application/apps/ui_btle_rx.cpp index d4b9afee..226f9dc1 100644 --- a/firmware/application/apps/ui_btle_rx.cpp +++ b/firmware/application/apps/ui_btle_rx.cpp @@ -60,6 +60,15 @@ BTLERxView::BTLERxView(NavigationView& nav) { &console }); + // load app settings + auto rc = settings.load("rx_btle", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + } + + // DEBUG record_view.on_error = [&nav](std::string message) { nav.display_modal("Error", message); @@ -152,6 +161,11 @@ void BTLERxView::on_data(uint32_t value, bool is_data) { } BTLERxView::~BTLERxView() { + + // save app settings + app_settings.rx_frequency = field_frequency.value(); + settings.save("rx_btle", &app_settings); + audio::output::stop(); receiver_model.disable(); baseband::shutdown(); diff --git a/firmware/application/apps/ui_btle_rx.hpp b/firmware/application/apps/ui_btle_rx.hpp index 9e331eef..91bf0710 100644 --- a/firmware/application/apps/ui_btle_rx.hpp +++ b/firmware/application/apps/ui_btle_rx.hpp @@ -27,6 +27,7 @@ #include "ui.hpp" #include "ui_navigation.hpp" #include "ui_receiver.hpp" +#include "app_settings.hpp" #include "ui_record_view.hpp" // DEBUG #include "utility.hpp" @@ -45,6 +46,11 @@ public: private: void on_data(uint32_t value, bool is_data); + + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + uint8_t console_color { 0 }; uint32_t prev_value { 0 }; std::string str_log { "" }; diff --git a/firmware/application/apps/ui_coasterp.cpp b/firmware/application/apps/ui_coasterp.cpp index cd918dda..446ad841 100644 --- a/firmware/application/apps/ui_coasterp.cpp +++ b/firmware/application/apps/ui_coasterp.cpp @@ -37,6 +37,10 @@ void CoasterPagerView::focus() { } CoasterPagerView::~CoasterPagerView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_coaster", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -119,6 +123,15 @@ CoasterPagerView::CoasterPagerView(NavigationView& nav) { &tx_view }); + // load app settings + auto rc = settings.load("tx_coaster", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + // Bytes to nibbles for (c = 0; c < 16; c++) sym_data.set_sym(c, (data_init[c >> 1] >> ((c & 1) ? 0 : 4)) & 0x0F); diff --git a/firmware/application/apps/ui_coasterp.hpp b/firmware/application/apps/ui_coasterp.hpp index 68963302..873d3abe 100644 --- a/firmware/application/apps/ui_coasterp.hpp +++ b/firmware/application/apps/ui_coasterp.hpp @@ -28,6 +28,7 @@ #include "message.hpp" #include "transmitter_model.hpp" +#include "app_settings.hpp" #include "portapack.hpp" namespace ui { @@ -50,6 +51,10 @@ private: tx_modes tx_mode = IDLE; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + void start_tx(); void generate_frame(); void on_tx_progress(const uint32_t progress, const bool done); diff --git a/firmware/application/apps/ui_debug.cpp b/firmware/application/apps/ui_debug.cpp index a1856e25..e9018c1c 100644 --- a/firmware/application/apps/ui_debug.cpp +++ b/firmware/application/apps/ui_debug.cpp @@ -31,6 +31,7 @@ #include "ui_sd_card_debug.hpp" #include "portapack.hpp" +#include "portapack_persistent_memory.hpp" using namespace portapack; #include "irq_controls.hpp" @@ -345,8 +346,11 @@ DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) { /* DebugMenuView *********************************************************/ DebugMenuView::DebugMenuView(NavigationView& nav) { + if( portapack::persistent_memory::show_gui_return_icon() ) + { + add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } ); + } add_items({ - //{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } }, { "Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push(); } }, //{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push(); } }, { "SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav](){ nav.push(); } }, diff --git a/firmware/application/apps/ui_encoders.cpp b/firmware/application/apps/ui_encoders.cpp index e15defd1..05c90a3f 100644 --- a/firmware/application/apps/ui_encoders.cpp +++ b/firmware/application/apps/ui_encoders.cpp @@ -203,6 +203,10 @@ void EncodersView::focus() { } EncodersView::~EncodersView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_ook", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -335,6 +339,15 @@ EncodersView::EncodersView( &tx_view }); + // load app settings + auto rc = settings.load("tx_ook", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + tx_view.on_edit_frequency = [this, &nav]() { auto new_view = nav.push(transmitter_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { diff --git a/firmware/application/apps/ui_encoders.hpp b/firmware/application/apps/ui_encoders.hpp index 7eef80d5..ac206f6e 100644 --- a/firmware/application/apps/ui_encoders.hpp +++ b/firmware/application/apps/ui_encoders.hpp @@ -26,6 +26,7 @@ #include "transmitter_model.hpp" #include "encoders.hpp" #include "de_bruijn.hpp" +#include "app_settings.hpp" using namespace encoders; @@ -169,6 +170,10 @@ private: SCAN }; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + tx_modes tx_mode = IDLE; uint8_t repeat_index { 0 }; uint8_t repeat_min { 0 }; diff --git a/firmware/application/apps/ui_keyfob.cpp b/firmware/application/apps/ui_keyfob.cpp index 6492cd6b..b5bfb145 100644 --- a/firmware/application/apps/ui_keyfob.cpp +++ b/firmware/application/apps/ui_keyfob.cpp @@ -136,6 +136,9 @@ void KeyfobView::focus() { } KeyfobView::~KeyfobView() { + // save app settings + settings.save("tx_keyfob", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -214,6 +217,13 @@ KeyfobView::KeyfobView( &tx_view }); + // load app settings + auto rc = settings.load("tx_keyfob", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + frame[0] = 0x55; update_symfields(); diff --git a/firmware/application/apps/ui_keyfob.hpp b/firmware/application/apps/ui_keyfob.hpp index 0c723340..3cc8419a 100644 --- a/firmware/application/apps/ui_keyfob.hpp +++ b/firmware/application/apps/ui_keyfob.hpp @@ -23,6 +23,7 @@ #include "ui.hpp" #include "ui_transmitter.hpp" #include "transmitter_model.hpp" +#include "app_settings.hpp" #include "encoders.hpp" using namespace encoders; @@ -36,11 +37,15 @@ public: void focus() override; - std::string title() const override { return "Key fob TX (beta)"; }; + std::string title() const override { return "Key fob TX"; }; private: NavigationView& nav_; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + // 1013210ns / bit static constexpr uint32_t subaru_samples_per_bit = (OOK_SAMPLERATE * 0.00101321); static constexpr uint32_t repeats = 4; diff --git a/firmware/application/apps/ui_lcr.cpp b/firmware/application/apps/ui_lcr.cpp index e664f82e..6f5b1489 100644 --- a/firmware/application/apps/ui_lcr.cpp +++ b/firmware/application/apps/ui_lcr.cpp @@ -39,6 +39,10 @@ void LCRView::focus() { } LCRView::~LCRView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_lcr", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -173,6 +177,15 @@ LCRView::LCRView(NavigationView& nav) { &tx_view }); + // load app settings + auto rc = settings.load("tx_lcr", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + options_scanlist.set_selected_index(0); const auto button_set_am_fn = [this, &nav](Button& button) { diff --git a/firmware/application/apps/ui_lcr.hpp b/firmware/application/apps/ui_lcr.hpp index 096a597a..bd5b4aac 100644 --- a/firmware/application/apps/ui_lcr.hpp +++ b/firmware/application/apps/ui_lcr.hpp @@ -27,6 +27,7 @@ #include "message.hpp" #include "transmitter_model.hpp" +#include "app_settings.hpp" namespace ui { @@ -81,6 +82,10 @@ private: SCAN }; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + tx_modes tx_mode = IDLE; uint8_t scan_count { 0 }, scan_index { 0 }; uint32_t scan_progress { 0 }; diff --git a/firmware/application/apps/ui_mictx.cpp b/firmware/application/apps/ui_mictx.cpp index bda0f278..68d98212 100644 --- a/firmware/application/apps/ui_mictx.cpp +++ b/firmware/application/apps/ui_mictx.cpp @@ -186,7 +186,7 @@ void MicTXView::rxaudio(bool is_on) { baseband::run_image(portapack::spi_flash::image_tag_mic_tx); audio::output::stop(); - audio::input::start(ak4951_alc_GUI_selected); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored) + audio::input::start(); // set up audio input = mic config of any audio coded AK4951/WM8731, (in WM8731 parameter will be ignored) portapack::pin_i2s0_rx_sda.mode(3); configure_baseband(); } @@ -212,7 +212,7 @@ MicTXView::MicTXView( baseband::run_image(portapack::spi_flash::image_tag_mic_tx); - if ( audio_codec_wm8731.detected() ) { + if (true ) { // Temporary , disabling ALC feature , (pending to solve -No Audio in Mic app ,in some H2/H2+ WM /QFP100 CPLS users- if ( audio_codec_wm8731.detected() ) { add_children({ &labels_WM8731, // we have audio codec WM8731, same MIC menu as original. &vumeter, @@ -285,7 +285,7 @@ MicTXView::MicTXView( options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) { ak4951_alc_GUI_selected = v; - audio::input::start(ak4951_alc_GUI_selected); + audio::input::start(); }; // options_ak4951_alc_mode.set_selected_index(0); @@ -341,23 +341,37 @@ MicTXView::MicTXView( enable_dsb = false; field_bw.set_value(transmitter_model.channel_bandwidth() / 1000); //if (rx_enabled) - rxaudio(rx_enabled); //Update now if we have RX audio on + rxaudio(rx_enabled); //Update now if we have RX audio on + options_tone_key.hidden(0); // we are in FM mode , we should have active the Key-tones & CTCSS option. + field_rxbw.hidden(0); // we are in FM mode, we need to allow the user set up of the RX NFM BW selection (8K5, 11K, 16K) break; case 1: enable_am = true; - rxaudio(rx_enabled); //Update now if we have RX audio on + rxaudio(rx_enabled); //Update now if we have RX audio on + options_tone_key.set_selected_index(0); // we are NOT in FM mode , we reset the possible previous key-tones &CTCSS selection. + set_dirty(); // Refresh display + options_tone_key.hidden(1); // we hide that Key-tones & CTCSS input selecction, (no meaning in AM/DSB/SSB). + field_rxbw.hidden(1); // we hide the NFM BW selection in other modes non_FM (no meaning in AM/DSB/SSB) + check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection. break; case 2: enable_usb = true; - rxaudio(rx_enabled); //Update now if we have RX audio on + rxaudio(rx_enabled); //Update now if we have RX audio on + check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now. + check_rogerbeep.hidden(1); // hide that roger beep selection. + set_dirty(); // Refresh display break; case 3: enable_lsb = true; - rxaudio(rx_enabled); //Update now if we have RX audio on + rxaudio(rx_enabled); //Update now if we have RX audio on + check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now. + check_rogerbeep.hidden(1); // hide that roger beep selection. + set_dirty(); // Refresh display break; case 4: enable_dsb = true; - rxaudio(rx_enabled); //Update now if we have RX audio on + rxaudio(rx_enabled); //Update now if we have RX audio on + check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection. break; } //configure_baseband(); @@ -525,7 +539,7 @@ MicTXView::MicTXView( set_tx(false); audio::set_rate(audio::Rate::Hz_24000); - audio::input::start(ak4951_alc_GUI_selected); // originally , audio::input::start(); (we added parameter) + audio::input::start(); // originally , audio::input::start(); (we added parameter) } MicTXView::~MicTXView() { diff --git a/firmware/application/apps/ui_morse.cpp b/firmware/application/apps/ui_morse.cpp index ebe44b6d..1c9468d9 100644 --- a/firmware/application/apps/ui_morse.cpp +++ b/firmware/application/apps/ui_morse.cpp @@ -97,6 +97,10 @@ void MorseView::focus() { } MorseView::~MorseView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_morse", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -203,6 +207,15 @@ MorseView::MorseView( &tx_view }); + // load app settings + auto rc = settings.load("tx_morse", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + // Default settings field_speed.set_value(15); // 15wps field_tone.set_value(700); // 700Hz FM tone diff --git a/firmware/application/apps/ui_morse.hpp b/firmware/application/apps/ui_morse.hpp index 5079fea8..90b60b49 100644 --- a/firmware/application/apps/ui_morse.hpp +++ b/firmware/application/apps/ui_morse.hpp @@ -27,7 +27,7 @@ #include "ui_widget.hpp" #include "ui_navigation.hpp" #include "ui_transmitter.hpp" - +#include "app_settings.hpp" #include "portapack.hpp" #include "message.hpp" #include "volume.hpp" @@ -67,6 +67,10 @@ private: std::string message { }; uint32_t time_units { 0 }; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + enum modulation_t { CW = 0, FM = 1 diff --git a/firmware/application/apps/ui_nrf_rx.cpp b/firmware/application/apps/ui_nrf_rx.cpp index 32982ae6..d5d916f8 100644 --- a/firmware/application/apps/ui_nrf_rx.cpp +++ b/firmware/application/apps/ui_nrf_rx.cpp @@ -60,6 +60,14 @@ NRFRxView::NRFRxView(NavigationView& nav) { &console }); + // load app settings + auto rc = settings.load("rx_nrf", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + } + // DEBUG record_view.on_error = [&nav](std::string message) { nav.display_modal("Error", message); @@ -157,6 +165,11 @@ void NRFRxView::on_data(uint32_t value, bool is_data) { } NRFRxView::~NRFRxView() { + + // save app settings + app_settings.rx_frequency = field_frequency.value(); + settings.save("rx_nrf", &app_settings); + audio::output::stop(); receiver_model.disable(); baseband::shutdown(); diff --git a/firmware/application/apps/ui_nrf_rx.hpp b/firmware/application/apps/ui_nrf_rx.hpp index 4f72b25b..18a6f814 100644 --- a/firmware/application/apps/ui_nrf_rx.hpp +++ b/firmware/application/apps/ui_nrf_rx.hpp @@ -27,6 +27,7 @@ #include "ui.hpp" #include "ui_navigation.hpp" #include "ui_receiver.hpp" +#include "app_settings.hpp" #include "ui_record_view.hpp" // DEBUG #include "utility.hpp" @@ -45,6 +46,10 @@ public: private: void on_data(uint32_t value, bool is_data); + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + uint8_t console_color { 0 }; uint32_t prev_value { 0 }; std::string str_log { "" }; diff --git a/firmware/application/apps/ui_pocsag_tx.cpp b/firmware/application/apps/ui_pocsag_tx.cpp index 56ced719..58de068e 100644 --- a/firmware/application/apps/ui_pocsag_tx.cpp +++ b/firmware/application/apps/ui_pocsag_tx.cpp @@ -38,6 +38,10 @@ void POCSAGTXView::focus() { } POCSAGTXView::~POCSAGTXView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_pocsag", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -141,6 +145,15 @@ POCSAGTXView::POCSAGTXView( &tx_view }); + // load app settings + auto rc = settings.load("tx_pocsag", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + options_bitrate.set_selected_index(1); // 1200bps options_type.set_selected_index(0); // Address only diff --git a/firmware/application/apps/ui_pocsag_tx.hpp b/firmware/application/apps/ui_pocsag_tx.hpp index 0dfbc30a..470ce0fe 100644 --- a/firmware/application/apps/ui_pocsag_tx.hpp +++ b/firmware/application/apps/ui_pocsag_tx.hpp @@ -31,6 +31,7 @@ #include "bch_code.hpp" #include "message.hpp" #include "transmitter_model.hpp" +#include "app_settings.hpp" #include "pocsag.hpp" using namespace pocsag; @@ -62,6 +63,10 @@ private: 5, 31, 21, 2 }; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + void on_set_text(NavigationView& nav); void on_tx_progress(const uint32_t progress, const bool done); bool start_tx(); diff --git a/firmware/application/apps/ui_rds.cpp b/firmware/application/apps/ui_rds.cpp index db9e2d2a..7e8f1da8 100644 --- a/firmware/application/apps/ui_rds.cpp +++ b/firmware/application/apps/ui_rds.cpp @@ -175,6 +175,10 @@ void RDSView::focus() { } RDSView::~RDSView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_rds", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -226,11 +230,17 @@ RDSView::RDSView( &view_radiotext, &view_datetime, &view_audio, - //&options_countrycode, - //&options_coverage, &tx_view, }); - + + // load app settings + auto rc = settings.load("tx_rds", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } check_TP.set_value(true); sym_pi_code.set_sym(0, 0xF); @@ -242,8 +252,6 @@ RDSView::RDSView( }; options_pty.set_selected_index(0); // None - //options_countrycode.set_selected_index(18); // Baguette du fromage - //options_coverage.set_selected_index(0); // Local tx_view.on_edit_frequency = [this, &nav]() { auto new_view = nav.push(receiver_model.tuning_frequency()); diff --git a/firmware/application/apps/ui_rds.hpp b/firmware/application/apps/ui_rds.hpp index 35d80ba4..bbffb1ed 100644 --- a/firmware/application/apps/ui_rds.hpp +++ b/firmware/application/apps/ui_rds.hpp @@ -24,7 +24,7 @@ #include "ui_transmitter.hpp" #include "ui_textentry.hpp" #include "ui_tabview.hpp" - +#include "app_settings.hpp" #include "rds.hpp" using namespace rds; @@ -150,6 +150,11 @@ private: NavigationView& nav_; RDS_flags rds_flags { }; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + + std::vector frame_psn { }; std::vector frame_radiotext { }; std::vector frame_datetime { }; diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 5b3cc4d3..b5e033b3 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -234,6 +234,7 @@ SetUIView::SetUIView(NavigationView& nav) { &checkbox_showsplash, &checkbox_showclock, &options_clockformat, + &checkbox_guireturnflag, &button_save, &button_cancel }); @@ -242,6 +243,7 @@ SetUIView::SetUIView(NavigationView& nav) { checkbox_speaker.set_value(persistent_memory::config_speaker()); checkbox_showsplash.set_value(persistent_memory::config_splash()); checkbox_showclock.set_value(!persistent_memory::hide_clock()); + checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon()); uint32_t backlight_timer = persistent_memory::config_backlight_timer(); if (backlight_timer) { @@ -257,12 +259,6 @@ SetUIView::SetUIView(NavigationView& nav) { options_clockformat.set_selected_index(0); } - //checkbox_speaker.on_select = [this](Checkbox&, bool v) { - // if (v) audio::output::speaker_mute(); //Just mute audio if speaker is disabled - // persistent_memory::set_config_speaker(v); //Store Speaker status - // StatusRefreshMessage message { }; //Refresh status bar with/out speaker - // EventDispatcher::send_message(message); - //}; button_save.on_select = [&nav, this](Button&) { if (checkbox_bloff.value()) @@ -284,6 +280,7 @@ SetUIView::SetUIView(NavigationView& nav) { persistent_memory::set_config_splash(checkbox_showsplash.value()); persistent_memory::set_clock_hidden(!checkbox_showclock.value()); + persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value()); persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value()); nav.pop(); }; @@ -296,6 +293,36 @@ void SetUIView::focus() { button_save.focus(); } + +// --------------------------------------------------------- +// Appl. Settings +// --------------------------------------------------------- +SetAppSettingsView::SetAppSettingsView(NavigationView& nav) { + add_children({ + &checkbox_load_app_settings, + &checkbox_save_app_settings, + &button_save, + &button_cancel + }); + + checkbox_load_app_settings.set_value(persistent_memory::load_app_settings()); + checkbox_save_app_settings.set_value(persistent_memory::save_app_settings()); + + + button_save.on_select = [&nav, this](Button&) { + persistent_memory::set_load_app_settings(checkbox_load_app_settings.value()); + persistent_memory::set_save_app_settings(checkbox_save_app_settings.value()); + nav.pop(); + }; + button_cancel.on_select = [&nav, this](Button&) { + nav.pop(); + }; +} + +void SetAppSettingsView::focus() { + button_save.focus(); +} + SetAudioView::SetAudioView(NavigationView& nav) { add_children({ &labels, @@ -344,14 +371,22 @@ void SetQRCodeView::focus() { button_save.focus(); } +// --------------------------------------------------------- +// Settings main menu +// --------------------------------------------------------- SettingsMenuView::SettingsMenuView(NavigationView& nav) { + if( portapack::persistent_memory::show_gui_return_icon() ) + { + add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } ); + } add_items({ { "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push(); } }, { "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push(); } }, - { "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push(); } }, + { "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push(); } }, { "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push(); } }, { "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push(); } }, - { "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push(); } } + { "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push(); } }, + { "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push(); } } }); set_max_rows(2); // allow wider buttons } diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index 68c1e750..d1f3cb63 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -271,6 +271,45 @@ private: { "time and date", 1 } } }; + + Checkbox checkbox_guireturnflag { + { 3 * 8, 14 * 16 }, + 25, + "add return icon in GUI" + }; + + Button button_save { + { 2 * 8, 16 * 16, 12 * 8, 32 }, + "Save" + }; + + Button button_cancel { + { 16 * 8, 16 * 16, 12 * 8, 32 }, + "Cancel", + }; +}; + +class SetAppSettingsView : public View { +public: + SetAppSettingsView(NavigationView& nav); + + void focus() override; + + std::string title() const override { return "App Settings"; }; + +private: + + Checkbox checkbox_load_app_settings { + { 3 * 8, 2 * 16 }, + 25, + "Load app settings" + }; + + Checkbox checkbox_save_app_settings { + { 3 * 8, 4 * 16 }, + 25, + "Save app settings" + }; Button button_save { { 2 * 8, 16 * 16, 12 * 8, 32 }, diff --git a/firmware/application/apps/ui_sonde.cpp b/firmware/application/apps/ui_sonde.cpp index f38fc3dd..5ddf157e 100644 --- a/firmware/application/apps/ui_sonde.cpp +++ b/firmware/application/apps/ui_sonde.cpp @@ -23,6 +23,7 @@ #include "ui_sonde.hpp" #include "baseband_api.hpp" #include "audio.hpp" +#include "app_settings.hpp" #include "portapack.hpp" #include @@ -43,6 +44,8 @@ namespace ui { SondeView::SondeView(NavigationView& nav) { + + baseband::run_image(portapack::spi_flash::image_tag_sonde); add_children({ @@ -68,8 +71,17 @@ SondeView::SondeView(NavigationView& nav) { &button_see_map }); - // start from the frequency currently stored in the receiver_model: - target_frequency_ = receiver_model.tuning_frequency(); + + // load app settings + auto rc = settings.load("rx_sonde", &app_settings); + if(rc == SETTINGS_OK) { + field_lna.set_value(app_settings.lna); + field_vga.set_value(app_settings.vga); + field_rf_amp.set_value(app_settings.rx_amp); + target_frequency_ = app_settings.rx_frequency; + } + else target_frequency_ = receiver_model.tuning_frequency(); + field_frequency.set_value(target_frequency_); field_frequency.set_step(500); //euquiq: was 10000, but we are using this for fine-tunning @@ -104,16 +116,6 @@ SondeView::SondeView(NavigationView& nav) { receiver_model.set_sampling_rate(sampling_rate); receiver_model.set_baseband_bandwidth(baseband_bandwidth); receiver_model.enable(); // Before using radio::enable(), but not updating Ant.DC-Bias. - - /* radio::enable({ // this can be removed, previous version, no DC-bias ant. control. - tuning_frequency(), - sampling_rate, - baseband_bandwidth, - rf::Direction::Receive, - receiver_model.rf_amp(), - static_cast(receiver_model.lna()), - static_cast(receiver_model.vga()), - }); */ // QR code with geo URI @@ -157,9 +159,13 @@ SondeView::SondeView(NavigationView& nav) { } SondeView::~SondeView() { + // save app settings + app_settings.rx_frequency = target_frequency_; + settings.save("rx_sonde", &app_settings); + baseband::set_pitch_rssi(0, false); -/* radio::disable(); */ - receiver_model.disable(); // to switch off all, including DC bias. + + receiver_model.disable(); // to switch off all, including DC bias. baseband::shutdown(); audio::output::stop(); } diff --git a/firmware/application/apps/ui_sonde.hpp b/firmware/application/apps/ui_sonde.hpp index b1fab391..3129c72b 100644 --- a/firmware/application/apps/ui_sonde.hpp +++ b/firmware/application/apps/ui_sonde.hpp @@ -34,7 +34,7 @@ #include "log_file.hpp" #include "sonde_packet.hpp" - +#include "app_settings.hpp" #include #include @@ -74,6 +74,9 @@ private: bool beep { false }; char geo_uri[32] = {}; + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; sonde::GPS_data gps_info { }; sonde::temp_humid temp_humid_info { }; diff --git a/firmware/application/apps/ui_sstvtx.cpp b/firmware/application/apps/ui_sstvtx.cpp index 4943315d..55e882d2 100644 --- a/firmware/application/apps/ui_sstvtx.cpp +++ b/firmware/application/apps/ui_sstvtx.cpp @@ -88,6 +88,10 @@ void SSTVTXView::paint(Painter&) { } SSTVTXView::~SSTVTXView() { + // save app settings + app_settings.tx_frequency = transmitter_model.tuning_frequency(); + settings.save("tx_sstv", &app_settings); + transmitter_model.disable(); baseband::shutdown(); } @@ -215,6 +219,15 @@ SSTVTXView::SSTVTXView( options_t mode_options; uint32_t c; + // load app settings + auto rc = settings.load("tx_sstv", &app_settings); + if(rc == SETTINGS_OK) { + transmitter_model.set_rf_amp(app_settings.tx_amp); + transmitter_model.set_channel_bandwidth(app_settings.channel_bandwidth); + transmitter_model.set_tuning_frequency(app_settings.tx_frequency); + transmitter_model.set_tx_gain(app_settings.tx_gain); + } + // Search for valid bitmaps file_list = scan_root_files(u"/sstv", u"*.bmp"); if (!file_list.size()) { diff --git a/firmware/application/apps/ui_sstvtx.hpp b/firmware/application/apps/ui_sstvtx.hpp index 8c320680..97f2cd68 100644 --- a/firmware/application/apps/ui_sstvtx.hpp +++ b/firmware/application/apps/ui_sstvtx.hpp @@ -34,6 +34,7 @@ #include "sstv.hpp" #include "file.hpp" #include "bmp.hpp" +#include "app_settings.hpp" using namespace sstv; @@ -58,7 +59,10 @@ private: NavigationView& nav_; sstv_scanline scanline_buffer { }; - + // app save settings + std::app_settings settings { }; + std::app_settings::AppSettings app_settings { }; + bool file_error { false }; File bmp_file { }; bmp_header_t bmp_header { }; diff --git a/firmware/application/audio.cpp b/firmware/application/audio.cpp index ce32076c..4ba23acc 100644 --- a/firmware/application/audio.cpp +++ b/firmware/application/audio.cpp @@ -168,8 +168,8 @@ void speaker_mute() { namespace input { -void start(int8_t alc_mode) { - audio_codec->microphone_enable(alc_mode); // added user-GUI selection for AK4951, ALC mode parameter. +void start() { + audio_codec->microphone_enable(); i2s::i2s0::rx_start(); } diff --git a/firmware/application/audio.hpp b/firmware/application/audio.hpp index 56301ee8..b02e42aa 100644 --- a/firmware/application/audio.hpp +++ b/firmware/application/audio.hpp @@ -49,7 +49,7 @@ public: virtual volume_range_t headphone_gain_range() const = 0; virtual void set_headphone_volume(const volume_t volume) = 0; - virtual void microphone_enable(int8_t alc_mode) = 0; // added user-GUI AK4951 ,selected ALC mode. + virtual void microphone_enable() = 0; virtual void microphone_disable() = 0; virtual size_t reg_count() const = 0; @@ -59,7 +59,7 @@ public: namespace output { -void start(); // this other start(),no changed. ,in namespace output , used to config audio playback mode, +void start(); void stop(); void mute(); @@ -72,7 +72,7 @@ void speaker_unmute(); namespace input { -void start(int8_t alc_mode); // added parameter user-GUI select AK4951-ALC mode for config mic path,(recording mode in datasheet), +void start(); void stop(); } /* namespace input */ diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 0157cd4f..5d51f175 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -403,6 +403,7 @@ bool init() { // if( !hackrf::cpld::load_sram() ) { // chSysHalt(); // } + chThdSleepMilliseconds(100); configure_pins_portapack(); @@ -412,6 +413,8 @@ bool init() { i2c0.stop(); + chThdSleepMilliseconds(10); + set_clock_config(clock_config_irc); cgu::pll1::disable(); @@ -452,9 +455,11 @@ bool init() { cgu::pll1::direct(); i2c0.start(i2c_config_fast_clock); + chThdSleepMilliseconds(10); touch::adc::init(); controls_init(); + chThdSleepMilliseconds(10); clock_manager.set_reference_ppb(persistent_memory::correction_ppb()); clock_manager.enable_first_if_clock(); @@ -465,10 +470,10 @@ bool init() { sdcStart(&SDCD1, nullptr); sd_card::poll_inserted(); - chThdSleepMilliseconds(1); + chThdSleepMilliseconds(10); if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) { - chThdSleepMilliseconds(1); + chThdSleepMilliseconds(10); // If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once. if (load_config() != 3){ shutdown_base(); @@ -480,11 +485,13 @@ bool init() { chSysHalt(); } - chThdSleepMilliseconds(1); // This delay seems to solve white noise audio issues + chThdSleepMilliseconds(10); // This delay seems to solve white noise audio issues LPC_CREG->DMAMUX = portapack::gpdma_mux; gpdma::controller.enable(); + chThdSleepMilliseconds(10); + audio::init(portapack_audio_codec()); diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index d7e35633..65641d75 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -465,8 +465,11 @@ void NavigationView::focus() { /* ReceiversMenuView *****************************************************/ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) { - add_items({ - //{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } }, + if( portapack::persistent_memory::show_gui_return_icon() ) + { + add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous , [&nav](){ nav.pop(); } } } ); + } + add_items( { { "ADS-B", ui::Color::green(), &bitmap_icon_adsb, [&nav](){ nav.push(); }, }, //{ "ACARS", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push(); }, }, { "AIS Boats", ui::Color::green(), &bitmap_icon_ais, [&nav](){ nav.push(); } }, @@ -486,16 +489,19 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) { { "LoRa", ui::Color::dark_grey(), &bitmap_icon_lora, [&nav](){ nav.push(); } }, { "SSTV", ui::Color::dark_grey(), &bitmap_icon_sstv, [&nav](){ nav.push(); } }, { "TETRA", ui::Color::dark_grey(), &bitmap_icon_tetra, [&nav](){ nav.push(); } },*/ - }); - - //set_highlighted(4); // Default selection is "Audio" + } ); + + //set_highlighted(0); // Default selection is "Audio" } /* TransmittersMenuView **************************************************/ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) { - add_items({ - //{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } }, + if( portapack::persistent_memory::show_gui_return_icon() ) + { + add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous , [&nav](){ nav.pop(); } } } ); + } + add_items({ { "ADS-B [S]", ui::Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push(); } }, { "APRS", ui::Color::green(), &bitmap_icon_aprs, [&nav](){ nav.push(); } }, { "BHT Xy/EP", ui::Color::green(), &bitmap_icon_bht, [&nav](){ nav.push(); } }, @@ -522,9 +528,12 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) { /* UtilitiesMenuView *****************************************************/ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) { + if( portapack::persistent_memory::show_gui_return_icon() ) + { + add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous , [&nav](){ nav.pop(); } } } ); + } add_items({ //{ "Test app", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push(); } }, - //{ "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } }, { "Freq. manager", ui::Color::green(), &bitmap_icon_freqman, [&nav](){ nav.push(); } }, { "File manager", ui::Color::yellow(), &bitmap_icon_dir, [&nav](){ nav.push(); } }, //{ "Notepad", ui::Color::dark_grey(), &bitmap_icon_notepad, [&nav](){ nav.push(); } }, @@ -532,7 +541,8 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) { //{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push(); } }, { "Wav viewer", ui::Color::yellow(), &bitmap_icon_soundboard, [&nav](){ nav.push(); } }, { "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push(); } }, - { "Wipe SD Card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push(); } }, + + { "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push(); } }, }); set_max_rows(2); // allow wider buttons } diff --git a/firmware/baseband/dsp_modulate.cpp b/firmware/baseband/dsp_modulate.cpp index 31dd3f85..04102800 100644 --- a/firmware/baseband/dsp_modulate.cpp +++ b/firmware/baseband/dsp_modulate.cpp @@ -21,6 +21,8 @@ #include "dsp_modulate.hpp" #include "sine_table_int8.hpp" +#include "portapack_shared_memory.hpp" +#include "tonesets.hpp" namespace dsp { namespace modulate { @@ -40,13 +42,42 @@ void Modulator::set_over(uint32_t new_over) { over = new_over; } +void Modulator::set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep ) { + audio_gain = new_audio_gain ; + play_beep = new_play_beep; + +} + +int32_t Modulator::apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message ) { + + if (play_beep) { // We need to add audio beep sample. + if (new_beep_timer) { + new_beep_timer--; + } else { + new_beep_timer = baseband_fs * 0.05; // 50ms + + if (new_beep_index == BEEP_TONES_NB) { + configured_in = false; + shared_memory.application_queue.push(new_txprogress_message); + } else { + beep_gen.configure(beep_deltas[new_beep_index], 1.0); // config sequentially the audio beep tone. + new_beep_index++; + } + } + sample_in = beep_gen.process(0); // Get sample of the selected sequence of 6 beep tones , and overwrite audio sample. Mix 0%. + } + return sample_in; // Return audio mic scaled with gain , 8 bit sample or audio beep sample. +} + + /// SSB::SSB() : hilbert() { mode = Mode::LSB; } -void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) { +void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer,TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) { + // No way to activate correctly the roger beep in this option, Maybe not enough M4 CPU power , Let's block roger beep in SSB selection by now . int32_t sample = 0; int8_t re = 0, im = 0; @@ -55,7 +86,9 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) { float i = 0.0, q = 0.0; sample = audio.p[counter / over] >> 2; - //switch (mode) { + sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation. + + //switch (mode) { //case Mode::LSB: hilbert.execute(sample / 32768.0f, i, q); //case Mode::USB: hilbert.execute(sample / 32768.0f, q, i); @@ -72,9 +105,23 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) { //re = q; //im = i; //break; + } buffer.p[counter] = { re, im }; + + // Update vu-meter bar in the LCD screen. + power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter + + if (new_power_acc_count) { + new_power_acc_count--; + } else { // power_acc_count = 0 + new_power_acc_count = new_divider; + new_level_message.value = power_acc / (new_divider *8); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter . + shared_memory.application_queue.push(new_level_message); + power_acc = 0; + } + } } @@ -88,15 +135,39 @@ void FM::set_fm_delta(uint32_t new_delta) { fm_delta = new_delta; } -void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) { +void FM::set_tone_gen_configure(const uint32_t set_delta, const float set_tone_mix_weight) { + tone_gen.configure(set_delta, set_tone_mix_weight); +} + +void FM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) { int32_t sample = 0; int8_t re, im; for (size_t counter = 0; counter < buffer.count; counter++) { - if (counter % over == 0) { - sample = audio.p[counter / over] >> 8; - delta = sample * fm_delta; - } + + sample = audio.p[counter>>6] >> 8; // sample = audio.p[counter / over] >> 8; (not enough efficient running code, over = 1536000/240000= 64 ) + sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation. + + if (play_beep) { + sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message ); // Apply beep -if selected - atom ,sample by sample. + } else { + // Update vu-meter bar in the LCD screen. + power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter + + if (new_power_acc_count) { + new_power_acc_count--; + } else { // power_acc_count = 0 + new_power_acc_count = new_divider; + new_level_message.value = power_acc / (new_divider / 4); // Why ? . This division is to adj vu-meter sentitivity, to match saturation point to red-muter . + shared_memory.application_queue.push(new_level_message); + power_acc = 0; + } + // TODO: pending to optimize CPU running code. + // So far , we can not handle all 3 issues at the same time (vu-meter , CTCSS, beep). + sample = tone_gen.process(sample); // Add selected Key_Tone or CTCSS subtone , atom function() , sample by sample. + } + + delta = sample * fm_delta; // Modulate FM phase += delta; sphase = phase >> 24; @@ -112,16 +183,33 @@ AM::AM() { mode = Mode::AM; } -void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) { +void AM::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) { int32_t sample = 0; int8_t re = 0, im = 0; - float q = 0.0; + float q = 0.0; for (size_t counter = 0; counter < buffer.count; counter++) { if (counter % 128 == 0) { sample = audio.p[counter / over] >> 2; + sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation. } + if (play_beep) { + sample = apply_beep(sample, configured_in, new_beep_index, new_beep_timer, new_txprogress_message )<<5; // Apply beep -if selected - atom sample by sample. + } else { + // Update vu-meter bar in the LCD screen. + power_acc += (sample < 0) ? -sample : sample; // Power average for UI vu-meter + + if (new_power_acc_count) { + new_power_acc_count--; + } else { // power_acc_count = 0 + new_power_acc_count = new_divider; + new_level_message.value = power_acc / (new_divider *8); // Why ?orig / (new_divider / 4); // Why ? + shared_memory.application_queue.push(new_level_message); + power_acc = 0; + } + } + q = sample / 32768.0f; q *= 256.0f; // Original 64.0f,now x4 (+12 dB's BB_modulation in AM & DSB) switch (mode) { diff --git a/firmware/baseband/dsp_modulate.hpp b/firmware/baseband/dsp_modulate.hpp index fdc6e95f..de964a68 100644 --- a/firmware/baseband/dsp_modulate.hpp +++ b/firmware/baseband/dsp_modulate.hpp @@ -24,6 +24,8 @@ #include "dsp_types.hpp" #include "dsp_hilbert.hpp" +#include "tone_gen.hpp" +#include "baseband_processor.hpp" namespace dsp { namespace modulate { @@ -41,13 +43,28 @@ enum class Mode { class Modulator { public: - virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer) = 0; + virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer,bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) = 0; virtual ~Modulator(); Mode get_mode(); void set_mode(Mode new_mode); void set_over(uint32_t new_over); + void set_gain_vumeter_beep(float new_audio_gain , bool new_play_beep ); + int32_t apply_beep(int32_t sample_in, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message ); + float audio_gain { }; + bool play_beep { false }; + uint32_t power_acc_count { 0 }; // this var it is initialized from Proc_mictx.cpp + uint32_t divider { }; // this var it is initialized from Proc_mictx.cpp + uint64_t power_acc { 0 }; // it is aux Accumulated sum (Absolute sample signal) , initialitzed to zero. + AudioLevelReportMessage level_message { }; + +private: + static constexpr size_t baseband_fs = 1536000U; + TXProgressMessage txprogress_message { }; + ToneGen beep_gen { }; + uint32_t beep_index { }, beep_timer { }; + protected: uint32_t over = 1; @@ -60,7 +77,7 @@ class SSB : public Modulator { public: SSB(); - virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer); + virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ); private: dsp::HilbertTransform hilbert; @@ -72,8 +89,9 @@ class FM : public Modulator { public: FM(); - virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer); + virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ) ; void set_fm_delta(uint32_t new_delta); + void set_tone_gen_configure(const uint32_t delta, const float tone_mix_weight); /// @@ -81,13 +99,16 @@ private: uint32_t fm_delta { 0 }; uint32_t phase { 0 }, sphase { 0 }; int32_t sample { 0 }, delta { }; + ToneGen tone_gen { }; + + }; class AM : public Modulator { public: AM(); - virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer); + virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider ); }; } /* namespace modulate */ diff --git a/firmware/baseband/proc_mictx.cpp b/firmware/baseband/proc_mictx.cpp index d5c0040c..6c9c9b97 100644 --- a/firmware/baseband/proc_mictx.cpp +++ b/firmware/baseband/proc_mictx.cpp @@ -35,8 +35,10 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){ if (!configured) return; audio_input.read_audio_buffer(audio_buffer); - modulator->execute(audio_buffer, buffer); - + modulator->set_gain_vumeter_beep(audio_gain, play_beep ) ; + modulator->execute(audio_buffer, buffer, configured, beep_index, beep_timer, txprogress_message, level_message, power_acc_count, divider ); // Now "Key Tones & CTCSS" baseband additon inside FM mod. dsp_modulate.cpp" + + /* Original fw 1.3.1 good reference, beep and vu-meter for (size_t i = 0; i < buffer.count; i++) { if (!play_beep) { @@ -67,13 +69,13 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){ beep_index++; } } - - sample = beep_gen.process(0); - } - - /* + sample = beep_gen.process(0); // TODO : Pending how to move inside modulate.cpp + } + */ + + /* Original fw 1.3.1 good reference FM moulation version, including "key tones CTCSS" fw 1.3.1 sample = tone_gen.process(sample); - + // FM if (configured) { delta = sample * fm_delta; @@ -89,8 +91,8 @@ void MicTXProcessor::execute(const buffer_c8_t& buffer){ } buffer.p[i] = { re, im }; - */ - } + + } */ } void MicTXProcessor::on_message(const Message* const msg) { @@ -100,12 +102,16 @@ void MicTXProcessor::on_message(const Message* const msg) { switch(msg->id) { case Message::ID::AudioTXConfig: if (fm_enabled) { - dsp::modulate::FM *fm = new dsp::modulate::FM(); - - fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs)); + dsp::modulate::FM *fm = new dsp::modulate::FM(); + + // Config fm_delta private var inside DSP modulate.cpp + fm->set_fm_delta(config_message.deviation_hz * (0xFFFFFFUL / baseband_fs)); + + // Config properly the private tone_gen function parameters inside DSP modulate.cpp + fm->set_tone_gen_configure(config_message.tone_key_delta, config_message.tone_key_mix_weight); modulator = fm; } - + if (usb_enabled) { modulator = new dsp::modulate::SSB(); modulator->set_mode(dsp::modulate::Mode::USB); @@ -124,7 +130,7 @@ void MicTXProcessor::on_message(const Message* const msg) { modulator->set_mode(dsp::modulate::Mode::DSB); } - modulator->set_over(baseband_fs / 24000); + modulator->set_over(baseband_fs / 24000); // Keep no change. am_enabled = config_message.am_enabled; usb_enabled = config_message.usb_enabled; @@ -137,8 +143,9 @@ void MicTXProcessor::on_message(const Message* const msg) { audio_gain = config_message.audio_gain; divider = config_message.divider; power_acc_count = 0; - - tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight); + + // now this config moved, in the case Message::ID::AudioTXConfig , only FM case. + // tone_gen.configure(config_message.tone_key_delta, config_message.tone_key_mix_weight); txprogress_message.done = true; diff --git a/firmware/baseband/proc_mictx.hpp b/firmware/baseband/proc_mictx.hpp index b26cae38..175e53c7 100644 --- a/firmware/baseband/proc_mictx.hpp +++ b/firmware/baseband/proc_mictx.hpp @@ -49,8 +49,8 @@ private: }; AudioInput audio_input { }; - ToneGen tone_gen { }; - ToneGen beep_gen { }; + // ToneGen tone_gen { }; moved to dsp_modulate.cpp + // ToneGen beep_gen { }; moved to dsp_modulate.cpp dsp::modulate::Modulator *modulator = NULL ; bool am_enabled { false }; diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index bdc5c77f..134de527 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -103,27 +103,13 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) { } } -/* 3 types of Windowing time domain shapes declaration , but only used Hamming , shapes for FFT - GCC10 compile sintax error c/m (1/2), - The primary diff. between const and constexpr variables is that - the initialization of a const var can be deferred until run time. - A constexpr var. must be initialized at compile time. ... - A var. can be declared with constexpr , when it has a literal type and is initialized. - GCC compile sintax error c/m (2/2) - Static assert --> Tests a software assertion at compile time for debugging. - we keep the same safety compile protection , just changing slightly the sintax checking that the size of the called array is power of 2. - if the bool "constant expression" is TRUE (normal case) , the declaration has no effect. - if the bool "constant expression" is FALSE (abnormal array size) , it is aborted the compile with a msg error. - */ - - -template // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m +template static typename T::value_type spectrum_window_none(const T& s, const size_t i) { static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions. return s[i]; }; -template // Currently we are calling and using that Window shape. +template static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t i) { static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions. const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const @@ -131,7 +117,7 @@ static typename T::value_type spectrum_window_hamming_3(const T& s, const size_t return s[i] * 0.54f + (s[(i-1) & mask] + s[(i+1) & mask]) * -0.23f; }; -template // Although currently we are not using that Windowing shape, we apply the same GCC10 compile error c/m +template static typename T::value_type spectrum_window_blackman_3(const T& s, const size_t i) { static_assert(power_of_two(ARRAY_ELEMENTS(s)), "Array number of elements must be power of 2"); // c/m compile error GCC10 , OK for all GCC versions. const size_t mask = s.size() - 1; // c/m compile error GCC10 , constexpr->const diff --git a/firmware/baseband/tone_gen.cpp b/firmware/baseband/tone_gen.cpp index dd74579d..d015f94f 100644 --- a/firmware/baseband/tone_gen.cpp +++ b/firmware/baseband/tone_gen.cpp @@ -24,14 +24,20 @@ #include "sine_table_int8.hpp" +/* int32_t ToneGen::tone_sine() { + // TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde + // Hoepfully we can manage without it , same as previous fw 1.3.1 int32_t tone_sample = sine_table_i8[tone_phase_] * 0x1000000; tone_phase_ += delta_; return tone_sample; } +*/ + int32_t ToneGen::tone_square() { + // TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde int32_t tone_sample = 0; if(tone_phase_ < (UINT32_MAX / 2)) { @@ -46,33 +52,66 @@ int32_t ToneGen::tone_square() { return tone_sample; } +/* void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) { + // Confirmed ! It is not working well in the fw 1.4.4 Mic App , CTCSS generation, (but added for Sonde App) + // I Think it should be deleted or modified but not use it as it is in Mic App . + delta_ = (uint8_t) ((delta & 0xFF000000U) >> 24); + delta_ = delta; tone_mix_weight_ = tone_mix_weight; input_mix_weight_ = 1.0 - tone_mix_weight; - current_tone_type_ = sine; } +*/ + + void ToneGen::configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate) { + // TODO : Added for Sonde App. We keep it by now to avoid compile errors, but it needs to be reviewed in Sonde delta_ = (uint8_t) ((freq * sizeof(sine_table_i8)) / sample_rate); tone_mix_weight_ = tone_mix_weight; input_mix_weight_ = 1.0 - tone_mix_weight; current_tone_type_ = tone_type; +} + + + + +// ----Original available core SW code from fw 1.3.1 , Working also well in Mic App CTCSS Gen from fw 1.4.0 onwards + +// Original direct-look-up synthesis algorithm with Fractional delta phase. It is OK +// Delta and Accumulator fase are stored in 32 bits (4 bytes), 1st top byte used as Modulo-256 Sine look-up table [index] +// the lower 3 bytes (24 bits) are used as a Fractional Detla and Accumulator phase, to have very finer Fstep control. + +void ToneGen::configure(const uint32_t delta, const float tone_mix_weight) { + delta_ = delta; + tone_mix_weight_ = tone_mix_weight; + input_mix_weight_ = 1.0 - tone_mix_weight; } int32_t ToneGen::process(const int32_t sample_in) { if (!delta_) return sample_in; - int32_t tone_sample = 0; - - if(current_tone_type_ == sine) { - tone_sample = tone_sine(); - } - else if(current_tone_type_ == square) { - tone_sample = tone_square(); - } + int32_t tone_sample = sine_table_i8[(tone_phase_ & 0xFF000000U) >> 24]; + tone_phase_ += delta_; + + return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_); +} +// ------------------------------------------------------------- + + + +int32_t ToneGen::process_square(const int32_t sample_in) { + // TODO : Added for Sonde App. We keep it by now , but it needs to be reviewed in Sonde + if (!delta_) + return sample_in; + + int32_t tone_sample = 0; + + tone_sample = tone_square(); + return (sample_in * input_mix_weight_) + (tone_sample * tone_mix_weight_); } diff --git a/firmware/baseband/tone_gen.hpp b/firmware/baseband/tone_gen.hpp index c1eee222..eca69e2f 100644 --- a/firmware/baseband/tone_gen.hpp +++ b/firmware/baseband/tone_gen.hpp @@ -28,7 +28,7 @@ class ToneGen { public: - enum tone_type { sine, square }; + enum tone_type { sine, square }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not. /*ToneGen(const size_t sample_rate ) : sample_rate_ { sample_rate } @@ -38,6 +38,7 @@ public: void configure(const uint32_t freq, const float tone_mix_weight, const tone_type tone_type, const uint32_t sample_rate); int32_t process(const int32_t sample_in); + int32_t process_square(const int32_t sample_in); private: tone_type current_tone_type_ { sine }; @@ -45,19 +46,23 @@ private: float input_mix_weight_ { 1 }; float tone_mix_weight_ { 0 }; - uint8_t delta_ { 0 }; - uint8_t tone_phase_ { 0 }; + uint32_t delta_ { 0 }; + uint32_t tone_phase_ { 0 }; + +// uint8_t delta_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not. +// uint8_t tone_phase_ { 0 }; // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not. /** * Generator function which selects every other sample from the reference sine waveform to the output sample: */ - int32_t tone_sine(); + int32_t tone_sine();// TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not. /** * Generator function for square waves: */ - int32_t tone_square(); + int32_t tone_square(); // TODO: Added for Radio Sonde.cpp PR 376, 381 , we need to check if keep or not. + }; #endif /* __TONE_GEN_H__ */ diff --git a/firmware/common/ak4951.cpp b/firmware/common/ak4951.cpp index 1f88a3d6..74301ecb 100644 --- a/firmware/common/ak4951.cpp +++ b/firmware/common/ak4951.cpp @@ -216,347 +216,90 @@ void AK4951::speaker_disable() { set_speaker_power(false); } -void AK4951::microphone_enable(int8_t alc_mode) { -// alc_mode =0 = (OFF =same as original code = NOT using AK4951 Programmable digital filter block), -// alc_mode >1 (with DIGITAL FILTER BLOCK , example : 1:(+12dB) , 2:(+9dB)", 3:(+6dB), ...) - -// map.r.digital_mic.DMIC = 0; // originally commented code -// update(Register::DigitalMic); // originally commented code - -uint_fast8_t mgain =0b0111; // Pre-amp mic (Original code, =0b0111 (+21dB's=7x3dBs),(Max is NOT 0b1111!, it is 0b1010=+30dBs=10x3dBs) - -map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 , our ext. MONO MIC is connected here LIN2 in Portapack. -map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 , Not used ,not connected ,but no problem. -map.r.signal_select_2.MICL = 0; // MPWR = 2.4V (it has two possible settings , 2.4V or 2.0V) , (majority smarthphones around 2V , range 1V-5V) -update(Register::SignalSelect2); - -// ------Common code part, = original setting conditions, it is fine for all user-GUI alc_modes: OFF , and ALC modes .*/ -map.r.digital_filter_select_1.HPFAD = 1; // HPF1 ON (after ADC);page 40 datasheet, HPFAD bit controls the ON/OFF of the HPF1 (HPF ON is recommended). -map.r.digital_filter_select_1.HPFC = 0b11; // HPF Cut off frequency of high pass filter from 236.8 Hz @fs=48k ("00":3.7Hz, "01":14,8Hz, "10":118,4Hz) -update(Register::DigitalFilterSelect1); - -// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB., (not used by now , original code cond.) -// update(Register::RchMicGainSetting); // (those two lines , not activated, same as original) - -// pre-load 4 byes LPF coefficicients (.lpf_coefficient_0,1,2,3), FSA 14..0, FSB 14..0 , (fcut initial 6kHz, fs 48Khz). -// it will be default pre-loading coeff. for al ALC modes, LPF bit is activated down, for all ALC digital modes. -map.r.lpf_coefficient_0.l = 0x5F; // Pre-loading here LPF 6kHz, 1st Order from digital Block , Fc=6000 Hz, fs = 48khz -map.r.lpf_coefficient_1.h = 0x09; // LPF bit is activated down, for all ALC digital modes. -map.r.lpf_coefficient_2.l = 0xBF; // Writting reg to AK4951, with "update", following instructions. -map.r.lpf_coefficient_3.h = 0x32; - -update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0 -update(Register::LPFCoefficient1); // In this case , LPF 6KHz , when we activate the LPF block. -update(Register::LPFCoefficient2); -update(Register::LPFCoefficient3); - -// Reset , setting OFF all 5 x Digital Equalizer filters -map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled -map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled -map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled -map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled -map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled -update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp - - - if (alc_mode==0) { // Programmable Digital Filter OFF, same as original condition., no Digital ALC, nor Wind Noise Filter, LPF , EQ - - map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain. - update(Register::DigitalFilterSelect2); - - // Pre-loading AUDIO PATH with all DIGITAL BLOCK by pased, see, audio path block diagramm AK4951 datasheet + Table Playback mode -Recording mode. - // Digital filter block PATH is BY PASSED (we can swith off DIG. BLOCK power , PMPFIL=0) .The Path in Recording Mode 2 & Playback Mode 2 (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback) - map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode) - map.r.digital_filter_mode.PFSDO = 0; // ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block . - map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin) - update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode. - - map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management - map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management - map.r.power_management_1.PMPFIL = 0; // Pre-loading , Programmable Dig. filter OFF ,filter unused, routed around.(original value = 0 ) - update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used ) - - // 1059/fs, 22ms @ 48kHz - chThdSleepMilliseconds(22); - - } else { // ( alc_mode !=0) - - switch(alc_mode) { // Pre-loading register values depending on user-GUI selection (they will be sended below, with "update(Register_name::xxx )". - - case 1: // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0xC0; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, C0H=+12dBs) - map.r.l_ch_input_volume_control.IV = 0xC0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xC0; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 2: // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0xB8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B8H= +9dBs) - map.r.l_ch_input_volume_control.IV = 0xB8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xB8; // Right Input Dig Vol Setting, same comment as above , The value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 3: // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0xB0; // 0xB8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, B0H= +6dBs) - map.r.l_ch_input_volume_control.IV = 0xB0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xB0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 4: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original) - // + EQ boosting ~<2kHz (f0:1,1k, fb:1,7K, k=1,8) && + LPF 3,5k - map.r.alc_mode_control_2.REF = 0xA8; // 0xA8 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs) - map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - //The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”. - map.r.digital_filter_select_3.EQ1 = 1; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled - update(Register::DigitalFilterSelect3); // A,B,C EQ1 Coefficients are already pre-loaded in ak4951.hpp - - map.r.lpf_coefficient_0.l = 0x0D; // Pre-loading here LPF 3,5k , 1st Order from digital Block , Fc=3.500 Hz, fs = 48khz - map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes. - map.r.lpf_coefficient_2.l = 0x1A; // Writting reg to AK4951 , down with update.... - map.r.lpf_coefficient_3.h = 0x2C; - // LPF bit is activated down, for all ALC digital modes. - break; - - case 5: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + Pre-amp Mic (+21dB=original) - // + EQ boosting ~<3kHz (f0~1k4,fb~2,4k,k=1,8) && LPF 4kHz - map.r.alc_mode_control_2.REF = 0xA8; // 0xA0 , REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A8H= +3dBs) - map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - map.r.digital_filter_select_3.EQ2 = 1; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled - update(Register::DigitalFilterSelect3); - - map.r.lpf_coefficient_0.l = 0xC3; // Pre-loading here LPF 4k , 1st Order from digital Block , Fc=4000 Hz, fs = 48khz - map.r.lpf_coefficient_1.h = 0x06; // LPF bit is activated down, for all ALC digital modes. - map.r.lpf_coefficient_2.l = 0x86; // Writting reg to AK4951 , down with update.... - map.r.lpf_coefficient_3.h = 0x2D; - // LPF bit is activated down, for all ALC digital modes. - break; - - case 6: // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0xA8; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs) - map.r.l_ch_input_volume_control.IV = 0xA8; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xA8; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 7: // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0xA0; // REF7-0 bits,max gain at ALC recoveryoperation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, A0H= 0dBs) - map.r.l_ch_input_volume_control.IV = 0xA0; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0xA0; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 8: // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0x98; //REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 98H=-03dBs) - map.r.l_ch_input_volume_control.IV = 0x98; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0x98; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s +void AK4951::microphone_enable() { +// map.r.digital_mic.DMIC = 0; +// update(Register::DigitalMic); - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; + const uint_fast8_t mgain = 0b0111; + map.r.signal_select_1.MGAIN20 = mgain & 7; + map.r.signal_select_1.PMMP = 1; + map.r.signal_select_1.MPSEL = 1; // MPWR2 pin + map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; + update(Register::SignalSelect1); - case 9: // ALC-> on, (-06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original) - map.r.alc_mode_control_2.REF = 0x90; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 90H=-06dBs) - map.r.l_ch_input_volume_control.IV = 0x90; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0x90; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s + map.r.signal_select_2.INL = 0b01; // Lch input signal = LIN2 + map.r.signal_select_2.INR = 0b01; // Rch input signal = RIN2 + map.r.signal_select_2.MICL = 0; // MPWR = 2.4V + update(Register::SignalSelect2); - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 10: // ALC-> on, (-09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -3dB (18dB's) - // Reduce also Pre-amp Mic -3dB's (+18dB's) - mgain = 0b0110; // Pre-amp mic Mic Gain Pre-amp (+18dB), Original=0b0111 (+21dB's =7x3dBs), - - map.r.alc_mode_control_2.REF = 0x88; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 88H=-09dBs) - map.r.l_ch_input_volume_control.IV = 0x88; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0x88; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - - case 11: // ALC-> on, (-12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz - Pre-amp MIC -6dB (15dB's) - // Reduce also Pre-amp Mic -6dB's (+15dB's) - mgain = 0b0101; // Pre-amp mic Mic Gain Pre-amp (+15dB), (Original=0b0111 (+21dB's= 7x3dBs), - - map.r.alc_mode_control_2.REF = 0x80; // REF7-0 bits,max gain at ALC recovery operation,(FFH +36dBs , D0H +18dBs, A0H 0dBs, 80H=-12dBs) - map.r.l_ch_input_volume_control.IV = 0x80; // Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - map.r.r_ch_input_volume_control.IV = 0x80; // Right Input Dig Vol Setting, same comment as above , Then value of IVOL should be <= than REF’s - - // Already Pre-loaded, "map.r.lpf_coefficient", 6Khz - LPF 1st Order from digital Block,Fc=6000Hz,fs = 48khz - // LPF bit is activated down, for all ALC digital modes. - break; - } - - //-------------------------------DIGITAL ALC (Automatic Level Control ) --- -------- - map.r.alc_mode_control_1.ALC = 0; // LMTH2-0, WTM1-0, RGAIN2-0, REF7-0, RFST1-0, EQFC1-0, FRATT, FRN and ALCEQN bits (needs to be set up with ALC disable = 0) - update(Register::ALCModeControl1); - - map.r.timer_select.FRN = 0; // (FRN= 0 Fast Recovery mode , enable ) - map.r.timer_select.FRATT = 0; // Fast Recovery Ref. Volume Atten. Amount -0,00106dB's, timing 4/fs (default) - map.r.timer_select.ADRST = 0b00; // initial offset ADC cycles , 22ms @fs=48Khz. +// map.r.r_ch_mic_gain_setting.MGR = 0x80; // Microphone sensitivity correction = 0dB. +// update(Register::RchMicGainSetting); +/* + map.r.timer_select.FRN = ?; + map.r.timer_select.FRATT = ?; + map.r.timer_select.ADRST = 0b??; update(Register::TimerSelect); - map.r.alc_timer_select.RFST = 0b00; // RFST1-0: ALC Fast Recovery Speed Default: “00” (0.0032dB) - map.r.alc_timer_select.WTM = 0b00; // ALC Recovery Operation Waiting Period 128/fs = 2,7 mseg (min=default) - map.r.alc_timer_select.EQFC = 0b10; // Selecting default, fs 48Khz , ALCEQ: First order zero pole high pass filter fc2=100Hz, fc1=150Hz - map.r.alc_timer_select.IVTM = 0; // IVTM bit set the vol transition time ,236/fs = 4,9msecs (min) (default was 19,7msegs.) + map.r.alc_timer_select. = ?; update(Register::ALCTimerSelect); - - map.r.alc_mode_control_1.LMTH10 = 0b11; // ALC Limiter Detec Level/ Recovery Counter Reset; lower 2 bits (Ob111=-8,4dbs), (default 0b000=-2,5dBs) - map.r.alc_mode_control_1.RGAIN = 0b000; // ALC Recovery Gain Step, max step , max speed. Default: “000” (0.00424dB) - map.r.alc_mode_control_1.ALC = 1; // ALC Enable . (we are now, NOT in MANUAL volume mode, only becomes manual when (ALC=“0” while ADCPF=“1”. ) - map.r.alc_mode_control_1.LMTH2 = 1; // ALC Limiter Detection Level/ Recovery Counter Reset Level,Upper bit,default 0b000 - map.r.alc_mode_control_1.ALCEQN = 1; // ALC EQ Off =1 not used by now, 0: ALC EQ On (default) + map.r.alc_mode_control_1. = ?; + map.r.alc_mode_control_1.ALC = 1; update(Register::ALCModeControl1); - // map.r.alc_mode_control_2.REF = 0x??; // Pre-loaded in top part. Maximum gain at ALC recovery operation,.(FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) + map.r.alc_mode_control_2.REF = ?; update(Register::ALCModeControl2); - - // map.r.l_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Left, Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - update(Register::LchInputVolumeControl); - - // map.r.r_ch_input_volume_control.IV = 0x??; // Pre-loaded in top part. Right,Input Digital Volume Setting, (FFH +36dBs , D0H +18dBs, A0H 0dBs, 70H=-18dBs) - update(Register::RchInputVolumeControl); - - - //---------------Switch ON, Digital Automatic Wind Noise Filter reduction ------------------- - // Difficult to realise that Dynamic HPF Wind noise filter benefit, maybe because we have another fixed HPF 236.8 Hz . - // Anyway , we propose to activate it , with default setting conditions. - map.r.power_management_1.PMPFIL = 0; // (*1) To programm SENC, STG , we need PMPFIL = 0 . (but this disconnect Digital block power supply. - update(Register::PowerManagement1); // Updated PMPFIL to 0 . (*1) - - map.r.auto_hpf_control.STG = 0b00; // (00=LOW ATTENUATION Level), lets put 11 (HIGH ATTENUATION Level) (default 00) - map.r.auto_hpf_control.SENC = 0b011; // (000=LOW sensitivity detection)… 111((MAX sensitivity detection) (default 011) - map.r.auto_hpf_control.AHPF = 1; // Autom. Wind noise filter ON (AHPF bit=“1”).It atten. wind noise when detecting ,and adjusts the atten. level dynamically. - update(Register::AutoHPFControl); - - // We are in Digital Block ON , (Wind Noise Filter+ALC+LPF+EQ),==> needs at the end , PMPFIL=1 , Program. Dig.filter ON - // map.r.power_management_1.PMPFIL = 1; // that instruction is at the end , we can skp pre-loading Programmable Dig. filter ON (*1) - //--------------------------------------------------------------------- - - // Writing AUDIO PATH diagramm, Changing Audio mode path : Playback mode1 /-Recording mode2. (Figure 37 AK4951 datasheet, Table 27. Recording Playback Mode) - // When changing those modes, PMPFIL bit must be “0”, it is OK (*1) - map.r.digital_filter_mode.ADCPF = 1; // ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode) - map.r.digital_filter_mode.PFSDO = 1; // ADC (+ 1st order HPF) Output - map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin) - update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode. - - // The EQn (n=1, 2, 3, 4 or 5) coefficient must be set when EQn bit = “0” or PMPFIL bit = “0”., but we are already (*1) - // map.r.power_management_1.PMPFIL = 0; // In the previous Wind Noise Filter , we already set up PPFIL = 0 - // update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used ) - - // ... Set EQ & LPF coefficients --------------------------------- - - // writting to the IC ak4951 reg. settings defined in Ak4951.hpp , the 30 bytes , EQ coefficient = 5 (EQ1,2,3,4,5) x 3 (A,B,C coefficients) x 2 bytes (16 bits) - update(Register::E1Coefficient0); // we could pre-load here,ex ,"map.r.e1_coefficient_0.l = 0x50;" , EQ1 Coefficient A : A7...A0, but already done in ak4951.hpp - update(Register::E1Coefficient1); // we could pre-load here,ex ,"map.r.e1_coefficient_1.h = 0xFE;" , EQ1 Coefficient A : A15..A8, " " - update(Register::E1Coefficient2); // we could pre-load here,ex ,"map.r.e1_coefficient_2.l = 0x29;" , EQ1 Coefficient B : B7...B0, " " - update(Register::E1Coefficient3); // we could pre-load here,ex ,"map.r.e1_coefficient_3.h = 0xC5;" , EQ1 Coefficient B : B15..B8, " " - update(Register::E1Coefficient4); // we could pre-load here,ex ,"map.r.e1_coefficient_4.l = 0xA0;" , EQ1 Coefficient C : C7...C0, " " - update(Register::E1Coefficient5); // we could pre-load here,ex ,"map.r.e1_coefficient_5.h = 0x1C;" , EQ1 Coefficient C : C15..C8, " " - - update(Register::E2Coefficient0); // writing pre-loaded EQ2 coefficcients - update(Register::E2Coefficient1); - update(Register::E2Coefficient2); - update(Register::E2Coefficient3); - update(Register::E2Coefficient4); - update(Register::E2Coefficient5); - - // Already pre-loaded LPF coefficients to 6k, 3,5k or 4k ,(LPF 6Khz all digital alc modes top , except when 3k5 , 4k) - update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0 - update(Register::LPFCoefficient1); - update(Register::LPFCoefficient2); - update(Register::LPFCoefficient3); - - // Activating LPF block , (and re-configuring the rest of bits of the same register) - map.r.digital_filter_select_2.HPF = 0; // HPF2-Block, Coeffic Setting Enable (OFF-Default), When HPF bit is “0”, audio data passes the HPF2 block by is 0dB gain. - map.r.digital_filter_select_2.LPF = 1; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain. - map.r.digital_filter_select_2.FIL3 = 0; // Stereo_Emphasis_Filter-Block,(OFF-Default) Coefficient Setting Enable , OFF , Disable. - map.r.digital_filter_select_2.EQ0 = 0; // Gain Compensation-Block, (OFF-Default) Coeffic Setting Enable, When EQ0 bit = “0” audio data passes the EQ0 block by 0dB gain. - map.r.digital_filter_select_2.GN = 0b00; // Gain Setting of the Gain Compensation Block Default: “00”-Default (0dB) +*/ +// map.r.l_ch_input_volume_control.IV = 0xe1; +// update(Register::LchInputVolumeControl); +// map.r.r_ch_input_volume_control.IV = 0xe1; +// update(Register::RchInputVolumeControl); +/* + map.r.auto_hpf_control.STG = 0b00; + map.r.auto_hpf_control.SENC = 0b011; + map.r.auto_hpf_control.AHPF = 0; + update(Register::AutoHPFControl); +*/ + map.r.digital_filter_select_1.HPFAD = 1; // HPF1 (after ADC) = on + map.r.digital_filter_select_1.HPFC = 0b11; // 2336.8 Hz @ fs=48k + update(Register::DigitalFilterSelect1); +/* + map.r.digital_filter_select_2.HPF = 0; + map.r.digital_filter_select_2.LPF = 0; + map.r.digital_filter_select_2.FIL3 = 0; + map.r.digital_filter_select_2.EQ0 = 0; + map.r.digital_filter_select_2.GN = 0b00; update(Register::DigitalFilterSelect2); - // Acitivating digital block , power supply - map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal. Mic Amp Lch and ADC Lch Power Management - map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management - map.r.power_management_1.PMPFIL = 1; // Pre-loaded in top part. Orig value=0, Programmable Digital filter unused (not power up), routed around. - update(Register::PowerManagement1); // Activating the Power management of the used blocks . (Mic ADC always + Dig Block filter , when used ) + map.r.digital_filter_select_3.EQ1 = 0; + map.r.digital_filter_select_3.EQ2 = 0; + map.r.digital_filter_select_3.EQ3 = 0; + map.r.digital_filter_select_3.EQ4 = 0; + map.r.digital_filter_select_3.EQ5 = 0; + update(Register::DigitalFilterSelect3); +*/ + map.r.digital_filter_mode.PFSDO = 0; // ADC (+ 1st order HPF) Output + map.r.digital_filter_mode.ADCPF = 1; // ADC Output (default) + update(Register::DigitalFilterMode); + + // ... Set coefficients ... + + map.r.power_management_1.PMADL = 1; // ADC Lch = Lch input signal + map.r.power_management_1.PMADR = 1; // ADC Rch = Rch input signal + map.r.power_management_1.PMPFIL = 0; // Programmable filter unused, routed around. + update(Register::PowerManagement1); // 1059/fs, 22ms @ 48kHz chThdSleepMilliseconds(22); - - } - - // Common part for all alc_mode , -------------------------- - // const uint_fast8_t mgain = 0b0111; // Already pre-loaded , in above switch case . - map.r.signal_select_1.MGAIN20 = mgain & 7; // writing 3 lower bits of mgain , (pre-amp mic gain). - map.r.signal_select_1.PMMP = 1; // Activating DC Mic Power supply through 2kohms res., similar majority smartphones headphone+mic jack, "plug-in-power" - map.r.signal_select_1.MPSEL = 1; // MPWR2 pin ,selecting output voltage to MPWR2 pin, that we are using in portapack ext. MIC) - map.r.signal_select_1.MGAIN3 = (mgain >> 3) & 1; // writing 4th upper bit of mgain (pre-amp mic gain). - update(Register::SignalSelect1); - } - - void AK4951::microphone_disable() { - map.r.power_management_1.PMADL = 0; // original code , disable Power managem.Mic ADC L - map.r.power_management_1.PMADR = 0; // original code , disable Power managem.Mic ADC R - map.r.power_management_1.PMPFIL = 0; // original code , disable Power managem. all Programmable Dig. block + map.r.power_management_1.PMADL = 0; + map.r.power_management_1.PMADR = 0; + map.r.power_management_1.PMPFIL = 0; update(Register::PowerManagement1); - map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block. + map.r.alc_mode_control_1.ALC = 0; update(Register::ALCModeControl1); - - map.r.auto_hpf_control.AHPF = 0; //----------- new code addition , Restore disable Wind noise filter OFF (AHPF bit=“0”). - update(Register::AutoHPFControl); - - //Restore original AUDIO PATH , condition, (Digital filter block PATH is BY PASSED) (we can also swith off DIG. BLOCK power , PMPFIL=0) - // The Path in Recording Mode 2 & Playback Mode 2 , (NO DIG FILTER BLOCK AT ALL, not for MIC recording, nor for Playback) - map.r.digital_filter_mode.ADCPF = 1; // new code addition , ADCPF bit swith ("0" Mic after ADC Output connected (recording mode) to the DIGITAL FILTER BLOCK. ("1" Playback mode) - map.r.digital_filter_mode.PFSDO = 0; // new code addition , ADC bit switch ("0" : 1st order HPF) connectedto the Output. By bass DIGITAL block . - map.r.digital_filter_mode.PFDAC = 0b00; // new code addition , (Input selector for DAC (not used in MIC), SDTI= Audio Serial Data Input Pin) - update(Register::DigitalFilterMode); // Writing the Audio Path : NO DIGITAL BLOCK or DIG BLOCK FOR MIC , Audio mode path : Playback mode /-Recording mode. - - // Restore original condition , LPF , OFF . same as when not using DIGITAL Programmable block - map.r.digital_filter_select_2.LPF = 0; // LPF-Block, Coeffic Setting Enable (OFF-Default), When LPF bit is “0”, audio data passes the LPF block by 0dB gain. - update(Register::DigitalFilterSelect2); - - map.r.lpf_coefficient_0.l = 0x00; // Pre-loading here LPF 6k , 1st Order from digital Block , Fc=6000 Hz, fs = 48khz - map.r.lpf_coefficient_1.h = 0x00; // LPF bit is activated down, for all ALC digital modes. - map.r.lpf_coefficient_2.l = 0x00; // Writting reg to AK4951 , down with update.... - map.r.lpf_coefficient_3.h = 0x00; - - update(Register::LPFCoefficient0); // Writing pre-loaded 4 bytes LPF CoefFiecients 14 bits (FSA13..0, FSB13..0 - update(Register::LPFCoefficient1); - update(Register::LPFCoefficient2); - update(Register::LPFCoefficient3); - - // Switch off all EQ 1,2,3,4,5 - map.r.digital_filter_select_3.EQ1 = 0; // EQ1 Coeffic Setting , (0: Disable-default, audio data passes EQ1 block by 0dB gain). When EQ1="1”, the settings of E1A15-0, E1B15-0 and E1C15-0 bits are enabled - map.r.digital_filter_select_3.EQ2 = 0; // EQ2 Coeffic Setting , (0: Disable-default, audio data passes EQ2 block by 0dB gain). When EQ2="1”, the settings of E2A15-0, E2B15-0 and E2C15-0 bits are enabled - map.r.digital_filter_select_3.EQ3 = 0; // EQ3 Coeffic Setting , (0: Disable-default, audio data passes EQ3 block by 0dB gain). When EQ3="1”, the settings of E3A15-0, E3B15-0 and E3C15-0 bits are enabled - map.r.digital_filter_select_3.EQ4 = 0; // EQ4 Coeffic Setting , (0: Disable-default, audio data passes EQ4 block by 0dB gain). When EQ4="1”, the settings of E4A15-0, E4B15-0 and E4C15-0 bits are enabled - map.r.digital_filter_select_3.EQ5 = 0; // EQ5 Coeffic Setting , (0: Disable-default, audio data passes EQ5 block by 0dB gain). When EQ5="1”, the settings of E5A15-0, E5B15-0 and E5C15-0 bits are enabled - update(Register::DigitalFilterSelect3); - } reg_t AK4951::read(const address_t reg_address) { diff --git a/firmware/common/ak4951.hpp b/firmware/common/ak4951.hpp index 3b1f9e1a..df168a09 100644 --- a/firmware/common/ak4951.hpp +++ b/firmware/common/ak4951.hpp @@ -773,41 +773,40 @@ constexpr RegisterMap default_after_reset { Register_Type { .REV = 0b1100, }, - // just pre-loading into memory, 30 bytes = EQ 1,2,3,4,5 x A,B,C (2 x bytes) coefficients, but it will be written from ak4951.cpp - .e1_coefficient_0 = { .l = 0xCA }, //EQ1 Coefficient A : A7...A0, BW : 300Hz - 1700Hz (fo = 1150Hz , fb= 1700Hz) , k=1,8 peaking - .e1_coefficient_1 = { .h = 0x05 }, //EQ1 Coefficient A : A15..A8 - .e1_coefficient_2 = { .l = 0xEB }, //EQ1 Coefficient B : B7...B0 - .e1_coefficient_3 = { .h = 0x38 }, //EQ1 Coefficient B : B15...B8 - .e1_coefficient_4 = { .l = 0x6F }, //EQ1 Coefficient C : C7...C0 - .e1_coefficient_5 = { .h = 0xE6 }, //EQ1 Coefficient C : C15..C8 + .e1_coefficient_0 = { .l = 0x00 }, + .e1_coefficient_1 = { .h = 0x00 }, + .e1_coefficient_2 = { .l = 0x00 }, + .e1_coefficient_3 = { .h = 0x00 }, + .e1_coefficient_4 = { .l = 0x00 }, + .e1_coefficient_5 = { .h = 0x00 }, - .e2_coefficient_0 = { .l = 0x05 }, //EQ2 Coefficient A : A7...A0, BW : 250Hz - 2700Hz (fo = 1475Hz , fb= 2450Hz) , k=1,8 peaking - .e2_coefficient_1 = { .h = 0x08 }, //EQ2 Coefficient A : A15..A8 - .e2_coefficient_2 = { .l = 0x11 }, //EQ2 Coefficient B : B7...B0 - .e2_coefficient_3 = { .h = 0x36 }, //EQ2 Coefficient B : B15...B8 - .e2_coefficient_4 = { .l = 0xE9 }, //EQ2 Coefficient C : C7...C0 - .e2_coefficient_5 = { .h = 0xE8 }, //EQ2 Coefficient C : C15..C8 + .e2_coefficient_0 = { .l = 0x00 }, + .e2_coefficient_1 = { .h = 0x00 }, + .e2_coefficient_2 = { .l = 0x00 }, + .e2_coefficient_3 = { .h = 0x00 }, + .e2_coefficient_4 = { .l = 0x00 }, + .e2_coefficient_5 = { .h = 0x00 }, - .e3_coefficient_0 = { .l = 0x00 }, //EQ3 Coefficient A : A7...A0, not used currently - .e3_coefficient_1 = { .h = 0x00 }, //EQ3 Coefficient A : A15..A8 - .e3_coefficient_2 = { .l = 0x00 }, //EQ3 Coefficient B : B7...B0 - .e3_coefficient_3 = { .h = 0x00 }, //EQ3 Coefficient B : B15...B8 - .e3_coefficient_4 = { .l = 0x00 }, //EQ3 Coefficient C : C7...C0 - .e3_coefficient_5 = { .h = 0x00 }, //EQ3 Coefficient C : C15..C8 + .e3_coefficient_0 = { .l = 0x00 }, + .e3_coefficient_1 = { .h = 0x00 }, + .e3_coefficient_2 = { .l = 0x00 }, + .e3_coefficient_3 = { .h = 0x00 }, + .e3_coefficient_4 = { .l = 0x00 }, + .e3_coefficient_5 = { .h = 0x00 }, - .e4_coefficient_0 = { .l = 0x00 }, //EQ4 Coefficient A : A7...A0, not used currently - .e4_coefficient_1 = { .h = 0x00 }, //EQ4 Coefficient A : A15..A8 - .e4_coefficient_2 = { .l = 0x00 }, //EQ4 Coefficient B : B7...B0 - .e4_coefficient_3 = { .h = 0x00 }, //EQ4 Coefficient B : B15...B8 - .e4_coefficient_4 = { .l = 0x00 }, //EQ4 Coefficient C : C7...C0 - .e4_coefficient_5 = { .h = 0x00 }, //EQ4 Coefficient C : C15..C8 + .e4_coefficient_0 = { .l = 0x00 }, + .e4_coefficient_1 = { .h = 0x00 }, + .e4_coefficient_2 = { .l = 0x00 }, + .e4_coefficient_3 = { .h = 0x00 }, + .e4_coefficient_4 = { .l = 0x00 }, + .e4_coefficient_5 = { .h = 0x00 }, - .e5_coefficient_0 = { .l = 0x00 }, //EQ5 Coefficient A : A7...A0, not used currently - .e5_coefficient_1 = { .h = 0x00 }, //EQ5 Coefficient A : A15..A8 - .e5_coefficient_2 = { .l = 0x00 }, //EQ5 Coefficient B : B7...B0 - .e5_coefficient_3 = { .h = 0x00 }, //EQ5 Coefficient B : B15...B8 - .e5_coefficient_4 = { .l = 0x00 }, //EQ5 Coefficient C : C7...C0 - .e5_coefficient_5 = { .h = 0x00 }, //EQ5 Coefficient C : C15..C8 + .e5_coefficient_0 = { .l = 0x00 }, + .e5_coefficient_1 = { .h = 0x00 }, + .e5_coefficient_2 = { .l = 0x00 }, + .e5_coefficient_3 = { .h = 0x00 }, + .e5_coefficient_4 = { .l = 0x00 }, + .e5_coefficient_5 = { .h = 0x00 }, } }; class AK4951 : public audio::Codec { @@ -842,7 +841,7 @@ public: void set_headphone_volume(const volume_t volume) override; void headphone_mute(); - void microphone_enable(int8_t alc_mode); // added user GUI parameter , to set up AK4951 ALC mode. + void microphone_enable(); void microphone_disable(); size_t reg_count() const override { diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 1b577336..35e2ad71 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -200,44 +200,32 @@ void set_serial_format(const serial_format_t new_value) { data->serial_format = new_value; } -/* static constexpr uint32_t playdead_magic = 0x88d3bb57; - -uint32_t playing_dead() { - return data->playing_dead; -} - -void set_playing_dead(const uint32_t new_value) { - if( data->playdead_magic != playdead_magic ) { - set_playdead_sequence(0x8D1); // U D L R - } - data->playing_dead = new_value; -} - -uint32_t playdead_sequence() { - if( data->playdead_magic != playdead_magic ) { - set_playdead_sequence(0x8D1); // U D L R - } - return data->playdead_sequence; -} - -void set_playdead_sequence(const uint32_t new_value) { - data->playdead_sequence = new_value; - data->playdead_magic = playdead_magic; -} */ - // ui_config is an uint32_t var storing information bitwise -// bits 0,1,2 store the backlight timer -// bits 31, 30,29,28,27, 26, 25, 24 stores the different single bit configs depicted below -// bits on position 4 to 19 (16 bits) store the clkout frequency +// bits 0-2 store the backlight timer +// bits 4-19 (16 bits) store the clkout frequency +// bits 21-31 store the different single bit configs depicted below +// bit 20 store the display state of the gui return icon, hidden (0) or shown (1) -bool disable_touchscreen() { // Option to disable touch screen - return data->ui_config & (1 << 24); +bool show_gui_return_icon(){ // add return icon in touchscreen menue +return data->ui_config & (1 << 20); +} + +bool load_app_settings() { // load (last saved) app settings on startup of app + return data->ui_config & (1 << 21); +} + +bool save_app_settings() { // save app settings when closing app + return data->ui_config & (1 << 22); } bool show_bigger_qr_code() { // show bigger QR code return data->ui_config & (1 << 23); } +bool disable_touchscreen() { // Option to disable touch screen + return data->ui_config & (1 << 24); +} + bool hide_clock() { // clock hidden from main menu return data->ui_config & (1 << 25); } @@ -274,14 +262,26 @@ uint32_t config_backlight_timer() { return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values } -void set_disable_touchscreen(bool v) { - data->ui_config = (data->ui_config & ~(1 << 24)) | (v << 24); +void set_gui_return_icon(bool v) { + data->ui_config = (data->ui_config & ~(1 << 20)) | (v << 20); } - + +void set_load_app_settings(bool v) { + data->ui_config = (data->ui_config & ~(1 << 21)) | (v << 21); +} + +void set_save_app_settings(bool v) { + data->ui_config = (data->ui_config & ~(1 << 22)) | (v << 22); +} + void set_show_bigger_qr_code(bool v) { data->ui_config = (data->ui_config & ~(1 << 23)) | (v << 23); } +void set_disable_touchscreen(bool v) { + data->ui_config = (data->ui_config & ~(1 << 24)) | (v << 24); +} + void set_clock_hidden(bool v) { data->ui_config = (data->ui_config & ~(1 << 25)) | (v << 25); } diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index bdfc1fef..03d5cc91 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -78,6 +78,9 @@ uint8_t config_cpld(); void set_config_cpld(uint8_t i); bool config_splash(); +bool show_gui_return_icon(); +bool load_app_settings(); +bool save_app_settings(); bool show_bigger_qr_code(); bool hide_clock(); bool clock_with_date(); @@ -86,8 +89,11 @@ bool config_speaker(); uint32_t config_backlight_timer(); bool disable_touchscreen(); -void set_config_splash(bool v); +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_splash(bool v); void set_clock_hidden(bool v); void set_clock_with_date(bool v); void set_config_login(bool v); diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index ac164a04..a5c8908b 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -345,9 +345,8 @@ public: void speaker_disable() {}; - void microphone_enable(int8_t alc_mode) override { - (void)alc_mode; // to avoid "unused warning" when compiling. (@WM8731 we do not use that parameter) - // TODO: Implement, + void microphone_enable() override { + // TODO: Implement } void microphone_disable() override { diff --git a/firmware/tools/generate_world_map.bin.py b/firmware/tools/generate_world_map.bin.py index ffb28659..38f575e2 100755 --- a/firmware/tools/generate_world_map.bin.py +++ b/firmware/tools/generate_world_map.bin.py @@ -36,7 +36,7 @@ outfile.write(struct.pack('H', im.size[1])) print("Generating: \t" + outfile.name + "\n from\t\t" + im.filename + "\n please wait..."); for y in range (0, im.size[1]): - line = '' + line = b'' for x in range (0, im.size[0]): # RRRRRGGGGGGBBBBB pixel_lcd = (pix[x, y][0] >> 3) << 11 @@ -47,8 +47,8 @@ for y in range (0, im.size[1]): # pixel_lcd = (pix[x, y][0] >> 5) << 5 # pixel_lcd |= (pix[x, y][1] >> 5) << 2 # pixel_lcd |= (pix[x, y][2] >> 6) - line += str(struct.pack('H', pixel_lcd)) - outfile.write(line.encode('utf-8')) + line += struct.pack('H', pixel_lcd) + outfile.write(line) print(str(y) + '/' + str(im.size[1]) + '\r', end="") print("Ready."); diff --git a/flashing/driver/amd64/WdfCoInstaller01011.dll b/flashing/driver/amd64/WdfCoInstaller01011.dll new file mode 100644 index 00000000..d49d2913 Binary files /dev/null and b/flashing/driver/amd64/WdfCoInstaller01011.dll differ diff --git a/flashing/driver/amd64/winusbcoinstaller2.dll b/flashing/driver/amd64/winusbcoinstaller2.dll new file mode 100644 index 00000000..30e55025 Binary files /dev/null and b/flashing/driver/amd64/winusbcoinstaller2.dll differ