1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
//! This library supports I2S communication for SPI version 1.2 (on STM32F1, STM32F2, STM32F4,
//! STM32L0, and STM32L1 microcontrollers).
//!
//! This library is normally used with a HAL library that provides a type that implements
//! [Instance](crate::Instance). An [I2s](crate::I2s) object can be created around the Instance
//! object and used for I2S.

#![no_std]

extern crate nb;
extern crate vcell;

mod config;
pub mod format;
mod pac;

use core::convert::Infallible;
use core::marker::PhantomData;

pub use self::config::{MasterConfig, SlaveConfig, MasterClock};
pub use self::pac::spi1::RegisterBlock;
use crate::format::{DataFormat, FrameFormat, FrameSync};
use crate::pac::spi1::i2scfgr::I2SCFG_A;

/// Clock polarity
#[derive(Debug, Clone)]
pub enum Polarity {
    /// Clock low when idle
    IdleLow,
    /// Clock high when idle
    IdleHigh,
}

/// The channel associated with a sample
#[derive(Debug, Clone, PartialEq)]
pub enum Channel {
    /// Left channel (word select low)
    Left,
    /// Right channel (word select high)
    Right,
}

/// Events with associated interrupts that can be enabled
pub enum Event {
    /// The transmit data register is empty, and a sample can be written
    TransmitEmtpy,
    /// The receive data register is not empty, and a sample can be read
    ReceiveNotEmpty,
    /// An error has occurred
    Error,
}

/// An SPI peripheral instance that can be used for I2C communication
///
/// This trait is meant to be implemented for a HAL-specific type that represent ownership of
/// the SPI peripheral (and any pins required by it, although that is entirely up to the HAL).
///
/// # Safety
///
/// It is only safe to implement this trait when:
///
/// * The implementing type has ownership of the peripheral, preventing any other accesses to the
///   register block.
/// * `REGISTERS` is a pointer to that peripheral's register block and can be safely accessed for as
///   long as ownership or a borrow of the implementing type is present.
pub unsafe trait Instance {
    /// Pointer to the SPI register block
    const REGISTERS: *mut RegisterBlock;
}

/// Interface to an SPI peripheral in I2S mode
///
/// # Basic sequence of operations
///
/// * Create an I2s object
/// * Configure it in the desired mode (master/slave, transmit/receive)
/// * Enable interrupts and DMA (optional)
/// * Enable
/// * Transmit or receive samples
/// * Disable
/// * Deconfigure the I2s, allowing it to be configured again differently
///
/// # Example
///
/// ```no_run
/// # use stm32_i2s::{I2s, Instance, MasterConfig, InitMode, Polarity, MasterClock};
/// # use stm32_i2s::format::{Data16Frame16, FrameFormat};
/// fn use_i2s<I>(i2s: I2s<I, InitMode>) where I: Instance {
///     let config = MasterConfig::with_division(
///         25,
///         Data16Frame16,
///         FrameFormat::PhilipsI2s,
///         Polarity::IdleHigh,
///         MasterClock::Disble,
///     );
///     let mut i2s_configured = i2s.configure_master_receive(config);
///     let mut samples: [i16; 64] = [0; 64];
///     i2s_configured.enable();
///     i2s_configured.receive_blocking(&mut samples);
///     i2s_configured.disable();
/// }
/// ```
///
pub struct I2s<I, MODE> {
    instance: I,
    frame_format: FrameFormat,
    _mode: PhantomData<MODE>,
}

/// Marker for initialization mode
pub struct InitMode;
/// Marker for transmit mode
///
/// F is the data format
pub struct TransmitMode<F>(F);
/// Marker for receive mode
///
/// F is the data format
pub struct ReceiveMode<F>(F);

mod sealed {
    pub trait Sealed {}
}
use self::sealed::Sealed;

/// A mode in which the I2S is configured and may be enabled (transmit or receive)
pub trait ActiveMode: Sealed {}
impl<F> Sealed for TransmitMode<F> {}
impl<F> ActiveMode for TransmitMode<F> {}
impl<F> Sealed for ReceiveMode<F> {}
impl<F> ActiveMode for ReceiveMode<F> {}

