Il y avait des problèmes dans la libraire...
Fork of ST_I2S by
targets/TARGET_STM/stm_i2s_api.c@2:0c9ce59aee25, 2016-12-13 (annotated)
- 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?
User | Revision | Line number | New 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 |