Skip to content

Commit

Permalink
Merge pull request #443 from 4ms/cpu-overload-restart
Browse files Browse the repository at this point in the history
Audio overload causes a retry before stopping audio
  • Loading branch information
danngreen authored Dec 27, 2024
2 parents b846a53 + d5bd2e9 commit fcafa0a
Show file tree
Hide file tree
Showing 19 changed files with 386 additions and 195 deletions.
42 changes: 33 additions & 9 deletions firmware/src/audio/audio.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,28 +91,30 @@ AudioStream::AudioStream(PatchPlayer &patchplayer,
HWSemaphore<block == 0 ? ParamsBuf2Lock : ParamsBuf1Lock>::unlock();

// 71.2us w/both MIDIs
// alternating 44us/71.3us with jack sense in metamparams (why alternating?)
// alternating 44us/71.3us with jack sense in metaparams (why alternating?)
auto &params = cache_params(block);

if (is_playing_patch())
if (!overrun_handler.is_retrying() && is_playing_patch())
process(audio_blocks[1 - block], params);
else
process_nopatch(audio_blocks[1 - block], params);

return_cached_params(block);

load_measure.end_measurement();

if (load_measure.get_last_measurement_load_percent() >= 98) {
overrun_handler.start_retrying();
param_blocks[block].metaparams.audio_overruns = 63;
} else
param_blocks[block].metaparams.audio_overruns = 0;

// 3.5us w/both MIDIs
sync_params.write_sync(param_state, param_blocks[block].metaparams);
param_state.reset_change_flags();

update_audio_settings();

load_measure.end_measurement();
if (load_measure.get_last_measurement_load_percent() >= 98) {
output_fade_amt = 0.f;
patch_loader.notify_audio_overrun();
}

// Debug::Pin0::low();
};

Expand All @@ -124,12 +126,27 @@ AudioStream::AudioStream(PatchPlayer &patchplayer,
s.set_size(block_size_);
}

void AudioStream::step() {
player.update_patch();
}

void AudioStream::start() {
codec_.start();
if (ext_audio_connected)
codec_ext_.start();
}

void AudioStream::handle_overruns() {
if (overrun_handler.is_retrying()) {
if (overrun_handler.handle()) {
step();
} else {
patch_loader.notify_audio_overrun();
}
overrun_handler.reset();
}
}

AudioConf::SampleT AudioStream::get_audio_output(int output_id) {
float output_volts = player.get_panel_output(output_id) * output_fade_amt;
return MathTools::signed_saturate(cal.out_cal[output_id].adjust(output_volts), 24);
Expand All @@ -142,6 +159,11 @@ AudioConf::SampleT AudioStream::get_ext_audio_output(int output_id) {
}

bool AudioStream::is_playing_patch() {
// Don't allow anyone to stop the patch while we are retrying to recover from an overrun:
// because core 0 has a lock on the player
if (overrun_handler.is_retrying())
return true;

if (patch_loader.should_fade_down_audio()) {
output_fade_delta = -1.f / (sample_rate_ * 0.02f);
if (output_fade_amt <= 0.f) {
Expand Down Expand Up @@ -424,7 +446,9 @@ void AudioStream::set_block_spans() {
}

void AudioStream::update_audio_settings() {
auto [sample_rate, block_size] = patch_loader.get_audio_settings();
auto [sample_rate, block_size, max_retries] = patch_loader.get_audio_settings();

overrun_handler.set_max_retry(max_retries);

if (sample_rate != sample_rate_ || block_size != block_size_) {

Expand Down
5 changes: 5 additions & 0 deletions firmware/src/audio/audio.hh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "drivers/codec_PCM3168.hh"
#include "drivers/cycle_counter.hh"
#include "drivers/stm32xx.h"
#include "overrun_handler.hh"
#include "param_block.hh"
#include "params.hh"
#include "params_state.hh"
Expand Down Expand Up @@ -47,6 +48,8 @@ public:
void start_playing();
void process(CombinedAudioBlock &audio, ParamBlock &param_block);
uint32_t get_audio_errors();
void handle_overruns();
void step();

private:
SyncParams &sync_params;
Expand Down Expand Up @@ -82,6 +85,8 @@ private:

bool midi_last_connected = false;

AudioOverrunHandler overrun_handler;

AudioConf::SampleT get_audio_output(int output_id);
AudioConf::SampleT get_ext_audio_output(int output_id);
void set_input(int input_id, AudioConf::SampleT in);
Expand Down
49 changes: 49 additions & 0 deletions firmware/src/audio/overrun_handler.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once
#include "console/pr_dbg.hh"
#include "drivers/stm32xx.h"
#include <atomic>
#include <cstdint>

namespace MetaModule
{

struct AudioOverrunHandler {
void start_retrying() {
retrying = true;
}

bool is_retrying() const {
return retrying;
}

void reset() {
retrying = false;
}

void set_max_retry(uint32_t max_times) {
max_retries = max_times;
}

bool handle() {
// if we've gone 1 sec without overrunning, then consider this a new overrun
uint64_t tm = PL1_GetCurrentPhysicalValue();
if (tm - last_overrun < 2'400'000) {
overrun_count++;
} else {
last_overrun = tm;
pr_dbg("Reset count from %u\n", overrun_count);
overrun_count = 0;
}

return (overrun_count < max_retries);
}

private:
uint32_t overrun_count = 0;
uint64_t last_overrun = 0;
unsigned max_retries = 0;

// bool retrying = false;
std::atomic<bool> retrying = false;
};
} // namespace MetaModule
27 changes: 15 additions & 12 deletions firmware/src/core_a7/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,19 @@ void main() {
patch_mod_queue};

SharedMemoryS::ptrs = {
&StaticBuffers::param_blocks,
&StaticBuffers::virtdrive,
&StaticBuffers::icc_shared_message,
.param_block = &StaticBuffers::param_blocks,
.ramdrive = &StaticBuffers::virtdrive,
.icc_message = &StaticBuffers::icc_shared_message,
};

A7SharedMemoryS::ptrs = {
&patch_player,
&patch_playloader,
&file_storage_proxy,
&open_patches_manager,
&StaticBuffers::sync_params,
&patch_mod_queue,
&StaticBuffers::virtdrive,
.patch_player = &patch_player,
.patch_playloader = &patch_playloader,
.patch_storage = &file_storage_proxy,
.open_patch_manager = &open_patches_manager,
.sync_params = &StaticBuffers::sync_params,
.patch_mod_queue = &patch_mod_queue,
.ramdrive = &StaticBuffers::virtdrive,
};

{
Expand Down Expand Up @@ -109,7 +109,7 @@ void main() {
while (mdrivlib::HWSemaphore<AuxCoreReady>::is_locked() || mdrivlib::HWSemaphore<M4CoreReady>::is_locked())
;

// ~290ms until while loop
// ~290ms until while loop

#ifdef CPU_TEST_ALL_MODULES
mdrivlib::HWSemaphore<MainCoreReady>::lock();
Expand All @@ -119,7 +119,7 @@ void main() {
if (but0.is_on()) {
auto db = LoadTest::test_all_modules();
auto filedata = LoadTest::entries_to_csv(db);
FS::write_file(file_storage_proxy, filedata, {"cpu_test.csv", Volume::USB});
FS::write_file(file_storage_proxy, filedata, {.filename = "cpu_test.csv", .vol = Volume::USB});
}

mdrivlib::HWSemaphore<MainCoreReady>::unlock();
Expand All @@ -133,6 +133,9 @@ void main() {

while (true) {
__NOP();

audio.handle_overruns();

if (audio.get_audio_errors() > 0) {
pr_err("Audio error\n");
audio.start();
Expand Down
28 changes: 28 additions & 0 deletions firmware/src/gui/helpers/load_meter.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once
#include "delay.hh"
#include "gui/helpers/lv_helpers.hh"
#include "lvgl.h"
#include "metaparams.hh"

namespace MetaModule
{

inline void update_load_text(MetaParams const &metaparams, lv_obj_t *meter) {
if (metaparams.audio_overruns > 0) {
lv_obj_set_style_bg_color(meter, lv_color_hex(0xFF0000), LV_PART_MAIN);
lv_obj_set_style_bg_opa(meter, LV_OPA_100, LV_PART_MAIN);

lv_obj_set_style_text_color(meter, lv_color_white(), LV_PART_MAIN);

lv_label_set_text(meter, "OVER");

} else {
lv_label_set_text_fmt(meter, "%d%%", metaparams.audio_load);
lv_obj_set_style_text_color(meter, lv_color_hex(0xFD8B18), LV_PART_MAIN);
lv_obj_set_style_outline_opa(meter, LV_OPA_0, LV_PART_MAIN);
lv_obj_set_style_bg_opa(meter, LV_OPA_0, LV_PART_MAIN);
}
lv_show(meter);
}

} // namespace MetaModule
9 changes: 2 additions & 7 deletions firmware/src/gui/pages/main_menu.hh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "gui/helpers/load_meter.hh"
#include "gui/helpers/lv_helpers.hh"
#include "gui/pages/base.hh"
#include "gui/pages/make_cable.hh"
Expand Down Expand Up @@ -70,11 +71,7 @@ struct MainMenuPage : PageBase {
load_page(PageId::PatchView, {.patch_loc_hash = patches.get_view_patch_loc_hash()});
}

if (last_audio_load != metaparams.audio_load) {
last_audio_load = metaparams.audio_load;
lv_label_set_text_fmt(ui_MainMenuLoadMeter, "%d%%", metaparams.audio_load);
lv_show(ui_MainMenuLoadMeter);
};
update_load_text(metaparams, ui_MainMenuLoadMeter);
}

void blur() final {
Expand Down Expand Up @@ -123,8 +120,6 @@ private:
return;
page->load_page(PageId::SystemMenu, {});
}

unsigned last_audio_load = 0;
};

} // namespace MetaModule
3 changes: 2 additions & 1 deletion firmware/src/gui/pages/patch_selector.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include "fs/dir_entry_kind.hh"
#include "gui/helpers/dir_entry_info.hh"
#include "gui/helpers/load_meter.hh"
#include "gui/helpers/lv_helpers.hh"
#include "gui/helpers/lvgl_mem_helper.hh"
#include "gui/helpers/lvgl_string_helper.hh"
Expand Down Expand Up @@ -290,7 +291,7 @@ struct PatchSelectorPage : PageBase {
last_refresh_check_tm = now;
state = State::TryingToRequestPatchList;

lv_label_set_text_fmt(ui_LoadMeter, "%d%%", metaparams.audio_load);
update_load_text(metaparams, ui_LoadMeter);
}
} break;

Expand Down
11 changes: 3 additions & 8 deletions firmware/src/gui/pages/patch_view.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "gui/elements/redraw.hh"
#include "gui/elements/redraw_display.hh"
#include "gui/elements/redraw_light.hh"
#include "gui/helpers/load_meter.hh"
#include "gui/helpers/lv_helpers.hh"
#include "gui/pages/base.hh"
#include "gui/pages/cable_drawer.hh"
Expand Down Expand Up @@ -70,7 +71,7 @@ struct PatchViewPage : PageBase {
is_patch_playing = patch_is_playing(args.patch_loc_hash);

if (is_patch_playing && !patch_playloader.is_audio_muted()) {
lv_label_set_text_fmt(ui_LoadMeter2, "%d%%", metaparams.audio_load);
lv_label_set_text(ui_LoadMeter2, "");
lv_show(ui_LoadMeter2);
lv_obj_add_state(ui_PlayButton, LV_STATE_USER_2);
} else {
Expand Down Expand Up @@ -310,11 +311,7 @@ struct PatchViewPage : PageBase {
lv_obj_add_state(ui_PlayButton, LV_STATE_USER_2);
}

if (last_audio_load != metaparams.audio_load) {
last_audio_load = metaparams.audio_load;
lv_label_set_text_fmt(ui_LoadMeter2, "%d%%", metaparams.audio_load);
lv_show(ui_LoadMeter2);
}
update_load_text(metaparams, ui_LoadMeter2);

} else {
if (lv_obj_has_state(ui_PlayButton, LV_STATE_USER_2)) {
Expand Down Expand Up @@ -659,8 +656,6 @@ private:
PatchLocHash displayed_patch_loc_hash;
uint32_t patch_revision = 0xFFFFFFFF;

unsigned last_audio_load = 0;

struct focussed_context {
PatchViewPage *page;
uint32_t selected_module_id;
Expand Down
Loading

0 comments on commit fcafa0a

Please sign in to comment.