From 0ecf44e099665e33828fe730e58dd7e8496ea7f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Mon, 11 Sep 2023 22:19:30 +0200 Subject: [PATCH] * Simplified encoder code * Added documentation to build.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Holger Müller --- build.rs | 62 +++++++++++++++++++++++++++++++------------------- src/encoder.rs | 15 ++++-------- src/main.rs | 2 +- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/build.rs b/build.rs index c9859a9..be50ac8 100644 --- a/build.rs +++ b/build.rs @@ -11,7 +11,7 @@ #![feature(iter_array_chunks)] use std::env; -use std::f32::consts::PI; +use std::f64::consts::PI; use std::fs::{read, write, File}; use std::io::Write; use std::path::{Path, PathBuf}; @@ -23,28 +23,38 @@ use tinybmp::Bmp; const PDM_BITS: usize = 14; -fn pdm_table() -> Vec { - let pdm_tics = 1 << PDM_BITS; - let mut bits: Vec = Vec::with_capacity(pdm_tics); - let mut qe: f32 = 0.0; - - let vals = (0..pdm_tics) - .map(|i| (((i + (pdm_tics * 3 / 4)) as f32) / ((pdm_tics >> 1) as f32) * PI).sin()); - for v in vals { - qe += v; - if qe > 0.0 { - bits.push(1); - qe -= 1.0; - } else { - bits.push(0); - qe += 1.0; - } - } +// Default waveform function. One sine but starting with the absolute +// minimum value to suppress crackle on startup. +#[inline] +fn i_sine(index: usize, points: usize) -> f64 { + -((index as f64) / (points as f64) * 2.0 * PI).cos() +} - bits.chunks(32) - // .rev() +// PDM modulation based on pseudo code from +// https://en.wikipedia.org/wiki/Pulse-density_modulation +// Takes the number of modulation bits and a curve function as +// parameters. Curve function gets current position and the +// ammount of modulation bits and should return a f64 value between +// -1.0 an 1.0 - preferable starting and ending with -1.0 to +// reduce crackle. Number of point have to be a multiple of 32! +fn pdm_table(nr_points: usize, curve: fn(usize, usize) -> f64) -> Vec { + assert_eq!(nr_points % 32, 0); + let mut qe = 0.0; + (0..nr_points) + .map(|i| curve(i, nr_points)) + .map(|v| { + qe += v; + if qe > 0.0 { + qe -= 1.0; + 1 + } else { + qe += 1.0; + 0 + } + }) + .array_chunks::<32>() .map(|x| x.iter().fold(0u32, |res, b| (res << 1) ^ *b)) - .collect::>() + .collect() } fn bmp2bitstr(s: &str) -> String { @@ -127,17 +137,23 @@ fn main() { .unwrap(); println!("cargo:rustc-link-search={}", out.display()); - let pdm = pdm_table(); - let clk_div_1hz = 125_000_000.0_f32 / 2.0_f32.powi(PDM_BITS as i32); + let pdm = pdm_table(1 << PDM_BITS, i_sine); + // 8 cycles in one table for higher frequencies + let pdm_8 = pdm_table(1 << PDM_BITS, |i, s| i_sine(i * 8, s)); + let clk_div_1hz = 125_000_000.0 / 2.0f32.powi(PDM_BITS as i32); write( out.join("pdm_table.rs"), format!( "\ const PDM_TABLE: [u32; {}] = {:?};\n\ +#[allow(dead_code)]\n\ +const PDM8_TABLE: [u32; {}] = {:?};\n\ const CLK_DIV_1HZ: f32 = {};\n\ ", pdm.len(), pdm, + pdm_8.len(), + pdm_8, clk_div_1hz, ), ) diff --git a/src/encoder.rs b/src/encoder.rs index bbb078a..bf112bc 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -1,8 +1,7 @@ use defmt::info; use embassy_futures::join::join; use embassy_futures::select::{select, Either}; -use embassy_rp::gpio::{Flex, Pin, Pull}; -use embassy_rp::Peripheral; +use embassy_rp::gpio::{Input, Pin}; use embassy_time::{Duration, Timer}; pub enum EncoderDirection { @@ -13,19 +12,13 @@ pub enum EncoderDirection { pub static DELAY_DEFAULT: Duration = Duration::from_millis(5); pub struct Encoder<'d, T: Pin, V: Pin> { - pin_a: Flex<'d, T>, - pin_b: Flex<'d, V>, + pin_a: Input<'d, T>, + pin_b: Input<'d, V>, } impl<'d, T: Pin, V: Pin> Encoder<'d, T, V> { #[inline] - pub fn new(pin_a: impl Peripheral

+ 'd, pin_b: impl Peripheral

+ 'd) -> Self { - let mut pin_a = Flex::new(pin_a); - let mut pin_b = Flex::new(pin_b); - pin_a.set_as_input(); - pin_a.set_pull(Pull::Up); - pin_b.set_as_input(); - pin_b.set_pull(Pull::Up); + pub fn new(pin_a: Input<'d, T>, pin_b: Input<'d, V>) -> Self { Self { pin_a, pin_b } } diff --git a/src/main.rs b/src/main.rs index 7a1bff8..5e3d1e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -155,7 +155,7 @@ fn main() -> ! { let p = embassy_rp::init(Default::default()); info!("Init Input"); - let enc = encoder::Encoder::new(p.PIN_2, p.PIN_4); + let enc = encoder::Encoder::new(Input::new(p.PIN_2, Pull::Up), Input::new(p.PIN_4, Pull::Up)); let button = Input::new(p.PIN_3, Pull::Up); info!("Set up I2c");