Much better logging, graphing html tool

This commit is contained in:
JP Stringham
2026-01-21 09:47:01 -05:00
parent 1d6ac5e58a
commit af707ac266
3 changed files with 302 additions and 58 deletions

View File

@@ -33,3 +33,7 @@ rustflags = [
# This runner will find a supported SWD debug probe and flash your RP2040 over # This runner will find a supported SWD debug probe and flash your RP2040 over
# SWD: # SWD:
runner = "probe-rs run --chip RP2040 --protocol swd" runner = "probe-rs run --chip RP2040 --protocol swd"
[env]
DEFMT_RTT_BUFFER_SIZE = { value = "4096", force = true }
DEFMT_LOG = { value = "info", force = true }

View File

@@ -1,11 +1,15 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use defmt::println; use cortex_m::singleton;
use defmt::info;
use defmt::{println, write};
use defmt_rtt as _; use defmt_rtt as _;
use panic_probe 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::DynFunction;
use rp2040_hal::gpio::DynPinId; use rp2040_hal::gpio::DynPinId;
use rp2040_hal::gpio::DynPullType; 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 /// if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32; const XTAL_FREQ_HZ: u32 = 12_000_000u32;
const NUM_ADC_SAMPLES: usize = 1024;
/// Entry point to our bare-metal application. /// Entry point to our bare-metal application.
/// ///
/// The `#[rp2040_hal::entry]` macro ensures the Cortex-M start-up code calls this function /// 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()), 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 = 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_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 { loop {
let pushed = input_btn_pin.is_high().unwrap(); let pushed = input_btn_pin.is_high().unwrap();
@@ -111,81 +127,112 @@ fn main() -> ! {
println!("Running test."); println!("Running test.");
delay.delay_ms(500); 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"); println!("Uh oh, voltage on test pins? Aborting test");
continue; continue;
} }
// TEST 1 // TEST 1
delay.delay_ms(10); delay.delay_ms(100);
println!("Testing at 0v"); println!("Testing at 0v");
test_pins[0].switch_into_output(); test_pins[0].switch_into_output();
test_pins[0].set_low(); test_pins[0].set_low();
adc_fifo.clear();
adc_fifo.resume(); adc_fifo.resume();
let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait();
while adc_fifo.len() < 8 { let avg = avg_fifo(buf_for_samples, false);
println!("waiting for ADC... {} / 8", adc_fifo.len());
}
adc_fifo.pause();
let avg = avg_fifo(&mut adc_fifo);
println!("Avg: {}", avg); 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 // TEST 2
delay.delay_ms(10); delay.delay_ms(1000);
println!("Testing at 3.3v"); println!("Testing at 3.3v");
test_pins[0].set_high(); test_pins[0].set_high();
adc_fifo.clear(); delay.delay_ms(100);
adc_fifo.resume(); adc_fifo.resume();
let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait();
while adc_fifo.len() < 8 { let avg = avg_fifo(buf_for_samples, false);
println!("waiting for ADC... {} / 8", adc_fifo.len());
}
adc_fifo.pause();
let avg = avg_fifo(&mut adc_fifo);
println!("Avg: {}", avg); 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 // TEST 3
delay.delay_ms(1000);
println!("Testing floating"); println!("Testing floating");
adc_fifo.clear(); test_pins[2].switch_into_output();
test_pins[2].set_low();
test_pins[0].switch_to_input(); delay.delay_ms(200);
adc_fifo.resume(); adc_fifo.resume();
test_pins[0].switch_to_floating();
while adc_fifo.len() < 8 { let (ch, adc_read_target, buf_for_samples) = dma_transfer.wait();
println!("waiting for ADC... {} / 8", adc_fifo.len()); let avg = avg_fifo(buf_for_samples, true);
} delay.delay_ms(10);
println!("Avg: {}", avg);
adc_fifo.pause(); 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); 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<u16>) -> u32 { fn avg_fifo(samps: &[u16; NUM_ADC_SAMPLES], log_all: bool) -> u32 {
let mut avg = 0u32; let mut avg = 0u32;
for i in 0..8 { if log_all {
let samp = adc_fifo.read(); info!("{}", samps[0..NUM_ADC_SAMPLES]);
println!("Value {}, {}", i, samp);
avg += samp as u32;
} }
samps.iter().for_each(|n| {
avg /= 8; avg += *n as u32;
avg });
avg / (NUM_ADC_SAMPLES as u32)
} }
enum MyPinMode { enum MyPinMode {
Input, Input,
Output, Output,
Floating,
} }
struct MyPin { struct MyPin {
mode: MyPinMode, mode: MyPinMode,
i_pin: Option<Pin<DynPinId, FunctionSioInput, PullNone>>, i_pin: Option<Pin<DynPinId, FunctionSioInput, PullNone>>,
o_pin: Option<Pin<DynPinId, FunctionSioOutput, PullDown>>, o_pin: Option<Pin<DynPinId, FunctionSioOutput, PullDown>>,
d_pin: Option<Pin<DynPinId, FunctionNull, PullNone>>,
} }
impl MyPin { impl MyPin {
@@ -200,6 +247,7 @@ impl MyPin {
.into_pull_type::<PullNone>(), .into_pull_type::<PullNone>(),
), ),
o_pin: None, o_pin: None,
d_pin: None,
}, },
MyPinMode::Output => MyPin { MyPinMode::Output => MyPin {
mode, mode,
@@ -209,59 +257,108 @@ impl MyPin {
.unwrap() .unwrap()
.into_pull_type::<PullDown>(), .into_pull_type::<PullDown>(),
), ),
d_pin: None,
},
MyPinMode::Floating => MyPin {
mode,
i_pin: None,
o_pin: None,
d_pin: Some(pin.into_pull_type::<PullNone>()),
}, },
} }
} }
fn switch_to_input(&mut self) { fn switch_to_floating(&mut self) {
match self.mode { self.d_pin = match self.mode {
MyPinMode::Input => (), MyPinMode::Floating => return,
MyPinMode::Input => {
let pin = self.i_pin.take().unwrap();
Some(
pin.into_pull_type::<PullNone>()
.try_into_function::<FunctionNull>()
.unwrap()
.into_pull_type::<PullNone>(),
)
}
MyPinMode::Output => { MyPinMode::Output => {
let pin = self.o_pin.take().unwrap(); let pin = self.o_pin.take().unwrap();
self.i_pin = Some( Some(
pin.into_pull_type::<PullNone>()
.try_into_function::<FunctionNull>()
.unwrap()
.into_pull_type::<PullNone>(),
)
}
};
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::<PullNone>() pin.into_pull_type::<PullNone>()
.try_into_function::<FunctionSioInput>() .try_into_function::<FunctionSioInput>()
.unwrap(), .unwrap()
); .into_pull_type::<PullNone>(),
self.mode = MyPinMode::Input; )
} }
} MyPinMode::Floating => {
let pin = self.d_pin.take().unwrap();
Some(
pin.into_pull_type::<PullNone>()
.try_into_function::<FunctionSioInput>()
.unwrap()
.into_pull_type::<PullNone>(),
)
}
};
self.mode = MyPinMode::Input;
} }
fn switch_into_output(&mut self) { fn switch_into_output(&mut self) {
match self.mode { self.o_pin = match self.mode {
MyPinMode::Output => return,
MyPinMode::Input => { MyPinMode::Input => {
let pin = self.i_pin.take().unwrap(); let pin = self.i_pin.take().unwrap();
self.o_pin = Some( Some(
pin.into_pull_type::<PullDown>() pin.into_pull_type::<PullDown>()
.try_into_function::<FunctionSioOutput>() .try_into_function::<FunctionSioOutput>()
.unwrap(), .unwrap(),
); )
self.mode = MyPinMode::Output;
} }
MyPinMode::Output => (), MyPinMode::Floating => {
} let pin = self.d_pin.take().unwrap();
Some(
pin.into_pull_type::<PullDown>()
.try_into_function::<FunctionSioOutput>()
.unwrap(),
)
}
};
self.mode = MyPinMode::Output;
} }
fn set_low(&mut self) { fn set_low(&mut self) {
match self.mode { match self.mode {
MyPinMode::Input => println!("Ignoring set_low for input pin"),
MyPinMode::Output => self.o_pin.as_mut().unwrap().set_low().unwrap(), 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) { fn set_high(&mut self) {
match self.mode { match self.mode {
MyPinMode::Input => println!("Ignoring set_high for input pin"),
MyPinMode::Output => self.o_pin.as_mut().unwrap().set_high().unwrap(), 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 { fn is_high(&mut self) -> bool {
match self.mode { match self.mode {
MyPinMode::Input => self.i_pin.as_mut().unwrap().is_high().unwrap(), 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 false
} }
} }
@@ -270,8 +367,8 @@ impl MyPin {
fn is_low(&mut self) -> bool { fn is_low(&mut self) -> bool {
match self.mode { match self.mode {
MyPinMode::Input => self.i_pin.as_mut().unwrap().is_low().unwrap(), 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 false
} }
} }

143
tests/draw.html Normal file

File diff suppressed because one or more lines are too long