Persist audio (#1110)

* Add credits
* Persist audio, add volume to apps
* Remove comment
* Hack around apparent alignment problem
This commit is contained in:
Kyle Reed 2023-06-05 11:09:50 -07:00 committed by GitHub
parent 9c39061590
commit af448cf444
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 46 additions and 49 deletions

View File

@ -34,6 +34,7 @@ void AboutView::update() {
console.writeln("notpike,jLynx,zigad");
console.writeln("MichalLeonBorsuk,jimilinuxguy");
console.writeln("kallanreed,bernd-herzog");
console.writeln("NotherNgineer,zxkmm,u-foka");
console.writeln("");
break;

View File

@ -55,6 +55,7 @@ AFSKRxView::AFSKRxView(NavigationView& nav) {
&field_rf_amp,
&field_lna,
&field_vga,
&field_volume,
&field_frequency,
&check_log,
&text_debug,

View File

@ -79,6 +79,9 @@ class AFSKRxView : public View {
{21 * 8, 5, 6 * 8, 4},
};
AudioVolumeField field_volume{
{28 * 8, 0 * 16}};
FrequencyField field_frequency{
{0 * 8, 0 * 16},
};

View File

@ -86,6 +86,7 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect)
&field_rf_amp,
&field_lna,
&field_vga,
&field_volume,
&options_region,
&field_frequency,
&record_view,

View File

@ -207,6 +207,9 @@ class APRSRxView : public View {
{21 * 8, 5, 6 * 8, 4},
};
AudioVolumeField field_volume{
{28 * 8, 0 * 16}};
OptionsField options_region{
{0 * 8, 0 * 8},
3,

View File

@ -132,7 +132,7 @@ LevelView::LevelView(NavigationView& nav)
audio::output::stop();
} else if (v == 1) {
audio::output::start();
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // TODO: Needed?
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
} else {
}
};

View File

@ -146,7 +146,7 @@ void PlaylistView::toggle() {
track_number = 0;
playlist_db.clear();
playlist_masterdb.clear();
} else { // Thanks kallanreed for providing this logic!
} else {
total_tracks = 0;
track_number = 0;
playlist_db.clear();

View File

@ -182,7 +182,6 @@ bool ReconView::recon_load_config_from_sd() {
squelch = -14;
recon_match_mode = RECON_MATCH_CONTINUOUS;
wait = RECON_DEF_WAIT_DURATION;
volume = 40;
return false;
}
@ -221,11 +220,6 @@ bool ReconView::recon_load_config_from_sd() {
else
wait = RECON_DEF_WAIT_DURATION;
if (it > 7)
volume = strtoll(params[7].c_str(), nullptr, 10);
else
volume = 40;
return true;
}
@ -244,13 +238,12 @@ bool ReconView::recon_save_config_to_sd() {
settings_file.write_line(to_string_dec_int(squelch));
settings_file.write_line(to_string_dec_uint(recon_match_mode));
settings_file.write_line(to_string_dec_int(wait));
settings_file.write_line(to_string_dec_int(volume));
return true;
}
void ReconView::audio_output_start() {
audio::output::start();
receiver_model.set_headphone_volume(receiver_model.headphone_volume());
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
}
void ReconView::recon_redraw() {
@ -438,7 +431,6 @@ ReconView::ReconView(NavigationView& nav)
load_ranges = persistent_memory::recon_load_ranges();
load_hamradios = persistent_memory::recon_load_hamradios();
update_ranges = persistent_memory::recon_update_ranges_when_recon();
field_volume.set_value(volume);
if (sd_card_mounted) {
// load auto common app settings
auto rc = settings.load("recon", &app_settings);

View File

@ -149,7 +149,6 @@ class ReconView : public View {
bool scanner_mode{false};
bool manual_mode{false};
bool sd_card_mounted = false;
int32_t volume = 40;
int32_t stepper = 0;
int32_t index_stepper = 0;
int64_t freq = 0;

View File

@ -60,7 +60,7 @@
//#define SCREEN_H 320
// recon settings nb params
#define RECON_SETTINGS_NB_PARAMS 8
#define RECON_SETTINGS_NB_PARAMS 7
namespace ui {

View File

@ -119,15 +119,6 @@ void ReceiverModel::set_vga(int32_t v_db) {
update_vga();
}
/*int32_t ReceiverModel::tx_gain() const {
return tx_gain_db_;
}
void ReceiverModel::set_tx_gain(int32_t v_db) {
tx_gain_db_ = v_db;
update_tx_gain();
}*/
uint32_t ReceiverModel::sampling_rate() const {
return sampling_rate_;
}
@ -147,20 +138,20 @@ void ReceiverModel::set_modulation(const Mode v) {
}
volume_t ReceiverModel::headphone_volume() const {
return headphone_volume_;
return persistent_memory::headphone_volume();
}
void ReceiverModel::set_headphone_volume(volume_t v) {
headphone_volume_ = v;
persistent_memory::set_headphone_volume(v);
update_headphone_volume();
}
int32_t ReceiverModel::normalized_headphone_volume() const {
return (headphone_volume_ - audio::headphone::volume_range().max).decibel() + 99;
return (headphone_volume() - audio::headphone::volume_range().max).decibel() + 99;
}
void ReceiverModel::set_normalized_headphone_volume(int32_t v) {
// TODO: Linear map instead to ensure 0 is minimal value.
// TODO: Linear map instead to ensure 0 is minimal value or fix volume_range_t::normalize.
v = clip<int32_t>(v, 0, 99);
auto new_volume = volume_t::decibel(v - 99) + audio::headphone::volume_range().max;
set_headphone_volume(new_volume);
@ -183,13 +174,11 @@ void ReceiverModel::enable() {
update_rf_amp();
update_lna();
update_vga();
// update_tx_gain();
update_baseband_bandwidth();
update_sampling_rate();
update_modulation();
// TODO: would challenge if this should belong to the
// receiver_model namespace:
// TODO: maybe not the perfect place for this, but it's reasonable.
update_headphone_volume();
led_rx.on();
@ -241,10 +230,6 @@ void ReceiverModel::update_vga() {
radio::set_vga_gain(vga_gain_db_);
}
/*void ReceiverModel::update_tx_gain() {
radio::set_tx_gain(tx_gain_db_);
}*/
void ReceiverModel::set_am_configuration(const size_t n) {
if (n < am_configs.size()) {
am_config_index = n;
@ -277,7 +262,7 @@ void ReceiverModel::update_sampling_rate() {
}
void ReceiverModel::update_headphone_volume() {
audio::headphone::set_volume(headphone_volume_);
audio::headphone::set_volume(headphone_volume());
}
void ReceiverModel::update_modulation() {

View File

@ -61,10 +61,6 @@ class ReceiverModel {
int32_t vga() const;
void set_vga(int32_t v_db);
// TODO: Why does receiver need tx_gain?
// int32_t tx_gain() const;
// void set_tx_gain(int32_t v_db);
uint32_t sampling_rate() const;
void set_sampling_rate(uint32_t v);
@ -108,13 +104,11 @@ class ReceiverModel {
int32_t lna_gain_db_{32};
uint32_t baseband_bandwidth_{max283x::filter::bandwidth_minimum};
int32_t vga_gain_db_{32};
// int32_t tx_gain_db_{47};
Mode mode_{Mode::NarrowbandFMAudio};
uint32_t sampling_rate_{3072000};
size_t am_config_index = 0;
size_t nbfm_config_index = 0;
size_t wfm_config_index = 0;
volume_t headphone_volume_{-43.0_dB};
uint8_t squelch_level_{80};
int32_t tuning_offset();

View File

@ -22,6 +22,7 @@
#include "portapack_persistent_memory.hpp"
#include "audio.hpp"
#include "portapack.hpp"
#include "hal.h"
@ -75,7 +76,7 @@ constexpr clkout_freq_range_t clkout_freq_range{10, 60000};
constexpr uint32_t clkout_freq_reset_value{10000};
enum data_structure_version_enum : uint32_t {
VERSION_CURRENT = 0x10000002,
VERSION_CURRENT = 0x10000003,
};
static const uint32_t TOUCH_CALIBRATION_MAGIC = 0x074af82f;
@ -305,6 +306,9 @@ struct data_t {
// Rotary encoder dial sensitivity (encoder.cpp/hpp)
uint8_t encoder_dial_sensitivity;
// Headphone volume in centibels.
int32_t headphone_volume_cb;
constexpr data_t()
: structure_version(data_structure_version_enum::VERSION_CURRENT),
tuned_frequency(tuned_frequency_reset_value),
@ -341,7 +345,8 @@ struct data_t {
updown_frequency_rx_correction(0),
frequency_tx_correction(0),
updown_frequency_tx_correction(0),
encoder_dial_sensitivity(0) {
encoder_dial_sensitivity(0),
headphone_volume_cb(-600) {
}
};
@ -423,6 +428,9 @@ namespace cache {
void defaults() {
cached_backup_ram = backup_ram_t();
*data = data_t(); // This is a workaround for apparently alignment issue
// that is causing backup_ram_t's block copy to be
// misaligned. This force sets values through the struct.
// defaults values for recon app
set_recon_autosave_freqs(false);
@ -469,6 +477,17 @@ void set_tuned_frequency(const rf::Frequency new_value) {
data->tuned_frequency = rf::tuning_range.clip(new_value);
}
volume_t headphone_volume() {
auto volume = volume_t::centibel(data->headphone_volume_cb);
volume = audio::headphone::volume_range().limit(volume);
return volume;
}
void set_headphone_volume(volume_t new_value) {
new_value = audio::headphone::volume_range().limit(new_value);
data->headphone_volume_cb = new_value.centibel();
}
ppb_t correction_ppb() {
ppb_range.reset_if_outside(data->correction_ppb, ppb_reset_value);
return data->correction_ppb;

View File

@ -31,6 +31,7 @@
#include "touch.hpp"
#include "modems.hpp"
#include "serializer.hpp"
#include "volume.hpp"
// persistant memory from/to sdcard flag file
#define PMEM_FILEFLAG "/SETTINGS/PMEM_FILEFLAG"
@ -132,6 +133,9 @@ using ppb_t = int32_t;
rf::Frequency tuned_frequency();
void set_tuned_frequency(const rf::Frequency new_value);
volume_t headphone_volume();
void set_headphone_volume(volume_t new_value);
ppb_t correction_ppb();
void set_correction_ppb(const ppb_t new_value);

View File

@ -23,6 +23,7 @@
#define __VOLUME_H__
#include <cstdint>
#include "utility.hpp"
class volume_t {
public:
@ -89,13 +90,7 @@ struct volume_range_t {
volume_t max;
volume_t limit(const volume_t value) const {
if (value < min) {
return min;
}
if (value > max) {
return max;
}
return value;
return clip(value, min, max);
}
volume_t normalize(const volume_t value) const {