Files
loopy_midi_controller/src/expression_pedal.cpp
T

74 lines
2.4 KiB
C++

#include "expression_pedal.h"
#include "midi_transport.h"
#include <Arduino.h>
ExpressionPedal::ExpressionPedal(uint8_t adc_pin)
: adc_pin(adc_pin)
, current_value(0)
, last_sent_value(255)
, midi_channel(1)
, midi_cc(4)
, last_read_time(0)
, current_raw(0)
, smoothed_raw(0)
, cal_min(36)
, cal_max(1100)
{
}
void ExpressionPedal::begin() {
Serial.printf("[EXP] Expression pedal on ADC1_CH3 (GPIO%d)\n", adc_pin);
analogReadResolution(12);
pinMode(adc_pin, INPUT);
delay(10);
current_raw = analogRead(adc_pin);
smoothed_raw = current_raw;
current_value = adc_to_midi(smoothed_raw);
last_sent_value = current_value;
Serial.printf("[EXP] Starting: raw ADC=%d -> MIDI=%d (cal: %d-%d)\n",
current_raw, current_value, cal_min, cal_max);
Serial.printf("[EXP] Move pedal full range to see raw values\n");
}
void ExpressionPedal::update(UsbMidiTransport& midi) {
uint32_t now = millis();
if (now - last_read_time < READ_INTERVAL_MS) return;
last_read_time = now;
current_raw = analogRead(adc_pin);
smoothed_raw = (smoothed_raw * 7 + current_raw + 4) / 8;
uint8_t new_value = adc_to_midi(smoothed_raw);
current_value = new_value;
// Proportional catch-up: send midpoint rounded up each update.
// Rejects ±1 stationary jitter but converges to exact value on movement
// (e.g., 0→127 converges in ~35ms).
if (current_value > last_sent_value + 1) {
last_sent_value = (last_sent_value + current_value + 1) / 2;
midi.send_cc(midi_channel, midi_cc, last_sent_value);
} else if (current_value < last_sent_value - 1) {
last_sent_value = (last_sent_value + current_value) / 2;
midi.send_cc(midi_channel, midi_cc, last_sent_value);
}
}
void ExpressionPedal::set_cal_min() {
cal_min = current_raw;
if (cal_min >= cal_max) cal_max = cal_min + 1;
Serial.printf("[EXP] cal_min set to %d (ADC raw)\n", cal_min);
}
void ExpressionPedal::set_cal_max() {
cal_max = current_raw;
if (cal_max <= cal_min) cal_min = cal_max - 1;
Serial.printf("[EXP] cal_max set to %d (ADC raw)\n", cal_max);
}
uint8_t ExpressionPedal::adc_to_midi(uint16_t adc_value) {
if (adc_value <= cal_min) return 0;
if (adc_value >= cal_max) return 127;
uint32_t span = cal_max - cal_min;
uint32_t offset = adc_value - cal_min;
return (uint8_t)(offset * 127 / span);
}