Mathias Gottschlag 5 年之前
父節點
當前提交
f935152ff5
共有 2 個檔案被更改,包括 279 行新增168 行删除
  1. 223
    168
      hackamp/firmware/src/halext/i2s.rs
  2. 56
    0
      hackamp/firmware/src/halext/sai.rs

+ 223
- 168
hackamp/firmware/src/halext/i2s.rs 查看文件

@@ -46,11 +46,58 @@ impl I2SClocks {
46 46
     }
47 47
 }
48 48
 
49
+pub type I2S2 = (SPI2, I2S2EXT);
50
+pub type I2S3 = (SPI3, I2S3EXT);
51
+
52
+/// Trait for master clock pins.
53
+pub trait MCK<I2S> {}
54
+
55
+impl MCK<I2S2> for PC6<Alternate5> {}
56
+impl MCK<I2S3> for PC7<Alternate6> {}
57
+
58
+/// Trait for word select pins.
59
+pub trait WS<I2S> {}
60
+
61
+impl WS<I2S3> for PA4<Alternate6> {}
62
+impl WS<I2S3> for PA15<Alternate6> {}
63
+impl WS<I2S2> for PB9<Alternate5> {}
64
+impl WS<I2S2> for PB12<Alternate5> {}
65
+impl WS<I2S2> for PI0<Alternate5> {}
66
+
67
+/// Trait for bit clock pins.
68
+pub trait CK<I2S> {}
69
+
70
+impl CK<I2S3> for PB3<Alternate6> {}
71
+impl CK<I2S2> for PB10<Alternate5> {}
72
+impl CK<I2S2> for PB13<Alternate5> {}
73
+impl CK<I2S3> for PC10<Alternate6> {}
74
+impl CK<I2S2> for PD3<Alternate5> {}
75
+impl CK<I2S2> for PI1<Alternate5> {}
76
+
77
+/// Trait for serial data input pins.
78
+pub trait SDI<I2S> {}
79
+
80
+impl SDI<I2S3> for PB4<Alternate7> {}
81
+impl SDI<I2S2> for PB14<Alternate6> {}
82
+impl SDI<I2S2> for PC2<Alternate6> {}
83
+impl SDI<I2S3> for PC11<Alternate5> {}
84
+impl SDI<I2S2> for PI2<Alternate6> {}
85
+
86
+/// Trait for serial data output pins.
87
+pub trait SDO<I2S> {}
88
+
89
+impl SDO<I2S3> for PB5<Alternate6> {}
90
+impl SDO<I2S2> for PB15<Alternate5> {}
91
+impl SDO<I2S2> for PC3<Alternate5> {}
92
+impl SDO<I2S3> for PC12<Alternate6> {}
93
+impl SDO<I2S3> for PD6<Alternate5> {}
94
+impl SDO<I2S2> for PI3<Alternate5> {}
95
+
49 96
 /// I2S interface with DMA data transfer.
