Compare commits

...

5 Commits

Author SHA1 Message Date
Brumi-2021 a1496c1b79 Allowing to hear Mic at TX time with Receiver ON (#1522) 2023-10-22 01:13:32 +02:00
Brumi-2021 1b73a138b6 Mic to hp refactoring (#1521)
* Refactoring previous "Hear Mic" PR

* Missed file
2023-10-21 17:31:17 +02:00
Brumi-2021 efcedd9005 Add "Hear Mic" feature to the Mic App (#1518)
* Add "Hear Mic" feature to the Mic App

* Following consensus change about ternary operators
2023-10-20 18:43:22 -05:00
Mark Thompson 86d4b17257 Simple amplification option in IQ Trim app (#1506)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2023-10-19 20:14:25 +02:00
Mark Thompson f6a437f7fb Create SETTINGS folder if one does not exist (#1512)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2023-10-19 20:09:49 +02:00
16 changed files with 226 additions and 31 deletions
+1
View File
@@ -156,6 +156,7 @@ bool save_settings(std::string_view store_name, const SettingBindings& bindings)
File f;
auto path = get_settings_path(std::string{store_name});
make_new_directory(SETTINGS_DIR);
auto error = f.create(path);
if (error)
return false;
+3
View File
@@ -36,6 +36,9 @@
#include "max283x.hpp"
#include "string_format.hpp"
// Folder to store app settings, pmem_fileflag, and date_fileflag
#define SETTINGS_DIR u"/SETTINGS"
// Bring in the string_view literal.
using std::literals::operator""sv;
+19 -2
View File
@@ -40,6 +40,7 @@ IQTrimView::IQTrimView(NavigationView& nav)
&text_samples,
&text_max,
&field_cutoff,
&field_amplify,
&button_trim,
});
@@ -72,6 +73,11 @@ IQTrimView::IQTrimView(NavigationView& nav)
refresh_ui();
};
field_amplify.set_value(1); // 1X is default (no amplification)
field_amplify.on_change = [this](int32_t) {
refresh_ui();
};
button_trim.on_select = [this](Button&) {
if (trim_capture()) {
profile_capture();
@@ -133,7 +139,18 @@ void IQTrimView::focus() {
void IQTrimView::refresh_ui() {
field_path.set_text(path_.filename().string());
text_samples.set(to_string_dec_uint(info_->sample_count));
text_max.set(to_string_dec_uint(info_->max_power));
// show max power after amplification applied
uint64_t power_amp = field_amplify.value() * field_amplify.value() * field_amplify.value() * field_amplify.value();
text_max.set(to_string_dec_uint(info_->max_power * power_amp));
// show max power in red if amplification is too high, causing clipping
uint32_t clipping_limit = (fs::capture_file_sample_size(path_) == sizeof(complex8_t)) ? 0x80 : 0x8000;
if ((field_amplify.value() * info_->max_iq) > clipping_limit)
text_max.set_style(&Styles::red);
else
text_max.set_style(&Styles::light_grey);
set_dirty();
}
@@ -191,7 +208,7 @@ bool IQTrimView::trim_capture() {
}
progress_ui.show_trimming();
trimmed = iq::trim_capture_with_range(path_, trim_range, progress_ui.get_callback());
trimmed = iq::trim_capture_with_range(path_, trim_range, progress_ui.get_callback(), field_amplify.value());
progress_ui.clear();
if (!trimmed)
+10 -1
View File
@@ -107,6 +107,8 @@ class IQTrimView : public View {
{{0 * 8, 9 * 16}, "Max Pwr:", Color::light_grey()},
{{0 * 8, 10 * 16}, "Cutoff :", Color::light_grey()},
{{12 * 8, 10 * 16}, "%", Color::light_grey()},
{{0 * 8, 12 * 16}, "Amplify:", Color::light_grey()},
{{10 * 8, 12 * 16}, "x", Color::light_grey()},
};
TextField field_path{
@@ -135,7 +137,7 @@ class IQTrimView : public View {
"0"};
Text text_max{
{9 * 8, 9 * 16, 10 * 8, 1 * 16},
{9 * 8, 9 * 16, 20 * 8, 1 * 16},
"0"};
NumberField field_cutoff{
@@ -145,6 +147,13 @@ class IQTrimView : public View {
1,
' '};
NumberField field_amplify{
{9 * 8, 12 * 16},
1,
{1, 9},
1,
' '};
Button button_trim{
{20 * 8, 16 * 16, 8 * 8, 2 * 16},
"Trim"};
+34 -11
View File
@@ -101,8 +101,11 @@ void MicTXView::set_tx(bool enable) {
transmitting = false;
configure_baseband();
transmitter_model.disable();
if (rx_enabled) // If audio RX is enabled and we've been transmitting
rxaudio(true); // Turn back on audio RX
if (rx_enabled) { // If audio RX is enabled and we've been transmitting
rxaudio(true); // Turn back on audio RX
vumeter.set_value(0); // Reset vumeter
vumeter.dirty(); // Force to refresh vumeter.
}
}
}
}
@@ -183,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_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // set up ALC mode (AK4951) or set up mic_boost ON/OFF (WM8731). and the check box "Hear Mic"
portapack::pin_i2s0_rx_sda.mode(3);
configure_baseband();
}
@@ -215,6 +218,7 @@ MicTXView::MicTXView(
&field_frequency,
&options_tone_key,
&check_rogerbeep,
&check_mic_to_HP, // check box to activate "hear mic"
&check_common_freq_tx_rx, // added to handle common or separate freq- TX/RX
&check_rxactive,
&field_volume,
@@ -242,6 +246,7 @@ MicTXView::MicTXView(
&field_frequency,
&options_tone_key,
&check_rogerbeep,
&check_mic_to_HP, // check box to activate "hear mic"
&check_common_freq_tx_rx, // added to handle common or separate freq- TX/RX
&check_rxactive,
&field_volume,
@@ -285,17 +290,17 @@ MicTXView::MicTXView(
shift_bits_s16 = 6; // -08 dBs respect ref level, (when +20dB's boost OFF)
break; // now mic-boost off (+00dBs) shift bits (6) (+0+12dB's)=12 dBs => -08dB's respect ref.
}
ak4951_alc_and_wm8731_boost_GUI = v; // 0..4, WM8731_boost dB's options, (combination boost on/off, and effective gain in captured data >>x)
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (WM8731), set up the proper wm_boost on/off, 0..4 (0,1) boost_on, (2,3,4) boost_off
configure_baseband(); // to update in real time, sending msg, var-parameters >>shift_bits FM msg, to audio_tx from M0 to M4 Proc -
ak4951_alc_and_wm8731_boost_GUI = v; // 0..4, WM8731_boost dB's options, (combination boost on/off, and effective gain in captured data >>x)
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // Detected (WM8731), set up the proper wm_boost on/off, 0..4 (0,1) boost_on, (2,3,4) boost_off,and the check box "Hear Mic"
configure_baseband(); // to update in real time, sending msg, var-parameters >>shift_bits FM msg, to audio_tx from M0 to M4 Proc -
};
options_wm8731_boost_mode.set_selected_index(3); // preset GUI index 3 as default WM -> -02 dB's.
} else {
shift_bits_s16 = 8; // Initialized default fixed >>8_FM for FM tx mod, shift audio data for AK4951, using top 8 bits s16 data (>>8)
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
ak4951_alc_and_wm8731_boost_GUI = v; // 0..11, AK4951 Mic -Automatic volume Level Control options,
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (AK4951) ==> Set up proper ALC mode from 0..11 options
configure_baseband(); // sending fixed >>8_FM, var-parameters msg, to audiotx from this M0 to M4 process.
ak4951_alc_and_wm8731_boost_GUI = v; // 0..11, AK4951 Mic -Automatic volume Level Control options,
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // Detected (AK4951) ==> Set up proper ALC mode from 0..11 options, and the check box "Hear Mic"
configure_baseband(); // sending fixed >>8_FM, var-parameters msg, to audiotx from this M0 to M4 process.
};
}
@@ -475,6 +480,20 @@ MicTXView::MicTXView(
rogerbeep_enabled = v;
};
check_mic_to_HP.on_select = [this](Checkbox&, bool v) {
mic_to_HP_enabled = v;
if (mic_to_HP_enabled)
audio::input::loopback_mic_to_hp_enable();
else
audio::input::loopback_mic_to_hp_disable();
if (mic_to_HP_enabled) { // When user click to "hear mic to HP", we will select the higher acoustic sound Option MODE ALC or BOOST-
if (audio::debug::codec_name() == "WM8731") {
options_wm8731_boost_mode.set_selected_index(0); // In WM we always go to Boost +12 dBs respect reference level
} else if (ak4951_alc_and_wm8731_boost_GUI == 0) // In AK we are changing only that ALC index =0, because in that option, there is no sound.
options_ak4951_alc_mode.set_selected_index(1); // alc_mode =0 , means no ALC,no DIGITAL filter block (by passed), and that mode has no loopback mode.
}
};
check_common_freq_tx_rx.on_select = [this](Checkbox&, bool v) {
bool_same_F_tx_rx_enabled = v;
field_rxfrequency.hidden(v); // Hide or show separated freq RX field. (When no hide user can enter down indep. freq for RX)
@@ -501,8 +520,12 @@ MicTXView::MicTXView(
check_rxactive.on_select = [this](Checkbox&, bool v) {
// vumeter.set_value(0); //Start with a clean vumeter
rx_enabled = v;
check_mic_to_HP.hidden(rx_enabled); // Togle Hide / show "Hear Mic" checkbox depending if we activate or not the receiver. (if RX on => no visible "Mic Hear" option)
if ((rx_enabled) && (transmitting))
check_mic_to_HP.set_value(transmitting); // Once we activate the "Rx audio" in reception time we disable "Hear Mic", but we allow it again in TX time.
// check_va.hidden(v); //Hide or show voice activation
rxaudio(v); // Activate-Deactivate audio rx accordingly
rxaudio(v); // Activate-Deactivate audio RX (receiver) accordingly
set_dirty(); // Refresh interface
};
@@ -602,7 +625,7 @@ MicTXView::MicTXView(
set_tx(false);
audio::set_rate(audio::Rate::Hz_24000);
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
audio::input::start(ak4951_alc_and_wm8731_boost_GUI, mic_to_HP_enabled); // set up ALC mode (AK4951) or set up mic_boost ON/OFF (WM8731). and the check box "Hear Mic"
}
MicTXView::MicTXView(
+7
View File
@@ -94,6 +94,7 @@ class MicTXView : public View {
bool va_enabled{false};
bool ptt_enabled{true};
bool rogerbeep_enabled{false};
bool mic_to_HP_enabled{false};
bool bool_same_F_tx_rx_enabled{false};
bool rx_enabled{false};
uint32_t tone_key_index{};
@@ -277,6 +278,12 @@ class MicTXView : public View {
"Roger beep",
false};
Checkbox check_mic_to_HP{
{18 * 8, (14 * 8) + 4},
10,
"Hear Mic",
false};
Checkbox check_rxactive{
{3 * 8, (21 * 8) - 7},
8, // it was 18, but if it is string size should be 8
+10 -2
View File
@@ -198,8 +198,8 @@ void update_audio_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(int8_t alc_mode, bool mic_to_HP_enabled) {
audio_codec->microphone_enable(alc_mode, mic_to_HP_enabled); // added user-GUI selection for AK4951, ALC mode parameter. and the check box "Hear Mic"
i2s::i2s0::rx_start();
}
@@ -208,6 +208,14 @@ void stop() {
audio_codec->microphone_disable();
}
void loopback_mic_to_hp_enable() {
audio_codec->microphone_to_HP_enable();
}
void loopback_mic_to_hp_disable() {
audio_codec->microphone_to_HP_disable();
}
} /* namespace input */
namespace headphone {
+8 -2
View File
@@ -50,9 +50,12 @@ class Codec {
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(int8_t alc_mode, bool mic_to_HP_enabled) = 0; // added user-GUI AK4951 ,selected ALC mode.
virtual void microphone_disable() = 0;
virtual void microphone_to_HP_enable() = 0;
virtual void microphone_to_HP_disable() = 0;
virtual size_t reg_count() const = 0;
virtual size_t reg_bits() const = 0;
virtual uint32_t reg_read(const size_t register_number) = 0;
@@ -76,9 +79,12 @@ void update_audio_mute();
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(int8_t alc_mode, bool mic_to_HP_enabled); // added parameters -GUI select AK4951-ALC mode for config mic path,(recording mode),and the check box "Hear Mic"
void stop();
void loopback_mic_to_hp_enable();
void loopback_mic_to_hp_disable();
} /* namespace input */
namespace headphone {
+54 -3
View File
@@ -36,6 +36,13 @@ uint32_t power(T value) {
return (real * real) + (imag * imag);
}
template <typename T>
uint32_t iq_max(T value) {
auto real = abs(value.real());
auto imag = abs(value.imag());
return (real > imag) ? real : imag;
}
/* Collects capture file metadata and sample power buckets. */
template <typename T>
Optional<CaptureInfo> profile_capture(
@@ -51,7 +58,8 @@ Optional<CaptureInfo> profile_capture(
.file_size = f.size(),
.sample_count = f.size() / sizeof(T),
.sample_size = sizeof(T),
.max_power = 0};
.max_power = 0,
.max_iq = 0};
auto profile_samples = buckets.size * samples_per_bucket;
auto sample_interval = info.sample_count / profile_samples;
@@ -67,8 +75,11 @@ Optional<CaptureInfo> profile_capture(
if (*result != info.sample_size)
break; // EOF
auto mag_squared = power(value);
auto max_iq = iq_max(value);
if (max_iq > info.max_iq)
info.max_iq = max_iq;
auto mag_squared = power(value);
if (mag_squared > info.max_power)
info.max_power = mag_squared;
@@ -133,13 +144,50 @@ TrimRange compute_trim_range(
info.sample_size};
}
void amplify_iq_buffer(uint8_t* buffer, uint32_t length, uint32_t amplification, uint8_t sample_size) {
uint32_t mult_count = length / sample_size / 2;
switch (sample_size) {
case sizeof(complex16_t): {
int16_t* buf_ptr = (int16_t*)buffer;
for (uint32_t i = 0; i < mult_count; i++) {
int32_t val = *buf_ptr * amplification;
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
*buf_ptr++ = val;
}
break;
}
case sizeof(complex8_t): {
int8_t* buf_ptr = (int8_t*)buffer;
for (uint32_t i = 0; i < mult_count; i++) {
int32_t val = *buf_ptr * amplification;
if (val > 0x7F)
val = 0x7F;
else if (val < -0x7F)
val = -0x7F;
*buf_ptr++ = val;
}
break;
}
default:
break;
}
}
bool trim_capture_with_range(
const fs::path& path,
TrimRange range,
const std::function<void(uint8_t)>& on_progress) {
const std::function<void(uint8_t)>& on_progress,
const uint32_t amplification) {
constexpr size_t buffer_size = std::filesystem::max_file_block_size;
uint8_t buffer[buffer_size];
auto temp_path = path + u"-tmp";
auto sample_size = fs::capture_file_sample_size(path);
// end_sample is the first sample to _not_ include.
auto start_byte = range.start_sample * range.sample_size;
@@ -168,6 +216,9 @@ bool trim_capture_with_range(
auto remaining = length - processed;
auto to_write = std::min(remaining, *result);
if (amplification > 1)
amplify_iq_buffer(buffer, to_write, amplification, sample_size);
result = dst->write(buffer, to_write);
if (result.is_error()) return false;
+10 -1
View File
@@ -37,6 +37,7 @@ struct CaptureInfo {
uint64_t sample_count;
uint8_t sample_size;
uint32_t max_power;
uint32_t max_iq;
};
/* Holds sample average power by bucket. */
@@ -82,11 +83,19 @@ TrimRange compute_trim_range(
const PowerBuckets& buckets,
uint8_t cutoff_percent);
/* Multiplies samples in an IQ buffer by amplification value */
void amplify_iq_buffer(
uint8_t* buffer,
uint32_t length,
uint32_t amplification,
uint8_t sample_size);
/* Trims the capture file with the specified range. */
bool trim_capture_with_range(
const std::filesystem::path& path,
TrimRange range,
const std::function<void(uint8_t)>& on_progress);
const std::function<void(uint8_t)>& on_progress,
const uint32_t amplification);
} // namespace iq
+1
View File
@@ -395,6 +395,7 @@ void SystemStatusView::rtc_battery_workaround() {
}
}
} else {
make_new_directory(SETTINGS_DIR);
make_new_file(DATE_FILEFLAG);
year = 1980;
+1 -1
View File
@@ -322,7 +322,7 @@ void RecordView::trim_capture() {
auto trim_range = iq::compute_trim_range(*info, power_buckets, 7);
trim_ui.show_trimming();
iq::trim_capture_with_range(trim_path, trim_range, trim_ui.get_callback());
iq::trim_capture_with_range(trim_path, trim_range, trim_ui.get_callback(), 1);
}
trim_ui.clear();
+38 -4
View File
@@ -224,7 +224,7 @@ void AK4951::speaker_disable() {
set_speaker_power(false);
}
void AK4951::microphone_enable(int8_t alc_mode) {
void AK4951::microphone_enable(int8_t alc_mode, bool mic_to_HP_enabled) {
// 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), ...)
@@ -279,7 +279,7 @@ void AK4951::microphone_enable(int8_t alc_mode) {
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.PMADR = 0; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management. (PMADL=1, PMADR=0) means MONO MIC input connected to Left pin.
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 )
@@ -461,7 +461,7 @@ void AK4951::microphone_enable(int8_t alc_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)
map.r.digital_filter_mode.PFDAC = 0b00; // (Input selector for DAC (initially 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)
@@ -501,10 +501,15 @@ void AK4951::microphone_enable(int8_t alc_mode) {
// 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.PMADR = 0; // ADC Rch = Rch input signal. Mic Amp Rch and ADC Rch Power Management. (PMADL=1, PMADR=0) means MONO MIC input connected to Left pin.
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 )
if (mic_to_HP_enabled)
microphone_to_HP_enable();
else
microphone_to_HP_disable();
// 1059/fs, 22ms @ 48kHz
chThdSleepMilliseconds(22);
}
@@ -522,8 +527,13 @@ 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.PMDAC = 0; // Pre-loaded power management DAC block OFF
update(Register::PowerManagement1);
map.r.power_management_2.PMHPL = 0; // Pre-loaded power management HP LEFT block OFF
map.r.power_management_2.PMHPR = 0; // Pre-loaded power management HP RIGHT block OFF
update(Register::PowerManagement2); // Deactivating the Power management of the HP L&R blocks.
map.r.alc_mode_control_1.ALC = 0; // original code , Restore , disable ALC block.
update(Register::ALCModeControl1);
@@ -560,6 +570,30 @@ void AK4951::microphone_disable() {
update(Register::DigitalFilterSelect3);
}
void AK4951::microphone_to_HP_enable() {
map.r.digital_filter_mode.PFDAC = 0b01; // (Input selector for DAC, audio Loopback Mode .
update(Register::DigitalFilterMode); // Writing the Audio Path , Audio mode path : Loopback Mode .
map.r.power_management_1.PMDAC = 1; // Pre-loaded power management DAC block ON
update(Register::PowerManagement1); // Activating the Power management of the DAC block for the loopback mode
map.r.power_management_2.PMHPL = 1; // Pre-loaded power management HP LEFT block ON
map.r.power_management_2.PMHPR = 1; // Pre-loaded power management HP RIGHT block ON
update(Register::PowerManagement2); // Activating the Power management of the HP L&R blocks.
}
void AK4951::microphone_to_HP_disable() {
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 , Audio mode path : Loopback Mode .
map.r.power_management_1.PMDAC = 0; // Pre-loaded power management DAC block OFF
update(Register::PowerManagement1); // Deactivating the Power management of the DAC block for the loopback mode
map.r.power_management_2.PMHPL = 0; // Pre-loaded power management HP LEFT block OFF
map.r.power_management_2.PMHPR = 0; // Pre-loaded power management HP RIGHT block OFF
update(Register::PowerManagement2); // Deactivating the Power management of the HP L&R blocks.
}
reg_t AK4951::read(const address_t reg_address) {
const std::array<uint8_t, 1> tx{reg_address};
std::array<uint8_t, 1> rx{0x00};
+4 -1
View File
@@ -844,9 +844,12 @@ class AK4951 : public audio::Codec {
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(int8_t alc_mode, bool mic_to_HP_enabled); // added user GUI parameter , to set up AK4951 ALC mode, and mic_to_HP_enabled to control "Hear to Mic"
void microphone_disable();
void microphone_to_HP_enable();
void microphone_to_HP_disable();
size_t reg_count() const override {
return asahi_kasei::ak4951::reg_count;
}
@@ -868,6 +868,8 @@ bool should_use_sdcard_for_pmem() {
int save_persistent_settings_to_file() {
File outfile;
make_new_directory(SETTINGS_DIR);
auto error = outfile.create(PMEM_SETTING_FILE);
if (error)
return false;
@@ -912,7 +914,9 @@ bool debug_dump() {
painter.draw_string({0, 320 - 16}, ui::Styles::red, "ERROR DUMPING " + filename.filename().string() + " !");
return false;
}
pmem_dump_file.write_line("FW version " VERSION_STRING);
pmem_dump_file.write_line("FW version: " VERSION_STRING);
pmem_dump_file.write_line("Ext APPS version req'd: 0x" + to_string_hex(VERSION_MD5));
pmem_dump_file.write_line("GCC version: " + to_string_dec_int(__GNUC__) + "." + to_string_dec_int(__GNUC_MINOR__) + "." + to_string_dec_int(__GNUC_PATCHLEVEL__));
// write persistent memory
pmem_dump_file.write_line("\n[Persistent Memory]");
+21 -2
View File
@@ -349,17 +349,36 @@ class WM8731 : public audio::Codec {
return false;
}
void microphone_enable(int8_t wm8731_boost_GUI) override {
void microphone_enable(int8_t wm8731_boost_GUI, bool mic_to_HP_enabled) override {
microphone_mute(true); // c/m to reduce "plop noise" when changing wm8731_boost_GUI.
// chThdSleepMilliseconds(20); // does not help to reduce the "plop noise"
microphone_boost((wm8731_boost_GUI < 2) ? 1 : 0); // 1 = Enable Boost (+20 dBs) . 0 = Disable Boost (0dBs).
chThdSleepMilliseconds(120); // >50 msegs, very effective , >100 msegs minor improvement ,120 msegs trade off speed .
microphone_mute(false);
// (void)alc_mode; In prev. fw version , when we did not use at all param., to avoid "unused warning" when compiling.)
if (mic_to_HP_enabled)
microphone_to_HP_enable();
else
microphone_to_HP_disable();
}
void microphone_disable() override {
// TODO: Implement
microphone_mute(true);
microphone_to_HP_disable();
}
void microphone_to_HP_enable() override {
map.r.analog_audio_path_control.sidetone = 1; // Side Tone Switch (Analogue) 1 = Enable Side Tone
map.r.analog_audio_path_control.sideatt = 0b00; // Side Tone Attenuation 00 = -6dB
write(Register::AnalogAudioPathControl);
headphone_enable();
}
void microphone_to_HP_disable() override {
map.r.analog_audio_path_control.sidetone = 0; // Side Tone Switch (Analogue) 0 = Disable Side Tone
map.r.analog_audio_path_control.sideatt = 0b11; // Side Tone Attenuation 11 = -15dB
write(Register::AnalogAudioPathControl);
}
void microphone_boost(const bool boost) {