Added basic tuning via encoder

This commit is contained in:
Sebastian 2023-08-22 19:02:33 +02:00
parent 4878a1a771
commit 35ad5dcb9f
2 changed files with 70 additions and 33 deletions

View File

@ -69,8 +69,8 @@ mod app {
board_led: gpioc::PC13<Output<PushPull>>,
rx_en: gpioa::PA7<Output<PushPull>>,
//mic_in: gpio::Pin<'A', 4, Analog>,
i_in: gpio::Pin<'A', 1, Analog>,
q_in: gpio::Pin<'A', 0, Analog>,
i_in: gpio::Pin<'A', 2, Analog>,
q_in: gpio::Pin<'A', 3, Analog>,
i_offset: f32,
q_offset: f32,
audio_pwm: AudioPwm,
@ -93,6 +93,10 @@ mod app {
disp: ST7735<Spi<SPI1>, gpio::Pin<'A', 12, Output>, gpio::Pin<'A', 11, Output>>,
col_pos: u16,
max_mag: f32,
encoder: qei::Qei<TIM2>,
last_encoder_pos: u32,
carrier_freq: u32,
}
#[shared]
@ -125,14 +129,12 @@ mod app {
let board_led = gpioc.pc13.into_push_pull_output();
/*
let enc_a = gpioa.pa5.into_input();
let enc_b = gpiob.pb3.into_input();
let enc_a = gpioa.pa0.into_input();
let enc_b = gpioa.pa1.into_input();
let encoder = qei::Qei::new(cx.device.TIM2, (enc_a, enc_b));
defmt::info!("Encoder Setup done");
*/
let scl = gpiob.pb6.into_alternate_open_drain();
let sda = gpiob.pb7.into_alternate_open_drain();
@ -152,8 +154,8 @@ mod app {
let freq = 7_100_000;
*/
let phase = 36;
let freq = 14_125_000;
let phase = 100;
let freq = 7_100_000;
pll.init(&mut i2c, 25_000_000, freq * phase, freq * phase);
pll.set_ms_source(&mut i2c, si5153::Multisynth::MS0, si5153::PLL::A);
@ -201,8 +203,8 @@ mod app {
defmt::info!("Display setup done");
let i_in = gpioa.pa1.into_analog();
let q_in = gpioa.pa0.into_analog();
let i_in = gpioa.pa2.into_analog();
let q_in = gpioa.pa3.into_analog();
let adc_config = AdcConfig::default()
.dma(Dma::Continuous)
@ -307,11 +309,15 @@ mod app {
disp,
col_pos: 0,
max_mag: 0.0,
encoder,
last_encoder_pos: 0,
carrier_freq: 7_100_000,
},
)
}
#[task(priority = 0, local = [disp, col_pos, max_mag])]
#[task(priority = 0, local = [disp, col_pos, max_mag, encoder, last_encoder_pos, carrier_freq, pll, i2c])]
async fn update_display(cx: update_display::Context, col: [Complex<f32>; 128]) {
for samp in col {
let mag = (samp.re.pow(2) as f32 + samp.im.pow(2) as f32).sqrt() as f32;
@ -341,6 +347,29 @@ mod app {
*cx.local.max_mag *= 0.999;
defmt::info!("Position is {}", cx.local.col_pos);
let encoder_pos = cx.local.encoder.count();
let diff = encoder_pos.wrapping_sub(*cx.local.last_encoder_pos) as i32;
if diff != 0 {
*cx.local.carrier_freq = (*cx.local.carrier_freq as i32 + diff * 100 / 4) as u32;
cx.local
.pll
.set_pll_freq(cx.local.i2c, si5153::PLL::A, *cx.local.carrier_freq * 100);
cx.local.pll.set_ms_freq(
cx.local.i2c,
si5153::Multisynth::MS0,
*cx.local.carrier_freq,
);
cx.local.pll.set_ms_freq(
cx.local.i2c,
si5153::Multisynth::MS1,
*cx.local.carrier_freq,
);
}
defmt::info!("Carrier freq is {}", cx.local.carrier_freq);
*cx.local.last_encoder_pos = encoder_pos;
}
#[task(binds = DMA2_STREAM0, local = [adc_transfer, iq_buffer, board_led, i_offset, q_offset, usb_filter, audio_max_duty], shared = [audio_buffer])]
@ -365,7 +394,7 @@ mod app {
let i_sample = (i_raw as f32) - *cx.local.i_offset;
let q_sample = (q_raw as f32) - *cx.local.q_offset;
samples[idx] = Complex::new(q_sample as f32 / 4096.0, i_sample as f32 / 4096.0);
samples[idx] = Complex::new(q_sample as f32 / 4096.0, i_sample as f32 / 4096.0) * 5.0;
}
let mut fft_input = [Complex::<f32>::default(); 128];
@ -376,8 +405,8 @@ mod app {
cx.shared.audio_buffer.lock(|buffer| {
let audio_buffer = buffer.take().unwrap();
for idx in 0..samples.len() {
//let filtered = usb_filter.compute(samples[idx]);
let filtered = usb_filter.compute(Complex::new(samples[idx].im, samples[idx].re));
let filtered = usb_filter.compute(samples[idx]);
//let filtered = usb_filter.compute(Complex::new(samples[idx].im, samples[idx].re));
fft_input[idx] = samples[idx];
audio_buffer[idx] = ((filtered.re * (audio_max_duty as f32)) * 3.0f32) as u16;

View File

@ -57,6 +57,7 @@ pub struct PllParams {
pub struct Si5153<I2C> {
// Marker that makes sure we always get the same I2C
i2c: PhantomData<I2C>,
freq_xtal: u32,
pll_freqs: [u32; 2],
outputs: u8,
ms_srcs: [PLL; 3],
@ -69,6 +70,7 @@ where
pub fn new(_i2c: &I2C) -> Self {
Si5153 {
i2c: PhantomData,
freq_xtal: 0,
pll_freqs: [0, 0],
outputs: 0,
ms_srcs: [PLL::A, PLL::A, PLL::A],
@ -76,6 +78,8 @@ where
}
pub fn init(&mut self, i2c: &mut I2C, freq_xtal: u32, freq_a: u32, freq_b: u32) {
self.freq_xtal = freq_xtal;
self.pll_freqs[PLL::A as usize] = freq_a;
self.pll_freqs[PLL::B as usize] = freq_b;
@ -83,34 +87,38 @@ where
self.write_byte_reg(i2c, CLK_ENABLE_CONTROL, self.outputs); // Disable all outputs
self.write_byte_reg(i2c, XTAL_LOAD_CAP, 0xD2); //crystal load capacitor = 10pF
self.set_pll_freq(i2c, PLL::A, freq_a);
self.set_pll_freq(i2c, PLL::B, freq_b);
for ms in [Multisynth::MS0, Multisynth::MS1, Multisynth::MS2].iter() {
self.ms_srcs[*ms as usize] = PLL::A;
self.write_byte_reg(i2c, ms.ctrl_address(), 0x0F); // MSi as Source, PLLA to MSi, 8 mA output
self.write_byte_reg(i2c, ms.phoff_address(), 0); // Phase offset to 0.
}
for pll in [PLL::A, PLL::B].iter() {
let fdiv = self.pll_freqs[*pll as usize] / freq_xtal;
let rm = self.pll_freqs[*pll as usize] % freq_xtal;
let gcd = num::integer::gcd(rm, freq_xtal);
let c = if gcd < 0x0FFFFF { gcd } else { 0x0FFFFF };
let a = fdiv;
let b = ((rm as u64) * (c as u64) / (freq_xtal as u64)) as u32;
let params = PllParams {
p1: 128 * a + (128 * b / c) - 512,
p2: 128 * b - c * (128 * b / c),
p3: c,
};
self.write_params(i2c, pll.base_address(), &params)
}
self.write_byte_reg(i2c, PLL_RESET, 0xA0); // Reset both PLLs
}
pub fn set_pll_freq(&mut self, i2c: &mut I2C, pll: PLL, freq: u32) {
let fdiv = freq / self.freq_xtal;
let rm = freq % self.freq_xtal;
let gcd = num::integer::gcd(rm, self.freq_xtal);
let c = if gcd < 0x0FFFFF { gcd } else { 0x0FFFFF };
let a = fdiv;
let b = ((rm as u64) * (c as u64) / (self.freq_xtal as u64)) as u32;
let params = PllParams {
p1: 128 * a + (128 * b / c) - 512,
p2: 128 * b - c * (128 * b / c),
p3: c,
};
self.write_params(i2c, pll.base_address(), &params);
self.pll_freqs[pll as usize] = freq;
}
pub fn enable_ms_output(&mut self, i2c: &mut I2C, synth: Multisynth) {
self.outputs &= !(1 << (synth as u8));
self.write_byte_reg(i2c, CLK_ENABLE_CONTROL, self.outputs);