aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp')
-rw-r--r--embassy-rp/src/pio_programs/i2s.rs18
1 files changed, 13 insertions, 5 deletions
diff --git a/embassy-rp/src/pio_programs/i2s.rs b/embassy-rp/src/pio_programs/i2s.rs
index b967f0160..7ceed3fa6 100644
--- a/embassy-rp/src/pio_programs/i2s.rs
+++ b/embassy-rp/src/pio_programs/i2s.rs
@@ -9,6 +9,10 @@ use crate::pio::{
9use crate::Peri; 9use crate::Peri;
10 10
11/// This struct represents an i2s output driver program 11/// This struct represents an i2s output driver program
12///
13/// The sample bit-depth is set through scratch register `Y`.
14/// `Y` has to be set to sample bit-depth - 2.
15/// (14 = 16bit, 22 = 24bit, 30 = 32bit)
12pub struct PioI2sOutProgram<'d, PIO: Instance> { 16pub struct PioI2sOutProgram<'d, PIO: Instance> {
13 prg: LoadedProgram<'d, PIO>, 17 prg: LoadedProgram<'d, PIO>,
14} 18}
@@ -17,13 +21,13 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> {
17 /// Load the program into the given pio 21 /// Load the program into the given pio
18 pub fn new(common: &mut Common<'d, PIO>) -> Self { 22 pub fn new(common: &mut Common<'d, PIO>) -> Self {
19 let prg = pio::pio_asm!( 23 let prg = pio::pio_asm!(
20 ".side_set 2", 24 ".side_set 2", // side 0bWB - W = Word Clock, B = Bit Clock
21 " set x, 14 side 0b01", // side 0bWB - W = Word Clock, B = Bit Clock 25 " mov x, y side 0b01", // y stores sample depth - 2 (14 = 16bit, 22 = 24bit, 30 = 32bit)
22 "left_data:", 26 "left_data:",
23 " out pins, 1 side 0b00", 27 " out pins, 1 side 0b00",
24 " jmp x-- left_data side 0b01", 28 " jmp x-- left_data side 0b01",
25 " out pins 1 side 0b10", 29 " out pins 1 side 0b10",
26 " set x, 14 side 0b11", 30 " mov x, y side 0b11",
27 "right_data:", 31 "right_data:",
28 " out pins 1 side 0b10", 32 " out pins 1 side 0b10",
29 " jmp x-- right_data side 0b11", 33 " jmp x-- right_data side 0b11",
@@ -53,7 +57,6 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
53 lr_clock_pin: Peri<'d, impl PioPin>, 57 lr_clock_pin: Peri<'d, impl PioPin>,
54 sample_rate: u32, 58 sample_rate: u32,
55 bit_depth: u32, 59 bit_depth: u32,
56 channels: u32,
57 program: &PioI2sOutProgram<'d, P>, 60 program: &PioI2sOutProgram<'d, P>,
58 ) -> Self { 61 ) -> Self {
59 let data_pin = common.make_pio_pin(data_pin); 62 let data_pin = common.make_pio_pin(data_pin);
@@ -64,7 +67,7 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
64 let mut cfg = Config::default(); 67 let mut cfg = Config::default();
65 cfg.use_program(&program.prg, &[&bit_clock_pin, &left_right_clock_pin]); 68 cfg.use_program(&program.prg, &[&bit_clock_pin, &left_right_clock_pin]);
66 cfg.set_out_pins(&[&data_pin]); 69 cfg.set_out_pins(&[&data_pin]);
67 let clock_frequency = sample_rate * bit_depth * channels; 70 let clock_frequency = sample_rate * bit_depth * 2;
68 cfg.clock_divider = (crate::clocks::clk_sys_freq() as f64 / clock_frequency as f64 / 2.).to_fixed(); 71 cfg.clock_divider = (crate::clocks::clk_sys_freq() as f64 / clock_frequency as f64 / 2.).to_fixed();
69 cfg.shift_out = ShiftConfig { 72 cfg.shift_out = ShiftConfig {
70 threshold: 32, 73 threshold: 32,
@@ -78,6 +81,11 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
78 sm.set_config(&cfg); 81 sm.set_config(&cfg);
79 sm.set_pin_dirs(Direction::Out, &[&data_pin, &left_right_clock_pin, &bit_clock_pin]); 82 sm.set_pin_dirs(Direction::Out, &[&data_pin, &left_right_clock_pin, &bit_clock_pin]);
80 83
84 // Set the `y` register up to configure the sample depth
85 // The SM counts down to 0 and uses one clock cycle to set up the counter,
86 // which results in bit_depth - 2 as register value.
87 unsafe { sm.set_y(bit_depth - 2) };
88
81 sm.set_enable(true); 89 sm.set_enable(true);
82 90
83 Self { dma: dma.into(), sm } 91 Self { dma: dma.into(), sm }