diff --git a/Bluemchen/Bluemchen.ioc b/Bluemchen/Bluemchen.ioc index 4df32422..f7c8a44a 100644 --- a/Bluemchen/Bluemchen.ioc +++ b/Bluemchen/Bluemchen.ioc @@ -18,8 +18,8 @@ ADC1.OffsetSignedSaturation-0\#ChannelRegularConversion=DISABLE ADC1.Overrun=ADC_OVR_DATA_OVERWRITTEN ADC1.OversamplingMode=ENABLE ADC1.Rank-0\#ChannelRegularConversion=1 -ADC1.Rank-1\#ChannelRegularConversion=2 -ADC1.Rank-2\#ChannelRegularConversion=3 +ADC1.Rank-1\#ChannelRegularConversion=3 +ADC1.Rank-2\#ChannelRegularConversion=2 ADC1.Rank-3\#ChannelRegularConversion=4 ADC1.Resolution=ADC_RESOLUTION_16B ADC1.RightBitShift=ADC_RIGHTBITSHIFT_4 diff --git a/Bluemchen/Inc/BluemchenParameterController.hpp b/Bluemchen/Inc/BluemchenParameterController.hpp index 504f801e..22e78e15 100644 --- a/Bluemchen/Inc/BluemchenParameterController.hpp +++ b/Bluemchen/Inc/BluemchenParameterController.hpp @@ -745,6 +745,14 @@ class ParameterController { return SIZE; } + int16_t getValue(uint8_t pid){ + return parameters[pid]; + } + + int16_t* getParameters(){ + return parameters; + } + void drawMessage(ScreenBuffer& screen) { ProgramVector* pv = getProgramVector(); if (pv->message != NULL) { @@ -803,7 +811,7 @@ class ParameterController { // called by MIDI cc and/or from patch void setValue(uint8_t pid, int16_t value) { - if (pid >= NOF_ADC_VALUES) + if (pid >= NOF_ADC_VALUES / 2) user[pid] = value; // reset encoder value if associated through selectedPid to avoid skipping for (int i = 0; i < NOF_ENCODERS; ++i) diff --git a/Bluemchen/Src/Bluemchen.cpp b/Bluemchen/Src/Bluemchen.cpp index 24ede2ab..784b5610 100644 --- a/Bluemchen/Src/Bluemchen.cpp +++ b/Bluemchen/Src/Bluemchen.cpp @@ -11,6 +11,7 @@ #include "PatchRegistry.h" #include "OpenWareMidiControl.h" #include "SoftwareEncoder.hpp" +#include "TakeoverControls.h" #include "VersionToken.h" extern bool updateUi; @@ -24,36 +25,50 @@ static SoftwareEncoder encoder( ENC_B_GPIO_Port, ENC_B_Pin, ENC_CLICK_GPIO_Port, ENC_CLICK_Pin); +TakeoverControls<2, uint16_t> takeover; + extern "C" void updateEncoderCounter(){ encoder.updateCounter(); } +// called from program, MIDI, or (potentially) digital bus +void setParameterValue(uint8_t pid, int16_t value) { + if (pid < NOF_PARAMETERS) { + if (pid < NOF_ADC_VALUES / 2) { + takeover.set(pid, __USAT(value, 12)); + takeover.reset(pid, false); + graphics.params.setValue(pid, takeover.get(pid)); + } + else { + graphics.params.setValue(pid, value); + } + } +} + + +static uint16_t smooth_adc_values[NOF_ADC_VALUES]; +extern "C" { +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { + // this runs at apprx 3.3kHz + // with 64.5 cycles sample time, 30 MHz ADC clock, and ClockPrescaler = 32 + extern uint16_t adc_values[NOF_ADC_VALUES]; + for (size_t i = 0; i < NOF_ADC_VALUES; i++) { + // IIR exponential filter with lambda 0.75: y[n] = 0.75*y[n-1] + 0.25*x[n] + smooth_adc_values[i] = (smooth_adc_values[i]*3 + adc_values[i]) >> 2; + } +} +} + void updateParameters(int16_t* parameter_values, size_t parameter_len, uint16_t* adc_values, size_t adc_len){ #ifdef USE_CACHE //SCB_InvalidateDCache_by_Addr((uint32_t*)adc_values, sizeof(adc_values)); #endif - // Note that updateValue will apply smoothing, so we don't have to do it here - graphics.params.updateValue(0, adc_values[0] + adc_values[2]); - graphics.params.updateValue(1, adc_values[1] + adc_values[3]); -} - -/* -void onChangePin(uint16_t pin){ - switch(pin){ - case GATE_IN1_Pin: { - bool state = !(GATE_IN1_GPIO_Port->IDR & GATE_IN1_Pin); - setButtonValue(BUTTON_A, state); - setButtonValue(PUSHBUTTON, state); - break; - } - case GATE_IN2_Pin: - setButtonValue(BUTTON_B, !(GATE_IN2_GPIO_Port->IDR & GATE_IN2_Pin)); - break; - default: - break; + for (int i = 0; i < NOF_ADC_VALUES / 2; i++) { + // CV ADC channels are inverted + takeover.update(i, __USAT(smooth_adc_values[i * 2] + 4220 - smooth_adc_values[i * 2 + 1] * 2, 12), 31); // We don't quite cover full range with 4095 due to DC offset? + graphics.params.updateValue(i, takeover.get(i)); } } -*/ void setup(){ qspi_init(QSPI_MODE_MEMORY_MAPPED); @@ -70,7 +85,6 @@ void setup(){ graphics.begin(&OLED_I2C); owl.setup(); -// setButtonValue(PUSHBUTTON, 0); } static int16_t enc_data[2]; diff --git a/Bluemchen/Src/main.c b/Bluemchen/Src/main.c index 9b338898..b8b83403 100644 --- a/Bluemchen/Src/main.c +++ b/Bluemchen/Src/main.c @@ -380,7 +380,7 @@ static void MX_ADC1_Init(void) } /** Configure Regular Channel */ - sConfig.Channel = ADC_CHANNEL_10; + sConfig.Channel = ADC_CHANNEL_4; sConfig.Rank = ADC_REGULAR_RANK_2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { @@ -388,7 +388,7 @@ static void MX_ADC1_Init(void) } /** Configure Regular Channel */ - sConfig.Channel = ADC_CHANNEL_4; + sConfig.Channel = ADC_CHANNEL_10; sConfig.Rank = ADC_REGULAR_RANK_3; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { diff --git a/Bluemchen/update.sh b/Bluemchen/update.sh index ccf9a6d1..b1c9da86 100755 --- a/Bluemchen/update.sh +++ b/Bluemchen/update.sh @@ -1,9 +1,11 @@ -PROJECT=Bluemchen-seed1.1 -DEVICE=hw:3,0,0 +PROJECT=Bluemchen +DEVICE=hw:4,0,0 +TOOLROOT=~/bin/arm-gnu-toolchain-12.2.rel1-aarch64-arm-none-eabi/bin/ +#TOOLROOT=`pwd`/../Tools/gcc-arm-none-eabi-9-2020-q2-update/bin/ make clean -TOOLROOT=`pwd`/../Tools/gcc-arm-none-eabi-9-2020-q2-update/bin/ make -j17 CONFIG=Release PLATFORM=Daisy PROJECT=${PROJECT} || exit 1 +TOOLROOT=${TOOLROOT} make -j17 CONFIG=Release PLATFORM=Daisy PROJECT=${PROJECT} || exit 1 FirmwareSender -in Build/${PROJECT}.bin -flash `crc32 Build/${PROJECT}.bin` -save Build/${PROJECT}.syx || exit 1 diff --git a/DaisyPod/Src/DaisyPod.cpp b/DaisyPod/Src/DaisyPod.cpp index 77fc8b88..9de5dd22 100644 --- a/DaisyPod/Src/DaisyPod.cpp +++ b/DaisyPod/Src/DaisyPod.cpp @@ -21,7 +21,7 @@ #include "VersionToken.h" #include "rainbow.h" -TakeoverControls<40, int16_t> takeover; +TakeoverControls<40, int16_t> takeover; // TODO: can we manage only 2 active parameters with this? volatile uint8_t patchselect; static uint8_t parameter_offset; static uint16_t enc_value; diff --git a/Source/ProgramManager.cpp b/Source/ProgramManager.cpp index dd57c3e8..5a2bbfc0 100644 --- a/Source/ProgramManager.cpp +++ b/Source/ProgramManager.cpp @@ -368,13 +368,13 @@ void updateProgramVector(ProgramVector* pv, PatchDefinition* def){ #elif defined OWL_ARCH_H7 extern char _ITCMHEAP, _ITCMHEAP_SIZE; extern char _EXTRAM, _EXTRAM_SIZE; - extern uint8_t _PATCHRAM, _PATCHRAM_END, _PATCHRAM_SIZE; + extern char _PATCHRAM, _PATCHRAM_END, _PATCHRAM_SIZE; uint8_t* end = (uint8_t*)def->getStackBase(); // program end - uint32_t remain = &_PATCHRAM_END - end; // space left - if(end < &_PATCHRAM || remain > (uint32_t)&_PATCHRAM_SIZE) // sanity check + uint32_t remain = (uint8_t*)&_PATCHRAM_END - end; // space left + if(end < (uint8_t*)&_PATCHRAM || remain > (uint32_t)&_PATCHRAM_SIZE) // sanity check remain = 0; // prevent errors if program stack is not linked to PATCHRAM #ifdef USE_PLUS_RAM - extern uint8_t _PLUSRAM, _PLUSRAM_END, _PLUSRAM_SIZE; + extern char _PLUSRAM, _PLUSRAM_END, _PLUSRAM_SIZE; uint8_t* plusend = (uint8_t*)&_PLUSRAM; uint32_t plusremain = (uint32_t)&_PLUSRAM_SIZE; if(def->getLinkAddress() == (uint32_t*)&_PLUSRAM){ @@ -382,7 +382,7 @@ void updateProgramVector(ProgramVector* pv, PatchDefinition* def){ remain = (uint32_t)&_PATCHRAM_SIZE; // use all of PATCHRAM for heap plusend = (uint8_t*)def->getStackBase(); plusremain = def->getStackSize(); - plusremain = &_PLUSRAM_END - plusend; + plusremain = (uint8_t*)&_PLUSRAM_END - plusend; } #endif static MemorySegment heapSegments[5]; diff --git a/Source/device.h b/Source/device.h index 8db43b8d..b6c8aa1f 100644 --- a/Source/device.h +++ b/Source/device.h @@ -4,7 +4,7 @@ #include "hardware.h" #define FIRMWARE_VERSION_MAJOR 25 -#define FIRMWARE_VERSION_MINOR 0 +#define FIRMWARE_VERSION_MINOR 2 #define _FW_STR(x) #x #define _FW_TO_STR(x) _FW_STR(x) #define FIRMWARE_VERSION "v" _FW_TO_STR(FIRMWARE_VERSION_MAJOR) "." _FW_TO_STR(FIRMWARE_VERSION_MINOR) @@ -90,7 +90,7 @@ #define MAX_SYSEX_PAYLOAD_SIZE (1 * 1024 * 1024) // Maximum resource size #endif #define BOOTLOADER_MAGIC 0xB007C0DE -#define BOOTLOADER_VERSION "v0.3" +#define BOOTLOADER_VERSION "v0.4" #ifndef MAX_SYSEX_PROGRAM_SIZE #define MAX_SYSEX_PROGRAM_SIZE (128*1024) // 128k, one flash sector