diff --git a/stereo_mix/drivers/adc.h b/stereo_mix/drivers/adc.h index 87c17b5..277381d 100644 --- a/stereo_mix/drivers/adc.h +++ b/stereo_mix/drivers/adc.h @@ -51,7 +51,7 @@ class Adc { inline uint16_t value(int32_t channel) const { - return static_cast(values_[channel]); + return static_cast(values_[channel]); } inline float float_value(int32_t index) const { diff --git a/stereo_mix/drivers/dac.h b/stereo_mix/drivers/dac.h index c0d83d8..5b10c0e 100644 --- a/stereo_mix/drivers/dac.h +++ b/stereo_mix/drivers/dac.h @@ -13,6 +13,7 @@ class Dac { // MCP4xx2 dac implementation : ssGpioPort(ssGpioPort_) , ssGpioPin(ssGpioPin_) { + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_SPI1_CLK_ENABLE(); diff --git a/stereo_mix/processor.cc b/stereo_mix/processor.cc new file mode 100644 index 0000000..4e19891 --- /dev/null +++ b/stereo_mix/processor.cc @@ -0,0 +1,44 @@ +#include "processor.h" +#include "stmlib/stmlib.h" +#include + +using namespace stereo_mix; + +const int kVolumeFilterValue = 4095; + +void Processor::Process(int16_t cvs[], uint16_t* outs) +{ + uint32_t value_l; + uint32_t value_r; + + uint16_t pan_pot = (pan_offset + 32767L) >> (16 - 12); // adc is only 12 bit anyways + uint16_t vol_pot = (volume_offset) >> (16 - 12); + int16_t pan_cv = cvs[0] >> (16 - 12); + int16_t vol_cv = cvs[1] >> (16 - 12); + int32_t pan = pan_pot + pan_cv; + int32_t vol = vol_pot + vol_cv; + CONSTRAIN(pan, 0, (1 << 12) - 1); + CONSTRAIN(vol, 0, (1 << 12) - 1); + + if (mute) { + vol = 0; + } + + if (vol > previous_vol + kVolumeFilterValue) { + vol = previous_vol + kVolumeFilterValue; + } else if (vol < previous_vol - kVolumeFilterValue) { + vol = previous_vol - kVolumeFilterValue; + } + + CONSTRAIN(pan, 0, (1 << 12) - 1); + CONSTRAIN(vol, 0, (1 << 12) - 1); + + previous_vol = vol; + + // leds.set_intensity(i, vol >> 4); + value_l = (lut_left_sin_pan[pan] * lut_linear_to_exp[vol]) >> 16; + value_r = (lut_right_cos_pan[pan] * lut_linear_to_exp[vol]) >> 16; + + outs[0] = value_r; + outs[1] = value_l; +} diff --git a/stereo_mix/processor.h b/stereo_mix/processor.h new file mode 100644 index 0000000..3efae8d --- /dev/null +++ b/stereo_mix/processor.h @@ -0,0 +1,30 @@ +#pragma once +#include "resources.h" + +class Processor { + public: + Processor() {}; + + void Process(int16_t cvs[], uint16_t* outs); + + inline void set_volume_offset(uint16_t volume_offset_) + { + volume_offset = volume_offset_; + } + + inline void set_pan_offset(int16_t pan_offset_) + { + pan_offset = pan_offset_; + } + + inline void set_muted(bool m) + { + mute = m; + } + + private: + uint16_t volume_offset = 0; + int16_t pan_offset = 0; + int32_t previous_vol; + bool mute = false; +}; diff --git a/stereo_mix/stereo_mix.cc b/stereo_mix/stereo_mix.cc index 0006bb7..a1dd703 100644 --- a/stereo_mix/stereo_mix.cc +++ b/stereo_mix/stereo_mix.cc @@ -3,6 +3,7 @@ #include "drivers/leds.h" #include "drivers/peripherals.h" #include "drivers/switches.h" +#include "processor.h" #include "resources.h" #include "stmlib/ui/event_queue.h" #include "ui.h" @@ -19,7 +20,8 @@ Dac dacs[8] = { Adc adc; Leds leds; Switches switches; -UI ui(&adc, &switches, &leds); +Processor processors[kNumChannels]; +UI ui(&adc, &switches, &leds, processors); bool mute[4]; @@ -136,30 +138,16 @@ void Init(void) void WriteOutputs(void) { - for (int i = 0; i < 4; i++) { - uint32_t value_l; - uint32_t value_r; - - uint16_t pan_pot = adc.value(ADC_GROUP_POT + ADC_CHANNEL_PAN_1 + i) >> (16 - 12); // adc is only 12 bit anyways - uint16_t vol_pot = adc.value(ADC_GROUP_POT + ADC_CHANNEL_VOL_1 + i) >> (16 - 12); - int16_t pan_cv = adc.cv_value(AdcChannel(ADC_CHANNEL_PAN_1 + i)) >> (16 - 12); - int16_t vol_cv = adc.cv_value(AdcChannel(ADC_CHANNEL_VOL_1 + i)) >> (16 - 12); - int32_t pan = pan_pot + pan_cv; - int32_t vol = vol_pot + vol_cv; - - if (mute[i]) - vol = 0; - - CONSTRAIN(pan, 0, (1 << 12) - 1); - CONSTRAIN(vol, 0, (1 << 12) - 1); - // leds.set_intensity(i, vol >> 4); - value_l = (lut_left_sin_pan[pan] * lut_linear_to_exp[vol]) >> 16; - value_r = (lut_right_cos_pan[pan] * lut_linear_to_exp[vol]) >> 16; - - dacs[i].Write16(0, value_r); - dacs[i + 4].Write16(0, value_r); - dacs[i].Write16(1, value_l); - dacs[i + 4].Write16(1, value_l); + for (int i = 0; i < kNumChannels; i++) { + uint16_t out[2]; + int16_t cvs[2]; + cvs[0] = 0; + cvs[1] = 0; + processors[i].Process(cvs, out); + dacs[i].Write16(0, out[0]); + dacs[i + 4].Write16(0, out[0]); + dacs[i].Write16(1, out[1]); + dacs[i + 4].Write16(1, out[1]); } } diff --git a/stereo_mix/ui.cc b/stereo_mix/ui.cc index 2feb5bd..b2d501c 100644 --- a/stereo_mix/ui.cc +++ b/stereo_mix/ui.cc @@ -48,7 +48,12 @@ void UI::Poll() } for (size_t i = 0; i < kNumChannels * 2; i++) { - if (abs(previous_pot_values[i] - adc->value(ADC_GROUP_POT + i)) > 1966) { + if (i >= kNumChannels) { + processors[i - kNumChannels].set_pan_offset(adc->value(ADC_GROUP_POT + i) - 32767L); + } else { + processors[i].set_volume_offset(adc->value(ADC_GROUP_POT + i)); + } + if (abs(previous_pot_values[i] - adc->value(ADC_GROUP_POT + i)) > 1900) { previous_pot_values[i] = adc->value(ADC_GROUP_POT + i); queue.AddEvent(CONTROL_POT, i, previous_pot_values[i]); } @@ -73,7 +78,9 @@ void UI::OnPotChanged(const Event& e) void UI::OnSwitchReleased(const Event& e) { mute[e.control_id] = !mute[e.control_id]; - for(size_t i = 0; i < kNumChannels; i++) { + processors[e.control_id].set_muted(mute[e.control_id]); + + for (size_t i = 0; i < kNumChannels; i++) { last_pan_pot_touch[i] = last_vol_pot_touch[i] = 0; } } @@ -100,7 +107,7 @@ void UI::TaskDrawLeds() // show volume leds->set_intensity(i, volume_pots[i] >> 8); leds->set_blinking(i, false); - } else if(system_clock.milliseconds() - last_pan_pot_touch[i] < kShowChangedValueMilliseconds) { + } else if (system_clock.milliseconds() - last_pan_pot_touch[i] < kShowChangedValueMilliseconds) { // show panning leds->set_intensity(i, abs(pan_pots[i] - 32767) >> 7); leds->set_blinking(i, pan_pots[i] - 32767 < 0); diff --git a/stereo_mix/ui.h b/stereo_mix/ui.h index c8691af..5669627 100644 --- a/stereo_mix/ui.h +++ b/stereo_mix/ui.h @@ -4,6 +4,7 @@ #include "drivers/leds.h" #include "drivers/switches.h" #include "pot_controller.h" +#include "processor.h" #include "stmlib/ui/event_queue.h" using namespace stmlib; @@ -12,10 +13,11 @@ extern const uint8_t kNumChannels; // TODO class UI { public: - UI(Adc* adc_, Switches* switches_, Leds* leds_) + UI(Adc* adc_, Switches* switches_, Leds* leds_, Processor* processors_) : adc(adc_) , switches(switches_) , leds(leds_) + , processors(processors_) { queue.Init(); @@ -47,6 +49,8 @@ class UI { Switches* switches; Leds* leds; + Processor* processors; + uint16_t previous_pot_values[kNumChannels * 2]; uint16_t volume_pots[kNumChannels];