ADC scaling and fixes
This commit is contained in:
@@ -5,10 +5,10 @@ use hal::gpio::{Output, PushPull, Alternate, AF0, AF5};
|
||||
use embedded_hal::blocking::spi::Transfer;
|
||||
use defmt::*;
|
||||
|
||||
pub const PEDAL_A_MIN: u8 = 10;
|
||||
pub const PEDAL_A_MAX: u8 = 245;
|
||||
pub const PEDAL_B_MIN: u8 = 10;
|
||||
pub const PEDAL_B_MAX: u8 = 245;
|
||||
pub const PEDAL_A_MIN: u8 = 71;
|
||||
pub const PEDAL_A_MAX: u8 = 248;
|
||||
pub const PEDAL_B_MIN: u8 = 83;
|
||||
pub const PEDAL_B_MAX: u8 = 250;
|
||||
|
||||
const IIR_ALPHA: u16 = 51;
|
||||
|
||||
@@ -38,7 +38,8 @@ impl Tlc0832 {
|
||||
let sck = sck.into_alternate_af5(critical_section);
|
||||
let miso = miso.into_alternate_af0(critical_section);
|
||||
let mosi = mosi.into_alternate_af0(critical_section);
|
||||
let cs = cs.into_push_pull_output(critical_section);
|
||||
let mut cs = cs.into_push_pull_output(critical_section);
|
||||
cs.set_high().ok();
|
||||
|
||||
let spi_mode = Mode {
|
||||
polarity: Polarity::IdleLow,
|
||||
@@ -53,21 +54,14 @@ impl Tlc0832 {
|
||||
rcc,
|
||||
);
|
||||
|
||||
let adc = Self {
|
||||
Self {
|
||||
spi,
|
||||
cs,
|
||||
pedal_a_filtered: 128 << 8,
|
||||
pedal_b_filtered: 128 << 8,
|
||||
last_midi_a: 64,
|
||||
last_midi_b: 64,
|
||||
};
|
||||
|
||||
// Small delay to ensure SPI peripheral is ready
|
||||
for _ in 0..1000 {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
|
||||
adc
|
||||
})
|
||||
}
|
||||
|
||||
@@ -75,34 +69,35 @@ impl Tlc0832 {
|
||||
if channel > 1 {
|
||||
return Err("Invalid channel");
|
||||
}
|
||||
|
||||
self.cs.set_high().ok();
|
||||
// Small delay before starting transaction
|
||||
for _ in 0..100 {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
|
||||
self.cs.set_low().ok();
|
||||
|
||||
// Small delay after CS low
|
||||
for _ in 0..100 {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
|
||||
let start_bit = 1u8 << 7;
|
||||
let channel_bit = if channel == 0 { 0x00 } else { 1u8 << 6 };
|
||||
let command = start_bit | channel_bit;
|
||||
|
||||
info!("Reading channel {} with command 0x{:02x}", channel, command);
|
||||
// TLC0832 protocol:
|
||||
// Send 3 bits: Start(1) + SGL/DIF(1 for single-ended) + ODD/EVEN(channel)
|
||||
// Then 1 clock cycle of MUX settling (DO goes low)
|
||||
// Then 8 clock cycles of MSB-first data
|
||||
|
||||
// Use HAL SPI transfer - much simpler and more reliable
|
||||
let mut data = [command, 0x00, 0x00]; // TLC0832 needs 3 bytes
|
||||
let result = match self.spi.transfer(&mut data) {
|
||||
Ok(response) => {
|
||||
info!("SPI transfer successful: [{:02x}, {:02x}, {:02x}]",
|
||||
response[0], response[1], response[2]);
|
||||
// TLC0832 returns data in the 3rd byte for 8-bit mode
|
||||
response[2]
|
||||
},
|
||||
// For single-ended mode:
|
||||
// Channel 0: 110 (Start=1, SGL/DIF=1, ODD/EVEN=0)
|
||||
// Channel 1: 111 (Start=1, SGL/DIF=1, ODD/EVEN=1)
|
||||
|
||||
let command_bits = 0x06 | channel; // 110 or 111 in the top 3 bits
|
||||
let command_byte = command_bits << 5; // Shift to MSB position: 11000000 or 11100000
|
||||
|
||||
info!("Reading channel {} with command bits {:03b} (0x{:02x})", channel, command_bits, command_byte);
|
||||
|
||||
// Send command byte + 2 dummy bytes to clock out the full response
|
||||
// The TLC0832 needs 11 total clock cycles:
|
||||
// 3 for command + 1 for MUX settling + 8 for data = 12 bits total
|
||||
let mut data = [command_byte, 0x00];
|
||||
|
||||
let response = match self.spi.transfer(&mut data) {
|
||||
Ok(resp) => resp,
|
||||
Err(_) => {
|
||||
self.cs.set_high().ok();
|
||||
error!("SPI transfer error");
|
||||
@@ -110,12 +105,26 @@ impl Tlc0832 {
|
||||
}
|
||||
};
|
||||
|
||||
info!("SPI response: [{:02x}, {:02x}]", response[0], response[1]);
|
||||
|
||||
// The result spans across the response bytes
|
||||
// After the 3 command bits + 1 MUX settling bit (4 bits total),
|
||||
// the next 8 bits are the conversion result
|
||||
// So we need to extract bits from both response bytes
|
||||
|
||||
// response[0] contains the first 8 bits (3 command + 1 settling + 4 data MSBs)
|
||||
// response[1] contains the remaining 4 data LSBs
|
||||
|
||||
let result = ((response[0] & 0x0F) << 4) | ((response[1] & 0xF0) >> 4);
|
||||
|
||||
// Small delay before CS high
|
||||
for _ in 0..100 {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
|
||||
self.cs.set_high().ok();
|
||||
info!("Read channel {} = {}", channel, result);
|
||||
|
||||
info!("Channel {} result: {}", channel, result);
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
@@ -154,13 +163,16 @@ impl Tlc0832 {
|
||||
let mut midi_a_change = None;
|
||||
let mut midi_b_change = None;
|
||||
|
||||
// Read channel 0 (pedal A)
|
||||
match self.read_channel(0) {
|
||||
Ok(raw_a) => {
|
||||
info!("Raw channel 0 value: {}", raw_a);
|
||||
self.apply_iir_filter(0, raw_a);
|
||||
let filtered_a = (self.pedal_a_filtered >> 8) as u8;
|
||||
let midi_a = self.adc_to_midi(filtered_a, PEDAL_A_MIN, PEDAL_A_MAX);
|
||||
|
||||
if midi_a != self.last_midi_a {
|
||||
info!("Channel 0 MIDI change: {} -> {}", self.last_midi_a, midi_a);
|
||||
self.last_midi_a = midi_a;
|
||||
midi_a_change = Some(midi_a);
|
||||
}
|
||||
@@ -170,13 +182,16 @@ impl Tlc0832 {
|
||||
}
|
||||
}
|
||||
|
||||
// Read channel 1 (pedal B)
|
||||
match self.read_channel(1) {
|
||||
Ok(raw_b) => {
|
||||
info!("Raw channel 1 value: {}", raw_b);
|
||||
self.apply_iir_filter(1, raw_b);
|
||||
let filtered_b = (self.pedal_b_filtered >> 8) as u8;
|
||||
let midi_b = self.adc_to_midi(filtered_b, PEDAL_B_MIN, PEDAL_B_MAX);
|
||||
|
||||
if midi_b != self.last_midi_b {
|
||||
info!("Channel 1 MIDI change: {} -> {}", self.last_midi_b, midi_b);
|
||||
self.last_midi_b = midi_b;
|
||||
midi_b_change = Some(midi_b);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user