Skip to content

Commit

Permalink
* Simplified encoder code
Browse files Browse the repository at this point in the history
* Added documentation to build.rs

Signed-off-by: Holger Müller <zarath@gmx.de>
  • Loading branch information
zarath committed Sep 11, 2023
1 parent ffaaba3 commit 0ecf44e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 35 deletions.
62 changes: 39 additions & 23 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -23,28 +23,38 @@ use tinybmp::Bmp;

const PDM_BITS: usize = 14;

fn pdm_table() -> Vec<u32> {
let pdm_tics = 1 << PDM_BITS;
let mut bits: Vec<u32> = 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<u32> {
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::<Vec<u32>>()
.collect()
}

fn bmp2bitstr(s: &str) -> String {
Expand Down Expand Up @@ -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,
),
)
Expand Down
15 changes: 4 additions & 11 deletions src/encoder.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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<P = T> + 'd, pin_b: impl Peripheral<P = V> + '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 }
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down

0 comments on commit 0ecf44e

Please sign in to comment.