1 /* 2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef __WM_I2S_H 17 #define __WM_I2S_H 18 19 #include <stdbool.h> 20 #include "wm_regs.h" 21 #include "wm_debug.h" 22 #include "wm_dma.h" 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 typedef void (*tls_i2s_callback)(uint32_t *data, uint16_t *len); 29 30 typedef struct { 31 __IO uint32_t CTRL; 32 __IO uint32_t INT_MASK; 33 __IO uint32_t INT_SRC; 34 __I uint32_t INT_STATUS; 35 __O uint32_t TX; 36 __I uint32_t RX; 37 } I2S_T; 38 39 typedef struct { 40 uint32_t I2S_Mode_MS; // master or slave mode 41 uint32_t I2S_Mode_SS; // stereo or single channel 42 uint32_t I2S_Mode_LR; // left or right channel 43 uint32_t I2S_Trans_STD; 44 uint32_t I2S_DataFormat; 45 uint32_t I2S_AudioFreq; 46 uint32_t I2S_MclkFreq; 47 } I2S_InitDef; 48 49 typedef struct _wm_dma_desc { 50 unsigned int valid; 51 unsigned int dma_ctrl; 52 unsigned int src_addr; 53 unsigned int dest_addr; 54 struct _wm_dma_desc *next; 55 }wm_dma_desc; 56 57 typedef struct _dma_handler_type { 58 uint8_t channel; 59 void (* XferCpltCallback)(struct _dma_handler_type *hdma); /* !< DMA transfer complete callback */ 60 void (* XferHalfCpltCallback)(struct _dma_handler_type *hdma); /* !< DMA Half transfer complete callback */ 61 }wm_dma_handler_type; 62 63 #define I2S ((I2S_T *)HR_I2S_REG_BASE) 64 65 #define I2S_MODE_MASTER ((bool)0x0) 66 #define I2S_MODE_SLAVE ((bool)0x1) 67 68 #define I2S_RIGHT_CHANNEL ((bool)0x0) 69 #define I2S_LEFT_CHANNEL ((bool)0x1) 70 71 #define I2S_Standard (0x0UL) 72 #define I2S_Standard_MSB (0x1000000UL) 73 #define I2S_Standard_PCMA (0x2000000UL) 74 #define I2S_Standard_PCMB (0x3000000UL) 75 76 #define I2S_DataFormat_8 (8) 77 #define I2S_DataFormat_16 (16) 78 #define I2S_DataFormat_24 (24) 79 #define I2S_DataFormat_32 (32) 80 81 #define I2S_CTRL_CHSEL_MASK (1UL<<23) 82 #define I2S_CTRL_CHSEL_LEFT (1UL<<23) 83 #define I2S_CTRL_MONO (1UL<<22) 84 #define I2S_CTRL_STEREO (0UL<<22) 85 #define I2S_CTRL_RXDMA_EN (1UL<<21) 86 #define I2S_CTRL_TXDMA_EN (1UL<<20) 87 #define I2S_CTRL_RX_CLR (1UL<<19) 88 #define I2S_CTRL_TX_CLR (1UL<<18) 89 #define I2S_CTRL_LZCEN (1UL<<17) 90 #define I2S_CTRL_RZCEN (1UL<<16) 91 #define I2S_CTRL_RXTH(n) (((n)-1)<<12) 92 #define I2S_CTRL_TXTH(n) ((n)<<9) 93 #define I2S_CTRL_SLAVE_SEL (1UL<<8) 94 #define I2S_CTRL_MUTE (1UL<<3) 95 #define I2S_CTRL_RXE (1UL<<2) 96 #define I2S_CTRL_TXE (1UL<<1) 97 #define I2S_CTRL_EN (1UL<<0) 98 99 #define I2S_INT_MASK_LZC ((uint16_t)0x200) 100 #define I2S_INT_MASK_RZC ((uint16_t)0x100) 101 #define I2S_INT_MASK_TXDONE ((uint16_t)0x080) 102 #define I2S_INT_MASK_TXTH ((uint16_t)0x040) 103 #define I2S_INT_MASK_TXOV ((uint16_t)0x020) 104 #define I2S_INT_MASK_TXUD ((uint16_t)0x010) 105 #define I2S_INT_MASK_RXDONE ((uint16_t)0x008) 106 #define I2S_INT_MASK_RXTH ((uint16_t)0x004) 107 #define I2S_INT_MASK_RXOV ((uint16_t)0x002) 108 #define I2S_INT_MASK_RXUD ((uint16_t)0x002) 109 110 #define I2S_FLAG_TX ((uint16_t)0x1000) 111 #define I2S_FLAG_RX ((uint16_t)0x0800) 112 #define I2S_FLAG_I2S ((uint16_t)0x0400) 113 #define I2S_FLAG_LZC ((uint16_t)0x0200) 114 #define I2S_FLAG_RZC ((uint16_t)0x0100) 115 #define I2S_FLAG_TXDONE ((uint16_t)0x0080) 116 #define I2S_FLAG_TXTH ((uint16_t)0x0040) 117 #define I2S_FLAG_TXOV ((uint16_t)0x0020) 118 #define I2S_FLAG_TXUD ((uint16_t)0x0010) 119 #define I2S_FLAG_RXDONE ((uint16_t)0x0008) 120 #define I2S_FLAG_RXTH ((uint16_t)0x0004) 121 #define I2S_FLAG_RXOV ((uint16_t)0x0002) 122 #define I2S_FLAG_RXUD ((uint16_t)0x0001) 123 124 #define WM_I2S_TX_DMA_CHANNEL (1) 125 #define WM_I2S_RX_DMA_CHANNEL (5) 126 127 typedef struct wm_i2s_buf_s { 128 volatile uint32_t *txbuf; 129 volatile uint32_t txlen; 130 volatile uint32_t txtail; 131 volatile uint32_t *rxbuf; 132 volatile uint32_t rxlen; 133 volatile uint32_t int_txlen; 134 volatile uint32_t rxhead; 135 volatile uint8_t rxdata_ready; 136 volatile uint8_t txdata_done; 137 138 /** function pointer for data receiver */ 139 void (*rx_callback)(void); 140 /** function pointer for data transmit */ 141 void (*tx_callback)(uint32_t *data, uint16_t *len); 142 } wm_i2s_buf_t; 143 /** 144 * @defgroup Driver_APIs Driver APIs 145 * @brief Driver APIs 146 */ 147 148 /** 149 * @addtogroup Driver_APIs 150 * @{ 151 */ 152 153 /** 154 * @defgroup I2S_Driver_APIs I2S Driver APIs 155 * @brief I2S driver APIs 156 */ 157 158 /** 159 * @addtogroup I2S_Driver_APIs 160 * @{ 161 */ 162 163 /** 164 * @brief Register a callback function 165 * @param callback pointer to a callback function in which you can prepare the next buffer 166 * @param callback->data pointer to data buffer to be prepared 167 * @param callback->len size of the data buffer to be prepared in 32-bit 168 * @note The registerred callback function will be called as long as the transmission begins 169 * @retval none 170 */ 171 void wm_i2s_register_callback(tls_i2s_callback callback); 172 173 /** 174 * @brief Initializes the I2S according to the specified parameters 175 * in the I2S_InitDef. 176 * @param opts pointer to a I2S_InitDef structure that contains 177 * the configuration information for I2S module 178 * @retval status 179 */ 180 int wm_i2s_port_init(I2S_InitDef *opts); 181 182 /** 183 * @brief stop i2s module 184 * @retval none 185 */ 186 void wm_i2s_tx_rx_stop(void); 187 188 /** 189 * @brief Transmit an amount of data in blocking mode with Interrupt 190 * @param data a 16-bit pointer to data buffer. 191 * @param len number of data sample to be sent: 192 * @param next_data a 16-bit pointer to the next data buffer, same size with data; set to NULL if it's not needed 193 * @note the len parameter means the number of 16-bit data length. 194 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 195 * between Master and Slave(example: audio streaming). 196 * @note This function will block its task until the transmission is over,so perpare the next data 197 * buffer at another task during this interval. 198 * @note This function will call the registerred callback function as long as the transmission begins 199 * @retval status 200 */ 201 int wm_i2s_tx_int(int16_t *data, uint16_t len, int16_t *next_data); 202 203 /** 204 * @brief Transmit an amount of data in blocking mode with DMA's normal mode 205 * @param data a 16-bit pointer to data buffer. 206 * @param len number of data sample to be sent: 207 * @param next_data a 16-bit pointer to the next data buffer, same size with data; set to NULL if it's not needed 208 * @note the len parameter means the number of 32-bit data length. 209 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 210 * between Master and Slave(example: audio streaming). 211 * @note This function will block its task until the transmission is over,so perpare the next data 212 * buffer at another task during this interval. 213 * @note This function will call the registerred callback function as long as the transmission begins 214 * @retval status 215 */ 216 int wm_i2s_tx_dma(int16_t *data, uint16_t len, int16_t *next_data); 217 218 /** 219 * @brief Transmit an amount of data in blocking mode with DMA's link mode 220 * @param data a 16-bit pointer to data buffer. 221 * @param len number of data sample to be sent: 222 * @param next_data a 16-bit pointer to the next data buffer, same size with data: 223 * @note the len parameter means the number of 32-bit data length. 224 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 225 * between Master and Slave(example: audio streaming). 226 * @note This function will block its task until the transmission is over,so perpare the next data 227 * buffer at another task during this interval.Set len to 0xffff will exit this rountine. 228 * @note This function will call the registerred callback function as long as the data or next_data 229 * is sent out.So prepare it in the callback. 230 * @note See the demo for detail use. 231 * @retval status 232 */ 233 int wm_i2s_tx_dma_link(int16_t *data, uint16_t len, int16_t *next_data); 234 235 /** 236 * @brief Receive an amount of data in blocking mode with Interrupt 237 * @param data a 16-bit pointer to the Receive data buffer. 238 * @param len number of data sample to be received: 239 * @note the len parameter means the number of 16-bit data length. 240 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 241 * between Master and Slave(example: audio streaming). 242 * @note This function will block its task until the transmission is over,so perpare the next data 243 * buffer at another task during this interval. 244 * @retval status 245 */ 246 int wm_i2s_rx_int(int16_t *data, uint16_t len); 247 248 /** 249 * @brief Receive an amount of data in blocking mode with DMA 250 * @param data a 16-bit pointer to the Receive data buffer. 251 * @param len number of data sample to be received: 252 * @note the len parameter means the number of 16-bit data length. 253 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 254 * between Master and Slave(example: audio streaming). 255 * @note This function will block its task until the transmission is over,so perpare the next data 256 * buffer at another task during this interval. 257 * @retval status 258 */ 259 int wm_i2s_rx_dma(int16_t *data, uint16_t len); 260 261 /** 262 * @brief Full-Duplex Transmit/Receive data in blocking mode using Interrupt 263 * @param opts pointer to a I2S_InitDef structure that contains 264 * the configuration information for I2S module 265 * @param data_tx a 16-bit pointer to the Transmit data buffer. 266 * @param data_rx a 16-bit pointer to the Receive data buffer. 267 * @param len number of data sample to be sent: 268 * @note the len parameter means the number of 16-bit data length. 269 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 270 * between Master and Slave(example: audio streaming). 271 * @note This function will block its task until the transmission is over,so perpare the next data 272 * buffer at another task during this interval. 273 * @retval status 274 */ 275 int wm_i2s_tx_rx_int(I2S_InitDef *opts, int16_t *data_tx, int16_t *data_rx, uint16_t len); 276 277 /** 278 * @brief Full-Duplex Transmit/Receive data in blocking mode using DMA 279 * @param opts pointer to a I2S_InitDef structure that contains 280 * the configuration information for I2S module 281 * @param data_tx a 16-bit pointer to the Transmit data buffer. 282 * @param data_rx a 16-bit pointer to the Receive data buffer. 283 * @param len number of data sample to be sent: 284 * @note the len parameter means the number of 16-bit data length. 285 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization 286 * between Master and Slave(example: audio streaming). 287 * @note This function will block its task until the transmission is over,so perpare the next data 288 * buffer at another task during this interval. 289 * @retval status 290 */ 291 int wm_i2s_tx_rx_dma(I2S_InitDef *opts, int16_t *data_tx, int16_t *data_rx, uint16_t len); 292 293 int wm_i2s_transmit_dma(wm_dma_handler_type *hdma, uint16_t *data, uint16_t len); 294 int wm_i2s_receive_dma(wm_dma_handler_type *hdma, uint16_t *data, uint16_t len); 295 296 /** 297 * @} 298 */ 299 300 /** 301 * @} 302 */ 303 304 #ifdef __cplusplus 305 } 306 #endif 307 308 #endif 309