impl<I, MODE> I2s<I, MODE>
where
    I: Instance,
{
    /// Returns a reference to the enclosed peripheral instance
    pub fn instance(&self) -> &I {
        &self.instance
    }
    /// Returns a mutable reference to the enclosed peripheral instance
    pub fn instance_mut(&mut self) -> &mut I {
        &mut self.instance
    }

    /// Returns a reference to the register block
    fn registers(&self) -> &RegisterBlock {
        unsafe { &*I::REGISTERS }
    }

    /// Enables the I2S peripheral
    fn common_enable(&self) {
        self.registers().i2scfgr.modify(|_, w| w.i2se().enabled());
    }

    /// Disables the I2S peripheral
    fn common_disable(&self) {
        self.registers().i2scfgr.modify(|_, w| w.i2se().disabled());
    }

    /// Resets the values of all control and configuration registers
    fn reset_registers(&self) {
        let registers = self.registers();
        registers.cr1.reset();
        registers.cr2.reset();
        registers.i2scfgr.reset();
        registers.i2spr.reset();
    }
}

impl<I> I2s<I, InitMode>
where
    I: Instance,
{
    /// Creates a wrapper around an instance, but does not do any configuration
    pub fn new(instance: I) -> Self {
        I2s {
            instance,
            // Default frame format (the real value will be filled in during configuration)
            frame_format: FrameFormat::PhilipsI2s,
            _mode: PhantomData,
        }
    }

    /// Configures the SPI peripheral in master transmit mode
    pub fn configure_master_transmit<F>(self, config: MasterConfig<F>) -> I2s<I, TransmitMode<F>>
    where
        F: DataFormat,
    {
        self.configure_clock_division(config.division, config.master_clock);
        self.configure_i2s(
            I2SCFG_A::MASTERTX,
            config.data_format,
            &config.frame_format,
            config.polarity,
        );
        I2s {
            instance: self.instance,
            frame_format: config.frame_format,
            _mode: PhantomData,
        }
    }

    /// Configures the SPI peripheral in master receive mode
    pub fn configure_master_receive<F>(self, config: MasterConfig<F>) -> I2s<I, ReceiveMode<F>>
    where
        F: DataFormat,
    {
        self.configure_clock_division(config.division, config.master_clock);
        self.configure_i2s(
            I2SCFG_A::MASTERRX,
            config.data_format,
            &config.frame_format,
            config.polarity,
        );
        I2s {
            instance: self.instance,
            frame_format: config.frame_format,
            _mode: PhantomData,
        }
    }

    /// Configures the SPI peripheral in slave transmit mode
    pub fn configure_slave_transmit<F>(self, config: SlaveConfig<F>) -> I2s<I, TransmitMode<F>>
    where
        F: DataFormat,
    {
        self.configure_i2s(
            I2SCFG_A::SLAVETX,
            config.data_format,
            &config.frame_format,
            config.polarity,
        );
        I2s {
            instance: self.instance,
            frame_format: config.frame_format,
            _mode: PhantomData,
        }
    }

    /// Configures the SPI peripheral in slave receive mode
    pub fn configure_slave_receive<F>(self, config: SlaveConfig<F>) -> I2s<I, ReceiveMode<F>>
    where
        F: DataFormat,
    {
        self.configure_i2s(
            I2SCFG_A::SLAVERX,
            config.data_format,
            &config.frame_format,
            config.polarity,
        );
        I2s {
            instance: self.instance,
            frame_format: config.frame_format,
            _mode: PhantomData,
        }
    }

    /// Sets the SPI peripheral to I2S mode and applies other settings to the SPI_CR2 register
    ///
    /// This does not modify any other registers, so it preserves interrupts and DMA setup.
    fn configure_i2s<F>(
        &self,
        mode: I2SCFG_A,
        _data_format: F,
        frame_format: &FrameFormat,
        polarity: Polarity,
    ) where
        F: DataFormat,
    {
        use self::pac::spi1::i2scfgr::{CKPOL_A, I2SSTD_A, PCMSYNC_A};
        let polarity = match polarity {
            Polarity::IdleLow => CKPOL_A::IDLELOW,
            Polarity::IdleHigh => CKPOL_A::IDLEHIGH,
        };
        let (i2sstd, pcmsync) = match frame_format {
            FrameFormat::PhilipsI2s => (I2SSTD_A::PHILIPS, PCMSYNC_A::SHORT),
            FrameFormat::MsbJustified => (I2SSTD_A::MSB, PCMSYNC_A::SHORT),
            FrameFormat::LsbJustified => (I2SSTD_A::LSB, PCMSYNC_A::SHORT),
            FrameFormat::Pcm(FrameSync::Short) => (I2SSTD_A::PCM, PCMSYNC_A::SHORT),
            FrameFormat::Pcm(FrameSync::Long) => (I2SSTD_A::PCM, PCMSYNC_A::LONG),
        };
        self.registers().i2scfgr.write(|w| {
            // Initially disabled (enable to actually start transferring data)
            w.i2se()
                .disabled()
                .i2smod()
                .i2smode()
                .i2scfg()
                .variant(mode)
                .pcmsync()
                .variant(pcmsync)
                .i2sstd()
                .variant(i2sstd)
                .ckpol()
                .variant(polarity)
                .datlen()
                .variant(F::DATLEN)
                .chlen()
                .variant(F::CHLEN)
        });
    }

    fn configure_clock_division(&self, division: u16, master_clock: MasterClock) {
        let master_clock_enable = matches!(master_clock, MasterClock::Enable);

        let spi = self.registers();
        let i2sdiv = division / 2;
        let odd = division % 2;
        assert!(i2sdiv >= 2 && i2sdiv <= 255);
        spi.i2spr.write(|w| unsafe {
            w.i2sdiv()
                .bits(i2sdiv as u8)
                .odd()
                .bit(odd != 0)
                .mckoe()
                .bit(master_clock_enable)
        });
    }
}

