WIP: Started microphone support
This commit is contained in:
parent
1f220b233f
commit
a36eab3aa1
5 changed files with 234 additions and 0 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -115,6 +115,7 @@ dependencies = [
|
||||||
"bitmask-enum",
|
"bitmask-enum",
|
||||||
"embedded-hal-bus",
|
"embedded-hal-bus",
|
||||||
"esp-hal",
|
"esp-hal",
|
||||||
|
"esp32s3",
|
||||||
"mipidsi",
|
"mipidsi",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ bitflags = "2.9.1"
|
||||||
bitmask-enum = "2.2.5"
|
bitmask-enum = "2.2.5"
|
||||||
embedded-hal-bus = "0.3.0"
|
embedded-hal-bus = "0.3.0"
|
||||||
esp-hal = {version = "=1.0.0-beta.1", features = ["esp32s3", "unstable"]}
|
esp-hal = {version = "=1.0.0-beta.1", features = ["esp32s3", "unstable"]}
|
||||||
|
esp32s3 = "0.32.0"
|
||||||
mipidsi = "0.9.0"
|
mipidsi = "0.9.0"
|
||||||
thiserror = {version = "2.0.11", default-features = false}
|
thiserror = {version = "2.0.11", default-features = false}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
pub mod display;
|
pub mod display;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
|
pub mod microphone;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
||||||
38
src/microphone.rs
Normal file
38
src/microphone.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
use crate::microphone::clock_calculation::{calculate_clock, set_clock};
|
||||||
|
|
||||||
|
mod clock_calculation;
|
||||||
|
|
||||||
|
fn mic(i2s0: esp_hal::peripherals::I2S0) {
|
||||||
|
drop(i2s0);
|
||||||
|
|
||||||
|
let i2s0 = unsafe { esp32s3::I2S0::steal() };
|
||||||
|
|
||||||
|
// clear clock config register
|
||||||
|
// i2s0.rx_clkm_conf().reset();
|
||||||
|
// i2s0.rx_conf().reset();
|
||||||
|
|
||||||
|
set_clock(
|
||||||
|
&i2s0,
|
||||||
|
calculate_clock(esp_hal::time::Rate::from_mhz(2), 1, 16),
|
||||||
|
);
|
||||||
|
|
||||||
|
let gpio = unsafe { esp32s3::GPIO::steal() };
|
||||||
|
gpio.func46_in_sel_cfg().modify(|_, w| w.)
|
||||||
|
|
||||||
|
// let io_mux = unsafe { esp32s3::IO_MUX::steal() };
|
||||||
|
// io_mux.gpio(46).modify(|_, w| w.)
|
||||||
|
|
||||||
|
i2s0.rx_conf()
|
||||||
|
.modify(|_, w| w.rx_reset().set_bit().rx_fifo_reset().set_bit());
|
||||||
|
|
||||||
|
i2s0.rx_conf()
|
||||||
|
.modify(|_, w| w.rx_reset().clear_bit().rx_fifo_reset().clear_bit());
|
||||||
|
|
||||||
|
i2s0.rx_conf().modify(|_, w| w.rx_ws_idle_pol().clear_bit());
|
||||||
|
|
||||||
|
i2s0.rx_conf1()
|
||||||
|
.modify(|_, w| unsafe { w.rx_half_sample_bits().bits(15).rx_bits_mod().bits(15) });
|
||||||
|
|
||||||
|
// Enable PDM mode
|
||||||
|
i2s0.rx_conf().modify(|_, w| w.rx_pdm_en().set_bit());
|
||||||
|
}
|
||||||
193
src/microphone/clock_calculation.rs
Normal file
193
src/microphone/clock_calculation.rs
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
//! This module contains code lifted from esp-rs/esp-hal,
|
||||||
|
//! which has been slightly modified for use in this library.
|
||||||
|
//!
|
||||||
|
//! ## License
|
||||||
|
//!
|
||||||
|
//! Copyright 2021 esp-rs
|
||||||
|
//!
|
||||||
|
//! Permission is hereby granted, free of charge, to any
|
||||||
|
//! person obtaining a copy of this software and associated
|
||||||
|
//! documentation files (the "Software"), to deal in the
|
||||||
|
//! Software without restriction, including without
|
||||||
|
//! limitation the rights to use, copy, modify, merge,
|
||||||
|
//! publish, distribute, sublicense, and/or sell copies of
|
||||||
|
//! the Software, and to permit persons to whom the Software
|
||||||
|
//! is furnished to do so, subject to the following
|
||||||
|
//! conditions:
|
||||||
|
//!
|
||||||
|
//! The above copyright notice and this permission notice
|
||||||
|
//! shall be included in all copies or substantial portions
|
||||||
|
//! of the Software.
|
||||||
|
//!
|
||||||
|
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
//! ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||||
|
//! TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
//! PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||||
|
//! SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
//! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
//! OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
//! IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
//! DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
use esp_hal::time::Rate;
|
||||||
|
|
||||||
|
pub(super) struct I2sClockDividers {
|
||||||
|
mclk_divider: u32,
|
||||||
|
bclk_divider: u32,
|
||||||
|
denominator: u32,
|
||||||
|
numerator: u32,
|
||||||
|
}
|
||||||
|
/// The default clock source for I2S operations.
|
||||||
|
const I2S_DEFAULT_CLK_SRC: u8 = 2;
|
||||||
|
|
||||||
|
const I2S_SCLK: u32 = 160_000_000;
|
||||||
|
|
||||||
|
const I2S_LL_MCLK_DIVIDER_BIT_WIDTH: usize = 6;
|
||||||
|
|
||||||
|
const I2S_LL_MCLK_DIVIDER_MAX: usize = (1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1;
|
||||||
|
|
||||||
|
pub(super) fn calculate_clock(sample_rate: Rate, channels: u8, data_bits: u8) -> I2sClockDividers {
|
||||||
|
// this loosely corresponds to `i2s_std_calculate_clock` and
|
||||||
|
// `i2s_ll_tx_set_mclk` in esp-idf
|
||||||
|
//
|
||||||
|
// main difference is we are using fixed-point arithmetic here
|
||||||
|
|
||||||
|
// If data_bits is a power of two, use 256 as the mclk_multiple
|
||||||
|
// If data_bits is 24, use 192 (24 * 8) as the mclk_multiple
|
||||||
|
let mclk_multiple = if data_bits == 24 { 192 } else { 256 };
|
||||||
|
let sclk = I2S_SCLK; // for now it's fixed 160MHz
|
||||||
|
|
||||||
|
let rate = sample_rate.as_hz();
|
||||||
|
|
||||||
|
let bclk = rate * channels as u32 * data_bits as u32;
|
||||||
|
let mclk = rate * mclk_multiple;
|
||||||
|
let bclk_divider = mclk / bclk;
|
||||||
|
let mut mclk_divider = sclk / mclk;
|
||||||
|
|
||||||
|
let mut ma: u32;
|
||||||
|
let mut mb: u32;
|
||||||
|
let mut denominator: u32 = 0;
|
||||||
|
let mut numerator: u32 = 0;
|
||||||
|
|
||||||
|
let freq_diff = sclk.abs_diff(mclk * mclk_divider);
|
||||||
|
|
||||||
|
if freq_diff != 0 {
|
||||||
|
let decimal = freq_diff as u64 * 10000 / mclk as u64;
|
||||||
|
|
||||||
|
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 /
|
||||||
|
// 126.0
|
||||||
|
if decimal > 1250000 / 126 {
|
||||||
|
mclk_divider += 1;
|
||||||
|
} else {
|
||||||
|
let mut min: u32 = !0;
|
||||||
|
|
||||||
|
for a in 2..=I2S_LL_MCLK_DIVIDER_MAX {
|
||||||
|
let b = (a as u64) * (freq_diff as u64 * 10000u64 / mclk as u64) + 5000;
|
||||||
|
ma = ((freq_diff as u64 * 10000u64 * a as u64) / 10000) as u32;
|
||||||
|
mb = (mclk as u64 * (b / 10000)) as u32;
|
||||||
|
|
||||||
|
if ma == mb {
|
||||||
|
denominator = a as u32;
|
||||||
|
numerator = (b / 10000) as u32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mb.abs_diff(ma) < min {
|
||||||
|
denominator = a as u32;
|
||||||
|
numerator = b as u32;
|
||||||
|
min = mb.abs_diff(ma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
I2sClockDividers {
|
||||||
|
mclk_divider,
|
||||||
|
bclk_divider,
|
||||||
|
denominator,
|
||||||
|
numerator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn set_clock(i2s0: &esp32s3::I2S0, clock_settings: I2sClockDividers) {
|
||||||
|
let clkm_div_x: u32;
|
||||||
|
let clkm_div_y: u32;
|
||||||
|
let clkm_div_z: u32;
|
||||||
|
let clkm_div_yn1: u32;
|
||||||
|
|
||||||
|
if clock_settings.denominator == 0 || clock_settings.numerator == 0 {
|
||||||
|
clkm_div_x = 0;
|
||||||
|
clkm_div_y = 0;
|
||||||
|
clkm_div_z = 0;
|
||||||
|
clkm_div_yn1 = 1;
|
||||||
|
} else if clock_settings.numerator > clock_settings.denominator / 2 {
|
||||||
|
clkm_div_x = clock_settings
|
||||||
|
.denominator
|
||||||
|
.overflowing_div(
|
||||||
|
clock_settings
|
||||||
|
.denominator
|
||||||
|
.overflowing_sub(clock_settings.numerator)
|
||||||
|
.0,
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.overflowing_sub(1)
|
||||||
|
.0;
|
||||||
|
clkm_div_y = clock_settings.denominator
|
||||||
|
% (clock_settings
|
||||||
|
.denominator
|
||||||
|
.overflowing_sub(clock_settings.numerator)
|
||||||
|
.0);
|
||||||
|
clkm_div_z = clock_settings
|
||||||
|
.denominator
|
||||||
|
.overflowing_sub(clock_settings.numerator)
|
||||||
|
.0;
|
||||||
|
clkm_div_yn1 = 1;
|
||||||
|
} else {
|
||||||
|
clkm_div_x = clock_settings.denominator / clock_settings.numerator - 1;
|
||||||
|
clkm_div_y = clock_settings.denominator % clock_settings.numerator;
|
||||||
|
clkm_div_z = clock_settings.numerator;
|
||||||
|
clkm_div_yn1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2s0.tx_clkm_div_conf().modify(|_, w| unsafe {
|
||||||
|
w.tx_clkm_div_x().bits(clkm_div_x as u16);
|
||||||
|
w.tx_clkm_div_y().bits(clkm_div_y as u16);
|
||||||
|
w.tx_clkm_div_yn1().bit(clkm_div_yn1 != 0);
|
||||||
|
w.tx_clkm_div_z().bits(clkm_div_z as u16)
|
||||||
|
});
|
||||||
|
|
||||||
|
i2s0.tx_clkm_conf().modify(|_, w| unsafe {
|
||||||
|
w.clk_en().set_bit();
|
||||||
|
w.tx_clk_active().set_bit();
|
||||||
|
w.tx_clk_sel()
|
||||||
|
.bits(I2S_DEFAULT_CLK_SRC) // for now fixed at 160MHz
|
||||||
|
;
|
||||||
|
w.tx_clkm_div_num().bits(clock_settings.mclk_divider as u8)
|
||||||
|
});
|
||||||
|
|
||||||
|
i2s0.tx_conf1().modify(|_, w| unsafe {
|
||||||
|
w.tx_bck_div_num()
|
||||||
|
.bits((clock_settings.bclk_divider - 1) as u8)
|
||||||
|
});
|
||||||
|
|
||||||
|
i2s0.rx_clkm_div_conf().modify(|_, w| unsafe {
|
||||||
|
w.rx_clkm_div_x().bits(clkm_div_x as u16);
|
||||||
|
w.rx_clkm_div_y().bits(clkm_div_y as u16);
|
||||||
|
w.rx_clkm_div_yn1().bit(clkm_div_yn1 != 0);
|
||||||
|
w.rx_clkm_div_z().bits(clkm_div_z as u16)
|
||||||
|
});
|
||||||
|
|
||||||
|
i2s0.rx_clkm_conf().modify(|_, w| unsafe {
|
||||||
|
w.rx_clk_active().set_bit();
|
||||||
|
// for now fixed at 160MHz
|
||||||
|
w.rx_clk_sel()
|
||||||
|
.bits(I2S_DEFAULT_CLK_SRC);
|
||||||
|
w.rx_clkm_div_num().bits(clock_settings.mclk_divider as u8);
|
||||||
|
w.mclk_sel().bit(true)
|
||||||
|
});
|
||||||
|
|
||||||
|
i2s0.rx_conf1().modify(|_, w| unsafe {
|
||||||
|
w.rx_bck_div_num()
|
||||||
|
.bits((clock_settings.bclk_divider - 1) as u8)
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue