Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Knob Expander #412

Draft
wants to merge 64 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
1759dba
Fix ext audio codec sync setting
danngreen Oct 3, 2024
b6f07ab
Simply gate-in logic so params can be const in audio loop
danngreen Oct 3, 2024
3352616
Audio routes panel jackS 8-15 to expander output
danngreen Oct 3, 2024
9b51383
Cleanup naming in aux core
danngreen Oct 3, 2024
558d9d1
Jack ordering...
danngreen Oct 4, 2024
e43750d
Register audio expander status in singleton
danngreen Oct 4, 2024
cb8b61e
GUI can map to Exp audio jacks if exp is connected
danngreen Oct 4, 2024
243d993
Update CoreModules (audio expander defs/info)
danngreen Oct 5, 2024
8871648
Move audio expander defs to CoreModules
danngreen Oct 5, 2024
8e21708
Graphics for audio expander
danngreen Oct 5, 2024
063795d
Display expander input jack names
danngreen Oct 5, 2024
a442079
Audio sends expander inputs to patch player
danngreen Oct 5, 2024
6f539eb
Remove patchcv from metaparams. Comments
danngreen Oct 5, 2024
d6750cb
Simulator builds with expander support
danngreen Oct 6, 2024
d4171a6
Update CoreModules (rename MMAIO)
danngreen Oct 8, 2024
9030870
Update CoreModules (input jack names)
danngreen Oct 9, 2024
6a4c3cf
Add Button expander status to Expanders
danngreen Oct 9, 2024
97b64db
Audio passes button events to patch player
danngreen Oct 9, 2024
6fe6a4e
Patch Player uses large knob_conns array for all param mappings
danngreen Oct 9, 2024
23cb362
Fixes
danngreen Oct 9, 2024
3a6bb97
Update patch-serial (add mapping_ids.hh)
danngreen Oct 9, 2024
bcc8424
Add control expander
danngreen Oct 9, 2024
ab5cd03
Patch Player can create knob_conns for buttons
danngreen Oct 9, 2024
57623f5
Store address of button expanders
danngreen Oct 9, 2024
dc2de64
Replace SharedBusQueue (GPIO expander reader) with SensePinReader
danngreen Oct 9, 2024
c300dfa
Update CoreModules (button expander conf)
danngreen Oct 9, 2024
190caae
Button Expander artwork source file
danngreen Oct 10, 2024
aaac90c
Patch Player uses MappedKnobSmall (less RAM+cache thrashing)
danngreen Oct 10, 2024
dcba1d6
Button LED states pass from PatchPlayer->Audio->MetaParams->Controls-…
danngreen Oct 10, 2024
0b6babe
Clarify naming
danngreen Oct 10, 2024
d2b3efc
Update patch-serial: add LightMaps to patch data
danngreen Oct 10, 2024
3a8bd59
LightMaps=>MappedLghts
danngreen Oct 10, 2024
19e9198
Update CoreModules (button expander info files)
danngreen Oct 10, 2024
6041897
Keep track of number of button expanders in metaparams
danngreen Oct 11, 2024
3a81c31
Set LED turn-on threshold to 0.1
danngreen Oct 11, 2024
fc492fc
Update plugin-sdk (docs)
danngreen Oct 11, 2024
6057b9c
Update plugin-sdk (api-v1.4 merged)
danngreen Oct 11, 2024
45e5ffa
Merge branch 'main' into button-expander
danngreen Oct 11, 2024
472592c
Update mdrivlib (tla2528 WIP branch)
danngreen Oct 11, 2024
6644d35
Fix ICC name (updated in mdrivlib)
danngreen Oct 11, 2024
74c74bf
Generalize ControlExpanderManager, start to add KnobExpander
danngreen Oct 11, 2024
93bacf1
Update mdrivlib (registers for TLA2528)
danngreen Oct 12, 2024
5cf7669
Update CoreModules (knob expander defs)
danngreen Oct 13, 2024
6ca8fc9
Add Exp Knob data to MetaParams
danngreen Oct 13, 2024
b057239
Control Expander Manager reads all pots
danngreen Oct 13, 2024
156c438
Controls stores exp knob readings in metaparams
danngreen Oct 13, 2024
e2c0355
Disable oversampling for knob exp
danngreen Oct 13, 2024
dbf9c01
Audio passes knob expander values to patch player
danngreen Oct 13, 2024
c29c5c0
Update patch-serial (knob expander ids)
danngreen Oct 13, 2024
6dfb95c
Interpolate Expander knobs over block
danngreen Oct 13, 2024
16f95a5
Update mp1-boot conf (Freeze pin moved to debug header)
danngreen Oct 14, 2024
2a18940
Update mp1-boot (LEDs off during most of boot, blue for freeze jumper)
danngreen Oct 14, 2024
1c2697f
Cmake: build bootloader with new conf
danngreen Oct 14, 2024
23098e3
Option for debug pins to not overlap control expander pins
danngreen Oct 14, 2024
96575d0
Update mdrivlib (finished tla2528 driver)
danngreen Oct 14, 2024
4b4b8bc
Control expander manager reads all 8 pots per loop, oversamples
danngreen Oct 14, 2024
5de541c
Fix knob reading units
danngreen Oct 15, 2024
7a782a9
Read expanders then pause 10ms
danngreen Oct 15, 2024
2a4e59b
Controls interpolates exp pot readings, so does audio
danngreen Oct 16, 2024
e77a3e6
Fix default block size
danngreen Oct 17, 2024
e024452
Update mdrivlib (i2c eeprom driver)
danngreen Oct 17, 2024
969b369
Refactor CalibrationDataReader to take a generic raw data loader
danngreen Oct 17, 2024
118eac8
Audio expander calibration data loaded from eeprom on startup
danngreen Oct 17, 2024
a6a398b
Fix missing include
danngreen Oct 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions firmware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,15 @@ endif()

