Il y avait des problèmes dans la libraire...

Dependents:   X_NUCLEO_CCA02M1

Fork of ST_I2S by ST

Committer:
Davide Aliprandi
Date:
Tue Dec 13 18:09:02 2016 +0100
Revision:
2:0c9ce59aee25
Parent:
1:f90318e0923b
Child:
3:25de898f5354
Restored default at 44100Hz, added setting of PLL into the i2s_audio_frequency() API.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 1:f90318e0923b 1 #include "mbed_assert.h"
Wolfgang Betz 1:f90318e0923b 2 #include "mbed_error.h"
Wolfgang Betz 1:f90318e0923b 3 #include "stm_i2s_api.h"
Wolfgang Betz 1:f90318e0923b 4
Wolfgang Betz 1:f90318e0923b 5 #include "stm_dma_caps.h"
Wolfgang Betz 1:f90318e0923b 6
Wolfgang Betz 1:f90318e0923b 7 #if DEVICE_I2S
Wolfgang Betz 1:f90318e0923b 8
Wolfgang Betz 1:f90318e0923b 9 #include <math.h>
Wolfgang Betz 1:f90318e0923b 10 #include <string.h>
Wolfgang Betz 1:f90318e0923b 11 #include "cmsis.h"
Wolfgang Betz 1:f90318e0923b 12 #include "pinmap.h"
Wolfgang Betz 1:f90318e0923b 13 #include "PeripheralPins.h"
Davide Aliprandi 2:0c9ce59aee25 14 #include "StmI2sPeripheralPins.h"
Wolfgang Betz 1:f90318e0923b 15
Davide Aliprandi 2:0c9ce59aee25 16 //#define DEBUG_STDIO 1 // betzw - TODO: temporarily enable debug printfs
Wolfgang Betz 1:f90318e0923b 17
Wolfgang Betz 1:f90318e0923b 18 #ifndef DEBUG_STDIO
Wolfgang Betz 1:f90318e0923b 19 # define DEBUG_STDIO 0
Wolfgang Betz 1:f90318e0923b 20 #endif
Wolfgang Betz 1:f90318e0923b 21
Wolfgang Betz 1:f90318e0923b 22 #if DEBUG_STDIO
Wolfgang Betz 1:f90318e0923b 23 # include <stdio.h>
Wolfgang Betz 1:f90318e0923b 24 # define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
Wolfgang Betz 1:f90318e0923b 25 #else
Wolfgang Betz 1:f90318e0923b 26 # define DEBUG_PRINTF(...) {}
Wolfgang Betz 1:f90318e0923b 27 #endif
Wolfgang Betz 1:f90318e0923b 28
Wolfgang Betz 1:f90318e0923b 29 typedef enum {
Wolfgang Betz 1:f90318e0923b 30 I2S_TRANSFER_TYPE_TX = 1,
Wolfgang Betz 1:f90318e0923b 31 I2S_TRANSFER_TYPE_RX = 2,
Wolfgang Betz 1:f90318e0923b 32 I2S_TRANSFER_TYPE_TXRX = 3,
Wolfgang Betz 1:f90318e0923b 33 } transfer_type_t;
Wolfgang Betz 1:f90318e0923b 34
Wolfgang Betz 1:f90318e0923b 35 typedef struct {
Wolfgang Betz 1:f90318e0923b 36 DMA_HandleTypeDef tx_dma_handle;
Wolfgang Betz 1:f90318e0923b 37 DMA_HandleTypeDef rx_dma_handle;
Wolfgang Betz 1:f90318e0923b 38 } dma_handles_t;
Wolfgang Betz 1:f90318e0923b 39
Wolfgang Betz 1:f90318e0923b 40 #define I2S_NUM (5) // betzw: this approach wastes quite a bit of memory - TO BE IMPROVED!?!?
Wolfgang Betz 1:f90318e0923b 41
Wolfgang Betz 1:f90318e0923b 42 static I2S_HandleTypeDef I2sHandle[I2S_NUM];
Wolfgang Betz 1:f90318e0923b 43 static DMA_HandleTypeDef DMaHandles[I2S_NUM][NUM_OF_DIRECTIONS];
Wolfgang Betz 1:f90318e0923b 44
Davide Aliprandi 2:0c9ce59aee25 45 static void init_i2s(i2s_t *obj) {
Wolfgang Betz 1:f90318e0923b 46 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 47
Wolfgang Betz 1:f90318e0923b 48 __HAL_I2S_DISABLE(handle);
Wolfgang Betz 1:f90318e0923b 49 HAL_I2S_Init(handle);
Wolfgang Betz 1:f90318e0923b 50 __HAL_I2S_ENABLE(handle);
Wolfgang Betz 1:f90318e0923b 51 }
Wolfgang Betz 1:f90318e0923b 52
Davide Aliprandi 2:0c9ce59aee25 53 static void init_dmas(i2s_t *obj) {
Wolfgang Betz 1:f90318e0923b 54 DMA_HandleTypeDef *primary_handle = NULL;
Wolfgang Betz 1:f90318e0923b 55 DMA_HandleTypeDef *secondary_handle = NULL;
Wolfgang Betz 1:f90318e0923b 56 DMA_HandleTypeDef *hdmatx = NULL;
Wolfgang Betz 1:f90318e0923b 57
Wolfgang Betz 1:f90318e0923b 58 switch(obj->dma.dma_direction) {
Davide Aliprandi 2:0c9ce59aee25 59 case DMA_TX:
Davide Aliprandi 2:0c9ce59aee25 60 if(obj->dma.dma[DMA_TX] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 61 hdmatx = primary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
Davide Aliprandi 2:0c9ce59aee25 62 }
Davide Aliprandi 2:0c9ce59aee25 63 if(obj->dma.dma[DMA_RX] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 64 secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
Davide Aliprandi 2:0c9ce59aee25 65 }
Davide Aliprandi 2:0c9ce59aee25 66 break;
Davide Aliprandi 2:0c9ce59aee25 67 case DMA_RX:
Davide Aliprandi 2:0c9ce59aee25 68 default:
Davide Aliprandi 2:0c9ce59aee25 69 if(obj->dma.dma[DMA_RX] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 70 primary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
Davide Aliprandi 2:0c9ce59aee25 71 }
Davide Aliprandi 2:0c9ce59aee25 72 if(obj->dma.dma[DMA_TX] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 73 hdmatx = secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
Davide Aliprandi 2:0c9ce59aee25 74 }
Davide Aliprandi 2:0c9ce59aee25 75 break;
Wolfgang Betz 1:f90318e0923b 76 }
Wolfgang Betz 1:f90318e0923b 77
Wolfgang Betz 1:f90318e0923b 78 if(primary_handle != NULL) {
Davide Aliprandi 2:0c9ce59aee25 79 __HAL_DMA_DISABLE(primary_handle);
Davide Aliprandi 2:0c9ce59aee25 80 HAL_DMA_Init(primary_handle);
Wolfgang Betz 1:f90318e0923b 81
Davide Aliprandi 2:0c9ce59aee25 82 if(hdmatx == primary_handle) {
Davide Aliprandi 2:0c9ce59aee25 83 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *primary_handle);
Davide Aliprandi 2:0c9ce59aee25 84 } else {
Davide Aliprandi 2:0c9ce59aee25 85 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *primary_handle);
Davide Aliprandi 2:0c9ce59aee25 86 }
Wolfgang Betz 1:f90318e0923b 87 }
Wolfgang Betz 1:f90318e0923b 88
Wolfgang Betz 1:f90318e0923b 89 if(secondary_handle != NULL) {
Davide Aliprandi 2:0c9ce59aee25 90 __HAL_DMA_DISABLE(secondary_handle);
Davide Aliprandi 2:0c9ce59aee25 91 HAL_DMA_Init(secondary_handle);
Wolfgang Betz 1:f90318e0923b 92
Davide Aliprandi 2:0c9ce59aee25 93 if(hdmatx == secondary_handle) {
Davide Aliprandi 2:0c9ce59aee25 94 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmatx, *secondary_handle);
Davide Aliprandi 2:0c9ce59aee25 95 } else {
Davide Aliprandi 2:0c9ce59aee25 96 __HAL_LINKDMA(&I2sHandle[obj->i2s.module], hdmarx, *secondary_handle);
Davide Aliprandi 2:0c9ce59aee25 97 }
Wolfgang Betz 1:f90318e0923b 98 }
Wolfgang Betz 1:f90318e0923b 99 }
Wolfgang Betz 1:f90318e0923b 100
Wolfgang Betz 1:f90318e0923b 101 static inline uint32_t i2s_get_mode(i2s_mode_t mode, uint8_t *direction) {
Wolfgang Betz 1:f90318e0923b 102 switch(mode) {
Davide Aliprandi 2:0c9ce59aee25 103 case SLAVE_TX:
Davide Aliprandi 2:0c9ce59aee25 104 *direction = DMA_TX;
Davide Aliprandi 2:0c9ce59aee25 105 return I2S_MODE_SLAVE_TX;
Davide Aliprandi 2:0c9ce59aee25 106 case SLAVE_RX:
Davide Aliprandi 2:0c9ce59aee25 107 *direction = DMA_RX;
Davide Aliprandi 2:0c9ce59aee25 108 return I2S_MODE_SLAVE_RX;
Davide Aliprandi 2:0c9ce59aee25 109 case MASTER_TX:
Davide Aliprandi 2:0c9ce59aee25 110 *direction = DMA_TX;
Davide Aliprandi 2:0c9ce59aee25 111 return I2S_MODE_MASTER_TX;
Davide Aliprandi 2:0c9ce59aee25 112 case MASTER_RX:
Davide Aliprandi 2:0c9ce59aee25 113 default:
Davide Aliprandi 2:0c9ce59aee25 114 *direction = DMA_RX;
Davide Aliprandi 2:0c9ce59aee25 115 return I2S_MODE_MASTER_RX;
Wolfgang Betz 1:f90318e0923b 116 }
Wolfgang Betz 1:f90318e0923b 117 }
Wolfgang Betz 1:f90318e0923b 118
Wolfgang Betz 1:f90318e0923b 119 static inline uint32_t i2s_get_priority(i2s_dma_prio_t priority) {
Wolfgang Betz 1:f90318e0923b 120 switch(priority) {
Davide Aliprandi 2:0c9ce59aee25 121 case LOW:
Davide Aliprandi 2:0c9ce59aee25 122 return DMA_PRIORITY_LOW;
Davide Aliprandi 2:0c9ce59aee25 123 case URGENT:
Davide Aliprandi 2:0c9ce59aee25 124 return DMA_PRIORITY_VERY_HIGH;
Davide Aliprandi 2:0c9ce59aee25 125 case HIGH:
Davide Aliprandi 2:0c9ce59aee25 126 return DMA_PRIORITY_HIGH;
Davide Aliprandi 2:0c9ce59aee25 127 default:
Davide Aliprandi 2:0c9ce59aee25 128 return DMA_PRIORITY_MEDIUM;
Wolfgang Betz 1:f90318e0923b 129 }
Wolfgang Betz 1:f90318e0923b 130 }
Wolfgang Betz 1:f90318e0923b 131
Wolfgang Betz 1:f90318e0923b 132 static void dma_i2s_init(i2s_t *obj, bool *use_tx, bool *use_rx, bool circular, i2s_dma_prio_t prio) {
Wolfgang Betz 1:f90318e0923b 133 // DMA declarations
Wolfgang Betz 1:f90318e0923b 134 DMA_HandleTypeDef *primary_handle = &DMaHandles[obj->i2s.module][obj->dma.dma_direction];
Wolfgang Betz 1:f90318e0923b 135 DMA_HandleTypeDef *secondary_handle = NULL;
Wolfgang Betz 1:f90318e0923b 136
Wolfgang Betz 1:f90318e0923b 137 // DMA initialization & configuration
Davide Aliprandi 2:0c9ce59aee25 138 stm_dma_init();
Wolfgang Betz 1:f90318e0923b 139 obj->dma.dma[DMA_TX] = obj->dma.dma[DMA_RX] = NULL;
Wolfgang Betz 1:f90318e0923b 140
Wolfgang Betz 1:f90318e0923b 141 switch(obj->dma.dma_direction) {
Davide Aliprandi 2:0c9ce59aee25 142 case DMA_TX:
Davide Aliprandi 2:0c9ce59aee25 143 if(*use_tx) {
Davide Aliprandi 2:0c9ce59aee25 144 obj->dma.dma[DMA_TX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
Davide Aliprandi 2:0c9ce59aee25 145 MBED_ASSERT(obj->dma.dma[DMA_TX] != DMA_ERROR_OUT_OF_CHANNELS);
Davide Aliprandi 2:0c9ce59aee25 146 }
Davide Aliprandi 2:0c9ce59aee25 147 break;
Davide Aliprandi 2:0c9ce59aee25 148 case DMA_RX:
Davide Aliprandi 2:0c9ce59aee25 149 default:
Davide Aliprandi 2:0c9ce59aee25 150 if(*use_rx) {
Davide Aliprandi 2:0c9ce59aee25 151 obj->dma.dma[DMA_RX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
Davide Aliprandi 2:0c9ce59aee25 152 MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS);
Davide Aliprandi 2:0c9ce59aee25 153 }
Davide Aliprandi 2:0c9ce59aee25 154 break;
Wolfgang Betz 1:f90318e0923b 155 }
Wolfgang Betz 1:f90318e0923b 156
Wolfgang Betz 1:f90318e0923b 157 // Primary DMA configuration
Wolfgang Betz 1:f90318e0923b 158 if(obj->dma.dma[obj->dma.dma_direction] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 159 primary_handle->Instance = obj->dma.dma[obj->dma.dma_direction]->dma_stream;
Davide Aliprandi 2:0c9ce59aee25 160 primary_handle->Init.Channel = obj->dma.dma[obj->dma.dma_direction]->channel_nr;
Davide Aliprandi 2:0c9ce59aee25 161 primary_handle->Init.Direction = (obj->dma.dma_direction == DMA_TX) ?
Davide Aliprandi 2:0c9ce59aee25 162 DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY;
Davide Aliprandi 2:0c9ce59aee25 163 primary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
Davide Aliprandi 2:0c9ce59aee25 164 primary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
Davide Aliprandi 2:0c9ce59aee25 165 primary_handle->Init.MemBurst = DMA_MBURST_SINGLE;
Davide Aliprandi 2:0c9ce59aee25 166 primary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
Davide Aliprandi 2:0c9ce59aee25 167 primary_handle->Init.MemInc = DMA_MINC_ENABLE;
Davide Aliprandi 2:0c9ce59aee25 168 primary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL);
Davide Aliprandi 2:0c9ce59aee25 169 primary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE;
Davide Aliprandi 2:0c9ce59aee25 170 primary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
Davide Aliprandi 2:0c9ce59aee25 171 primary_handle->Init.PeriphInc = DMA_PINC_DISABLE;
Davide Aliprandi 2:0c9ce59aee25 172 primary_handle->Init.Priority = i2s_get_priority(prio);
Wolfgang Betz 1:f90318e0923b 173 }
Wolfgang Betz 1:f90318e0923b 174
Wolfgang Betz 1:f90318e0923b 175 // Allocate secondary DMA channel (if full-duplex)
Wolfgang Betz 1:f90318e0923b 176 if(obj->i2s.pin_fdpx != NC) {
Davide Aliprandi 2:0c9ce59aee25 177 switch(obj->dma.dma_direction) {
Davide Aliprandi 2:0c9ce59aee25 178 case DMA_TX:
Davide Aliprandi 2:0c9ce59aee25 179 if(*use_rx) {
Davide Aliprandi 2:0c9ce59aee25 180 obj->dma.dma[DMA_RX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_RX));
Davide Aliprandi 2:0c9ce59aee25 181 secondary_handle = &DMaHandles[obj->i2s.module][DMA_RX];
Davide Aliprandi 2:0c9ce59aee25 182 MBED_ASSERT(obj->dma.dma[DMA_RX] != DMA_ERROR_OUT_OF_CHANNELS);
Davide Aliprandi 2:0c9ce59aee25 183 }
Davide Aliprandi 2:0c9ce59aee25 184 break;
Davide Aliprandi 2:0c9ce59aee25 185 case DMA_RX:
Davide Aliprandi 2:0c9ce59aee25 186 default:
Davide Aliprandi 2:0c9ce59aee25 187 if(*use_tx) {
Davide Aliprandi 2:0c9ce59aee25 188 obj->dma.dma[DMA_TX] = stm_dma_channel_allocate(MAKE_CAP(obj->dma.dma_device, DMA_TX));
Davide Aliprandi 2:0c9ce59aee25 189 secondary_handle = &DMaHandles[obj->i2s.module][DMA_TX];
Davide Aliprandi 2:0c9ce59aee25 190 MBED_ASSERT(obj->dma.dma[DMA_TX] != DMA_ERROR_OUT_OF_CHANNELS);
Davide Aliprandi 2:0c9ce59aee25 191 }
Davide Aliprandi 2:0c9ce59aee25 192 break;
Davide Aliprandi 2:0c9ce59aee25 193 }
Wolfgang Betz 1:f90318e0923b 194 }
Wolfgang Betz 1:f90318e0923b 195
Wolfgang Betz 1:f90318e0923b 196 // Secondary DMA configuration
Wolfgang Betz 1:f90318e0923b 197 if(secondary_handle != NULL) {
Davide Aliprandi 2:0c9ce59aee25 198 uint8_t secondary_dma_direction = (obj->dma.dma_direction == DMA_TX) ? DMA_RX : DMA_TX;
Wolfgang Betz 1:f90318e0923b 199
Davide Aliprandi 2:0c9ce59aee25 200 secondary_handle->Instance = obj->dma.dma[secondary_dma_direction]->dma_stream;
Davide Aliprandi 2:0c9ce59aee25 201 secondary_handle->Init.Channel = obj->dma.dma[secondary_dma_direction]->channel_nr_fd;
Davide Aliprandi 2:0c9ce59aee25 202 secondary_handle->Init.Direction = (secondary_dma_direction == DMA_TX) ?
Davide Aliprandi 2:0c9ce59aee25 203 DMA_MEMORY_TO_PERIPH : DMA_PERIPH_TO_MEMORY;
Davide Aliprandi 2:0c9ce59aee25 204 secondary_handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
Davide Aliprandi 2:0c9ce59aee25 205 secondary_handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
Davide Aliprandi 2:0c9ce59aee25 206 secondary_handle->Init.MemBurst = DMA_MBURST_SINGLE;
Davide Aliprandi 2:0c9ce59aee25 207 secondary_handle->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
Davide Aliprandi 2:0c9ce59aee25 208 secondary_handle->Init.MemInc = DMA_MINC_ENABLE;
Davide Aliprandi 2:0c9ce59aee25 209 secondary_handle->Init.Mode = (circular ? DMA_CIRCULAR : DMA_NORMAL);
Davide Aliprandi 2:0c9ce59aee25 210 secondary_handle->Init.PeriphBurst = DMA_PBURST_SINGLE;
Davide Aliprandi 2:0c9ce59aee25 211 secondary_handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
Davide Aliprandi 2:0c9ce59aee25 212 secondary_handle->Init.PeriphInc = DMA_PINC_DISABLE;
Davide Aliprandi 2:0c9ce59aee25 213 secondary_handle->Init.Priority = i2s_get_priority(prio);
Wolfgang Betz 1:f90318e0923b 214 }
Wolfgang Betz 1:f90318e0923b 215
Wolfgang Betz 1:f90318e0923b 216 if(obj->dma.dma[DMA_TX] == NULL) *use_tx = false;
Wolfgang Betz 1:f90318e0923b 217 if(obj->dma.dma[DMA_RX] == NULL) *use_rx = false;
Wolfgang Betz 1:f90318e0923b 218
Wolfgang Betz 1:f90318e0923b 219 // don't do anything, if the buffers aren't valid
Wolfgang Betz 1:f90318e0923b 220 if (!use_tx && !use_rx) {
Davide Aliprandi 2:0c9ce59aee25 221 DEBUG_PRINTF(" I2S%u: No DMAs to init\r\n", obj->i2s.module + 1);
Davide Aliprandi 2:0c9ce59aee25 222 return;
Wolfgang Betz 1:f90318e0923b 223 }
Wolfgang Betz 1:f90318e0923b 224
Davide Aliprandi 2:0c9ce59aee25 225 DEBUG_PRINTF(" I2S%u: DMA(s) Init\r\n", obj->i2s.module + 1);
Davide Aliprandi 2:0c9ce59aee25 226
Wolfgang Betz 1:f90318e0923b 227 init_dmas(obj);
Wolfgang Betz 1:f90318e0923b 228 }
Wolfgang Betz 1:f90318e0923b 229
Wolfgang Betz 1:f90318e0923b 230 static void dma_i2s_free(i2s_t *obj, uint8_t direction) {
Wolfgang Betz 1:f90318e0923b 231 const struct dma_stream_s *stream = obj->dma.dma[direction];
Wolfgang Betz 1:f90318e0923b 232
Wolfgang Betz 1:f90318e0923b 233 MBED_ASSERT(stream != NULL);
Wolfgang Betz 1:f90318e0923b 234
Wolfgang Betz 1:f90318e0923b 235 // disable irq
Wolfgang Betz 1:f90318e0923b 236 NVIC_DisableIRQ(stream->dma_stream_irq);
Wolfgang Betz 1:f90318e0923b 237
Wolfgang Betz 1:f90318e0923b 238 // free channel
Davide Aliprandi 2:0c9ce59aee25 239 stm_dma_channel_free((void*)stream);
Wolfgang Betz 1:f90318e0923b 240 obj->dma.dma[direction] = NULL;
Wolfgang Betz 1:f90318e0923b 241 }
Wolfgang Betz 1:f90318e0923b 242
Davide Aliprandi 2:0c9ce59aee25 243 void i2s_init(i2s_t *obj, PinName data, PinName sclk, PinName wsel, PinName fdpx, PinName mclk, i2s_mode_t mode) {
Wolfgang Betz 1:f90318e0923b 244 uint8_t dma_dev = 0, dma_direction = 0;
Wolfgang Betz 1:f90318e0923b 245
Wolfgang Betz 1:f90318e0923b 246 // Determine the I2S/SPI to use
Wolfgang Betz 1:f90318e0923b 247 SPIName i2s_data = (SPIName)pinmap_peripheral(data, PinMap_I2S_DATA);
Wolfgang Betz 1:f90318e0923b 248 SPIName i2s_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_I2S_SCLK);
Wolfgang Betz 1:f90318e0923b 249
Wolfgang Betz 1:f90318e0923b 250 SPIName i2s_wsel = (SPIName)pinmap_peripheral(wsel, PinMap_I2S_WSEL);
Wolfgang Betz 1:f90318e0923b 251 SPIName i2s_fdpx = (SPIName)pinmap_peripheral(fdpx, PinMap_I2S_FDPX);
Wolfgang Betz 1:f90318e0923b 252
Wolfgang Betz 1:f90318e0923b 253 SPIName i2s_mclk = (SPIName)pinmap_peripheral(mclk, PinMap_I2S_MCLK);
Wolfgang Betz 1:f90318e0923b 254
Wolfgang Betz 1:f90318e0923b 255 SPIName i2s_merge1 = (SPIName)pinmap_merge(i2s_data, i2s_sclk);
Wolfgang Betz 1:f90318e0923b 256 SPIName i2s_merge2 = (SPIName)pinmap_merge(i2s_wsel, i2s_fdpx);
Wolfgang Betz 1:f90318e0923b 257
Wolfgang Betz 1:f90318e0923b 258 SPIName i2s_merge3 = (SPIName)pinmap_merge(i2s_merge1, i2s_merge2);
Wolfgang Betz 1:f90318e0923b 259 SPIName instance = (SPIName)pinmap_merge(i2s_merge3, i2s_mclk);
Wolfgang Betz 1:f90318e0923b 260 MBED_ASSERT(instance != (SPIName)NC);
Wolfgang Betz 1:f90318e0923b 261
Wolfgang Betz 1:f90318e0923b 262 // Enable I2S/SPI clock and set the right module number
Wolfgang Betz 1:f90318e0923b 263 switch(instance) {
Wolfgang Betz 1:f90318e0923b 264 #if defined(I2S1ext_BASE)
Wolfgang Betz 1:f90318e0923b 265 case SPI_1:
Wolfgang Betz 1:f90318e0923b 266 __SPI1_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 267 obj->i2s.module = 0;
Wolfgang Betz 1:f90318e0923b 268 dma_dev = DMA_SPI1;
Wolfgang Betz 1:f90318e0923b 269 break;
Wolfgang Betz 1:f90318e0923b 270 #endif
Wolfgang Betz 1:f90318e0923b 271 #if defined(I2S2ext_BASE)
Wolfgang Betz 1:f90318e0923b 272 case SPI_2:
Wolfgang Betz 1:f90318e0923b 273 __SPI2_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 274 obj->i2s.module = 1;
Wolfgang Betz 1:f90318e0923b 275 dma_dev = DMA_SPI2;
Wolfgang Betz 1:f90318e0923b 276 break;
Wolfgang Betz 1:f90318e0923b 277 #endif
Wolfgang Betz 1:f90318e0923b 278 #if defined(I2S3ext_BASE)
Wolfgang Betz 1:f90318e0923b 279 case SPI_3:
Wolfgang Betz 1:f90318e0923b 280 __SPI3_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 281 obj->i2s.module = 2;
Wolfgang Betz 1:f90318e0923b 282 dma_dev = DMA_SPI3;
Wolfgang Betz 1:f90318e0923b 283 break;
Wolfgang Betz 1:f90318e0923b 284 #endif
Wolfgang Betz 1:f90318e0923b 285 #if defined(I2S4ext_BASE)
Wolfgang Betz 1:f90318e0923b 286 case SPI_4:
Wolfgang Betz 1:f90318e0923b 287 __SPI4_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 288 obj->i2s.module = 3;
Wolfgang Betz 1:f90318e0923b 289 dma_dev = DMA_SPI4;
Wolfgang Betz 1:f90318e0923b 290 break;
Wolfgang Betz 1:f90318e0923b 291 #endif
Wolfgang Betz 1:f90318e0923b 292 #if defined(I2S5ext_BASE)
Wolfgang Betz 1:f90318e0923b 293 case SPI_5:
Wolfgang Betz 1:f90318e0923b 294 __SPI5_CLK_ENABLE();
Wolfgang Betz 1:f90318e0923b 295 obj->i2s.module = 4;
Wolfgang Betz 1:f90318e0923b 296 dma_dev = DMA_SPI5;
Wolfgang Betz 1:f90318e0923b 297 break;
Wolfgang Betz 1:f90318e0923b 298 #endif
Wolfgang Betz 1:f90318e0923b 299 default:
Wolfgang Betz 1:f90318e0923b 300 MBED_ASSERT(0);
Wolfgang Betz 1:f90318e0923b 301 break;
Wolfgang Betz 1:f90318e0923b 302 }
Wolfgang Betz 1:f90318e0923b 303
Wolfgang Betz 1:f90318e0923b 304 // Save DMA device
Wolfgang Betz 1:f90318e0923b 305 obj->dma.dma_device = dma_dev;
Wolfgang Betz 1:f90318e0923b 306
Wolfgang Betz 1:f90318e0923b 307 // Configure the I2S pins
Wolfgang Betz 1:f90318e0923b 308 pinmap_pinout(data, PinMap_I2S_DATA);
Wolfgang Betz 1:f90318e0923b 309 pinmap_pinout(wsel, PinMap_I2S_WSEL);
Wolfgang Betz 1:f90318e0923b 310 pinmap_pinout(sclk, PinMap_I2S_SCLK);
Wolfgang Betz 1:f90318e0923b 311 pinmap_pinout(fdpx, PinMap_I2S_FDPX);
Wolfgang Betz 1:f90318e0923b 312 pinmap_pinout(mclk, PinMap_I2S_MCLK);
Wolfgang Betz 1:f90318e0923b 313
Wolfgang Betz 1:f90318e0923b 314 obj->i2s.pin_wsel = wsel;
Wolfgang Betz 1:f90318e0923b 315 obj->i2s.pin_data = data;
Wolfgang Betz 1:f90318e0923b 316 obj->i2s.pin_sclk = sclk;
Wolfgang Betz 1:f90318e0923b 317 obj->i2s.pin_fdpx = fdpx;
Wolfgang Betz 1:f90318e0923b 318 obj->i2s.pin_mclk = mclk;
Wolfgang Betz 1:f90318e0923b 319
Davide Aliprandi 2:0c9ce59aee25 320 /* Configure PLLI2S */
Wolfgang Betz 1:f90318e0923b 321 static bool first_time = true;
Davide Aliprandi 2:0c9ce59aee25 322 if (first_time)
Davide Aliprandi 2:0c9ce59aee25 323 {
Davide Aliprandi 2:0c9ce59aee25 324 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
Wolfgang Betz 1:f90318e0923b 325
Davide Aliprandi 2:0c9ce59aee25 326 /* Get RTCClockSelection */
Davide Aliprandi 2:0c9ce59aee25 327 HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInitStruct);
Wolfgang Betz 1:f90318e0923b 328
Davide Aliprandi 2:0c9ce59aee25 329 /* Set default configuration. Default frequency is 44100Hz. */
Davide Aliprandi 2:0c9ce59aee25 330 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
Davide Aliprandi 2:0c9ce59aee25 331 PeriphClkInitStruct.PLLI2S.PLLI2SN = 271; // betzw: use values which are suggested in Table 91 of the
Davide Aliprandi 2:0c9ce59aee25 332 PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; // reference manual for master clock enabled & 44100Hz.
Davide Aliprandi 2:0c9ce59aee25 333
Wolfgang Betz 1:f90318e0923b 334 #ifdef NDEBUG
Davide Aliprandi 2:0c9ce59aee25 335 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
Wolfgang Betz 1:f90318e0923b 336 #else
Davide Aliprandi 2:0c9ce59aee25 337 HAL_StatusTypeDef ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
Wolfgang Betz 1:f90318e0923b 338 #endif
Davide Aliprandi 2:0c9ce59aee25 339 MBED_ASSERT(ret == HAL_OK);
Davide Aliprandi 2:0c9ce59aee25 340
Davide Aliprandi 2:0c9ce59aee25 341 first_time = false;
Wolfgang Betz 1:f90318e0923b 342 }
Wolfgang Betz 1:f90318e0923b 343
Davide Aliprandi 2:0c9ce59aee25 344 /* Initializing the handle for this master. */
Wolfgang Betz 1:f90318e0923b 345 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 346
Wolfgang Betz 1:f90318e0923b 347 handle->Instance = (SPI_TypeDef *)(instance);
Wolfgang Betz 1:f90318e0923b 348 handle->Init.Mode = i2s_get_mode(mode, &dma_direction);
Wolfgang Betz 1:f90318e0923b 349 handle->Init.Standard = I2S_STANDARD_PCM_SHORT;
Wolfgang Betz 1:f90318e0923b 350 handle->Init.DataFormat = I2S_DATAFORMAT_16B;
Wolfgang Betz 1:f90318e0923b 351 handle->Init.CPOL = I2S_CPOL_LOW;
Davide Aliprandi 2:0c9ce59aee25 352 handle->Init.AudioFreq = I2S_AUDIOFREQ_44K; //Default frequency is 44100Hz.
Wolfgang Betz 1:f90318e0923b 353 handle->Init.ClockSource = I2S_CLOCK_PLL;
Davide Aliprandi 2:0c9ce59aee25 354 handle->Init.FullDuplexMode = (fdpx == NC ? I2S_FULLDUPLEXMODE_DISABLE : I2S_FULLDUPLEXMODE_ENABLE);
Davide Aliprandi 2:0c9ce59aee25 355 handle->Init.MCLKOutput = (mclk == NC ? I2S_MCLKOUTPUT_DISABLE : I2S_MCLKOUTPUT_ENABLE); //Davide: Microphones need master clock disabled, while sound terminal needs it enabled.
Davide Aliprandi 2:0c9ce59aee25 356
Davide Aliprandi 2:0c9ce59aee25 357 DEBUG_PRINTF("--> %s\r\n", __FUNCTION__);
Davide Aliprandi 2:0c9ce59aee25 358 DEBUG_PRINTF(" I2S%u: Mode: %u (%u)\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 359 (unsigned int)handle->Init.Mode, (unsigned int)mode);
Davide Aliprandi 2:0c9ce59aee25 360 DEBUG_PRINTF(" I2S%u: Standard: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 361 (unsigned int)handle->Init.Standard);
Davide Aliprandi 2:0c9ce59aee25 362 DEBUG_PRINTF(" I2S%u: DataFormat: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 363 (unsigned int)handle->Init.DataFormat);
Davide Aliprandi 2:0c9ce59aee25 364 DEBUG_PRINTF(" I2S%u: CPOL: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 365 (unsigned int)handle->Init.CPOL);
Davide Aliprandi 2:0c9ce59aee25 366 DEBUG_PRINTF(" I2S%u: AudioFreq: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 367 (unsigned int)handle->Init.AudioFreq);
Davide Aliprandi 2:0c9ce59aee25 368 DEBUG_PRINTF(" I2S%u: ClockSource: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 369 (unsigned int)handle->Init.ClockSource);
Davide Aliprandi 2:0c9ce59aee25 370 DEBUG_PRINTF(" I2S%u: FullDuplexMode: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 371 (unsigned int)handle->Init.FullDuplexMode);
Davide Aliprandi 2:0c9ce59aee25 372 DEBUG_PRINTF(" I2S%u: MCLKOutput: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 373 (unsigned int)handle->Init.MCLKOutput);
Wolfgang Betz 1:f90318e0923b 374
Wolfgang Betz 1:f90318e0923b 375 // Save primary DMA direction
Wolfgang Betz 1:f90318e0923b 376 obj->dma.dma_direction = dma_direction;
Wolfgang Betz 1:f90318e0923b 377
Wolfgang Betz 1:f90318e0923b 378 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 379 }
Wolfgang Betz 1:f90318e0923b 380
Davide Aliprandi 2:0c9ce59aee25 381 void i2s_free(i2s_t *obj) {
Wolfgang Betz 1:f90318e0923b 382 // Reset I2S and disable clock
Wolfgang Betz 1:f90318e0923b 383 switch(obj->i2s.module) {
Wolfgang Betz 1:f90318e0923b 384 #if defined(I2S1ext_BASE)
Davide Aliprandi 2:0c9ce59aee25 385 case 0:
Davide Aliprandi 2:0c9ce59aee25 386 __SPI1_FORCE_RESET();
Davide Aliprandi 2:0c9ce59aee25 387 __SPI1_RELEASE_RESET();
Davide Aliprandi 2:0c9ce59aee25 388 __SPI1_CLK_DISABLE();
Davide Aliprandi 2:0c9ce59aee25 389 break;
Wolfgang Betz 1:f90318e0923b 390 #endif
Wolfgang Betz 1:f90318e0923b 391 #if defined(I2S2ext_BASE)
Davide Aliprandi 2:0c9ce59aee25 392 case 1:
Davide Aliprandi 2:0c9ce59aee25 393 __SPI2_FORCE_RESET();
Davide Aliprandi 2:0c9ce59aee25 394 __SPI2_RELEASE_RESET();
Davide Aliprandi 2:0c9ce59aee25 395 __SPI2_CLK_DISABLE();
Davide Aliprandi 2:0c9ce59aee25 396 break;
Wolfgang Betz 1:f90318e0923b 397 #endif
Wolfgang Betz 1:f90318e0923b 398 #if defined(I2S3ext_BASE)
Davide Aliprandi 2:0c9ce59aee25 399 case 2:
Davide Aliprandi 2:0c9ce59aee25 400 __SPI3_FORCE_RESET();
Davide Aliprandi 2:0c9ce59aee25 401 __SPI3_RELEASE_RESET();
Davide Aliprandi 2:0c9ce59aee25 402 __SPI3_CLK_DISABLE();
Davide Aliprandi 2:0c9ce59aee25 403 break;
Wolfgang Betz 1:f90318e0923b 404 #endif
Wolfgang Betz 1:f90318e0923b 405 #if defined(I2S4ext_BASE)
Davide Aliprandi 2:0c9ce59aee25 406 case 3:
Davide Aliprandi 2:0c9ce59aee25 407 __SPI4_FORCE_RESET();
Davide Aliprandi 2:0c9ce59aee25 408 __SPI4_RELEASE_RESET();
Davide Aliprandi 2:0c9ce59aee25 409 __SPI4_CLK_DISABLE();
Davide Aliprandi 2:0c9ce59aee25 410 break;
Wolfgang Betz 1:f90318e0923b 411 #endif
Wolfgang Betz 1:f90318e0923b 412 #if defined(I2S5ext_BASE)
Davide Aliprandi 2:0c9ce59aee25 413 case 4:
Davide Aliprandi 2:0c9ce59aee25 414 __SPI5_FORCE_RESET();
Davide Aliprandi 2:0c9ce59aee25 415 __SPI5_RELEASE_RESET();
Davide Aliprandi 2:0c9ce59aee25 416 __SPI5_CLK_DISABLE();
Davide Aliprandi 2:0c9ce59aee25 417 break;
Wolfgang Betz 1:f90318e0923b 418 #endif
Davide Aliprandi 2:0c9ce59aee25 419 default:
Davide Aliprandi 2:0c9ce59aee25 420 MBED_ASSERT(0);
Davide Aliprandi 2:0c9ce59aee25 421 break;
Wolfgang Betz 1:f90318e0923b 422 }
Wolfgang Betz 1:f90318e0923b 423
Wolfgang Betz 1:f90318e0923b 424 // betzw - TODO: what about 'PLLI2S'?!?
Wolfgang Betz 1:f90318e0923b 425 // for the moment we leave it enabled!
Wolfgang Betz 1:f90318e0923b 426
Wolfgang Betz 1:f90318e0923b 427 // Configure GPIOs
Wolfgang Betz 1:f90318e0923b 428 pin_function(obj->i2s.pin_wsel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 429 pin_function(obj->i2s.pin_data, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 430 pin_function(obj->i2s.pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 431 pin_function(obj->i2s.pin_fdpx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 432 pin_function(obj->i2s.pin_mclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
Wolfgang Betz 1:f90318e0923b 433
Davide Aliprandi 2:0c9ce59aee25 434 DEBUG_PRINTF("--> %s\r\n", __FUNCTION__);
Wolfgang Betz 1:f90318e0923b 435 }
Wolfgang Betz 1:f90318e0923b 436
Davide Aliprandi 2:0c9ce59aee25 437 void i2s_format(i2s_t *obj, int dbits, int fbits, int polarity) {
Wolfgang Betz 1:f90318e0923b 438 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 439
Wolfgang Betz 1:f90318e0923b 440 // Save new values
Davide Aliprandi 2:0c9ce59aee25 441 if (fbits == 16)
Davide Aliprandi 2:0c9ce59aee25 442 { // format MUST be 16B
Davide Aliprandi 2:0c9ce59aee25 443 handle->Init.DataFormat = I2S_DATAFORMAT_16B;
Wolfgang Betz 1:f90318e0923b 444 } else { // format may NOT be 16B
Davide Aliprandi 2:0c9ce59aee25 445 switch (dbits)
Davide Aliprandi 2:0c9ce59aee25 446 {
Davide Aliprandi 2:0c9ce59aee25 447 case 16:
Davide Aliprandi 2:0c9ce59aee25 448 handle->Init.DataFormat = I2S_DATAFORMAT_16B_EXTENDED;
Davide Aliprandi 2:0c9ce59aee25 449 break;
Davide Aliprandi 2:0c9ce59aee25 450 case 24:
Davide Aliprandi 2:0c9ce59aee25 451 handle->Init.DataFormat = I2S_DATAFORMAT_24B;
Davide Aliprandi 2:0c9ce59aee25 452 break;
Davide Aliprandi 2:0c9ce59aee25 453 case 32:
Davide Aliprandi 2:0c9ce59aee25 454 default:
Davide Aliprandi 2:0c9ce59aee25 455 handle->Init.DataFormat = I2S_DATAFORMAT_32B;
Davide Aliprandi 2:0c9ce59aee25 456 break;
Davide Aliprandi 2:0c9ce59aee25 457 }
Wolfgang Betz 1:f90318e0923b 458 }
Wolfgang Betz 1:f90318e0923b 459
Wolfgang Betz 1:f90318e0923b 460 handle->Init.CPOL = (polarity == 0) ? I2S_CPOL_LOW : I2S_CPOL_HIGH;
Wolfgang Betz 1:f90318e0923b 461
Davide Aliprandi 2:0c9ce59aee25 462 DEBUG_PRINTF("--> %s\r\n", __FUNCTION__);
Davide Aliprandi 2:0c9ce59aee25 463 DEBUG_PRINTF(" I2S%u: DataFormat: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 464 (unsigned int)handle->Init.DataFormat);
Davide Aliprandi 2:0c9ce59aee25 465 DEBUG_PRINTF(" I2S%u: CPOL: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 466 (unsigned int)handle->Init.CPOL);
Davide Aliprandi 2:0c9ce59aee25 467 DEBUG_PRINTF(" I2S%u: (dbits, fbits): (%u, %u)\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 468 (unsigned int)dbits, (unsigned int)fbits);
Davide Aliprandi 2:0c9ce59aee25 469 DEBUG_PRINTF(" I2S%u: Polarity: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 470 (unsigned int)polarity);
Wolfgang Betz 1:f90318e0923b 471
Wolfgang Betz 1:f90318e0923b 472 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 473 }
Wolfgang Betz 1:f90318e0923b 474
Davide Aliprandi 2:0c9ce59aee25 475 void i2s_set_mode(i2s_t *obj, i2s_mode_t mode) {
Wolfgang Betz 1:f90318e0923b 476 uint8_t dma_direction;
Wolfgang Betz 1:f90318e0923b 477 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 478
Wolfgang Betz 1:f90318e0923b 479 handle->Init.Mode = i2s_get_mode(mode, &dma_direction);
Wolfgang Betz 1:f90318e0923b 480
Wolfgang Betz 1:f90318e0923b 481 // Save primary DMA direction
Wolfgang Betz 1:f90318e0923b 482 obj->dma.dma_direction = dma_direction;
Wolfgang Betz 1:f90318e0923b 483
Davide Aliprandi 2:0c9ce59aee25 484 DEBUG_PRINTF("--> %s\r\n", __FUNCTION__);
Davide Aliprandi 2:0c9ce59aee25 485 DEBUG_PRINTF(" I2S%u: Mode: %u (%u)\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 486 (unsigned int)handle->Init.Mode, (unsigned int)mode);
Davide Aliprandi 2:0c9ce59aee25 487
Davide Aliprandi 2:0c9ce59aee25 488 init_i2s(obj);
Davide Aliprandi 2:0c9ce59aee25 489 }
Davide Aliprandi 2:0c9ce59aee25 490
Davide Aliprandi 2:0c9ce59aee25 491 void i2s_set_protocol(i2s_t *obj, i2s_bitorder_t protocol) {
Davide Aliprandi 2:0c9ce59aee25 492 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Davide Aliprandi 2:0c9ce59aee25 493
Davide Aliprandi 2:0c9ce59aee25 494 switch (protocol)
Davide Aliprandi 2:0c9ce59aee25 495 {
Davide Aliprandi 2:0c9ce59aee25 496 case PHILIPS:
Davide Aliprandi 2:0c9ce59aee25 497 handle->Init.Standard = I2S_STANDARD_PHILIPS;
Davide Aliprandi 2:0c9ce59aee25 498 break;
Davide Aliprandi 2:0c9ce59aee25 499 case MSB:
Davide Aliprandi 2:0c9ce59aee25 500 handle->Init.Standard = I2S_STANDARD_MSB;
Davide Aliprandi 2:0c9ce59aee25 501 break;
Davide Aliprandi 2:0c9ce59aee25 502 case LSB:
Davide Aliprandi 2:0c9ce59aee25 503 handle->Init.Standard = I2S_STANDARD_LSB;
Davide Aliprandi 2:0c9ce59aee25 504 break;
Davide Aliprandi 2:0c9ce59aee25 505 case PCM_SHORT:
Davide Aliprandi 2:0c9ce59aee25 506 handle->Init.Standard = I2S_STANDARD_PCM_SHORT;
Davide Aliprandi 2:0c9ce59aee25 507 break;
Davide Aliprandi 2:0c9ce59aee25 508 case PCM_LONG:
Davide Aliprandi 2:0c9ce59aee25 509 default:
Davide Aliprandi 2:0c9ce59aee25 510 handle->Init.Standard = I2S_STANDARD_PCM_LONG;
Davide Aliprandi 2:0c9ce59aee25 511 break;
Davide Aliprandi 2:0c9ce59aee25 512 }
Davide Aliprandi 2:0c9ce59aee25 513
Davide Aliprandi 2:0c9ce59aee25 514 DEBUG_PRINTF("--> %s\r\n", __FUNCTION__);
Davide Aliprandi 2:0c9ce59aee25 515 DEBUG_PRINTF(" I2S%u: Standard: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 516 (unsigned int)handle->Init.Standard);
Wolfgang Betz 1:f90318e0923b 517
Wolfgang Betz 1:f90318e0923b 518 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 519 }
Wolfgang Betz 1:f90318e0923b 520
Davide Aliprandi 2:0c9ce59aee25 521 void i2s_audio_frequency(i2s_t *obj, uint32_t hz) {
Wolfgang Betz 1:f90318e0923b 522 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 523
Davide Aliprandi 2:0c9ce59aee25 524 if (IS_I2S_AUDIO_FREQ(hz) && (hz != I2S_AUDIOFREQ_DEFAULT)) {
Davide Aliprandi 2:0c9ce59aee25 525 handle->Init.AudioFreq = hz;
Davide Aliprandi 2:0c9ce59aee25 526 }
Davide Aliprandi 2:0c9ce59aee25 527 else if (hz < I2S_AUDIOFREQ_8K) {
Davide Aliprandi 2:0c9ce59aee25 528 handle->Init.AudioFreq = I2S_AUDIOFREQ_8K;
Davide Aliprandi 2:0c9ce59aee25 529 }
Davide Aliprandi 2:0c9ce59aee25 530 else {
Davide Aliprandi 2:0c9ce59aee25 531 handle->Init.AudioFreq = I2S_AUDIOFREQ_192K;
Wolfgang Betz 1:f90318e0923b 532 }
Wolfgang Betz 1:f90318e0923b 533
Davide Aliprandi 2:0c9ce59aee25 534 /* Configuring PLLI2S. */
Davide Aliprandi 2:0c9ce59aee25 535 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
Davide Aliprandi 2:0c9ce59aee25 536
Davide Aliprandi 2:0c9ce59aee25 537 /* Getting RTCClockSelection. */
Davide Aliprandi 2:0c9ce59aee25 538 HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInitStruct);
Davide Aliprandi 2:0c9ce59aee25 539
Davide Aliprandi 2:0c9ce59aee25 540 /* Setting configuration. */
Davide Aliprandi 2:0c9ce59aee25 541 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
Davide Aliprandi 2:0c9ce59aee25 542
Davide Aliprandi 2:0c9ce59aee25 543 // Davide: All the following values are taken from Table 91 of the
Davide Aliprandi 2:0c9ce59aee25 544 // reference manual for master clock enabled.
Davide Aliprandi 2:0c9ce59aee25 545 switch (hz) {
Davide Aliprandi 2:0c9ce59aee25 546 case I2S_AUDIOFREQ_8K:
Davide Aliprandi 2:0c9ce59aee25 547 PeriphClkInitStruct.PLLI2S.PLLI2SN = 256;
Davide Aliprandi 2:0c9ce59aee25 548 PeriphClkInitStruct.PLLI2S.PLLI2SR = 5;
Davide Aliprandi 2:0c9ce59aee25 549 break;
Davide Aliprandi 2:0c9ce59aee25 550
Davide Aliprandi 2:0c9ce59aee25 551 case I2S_AUDIOFREQ_16K:
Davide Aliprandi 2:0c9ce59aee25 552 case I2S_AUDIOFREQ_32K:
Davide Aliprandi 2:0c9ce59aee25 553 case (I2S_AUDIOFREQ_32K << 1):
Davide Aliprandi 2:0c9ce59aee25 554 PeriphClkInitStruct.PLLI2S.PLLI2SN = 213;
Davide Aliprandi 2:0c9ce59aee25 555 PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
Davide Aliprandi 2:0c9ce59aee25 556 break;
Davide Aliprandi 2:0c9ce59aee25 557
Davide Aliprandi 2:0c9ce59aee25 558 case I2S_AUDIOFREQ_48K:
Davide Aliprandi 2:0c9ce59aee25 559 PeriphClkInitStruct.PLLI2S.PLLI2SN = 258;
Davide Aliprandi 2:0c9ce59aee25 560 PeriphClkInitStruct.PLLI2S.PLLI2SR = 3;
Davide Aliprandi 2:0c9ce59aee25 561 break;
Davide Aliprandi 2:0c9ce59aee25 562
Davide Aliprandi 2:0c9ce59aee25 563 case I2S_AUDIOFREQ_96K:
Davide Aliprandi 2:0c9ce59aee25 564 PeriphClkInitStruct.PLLI2S.PLLI2SN = 344;
Davide Aliprandi 2:0c9ce59aee25 565 PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
Davide Aliprandi 2:0c9ce59aee25 566 break;
Davide Aliprandi 2:0c9ce59aee25 567
Davide Aliprandi 2:0c9ce59aee25 568 case I2S_AUDIOFREQ_44K:
Davide Aliprandi 2:0c9ce59aee25 569 default:
Davide Aliprandi 2:0c9ce59aee25 570 PeriphClkInitStruct.PLLI2S.PLLI2SN = 271;
Davide Aliprandi 2:0c9ce59aee25 571 PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
Davide Aliprandi 2:0c9ce59aee25 572 break;
Davide Aliprandi 2:0c9ce59aee25 573 }
Davide Aliprandi 2:0c9ce59aee25 574 #ifdef NDEBUG
Davide Aliprandi 2:0c9ce59aee25 575 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
Davide Aliprandi 2:0c9ce59aee25 576 #else
Davide Aliprandi 2:0c9ce59aee25 577 HAL_StatusTypeDef ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
Davide Aliprandi 2:0c9ce59aee25 578 #endif
Davide Aliprandi 2:0c9ce59aee25 579 MBED_ASSERT(ret == HAL_OK);
Davide Aliprandi 2:0c9ce59aee25 580
Davide Aliprandi 2:0c9ce59aee25 581 DEBUG_PRINTF("--> %s\r\n", __FUNCTION__);
Davide Aliprandi 2:0c9ce59aee25 582 DEBUG_PRINTF(" I2S%u: AudioFreq: %u\r\n", obj->i2s.module + 1,
Davide Aliprandi 2:0c9ce59aee25 583 (unsigned int)handle->Init.AudioFreq);
Wolfgang Betz 1:f90318e0923b 584
Wolfgang Betz 1:f90318e0923b 585 init_i2s(obj);
Wolfgang Betz 1:f90318e0923b 586 }
Wolfgang Betz 1:f90318e0923b 587
Davide Aliprandi 2:0c9ce59aee25 588 uint8_t i2s_get_module(i2s_t *obj) {
Wolfgang Betz 1:f90318e0923b 589 return obj->i2s.module;
Wolfgang Betz 1:f90318e0923b 590 }
Wolfgang Betz 1:f90318e0923b 591
Davide Aliprandi 2:0c9ce59aee25 592 static void i2s_start_asynch_transfer(i2s_t *obj, transfer_type_t transfer_type, void *tx, void *rx, int length) {
Wolfgang Betz 1:f90318e0923b 593 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 594 obj->i2s.transfer_type = transfer_type;
Wolfgang Betz 1:f90318e0923b 595
Wolfgang Betz 1:f90318e0923b 596 // the HAL expects number of transfers instead of number of bytes
Wolfgang Betz 1:f90318e0923b 597 int words;
Wolfgang Betz 1:f90318e0923b 598 switch(handle->Init.DataFormat) {
Davide Aliprandi 2:0c9ce59aee25 599 case I2S_DATAFORMAT_16B:
Davide Aliprandi 2:0c9ce59aee25 600 case I2S_DATAFORMAT_16B_EXTENDED:
Davide Aliprandi 2:0c9ce59aee25 601 words = length / 2;
Davide Aliprandi 2:0c9ce59aee25 602 if(words > 0xFFFC) words = 0xFFFC; // truncate in order to respect max DMA length
Davide Aliprandi 2:0c9ce59aee25 603 break;
Davide Aliprandi 2:0c9ce59aee25 604 case I2S_DATAFORMAT_24B:
Davide Aliprandi 2:0c9ce59aee25 605 case I2S_DATAFORMAT_32B:
Davide Aliprandi 2:0c9ce59aee25 606 default:
Davide Aliprandi 2:0c9ce59aee25 607 words = length / 4;
Davide Aliprandi 2:0c9ce59aee25 608 if(words > 0x7FFC) words = 0x7FFC; // truncate in order to respect max DMA length
Davide Aliprandi 2:0c9ce59aee25 609 break;
Wolfgang Betz 1:f90318e0923b 610 }
Wolfgang Betz 1:f90318e0923b 611
Wolfgang Betz 1:f90318e0923b 612 // enable the right hal transfer
Wolfgang Betz 1:f90318e0923b 613 int rc = 0;
Wolfgang Betz 1:f90318e0923b 614 switch(transfer_type) {
Davide Aliprandi 2:0c9ce59aee25 615 case I2S_TRANSFER_TYPE_TXRX:
Davide Aliprandi 2:0c9ce59aee25 616 // enable the interrupts
Davide Aliprandi 2:0c9ce59aee25 617 NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq);
Davide Aliprandi 2:0c9ce59aee25 618 NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq);
Davide Aliprandi 2:0c9ce59aee25 619 // trigger DMA transfers
Davide Aliprandi 2:0c9ce59aee25 620 rc = HAL_I2SEx_TransmitReceive_DMA(handle, (uint16_t*)tx, (uint16_t*)rx, (uint16_t)words);
Davide Aliprandi 2:0c9ce59aee25 621 break;
Davide Aliprandi 2:0c9ce59aee25 622 case I2S_TRANSFER_TYPE_TX:
Davide Aliprandi 2:0c9ce59aee25 623 // enable the interrupt
Davide Aliprandi 2:0c9ce59aee25 624 NVIC_EnableIRQ(obj->dma.dma[DMA_TX]->dma_stream_irq);
Davide Aliprandi 2:0c9ce59aee25 625 // trigger DMA transfer
Davide Aliprandi 2:0c9ce59aee25 626 rc = HAL_I2S_Transmit_DMA(handle, (uint16_t*)tx, (uint16_t)words);
Davide Aliprandi 2:0c9ce59aee25 627 break;
Davide Aliprandi 2:0c9ce59aee25 628 case I2S_TRANSFER_TYPE_RX:
Davide Aliprandi 2:0c9ce59aee25 629 // enable the interrupt
Davide Aliprandi 2:0c9ce59aee25 630 NVIC_EnableIRQ(obj->dma.dma[DMA_RX]->dma_stream_irq);
Davide Aliprandi 2:0c9ce59aee25 631 // trigger DMA transfer
Davide Aliprandi 2:0c9ce59aee25 632 rc = HAL_I2S_Receive_DMA(handle, (uint16_t*)rx, (uint16_t)words);
Davide Aliprandi 2:0c9ce59aee25 633 break;
Wolfgang Betz 1:f90318e0923b 634 }
Wolfgang Betz 1:f90318e0923b 635
Wolfgang Betz 1:f90318e0923b 636 if (rc) {
Davide Aliprandi 2:0c9ce59aee25 637 DEBUG_PRINTF(" I2S%u: RC: %d\r\n", obj->i2s.module + 1, rc);
Wolfgang Betz 1:f90318e0923b 638 }
Wolfgang Betz 1:f90318e0923b 639
Wolfgang Betz 1:f90318e0923b 640 return;
Wolfgang Betz 1:f90318e0923b 641 }
Wolfgang Betz 1:f90318e0923b 642
Wolfgang Betz 1:f90318e0923b 643 // asynchronous API
Wolfgang Betz 1:f90318e0923b 644 void i2s_transfer(i2s_t *obj,
Wolfgang Betz 1:f90318e0923b 645 void *tx, int tx_length,
Wolfgang Betz 1:f90318e0923b 646 void *rx, int rx_length,
Wolfgang Betz 1:f90318e0923b 647 bool circular, i2s_dma_prio_t prio,
Davide Aliprandi 2:0c9ce59aee25 648 uint32_t handler_tx, uint32_t handler_rx, uint32_t event) {
Wolfgang Betz 1:f90318e0923b 649 // check which use-case we have
Wolfgang Betz 1:f90318e0923b 650 bool use_tx = (tx != NULL && tx_length > 0);
Wolfgang Betz 1:f90318e0923b 651 bool use_rx = (rx != NULL && rx_length > 0);
Wolfgang Betz 1:f90318e0923b 652
Wolfgang Betz 1:f90318e0923b 653 // Init DMAs
Wolfgang Betz 1:f90318e0923b 654 dma_i2s_init(obj, &use_tx, &use_rx, circular, prio);
Wolfgang Betz 1:f90318e0923b 655
Wolfgang Betz 1:f90318e0923b 656 // don't do anything, if the buffers aren't valid
Wolfgang Betz 1:f90318e0923b 657 if (!use_tx && !use_rx)
Wolfgang Betz 1:f90318e0923b 658 return;
Wolfgang Betz 1:f90318e0923b 659
Wolfgang Betz 1:f90318e0923b 660 // copy the buffers to the I2S object
Wolfgang Betz 1:f90318e0923b 661 obj->tx_buff.buffer = tx;
Wolfgang Betz 1:f90318e0923b 662 obj->tx_buff.length = tx_length;
Wolfgang Betz 1:f90318e0923b 663 obj->tx_buff.pos = 0;
Wolfgang Betz 1:f90318e0923b 664 obj->tx_buff.width = 16;
Wolfgang Betz 1:f90318e0923b 665
Wolfgang Betz 1:f90318e0923b 666 obj->rx_buff.buffer = rx;
Wolfgang Betz 1:f90318e0923b 667 obj->rx_buff.length = rx_length;
Wolfgang Betz 1:f90318e0923b 668 obj->rx_buff.pos = 0;
Wolfgang Betz 1:f90318e0923b 669 obj->rx_buff.width = obj->tx_buff.width;
Wolfgang Betz 1:f90318e0923b 670
Wolfgang Betz 1:f90318e0923b 671 obj->i2s.event = event;
Wolfgang Betz 1:f90318e0923b 672
Davide Aliprandi 2:0c9ce59aee25 673 DEBUG_PRINTF(" I2S%u: Transfer: %u, %u\r\n", obj->i2s.module + 1, tx_length, rx_length);
Wolfgang Betz 1:f90318e0923b 674
Wolfgang Betz 1:f90318e0923b 675 // register the thunking handler
Davide Aliprandi 2:0c9ce59aee25 676 if (use_tx) {
Davide Aliprandi 2:0c9ce59aee25 677 NVIC_SetVector(obj->dma.dma[DMA_TX]->dma_stream_irq, handler_tx);
Wolfgang Betz 1:f90318e0923b 678 }
Davide Aliprandi 2:0c9ce59aee25 679 if (use_rx) {
Davide Aliprandi 2:0c9ce59aee25 680 NVIC_SetVector(obj->dma.dma[DMA_RX]->dma_stream_irq, handler_rx);
Wolfgang Betz 1:f90318e0923b 681 }
Wolfgang Betz 1:f90318e0923b 682
Wolfgang Betz 1:f90318e0923b 683 // enable the right hal transfer
Wolfgang Betz 1:f90318e0923b 684 if (use_tx && use_rx) {
Davide Aliprandi 2:0c9ce59aee25 685 int size = (tx_length < rx_length)? tx_length : rx_length;
Davide Aliprandi 2:0c9ce59aee25 686 i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TXRX, tx, rx, size);
Wolfgang Betz 1:f90318e0923b 687 } else if (use_tx) {
Davide Aliprandi 2:0c9ce59aee25 688 i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_TX, tx, NULL, tx_length);
Wolfgang Betz 1:f90318e0923b 689 } else if (use_rx) {
Davide Aliprandi 2:0c9ce59aee25 690 i2s_start_asynch_transfer(obj, I2S_TRANSFER_TYPE_RX, NULL, rx, rx_length);
Wolfgang Betz 1:f90318e0923b 691 }
Wolfgang Betz 1:f90318e0923b 692 }
Wolfgang Betz 1:f90318e0923b 693
Davide Aliprandi 2:0c9ce59aee25 694 uint32_t i2s_irq_handler_asynch(i2s_t *obj, uint8_t direction) {
Wolfgang Betz 1:f90318e0923b 695 direction = (direction == I2S_TX_EVENT) ? DMA_TX : DMA_RX;
Wolfgang Betz 1:f90318e0923b 696
Wolfgang Betz 1:f90318e0923b 697 // use the right instance
Wolfgang Betz 1:f90318e0923b 698 I2S_HandleTypeDef *i2s_handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 699 DMA_HandleTypeDef *dma_handle = (direction == DMA_TX) ? i2s_handle->hdmatx : i2s_handle->hdmarx;
Wolfgang Betz 1:f90318e0923b 700
Wolfgang Betz 1:f90318e0923b 701 MBED_ASSERT(dma_handle != NULL);
Wolfgang Betz 1:f90318e0923b 702
Wolfgang Betz 1:f90318e0923b 703 int event = 0;
Wolfgang Betz 1:f90318e0923b 704
Wolfgang Betz 1:f90318e0923b 705 // call the Cube handler, this will update the handle
Wolfgang Betz 1:f90318e0923b 706 HAL_DMA_IRQHandler(dma_handle);
Wolfgang Betz 1:f90318e0923b 707
Davide Aliprandi 2:0c9ce59aee25 708 switch(HAL_I2S_GetState(i2s_handle))
Davide Aliprandi 2:0c9ce59aee25 709 {
Davide Aliprandi 2:0c9ce59aee25 710 case HAL_I2S_STATE_READY: {
Davide Aliprandi 2:0c9ce59aee25 711 // adjust buffer positions (betzw - TODO: to be checked for DMA transfers!!!)
Davide Aliprandi 2:0c9ce59aee25 712 int tx_size = (i2s_handle->TxXferSize - i2s_handle->TxXferCount);
Davide Aliprandi 2:0c9ce59aee25 713 int rx_size = (i2s_handle->RxXferSize - i2s_handle->RxXferCount);
Wolfgang Betz 1:f90318e0923b 714
Davide Aliprandi 2:0c9ce59aee25 715 // take data format into consideration
Davide Aliprandi 2:0c9ce59aee25 716 switch(i2s_handle->Init.DataFormat)
Davide Aliprandi 2:0c9ce59aee25 717 {
Davide Aliprandi 2:0c9ce59aee25 718 case I2S_DATAFORMAT_16B:
Davide Aliprandi 2:0c9ce59aee25 719 case I2S_DATAFORMAT_16B_EXTENDED:
Davide Aliprandi 2:0c9ce59aee25 720 tx_size *= 2;
Davide Aliprandi 2:0c9ce59aee25 721 rx_size *= 2;
Davide Aliprandi 2:0c9ce59aee25 722 break;
Davide Aliprandi 2:0c9ce59aee25 723 case I2S_DATAFORMAT_24B:
Davide Aliprandi 2:0c9ce59aee25 724 case I2S_DATAFORMAT_32B:
Davide Aliprandi 2:0c9ce59aee25 725 default:
Davide Aliprandi 2:0c9ce59aee25 726 tx_size *= 4;
Davide Aliprandi 2:0c9ce59aee25 727 rx_size *= 4;
Davide Aliprandi 2:0c9ce59aee25 728 break;
Davide Aliprandi 2:0c9ce59aee25 729 }
Wolfgang Betz 1:f90318e0923b 730
Davide Aliprandi 2:0c9ce59aee25 731 // adjust buffer positions
Davide Aliprandi 2:0c9ce59aee25 732 if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_RX) {
Davide Aliprandi 2:0c9ce59aee25 733 obj->tx_buff.pos += tx_size;
Davide Aliprandi 2:0c9ce59aee25 734 }
Davide Aliprandi 2:0c9ce59aee25 735 if (obj->i2s.transfer_type != I2S_TRANSFER_TYPE_TX) {
Davide Aliprandi 2:0c9ce59aee25 736 obj->rx_buff.pos += rx_size;
Davide Aliprandi 2:0c9ce59aee25 737 }
Wolfgang Betz 1:f90318e0923b 738
Davide Aliprandi 2:0c9ce59aee25 739 if (i2s_handle->TxXferCount > 0) {
Davide Aliprandi 2:0c9ce59aee25 740 DEBUG_PRINTF(" I2S%u: TxXferCount: %u\r\n", obj->i2s.module + 1, i2s_handle->TxXferCount);
Davide Aliprandi 2:0c9ce59aee25 741 }
Davide Aliprandi 2:0c9ce59aee25 742 if (i2s_handle->RxXferCount > 0) {
Davide Aliprandi 2:0c9ce59aee25 743 DEBUG_PRINTF(" I2S%u: RxXferCount: %u\r\n", obj->i2s.module + 1, i2s_handle->RxXferCount);
Davide Aliprandi 2:0c9ce59aee25 744 }
Davide Aliprandi 2:0c9ce59aee25 745 }
Davide Aliprandi 2:0c9ce59aee25 746 /* no break */
Wolfgang Betz 1:f90318e0923b 747
Davide Aliprandi 2:0c9ce59aee25 748 case HAL_I2S_STATE_BUSY_TX:
Davide Aliprandi 2:0c9ce59aee25 749 case HAL_I2S_STATE_BUSY_RX:
Davide Aliprandi 2:0c9ce59aee25 750 case HAL_I2S_STATE_BUSY_TX_RX:
Davide Aliprandi 2:0c9ce59aee25 751 {
Davide Aliprandi 2:0c9ce59aee25 752 int error = HAL_I2S_GetError(i2s_handle);
Wolfgang Betz 1:f90318e0923b 753
Davide Aliprandi 2:0c9ce59aee25 754 if (error != HAL_I2S_ERROR_NONE) {
Davide Aliprandi 2:0c9ce59aee25 755 // something went wrong and the transfer has definitely completed
Davide Aliprandi 2:0c9ce59aee25 756 event = ((direction == DMA_TX) ? I2S_EVENT_TX_ERROR : I2S_EVENT_RX_ERROR) | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE;
Wolfgang Betz 1:f90318e0923b 757
Davide Aliprandi 2:0c9ce59aee25 758 if (error & HAL_I2S_ERROR_OVR) {
Davide Aliprandi 2:0c9ce59aee25 759 // buffer overrun
Davide Aliprandi 2:0c9ce59aee25 760 event |= I2S_EVENT_RX_OVERFLOW;
Davide Aliprandi 2:0c9ce59aee25 761 }
Wolfgang Betz 1:f90318e0923b 762
Davide Aliprandi 2:0c9ce59aee25 763 if (error & HAL_I2S_ERROR_UDR) {
Davide Aliprandi 2:0c9ce59aee25 764 // buffer underrun
Davide Aliprandi 2:0c9ce59aee25 765 event |= I2S_EVENT_TX_UNDERRUN;
Davide Aliprandi 2:0c9ce59aee25 766 }
Wolfgang Betz 1:f90318e0923b 767
Davide Aliprandi 2:0c9ce59aee25 768 // cleanup DMA (after error)
Davide Aliprandi 2:0c9ce59aee25 769 dma_i2s_free(obj, direction);
Davide Aliprandi 2:0c9ce59aee25 770 } else
Davide Aliprandi 2:0c9ce59aee25 771 { // no error detected
Davide Aliprandi 2:0c9ce59aee25 772 HAL_DMA_StateTypeDef dma_state = HAL_DMA_GetState(dma_handle);
Wolfgang Betz 1:f90318e0923b 773
Davide Aliprandi 2:0c9ce59aee25 774 switch(dma_state)
Davide Aliprandi 2:0c9ce59aee25 775 {
Davide Aliprandi 2:0c9ce59aee25 776 case HAL_DMA_STATE_READY_HALF_MEM0:
Davide Aliprandi 2:0c9ce59aee25 777 case HAL_DMA_STATE_READY_HALF_MEM1:
Davide Aliprandi 2:0c9ce59aee25 778 event = ((direction == DMA_TX) ? I2S_EVENT_TX_HALF_COMPLETE : I2S_EVENT_RX_HALF_COMPLETE);
Davide Aliprandi 2:0c9ce59aee25 779 break;
Davide Aliprandi 2:0c9ce59aee25 780 case HAL_DMA_STATE_READY_MEM0:
Davide Aliprandi 2:0c9ce59aee25 781 case HAL_DMA_STATE_READY_MEM1:
Davide Aliprandi 2:0c9ce59aee25 782 event = ((direction == DMA_TX) ? I2S_EVENT_TX_COMPLETE : I2S_EVENT_RX_COMPLETE);
Davide Aliprandi 2:0c9ce59aee25 783 if(dma_handle->Init.Mode != DMA_CIRCULAR)
Davide Aliprandi 2:0c9ce59aee25 784 {
Davide Aliprandi 2:0c9ce59aee25 785 if (!i2s_active(obj))
Davide Aliprandi 2:0c9ce59aee25 786 { // Check for full-duplex transfer complete!
Davide Aliprandi 2:0c9ce59aee25 787 event |= I2S_EVENT_INTERNAL_TRANSFER_COMPLETE;
Davide Aliprandi 2:0c9ce59aee25 788 }
Wolfgang Betz 1:f90318e0923b 789
Davide Aliprandi 2:0c9ce59aee25 790 // cleanup DMA (because we are done)
Davide Aliprandi 2:0c9ce59aee25 791 dma_i2s_free(obj, direction);
Davide Aliprandi 2:0c9ce59aee25 792 }
Davide Aliprandi 2:0c9ce59aee25 793 break;
Davide Aliprandi 2:0c9ce59aee25 794 default:
Davide Aliprandi 2:0c9ce59aee25 795 printf("betzw(%s, %d): dma_state=0x%x\r\n", __func__, __LINE__, (int)dma_state);
Davide Aliprandi 2:0c9ce59aee25 796 MBED_ASSERT(0);
Davide Aliprandi 2:0c9ce59aee25 797 break;
Davide Aliprandi 2:0c9ce59aee25 798 }
Davide Aliprandi 2:0c9ce59aee25 799 }
Davide Aliprandi 2:0c9ce59aee25 800 }
Davide Aliprandi 2:0c9ce59aee25 801 break;
Wolfgang Betz 1:f90318e0923b 802 default:
Davide Aliprandi 2:0c9ce59aee25 803 // nothing to do?!?
Davide Aliprandi 2:0c9ce59aee25 804 break;
Wolfgang Betz 1:f90318e0923b 805 }
Wolfgang Betz 1:f90318e0923b 806
Davide Aliprandi 2:0c9ce59aee25 807 if (event) DEBUG_PRINTF(" I2S%u: Event: 0x%x\r\n", obj->i2s.module + 1, event);
Wolfgang Betz 1:f90318e0923b 808
Wolfgang Betz 1:f90318e0923b 809 return (event & (obj->i2s.event | I2S_EVENT_INTERNAL_TRANSFER_COMPLETE));
Wolfgang Betz 1:f90318e0923b 810 }
Wolfgang Betz 1:f90318e0923b 811
Davide Aliprandi 2:0c9ce59aee25 812 uint8_t i2s_active(i2s_t *obj) {
Wolfgang Betz 1:f90318e0923b 813 I2S_HandleTypeDef *handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 814 HAL_I2S_StateTypeDef state = HAL_I2S_GetState(handle);
Wolfgang Betz 1:f90318e0923b 815
Davide Aliprandi 2:0c9ce59aee25 816 switch(state){
Davide Aliprandi 2:0c9ce59aee25 817 case HAL_I2S_STATE_RESET:
Davide Aliprandi 2:0c9ce59aee25 818 case HAL_I2S_STATE_READY:
Davide Aliprandi 2:0c9ce59aee25 819 case HAL_I2S_STATE_ERROR:
Davide Aliprandi 2:0c9ce59aee25 820 return 0;
Davide Aliprandi 2:0c9ce59aee25 821 default:
Davide Aliprandi 2:0c9ce59aee25 822 return -1;
Wolfgang Betz 1:f90318e0923b 823 }
Wolfgang Betz 1:f90318e0923b 824 }
Wolfgang Betz 1:f90318e0923b 825
Davide Aliprandi 2:0c9ce59aee25 826 void i2s_abort_asynch(i2s_t *obj) {
Wolfgang Betz 1:f90318e0923b 827 I2S_HandleTypeDef *i2s_handle = &I2sHandle[obj->i2s.module];
Wolfgang Betz 1:f90318e0923b 828
Wolfgang Betz 1:f90318e0923b 829 // Stop transfer
Wolfgang Betz 1:f90318e0923b 830 HAL_I2S_DMAStop(i2s_handle);
Wolfgang Betz 1:f90318e0923b 831
Wolfgang Betz 1:f90318e0923b 832 if(obj->dma.dma[DMA_TX] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 833 DMA_HandleTypeDef *dma_handle_tx = &DMaHandles[obj->i2s.module][DMA_TX];
Wolfgang Betz 1:f90318e0923b 834
Davide Aliprandi 2:0c9ce59aee25 835 // disable interrupt & free resource
Davide Aliprandi 2:0c9ce59aee25 836 dma_i2s_free(obj, DMA_TX);
Davide Aliprandi 2:0c9ce59aee25 837
Davide Aliprandi 2:0c9ce59aee25 838 //clean up
Davide Aliprandi 2:0c9ce59aee25 839 __HAL_DMA_DISABLE(dma_handle_tx);
Davide Aliprandi 2:0c9ce59aee25 840 HAL_DMA_DeInit(dma_handle_tx);
Davide Aliprandi 2:0c9ce59aee25 841 HAL_DMA_Init(dma_handle_tx);
Davide Aliprandi 2:0c9ce59aee25 842 __HAL_DMA_ENABLE(dma_handle_tx);
Wolfgang Betz 1:f90318e0923b 843 }
Wolfgang Betz 1:f90318e0923b 844 if(obj->dma.dma[DMA_RX] != NULL) {
Davide Aliprandi 2:0c9ce59aee25 845 DMA_HandleTypeDef *dma_handle_rx = &DMaHandles[obj->i2s.module][DMA_RX];
Wolfgang Betz 1:f90318e0923b 846
Davide Aliprandi 2:0c9ce59aee25 847 // disable interrupt & free resource
Davide Aliprandi 2:0c9ce59aee25 848 dma_i2s_free(obj, DMA_RX);
Wolfgang Betz 1:f90318e0923b 849
Davide Aliprandi 2:0c9ce59aee25 850 //clean up
Davide Aliprandi 2:0c9ce59aee25 851 __HAL_DMA_DISABLE(dma_handle_rx);
Davide Aliprandi 2:0c9ce59aee25 852 HAL_DMA_DeInit(dma_handle_rx);
Davide Aliprandi 2:0c9ce59aee25 853 HAL_DMA_Init(dma_handle_rx);
Davide Aliprandi 2:0c9ce59aee25 854 __HAL_DMA_ENABLE(dma_handle_rx);
Wolfgang Betz 1:f90318e0923b 855 }
Wolfgang Betz 1:f90318e0923b 856
Wolfgang Betz 1:f90318e0923b 857 // clean-up I2S
Wolfgang Betz 1:f90318e0923b 858 __HAL_I2S_DISABLE(i2s_handle);
Wolfgang Betz 1:f90318e0923b 859 HAL_I2S_DeInit(i2s_handle);
Wolfgang Betz 1:f90318e0923b 860 HAL_I2S_Init(i2s_handle);
Wolfgang Betz 1:f90318e0923b 861 __HAL_I2S_ENABLE(i2s_handle);
Wolfgang Betz 1:f90318e0923b 862 }
Wolfgang Betz 1:f90318e0923b 863
Wolfgang Betz 1:f90318e0923b 864 #endif