From 1353b3da9cf94d96557cba281b381b62a8a3c510 Mon Sep 17 00:00:00 2001 From: Matt Johnston <matt@ucc.asn.au> Date: Sat, 1 Oct 2022 19:17:35 +0800 Subject: [PATCH] starting ascii art --- examples/rp/src/bin/usb_serial.rs | 86 +++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 0d10d4fb..17dc04f4 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -2,7 +2,7 @@ #![no_main] #![feature(type_alias_impl_trait)] -use defmt::{info, panic}; +use defmt::{info, debug, panic}; use embassy_executor::Spawner; use embassy_time::{Timer, Duration}; use embassy_rp::pac as pac; @@ -112,18 +112,47 @@ async fn run<'d, P: Pin>(pin: &mut Flex<'d, P>, syst: &mut SYST) -> Result<(), D let mut up_x = 1u32; let mut down_x = 1u32; - let mut up = 0u32; - let mut down = 0u32; + + /* + |prev | | + |iter | | + | | | + . | + . . | . + . . | . . + . . | . . + .---------------.---------------.-----------.------ GPIO threshold. Probably isn't really flat. + . . . + . . + . . + . + */ loop { - // number of loops per interrupt-free block + // number of iterations per interrupt-free block const LOOP: usize = 2000; - // count of cycles to target - const T: u32 = 256; - - // BUF iterations from the start (or end?) will be printed - const BUF: usize = 16; + // Range of cycle counts for overshoot. Upper limit is the pullup/pulldown time + // from vcc/gnd to threshold. + // A large upper limit will also decrease the number of samples/second (but will + // perhaps have more entropy bits/sample?) + // Lower limit is necessary because we don't want to hit the threshold immediately + // on reading. + // Empirical values for a 1uF capacitor. + // TODO this could be determined from a calibration step? + // const UPRANGE: u32 = 50000; + // const LOWRANGE: u32 = 15000; + // nice integers + const LOW_OVER: u32 = 15000; + const HIGH_OVER: u32 = LOW_OVER + 8192; + + // for debug printout + // BUF iterations from the start (or end?) will be printed. must be <LOOP + const BUF: usize = 64; + // for end of buffer + // const BUF_START: usize = LOOP - BUF; + // for start of buffer + const BUF_START: usize = 0; let mut ups = [0u32; BUF]; let mut downs = [0u32; BUF]; let mut upx = [0u32; BUF]; @@ -135,24 +164,35 @@ async fn run<'d, P: Pin>(pin: &mut Flex<'d, P>, syst: &mut SYST) -> Result<(), D // taken for the return to centre value (which is targetting `T`). // eg `up_x = step(up_x, down);` let step = |prev: u32, meas: u32| { - if meas < T { - (prev + meas)*2 + // doubling step. + // x[n] = 2*x[n-1] + meas + let v = prev*2 + meas; + + // modulo to sensible range + if v > UPRANGE { + LOWRANGE + (v % (UPRANGE - LOWRANGE)) } else { - prev - prev/4 + meas % T - }.max(1) + v + } }; critical_section::with(|_cs| { + // We alternate between taking the measured down/up values as real output, + // and using it to compute the next overshoot. + // That prevents leaking "real output" values in the timing of subsequent overshoot + // delays. for i in 0..LOOP { pin.set_pull(Pull::Up); syst.clear_current(); let t1 = SYST::get_current(); while pin.is_low() {} let t2 = SYST::get_current(); - up = t1 - t2; + let t_up = t1 - t2; if i % 2 == 0 { - down_x = step(down_x, up); + down_x = step(down_x, t_up); + } else { + // TODO: keep `up` as our random output } cortex_m::asm::delay(up_x); @@ -161,21 +201,25 @@ async fn run<'d, P: Pin>(pin: &mut Flex<'d, P>, syst: &mut SYST) -> Result<(), D let t1 = SYST::get_current(); while pin.is_high() {} let t2 = SYST::get_current(); - down = t1 - t2; + let t_down = t1 - t2; if i % 2 == 0 { - up_x = step(up_x, down); + up_x = step(up_x, t_down); + } else { + // TODO: keep `down` as our random output } cortex_m::asm::delay(down_x); - if i >= LOOP-BUF { - let n = i - (LOOP-BUF); - ups[n] = up; + if (BUF_START..BUF_START+BUF).contains(i) { + let n = i - BUF_START; + ups[n] = t_up; upx[n] = up_x; - downs[n] = down; + downs[n] = t_down; downx[n] = down_x; } } + // put it in idle state so it'll be closer to threshold + // on the next critical_section iteration. pin.set_pull(Pull::None); }); -- GitLab