/// # Transmit mode
///
/// Both master and slave mode use the same functions to transmit. The only difference is where
/// the clock is generated.
///
/// ## Slave transmit
///
/// The I2S peripheral must be enabled and the first sample should be written to the transmit
/// register before the master starts sending clock and word select signals.
///
/// ## Master transmit
///
/// The first sample should be written to the transmit register just after the I2S peripheral is enabled.
/// Once the I2S peripheral is enabled, the first sample will be transmitted and the next sample
/// should be written to the transmit register.
///
impl<I, F> I2s<I, TransmitMode<F>>
where
    I: Instance,
    F: DataFormat,
{
    /// Returns the channel on which the next sample will be transmitted, or None if a previous
    /// sample is still in the process of being transmitted
    pub fn ready_to_transmit(&self) -> Option<Channel> {
        use self::pac::spi1::sr::CHSIDE_A;
        let registers = self.registers();
        let sr = registers.sr.read();
        if sr.txe().is_empty() {
            let channel = match sr.chside().variant() {
                CHSIDE_A::LEFT => Channel::Left,
                CHSIDE_A::RIGHT => Channel::Right,
            };
            Some(channel)
        } else {
            // Not ready, channel not valid
            None
        }
    }

    /// Writes a sample into the transmit buffer
    ///
    /// The I2S peripheral should normally be enabled before this function is called. However,
    /// if the data format contains 16 bits, this function can be called once before enabling the
    /// I2S to load the first sample.
    ///
    /// If the data format contains 24 or 32 bits, the sample will be split into two write
    /// operations. This function will block until the second write has completed.
    ///
    pub fn transmit(&mut self, sample: F::Sample) -> nb::Result<(), Infallible> {
        let registers = self.registers();
        let sr = registers.sr.read();
        if sr.txe().is_empty() {
            F::write_sample(&self.frame_format, &registers, sample);
            Ok(())
        } else {
            // Can't write yet
            Err(nb::Error::WouldBlock)
        }
    }

    /// Transmits multiple samples, blocking until all samples have been transmitted
    pub fn transmit_blocking(&mut self, samples: &[F::Sample]) {
        for sample in samples {
            nb::block!(self.transmit(*sample)).unwrap();
        }
    }

    /// Writes a 16-bit value to the data register
    ///
    /// Like `transmit`, this function returns `Err(nb::Error::WouldBlock)` if the data register
    /// contains a value that has not been transmitted yet.
    ///
    /// Unlike `transmit`, this function never blocks because it performs only one 16-bit write.
    /// If the data format contains 24 or 32 bits, the calling code is responsible for dividing
    /// each sample into two chunks and calling this function twice. Details about this can be found
    /// in the microcontroller reference manual.
    pub fn write_data_register(&mut self, value: u16) -> nb::Result<(), Infallible> {
        let registers = self.registers();
        let sr = registers.sr.read();
        if sr.txe().is_empty() {
            registers.dr.write(|w| w.dr().bits(value));
            Ok(())
        } else {
            // Can't write yet
            Err(nb::Error::WouldBlock)
        }
    }

    /// Checks for an error and clears the error flag
    pub fn take_error(&mut self) -> Result<(), TransmitError> {
        let spi = self.registers();
        // This read also clears the underrun flag
        let sr = spi.sr.read();
        if sr.udr().is_underrun() {
            Err(TransmitError::Underrun)
        } else {
            Ok(())
        }
    }

    /// Enables or disables DMA requests for transmission
    pub fn set_dma_enabled(&mut self, enabled: bool) {
        self.registers().cr2.modify(|_, w| w.txdmaen().bit(enabled));
    }

    /// Enables the I2S peripheral
    ///
    /// In master mode, this will activate the word select and clock outputs and start sending
    /// samples, with the left channel first. The first sample should be transmitted immediately
    /// after enabling the I2S.
    ///
    /// In slave mode, this will cause the I2S peripheral to start responding to word select
    /// and clock inputs from the master device. The first sample should be written to the data
    /// register before the word select input goes low.
    pub fn enable(&mut self) {
        self.common_enable();
    }

    /// Disables the I2S peripheral
    ///
    /// To avoid stopping a transfer in the middle of a frame, this function returns WouldBlock
    /// until the current transfer is finished.
    pub fn disable(&mut self) -> nb::Result<(), Infallible> {
        // "To switch off the I2S, by clearing I2SE, it is mandatory to wait for TXE = 1 and BSY = 0."
        let sr = self.registers().sr.read();
        if sr.txe().is_empty() && sr.bsy().is_not_busy() {
            self.common_disable();
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }

    /// Returns the I2S to init mode, allowing it to be reconfigured
    ///
    /// This function resets all configuration options, including interrupts and DMA setup.
    ///
    /// If the I2S peripheral is enabled, this function will block until it has finished the
    /// current transmission.
    pub fn deconfigure(mut self) -> I2s<I, InitMode> {
        nb::block!(self.disable()).unwrap();
        self.reset_registers();
        I2s {
            instance: self.instance,
            // Default frame format (the real value will be filled in during configuration)
            frame_format: FrameFormat::PhilipsI2s,
            _mode: PhantomData,
        }
    }
}

/// # Receive mode
///
/// Both master and slave mode use the same functions to receive. The only difference is where
/// the clock is generated.
///
impl<I, F> I2s<I, ReceiveMode<F>>
where
    I: Instance,
    F: DataFormat,
{
    /// Enables the I2S peripheral
    ///
    /// In master mode, this will activate the word select and clock outputs and start receiving
    /// samples, with the left channel first. The first sample will be available shortly
    /// after enabling the I2S.
    ///
    /// In slave mode, this will cause the I2S peripheral to start responding to word select
    /// and clock inputs from the master device.
    pub fn enable(&mut self) {
        self.common_enable();
    }

    /// If a sample has been read in and is ready to receive, this function returns the channel
    /// it was received on.
    pub fn sample_ready(&self) -> Option<Channel> {
        use crate::pac::spi1::sr::CHSIDE_A;

        let spi = self.registers();
        let sr = spi.sr.read();
        if sr.rxne().is_not_empty() {
            let channel = match sr.chside().variant() {
                CHSIDE_A::LEFT => Channel::Left,
                CHSIDE_A::RIGHT => Channel::Right,
            };
            Some(channel)
        } else {
            None
        }
    }

    /// Receives a sample from the data register, returning the sample and its associated channel
    ///
    /// If the data format contains 24 or 32 bits, the sample will be split into two read
    /// operations. This function will block until the second read has completed.
    pub fn receive(&mut self) -> nb::Result<(F::Sample, Channel), Infallible> {
        match self.sample_ready() {
            Some(channel) => {
                let sample = F::read_sample(&self.frame_format, self.registers());
                Ok((sample, channel))
            }
            None => Err(nb::Error::WouldBlock),
        }
    }

    /// Receives multiple samples, blocking until all samples have been received
    ///
    /// Samples from the left and right channels will be interleaved.
    pub fn receive_blocking(&mut self, samples: &mut [F::Sample]) {
        for sample_in_buffer in samples {
            let (sample, _channel) = nb::block!(self.receive()).unwrap();
            *sample_in_buffer = sample;
        }
    }

    /// Reads a 16-bit value from the data register, returning the value and its associated channel
    ///
    /// Like `receive`, this function returns `Err(nb::Error::WouldBlock)` if the data register
    /// does not contain a value.
    ///
    /// Unlike `receive`, this function never blocks because it performs only one 16-bit read.
    /// If the data format contains 24 or 32 bits, the calling code is responsible for calling this
    /// function twice and combining the two returned chunks into a sample. Details about this can
    /// be found in the microcontroller reference manual.
    pub fn read_data_register(&mut self) -> nb::Result<(u16, Channel), Infallible> {
        match self.sample_ready() {
            Some(channel) => {
                let sample = self.registers().dr.read().dr().bits();
                Ok((sample, channel))
            }
            None => Err(nb::Error::WouldBlock),
        }
    }

    /// Checks if an error has occurred, and clears the overrun error flag
    pub fn take_error(&mut self) -> Result<(), ReceiveError> {
        let spi = self.registers();
        let sr = spi.sr.read();
        let frame_error = sr.fre().is_error();
        let overrun = sr.ovr().is_overrun();
        if overrun {
            // Clear flag by reading DR and then SR
            let dr = spi.dr.read();
            let _ = spi.sr.read();
            if frame_error {
                Err(ReceiveError::FrameAndOverrun(dr.dr().bits))
            } else {
                Err(ReceiveError::Overrun(dr.dr().bits))
            }
        } else if frame_error {
            Err(ReceiveError::Frame)
        } else {
            Ok(())
        }
    }

    /// Enables or disables DMA requests for reception
    pub fn set_dma_enabled(&mut self, enabled: bool) {
        self.registers().cr2.modify(|_, w| w.rxdmaen().bit(enabled));
    }

    /// Disables the I2S
    ///
    /// In master mode, this stops the clock, word select, and (if enabled) master clock outputs.
    ///
    /// Caution: Before disabling the I2S, a specific sequence of operations should be performed
    /// so that the I2S peripheral does not stop in the middle of a frame. Refer to the target
    /// microcontroller reference manual for more information.
    pub fn disable(&mut self) {
        self.common_disable();
    }

    /// Returns the I2S to init mode, allowing it to be reconfigured
    ///
    /// This function resets all configuration options, including interrupts and DMA setup.
    ///
    /// If the I2S peripheral is enabled, this function will disable it.
    pub fn deconfigure(mut self) -> I2s<I, InitMode> {
        self.disable();
        self.reset_registers();
        I2s {
            instance: self.instance,
            // Default frame format (the real value will be filled in during configuration)
            frame_format: FrameFormat::PhilipsI2s,
            _mode: PhantomData,
        }
    }
}

/// # Common functions
///
/// These interrupt functions can be used for transmission and reception.
impl<I, M> I2s<I, M>
where
    I: Instance,
    M: ActiveMode,
{
    /// Enables the interrupt signal output for an event
    pub fn listen(&mut self, event: Event) {
        self.registers().cr2.modify(|_, w| match event {
            Event::TransmitEmtpy => w.txeie().not_masked(),
            Event::ReceiveNotEmpty => w.rxneie().not_masked(),
            Event::Error => w.errie().not_masked(),
        })
    }
    /// Disables the interrupt signal output for an event
    pub fn unlisten(&mut self, event: Event) {
        self.registers().cr2.modify(|_, w| match event {
            Event::TransmitEmtpy => w.txeie().masked(),
            Event::ReceiveNotEmpty => w.rxneie().masked(),
            Event::Error => w.errie().masked(),
        })
    }
}

/// Errors that can occur when transmitting
#[derive(Debug)]
pub enum TransmitError {
    /// The I2S peripheral needed to transmit a sample but no sample had been written
    /// to the data register
    ///
    /// This indicates that at least one incorrect sample was transmitted
    Underrun,
}

/// Errors that can occur when receiving
#[derive(Debug)]
pub enum ReceiveError {
    /// The I2S peripheral received a sample before software read the previous sample
    ///
    /// This indicates that at least one sample was lost.
    ///
    /// The enclosed value is the 16-bit value in the data register when overrun first happened.
    /// Depending on the data format, this may be a full sample or just part of a sample.
    /// The following samples have been discarded.
    Overrun(u16),
    /// The word select signal changed at an unexpected time (for slave mode only)
    ///
    /// If this error occurs, the I2S peripheral should be disabled and then re-enabled when
    /// the word select signal is high.
    Frame,
    /// Both frame and overrun errors were detected
    FrameAndOverrun(u16),
}