1use crate::peripherals::I2s;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum I2sMode {
20 I2s,
22 Pcm,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum I2sRole {
29 Slave,
31 Master,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum ClockEdge {
38 Rising,
40 Falling,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum ChannelCount {
47 Two = 0,
49 Four = 1,
51 Six = 2,
53 Eight = 3,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum DataWidth {
60 Bits8 = 0,
62 Bits10 = 1,
64 Bits12 = 2,
66 Bits14 = 3,
68 Bits16 = 4,
70 Bits18 = 5,
72 Bits20 = 6,
74 Bits24 = 7,
76}
77
78#[derive(Debug, Clone, Copy)]
80pub struct I2sConfig {
81 pub mode: I2sMode,
83 pub role: I2sRole,
85 pub clock_edge: ClockEdge,
87 pub channels: ChannelCount,
89 pub tx_width: DataWidth,
91 pub rx_width: DataWidth,
93 pub bclk_div: u8,
95 pub fs_div_num: u16,
97 pub fs_div_ratio: u16,
99 pub tx_fifo_threshold: u8,
101 pub rx_fifo_threshold: u8,
103 pub loopback: bool,
105}
106
107impl Default for I2sConfig {
108 fn default() -> Self {
109 Self {
110 mode: I2sMode::I2s,
111 role: I2sRole::Master,
112 clock_edge: ClockEdge::Rising,
113 channels: ChannelCount::Two,
114 tx_width: DataWidth::Bits16,
115 rx_width: DataWidth::Bits16,
116 bclk_div: 0,
117 fs_div_num: 0,
118 fs_div_ratio: 0,
119 tx_fifo_threshold: 8,
120 rx_fifo_threshold: 8,
121 loopback: false,
122 }
123 }
124}
125
126pub struct I2sDriver<'d> {
128 _i2s: I2s<'d>,
129}
130
131impl<'d> I2sDriver<'d> {
132 pub fn new(i2s: I2s<'d>) -> Self {
134 Self { _i2s: i2s }
135 }
136
137 fn regs(&self) -> &'static ws63_pac::i2s::RegisterBlock {
138 unsafe { &*I2s::ptr() }
140 }
141
142 pub fn configure(&mut self, config: &I2sConfig) {
144 let r = self.regs();
145
146 let mut mode: u32 = 0;
148 mode |= (config.channels as u32) & 0x03; if matches!(config.clock_edge, ClockEdge::Falling) {
150 mode |= 1 << 2; }
152 if matches!(config.role, I2sRole::Master) {
153 mode |= 1 << 3; }
155 if matches!(config.mode, I2sMode::Pcm) {
156 mode |= 1 << 4; }
158 unsafe {
159 r.mode().write(|w| w.bits(mode));
160 }
161
162 if config.loopback {
164 unsafe {
165 r.version().write(|w| w.bits(1 << 8));
166 }
167 }
168
169 let dw = ((config.tx_width as u32) & 0x07) | (((config.rx_width as u32) & 0x07) << 8);
171 unsafe {
172 r.data_width_set().write(|w| w.bits(dw));
173 }
174
175 let thresh = (config.tx_fifo_threshold as u32 & 0xFF) | ((config.rx_fifo_threshold as u32 & 0xFF) << 8);
177 unsafe {
178 r.fifo_threshold().write(|w| w.bits(thresh));
179 }
180
181 unsafe {
183 r.i2s_bclk_div_num().write(|w| w.bits(config.bclk_div as u32 & 0x7F));
184 r.i2s_fs_div_num().write(|w| w.bits(config.fs_div_num as u32 & 0x3FF));
185 r.i2s_fs_div_ratio_num().write(|w| w.bits(config.fs_div_ratio as u32 & 0x7FF));
186 }
187
188 let crg_val = if matches!(config.role, I2sRole::Master) {
190 0x100 } else {
192 0
193 };
194 unsafe {
195 r.i2s_crg().write(|w| w.bits(crg_val));
196 }
197
198 unsafe {
200 r.signed_ext().write(|w| w.bits(0x01));
201 }
202 }
203
204 pub fn enable_tx(&mut self) {
206 unsafe {
207 self.regs().ct_set().write(|w| w.bits(0x01)); }
209 }
210
211 pub fn enable_rx(&mut self) {
213 unsafe {
214 self.regs().ct_set().write(|w| w.bits(0x02)); }
216 }
217
218 pub fn disable_tx(&mut self) {
220 unsafe {
221 self.regs().ct_clr().write(|w| w.bits(0x01));
222 }
223 }
224
225 pub fn disable_rx(&mut self) {
227 unsafe {
228 self.regs().ct_clr().write(|w| w.bits(0x02));
229 }
230 }
231
232 pub fn reset_tx(&mut self) {
234 unsafe {
235 self.regs().ct_set().write(|w| w.bits(0x04));
236 }
237 }
238
239 pub fn reset_rx(&mut self) {
241 unsafe {
242 self.regs().ct_set().write(|w| w.bits(0x08));
243 }
244 }
245
246 pub fn enable_tx_interrupt(&mut self) {
248 unsafe {
249 self.regs().ct_set().write(|w| w.bits(0x10));
250 }
251 }
252
253 pub fn enable_rx_interrupt(&mut self) {
255 unsafe {
256 self.regs().ct_set().write(|w| w.bits(0x20));
257 }
258 }
259
260 pub fn write_left(&mut self, data: u32) {
262 unsafe {
263 self.regs().left_tx().write(|w| w.bits(data));
264 }
265 }
266
267 pub fn write_right(&mut self, data: u32) {
269 unsafe {
270 self.regs().right_tx().write(|w| w.bits(data));
271 }
272 }
273
274 pub fn read_left(&self) -> u32 {
276 self.regs().left_rx().read().bits()
277 }
278
279 pub fn read_right(&self) -> u32 {
281 self.regs().right_rx().read().bits()
282 }
283
284 pub fn tx_fifo_left_depth(&self) -> u8 {
286 (self.regs().tx_sta().read().bits() & 0xFF) as u8
287 }
288
289 pub fn tx_fifo_right_depth(&self) -> u8 {
291 ((self.regs().tx_sta().read().bits() >> 8) & 0xFF) as u8
292 }
293
294 pub fn rx_fifo_left_depth(&self) -> u8 {
296 (self.regs().rx_sta().read().bits() & 0xFF) as u8
297 }
298
299 pub fn rx_fifo_right_depth(&self) -> u8 {
301 ((self.regs().rx_sta().read().bits() >> 8) & 0xFF) as u8
302 }
303
304 pub fn interrupt_status(&self) -> (bool, bool, bool, bool) {
308 let sts = self.regs().intstatus().read().bits();
309 ((sts & 0x01) != 0, (sts & 0x02) != 0, (sts & 0x04) != 0, (sts & 0x08) != 0)
310 }
311
312 pub fn clear_interrupts(&mut self) {
314 unsafe {
315 self.regs().intclr().write(|w| w.bits(0x0F));
316 }
317 }
318
319 pub fn set_interrupt_mask(
326 &mut self,
327 rx_int_mask: bool,
328 tx_int_mask: bool,
329 rx_overflow_mask: bool,
330 tx_underflow_mask: bool,
331 ) {
332 let mut val: u32 = 0;
333 if rx_int_mask {
334 val |= 0x01;
335 }
336 if tx_int_mask {
337 val |= 0x02;
338 }
339 if rx_overflow_mask {
340 val |= 0x04;
341 }
342 if tx_underflow_mask {
343 val |= 0x08;
344 }
345 unsafe {
346 self.regs().intmask().write(|w| w.bits(val));
347 }
348 }
349
350 pub fn version(&self) -> u8 {
352 (self.regs().version().read().bits() & 0xFF) as u8
353 }
354}