50
-pub struct I2S {
51
-    spi: SPI2,
52
-    i2sext: I2S2EXT,
53
-    rx_dma: dma::Stream3<DMA1>,
97
+pub struct I2S<SPI, I2SEXT> {
98
+    spi: SPI,
99
+    i2sext: I2SEXT,
100
+    rx_dma: dma::Stream3<DMA1>, // TODO: Correct DMA unit?
54 101
     tx_dma: dma::Stream4<DMA1>,
55 102
     in_: &'static AudioBuffer,
56 103
     in_packets: [Option<WritePacket>; 2],
@@ -58,175 +105,183 @@ pub struct I2S {
58 105
     out_packets: [Option<ReadPacket>; 2],
59 106
 }
60 107
 
61
-impl I2S {
62
-    /// Initializes the I2S interface to read from/write to the specified buffers.
63
-    ///
64
-    /// The interface is only started when the `start()` function is called.
65
-    pub fn new(
66
-        spi: SPI2,
67
-        i2sext: I2S2EXT,
68
-        mut rx_dma: dma::Stream3<DMA1>,
69
-        mut tx_dma: dma::Stream4<DMA1>,
70
-        mck: PC6<Alternate<AF5>>,
71
-        ws: PB12<Alternate<AF5>>,
72
-        ck: PB13<Alternate<AF5>>,
73
-        sdin: PB14<Alternate<AF6>>,
74
-        sdout: PB15<Alternate<AF5>>,
75
-        in_: &'static AudioBuffer,
76
-        out: &'static AudioBuffer,
77
-        _clocks: I2SClocks,
78
-    ) -> I2S {
79
-        // Enable and reset the peripheral.
80
-        let rcc = unsafe { &*RCC::ptr() };
81
-        rcc.apb1enr.modify(|_, w| w.spi2en().set_bit());
82
-        rcc.apb1rstr.modify(|_, w| w.spi2rst().set_bit());
83
-        rcc.apb1rstr.modify(|_, w| w.spi2rst().clear_bit());
84
-        //rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit());
85
-
86
-        // Disable SS output.
87
-        spi.cr2.write(|w| w.ssoe().clear_bit());
88
-
89
-        // Configure the pins.
90
-        // TODO
108
+macro_rules! i2s_impl {
109
+    ($SPIX:ident, $I2SXEXT:ident, $spiXen:ident,$spiXrst:ident) => {
110
+        impl I2S<SPIX, I2SXEXT> {
111
+            /// Initializes the I2S interface to read from/write to the specified buffers.
112
+            ///
113
+            /// The interface is only started when the `start()` function is called.
114
+            pub fn new(
115
+                spi: SPIX,
116
+                i2sext: I2SXEXT,
117
+                mut rx_dma: dma::Stream3<DMA1>, // TODO: Correct DMA streams
118
+                mut tx_dma: dma::Stream4<DMA1>,
119
+                mck: MCK<(SPIX, I2SXEXT)>,
120
+                ws: WS<(SPIX, I2SXEXT)>,
121
+                ck: CK<(SPIX, I2SXEXT)>,
122
+                sdin: SDI<(SPIX, I2SXEXT)>,
123
+                sdout: SDO<(SPIX, I2SXEXT)>,
124
+                in_: &'static AudioBuffer,
125
+                out: &'static AudioBuffer,
126
+                _clocks: I2SClocks,
127
+            ) -> Self {
128
+                // Enable and reset the peripheral.
129
+                let rcc = unsafe { &*RCC::ptr() };
130
+                rcc.apb1enr.modify(|_, w| w.spi2en().set_bit());
131
+                rcc.apb1rstr.modify(|_, w| w.spi2rst().set_bit());
132
+                rcc.apb1rstr.modify(|_, w| w.spi2rst().clear_bit());
133
+                //rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit());
91 134
 
92
-        // Configure the clocks.
93
-        // For the values, see the comment in I2SClocks::init().
94
-        spi.i2spr
95
-            .write(|w| unsafe { w.mckoe().set_bit().odd().set_bit().i2sdiv().bits(3) });
96
-        i2sext
97
-            .i2spr
98
-            .write(|w| unsafe { w.mckoe().set_bit().odd().set_bit().i2sdiv().bits(3) });
99
-
100
-        // Configure I2S.
101
-        spi.i2scfgr.modify(|_, w| unsafe {
102
-            w.i2smod()
103
-                .set_bit()
104
-                .i2se()
105
-                .clear_bit()
106
-                .i2scfg()
107
-                .master_tx()
108
-                .i2sstd()
109
-                .bits(0b01)
110
-                .ckpol()
111
-                .idle_high()
112
-                .datlen()
113
-                .bits(0b10)
114
-                .chlen()
115
-                .set_bit()
116
-        });
117
-        i2sext.i2scfgr.modify(|_, w| unsafe {
118
-            w.i2smod()
119
-                .set_bit()
120
-                .i2se()
121
-                .clear_bit()
122
-                .i2scfg()
123
-                .slave_rx()
124
-                .i2sstd()
125
-                .bits(0b01)
126
-                .ckpol()
127
-                .idle_high()
128
-                .datlen()
129
-                .bits(0b10)
130
-                .chlen()
131
-                .set_bit()
132
-        });
133
-        i2sext.cr2.modify(|_, w| w.rxdmaen().set_bit());
134
-        spi.cr2.modify(|_, w| w.txdmaen().set_bit());
135
-
136
-        rx_dma.set_channel(dma::Channel3);
137
-        rx_dma.clear_interrupts();
138
-        unsafe {
139
-            rx_dma.set_memory_size(1);
140
-            rx_dma.set_peripheral_size(1);
141
-        }
142
-        rx_dma.set_memory_increment(true);
143
-        rx_dma.set_direction(dma::PeripheralToMemory);
144
-        rx_dma.set_interrupts_enable(true, false, true, true);
145
-        rx_dma.set_double_buffer(true);
146
-        rx_dma.set_fifo_enable(false);
147
-        rx_dma.set_number_of_transfers((SAMPLES_PER_PACKET * CHANNELS * 2) as u16);
148
-
149
-        tx_dma.set_channel(dma::Channel0);
150
-        tx_dma.clear_interrupts();
151
-        unsafe {
152
-            tx_dma.set_memory_size(1);
153
-            tx_dma.set_peripheral_size(1);
154
-        }
155
-        tx_dma.set_memory_increment(true);
156
-        tx_dma.set_direction(dma::MemoryToPeripheral);
157
-        tx_dma.set_interrupts_enable(true, false, true, true);
158
-        tx_dma.set_double_buffer(true);
159
-        tx_dma.set_fifo_enable(false);
160
-        tx_dma.set_number_of_transfers((SAMPLES_PER_PACKET * CHANNELS * 2) as u16);
161
-
162
-        const DR_OFFSET: usize = 0x0c;
163
-        let spi_dr = SPI2::ptr() as usize + DR_OFFSET;
164
-        let i2sext_dr = I2S2EXT::ptr() as usize + DR_OFFSET;
165
-        rx_dma.set_peripheral_address(i2sext_dr as u32);
166
-        tx_dma.set_peripheral_address(spi_dr as u32);
167
-
168
-        I2S {
169
-            spi,
170
-            i2sext,
171
-            rx_dma,
172
-            tx_dma,
173
-            in_,
174
-            in_packets: [None, None],
175
-            out,
176
-            out_packets: [None, None],
177
-        }
178
-    }
135
+                // Disable SS output.
136
+                spi.cr2.write(|w| w.ssoe().clear_bit());
179 137
 
180
-    /// Starts the data stream of the I2S interface.
181
-    pub fn start(&mut self) {
182
-        interrupt::free(|cs| {
183
-            for i in 0..2 {
184
-                self.in_packets[i] = self.in_.borrow_write(cs);
185
-            }
186
-            for i in 0..2 {
187
-                self.out_packets[i] = self.out.borrow_read(cs);
188
-            }
189
-        });
190
-
191
-        // The system was just started, and some buffers were filled with dummy data, so we can
192
-        // assume that borrowing was successful.
193
-        let in_0 = self.in_packets[0].as_mut().unwrap().as_mut().as_ptr() as usize as u32;
194
-        let in_1 = self.in_packets[1].as_mut().unwrap().as_mut().as_ptr() as usize as u32;
195
-        self.rx_dma.set_memory_address(in_0);
196
-        self.rx_dma.set_memory_double_buffer_address(in_1);
197
-        /*self.dma.st[3].m0ar.write(|w| unsafe { w.bits(in_0) });
198
-        self.dma.st[3].m1ar.write(|w| unsafe { w.bits(in_1) });*/
199
-        let out_0 = self.out_packets[0].as_ref().unwrap().as_ref().as_ptr() as usize as u32;
200
-        let out_1 = self.out_packets[1].as_ref().unwrap().as_ref().as_ptr() as usize as u32;
201
-        self.tx_dma.set_memory_address(out_0);
202
-        self.tx_dma.set_memory_double_buffer_address(out_1);
203
-        /*self.dma.st[4].m0ar.write(|w| unsafe { w.bits(out_0) });
204
-        self.dma.st[4].m1ar.write(|w| unsafe { w.bits(out_1) });*/
205
-
206
-        // Enable DMA and activate the I2S peripherals.
207
-        /*self.dma.st[3].cr.modify(|_, w| w.en().set_bit());
208
-        self.dma.st[4].cr.modify(|_, w| w.en().set_bit());*/
209
-        unsafe {
210
-            self.rx_dma.enable();
211
-            self.tx_dma.enable();
212
-        }
213
-        self.i2sext.i2scfgr.modify(|_, w| w.i2se().set_bit());
214
-        self.spi.i2scfgr.modify(|_, w| w.i2se().set_bit());
138
+                // Configure the pins.
139
+                // TODO
140
+
141
+                // Configure the clocks.
142
+                // For the values, see the comment in I2SClocks::init().
143
+                spi.i2spr
144
+                    .write(|w| unsafe { w.mckoe().set_bit().odd().set_bit().i2sdiv().bits(3) });
145
+                i2sext
146
+                    .i2spr
147
+                    .write(|w| unsafe { w.mckoe().set_bit().odd().set_bit().i2sdiv().bits(3) });
148
+
149
+                // Configure I2S.
150
+                spi.i2scfgr.modify(|_, w| unsafe {
151
+                    w.i2smod()
152
+                        .set_bit()
153
+                        .i2se()
154
+                        .clear_bit()
155
+                        .i2scfg()
156
+                        .master_tx()
157
+                        .i2sstd()
158
+                        .bits(0b01)
159
+                        .ckpol()
160
+                        .idle_high()
161
+                        .datlen()
162
+                        .bits(0b10)
163
+                        .chlen()
164
+                        .set_bit()
165
+                });
166
+                i2sext.i2scfgr.modify(|_, w| unsafe {
167
+                    w.i2smod()
168
+                        .set_bit()
169
+                        .i2se()
170
+                        .clear_bit()
171
+                        .i2scfg()
172
+                        .slave_rx()
173
+                        .i2sstd()
174
+                        .bits(0b01)
175
+                        .ckpol()
176
+                        .idle_high()
177
+                        .datlen()
178
+                        .bits(0b10)
179
+                        .chlen()
180
+                        .set_bit()
181
+                });
182
+                i2sext.cr2.modify(|_, w| w.rxdmaen().set_bit());
183
+                spi.cr2.modify(|_, w| w.txdmaen().set_bit());
184
+
185
+                rx_dma.set_channel(dma::Channel3);
186
+                rx_dma.clear_interrupts();
187
+                unsafe {
188
+                    rx_dma.set_memory_size(1);
189
+                    rx_dma.set_peripheral_size(1);
190
+                }
191
+                rx_dma.set_memory_increment(true);
192
+                rx_dma.set_direction(dma::PeripheralToMemory);
193
+                rx_dma.set_interrupts_enable(true, false, true, true);
194
+                rx_dma.set_double_buffer(true);
195
+                rx_dma.set_fifo_enable(false);
196
+                rx_dma.set_number_of_transfers((SAMPLES_PER_PACKET * CHANNELS * 2) as u16);
215 197
 
216
-        /*loop {
217
-            if self.spi.sr.read().txe().bit_is_set() {
218
-                self.spi.dr.write(|w| unsafe { w.bits(0xaaaa) });
198
+                tx_dma.set_channel(dma::Channel0);
199
+                tx_dma.clear_interrupts();
200
+                unsafe {
201
+                    tx_dma.set_memory_size(1);
202
+                    tx_dma.set_peripheral_size(1);
203
+                }
204
+                tx_dma.set_memory_increment(true);
205
+                tx_dma.set_direction(dma::MemoryToPeripheral);
206
+                tx_dma.set_interrupts_enable(true, false, true, true);
207
+                tx_dma.set_double_buffer(true);
208
+                tx_dma.set_fifo_enable(false);
209
+                tx_dma.set_number_of_transfers((SAMPLES_PER_PACKET * CHANNELS * 2) as u16);
210
+
211
+                const DR_OFFSET: usize = 0x0c;
212
+                let spi_dr = SPI2::ptr() as usize + DR_OFFSET;
213
+                let i2sext_dr = I2S2EXT::ptr() as usize + DR_OFFSET;
214
+                rx_dma.set_peripheral_address(i2sext_dr as u32);
215
+                tx_dma.set_peripheral_address(spi_dr as u32);
216
+
217
+                I2S {
218
+                    spi,
219
+                    i2sext,
220
+                    rx_dma,
221
+                    tx_dma,
222
+                    in_,
223
+                    in_packets: [None, None],
224
+                    out,
225
+                    out_packets: [None, None],
226
+                }
219 227
             }
220
-            if self.i2sext.sr.read().rxne().bit_is_set() {
221
-                self.i2sext.dr.read();
228
+
229
+            /// Starts the data stream of the I2S interface.
230
+            pub fn start(&mut self) {
231
+                interrupt::free(|cs| {
232
+                    for i in 0..2 {
233
+                        self.in_packets[i] = self.in_.borrow_write(cs);
234
+                    }
235
+                    for i in 0..2 {
236
+                        self.out_packets[i] = self.out.borrow_read(cs);
237
+                    }
238
+                });
239
+
240
+                // The system was just started, and some buffers were filled with dummy data, so we can
241
+                // assume that borrowing was successful.
242
+                let in_0 = self.in_packets[0].as_mut().unwrap().as_mut().as_ptr() as usize as u32;
243
+                let in_1 = self.in_packets[1].as_mut().unwrap().as_mut().as_ptr() as usize as u32;
244
+                self.rx_dma.set_memory_address(in_0);
245
+                self.rx_dma.set_memory_double_buffer_address(in_1);
246
+                /*self.dma.st[3].m0ar.write(|w| unsafe { w.bits(in_0) });
247
+                self.dma.st[3].m1ar.write(|w| unsafe { w.bits(in_1) });*/
248
+                let out_0 = self.out_packets[0].as_ref().unwrap().as_ref().as_ptr() as usize as u32;
249
+                let out_1 = self.out_packets[1].as_ref().unwrap().as_ref().as_ptr() as usize as u32;
250
+                self.tx_dma.set_memory_address(out_0);
251
+                self.tx_dma.set_memory_double_buffer_address(out_1);
252
+                /*self.dma.st[4].m0ar.write(|w| unsafe { w.bits(out_0) });
253
+                self.dma.st[4].m1ar.write(|w| unsafe { w.bits(out_1) });*/
254
+
255
+                // Enable DMA and activate the I2S peripherals.
256
+                /*self.dma.st[3].cr.modify(|_, w| w.en().set_bit());
257
+                self.dma.st[4].cr.modify(|_, w| w.en().set_bit());*/
258
+                unsafe {
259
+                    self.rx_dma.enable();
260
+                    self.tx_dma.enable();
261
+                }
262
+                self.i2sext.i2scfgr.modify(|_, w| w.i2se().set_bit());
263
+                self.spi.i2scfgr.modify(|_, w| w.i2se().set_bit());
264
+
265
+                /*loop {
266
+                    if self.spi.sr.read().txe().bit_is_set() {
267
+                        self.spi.dr.write(|w| unsafe { w.bits(0xaaaa) });
268
+                    }
269
+                    if self.i2sext.sr.read().rxne().bit_is_set() {
270
+                        self.i2sext.dr.read();
271
+                    }
272
+                }*/
222 273
             }
223
-        }*/
224
-    }
225 274
 
226
-    /// Reads data from the output audio buffer and writes to the input audio buffer as required.
227
-    ///
228
-    /// This function needs to be called from the DMA interrupt handler.
229
-    pub fn poll(&mut self) {
275
+            /// Reads data from the output audio buffer and writes to the input audio buffer as required.
276
+            ///
277
+            /// This function needs to be called from the DMA interrupt handler.
278
+            pub fn poll(&mut self) {
279
+                // TODO
280
+            }
281
+        }
230 282
         // TODO
231
-    }
283
+    };
232 284
 }
285
+
286
+i2s_impl!(SPI2, I2S2EXT, spi2en, spi2rst);
287
+i2s_impl!(SPI3, I2S3EXT, spi3en, spi3rst);

+ 56
- 0
hackamp/firmware/src/halext/sai.rs 查看文件

@@ -0,0 +1,56 @@
1
+//! SAI interface with DMA data transfer.
2
+
3
+// Use cases:
4
+// - SAI should be usable as two simplex I2S interfaces, both either slave or master.
5
+// - SAI should be usable as one duplex I2S interface, either as slave or master.
6
+// - SAI should be usable as two simple I2S interfaces with synchronization
7
+
8
+trait SubBlock {
9
+    type SAI;
10
+
11
+    // TODO
12
+}
13
+
14
+struct Transmit<Block: SubBlock> {
15
+    // TODO
16
+}
17
+
18
+struct Receive<Block: SubBlock> {
19
+    // TODO
20
+}
21
+
22
+struct SAIA<SAI> {
23
+    // TODO
24
+}
25
+
26
+struct SAIB<SAI> {
27
+    // TODO
28
+}
29
+
30
+trait SAIExt<SAI> {
31
+    fn split(pins_a: AsyncPins<SAIA<SAI>>, pins_b: AsyncPins<SAIB<SAI>>) -> (SAIA<SAI>, SAIB<SAI>) {
32
+        // TODO
33
+    }
34
+
35
+    fn split_synchronous_a(pins_a: SyncPins<SAIA<SAI>>, pins_b: AsyncPins<SAIB<SAI>>) {
36
+        // TODO
37
+    }
38
+
39
+    fn split_synchronous_b(pins_a: AsyncPins<SAIA<SAI>>, pins_b: SyncPins<SAIB<SAI>>) {
40
+        // TODO
41
+    }
42
+}
43
+
44
+impl SAIExt<SAI> for SAI1 {
45
+    // TODO
46
+}
47
+
48
+struct Duplex<SAI: SAIExt<SAI>> {
49
+    // TODO
50
+}
51
+
52
+impl<SAI: SAIExt<SAI>> Duplex<SAI> {
53
+    fn new(sai: SAI) -> Self {
54
+        // TODO
55
+    }
56
+}

Loading…
取消
儲存