diff --git a/.github/workflows/create_stable_release.yml b/.github/workflows/create_stable_release.yml new file mode 100644 index 00000000..30a74fdd --- /dev/null +++ b/.github/workflows/create_stable_release.yml @@ -0,0 +1,93 @@ +name: Stable Release + +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Get current date + id: date + run: echo "::set-output name=date::$(date +'%Y-%m-%d')" + - name: Checkout + uses: actions/checkout@master + with: + fetch-depth: 0 + ref: next + submodules: true + - name: Git Sumbodule Update + run: | + git submodule update --init --recursive + - name: Get version + id: version + run: echo "::set-output name=version::$(cat .github/workflows/version.txt)" + - name: Get past version + id: past_version + run: echo "::set-output name=past_version::$(cat .github/workflows/past_version.txt)" + - name: Build the Docker image + run: docker build -t portapack-dev -f dockerfile-nogit . --tag my-image-name:$(date +%s) + - name: Make build folder + run: mkdir ${{ github.workspace }}/build + - name: Run the Docker image + run: docker run -e VERSION_STRING=${{ steps.version.outputs.version }} -i -v ${{ github.workspace }}:/havoc portapack-dev + - name: Create Firmware ZIP + run: | + zip -j firmware.zip build/firmware/portapack-h1_h2-mayhem.bin && cd flashing && zip -r ../firmware.zip * + - name: Create SD Card ZIP + run: | + zip -r sdcard.zip sdcard + - name: Create changelog + run: | + CHANGELOG=$(python3 .github/workflows/stable_changelog.py ${{ steps.past_version.outputs.past_version }}) + CHANGELOG="${CHANGELOG//'%'/'%25'}" + CHANGELOG="${CHANGELOG//$'\n'/'%0A'}" + CHANGELOG="${CHANGELOG//$'\r'/'%0D'}" + echo "::set-output name=content::$CHANGELOG" + id: changelog + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.version.outputs.version }} + release_name: Mayhem firmware ${{ steps.version.outputs.version }} + body: | + **Stable release - ${{ steps.version.outputs.version }}** + This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmware, which itself was a fork of the [PortaPack](https://github.com/sharebrained/portapack-hackrf) firmware, an add-on for the [HackRF](http://greatscottgadgets.com/hackrf/). Please check the [readme](https://github.com/eried/portapack-mayhem/blob/master/README.md) for details. + ## Release notes + ### Revision (${{ steps.version.outputs.version }}): + ${{ steps.changelog.outputs.content }} + + **Full Changelog**: https://github.com/eried/portapack-mayhem/compare/${{ steps.past_version.outputs.past_version }}...${{ steps.version.outputs.version }} + + ## Installation + Check the [wiki](https://github.com/eried/portapack-havoc/wiki/Update-firmware) for details how to upgrade. + + ### MicroSD card files + + For certain functionality, like the world map, GPS simulator, and others you need to uncompress (using [7-zip](https://www.7-zip.org/download.html)) the files from `mayhem_vX.Y.Z_COPY_TO_SDCARD.zip` to a FAT32 formatted MicroSD card. + draft: true + prerelease: false + - name: Upload Firmware Asset + id: upload-firmware-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./firmware.zip + asset_name: mayhem_${{ steps.version.outputs.version }}_FIRMWARE.zip + asset_content_type: application/zip + - name: Upload SD Card Assets + id: upload-sd-card-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./sdcard.zip + asset_name: mayhem_${{ steps.version.outputs.version }}_COPY_TO_SDCARD.zip + asset_content_type: application/zip + diff --git a/.github/workflows/past_version.txt b/.github/workflows/past_version.txt new file mode 100644 index 00000000..53b5bbb1 --- /dev/null +++ b/.github/workflows/past_version.txt @@ -0,0 +1 @@ +v1.5.1 diff --git a/.github/workflows/stable_changelog.py b/.github/workflows/stable_changelog.py new file mode 100644 index 00000000..cca6cb7a --- /dev/null +++ b/.github/workflows/stable_changelog.py @@ -0,0 +1,30 @@ +import os +import re +import sys + +past_version = sys.argv[1] + +raw_git = os.popen('git log ' + past_version + '..next --pretty=format:"- %h - {USERNAME}*+%al-%an*: %s"').read() + + +def compute_username(line): + stripped = re.search(r'(?<=\*)(.*?)(?=\*)', line).group(0) + + pattern = re.compile("[$@+&?].*[$@+&?]") + if pattern.match(stripped): + stripped = re.sub("[$@+&?].*[$@+&?]", "", stripped) + stripped = re.match(r'.+?(?=-)', stripped).group(0) + else: + stripped = re.sub(r'^.*?-', "", stripped) + return "@" + stripped + + +def compile_line(line): + username = compute_username(line) + line = re.sub(r'[*].*[*]', "", line) + line = line.replace("{USERNAME}", username) + return line + + +for row in raw_git.splitlines(): + print(compile_line(row)) diff --git a/.github/workflows/version.txt b/.github/workflows/version.txt new file mode 100644 index 00000000..f1a2e631 --- /dev/null +++ b/.github/workflows/version.txt @@ -0,0 +1 @@ +v1.5.3 diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index a422aaaf..2def6164 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 06a36a6f..1561fee2 100644 --- a/firmware/application/apps/ais_app.cpp +++ b/firmware/application/apps/ais_app.cpp @@ -254,8 +254,18 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) { }; - - +} + + +AISRecentEntryDetailView::AISRecentEntryDetailView(const AISRecentEntryDetailView&Entry) : View() +{ + (void)Entry; +} + +AISRecentEntryDetailView & AISRecentEntryDetailView::operator=(const AISRecentEntryDetailView&Entry) +{ + (void)Entry; + return *this; } void AISRecentEntryDetailView::update_position() { @@ -325,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); @@ -363,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 c7f03aca..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" @@ -127,6 +127,9 @@ public: void focus() override; void paint(Painter&) override; + AISRecentEntryDetailView(const AISRecentEntryDetailView&Entry); + AISRecentEntryDetailView &operator=(const AISRecentEntryDetailView&Entry); + private: AISRecentEntry entry_ { }; @@ -163,13 +166,18 @@ public: void focus() override; - std::string title() const override { return "AIS"; }; + std::string title() const override { return "AIS Boats RX"; }; private: static constexpr uint32_t initial_target_frequency = 162025000; 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 8f62e237..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" @@ -143,7 +143,7 @@ public: void focus() override; - std::string title() const override { return "Analog audio"; }; + std::string title() const override { return "Audio RX"; }; size_t get_spec_bw_index(); void set_spec_bw(size_t index, uint32_t bw); @@ -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 6f90a55c..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" @@ -53,11 +53,15 @@ public: void focus() override; - std::string title() const override { return "Analog TV"; }; + std::string title() const override { return "Analog TV RX"; }; 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 14eb61c0..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" @@ -125,12 +125,17 @@ public: void focus() override; - std::string title() const override { return "ERT"; }; + std::string title() const override { return "ERT Meter RX"; }; 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/gps_sim_app.hpp b/firmware/application/apps/gps_sim_app.hpp index 34c7bb2d..b027eeec 100644 --- a/firmware/application/apps/gps_sim_app.hpp +++ b/firmware/application/apps/gps_sim_app.hpp @@ -44,7 +44,7 @@ public: void set_parent_rect(const Rect new_parent_rect) override; void focus() override; - std::string title() const override { return "GPS Simulator"; }; + std::string title() const override { return "GPS Sim TX"; }; private: NavigationView& nav_; 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 81825800..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 { @@ -40,7 +41,7 @@ public: void focus() override; - std::string title() const override { return "LGE tool"; }; + std::string title() const override { return "LGE tool TX"; }; private: enum tx_modes { @@ -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 91feaf96..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 { @@ -45,10 +46,14 @@ public: void focus() override; - std::string title() const override { return "Soundboard"; }; + std::string title() const override { return "Soundboard TX"; }; 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 7ccef644..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" @@ -103,13 +103,17 @@ public: void focus() override; - std::string title() const override { return "TPMS"; }; + std::string title() const override { return "TPMS Cars RX"; }; private: static constexpr uint32_t initial_target_frequency = 315000000; 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 e9ee91cb..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; @@ -184,7 +184,7 @@ private: AircraftRecentEntry entry_copy { 0 }; std::function on_close_ { }; bool send_updates { false }; - std::database db; + std::database db = { }; std::string icao_code = ""; int return_code = 0; @@ -279,7 +279,7 @@ private: GeoMapView* geomap_view { nullptr }; ADSBRxAircraftDetailsView* aircraft_details_view { nullptr }; bool send_updates { false }; - std::database db; + std::database db = { }; std::string airline_code = ""; int return_code = 0; @@ -361,17 +361,20 @@ public: void focus() override; - std::string title() const override { return "ADS-B receive"; }; + std::string title() const override { return "ADS-B RX"; }; void replace_entry(AircraftRecentEntry & entry); AircraftRecentEntry find_or_create_entry(uint32_t ICAO_address); void sort_entries_by_state(); private: - rf::Frequency prevFreq; + rf::Frequency prevFreq = { 0 }; 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 f68da241..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; @@ -152,7 +153,7 @@ public: void focus() override; - std::string title() const override { return "ADS-B transmit"; }; + std::string title() const override { return "ADS-B TX"; }; private: /*enum tx_modes { @@ -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 216e96a3..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" @@ -57,12 +57,12 @@ struct APRSRecentEntry { uint16_t hits { 0 }; uint32_t age { 0 }; - uint64_t source; + uint64_t source { 0 }; std::string source_formatted { " " }; std::string time_string { "" }; std::string info_string { "" }; - aprs::aprs_pos pos; + aprs::aprs_pos pos { 0 , 0 , 0 , 0 }; bool has_position = false; APRSRecentEntry(uint64_t src) { @@ -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 64cf838d..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 { @@ -178,9 +179,13 @@ public: void focus() override; - std::string title() const override { return "BHT transmit"; }; + 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 8d169d86..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 { @@ -39,7 +40,7 @@ public: void focus() override; - std::string title() const override { return "Si44xx TX"; }; + std::string title() const override { return "BurgerPgr TX"; }; private: enum tx_modes { @@ -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 2bec78fa..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,14 +346,17 @@ 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(); } }, { "Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav](){ nav.push(); } }, { "Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav](){ nav.push(); } }, - { "Buttons test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push(); } }, + { "Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav](){ nav.push(); } }, }); set_max_rows(2); // allow wider buttons } diff --git a/firmware/application/apps/ui_debug.hpp b/firmware/application/apps/ui_debug.hpp index 1e3d6003..19118721 100644 --- a/firmware/application/apps/ui_debug.hpp +++ b/firmware/application/apps/ui_debug.hpp @@ -43,6 +43,8 @@ public: void focus() override; + std::string title() const override { return "Memory"; }; + private: Text text_title { { 96, 96, 48, 16 }, @@ -113,6 +115,8 @@ public: void focus() override; + std::string title() const override { return "Temperature"; }; + private: Text text_title { { 76, 16, 240, 16 }, @@ -252,6 +256,8 @@ public: void focus() override; + std::string title() const override { return "Buttons Test"; }; + private: Text text_title { { 64, 16, 184, 16 }, 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 ee311e38..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; @@ -158,7 +159,7 @@ public: void focus() override; - std::string title() const override { return "OOK transmit"; }; + std::string title() const override { return "OOK TX"; }; private: NavigationView& nav_; @@ -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_jammer.hpp b/firmware/application/apps/ui_jammer.hpp index 8158a6f7..13869262 100644 --- a/firmware/application/apps/ui_jammer.hpp +++ b/firmware/application/apps/ui_jammer.hpp @@ -106,7 +106,7 @@ public: void focus() override; - std::string title() const override { return "Jammer"; }; + std::string title() const override { return "Jammer TX"; }; private: NavigationView& nav_; 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 7f28d554..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 "Keyfob (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 a9c7548a..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 { @@ -39,7 +40,7 @@ public: void focus() override; - std::string title() const override { return "LCR transmit"; }; + std::string title() const override { return "TEDI/LCR TX"; }; private: struct scan_list_t { @@ -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_mictx.hpp b/firmware/application/apps/ui_mictx.hpp index aaab059c..9b091e53 100644 --- a/firmware/application/apps/ui_mictx.hpp +++ b/firmware/application/apps/ui_mictx.hpp @@ -58,7 +58,7 @@ public: }; */ - std::string title() const override { return "Mic TX RX"; }; + std::string title() const override { return "Microphone"; }; private: static constexpr uint32_t sampling_rate = 1536000U; 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 6e6e0797..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; @@ -144,12 +144,17 @@ public: void focus() override; - std::string title() const override { return "RDS transmit"; }; + std::string title() const override { return "RDS TX"; }; 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_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index 6874280a..3bd350c8 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -484,6 +484,7 @@ void ScannerView::scan_pause() { scan_thread->set_freq_lock(0); //Reset the scanner lock (because user paused, or MAX_FREQ_LOCK reached) for next freq scan scan_thread->set_scanning(false); // WE STOP SCANNING audio::output::start(); + on_headphone_volume_changed(field_volume.value()); // quick fix to make sure WM8731S chips don't stay silent after pause } } diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp index 3936904e..caa571f9 100644 --- a/firmware/application/apps/ui_scanner.hpp +++ b/firmware/application/apps/ui_scanner.hpp @@ -111,7 +111,7 @@ public: .foreground = Color::red(), }; - std::string title() const override { return "SCANNER"; }; + std::string title() const override { return "Scanner"; }; std::vector frequency_list{ }; std::vector description_list { }; diff --git a/firmware/application/apps/ui_sd_wipe.hpp b/firmware/application/apps/ui_sd_wipe.hpp index 6d49b6f4..fc593f16 100644 --- a/firmware/application/apps/ui_sd_wipe.hpp +++ b/firmware/application/apps/ui_sd_wipe.hpp @@ -38,7 +38,7 @@ public: ~WipeSDView(); void focus() override; - std::string title() const override { return "Wipe FAT"; }; + std::string title() const override { return "Wipe SD Card"; }; private: NavigationView& nav_; diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index fbda02b7..b5e033b3 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -43,7 +43,7 @@ namespace ui { SetDateTimeView::SetDateTimeView( NavigationView& nav ) { - button_done.on_select = [&nav, this](Button&){ + button_save.on_select = [&nav, this](Button&){ const auto model = this->form_collect(); const rtc::RTC new_datetime { model.year, model.month, model.day, @@ -65,7 +65,7 @@ SetDateTimeView::SetDateTimeView( &field_hour, &field_minute, &field_second, - &button_done, + &button_save, &button_cancel, }); @@ -150,7 +150,7 @@ SetRadioView::SetRadioView( &value_freq_step, &labels_bias, &check_bias, - &button_done, + &button_save, &button_cancel }); @@ -200,7 +200,7 @@ SetRadioView::SetRadioView( EventDispatcher::send_message(message); }; - button_done.on_select = [this, &nav](Button&){ + button_save.on_select = [this, &nav](Button&){ const auto model = this->form_collect(); portapack::persistent_memory::set_correction_ppb(model.ppm * 1000); portapack::persistent_memory::set_clkout_freq(model.freq); @@ -210,7 +210,7 @@ SetRadioView::SetRadioView( } void SetRadioView::focus() { - button_done.focus(); + button_save.focus(); } void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) { @@ -224,76 +224,26 @@ SetFrequencyCorrectionModel SetRadioView::form_collect() { }; } -/* -SetPlayDeadView::SetPlayDeadView(NavigationView& nav) { - add_children({ - &text_sequence, - &button_enter, - &button_cancel - }); - - button_enter.on_select = [this, &nav](Button&){ - if (!entermode) { - sequence = 0; - keycount = 0; - memset(sequence_txt, '-', 10); - text_sequence.set(sequence_txt); - entermode = true; - button_cancel.hidden(true); - set_dirty(); - } else { - if (sequence == 0x8D1) // U D L R - nav.display_modal("Warning", "Default sequence entered !", ABORT, nullptr); - else { - persistent_memory::set_playdead_sequence(sequence); - nav.pop(); - } - } - }; - - button_enter.on_dir = [this](Button&, KeyEvent key){ - if ((entermode == true) && (keycount < 10)) { - key_code = static_cast::type>(key); - if (key_code == 0) - sequence_txt[keycount] = 'R'; - else if (key_code == 1) - sequence_txt[keycount] = 'L'; - else if (key_code == 2) - sequence_txt[keycount] = 'D'; - else if (key_code == 3) - sequence_txt[keycount] = 'U'; - text_sequence.set(sequence_txt); - sequence = (sequence << 3) | (key_code + 1); - keycount++; - return true; - } - return false; - }; - - button_cancel.on_select = [&nav](Button&){ nav.pop(); }; -} - -void SetPlayDeadView::focus() { - button_cancel.focus(); -} -*/ SetUIView::SetUIView(NavigationView& nav) { add_children({ - //&checkbox_login, + &checkbox_disable_touchscreen, &checkbox_speaker, &checkbox_bloff, &options_bloff, &checkbox_showsplash, &checkbox_showclock, - &options_clockformat, - &button_ok + &options_clockformat, + &checkbox_guireturnflag, + &button_save, + &button_cancel }); + checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen()); 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_login.set_value(persistent_memory::config_login()); + checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon()); uint32_t backlight_timer = persistent_memory::config_backlight_timer(); if (backlight_timer) { @@ -309,16 +259,8 @@ 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_ok.on_select = [&nav, this](Button&) { + button_save.on_select = [&nav, this](Button&) { if (checkbox_bloff.value()) persistent_memory::set_config_backlight_timer(options_bloff.selected_index() + 1); else @@ -329,225 +271,122 @@ SetUIView::SetUIView(NavigationView& nav) { persistent_memory::set_clock_with_date(true); else persistent_memory::set_clock_with_date(false); - } + } + + if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled + persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status + StatusRefreshMessage message { }; //Refresh status bar with/out speaker + EventDispatcher::send_message(message); + persistent_memory::set_config_splash(checkbox_showsplash.value()); persistent_memory::set_clock_hidden(!checkbox_showclock.value()); - //persistent_memory::set_config_login(checkbox_login.value()); + persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value()); + persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value()); + nav.pop(); + }; + button_cancel.on_select = [&nav, this](Button&) { nav.pop(); }; } void SetUIView::focus() { - button_ok.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, &field_tone_mix, - &button_ok + &button_save, + &button_cancel }); field_tone_mix.set_value(persistent_memory::tone_mix()); - button_ok.on_select = [&nav, this](Button&) { + button_save.on_select = [&nav, this](Button&) { persistent_memory::set_tone_mix(field_tone_mix.value()); nav.pop(); }; + + button_cancel.on_select = [&nav, this](Button&) { + nav.pop(); + }; } void SetAudioView::focus() { - field_tone_mix.focus(); + button_save.focus(); } -/*void ModInfoView::on_show() { - if (modules_nb) update_infos(0); -} +SetQRCodeView::SetQRCodeView(NavigationView& nav) { + add_children({ + &checkbox_bigger_qr, + &button_save, + &button_cancel + }); -void ModInfoView::update_infos(uint8_t modn) { - char info_str[27]; - char ch; - uint8_t c; - Point pos = { 0, 0 }; - Rect rect = { { 16, 144 }, { 208, 144 } }; + checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code()); - info_str[0] = 0; - strcat(info_str, module_list[modn].name); - text_namestr.set(info_str); - - info_str[0] = 0; - strcat(info_str, to_string_dec_uint(module_list[modn].size).c_str()); - strcat(info_str, " bytes"); - text_sizestr.set(info_str); - - info_str[0] = 0; - for (c = 0; c < 8; c++) - strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str()); - text_md5_a.set(info_str); - - info_str[0] = 0; - for (c = 8; c < 16; c++) - strcat(info_str, to_string_hex(module_list[modn].md5[c], 2).c_str()); - text_md5_b.set(info_str); - - // TODO: Use ui_console - display.fill_rectangle(rect, Color::black()); - - const Font& font = font::fixed_8x16; - const auto line_height = font.line_height(); - c = 0; - while((ch = module_list[modn].description[c++])) { - const auto glyph = font.glyph(ch); - const auto advance = glyph.advance(); - if((pos.x + advance.x) > rect.width()) { - pos.x = 0; - pos.y += line_height; - } - const Point pos_glyph { - static_cast(rect.pos.x + pos.x), - static_cast(rect.pos.y + pos.y) - }; - display.draw_glyph(pos_glyph, glyph, Color::white(), Color::black()); - pos.x += advance.x; - } -} - -ModInfoView::ModInfoView(NavigationView& nav) { - const char magic[4] = {'P', 'P', 'M', ' '}; - UINT bw; - uint8_t i; - char read_buf[16]; - char info_str[25]; - FILINFO modinfo; - FIL modfile; - DIR rootdir; - FRESULT res; - uint8_t c; - - using option_t = std::pair; - using options_t = std::vector; - option_t opt; - options_t opts; - - static constexpr Style style_orange { - .font = font::fixed_8x16, - .background = Color::black(), - .foreground = Color::orange(), - }; - - add_children({{ - &text_modcount, - &text_name, - &text_namestr, - &text_size, - &text_sizestr, - &text_md5, - &text_md5_a, - &text_md5_b, - &button_ok - }}); - - text_name.set_style(&style_orange); - text_size.set_style(&style_orange); - text_md5.set_style(&style_orange); - - // TODO: Find a way to merge this with m4_load_image() in m4_startup.cpp - - // Scan SD card root directory for files starting with the magic bytes - c = 0; - if (f_opendir(&rootdir, "/") == FR_OK) { - for (;;) { - res = f_readdir(&rootdir, &modinfo); - if (res != FR_OK || modinfo.fname[0] == 0) break; // Reached last file, abort - // Only care about files with .bin extension - if ((!(modinfo.fattrib & AM_DIR)) && (modinfo.fname[9] == 'B') && (modinfo.fname[10] == 'I') && (modinfo.fname[11] == 'N')) { - f_open(&modfile, modinfo.fname, FA_OPEN_EXISTING | FA_READ); - // Magic bytes check - f_read(&modfile, &read_buf, 4, &bw); - for (i = 0; i < 4; i++) - if (read_buf[i] != magic[i]) break; - if (i == 4) { - memcpy(&module_list[c].filename, modinfo.fname, 8); - module_list[c].filename[8] = 0; - - f_lseek(&modfile, 4); - f_read(&modfile, &module_list[c].version, 2, &bw); - f_lseek(&modfile, 6); - f_read(&modfile, &module_list[c].size, 4, &bw); - f_lseek(&modfile, 10); - f_read(&modfile, &module_list[c].name, 16, &bw); - f_lseek(&modfile, 26); - f_read(&modfile, &module_list[c].md5, 16, &bw); - f_lseek(&modfile, 42); - f_read(&modfile, &module_list[c].description, 214, &bw); - f_lseek(&modfile, 256); - - // Sanitize - module_list[c].name[15] = 0; - module_list[c].description[213] = 0; - - memcpy(info_str, module_list[c].filename, 16); - strcat(info_str, "(V"); - strcat(info_str, to_string_dec_uint(module_list[c].version, 4, '0').c_str()); - strcat(info_str, ")"); - while(strlen(info_str) < 24) - strcat(info_str, " "); - - opt = std::make_pair(info_str, c); - opts.insert(opts.end(), opt); - - c++; - } - f_close(&modfile); - } - if (c == 8) break; - } - } - f_closedir(&rootdir); - - modules_nb = c; - - if (modules_nb) { - strcpy(info_str, "Found "); - strcat(info_str, to_string_dec_uint(modules_nb, 1).c_str()); - strcat(info_str, " module(s)"); - - text_modcount.set(info_str); - option_modules.set_options(opts); - - add_child(&option_modules); - - option_modules.on_change = [this](size_t n, OptionsField::value_t v) { - (void)n; - update_infos(v); - }; - } else { - strcpy(info_str, "No modules found"); - text_modcount.set(info_str); - } - - button_ok.on_select = [&nav,this](Button&){ + button_save.on_select = [&nav, this](Button&) { + persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value()); nav.pop(); }; + + button_cancel.on_select = [&nav, this](Button&) { + nav.pop(); + }; + } -void ModInfoView::focus() { - if (modules_nb) - option_modules.focus(); - else - button_ok.focus(); -}*/ +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({ - //{ "..", ui::Color::light_grey(), &bitmap_icon_previous, [&nav](){ nav.pop(); } }, - { "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push(); } }, - { "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push(); } }, - { "Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push(); } }, - //{ "SD card modules", ui::Color::dark_cyan(), [&nav](){ nav.push(); } }, - { "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push(); } }, - { "Touchscreen", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push(); } }, - //{ "Play dead", ui::Color::dark_cyan(), &bitmap_icon_playdead, [&nav](){ nav.push(); } } + { "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(); } }, + { "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(); } }, + { "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 30acd820..d1f3cb63 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -47,7 +47,7 @@ public: void focus() override; - std::string title() const override { return "Set Date/Time"; }; + std::string title() const override { return "Date/Time"; }; private: Labels labels { @@ -99,7 +99,7 @@ private: '0', }; - Button button_done { + Button button_save { { 2 * 8, 16 * 16, 12 * 8, 32 }, "Save" }; @@ -197,7 +197,7 @@ private: "Turn on bias voltage" }; - Button button_done { + Button button_save { { 2 * 8, 16 * 16, 12 * 8, 32 }, "Save" }; @@ -219,11 +219,12 @@ public: std::string title() const override { return "UI settings"; }; private: - /*Checkbox checkbox_login { + + Checkbox checkbox_disable_touchscreen { { 3 * 8, 2 * 16 }, 20, - "Login with play dead" - };*/ + "Disable touchscreen" + }; Checkbox checkbox_speaker { { 3 * 8, 4 * 16 }, @@ -270,11 +271,55 @@ private: { "time and date", 1 } } }; + + Checkbox checkbox_guireturnflag { + { 3 * 8, 14 * 16 }, + 25, + "add return icon in GUI" + }; - Button button_ok { + 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 }, + "Save" + }; + + Button button_cancel { + { 16 * 8, 16 * 16, 12 * 8, 32 }, + "Cancel", + }; }; class SetAudioView : public View { @@ -298,111 +343,43 @@ private: '0' }; - Button button_ok { + Button button_save { { 2 * 8, 16 * 16, 12 * 8, 32 }, "Save" }; + + Button button_cancel { + { 16 * 8, 16 * 16, 12 * 8, 32 }, + "Cancel", + }; }; -/* -class SetPlayDeadView : public View { -public: - SetPlayDeadView(NavigationView& nav); - - void focus() override; - - std::string title() const override { return "Playdead settings"; }; - -private: - bool entermode = false; - uint32_t sequence { 0 }; - uint8_t keycount { 0 }, key_code { }; - char sequence_txt[11] = { 0 }; - - Text text_sequence { - { 64, 32, 14 * 8, 16 }, - "Enter sequence", - }; - - Button button_enter { - { 16, 192, 96, 24 }, - "Enter" - }; - Button button_cancel { - { 128, 192, 96, 24 }, - "Cancel" - }; -};*/ -/*class ModInfoView : public View { +class SetQRCodeView : public View { public: - ModInfoView(NavigationView& nav); + SetQRCodeView(NavigationView& nav); + void focus() override; - void on_show() override; + + std::string title() const override { return "QR Code"; }; private: - void update_infos(uint8_t modn); - - typedef struct moduleinfo_t{ - char filename[9]; - uint16_t version; - uint32_t size; - char md5[16]; - char name[16]; - char description[214]; - } moduleinfo_t; - - moduleinfo_t module_list[8]; // 8 max for now - - uint8_t modules_nb; - - Text text_modcount { - { 2 * 8, 1 * 16, 18 * 8, 16 }, - "Searching..." + Checkbox checkbox_bigger_qr { + { 3 * 8, 9 * 16 }, + 20, + "Show large QR code" }; - OptionsField option_modules { - { 2 * 8, 2 * 16 }, - 24, - { - { "-", 0 } - } + Button button_save { + { 2 * 8, 16 * 16, 12 * 8, 32 }, + "Save" }; - Text text_name { - { 2 * 8, 4 * 16, 5 * 8, 16 }, - "Name:" + Button button_cancel { + { 16 * 8, 16 * 16, 12 * 8, 32 }, + "Cancel", }; - Text text_namestr { - { 8 * 8, 4 * 16, 16 * 8, 16 }, - "..." - }; - Text text_size { - { 2 * 8, 5 * 16, 5 * 8, 16 }, - "Size:" - }; - Text text_sizestr { - { 8 * 8, 5 * 16, 16 * 8, 16 }, - "..." - }; - Text text_md5 { - { 2 * 8, 6 * 16, 4 * 8, 16 }, - "MD5:" - }; - Text text_md5_a { - { 7 * 8, 6 * 16, 16 * 8, 16 }, - "..." - }; - Text text_md5_b { - { 7 * 8, 7 * 16, 16 * 8, 16 }, - "..." - }; - - Button button_ok { - { 4 * 8, 272, 64, 24 }, - "Ok" - }; -};*/ +}; class SettingsMenuView : public BtnGridView { public: diff --git a/firmware/application/apps/ui_siggen.hpp b/firmware/application/apps/ui_siggen.hpp index 5abcdd85..f55d19d1 100644 --- a/firmware/application/apps/ui_siggen.hpp +++ b/firmware/application/apps/ui_siggen.hpp @@ -40,7 +40,7 @@ public: void focus() override; - std::string title() const override { return "Generator"; }; + std::string title() const override { return "Signal gen"; }; private: void start_tx(); 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/bitmap.hpp b/firmware/application/bitmap.hpp index 8cb98a43..57c9f5fe 100644 --- a/firmware/application/bitmap.hpp +++ b/firmware/application/bitmap.hpp @@ -1285,6 +1285,28 @@ static constexpr Bitmap bitmap_icon_previous { { 16, 16 }, bitmap_icon_previous_data }; +static constexpr uint8_t bitmap_icon_qr_code_data[] = { + 0x00, 0x00, + 0xFE, 0x7E, + 0xC6, 0x62, + 0xFA, 0x5A, + 0xFA, 0x5A, + 0xDA, 0x5A, + 0xFE, 0x7E, + 0x7E, 0x7E, + 0x00, 0x00, + 0xFE, 0x46, + 0xC2, 0x06, + 0xFA, 0x18, + 0xFA, 0x18, + 0xC6, 0x60, + 0xFE, 0x62, + 0x00, 0x00, +}; +static constexpr Bitmap bitmap_icon_qr_code { + { 16, 16 }, bitmap_icon_qr_code_data +}; + static constexpr uint8_t bitmap_icon_rds_data[] = { 0x00, 0x00, 0x00, 0x00, diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 185a905d..2e471b9f 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -167,7 +167,7 @@ int main(void) { if( portapack::init() ) { portapack::display.init(); - sdcStart(&SDCD1, nullptr); + // sdcStart(&SDCD1, nullptr); // Commented out as now happens in portapack.cpp // controls_init(); // Commented out as now happens in portapack.cpp lcd_frame_sync_configure(); @@ -175,6 +175,7 @@ int main(void) { event_loop(); + sdcDisconnect(&SDCD1); sdcStop(&SDCD1); diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 7ecfb721..5d51f175 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -48,6 +48,10 @@ using asahi_kasei::ak4951::AK4951; #include "optional.hpp" #include "irq_controls.hpp" +#include "file.hpp" +#include "sd_card.hpp" +#include "string_format.hpp" + namespace portapack { portapack::IO io { @@ -177,14 +181,84 @@ enum class PortaPackModel { R2_20170522, }; +static bool save_config(int8_t value){ + persistent_memory::set_config_cpld(value); + if(sd_card::status() == sd_card::Status::Mounted){ + make_new_directory("/hardware"); + File file; + auto sucess = file.create("/hardware/settings.txt"); + if(!sucess.is_valid()) { + file.write_line(to_string_dec_uint(value)); + } + } + return true; +} + +int read_file(std::string name) { + std::string return_string = ""; + File file; + auto success = file.open(name); + + if(!success.is_valid()) { + char one_char[1]; + for(size_t pointer = 0; pointer < file.size() ; pointer++) { + file.seek(pointer); + file.read(one_char, 1); + return_string += one_char[0]; + } + return std::stoi(return_string); + } + return -1; +} + +static int load_config(){ + static Optional config_value; + if(!config_value.is_valid()){ + int8_t value = portapack::persistent_memory::config_cpld(); + if((value <= 0 || value >= 4) && sd_card::status() == sd_card::Status::Mounted){ + int data = read_file("/hardware/settings.txt"); + if(data != -1) { + config_value = data; + } + } else { + config_value = value; + } + } + return config_value.value(); +} + + static PortaPackModel portapack_model() { static Optional model; if( !model.is_valid() ) { - if( audio_codec_wm8731.detected() ) { - model = PortaPackModel::R1_20150901; // H1R1 + const auto switches_state = get_switches_state(); + if (switches_state[(size_t)ui::KeyEvent::Up]){ + save_config(1); + model = PortaPackModel::R2_20170522; + } + else if (switches_state[(size_t)ui::KeyEvent::Down]){ + save_config(2); + model = PortaPackModel::R1_20150901; + } + else if (switches_state[(size_t)ui::KeyEvent::Left]){ + save_config(3); + } + else if (switches_state[(size_t)ui::KeyEvent::Select]){ + save_config(0); + } + + + if (load_config() == 1) { + model = PortaPackModel::R2_20170522; + } else if (load_config() == 2) { + model = PortaPackModel::R1_20150901; } else { - model = PortaPackModel::R2_20170522; // H1R2, H2+ + if( audio_codec_wm8731.detected() ) { + model = PortaPackModel::R1_20150901; // H1R1 + } else { + model = PortaPackModel::R2_20170522; // H1R2, H2, H2+ + } } } @@ -203,28 +277,6 @@ static audio::Codec* portapack_audio_codec() { } static const portapack::cpld::Config& portapack_cpld_config() { - const auto switches_state = get_switches_state(); - if (switches_state[(size_t)ui::KeyEvent::Up]){ - persistent_memory::set_config_cpld(1); - return portapack::cpld::rev_20170522::config; - } - if (switches_state[(size_t)ui::KeyEvent::Down]){ - persistent_memory::set_config_cpld(2); - return portapack::cpld::rev_20150901::config; - } - if (switches_state[(size_t)ui::KeyEvent::Left]){ - persistent_memory::set_config_cpld(3); - } - if (switches_state[(size_t)ui::KeyEvent::Select]){ - persistent_memory::set_config_cpld(0); - } - - - if (portapack::persistent_memory::config_cpld() == 1) { - return portapack::cpld::rev_20170522::config; - } else if (portapack::persistent_memory::config_cpld() == 2) { - return portapack::cpld::rev_20150901::config; - } return (portapack_model() == PortaPackModel::R2_20170522) ? portapack::cpld::rev_20170522::config : portapack::cpld::rev_20150901::config; @@ -351,6 +403,7 @@ bool init() { // if( !hackrf::cpld::load_sram() ) { // chSysHalt(); // } + chThdSleepMilliseconds(100); configure_pins_portapack(); @@ -360,8 +413,9 @@ bool init() { i2c0.stop(); - set_clock_config(clock_config_irc); + chThdSleepMilliseconds(10); + set_clock_config(clock_config_irc); cgu::pll1::disable(); /* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4 @@ -401,25 +455,27 @@ 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(); clock_manager.enable_second_if_clock(); clock_manager.enable_codec_clocks(); - radio::init(); + radio::init(); + + sdcStart(&SDCD1, nullptr); + sd_card::poll_inserted(); - - LPC_CREG->DMAMUX = portapack::gpdma_mux; - gpdma::controller.enable(); - - audio::init(portapack_audio_codec()); + chThdSleepMilliseconds(10); if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) { + chThdSleepMilliseconds(10); // If using a "2021/12 QFP100", press and hold the left button while booting. Should only need to do once. - if (portapack::persistent_memory::config_cpld() != 3){ + if (load_config() != 3){ shutdown_base(); return false; } @@ -429,6 +485,16 @@ bool init() { chSysHalt(); } + 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()); + + return true; } diff --git a/firmware/application/qrcodegen.cpp b/firmware/application/qrcodegen.cpp index 9e1e293a..2dcdbee5 100644 --- a/firmware/application/qrcodegen.cpp +++ b/firmware/application/qrcodegen.cpp @@ -38,7 +38,7 @@ #include #include -#pragma mark - Error Correction Lookup tables +/* #pragma mark - Error Correction Lookup tables */ #if LOCK_VERSION == 0 @@ -101,7 +101,7 @@ static int abs(int value) { */ -#pragma mark - Mode testing and conversion +/* #pragma mark - Mode testing and conversion */ static int8_t getAlphanumeric(char c) { @@ -140,7 +140,7 @@ static bool isNumeric(const char *text, uint16_t length) { } -#pragma mark - Counting +/* #pragma mark - Counting */ // We store the following tightly packed (less 8) in modeInfo // <=9 <=26 <= 40 @@ -167,7 +167,7 @@ static char getModeBits(uint8_t version, uint8_t mode) { } -#pragma mark - BitBucket +/* #pragma mark - BitBucket */ typedef struct BitBucket { uint32_t bitOffsetOrWidth; @@ -251,7 +251,7 @@ static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) { } -#pragma mark - Drawing Patterns +/* #pragma mark - Drawing Patterns */ // XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical // properties, calling applyMask(m) twice with the same value is equivalent to no change at all. @@ -474,7 +474,7 @@ static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket * -#pragma mark - Penalty Calculation +/* #pragma mark - Penalty Calculation */ #define PENALTY_N1 3 #define PENALTY_N2 3 @@ -574,7 +574,7 @@ static uint32_t getPenaltyScore(BitBucket *modules) { } -#pragma mark - Reed-Solomon Generator +/* #pragma mark - Reed-Solomon Generator */ static uint8_t rs_multiply(uint8_t x, uint8_t y) { // Russian peasant multiplication @@ -628,7 +628,7 @@ static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8 -#pragma mark - QrCode +/* #pragma mark - QrCode */ static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) { int8_t mode = MODE_BYTE; @@ -769,7 +769,7 @@ static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | (0x01 << 0); -#pragma mark - Public QRCode functions +/* #pragma mark - Public QRCode functions */ uint16_t qrcode_getBufferSize(uint8_t version) { return bb_getGridSizeBytes(4 * version + 17); @@ -857,7 +857,7 @@ int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_ } bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) { - if (x < 0 || x >= qrcode->size || y < 0 || y >= qrcode->size) { + if ( x >= qrcode->size || y >= qrcode->size) { return false; } @@ -873,4 +873,4 @@ uint8_t qrcode_getHexLength(QRCode *qrcode) { void qrcode_getHex(QRCode *qrcode, char *result) { } -*/ \ No newline at end of file +*/ diff --git a/firmware/application/touch.cpp b/firmware/application/touch.cpp index d3fc6c92..63c7bb47 100644 --- a/firmware/application/touch.cpp +++ b/firmware/application/touch.cpp @@ -109,7 +109,7 @@ void Manager::feed(const Frame& frame) { switch(state) { case State::NoTouch: - if( touch_stable && touch_pressure ) { + if( touch_stable && touch_pressure && !persistent_memory::disable_touchscreen()) { if( point_stable() ) { state = State::TouchDetected; touch_started(); diff --git a/firmware/application/ui/ui_qrcode.cpp b/firmware/application/ui/ui_qrcode.cpp index fd18d990..736ef441 100644 --- a/firmware/application/ui/ui_qrcode.cpp +++ b/firmware/application/ui/ui_qrcode.cpp @@ -23,6 +23,7 @@ #include "ui_qrcode.hpp" #include "qrcodegen.hpp" #include "portapack.hpp" +#include "portapack_persistent_memory.hpp" #include #include @@ -42,26 +43,74 @@ QRCodeImage::QRCodeImage( } +QRCodeImage::~QRCodeImage( ) +{ + +} + +QRCodeImage::QRCodeImage(const QRCodeImage&Image) : Widget { } +{ + (void)Image; +} + +QRCodeImage & QRCodeImage::operator=(const QRCodeImage&Image) +{ + (void)Image; + return *this; +} + void QRCodeImage::paint(Painter& painter) { + + (void)painter ; + // The structure to manage the QR code QRCode qrcode; - int qr_version = 10; // bigger versions aren't handled very well - - // Allocate a chunk of memory to store the QR code - uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)]; - - qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_); - display.fill_rectangle(Rect(92, 97, 63, 63), Color::white()); + //Either small or large QR code can be shown.. - for (uint8_t y = 0; y < qrcode.size; y++) { - for (uint8_t x = 0; x < qrcode.size; x++) { - if (qrcode_getModule(&qrcode, x, y)) { - display.draw_pixel(Point(95+x,100+y), Color::black()); + if(portapack::persistent_memory::show_bigger_qr_code()) { // show large QR code + int qr_version = 2; + + // Allocate a chunk of memory to store the QR code + uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)]; + + qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_); + + + display.fill_rectangle(Rect(10, 30, 220, 220), Color::white()); + + for (uint8_t y = 0; y < qrcode.size; y++) { + for (uint8_t x = 0; x < qrcode.size; x++) { + if (qrcode_getModule(&qrcode, x, y)) { + display.fill_rectangle(Rect(20+(x*8), 40+(y*8), 8, 8), Color::black()); + + } + } + } + + } + + else { // show small QR code + int qr_version = 10; + + // Allocate a chunk of memory to store the QR code + uint8_t qrcodeBytes[qrcode_getBufferSize(qr_version)]; + + qrcode_initText(&qrcode, qrcodeBytes, qr_version, ECC_HIGH, qr_text_); + + + display.fill_rectangle(Rect(92, 97, 63, 63), Color::white()); + + for (uint8_t y = 0; y < qrcode.size; y++) { + for (uint8_t x = 0; x < qrcode.size; x++) { + if (qrcode_getModule(&qrcode, x, y)) { + display.draw_pixel(Point(95+x,100+y), Color::black()); + + } + } + } - } - } } } @@ -84,10 +133,9 @@ QRCodeView::QRCodeView( add_children({ - &text_qr, &qr_code, &button_close}); - text_qr.set(qr_text); + //text_qr.set(qr_text); qr_code.set_text(qr_text); button_close.on_select = [&nav](Button&){ diff --git a/firmware/application/ui/ui_qrcode.hpp b/firmware/application/ui/ui_qrcode.hpp index 43dab2d8..d30b7715 100644 --- a/firmware/application/ui/ui_qrcode.hpp +++ b/firmware/application/ui/ui_qrcode.hpp @@ -40,10 +40,13 @@ public: qr_text_ = qr_text; } void paint(Painter& painter) override; - + // for -weffc++ to be killed + ~QRCodeImage(); // destructor + QRCodeImage(const QRCodeImage&Image); + QRCodeImage & operator=(const QRCodeImage &Image); // assignment private: - const char * qr_text_ ; + const char * qr_text_ = NULL ; }; class QRCodeView : public View { @@ -74,13 +77,13 @@ private: { 50, 100, 100, 100 } }; - Text text_qr { - { 0 * 8, 10 * 16, 32 * 8, 1 * 8 }, - "-" - }; + //Text text_qr { + // { 0 * 8, 10 * 16, 32 * 8, 1 * 8 }, + // "-" + //}; Button button_close { - { 9 * 8, 15 * 16, 12 * 8, 3 * 16 }, + { 9 * 8, 31 * 8, 12 * 8, 3 * 16 }, "Back" }; }; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 435a7b73..9d310a62 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -464,8 +464,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(); } }, @@ -485,16 +488,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(); } }, @@ -519,17 +525,20 @@ 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(); } }, + { "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(); } }, { "Signal gen", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push(); } }, //{ "Tone search", ui::Color::dark_grey(), nullptr, [&nav](){ nav.push(); } }, - { "Wave viewer", ui::Color::yellow(), &bitmap_icon_soundboard, [&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 } @@ -553,12 +562,12 @@ SystemMenuView::SystemMenuView(NavigationView& nav) { { "Transmit", ui::Color::cyan(), &bitmap_icon_transmit, [&nav](){ nav.push(); } }, { "Capture", ui::Color::red(), &bitmap_icon_capture, [&nav](){ nav.push(); } }, { "Replay", ui::Color::green(), &bitmap_icon_replay, [&nav](){ nav.push(); } }, - { "Calls", ui::Color::yellow(), &bitmap_icon_search, [&nav](){ nav.push(); } }, + { "Search", ui::Color::yellow(), &bitmap_icon_search, [&nav](){ nav.push(); } }, { "Scanner", ui::Color::yellow(), &bitmap_icon_scanner, [&nav](){ nav.push(); } }, { "Microphone", ui::Color::yellow(), &bitmap_icon_microphone,[&nav](){ nav.push(); } }, { "Looking Glass", ui::Color::yellow(), &bitmap_icon_looking, [&nav](){ nav.push(); } }, - { "Tools", ui::Color::cyan(), &bitmap_icon_utilities, [&nav](){ nav.push(); } }, - { "Options", ui::Color::cyan(), &bitmap_icon_setup, [&nav](){ nav.push(); } }, + { "Utilities", ui::Color::cyan(), &bitmap_icon_utilities, [&nav](){ nav.push(); } }, + { "Settings", ui::Color::cyan(), &bitmap_icon_setup, [&nav](){ nav.push(); } }, { "Debug", ui::Color::light_grey(), &bitmap_icon_debug, [&nav](){ nav.push(); } }, { "HackRF", ui::Color::cyan(), &bitmap_icon_hackrf, [this, &nav](){ hackrf_mode(nav); } }, //{ "About", ui::Color::cyan(), nullptr, [&nav](){ nav.push(); } } diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 68723744..d0e3b03f 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -248,14 +248,14 @@ namespace ui { public: ReceiversMenuView(NavigationView &nav); - std::string title() const override { return "Receivers"; }; + std::string title() const override { return "Receive"; }; }; class TransmittersMenuView : public BtnGridView { public: TransmittersMenuView(NavigationView &nav); - std::string title() const override { return "Transmitters"; }; + std::string title() const override { return "Transmit"; }; }; class UtilitiesMenuView : public BtnGridView diff --git a/firmware/application/ui_sd_card_debug.hpp b/firmware/application/ui_sd_card_debug.hpp index 170c2a68..56253c53 100644 --- a/firmware/application/ui_sd_card_debug.hpp +++ b/firmware/application/ui_sd_card_debug.hpp @@ -38,6 +38,8 @@ public: void focus() override; + std::string title() const override { return "SD Card"; }; + private: SignalToken sd_card_status_signal_token { }; diff --git a/firmware/baseband/dsp_hilbert.hpp b/firmware/baseband/dsp_hilbert.hpp index a4b56cd5..7687ccb3 100644 --- a/firmware/baseband/dsp_hilbert.hpp +++ b/firmware/baseband/dsp_hilbert.hpp @@ -35,8 +35,8 @@ public: private: uint8_t n = 0; - SOSFilter<5> sos_i; - SOSFilter<5> sos_q; + SOSFilter<5> sos_i = {}; + SOSFilter<5> sos_q = {}; }; } /* namespace dsp */ 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_adsbrx.cpp b/firmware/baseband/proc_adsbrx.cpp index faef978f..4520f1c9 100644 --- a/firmware/baseband/proc_adsbrx.cpp +++ b/firmware/baseband/proc_adsbrx.cpp @@ -120,7 +120,7 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) { // the high levels as signals can be out of phase so part of the // energy can be in the near samples int32_t thisAmp = (shifter[1] + shifter[3] + shifter[8] + shifter[10]); - int32_t high = thisAmp / 9; + uint32_t high = thisAmp / 9; if ( shifter[5] < high && shifter[6] < high && diff --git a/firmware/baseband/proc_aprsrx.hpp b/firmware/baseband/proc_aprsrx.hpp index 2d3c4568..9bcc4828 100644 --- a/firmware/baseband/proc_aprsrx.hpp +++ b/firmware/baseband/proc_aprsrx.hpp @@ -125,18 +125,18 @@ private: uint32_t sample_bits { 0 }; uint32_t phase { }, phase_inc { }; int32_t sample_mixed { }, prev_mixed { }, sample_filtered { }, prev_filtered { }; - uint8_t last_bit; - uint8_t ones_count = 0; + uint8_t last_bit = 0; + uint8_t ones_count = 0 ; uint8_t current_byte = 0; uint8_t byte_index = 0; uint8_t packet_buffer[256]; size_t packet_buffer_size = 0; bool configured { false }; - bool wait_start { }; - bool bit_value { }; + bool wait_start { 0 }; + bool bit_value { 0 }; - aprs::APRSPacket aprs_packet; + aprs::APRSPacket aprs_packet { }; void configure(const APRSRxConfigureMessage& message); void capture_config(const CaptureConfigMessage& message); 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 6220835c..175e53c7 100644 --- a/firmware/baseband/proc_mictx.hpp +++ b/firmware/baseband/proc_mictx.hpp @@ -49,9 +49,9 @@ private: }; AudioInput audio_input { }; - ToneGen tone_gen { }; - ToneGen beep_gen { }; - dsp::modulate::Modulator *modulator; + // 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 }; bool fm_enabled { true }; diff --git a/firmware/baseband/proc_pocsag.hpp b/firmware/baseband/proc_pocsag.hpp index f5f7ec14..f848e40e 100644 --- a/firmware/baseband/proc_pocsag.hpp +++ b/firmware/baseband/proc_pocsag.hpp @@ -68,6 +68,16 @@ public: delete[] m_lastVals; } + SmoothVals(const SmoothVals&) + { + + } + + SmoothVals & operator=(const SmoothVals&) + { + return *this ; + } + // -------------------------------------------------- // Set size of smoothing // -------------------------------------------------- @@ -154,7 +164,7 @@ private: dsp::decimate::FIRC16xR16x32Decim8 decim_1 { }; dsp::decimate::FIRAndDecimateComplex channel_filter { }; dsp::demodulate::FM demod { }; - SmoothVals smooth; + SmoothVals smooth = { }; AudioOutput audio_output { }; 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/acars_packet.cpp b/firmware/common/acars_packet.cpp index 2cf0366e..4a0e46bd 100644 --- a/firmware/common/acars_packet.cpp +++ b/firmware/common/acars_packet.cpp @@ -84,7 +84,7 @@ bool Packet::crc_ok() const { acars_fcs.process_byte(field_crc.read(i, 8)); } - return (acars_fcs.checksum() == field_crc.read(data_length(), fcs_length)); + return (acars_fcs.checksum() == (unsigned)field_crc.read(data_length(), fcs_length)); } size_t Packet::data_and_fcs_length() const { diff --git a/firmware/common/ais_packet.cpp b/firmware/common/ais_packet.cpp index 61fabd89..c6e7561f 100644 --- a/firmware/common/ais_packet.cpp +++ b/firmware/common/ais_packet.cpp @@ -191,7 +191,7 @@ bool Packet::crc_ok() const { ais_fcs.process_byte(field_crc.read(i, 8)); } - return (ais_fcs.checksum() == field_crc.read(data_length(), fcs_length)); + return (ais_fcs.checksum() == (unsigned)field_crc.read(data_length(), fcs_length)); } size_t Packet::data_and_fcs_length() const { 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/aprs_packet.hpp b/firmware/common/aprs_packet.hpp index e521a955..c7e7c1db 100644 --- a/firmware/common/aprs_packet.hpp +++ b/firmware/common/aprs_packet.hpp @@ -259,7 +259,7 @@ private: bool valid_checksum = false; uint8_t payload[256]; char address_buffer[15]; - uint8_t payload_size; + uint8_t payload_size = 0 ; Timestamp timestamp_ { }; float parse_lat_str_cmp(const std::string& lat_str){ diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 0fdada7d..35e2ad71 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -83,9 +83,6 @@ struct data_t { int32_t modem_baudrate; int32_t modem_repeat; - // Hardware - uint32_t hardware_config; - // Play dead unlock uint32_t playdead_magic; uint32_t playing_dead; @@ -98,6 +95,9 @@ struct data_t { uint32_t pocsag_ignore_address; int32_t tone_mix; + + // Hardware + uint32_t hardware_config; }; static_assert(sizeof(data_t) <= backup_ram.size(), "Persistent memory structure too large for VBAT-maintained region"); @@ -200,35 +200,31 @@ 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 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 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); @@ -266,6 +262,26 @@ uint32_t config_backlight_timer() { return timer_seconds[data->ui_config & 7]; //first three bits, 8 possible values } +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 d04b1239..03d5cc91 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -78,18 +78,28 @@ 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(); bool config_login(); bool config_speaker(); uint32_t config_backlight_timer(); +bool disable_touchscreen(); +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); void set_config_speaker(bool v); void set_config_backlight_timer(uint32_t i); +void set_disable_touchscreen(bool v); //uint8_t ui_config_textentry(); //void set_config_textentry(uint8_t new_value); diff --git a/firmware/common/tpms_packet.cpp b/firmware/common/tpms_packet.cpp index a2abaada..f81ef35a 100644 --- a/firmware/common/tpms_packet.cpp +++ b/firmware/common/tpms_packet.cpp @@ -40,7 +40,7 @@ Optional Packet::reading_fsk_19k2_schrader() const { case 64: return Reading { Reading::Type::FLM_64, - reader_.read(0, 32), + (uint32_t)reader_.read(0, 32), Pressure { static_cast(reader_.read(32, 8)) * 4 / 3 }, Temperature { static_cast(reader_.read(40, 8) & 0x7f) - 56 } }; @@ -48,7 +48,7 @@ Optional Packet::reading_fsk_19k2_schrader() const { case 72: return Reading { Reading::Type::FLM_72, - reader_.read(0, 32), + (uint32_t)reader_.read(0, 32), Pressure { static_cast(reader_.read(40, 8)) * 4 / 3 }, Temperature { static_cast(reader_.read(48, 8)) - 56 } }; @@ -56,7 +56,7 @@ Optional Packet::reading_fsk_19k2_schrader() const { case 80: return Reading { Reading::Type::FLM_80, - reader_.read(8, 32), + (uint32_t)reader_.read(8, 32), Pressure { static_cast(reader_.read(48, 8)) * 4 / 3 }, Temperature { static_cast(reader_.read(56, 8)) - 56 } }; @@ -85,7 +85,7 @@ Optional Packet::reading_ook_8k192_schrader() const { if( (checksum_calculated & 3) == 3 ) { return Reading { Reading::Type::Schrader, - reader_.read(3, 24), + (uint32_t)reader_.read(3, 24), Pressure { static_cast(reader_.read(27, 8)) * 4 / 3 }, { }, Flags { static_cast((flags << 4) | checksum) } @@ -122,7 +122,7 @@ Optional Packet::reading_ook_8k4_schrader() const { if( checksum_calculated == checksum ) { return Reading { Reading::Type::GMC_96, - id, + (uint32_t)id, Pressure { static_cast(value_1) * 4 / 3 }, Temperature { static_cast(value_0) - 56 } }; diff --git a/firmware/common/tpms_packet.hpp b/firmware/common/tpms_packet.hpp index 5ee3e02a..75ad0077 100644 --- a/firmware/common/tpms_packet.hpp +++ b/firmware/common/tpms_packet.hpp @@ -39,7 +39,7 @@ namespace tpms { using Flags = uint8_t; -enum SignalType : uint32_t { +enum SignalType { FSK_19k2_Schrader = 1, OOK_8k192_Schrader = 2, OOK_8k4_Schrader = 3, 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/graphics/icon_qr_code.png b/firmware/graphics/icon_qr_code.png new file mode 100755 index 00000000..c19e9bdb Binary files /dev/null and b/firmware/graphics/icon_qr_code.png differ diff --git a/firmware/tools/convert_C16_to_complex.grc b/firmware/tools/convert_C16_to_complex.grc new file mode 100644 index 00000000..a46b15f2 --- /dev/null +++ b/firmware/tools/convert_C16_to_complex.grc @@ -0,0 +1,117 @@ +options: + parameters: + author: '' + category: Custom + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: no_gui + hier_block_src_path: '.:' + id: top_block + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: run + sizing_mode: fixed + thread_safe_setters: '' + title: '' + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: blocks_file_sink_0 + id: blocks_file_sink + parameters: + affinity: '' + alias: '' + append: 'False' + comment: '' + file: /tmp/foo.cfile + type: complex + unbuffered: 'False' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 140.0] + rotation: 0 + state: enabled +- name: blocks_file_source_0 + id: blocks_file_source + parameters: + affinity: '' + alias: '' + begin_tag: pmt.PMT_NIL + comment: '' + file: Porpack_Capture.C16 + length: '0' + maxoutbuf: '0' + minoutbuf: '0' + offset: '0' + repeat: 'False' + type: short + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [64, 124.0] + rotation: 0 + state: enabled +- name: blocks_interleaved_short_to_complex_0 + id: blocks_interleaved_short_to_complex + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + swap: 'False' + vector_input: 'False' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [272, 156.0] + rotation: 0 + state: enabled +- name: blocks_multiply_const_vxx_0 + id: blocks_multiply_const_vxx + parameters: + affinity: '' + alias: '' + comment: '' + const: ' 1.0 / 32768.0' + maxoutbuf: '0' + minoutbuf: '0' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [448, 156.0] + rotation: 0 + state: true + +connections: +- [blocks_file_source_0, '0', blocks_interleaved_short_to_complex_0, '0'] +- [blocks_interleaved_short_to_complex_0, '0', blocks_multiply_const_vxx_0, '0'] +- [blocks_multiply_const_vxx_0, '0', blocks_file_sink_0, '0'] + +metadata: + file_format: 1 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