diff --git a/.cargo/config.toml b/.cargo/config.toml index 9efbea9..a492de7 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -32,4 +32,8 @@ rustflags = [ # This runner will find a supported SWD debug probe and flash your RP2040 over # SWD: -runner = "probe-rs run --chip RP2040 --protocol swd" \ No newline at end of file +runner = "probe-rs run --chip RP2040 --protocol swd" + +[env] +DEFMT_RTT_BUFFER_SIZE = { value = "4096", force = true } +DEFMT_LOG = { value = "info", force = true } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index b630e4f..ca1d514 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,15 @@ #![no_std] #![no_main] -use defmt::println; +use cortex_m::singleton; +use defmt::info; +use defmt::{println, write}; use defmt_rtt as _; use panic_probe as _; +use rp2040_hal::dma::DMAExt; +use rp2040_hal::dma::single_buffer; use rp2040_hal::gpio::DynFunction; use rp2040_hal::gpio::DynPinId; use rp2040_hal::gpio::DynPullType; @@ -39,6 +43,8 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H; /// if your board has a different frequency const XTAL_FREQ_HZ: u32 = 12_000_000u32; +const NUM_ADC_SAMPLES: usize = 1024; + /// Entry point to our bare-metal application. /// /// The `#[rp2040_hal::entry]` macro ensures the Cortex-M start-up code calls this function @@ -89,9 +95,19 @@ fn main() -> ! { MyPin::new(MyPinMode::Input, pins.gpio13.into_dyn_pin()), ]; + let dma = pac.DMA.split(&mut pac.RESETS); + let mut adc = hal::Adc::new(pac.ADC, &mut pac.RESETS); let mut adc_pin = hal::adc::AdcPin::new(pins.gpio26.into_floating_input()).unwrap(); - let mut adc_fifo = adc.build_fifo().set_channel(&mut adc_pin).start_paused(); + let mut adc_fifo = adc + .build_fifo() + .clock_divider(24000, 0) + .set_channel(&mut adc_pin) + .enable_dma() + .start_paused(); + let buf_for_samples = singleton!(: [u16; NUM_ADC_SAMPLES] = [0; NUM_ADC_SAMPLES]).unwrap(); + let mut dma_transfer = + single_buffer::Config::new(dma.ch0, adc_fifo.dma_read_target(), buf_for_samples).start(); loop { let pushed = input_btn_pin.is_high().unwrap(); @@ -111,81 +127,112 @@ fn main() -> ! { println!("Running test."); delay.delay_ms(500); - if test_pins.iter_mut().any(|tp| tp.is_high()) { + if test_pins.iter_mut().any(|tp| { + tp.switch_to_input(); + tp.is_high() + }) { println!("Uh oh, voltage on test pins? Aborting test"); continue; } // TEST 1 - delay.delay_ms(10); + delay.delay_ms(100); println!("Testing at 0v"); test_pins[0].switch_into_output(); test_pins[0].set_low(); - adc_fifo.clear(); adc_fifo.resume(); - - while adc_fifo.len() < 8 { - println!("waiting for ADC... {} / 8", adc_fifo.len()); - } - adc_fifo.pause(); - - let avg = avg_fifo(&mut adc_fifo); + let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait(); + let avg = avg_fifo(buf_for_samples, false); println!("Avg: {}", avg); + adc_fifo.pause(); + adc_fifo.clear(); + dma_transfer = single_buffer::Config::new(ch, adc_read_target, buf_for_samples).start(); + // TEST 2 - delay.delay_ms(10); + delay.delay_ms(1000); println!("Testing at 3.3v"); test_pins[0].set_high(); - adc_fifo.clear(); + delay.delay_ms(100); adc_fifo.resume(); - - while adc_fifo.len() < 8 { - println!("waiting for ADC... {} / 8", adc_fifo.len()); - } - adc_fifo.pause(); - - let avg = avg_fifo(&mut adc_fifo); + let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait(); + let avg = avg_fifo(buf_for_samples, false); println!("Avg: {}", avg); + adc_fifo.pause(); + adc_fifo.clear(); + dma_transfer = single_buffer::Config::new(ch, adc_read_target, buf_for_samples).start(); + // TEST 3 + delay.delay_ms(1000); println!("Testing floating"); - adc_fifo.clear(); - - test_pins[0].switch_to_input(); + test_pins[2].switch_into_output(); + test_pins[2].set_low(); + delay.delay_ms(200); adc_fifo.resume(); - - while adc_fifo.len() < 8 { - println!("waiting for ADC... {} / 8", adc_fifo.len()); - } + test_pins[0].switch_to_floating(); + let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait(); + let avg = avg_fifo(buf_for_samples, true); + delay.delay_ms(10); + println!("Avg: {}", avg); adc_fifo.pause(); - let avg = avg_fifo(&mut adc_fifo); + adc_fifo.clear(); + dma_transfer = single_buffer::Config::new(ch, adc_read_target, buf_for_samples).start(); + + // TEST 4 + delay.delay_ms(1000); + println!("Testing resistance"); + test_pins[0].switch_into_output(); + test_pins[2].switch_into_output(); + test_pins[0].set_high(); + test_pins[2].set_low(); + delay.delay_ms(100); + adc_fifo.resume(); + let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait(); + delay.delay_ms(10); + let avg = avg_fifo(buf_for_samples, false); + delay.delay_ms(10); println!("Avg: {}", avg); + + adc_fifo.pause(); + adc_fifo.clear(); + dma_transfer = single_buffer::Config::new(ch, adc_read_target, buf_for_samples).start(); + + // CLEAN UP + delay.delay_ms(1000); + println!("Draining outputs"); + + test_pins.iter_mut().for_each(|tp| { + tp.switch_into_output(); + tp.set_low(); + }); } } -fn avg_fifo(adc_fifo: &mut rp2040_hal::adc::AdcFifo) -> u32 { +fn avg_fifo(samps: &[u16; NUM_ADC_SAMPLES], log_all: bool) -> u32 { let mut avg = 0u32; - for i in 0..8 { - let samp = adc_fifo.read(); - println!("Value {}, {}", i, samp); - avg += samp as u32; + if log_all { + info!("{}", samps[0..NUM_ADC_SAMPLES]); } - - avg /= 8; - avg + samps.iter().for_each(|n| { + avg += *n as u32; + }); + avg / (NUM_ADC_SAMPLES as u32) } enum MyPinMode { Input, Output, + Floating, } struct MyPin { mode: MyPinMode, i_pin: Option>, o_pin: Option>, + d_pin: Option>, } impl MyPin { @@ -200,6 +247,7 @@ impl MyPin { .into_pull_type::(), ), o_pin: None, + d_pin: None, }, MyPinMode::Output => MyPin { mode, @@ -209,59 +257,108 @@ impl MyPin { .unwrap() .into_pull_type::(), ), + d_pin: None, + }, + MyPinMode::Floating => MyPin { + mode, + i_pin: None, + o_pin: None, + d_pin: Some(pin.into_pull_type::()), }, } } - fn switch_to_input(&mut self) { - match self.mode { - MyPinMode::Input => (), + fn switch_to_floating(&mut self) { + self.d_pin = match self.mode { + MyPinMode::Floating => return, + MyPinMode::Input => { + let pin = self.i_pin.take().unwrap(); + Some( + pin.into_pull_type::() + .try_into_function::() + .unwrap() + .into_pull_type::(), + ) + } MyPinMode::Output => { let pin = self.o_pin.take().unwrap(); - self.i_pin = Some( + Some( + pin.into_pull_type::() + .try_into_function::() + .unwrap() + .into_pull_type::(), + ) + } + }; + self.mode = MyPinMode::Floating; + } + fn switch_to_input(&mut self) { + self.i_pin = match self.mode { + MyPinMode::Input => return, + MyPinMode::Output => { + let pin = self.o_pin.take().unwrap(); + Some( pin.into_pull_type::() .try_into_function::() - .unwrap(), - ); - self.mode = MyPinMode::Input; + .unwrap() + .into_pull_type::(), + ) } - } + MyPinMode::Floating => { + let pin = self.d_pin.take().unwrap(); + Some( + pin.into_pull_type::() + .try_into_function::() + .unwrap() + .into_pull_type::(), + ) + } + }; + self.mode = MyPinMode::Input; } fn switch_into_output(&mut self) { - match self.mode { + self.o_pin = match self.mode { + MyPinMode::Output => return, MyPinMode::Input => { let pin = self.i_pin.take().unwrap(); - self.o_pin = Some( + Some( pin.into_pull_type::() .try_into_function::() .unwrap(), - ); - self.mode = MyPinMode::Output; + ) } - MyPinMode::Output => (), - } + MyPinMode::Floating => { + let pin = self.d_pin.take().unwrap(); + Some( + pin.into_pull_type::() + .try_into_function::() + .unwrap(), + ) + } + }; + self.mode = MyPinMode::Output; } fn set_low(&mut self) { match self.mode { - MyPinMode::Input => println!("Ignoring set_low for input pin"), MyPinMode::Output => self.o_pin.as_mut().unwrap().set_low().unwrap(), + _ => println!("Ignoring set_low for input or floating pin"), } } fn set_high(&mut self) { match self.mode { - MyPinMode::Input => println!("Ignoring set_high for input pin"), MyPinMode::Output => self.o_pin.as_mut().unwrap().set_high().unwrap(), + _ => println!("Ignoring set_high for input or floating pin"), } } fn is_high(&mut self) -> bool { match self.mode { MyPinMode::Input => self.i_pin.as_mut().unwrap().is_high().unwrap(), - MyPinMode::Output => { - println!("Warning: read of output pin."); + _ => { + println!("Warning: read of output or floating pin."); false } } @@ -270,8 +367,8 @@ impl MyPin { fn is_low(&mut self) -> bool { match self.mode { MyPinMode::Input => self.i_pin.as_mut().unwrap().is_low().unwrap(), - MyPinMode::Output => { - println!("Warning: read of output pin."); + _ => { + println!("Warning: read of output or floating pin."); false } } diff --git a/tests/draw.html b/tests/draw.html new file mode 100644 index 0000000..6d18fff --- /dev/null +++ b/tests/draw.html @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + \ No newline at end of file