Merge pull request #4193 from embediver/pio-i2s-bit-depth-config
embassy-rp: Make bit-depth of I2S PIO program configurable
This commit is contained in:
commit
3ad9b73dd5
@ -9,6 +9,10 @@ use crate::pio::{
|
|||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
|
|
||||||
/// This struct represents an i2s output driver program
|
/// This struct represents an i2s output driver program
|
||||||
|
///
|
||||||
|
/// The sample bit-depth is set through scratch register `Y`.
|
||||||
|
/// `Y` has to be set to sample bit-depth - 2.
|
||||||
|
/// (14 = 16bit, 22 = 24bit, 30 = 32bit)
|
||||||
pub struct PioI2sOutProgram<'d, PIO: Instance> {
|
pub struct PioI2sOutProgram<'d, PIO: Instance> {
|
||||||
prg: LoadedProgram<'d, PIO>,
|
prg: LoadedProgram<'d, PIO>,
|
||||||
}
|
}
|
||||||
@ -17,13 +21,13 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> {
|
|||||||
/// Load the program into the given pio
|
/// Load the program into the given pio
|
||||||
pub fn new(common: &mut Common<'d, PIO>) -> Self {
|
pub fn new(common: &mut Common<'d, PIO>) -> Self {
|
||||||
let prg = pio::pio_asm!(
|
let prg = pio::pio_asm!(
|
||||||
".side_set 2",
|
".side_set 2", // side 0bWB - W = Word Clock, B = Bit Clock
|
||||||
" set x, 14 side 0b01", // side 0bWB - W = Word Clock, B = Bit Clock
|
" mov x, y side 0b01", // y stores sample depth - 2 (14 = 16bit, 22 = 24bit, 30 = 32bit)
|
||||||
"left_data:",
|
"left_data:",
|
||||||
" out pins, 1 side 0b00",
|
" out pins, 1 side 0b00",
|
||||||
" jmp x-- left_data side 0b01",
|
" jmp x-- left_data side 0b01",
|
||||||
" out pins 1 side 0b10",
|
" out pins 1 side 0b10",
|
||||||
" set x, 14 side 0b11",
|
" mov x, y side 0b11",
|
||||||
"right_data:",
|
"right_data:",
|
||||||
" out pins 1 side 0b10",
|
" out pins 1 side 0b10",
|
||||||
" jmp x-- right_data side 0b11",
|
" jmp x-- right_data side 0b11",
|
||||||
@ -53,7 +57,6 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
|
|||||||
lr_clock_pin: Peri<'d, impl PioPin>,
|
lr_clock_pin: Peri<'d, impl PioPin>,
|
||||||
sample_rate: u32,
|
sample_rate: u32,
|
||||||
bit_depth: u32,
|
bit_depth: u32,
|
||||||
channels: u32,
|
|
||||||
program: &PioI2sOutProgram<'d, P>,
|
program: &PioI2sOutProgram<'d, P>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let data_pin = common.make_pio_pin(data_pin);
|
let data_pin = common.make_pio_pin(data_pin);
|
||||||
@ -64,7 +67,7 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
|
|||||||
let mut cfg = Config::default();
|
let mut cfg = Config::default();
|
||||||
cfg.use_program(&program.prg, &[&bit_clock_pin, &left_right_clock_pin]);
|
cfg.use_program(&program.prg, &[&bit_clock_pin, &left_right_clock_pin]);
|
||||||
cfg.set_out_pins(&[&data_pin]);
|
cfg.set_out_pins(&[&data_pin]);
|
||||||
let clock_frequency = sample_rate * bit_depth * channels;
|
let clock_frequency = sample_rate * bit_depth * 2;
|
||||||
cfg.clock_divider = (crate::clocks::clk_sys_freq() as f64 / clock_frequency as f64 / 2.).to_fixed();
|
cfg.clock_divider = (crate::clocks::clk_sys_freq() as f64 / clock_frequency as f64 / 2.).to_fixed();
|
||||||
cfg.shift_out = ShiftConfig {
|
cfg.shift_out = ShiftConfig {
|
||||||
threshold: 32,
|
threshold: 32,
|
||||||
@ -78,6 +81,11 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
|
|||||||
sm.set_config(&cfg);
|
sm.set_config(&cfg);
|
||||||
sm.set_pin_dirs(Direction::Out, &[&data_pin, &left_right_clock_pin, &bit_clock_pin]);
|
sm.set_pin_dirs(Direction::Out, &[&data_pin, &left_right_clock_pin, &bit_clock_pin]);
|
||||||
|
|
||||||
|
// Set the `y` register up to configure the sample depth
|
||||||
|
// The SM counts down to 0 and uses one clock cycle to set up the counter,
|
||||||
|
// which results in bit_depth - 2 as register value.
|
||||||
|
unsafe { sm.set_y(bit_depth - 2) };
|
||||||
|
|
||||||
sm.set_enable(true);
|
sm.set_enable(true);
|
||||||
|
|
||||||
Self { dma: dma.into(), sm }
|
Self { dma: dma.into(), sm }
|
||||||
|
|||||||
@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs {
|
|||||||
|
|
||||||
const SAMPLE_RATE: u32 = 48_000;
|
const SAMPLE_RATE: u32 = 48_000;
|
||||||
const BIT_DEPTH: u32 = 16;
|
const BIT_DEPTH: u32 = 16;
|
||||||
const CHANNELS: u32 = 2;
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) {
|
|||||||
left_right_clock_pin,
|
left_right_clock_pin,
|
||||||
SAMPLE_RATE,
|
SAMPLE_RATE,
|
||||||
BIT_DEPTH,
|
BIT_DEPTH,
|
||||||
CHANNELS,
|
|
||||||
&program,
|
&program,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs {
|
|||||||
|
|
||||||
const SAMPLE_RATE: u32 = 48_000;
|
const SAMPLE_RATE: u32 = 48_000;
|
||||||
const BIT_DEPTH: u32 = 16;
|
const BIT_DEPTH: u32 = 16;
|
||||||
const CHANNELS: u32 = 2;
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) {
|
|||||||
left_right_clock_pin,
|
left_right_clock_pin,
|
||||||
SAMPLE_RATE,
|
SAMPLE_RATE,
|
||||||
BIT_DEPTH,
|
BIT_DEPTH,
|
||||||
CHANNELS,
|
|
||||||
&program,
|
&program,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user