add_custom_target(
bootloader
COMMAND make --no-print-directory BOARD_CONF=../board_conf/mmp11_conf.hh ${BOOTLOADER_TOOLCHAIN_OPT}
COMMAND make --no-print-directory BOARD_CONF=../board_conf/mmp11_with_expanders_conf.hh ${BOOTLOADER_TOOLCHAIN_OPT}
COMMENT "Building MP1-Boot (FSBL)"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/bootloader/mp1-boot
VERBATIM
)

add_custom_target(
bootloader-dfu
COMMAND make --no-print-directory BOARD_CONF=board_conf/mmp11_conf.hh ${BOOTLOADER_TOOLCHAIN_OPT}
COMMAND make --no-print-directory BOARD_CONF=board_conf/mmp11_with_expanders_conf.hh ${BOOTLOADER_TOOLCHAIN_OPT}
COMMENT "Building DFU Bootloader"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/bootloader/mp1-usb-dfu
VERBATIM
Expand Down
46 changes: 46 additions & 0 deletions firmware/bootloader/board_conf/mmp11_with_expanders_conf.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once
#include "drivers/clocks.hh"
#include "drivers/i2c_conf.hh"
#include "drivers/leds.hh"

namespace Board
{

using RedLED = Led<GPIO::E, PinNum::_14, LedActive::Low>; // button LED red
using GreenLED = Led<GPIO::B, PinNum::_15, LedActive::Low>; // button LED green
using RedLED2 = RedLED;
using GreenLED2 = GreenLED;

using OrangeLED = RedLED2;
using BlueLED = Led<GPIO::A, PinNum::_9, LedActive::Low>; // button LED blue

// Boot Select pin: press Rotary encoder to select DFU USB
constexpr bool UseBootSelect = true;
constexpr PinConf BootSelectPin{GPIO::E, PinNum::_15};

// Freeze mode: jumper on debug header (left-most column)
constexpr bool UseFreezePin = true;
constexpr PinConf FreezePin{GPIO::D, PinNum::_3}; //DEBUG1 of debug header

constexpr uint32_t ConsoleUART = UART7_BASE;
constexpr PinConf UartRX{GPIO::B, PinNum::_3, PinAF::AF_13};
constexpr PinConf UartTX{GPIO::B, PinNum::_4, PinAF::AF_13};

namespace NORFlash
{
constexpr bool HasNORFlash = true;
constexpr PinConf d2{GPIO::F, PinNum::_7, PinAF::AF_9};
constexpr PinConf d3{GPIO::A, PinNum::_1, PinAF::AF_9};
} // namespace NORFlash

namespace PMIC
{
constexpr bool HasSTPMIC = false;
constexpr I2C_Config I2C_config{};
} // namespace PMIC

constexpr uint32_t HSE_Clock_Hz = 24000000;
constexpr uint32_t MPU_MHz = 800;
constexpr auto ClockType = SystemClocks::HSEClockSource::Resonator;

} // namespace Board
2 changes: 1 addition & 1 deletion firmware/bootloader/mp1-boot
Submodule mp1-boot updated 1 files
+7 −3 src/main.cc
1 change: 1 addition & 0 deletions firmware/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ add_executable(
${FWDIR}/src/gui/elements/element_name.cc
${FWDIR}/src/gui/slsexport/ui_local.cc
${FWDIR}/src/gui/fonts/fonts.cc
${FWDIR}/src/params/expanders.cc
#
${FWDIR}/src/dynload/dynloader.cc
${FWDIR}/metamodule-plugin-sdk/version.cc
Expand Down
107 changes: 95 additions & 12 deletions firmware/src/audio/audio.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "audio/audio.hh"
#include "CoreModules/hub/audio_expander_defs.hh"
#include "CoreModules/hub/knob_expander_defs.hh"
#include "audio/audio_test_signals.hh"
#include "calibrate/calibration_data_reader.hh"
#include "conf/audio_settings.hh"
#include "conf/hsem_conf.hh"
#include "conf/jack_sense_conf.hh"
Expand All @@ -8,6 +11,7 @@
#include "drivers/arch.hh"
#include "drivers/cache.hh"
#include "drivers/hsem.hh"
#include "expanders.hh"
#include "param_block.hh"
#include "patch_play/patch_mods.hh"
#include "patch_play/patch_player.hh"
Expand Down Expand Up @@ -54,12 +58,21 @@ AudioStream::AudioStream(PatchPlayer &patchplayer,
codec_.set_rx_buffer(audio_blocks[0].in_codec, block_size_);

if (codec_ext_.init() == CodecT::CODEC_NO_ERR) {
ext_cal.reset_to_default();
ext_audio_connected = true;
codec_ext_.set_tx_buffer(audio_blocks[0].out_ext_codec, block_size_);
codec_ext_.set_rx_buffer(audio_blocks[0].in_ext_codec, block_size_);
Expanders::ext_audio_found(true);

if (!CalibrationDataReader::read_calibration(&ext_cal, Hardware::codec_ext_memory, 0)) {
ext_cal.reset_to_default();
Hardware::codec_ext_memory.write(ext_cal);
}

pr_info("Audio Expander detected\n");
} else {
ext_audio_connected = false;
Expanders::ext_audio_found(false);
pr_info("No Audio Expander detected\n");
}

Expand Down Expand Up @@ -105,6 +118,11 @@ AudioStream::AudioStream(PatchPlayer &patchplayer,

for (auto &s : smoothed_ins)
s.set_size(block_size_);

for (auto &expander : exp_knobs) {
for (auto &knobs : expander)
knobs.set_num_updates(block_size_);
}
}

void AudioStream::start() {
Expand All @@ -118,6 +136,12 @@ AudioConf::SampleT AudioStream::get_audio_output(int output_id) {
return MathTools::signed_saturate(cal.out_cal[output_id].adjust(output_volts), 24);
}

AudioConf::SampleT AudioStream::get_ext_audio_output(int output_id) {
output_id = AudioExpander::out_order[output_id];
float output_volts = player.get_panel_output(output_id + PanelDef::NumAudioOut) * output_fade_amt;
return MathTools::signed_saturate(ext_cal.out_cal[output_id].adjust(output_volts), 24);
}

bool AudioStream::is_playing_patch() {
if (patch_loader.should_fade_down_audio()) {
output_fade_delta = -1.f / (sample_rate_ * 0.02f);
Expand Down Expand Up @@ -153,16 +177,20 @@ void AudioStream::handle_patch_just_loaded() {
void AudioStream::process(CombinedAudioBlock &audio_block, ParamBlock &param_block) {
handle_patch_mod_queue();

// TODO: handle second codec
if (ext_audio_connected)
AudioTestSignal::passthrough(audio_block.in_ext_codec, audio_block.out_ext_codec);

param_block.metaparams.midi_poly_chans = player.get_midi_poly_num();

// for (auto [in, out, params] : zip(audio_block.in_codec, audio_block.out_codec, param_block.params)) {
for (auto exp_i = 0u; exp_i < param_block.metaparams.num_knob_expanders_found; exp_i++) {
for (auto knob_i = 0u; knob_i < param_block.metaparams.exp_knobs[exp_i].size(); knob_i++) {
float reading = param_block.metaparams.exp_knobs[exp_i][knob_i];
exp_knobs[exp_i][knob_i].set_new_value(reading);
}
}

for (auto idx = 0u; auto const &in : audio_block.in_codec) {
auto &out = audio_block.out_codec[idx];
auto &params = param_block.params[idx];
auto const &params = param_block.params[idx];
auto &ext_out = audio_block.out_ext_codec[idx];
auto const &ext_in = audio_block.out_ext_codec[idx];
idx++;

// Audio inputs
Expand All @@ -176,19 +204,33 @@ void AudioStream::process(CombinedAudioBlock &audio_block, ParamBlock &param_blo

player.set_panel_input(panel_jack_i, calibrated_input);

// Send smoothed sigals to other core via metaparams
// Send smoothed sigals to other core
smoothed_ins[panel_jack_i].add_val(calibrated_input);
}

if (ext_audio_connected) {
for (auto [panel_jack_i, inchan] : zip(AudioExpander::in_order, ext_in.chan)) {

// Skip unpatched jacks
if (!AudioExpander::jack_is_patched(param_state.jack_senses, panel_jack_i))
continue;

float calibrated_input = ext_cal.in_cal[panel_jack_i].adjust(AudioInFrame::sign_extend(inchan));

player.set_panel_input(panel_jack_i, calibrated_input);
}
}

// Gate inputs
for (auto [i, gatein, sync_gatein] : countzip(params.gate_ins, param_state.gate_ins)) {

if (!jack_is_patched(param_state.jack_senses, i + FirstGateInput)) {
gatein = false;
} else
bool gate = false;
if (jack_is_patched(param_state.jack_senses, i + FirstGateInput)) {
gate = gatein;
player.set_panel_input(i + FirstGateInput, gatein ? 8.f : 0.f);
}

sync_gatein.register_state(gatein);
sync_gatein.register_state(gate);
}

// Pass Knob values to modules
Expand All @@ -208,6 +250,28 @@ void AudioStream::process(CombinedAudioBlock &audio_block, ParamBlock &param_blo

for (auto [i, outchan] : countzip(out.chan))
outchan = get_audio_output(i);

// Ext audio modules:
if (ext_audio_connected) {
for (auto [i, extoutchan] : countzip(ext_out.chan))
extoutchan = get_ext_audio_output(i);
}

// Button Expanders:
if (param_block.metaparams.num_button_expanders_found > 0) {
handle_button_events(param_block.metaparams.ext_buttons_pressed_event, 1.f);
handle_button_events(param_block.metaparams.ext_buttons_released_event, 0.f);

param_block.metaparams.button_leds = player.get_button_leds();
}

unsigned param_id = FirstExpKnob;
for (auto exp_i = 0u; exp_i < param_block.metaparams.num_knob_expanders_found; exp_i++) {
for (auto &knob : exp_knobs[exp_i]) {
player.set_panel_param(param_id, knob.next());
param_id++;
}
}
}

for (auto [m, s] : zip(param_block.metaparams.ins, smoothed_ins)) {
Expand All @@ -221,7 +285,6 @@ void AudioStream::process(CombinedAudioBlock &audio_block, ParamBlock &param_blo
void AudioStream::process_nopatch(CombinedAudioBlock &audio_block, ParamBlock &param_block) {
param_state.jack_senses = param_block.params[0].jack_senses;

// for (auto [in, out, params] : zip(audio_block.in_codec, audio_block.out_codec, param_block.params)) {
for (auto idx = 0u; auto const &in : audio_block.in_codec) {
auto &out = audio_block.out_codec[idx];
auto &params = param_block.params[idx];
Expand Down Expand Up @@ -296,6 +359,16 @@ void AudioStream::handle_midi(bool is_connected, Midi::Event const &event, unsig
}
}

void AudioStream::handle_button_events(uint32_t event_bitmask, bool pressed) {
unsigned i = 0;
while (event_bitmask) {
if (event_bitmask & 0b1) {
player.set_panel_param(i + FirstButton, pressed ? 1 : 0);
}
event_bitmask >>= 1;
i++;
}
}
void AudioStream::propagate_sense_pins(Params &params) {
for (unsigned i = 0; auto &plug_detect : plug_detects) {
bool sense = jack_is_patched(params.jack_senses, i);
Expand Down Expand Up @@ -360,6 +433,9 @@ void AudioStream::return_cached_params(unsigned block) {

// copy midi_poly_chans back so Controls can read it
param_blocks[block].metaparams.midi_poly_chans = local_params.metaparams.midi_poly_chans;

// copy button_leds back so Controls can light them
param_blocks[block].metaparams.button_leds = local_params.metaparams.button_leds;
}

void AudioStream::set_block_spans() {
Expand Down Expand Up @@ -392,11 +468,18 @@ void AudioStream::update_audio_settings() {

if (block_size != block_size_) {
block_size_ = block_size;
param_blocks[0].metaparams.block_size = block_size;
param_blocks[1].metaparams.block_size = block_size;

set_block_spans();

for (auto &s : smoothed_ins)
s.set_size(block_size_);

for (auto &expander : exp_knobs) {
for (auto &knobs : expander)
knobs.set_num_updates(block_size_);
}
}

} else {
Expand Down
8 changes: 8 additions & 0 deletions firmware/src/audio/audio.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "util/calibrator.hh"
#include "util/edge_detector.hh"
#include "util/filter.hh"
#include "util/interp_param.hh"
#include "util/math.hh"
#include <array>

Expand Down Expand Up @@ -67,8 +68,12 @@ private:
CalData cal_stash;
EdgeStateDetector plug_detects[PanelDef::NumJacks];

CalData ext_cal{};

std::array<ResizingOversampler, PanelDef::NumAudioIn> smoothed_ins;

std::array<std::array<InterpParamVariable<float>, 8>, 4> exp_knobs;

PatchPlayer &player;
mdrivlib::CycleCounter load_measure;
float load_lpf = 0.f;
Expand All @@ -82,11 +87,14 @@ private:
bool midi_last_connected = false;

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);
bool check_patch_change(int motion);
void send_zeros_to_patch();
void propagate_sense_pins(Params &params);
void handle_midi(bool is_connected, Midi::Event const &event, unsigned poly_num);
void handle_button_events(uint32_t event_bitmask, bool pressed);

void process_nopatch(CombinedAudioBlock &audio_block, ParamBlock &param_block);
bool is_playing_patch();
void handle_patch_just_loaded();
Expand Down
2 changes: 2 additions & 0 deletions firmware/src/calibrate/calibration_data.hh
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,6 @@ struct CalData {
}
};

static constexpr size_t CalDataSize = sizeof(CalData);

} // namespace MetaModule
16 changes: 5 additions & 11 deletions firmware/src/calibrate/calibration_data_reader.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,11 @@ namespace MetaModule
{

class CalibrationDataReader {
FlashLoader &loader;

public:
CalibrationDataReader(FlashLoader &loader)
: loader{loader} {
}

CalData read_calibration_or_defaults() {
static CalData read_calibration_or_defaults(auto &&loader, uint32_t address) {
CalData caldata;

auto valid = read_calibration(&caldata);
auto valid = read_calibration(&caldata, std::move(loader), address);
if (!valid) {
caldata.reset_to_default();
pr_info("No Calibration data found, using defaults\n");
Expand All @@ -32,10 +26,10 @@ public:
return caldata;
}

bool read_calibration(CalData *caldata) {
pr_dbg("Read Calibration at %x\n", CalDataFlashOffset);
static bool read_calibration(CalData *caldata, auto &&loader, uint32_t address) {
pr_dbg("Read Calibration at %x\n", address);

if (loader.read_sectors(CalDataFlashOffset, {reinterpret_cast<uint8_t *>(caldata), sizeof(CalData)})) {
if (loader.read(address, {reinterpret_cast<uint8_t *>(caldata), sizeof(CalData)})) {

if (caldata->validate()) {
pr_info("Calibration data read and validated\n");
Expand Down
5 changes: 2 additions & 3 deletions firmware/src/calibrate/calibration_message_handler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class CalibrationMessageHandler {

public:
CalibrationMessageHandler(FlashLoader &loader)
: loader{loader}
, reader{loader} {
: loader{loader} {
}

std::optional<IntercoreStorageMessage> handle_message(const IntercoreStorageMessage &message) {
Expand All @@ -28,7 +27,7 @@ public:
if (message.buffer.data() && message.buffer.size() >= sizeof(CalData)) {

auto *caldata = new (message.buffer.data()) CalData;
if (!reader.read_calibration(caldata))
if (!reader.read_calibration(caldata, loader, CalDataFlashOffset))
caldata->reset_to_default();

return IntercoreStorageMessage{.message_type = ReadFlashOk, .bytes_read = sizeof(CalData)};
Expand Down
Loading