STMicroelectronics' implementation of an I2S driver, also including DMA support.

Dependents:   temp X_NUCLEO_CCA01M1 X_NUCLEO_CCA01M1 X_NUCLEO_CCA02M1

Platform compatibility

This driver has been designed to support a wide range of the Nucleo F4 Family of platforms and MCUs, but not all members of this family support I2S and/or some of the members might require slight modifications to the sources of this driver in order to make it work on those.

This driver has for now been tested only with the following platforms:

Committer:
Wolfgang Betz
Date:
Wed Jul 12 15:24:49 2017 +0200
Revision:
31:bb4bac0874da
Parent:
9:c4c2240e06d6
Merge branch 'master' into betzw_wb

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 1:f90318e0923b 1 #ifndef STM_I2S_API_H
Wolfgang Betz 1:f90318e0923b 2 #define STM_I2S_API_H
Wolfgang Betz 1:f90318e0923b 3
Wolfgang Betz 1:f90318e0923b 4 #include <stdbool.h>
Wolfgang Betz 1:f90318e0923b 5
Wolfgang Betz 1:f90318e0923b 6 #include "device.h"
Wolfgang Betz 1:f90318e0923b 7 #include "stm_objects.h"
Wolfgang Betz 1:f90318e0923b 8 #include "hal/stm_dma_api.h"
Wolfgang Betz 1:f90318e0923b 9 #include "hal/buffer.h"
Wolfgang Betz 1:f90318e0923b 10
Wolfgang Betz 1:f90318e0923b 11 #if DEVICE_I2S
Wolfgang Betz 1:f90318e0923b 12
Wolfgang Betz 1:f90318e0923b 13 #define I2S_EVENT_RX_ERROR (1 << 1) // 0x2
Wolfgang Betz 1:f90318e0923b 14 #define I2S_EVENT_RX_COMPLETE (1 << 2) // 0x4
Wolfgang Betz 1:f90318e0923b 15 #define I2S_EVENT_RX_OVERFLOW (1 << 3) // 0x8
Wolfgang Betz 1:f90318e0923b 16 #define I2S_EVENT_RX_HALF_COMPLETE (1 << 4) // 0x10
Wolfgang Betz 1:f90318e0923b 17
Wolfgang Betz 1:f90318e0923b 18 #define I2S_EVENT_TX_ERROR (I2S_EVENT_RX_ERROR << 8) // 0x200
Wolfgang Betz 1:f90318e0923b 19 #define I2S_EVENT_TX_COMPLETE (I2S_EVENT_RX_COMPLETE << 8) // 0x400
Wolfgang Betz 1:f90318e0923b 20 #define I2S_EVENT_TX_UNDERRUN (I2S_EVENT_RX_OVERFLOW << 8) // 0x800
Wolfgang Betz 1:f90318e0923b 21 #define I2S_EVENT_TX_HALF_COMPLETE (I2S_EVENT_RX_HALF_COMPLETE << 8) // 0x1000
Wolfgang Betz 1:f90318e0923b 22
Wolfgang Betz 1:f90318e0923b 23 #define I2S_EVENT_ALL ((I2S_EVENT_RX_ERROR | I2S_EVENT_RX_COMPLETE | I2S_EVENT_RX_OVERFLOW | I2S_EVENT_RX_HALF_COMPLETE) | \
Wolfgang Betz 1:f90318e0923b 24 (I2S_EVENT_TX_ERROR | I2S_EVENT_TX_COMPLETE | I2S_EVENT_TX_UNDERRUN | I2S_EVENT_TX_HALF_COMPLETE))
Wolfgang Betz 1:f90318e0923b 25
Wolfgang Betz 1:f90318e0923b 26 #define I2S_EVENT_INTERNAL_TRANSFER_COMPLETE (1 << 30) // Internal flag to report that an event occurred
Wolfgang Betz 1:f90318e0923b 27
Wolfgang Betz 1:f90318e0923b 28 #define I2S_TX_EVENT (0x0) // see DMA_TX
Wolfgang Betz 1:f90318e0923b 29 #define I2S_RX_EVENT (0x1) // see DMA_RX
Wolfgang Betz 1:f90318e0923b 30
Wolfgang Betz 1:f90318e0923b 31 typedef enum {
Wolfgang Betz 9:c4c2240e06d6 32 PHILIPS,
Wolfgang Betz 9:c4c2240e06d6 33 MSB,
Wolfgang Betz 9:c4c2240e06d6 34 LSB,
Wolfgang Betz 9:c4c2240e06d6 35 PCM_SHORT,
Wolfgang Betz 9:c4c2240e06d6 36 PCM_LONG
Wolfgang Betz 1:f90318e0923b 37 } i2s_bitorder_t;
Wolfgang Betz 1:f90318e0923b 38
Wolfgang Betz 1:f90318e0923b 39 typedef enum {
Wolfgang Betz 9:c4c2240e06d6 40 SLAVE_TX,
Wolfgang Betz 9:c4c2240e06d6 41 SLAVE_RX,
Wolfgang Betz 9:c4c2240e06d6 42 MASTER_TX,
Wolfgang Betz 9:c4c2240e06d6 43 MASTER_RX
Wolfgang Betz 1:f90318e0923b 44 } i2s_mode_t;
Wolfgang Betz 1:f90318e0923b 45
Wolfgang Betz 1:f90318e0923b 46 typedef enum {
Wolfgang Betz 9:c4c2240e06d6 47 LOW,
Wolfgang Betz 9:c4c2240e06d6 48 MEDIUM,
Wolfgang Betz 9:c4c2240e06d6 49 HIGH,
Wolfgang Betz 9:c4c2240e06d6 50 URGENT
Wolfgang Betz 1:f90318e0923b 51 } i2s_dma_prio_t;
Wolfgang Betz 1:f90318e0923b 52
Wolfgang Betz 1:f90318e0923b 53 /** Asynch I2S HAL structure
Wolfgang Betz 1:f90318e0923b 54 */
Wolfgang Betz 1:f90318e0923b 55 typedef struct {
Wolfgang Betz 1:f90318e0923b 56 struct i2s_s i2s; /**< Target specific I2S structure */
Wolfgang Betz 1:f90318e0923b 57 struct dma_s dma; /**< Target specific DMA structure */
Wolfgang Betz 1:f90318e0923b 58 struct buffer_s tx_buff; /**< Tx buffer */
Wolfgang Betz 1:f90318e0923b 59 struct buffer_s rx_buff; /**< Rx buffer */
Wolfgang Betz 1:f90318e0923b 60 } i2s_t;
Wolfgang Betz 1:f90318e0923b 61
Wolfgang Betz 1:f90318e0923b 62 #ifdef __cplusplus
Wolfgang Betz 1:f90318e0923b 63 extern "C" {
Wolfgang Betz 1:f90318e0923b 64 #endif
Wolfgang Betz 1:f90318e0923b 65
Wolfgang Betz 1:f90318e0923b 66 /**
Wolfgang Betz 1:f90318e0923b 67 * \defgroup hal_GeneralI2S I2S Configuration Functions
Wolfgang Betz 1:f90318e0923b 68 * @{
Wolfgang Betz 1:f90318e0923b 69 */
Wolfgang Betz 1:f90318e0923b 70
Wolfgang Betz 1:f90318e0923b 71 /** Initialize the I2S peripheral
Wolfgang Betz 1:f90318e0923b 72 *
Wolfgang Betz 1:f90318e0923b 73 * Configures the pins used by I2S, sets a default format and frequency, and enables the peripheral
Wolfgang Betz 1:f90318e0923b 74 * @param[out] obj The I2S object to initialize
Wolfgang Betz 1:f90318e0923b 75 * @param[in] data I2S data input/output pin
Wolfgang Betz 1:f90318e0923b 76 * @param[in] sclk I2S clock output pin
Wolfgang Betz 1:f90318e0923b 77 * @param[in] wsel I2S word select output pin (might be NC for PDM sources)
Wolfgang Betz 1:f90318e0923b 78 * @param[in] fdpx I2S data input pin (for full-duplex operation, default = NC)
Wolfgang Betz 1:f90318e0923b 79 * @param[in] mclk I2S master clock output pin (default = NC, enables master clock output when not NC)
Wolfgang Betz 1:f90318e0923b 80 * @param[in] mode I2S mode to be applied
Wolfgang Betz 1:f90318e0923b 81 */
Wolfgang Betz 9:c4c2240e06d6 82 void i2s_init(i2s_t *obj, PinName data, PinName sclk, PinName wsel, PinName fdpx, PinName mclk, i2s_mode_t mode);
Wolfgang Betz 1:f90318e0923b 83
Wolfgang Betz 1:f90318e0923b 84 /** Release a I2S object
Wolfgang Betz 1:f90318e0923b 85 *
Wolfgang Betz 1:f90318e0923b 86 * TODO: i2s_free is currently unimplemented
Wolfgang Betz 1:f90318e0923b 87 * This will require reference counting at the C++ level to be safe
Wolfgang Betz 1:f90318e0923b 88 *
Wolfgang Betz 1:f90318e0923b 89 * Return the pins owned by the I2S object to their reset state
Wolfgang Betz 1:f90318e0923b 90 * Disable the I2S peripheral
Wolfgang Betz 1:f90318e0923b 91 * Disable the I2S clock
Wolfgang Betz 1:f90318e0923b 92 * @param[in] obj The I2S object to deinitialize
Wolfgang Betz 1:f90318e0923b 93 */
Wolfgang Betz 9:c4c2240e06d6 94 void i2s_free(i2s_t *obj);
Wolfgang Betz 1:f90318e0923b 95
Wolfgang Betz 1:f90318e0923b 96 /** Configure the I2S format
Wolfgang Betz 1:f90318e0923b 97 *
Wolfgang Betz 1:f90318e0923b 98 * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode
Wolfgang Betz 1:f90318e0923b 99 * @param[in,out] obj The I2S object to configure
Wolfgang Betz 1:f90318e0923b 100 * @param[in] dbits Number of data bits per I2S frame (16, 24, or 32)
Wolfgang Betz 1:f90318e0923b 101 * @param[in] fbits Number of bits per I2S frame (16 or 32)
Wolfgang Betz 1:f90318e0923b 102 * @param[in] polarity Clock polarity (either 0 or 1, default = 0)
Wolfgang Betz 1:f90318e0923b 103 */
Wolfgang Betz 9:c4c2240e06d6 104 void i2s_format(i2s_t *obj, int dbits, int fbits, int polarity);
Wolfgang Betz 1:f90318e0923b 105
Wolfgang Betz 1:f90318e0923b 106 /** Configure the I2S protocol
Wolfgang Betz 1:f90318e0923b 107 *
Wolfgang Betz 1:f90318e0923b 108 * @param[in,out] obj The I2S object to configure
Wolfgang Betz 1:f90318e0923b 109 * @param[in] protocol I2S protocol to be used
Wolfgang Betz 1:f90318e0923b 110 */
Wolfgang Betz 9:c4c2240e06d6 111 void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol);
Wolfgang Betz 1:f90318e0923b 112
Wolfgang Betz 1:f90318e0923b 113 /** Configure the I2S mode
Wolfgang Betz 1:f90318e0923b 114 *
Wolfgang Betz 1:f90318e0923b 115 * @param[in,out] obj The I2S object to configure
Wolfgang Betz 1:f90318e0923b 116 * @param[in] mode I2S mode to be applied
Wolfgang Betz 1:f90318e0923b 117 */
Wolfgang Betz 9:c4c2240e06d6 118 void i2s_set_mode(i2s_t *obj, i2s_mode_t mode);
Wolfgang Betz 1:f90318e0923b 119
Wolfgang Betz 1:f90318e0923b 120 /** Set the I2S audio frequency
Wolfgang Betz 1:f90318e0923b 121 *
Wolfgang Betz 1:f90318e0923b 122 * Actual frequency may differ from the desired frequency due to available dividers and bus clock
Wolfgang Betz 1:f90318e0923b 123 * Configures the I2S audio frequency
Wolfgang Betz 1:f90318e0923b 124 * @param[in,out] obj The I2S object to configure
Wolfgang Betz 1:f90318e0923b 125 * @param[in] hz The baud rate in Hz
Wolfgang Betz 1:f90318e0923b 126 */
Wolfgang Betz 9:c4c2240e06d6 127 void i2s_audio_frequency(i2s_t *obj, uint32_t hz);
Wolfgang Betz 1:f90318e0923b 128
Wolfgang Betz 1:f90318e0923b 129 /**@}*/
Wolfgang Betz 1:f90318e0923b 130 /**
Wolfgang Betz 1:f90318e0923b 131 * \defgroup SynchI2S Synchronous I2S Hardware Abstraction Layer
Wolfgang Betz 1:f90318e0923b 132 * @{
Wolfgang Betz 1:f90318e0923b 133 */
Wolfgang Betz 1:f90318e0923b 134
Wolfgang Betz 1:f90318e0923b 135 /** Get the module number
Wolfgang Betz 1:f90318e0923b 136 *
Wolfgang Betz 1:f90318e0923b 137 * @param[in] obj The I2S peripheral to check
Wolfgang Betz 1:f90318e0923b 138 * @return The module number
Wolfgang Betz 1:f90318e0923b 139 */
Wolfgang Betz 9:c4c2240e06d6 140 uint8_t i2s_get_module(i2s_t *obj);
Wolfgang Betz 1:f90318e0923b 141
Wolfgang Betz 1:f90318e0923b 142 /**@}*/
Wolfgang Betz 1:f90318e0923b 143
Wolfgang Betz 1:f90318e0923b 144 /**
Wolfgang Betz 1:f90318e0923b 145 * \defgroup AsynchI2S Asynchronous I2S Hardware Abstraction Layer
Wolfgang Betz 1:f90318e0923b 146 * @{
Wolfgang Betz 1:f90318e0923b 147 */
Wolfgang Betz 1:f90318e0923b 148
Wolfgang Betz 1:f90318e0923b 149 /** Begin the I2S transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
Wolfgang Betz 1:f90318e0923b 150 *
Wolfgang Betz 1:f90318e0923b 151 * @param[in] obj The I2S object that holds the transfer information
Wolfgang Betz 1:f90318e0923b 152 * @param[in] tx The transmit buffer
Wolfgang Betz 1:f90318e0923b 153 * @param[in] tx_length The number of bytes to transmit
Wolfgang Betz 1:f90318e0923b 154 * @param[in] rx The receive buffer
Wolfgang Betz 1:f90318e0923b 155 * @param[in] rx_length The number of bytes to receive
Wolfgang Betz 1:f90318e0923b 156 * @param[in] circular Enable circular buffer transfer
Wolfgang Betz 1:f90318e0923b 157 * @param[in] prio DMA priority of the transfer
Wolfgang Betz 1:f90318e0923b 158 * @param[in] handler_tx I2S tx interrupt handler
Wolfgang Betz 1:f90318e0923b 159 * @param[in] handler_rx I2S rx interrupt handler
Wolfgang Betz 1:f90318e0923b 160 * @param[in] event The logical OR of events to be registered
Wolfgang Betz 1:f90318e0923b 161 */
Wolfgang Betz 9:c4c2240e06d6 162 void i2s_transfer(i2s_t *obj, void *tx, int tx_length, void *rx, int rx_length,
Wolfgang Betz 9:c4c2240e06d6 163 bool circular, i2s_dma_prio_t prio,
Wolfgang Betz 9:c4c2240e06d6 164 uint32_t handler_tx, uint32_t handler_rx,
Wolfgang Betz 9:c4c2240e06d6 165 uint32_t event);
Wolfgang Betz 1:f90318e0923b 166
Wolfgang Betz 1:f90318e0923b 167 /** The asynchronous IRQ handler
Wolfgang Betz 1:f90318e0923b 168 *
Wolfgang Betz 1:f90318e0923b 169 * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
Wolfgang Betz 1:f90318e0923b 170 * conditions, such as buffer overflows or transfer complete.
Wolfgang Betz 1:f90318e0923b 171 * @param[in] obj The I2S object that holds the transfer information
Wolfgang Betz 1:f90318e0923b 172 * @param[in] direction From whom is the irq coming (RX or TX)
Wolfgang Betz 1:f90318e0923b 173 * @return Event flags if a transfer termination condition was met; otherwise 0.
Wolfgang Betz 1:f90318e0923b 174 */
Wolfgang Betz 9:c4c2240e06d6 175 uint32_t i2s_irq_handler_asynch(i2s_t *obj, uint8_t direction);
Wolfgang Betz 1:f90318e0923b 176
Wolfgang Betz 1:f90318e0923b 177 /** Attempts to determine if the I2S peripheral is already in use
Wolfgang Betz 1:f90318e0923b 178 *
Wolfgang Betz 1:f90318e0923b 179 * For each assigned buffer, check
Wolfgang Betz 1:f90318e0923b 180 * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
Wolfgang Betz 1:f90318e0923b 181 * there are any bytes in the FIFOs.
Wolfgang Betz 1:f90318e0923b 182 * @param[in] obj The I2S object to check for activity
Wolfgang Betz 1:f90318e0923b 183 * @return Non-zero if the I2S port is active or zero if it is not.
Wolfgang Betz 1:f90318e0923b 184 */
Wolfgang Betz 9:c4c2240e06d6 185 uint8_t i2s_active(i2s_t *obj);
Wolfgang Betz 1:f90318e0923b 186
Wolfgang Betz 1:f90318e0923b 187 /** Abort an I2S transfer
Wolfgang Betz 1:f90318e0923b 188 *
Wolfgang Betz 1:f90318e0923b 189 * @param obj The I2S peripheral to stop
Wolfgang Betz 1:f90318e0923b 190 */
Wolfgang Betz 9:c4c2240e06d6 191 void i2s_abort_asynch(i2s_t *obj);
Wolfgang Betz 1:f90318e0923b 192
Davide Aliprandi 4:21603d68bcf7 193 /**
Wolfgang Betz 9:c4c2240e06d6 194 * @brief Harmonize frequencies of two I2S devices
Wolfgang Betz 9:c4c2240e06d6 195 * TODO: doxygen description
Wolfgang Betz 9:c4c2240e06d6 196 * @return Zero if the frequencies have been harmonized correctly, -1
Wolfgang Betz 9:c4c2240e06d6 197 * otherwise.
Wolfgang Betz 9:c4c2240e06d6 198 */
Wolfgang Betz 9:c4c2240e06d6 199 int8_t i2s_harmonize(i2s_t *dev_i2s_1, uint32_t *freq_i2s_1, i2s_t *dev_i2s_2, uint32_t *freq_i2s_2);
Wolfgang Betz 1:f90318e0923b 200
Wolfgang Betz 1:f90318e0923b 201 /**@}*/
Wolfgang Betz 1:f90318e0923b 202
Wolfgang Betz 1:f90318e0923b 203 #ifdef __cplusplus
Wolfgang Betz 1:f90318e0923b 204 }
Wolfgang Betz 1:f90318e0923b 205 #endif // __cplusplus
Wolfgang Betz 1:f90318e0923b 206
Wolfgang Betz 1:f90318e0923b 207 #endif // DEVICE_I2S
Wolfgang Betz 1:f90318e0923b 208
Wolfgang Betz 1:f90318e0923b 209 #endif // STM_I2S_API_H