diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs index 385117bc02c95828b9e5fa62eaae9b3d2c456913..2480bcf740df148f88d501451fbbdee52c8639e0 100644 --- a/firmware/rust1/src/bin/heizung.rs +++ b/firmware/rust1/src/bin/heizung.rs @@ -5,8 +5,7 @@ use defmt::*; use embassy_executor::Spawner; //use embassy_futures::join::join; -use embassy_futures::select::select; -use embassy_futures::select::Either::*; +use embassy_futures::select::{select, Either, select3, Either3}; use embassy_rp::gpio; use embassy_time::{Duration, Timer}; use embassy_rp::gpio::{Input, Level, Output, Pull, Flex}; @@ -17,7 +16,7 @@ use embassy_embedded_hal::SetConfig; use embassy_rp::peripherals::{UART0}; use embassy_rp::uart::{self, UartRx, Parity}; use embassy_rp::pwm::{self, Pwm}; -use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; +use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection, FifoJoin}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::Peripheral; use {defmt_rtt as _, panic_probe as _}; @@ -97,8 +96,8 @@ async fn handle_clock_stretching<'d, SCL: gpio::Pin>(scl: &mut Flex<'d, SCL>) -> let timeout = Timer::after(Duration::from_micros(100)); return match select(is_high, timeout).await { - First(_) => Ok(()), - Second(_) => Err(Abort(ArbitrationLoss)), + Either::First(_) => Ok(()), + Either::Second(_) => Err(Abort(ArbitrationLoss)), } } async fn i2c_write_zero_bytes_middle_part<'d, SCL: gpio::Pin, SDA: gpio::Pin, const FREQ : u64>( @@ -298,6 +297,7 @@ async fn autobaud_task(pio0: embassy_rp::peripherals::PIO0, rx_pin: embassy_rp:: let Pio { mut common, sm0: mut sm, + mut irq0, .. } = Pio::new(pio0); @@ -335,7 +335,7 @@ async fn autobaud_task(pio0: embassy_rp::peripherals::PIO0, rx_pin: embassy_rp:: // We want to measure 9 bits (start bit plus eight (or nine) data bits). However, we need // different code for high and low so it's easier to measure 4x2 bits. Weuse Y as the loop counter. - "set y, 4", + "set y, 3", // Start counting. We count down from the value in OSR (which is our timeout). "measure_next:", @@ -394,22 +394,35 @@ async fn autobaud_task(pio0: embassy_rp::peripherals::PIO0, rx_pin: embassy_rp:: pin_io(&rx_pin).ctrl().write(|w| w.set_funcsel(embassy_rp::pac::io::vals::Gpio17ctrlFuncsel::UART0_RX.0)); } + if false { + cfg.fifo_join = FifoJoin::RxOnly; + sm.set_config(&cfg); + // set_config has also set the origin so let's go back to after the pull + // -> still doesn't work for some reason + unsafe { embassy_rp::pio_instr_util::exec_jmp(&mut sm, 1); }; + } + // Timeout: Modbus wants 1.5 ms between frames so we make this a bit smaller. SM runs at 25 MHz - // but we need 4 clocks per loop. - let timeout_start_value = (SM_FREQ as f32 * 1.2e-3 / 4.) as u32; + // but we need two clocks per loop. + let timeout_start_value = (SM_FREQ as f32 * 1.2e-3 / 2.) as u32; sm.tx().push(timeout_start_value); info!("timeout_start_value: {} = 0x{:08x}", timeout_start_value, timeout_start_value); let mut dma_in_ref = dma_channel.into_ref(); - let mut din = [42u32; 4]; + let mut din = [42u32; 9]; let mut bit_index = 0; loop { - let x = select( + let x = select3( + irq0.wait(), sm.rx().dma_pull(dma_in_ref.reborrow(), &mut din), debug_print_pio_addr(embassy_rp::pac::PIO0.sm(0)), ).await; match x { - First(_) => { + Either3::First(_) => { + let mut sum = 0; + let mut first = 0; + let mut ok = true; + let mut got_to_eight = false; for i in 0..din.len() { if din[i] == 0 { bit_index = 0; @@ -427,9 +440,53 @@ async fn autobaud_task(pio0: embassy_rp::peripherals::PIO0, rx_pin: embassy_rp:: let millis = (delay) as f32 / SM_FREQ as f32 * 1000. * 2.; let baud = 1000. / millis; info!("SM in {} ({}): {:08x} -> {} -> {} ms -> {}", i, bit_index, din[i], delay, millis, baud); + if bit_index == 0 { + sum = 0; + first = delay; + ok = true; + } else if delay < first-first/4 || delay > first+first/4 { + ok = false; + } + sum += delay; + bit_index += 1; + got_to_eight = bit_index == 8; + } + } + + for _ in bit_index..8 { + if let Some(x) = sm.rx().try_pull() { + let mut delay = timeout_start_value - x; + if bit_index == 0 { + delay += 7; + } else if bit_index%2 == 1 { + //delay += 4; + delay += 3; + } else { + delay += 3; + } + let millis = (delay) as f32 / SM_FREQ as f32 * 1000. * 2.; + let baud = 1000. / millis; + info!("SM in ({}): {:08x} -> {} -> {} ms -> {}", bit_index, x, delay, millis, baud); + if bit_index == 0 { + sum = 0; + first = delay; + ok = true; + } else if delay < first-first/4 || delay > first+first/4 { + ok = false; + } + sum += delay; bit_index += 1; + got_to_eight = bit_index == 8; + } else { + break } } + + if got_to_eight && ok { + let millis = sum as f32 / SM_FREQ as f32 * 1000. * 2. / 8.; + let baud = 1000. / millis; + info!("Guessed baud rate: {}", baud); + } }, _ => { },