Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_sai.c@154:37f96f9d4de2, 2017-01-04 (annotated)
- Committer:
- <>
- Date:
- Wed Jan 04 16:58:05 2017 +0000
- Revision:
- 154:37f96f9d4de2
This updates the lib to the mbed lib v133
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 154:37f96f9d4de2 | 1 | /* |
<> | 154:37f96f9d4de2 | 2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. |
<> | 154:37f96f9d4de2 | 3 | * All rights reserved. |
<> | 154:37f96f9d4de2 | 4 | * |
<> | 154:37f96f9d4de2 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
<> | 154:37f96f9d4de2 | 6 | * are permitted provided that the following conditions are met: |
<> | 154:37f96f9d4de2 | 7 | * |
<> | 154:37f96f9d4de2 | 8 | * o Redistributions of source code must retain the above copyright notice, this list |
<> | 154:37f96f9d4de2 | 9 | * of conditions and the following disclaimer. |
<> | 154:37f96f9d4de2 | 10 | * |
<> | 154:37f96f9d4de2 | 11 | * o Redistributions in binary form must reproduce the above copyright notice, this |
<> | 154:37f96f9d4de2 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
<> | 154:37f96f9d4de2 | 13 | * other materials provided with the distribution. |
<> | 154:37f96f9d4de2 | 14 | * |
<> | 154:37f96f9d4de2 | 15 | * o Neither the name of Freescale Semiconductor, Inc. nor the names of its |
<> | 154:37f96f9d4de2 | 16 | * contributors may be used to endorse or promote products derived from this |
<> | 154:37f96f9d4de2 | 17 | * software without specific prior written permission. |
<> | 154:37f96f9d4de2 | 18 | * |
<> | 154:37f96f9d4de2 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
<> | 154:37f96f9d4de2 | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
<> | 154:37f96f9d4de2 | 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
<> | 154:37f96f9d4de2 | 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
<> | 154:37f96f9d4de2 | 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
<> | 154:37f96f9d4de2 | 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
<> | 154:37f96f9d4de2 | 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
<> | 154:37f96f9d4de2 | 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
<> | 154:37f96f9d4de2 | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
<> | 154:37f96f9d4de2 | 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
<> | 154:37f96f9d4de2 | 29 | */ |
<> | 154:37f96f9d4de2 | 30 | |
<> | 154:37f96f9d4de2 | 31 | #include "fsl_sai.h" |
<> | 154:37f96f9d4de2 | 32 | |
<> | 154:37f96f9d4de2 | 33 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 34 | * Definitations |
<> | 154:37f96f9d4de2 | 35 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 36 | enum _sai_transfer_state |
<> | 154:37f96f9d4de2 | 37 | { |
<> | 154:37f96f9d4de2 | 38 | kSAI_Busy = 0x0U, /*!< SAI is busy */ |
<> | 154:37f96f9d4de2 | 39 | kSAI_Idle, /*!< Transfer is done. */ |
<> | 154:37f96f9d4de2 | 40 | kSAI_Error /*!< Transfer error occured. */ |
<> | 154:37f96f9d4de2 | 41 | }; |
<> | 154:37f96f9d4de2 | 42 | |
<> | 154:37f96f9d4de2 | 43 | /*! @brief Typedef for sai tx interrupt handler. */ |
<> | 154:37f96f9d4de2 | 44 | typedef void (*sai_tx_isr_t)(I2S_Type *base, sai_handle_t *saiHandle); |
<> | 154:37f96f9d4de2 | 45 | |
<> | 154:37f96f9d4de2 | 46 | /*! @brief Typedef for sai rx interrupt handler. */ |
<> | 154:37f96f9d4de2 | 47 | typedef void (*sai_rx_isr_t)(I2S_Type *base, sai_handle_t *saiHandle); |
<> | 154:37f96f9d4de2 | 48 | |
<> | 154:37f96f9d4de2 | 49 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 50 | * Prototypes |
<> | 154:37f96f9d4de2 | 51 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 52 | #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) |
<> | 154:37f96f9d4de2 | 53 | |
<> | 154:37f96f9d4de2 | 54 | /*! |
<> | 154:37f96f9d4de2 | 55 | * @brief Set the master clock divider. |
<> | 154:37f96f9d4de2 | 56 | * |
<> | 154:37f96f9d4de2 | 57 | * This API will compute the master clock divider according to master clock frequency and master |
<> | 154:37f96f9d4de2 | 58 | * clock source clock source frequency. |
<> | 154:37f96f9d4de2 | 59 | * |
<> | 154:37f96f9d4de2 | 60 | * @param base SAI base pointer. |
<> | 154:37f96f9d4de2 | 61 | * @param mclk_Hz Mater clock frequency in Hz. |
<> | 154:37f96f9d4de2 | 62 | * @param mclkSrcClock_Hz Master clock source frequency in Hz. |
<> | 154:37f96f9d4de2 | 63 | */ |
<> | 154:37f96f9d4de2 | 64 | static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz); |
<> | 154:37f96f9d4de2 | 65 | #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */ |
<> | 154:37f96f9d4de2 | 66 | |
<> | 154:37f96f9d4de2 | 67 | /*! |
<> | 154:37f96f9d4de2 | 68 | * @brief Get the instance number for SAI. |
<> | 154:37f96f9d4de2 | 69 | * |
<> | 154:37f96f9d4de2 | 70 | * @param base SAI base pointer. |
<> | 154:37f96f9d4de2 | 71 | */ |
<> | 154:37f96f9d4de2 | 72 | uint32_t SAI_GetInstance(I2S_Type *base); |
<> | 154:37f96f9d4de2 | 73 | |
<> | 154:37f96f9d4de2 | 74 | /*! |
<> | 154:37f96f9d4de2 | 75 | * @brief sends a piece of data in non-blocking way. |
<> | 154:37f96f9d4de2 | 76 | * |
<> | 154:37f96f9d4de2 | 77 | * @param base SAI base pointer |
<> | 154:37f96f9d4de2 | 78 | * @param channel Data channel used. |
<> | 154:37f96f9d4de2 | 79 | * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits. |
<> | 154:37f96f9d4de2 | 80 | * @param buffer Pointer to the data to be written. |
<> | 154:37f96f9d4de2 | 81 | * @param size Bytes to be written. |
<> | 154:37f96f9d4de2 | 82 | */ |
<> | 154:37f96f9d4de2 | 83 | static void SAI_WriteNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size); |
<> | 154:37f96f9d4de2 | 84 | |
<> | 154:37f96f9d4de2 | 85 | /*! |
<> | 154:37f96f9d4de2 | 86 | * @brief Receive a piece of data in non-blocking way. |
<> | 154:37f96f9d4de2 | 87 | * |
<> | 154:37f96f9d4de2 | 88 | * @param base SAI base pointer |
<> | 154:37f96f9d4de2 | 89 | * @param channel Data channel used. |
<> | 154:37f96f9d4de2 | 90 | * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits. |
<> | 154:37f96f9d4de2 | 91 | * @param buffer Pointer to the data to be read. |
<> | 154:37f96f9d4de2 | 92 | * @param size Bytes to be read. |
<> | 154:37f96f9d4de2 | 93 | */ |
<> | 154:37f96f9d4de2 | 94 | static void SAI_ReadNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size); |
<> | 154:37f96f9d4de2 | 95 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 96 | * Variables |
<> | 154:37f96f9d4de2 | 97 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 98 | /*!@brief SAI handle pointer */ |
<> | 154:37f96f9d4de2 | 99 | sai_handle_t *s_saiHandle[FSL_FEATURE_SOC_I2S_COUNT][2]; |
<> | 154:37f96f9d4de2 | 100 | /* Base pointer array */ |
<> | 154:37f96f9d4de2 | 101 | static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS; |
<> | 154:37f96f9d4de2 | 102 | /* IRQ number array */ |
<> | 154:37f96f9d4de2 | 103 | static const IRQn_Type s_saiTxIRQ[] = I2S_TX_IRQS; |
<> | 154:37f96f9d4de2 | 104 | static const IRQn_Type s_saiRxIRQ[] = I2S_RX_IRQS; |
<> | 154:37f96f9d4de2 | 105 | /* Clock name array */ |
<> | 154:37f96f9d4de2 | 106 | static const clock_ip_name_t s_saiClock[] = SAI_CLOCKS; |
<> | 154:37f96f9d4de2 | 107 | /*! @brief Pointer to tx IRQ handler for each instance. */ |
<> | 154:37f96f9d4de2 | 108 | static sai_tx_isr_t s_saiTxIsr; |
<> | 154:37f96f9d4de2 | 109 | /*! @brief Pointer to tx IRQ handler for each instance. */ |
<> | 154:37f96f9d4de2 | 110 | static sai_rx_isr_t s_saiRxIsr; |
<> | 154:37f96f9d4de2 | 111 | |
<> | 154:37f96f9d4de2 | 112 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 113 | * Code |
<> | 154:37f96f9d4de2 | 114 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 115 | #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) |
<> | 154:37f96f9d4de2 | 116 | static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz) |
<> | 154:37f96f9d4de2 | 117 | { |
<> | 154:37f96f9d4de2 | 118 | uint32_t freq = mclkSrcClock_Hz; |
<> | 154:37f96f9d4de2 | 119 | uint16_t fract, divide; |
<> | 154:37f96f9d4de2 | 120 | uint32_t remaind = 0; |
<> | 154:37f96f9d4de2 | 121 | uint32_t current_remainder = 0xFFFFFFFFU; |
<> | 154:37f96f9d4de2 | 122 | uint16_t current_fract = 0; |
<> | 154:37f96f9d4de2 | 123 | uint16_t current_divide = 0; |
<> | 154:37f96f9d4de2 | 124 | uint32_t mul_freq = 0; |
<> | 154:37f96f9d4de2 | 125 | uint32_t max_fract = 256; |
<> | 154:37f96f9d4de2 | 126 | |
<> | 154:37f96f9d4de2 | 127 | /*In order to prevent overflow */ |
<> | 154:37f96f9d4de2 | 128 | freq /= 100; |
<> | 154:37f96f9d4de2 | 129 | mclk_Hz /= 100; |
<> | 154:37f96f9d4de2 | 130 | |
<> | 154:37f96f9d4de2 | 131 | /* Compute the max fract number */ |
<> | 154:37f96f9d4de2 | 132 | max_fract = mclk_Hz * 4096 / freq + 1; |
<> | 154:37f96f9d4de2 | 133 | if (max_fract > 256) |
<> | 154:37f96f9d4de2 | 134 | { |
<> | 154:37f96f9d4de2 | 135 | max_fract = 256; |
<> | 154:37f96f9d4de2 | 136 | } |
<> | 154:37f96f9d4de2 | 137 | |
<> | 154:37f96f9d4de2 | 138 | /* Looking for the closet frequency */ |
<> | 154:37f96f9d4de2 | 139 | for (fract = 1; fract < max_fract; fract++) |
<> | 154:37f96f9d4de2 | 140 | { |
<> | 154:37f96f9d4de2 | 141 | mul_freq = freq * fract; |
<> | 154:37f96f9d4de2 | 142 | remaind = mul_freq % mclk_Hz; |
<> | 154:37f96f9d4de2 | 143 | divide = mul_freq / mclk_Hz; |
<> | 154:37f96f9d4de2 | 144 | |
<> | 154:37f96f9d4de2 | 145 | /* Find the exactly frequency */ |
<> | 154:37f96f9d4de2 | 146 | if (remaind == 0) |
<> | 154:37f96f9d4de2 | 147 | { |
<> | 154:37f96f9d4de2 | 148 | current_fract = fract; |
<> | 154:37f96f9d4de2 | 149 | current_divide = mul_freq / mclk_Hz; |
<> | 154:37f96f9d4de2 | 150 | break; |
<> | 154:37f96f9d4de2 | 151 | } |
<> | 154:37f96f9d4de2 | 152 | |
<> | 154:37f96f9d4de2 | 153 | /* Closer to next one, set the closest to next data */ |
<> | 154:37f96f9d4de2 | 154 | if (remaind > mclk_Hz / 2) |
<> | 154:37f96f9d4de2 | 155 | { |
<> | 154:37f96f9d4de2 | 156 | remaind = mclk_Hz - remaind; |
<> | 154:37f96f9d4de2 | 157 | divide += 1; |
<> | 154:37f96f9d4de2 | 158 | } |
<> | 154:37f96f9d4de2 | 159 | |
<> | 154:37f96f9d4de2 | 160 | /* Update the closest div and fract */ |
<> | 154:37f96f9d4de2 | 161 | if (remaind < current_remainder) |
<> | 154:37f96f9d4de2 | 162 | { |
<> | 154:37f96f9d4de2 | 163 | current_fract = fract; |
<> | 154:37f96f9d4de2 | 164 | current_divide = divide; |
<> | 154:37f96f9d4de2 | 165 | current_remainder = remaind; |
<> | 154:37f96f9d4de2 | 166 | } |
<> | 154:37f96f9d4de2 | 167 | } |
<> | 154:37f96f9d4de2 | 168 | |
<> | 154:37f96f9d4de2 | 169 | /* Fill the computed fract and divider to registers */ |
<> | 154:37f96f9d4de2 | 170 | base->MDR = I2S_MDR_DIVIDE(current_divide - 1) | I2S_MDR_FRACT(current_fract - 1); |
<> | 154:37f96f9d4de2 | 171 | |
<> | 154:37f96f9d4de2 | 172 | /* Waiting for the divider updated */ |
<> | 154:37f96f9d4de2 | 173 | while (base->MCR & I2S_MCR_DUF_MASK) |
<> | 154:37f96f9d4de2 | 174 | { |
<> | 154:37f96f9d4de2 | 175 | } |
<> | 154:37f96f9d4de2 | 176 | } |
<> | 154:37f96f9d4de2 | 177 | #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */ |
<> | 154:37f96f9d4de2 | 178 | |
<> | 154:37f96f9d4de2 | 179 | uint32_t SAI_GetInstance(I2S_Type *base) |
<> | 154:37f96f9d4de2 | 180 | { |
<> | 154:37f96f9d4de2 | 181 | uint32_t instance; |
<> | 154:37f96f9d4de2 | 182 | |
<> | 154:37f96f9d4de2 | 183 | /* Find the instance index from base address mappings. */ |
<> | 154:37f96f9d4de2 | 184 | for (instance = 0; instance < FSL_FEATURE_SOC_I2S_COUNT; instance++) |
<> | 154:37f96f9d4de2 | 185 | { |
<> | 154:37f96f9d4de2 | 186 | if (s_saiBases[instance] == base) |
<> | 154:37f96f9d4de2 | 187 | { |
<> | 154:37f96f9d4de2 | 188 | break; |
<> | 154:37f96f9d4de2 | 189 | } |
<> | 154:37f96f9d4de2 | 190 | } |
<> | 154:37f96f9d4de2 | 191 | |
<> | 154:37f96f9d4de2 | 192 | assert(instance < FSL_FEATURE_SOC_I2S_COUNT); |
<> | 154:37f96f9d4de2 | 193 | |
<> | 154:37f96f9d4de2 | 194 | return instance; |
<> | 154:37f96f9d4de2 | 195 | } |
<> | 154:37f96f9d4de2 | 196 | |
<> | 154:37f96f9d4de2 | 197 | static void SAI_WriteNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size) |
<> | 154:37f96f9d4de2 | 198 | { |
<> | 154:37f96f9d4de2 | 199 | uint32_t i = 0; |
<> | 154:37f96f9d4de2 | 200 | uint8_t j = 0; |
<> | 154:37f96f9d4de2 | 201 | uint8_t bytesPerWord = bitWidth / 8U; |
<> | 154:37f96f9d4de2 | 202 | uint32_t data = 0; |
<> | 154:37f96f9d4de2 | 203 | uint32_t temp = 0; |
<> | 154:37f96f9d4de2 | 204 | |
<> | 154:37f96f9d4de2 | 205 | for (i = 0; i < size / bytesPerWord; i++) |
<> | 154:37f96f9d4de2 | 206 | { |
<> | 154:37f96f9d4de2 | 207 | for (j = 0; j < bytesPerWord; j++) |
<> | 154:37f96f9d4de2 | 208 | { |
<> | 154:37f96f9d4de2 | 209 | temp = (uint32_t)(*buffer); |
<> | 154:37f96f9d4de2 | 210 | data |= (temp << (8U * j)); |
<> | 154:37f96f9d4de2 | 211 | buffer++; |
<> | 154:37f96f9d4de2 | 212 | } |
<> | 154:37f96f9d4de2 | 213 | base->TDR[channel] = data; |
<> | 154:37f96f9d4de2 | 214 | data = 0; |
<> | 154:37f96f9d4de2 | 215 | } |
<> | 154:37f96f9d4de2 | 216 | } |
<> | 154:37f96f9d4de2 | 217 | |
<> | 154:37f96f9d4de2 | 218 | static void SAI_ReadNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size) |
<> | 154:37f96f9d4de2 | 219 | { |
<> | 154:37f96f9d4de2 | 220 | uint32_t i = 0; |
<> | 154:37f96f9d4de2 | 221 | uint8_t j = 0; |
<> | 154:37f96f9d4de2 | 222 | uint8_t bytesPerWord = bitWidth / 8U; |
<> | 154:37f96f9d4de2 | 223 | uint32_t data = 0; |
<> | 154:37f96f9d4de2 | 224 | |
<> | 154:37f96f9d4de2 | 225 | for (i = 0; i < size / bytesPerWord; i++) |
<> | 154:37f96f9d4de2 | 226 | { |
<> | 154:37f96f9d4de2 | 227 | data = base->RDR[channel]; |
<> | 154:37f96f9d4de2 | 228 | for (j = 0; j < bytesPerWord; j++) |
<> | 154:37f96f9d4de2 | 229 | { |
<> | 154:37f96f9d4de2 | 230 | *buffer = (data >> (8U * j)) & 0xFF; |
<> | 154:37f96f9d4de2 | 231 | buffer++; |
<> | 154:37f96f9d4de2 | 232 | } |
<> | 154:37f96f9d4de2 | 233 | } |
<> | 154:37f96f9d4de2 | 234 | } |
<> | 154:37f96f9d4de2 | 235 | |
<> | 154:37f96f9d4de2 | 236 | void SAI_TxInit(I2S_Type *base, const sai_config_t *config) |
<> | 154:37f96f9d4de2 | 237 | { |
<> | 154:37f96f9d4de2 | 238 | uint32_t val = 0; |
<> | 154:37f96f9d4de2 | 239 | |
<> | 154:37f96f9d4de2 | 240 | /* Enable the SAI clock */ |
<> | 154:37f96f9d4de2 | 241 | CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 242 | |
<> | 154:37f96f9d4de2 | 243 | #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) |
<> | 154:37f96f9d4de2 | 244 | /* Master clock source setting */ |
<> | 154:37f96f9d4de2 | 245 | val = (base->MCR & ~I2S_MCR_MICS_MASK); |
<> | 154:37f96f9d4de2 | 246 | base->MCR = (val | I2S_MCR_MICS(config->mclkSource)); |
<> | 154:37f96f9d4de2 | 247 | |
<> | 154:37f96f9d4de2 | 248 | /* Configure Master clock output enable */ |
<> | 154:37f96f9d4de2 | 249 | val = (base->MCR & ~I2S_MCR_MOE_MASK); |
<> | 154:37f96f9d4de2 | 250 | base->MCR = (val | I2S_MCR_MOE(config->mclkOutputEnable)); |
<> | 154:37f96f9d4de2 | 251 | #endif /* FSL_FEATURE_SAI_HAS_MCR */ |
<> | 154:37f96f9d4de2 | 252 | |
<> | 154:37f96f9d4de2 | 253 | /* Configure audio protocol */ |
<> | 154:37f96f9d4de2 | 254 | switch (config->protocol) |
<> | 154:37f96f9d4de2 | 255 | { |
<> | 154:37f96f9d4de2 | 256 | case kSAI_BusLeftJustified: |
<> | 154:37f96f9d4de2 | 257 | base->TCR2 |= I2S_TCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 258 | base->TCR3 &= ~I2S_TCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 259 | base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 260 | break; |
<> | 154:37f96f9d4de2 | 261 | |
<> | 154:37f96f9d4de2 | 262 | case kSAI_BusRightJustified: |
<> | 154:37f96f9d4de2 | 263 | base->TCR2 |= I2S_TCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 264 | base->TCR3 &= ~I2S_TCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 265 | base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 266 | break; |
<> | 154:37f96f9d4de2 | 267 | |
<> | 154:37f96f9d4de2 | 268 | case kSAI_BusI2S: |
<> | 154:37f96f9d4de2 | 269 | base->TCR2 |= I2S_TCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 270 | base->TCR3 &= ~I2S_TCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 271 | base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(1U) | I2S_TCR4_FSP(1U) | I2S_TCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 272 | break; |
<> | 154:37f96f9d4de2 | 273 | |
<> | 154:37f96f9d4de2 | 274 | case kSAI_BusPCMA: |
<> | 154:37f96f9d4de2 | 275 | base->TCR2 &= ~I2S_TCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 276 | base->TCR3 &= ~I2S_TCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 277 | base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(0U) | I2S_TCR4_FSE(1U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 278 | break; |
<> | 154:37f96f9d4de2 | 279 | |
<> | 154:37f96f9d4de2 | 280 | case kSAI_BusPCMB: |
<> | 154:37f96f9d4de2 | 281 | base->TCR2 &= ~I2S_TCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 282 | base->TCR3 &= ~I2S_TCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 283 | base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(0U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 284 | break; |
<> | 154:37f96f9d4de2 | 285 | |
<> | 154:37f96f9d4de2 | 286 | default: |
<> | 154:37f96f9d4de2 | 287 | break; |
<> | 154:37f96f9d4de2 | 288 | } |
<> | 154:37f96f9d4de2 | 289 | |
<> | 154:37f96f9d4de2 | 290 | /* Set master or slave */ |
<> | 154:37f96f9d4de2 | 291 | if (config->masterSlave == kSAI_Master) |
<> | 154:37f96f9d4de2 | 292 | { |
<> | 154:37f96f9d4de2 | 293 | base->TCR2 |= I2S_TCR2_BCD_MASK; |
<> | 154:37f96f9d4de2 | 294 | base->TCR4 |= I2S_TCR4_FSD_MASK; |
<> | 154:37f96f9d4de2 | 295 | |
<> | 154:37f96f9d4de2 | 296 | /* Bit clock source setting */ |
<> | 154:37f96f9d4de2 | 297 | val = base->TCR2 & (~I2S_TCR2_MSEL_MASK); |
<> | 154:37f96f9d4de2 | 298 | base->TCR2 = (val | I2S_TCR2_MSEL(config->bclkSource)); |
<> | 154:37f96f9d4de2 | 299 | } |
<> | 154:37f96f9d4de2 | 300 | else |
<> | 154:37f96f9d4de2 | 301 | { |
<> | 154:37f96f9d4de2 | 302 | base->TCR2 &= ~I2S_TCR2_BCD_MASK; |
<> | 154:37f96f9d4de2 | 303 | base->TCR4 &= ~I2S_TCR4_FSD_MASK; |
<> | 154:37f96f9d4de2 | 304 | } |
<> | 154:37f96f9d4de2 | 305 | |
<> | 154:37f96f9d4de2 | 306 | /* Set Sync mode */ |
<> | 154:37f96f9d4de2 | 307 | switch (config->syncMode) |
<> | 154:37f96f9d4de2 | 308 | { |
<> | 154:37f96f9d4de2 | 309 | case kSAI_ModeAsync: |
<> | 154:37f96f9d4de2 | 310 | val = base->TCR2; |
<> | 154:37f96f9d4de2 | 311 | val &= ~I2S_TCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 312 | base->TCR2 = (val | I2S_TCR2_SYNC(0U)); |
<> | 154:37f96f9d4de2 | 313 | break; |
<> | 154:37f96f9d4de2 | 314 | case kSAI_ModeSync: |
<> | 154:37f96f9d4de2 | 315 | val = base->TCR2; |
<> | 154:37f96f9d4de2 | 316 | val &= ~I2S_TCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 317 | base->TCR2 = (val | I2S_TCR2_SYNC(1U)); |
<> | 154:37f96f9d4de2 | 318 | /* If sync with Rx, should set Rx to async mode */ |
<> | 154:37f96f9d4de2 | 319 | val = base->RCR2; |
<> | 154:37f96f9d4de2 | 320 | val &= ~I2S_RCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 321 | base->RCR2 = (val | I2S_RCR2_SYNC(0U)); |
<> | 154:37f96f9d4de2 | 322 | break; |
<> | 154:37f96f9d4de2 | 323 | case kSAI_ModeSyncWithOtherTx: |
<> | 154:37f96f9d4de2 | 324 | val = base->TCR2; |
<> | 154:37f96f9d4de2 | 325 | val &= ~I2S_TCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 326 | base->TCR2 = (val | I2S_TCR2_SYNC(2U)); |
<> | 154:37f96f9d4de2 | 327 | break; |
<> | 154:37f96f9d4de2 | 328 | case kSAI_ModeSyncWithOtherRx: |
<> | 154:37f96f9d4de2 | 329 | val = base->TCR2; |
<> | 154:37f96f9d4de2 | 330 | val &= ~I2S_TCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 331 | base->TCR2 = (val | I2S_TCR2_SYNC(3U)); |
<> | 154:37f96f9d4de2 | 332 | break; |
<> | 154:37f96f9d4de2 | 333 | default: |
<> | 154:37f96f9d4de2 | 334 | break; |
<> | 154:37f96f9d4de2 | 335 | } |
<> | 154:37f96f9d4de2 | 336 | } |
<> | 154:37f96f9d4de2 | 337 | |
<> | 154:37f96f9d4de2 | 338 | void SAI_RxInit(I2S_Type *base, const sai_config_t *config) |
<> | 154:37f96f9d4de2 | 339 | { |
<> | 154:37f96f9d4de2 | 340 | uint32_t val = 0; |
<> | 154:37f96f9d4de2 | 341 | |
<> | 154:37f96f9d4de2 | 342 | /* Enable SAI clock first. */ |
<> | 154:37f96f9d4de2 | 343 | CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 344 | |
<> | 154:37f96f9d4de2 | 345 | #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) |
<> | 154:37f96f9d4de2 | 346 | /* Master clock source setting */ |
<> | 154:37f96f9d4de2 | 347 | val = (base->MCR & ~I2S_MCR_MICS_MASK); |
<> | 154:37f96f9d4de2 | 348 | base->MCR = (val | I2S_MCR_MICS(config->mclkSource)); |
<> | 154:37f96f9d4de2 | 349 | |
<> | 154:37f96f9d4de2 | 350 | /* Configure Master clock output enable */ |
<> | 154:37f96f9d4de2 | 351 | val = (base->MCR & ~I2S_MCR_MOE_MASK); |
<> | 154:37f96f9d4de2 | 352 | base->MCR = (val | I2S_MCR_MOE(config->mclkOutputEnable)); |
<> | 154:37f96f9d4de2 | 353 | #endif /* FSL_FEATURE_SAI_HAS_MCR */ |
<> | 154:37f96f9d4de2 | 354 | |
<> | 154:37f96f9d4de2 | 355 | /* Configure audio protocol */ |
<> | 154:37f96f9d4de2 | 356 | switch (config->protocol) |
<> | 154:37f96f9d4de2 | 357 | { |
<> | 154:37f96f9d4de2 | 358 | case kSAI_BusLeftJustified: |
<> | 154:37f96f9d4de2 | 359 | base->RCR2 |= I2S_RCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 360 | base->RCR3 &= ~I2S_RCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 361 | base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 362 | break; |
<> | 154:37f96f9d4de2 | 363 | |
<> | 154:37f96f9d4de2 | 364 | case kSAI_BusRightJustified: |
<> | 154:37f96f9d4de2 | 365 | base->RCR2 |= I2S_RCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 366 | base->RCR3 &= ~I2S_RCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 367 | base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 368 | break; |
<> | 154:37f96f9d4de2 | 369 | |
<> | 154:37f96f9d4de2 | 370 | case kSAI_BusI2S: |
<> | 154:37f96f9d4de2 | 371 | base->RCR2 |= I2S_RCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 372 | base->RCR3 &= ~I2S_RCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 373 | base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(1U) | I2S_RCR4_FSP(1U) | I2S_RCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 374 | break; |
<> | 154:37f96f9d4de2 | 375 | |
<> | 154:37f96f9d4de2 | 376 | case kSAI_BusPCMA: |
<> | 154:37f96f9d4de2 | 377 | base->RCR2 &= ~I2S_RCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 378 | base->RCR3 &= ~I2S_RCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 379 | base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(0U) | I2S_RCR4_FSE(1U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 380 | break; |
<> | 154:37f96f9d4de2 | 381 | |
<> | 154:37f96f9d4de2 | 382 | case kSAI_BusPCMB: |
<> | 154:37f96f9d4de2 | 383 | base->RCR2 &= ~I2S_RCR2_BCP_MASK; |
<> | 154:37f96f9d4de2 | 384 | base->RCR3 &= ~I2S_RCR3_WDFL_MASK; |
<> | 154:37f96f9d4de2 | 385 | base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(0U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U); |
<> | 154:37f96f9d4de2 | 386 | break; |
<> | 154:37f96f9d4de2 | 387 | |
<> | 154:37f96f9d4de2 | 388 | default: |
<> | 154:37f96f9d4de2 | 389 | break; |
<> | 154:37f96f9d4de2 | 390 | } |
<> | 154:37f96f9d4de2 | 391 | |
<> | 154:37f96f9d4de2 | 392 | /* Set master or slave */ |
<> | 154:37f96f9d4de2 | 393 | if (config->masterSlave == kSAI_Master) |
<> | 154:37f96f9d4de2 | 394 | { |
<> | 154:37f96f9d4de2 | 395 | base->RCR2 |= I2S_RCR2_BCD_MASK; |
<> | 154:37f96f9d4de2 | 396 | base->RCR4 |= I2S_RCR4_FSD_MASK; |
<> | 154:37f96f9d4de2 | 397 | |
<> | 154:37f96f9d4de2 | 398 | /* Bit clock source setting */ |
<> | 154:37f96f9d4de2 | 399 | val = base->RCR2 & (~I2S_RCR2_MSEL_MASK); |
<> | 154:37f96f9d4de2 | 400 | base->RCR2 = (val | I2S_RCR2_MSEL(config->bclkSource)); |
<> | 154:37f96f9d4de2 | 401 | } |
<> | 154:37f96f9d4de2 | 402 | else |
<> | 154:37f96f9d4de2 | 403 | { |
<> | 154:37f96f9d4de2 | 404 | base->RCR2 &= ~I2S_RCR2_BCD_MASK; |
<> | 154:37f96f9d4de2 | 405 | base->RCR4 &= ~I2S_RCR4_FSD_MASK; |
<> | 154:37f96f9d4de2 | 406 | } |
<> | 154:37f96f9d4de2 | 407 | |
<> | 154:37f96f9d4de2 | 408 | /* Set Sync mode */ |
<> | 154:37f96f9d4de2 | 409 | switch (config->syncMode) |
<> | 154:37f96f9d4de2 | 410 | { |
<> | 154:37f96f9d4de2 | 411 | case kSAI_ModeAsync: |
<> | 154:37f96f9d4de2 | 412 | val = base->RCR2; |
<> | 154:37f96f9d4de2 | 413 | val &= ~I2S_RCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 414 | base->RCR2 = (val | I2S_RCR2_SYNC(0U)); |
<> | 154:37f96f9d4de2 | 415 | break; |
<> | 154:37f96f9d4de2 | 416 | case kSAI_ModeSync: |
<> | 154:37f96f9d4de2 | 417 | val = base->RCR2; |
<> | 154:37f96f9d4de2 | 418 | val &= ~I2S_RCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 419 | base->RCR2 = (val | I2S_RCR2_SYNC(1U)); |
<> | 154:37f96f9d4de2 | 420 | /* If sync with Tx, should set Tx to async mode */ |
<> | 154:37f96f9d4de2 | 421 | val = base->TCR2; |
<> | 154:37f96f9d4de2 | 422 | val &= ~I2S_TCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 423 | base->TCR2 = (val | I2S_TCR2_SYNC(0U)); |
<> | 154:37f96f9d4de2 | 424 | break; |
<> | 154:37f96f9d4de2 | 425 | case kSAI_ModeSyncWithOtherTx: |
<> | 154:37f96f9d4de2 | 426 | val = base->RCR2; |
<> | 154:37f96f9d4de2 | 427 | val &= ~I2S_RCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 428 | base->RCR2 = (val | I2S_RCR2_SYNC(2U)); |
<> | 154:37f96f9d4de2 | 429 | break; |
<> | 154:37f96f9d4de2 | 430 | case kSAI_ModeSyncWithOtherRx: |
<> | 154:37f96f9d4de2 | 431 | val = base->RCR2; |
<> | 154:37f96f9d4de2 | 432 | val &= ~I2S_RCR2_SYNC_MASK; |
<> | 154:37f96f9d4de2 | 433 | base->RCR2 = (val | I2S_RCR2_SYNC(3U)); |
<> | 154:37f96f9d4de2 | 434 | break; |
<> | 154:37f96f9d4de2 | 435 | default: |
<> | 154:37f96f9d4de2 | 436 | break; |
<> | 154:37f96f9d4de2 | 437 | } |
<> | 154:37f96f9d4de2 | 438 | } |
<> | 154:37f96f9d4de2 | 439 | |
<> | 154:37f96f9d4de2 | 440 | void SAI_Deinit(I2S_Type *base) |
<> | 154:37f96f9d4de2 | 441 | { |
<> | 154:37f96f9d4de2 | 442 | SAI_TxEnable(base, false); |
<> | 154:37f96f9d4de2 | 443 | SAI_RxEnable(base, false); |
<> | 154:37f96f9d4de2 | 444 | CLOCK_DisableClock(s_saiClock[SAI_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 445 | } |
<> | 154:37f96f9d4de2 | 446 | |
<> | 154:37f96f9d4de2 | 447 | void SAI_TxGetDefaultConfig(sai_config_t *config) |
<> | 154:37f96f9d4de2 | 448 | { |
<> | 154:37f96f9d4de2 | 449 | config->bclkSource = kSAI_BclkSourceMclkDiv; |
<> | 154:37f96f9d4de2 | 450 | config->masterSlave = kSAI_Master; |
<> | 154:37f96f9d4de2 | 451 | config->mclkSource = kSAI_MclkSourceSysclk; |
<> | 154:37f96f9d4de2 | 452 | config->protocol = kSAI_BusLeftJustified; |
<> | 154:37f96f9d4de2 | 453 | config->syncMode = kSAI_ModeAsync; |
<> | 154:37f96f9d4de2 | 454 | #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) |
<> | 154:37f96f9d4de2 | 455 | config->mclkOutputEnable = true; |
<> | 154:37f96f9d4de2 | 456 | #endif /* FSL_FEATURE_SAI_HAS_MCR */ |
<> | 154:37f96f9d4de2 | 457 | } |
<> | 154:37f96f9d4de2 | 458 | |
<> | 154:37f96f9d4de2 | 459 | void SAI_RxGetDefaultConfig(sai_config_t *config) |
<> | 154:37f96f9d4de2 | 460 | { |
<> | 154:37f96f9d4de2 | 461 | config->bclkSource = kSAI_BclkSourceMclkDiv; |
<> | 154:37f96f9d4de2 | 462 | config->masterSlave = kSAI_Master; |
<> | 154:37f96f9d4de2 | 463 | config->mclkSource = kSAI_MclkSourceSysclk; |
<> | 154:37f96f9d4de2 | 464 | config->protocol = kSAI_BusLeftJustified; |
<> | 154:37f96f9d4de2 | 465 | config->syncMode = kSAI_ModeSync; |
<> | 154:37f96f9d4de2 | 466 | #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR) |
<> | 154:37f96f9d4de2 | 467 | config->mclkOutputEnable = true; |
<> | 154:37f96f9d4de2 | 468 | #endif /* FSL_FEATURE_SAI_HAS_MCR */ |
<> | 154:37f96f9d4de2 | 469 | } |
<> | 154:37f96f9d4de2 | 470 | |
<> | 154:37f96f9d4de2 | 471 | void SAI_TxReset(I2S_Type *base) |
<> | 154:37f96f9d4de2 | 472 | { |
<> | 154:37f96f9d4de2 | 473 | /* Set the software reset and FIFO reset to clear internal state */ |
<> | 154:37f96f9d4de2 | 474 | base->TCSR = I2S_TCSR_SR_MASK | I2S_TCSR_FR_MASK; |
<> | 154:37f96f9d4de2 | 475 | |
<> | 154:37f96f9d4de2 | 476 | /* Clear software reset bit, this should be done by software */ |
<> | 154:37f96f9d4de2 | 477 | base->TCSR &= ~I2S_TCSR_SR_MASK; |
<> | 154:37f96f9d4de2 | 478 | |
<> | 154:37f96f9d4de2 | 479 | /* Reset all Tx register values */ |
<> | 154:37f96f9d4de2 | 480 | base->TCR2 = 0; |
<> | 154:37f96f9d4de2 | 481 | base->TCR3 = 0; |
<> | 154:37f96f9d4de2 | 482 | base->TCR4 = 0; |
<> | 154:37f96f9d4de2 | 483 | base->TCR5 = 0; |
<> | 154:37f96f9d4de2 | 484 | base->TMR = 0; |
<> | 154:37f96f9d4de2 | 485 | } |
<> | 154:37f96f9d4de2 | 486 | |
<> | 154:37f96f9d4de2 | 487 | void SAI_RxReset(I2S_Type *base) |
<> | 154:37f96f9d4de2 | 488 | { |
<> | 154:37f96f9d4de2 | 489 | /* Set the software reset and FIFO reset to clear internal state */ |
<> | 154:37f96f9d4de2 | 490 | base->RCSR = I2S_RCSR_SR_MASK | I2S_RCSR_FR_MASK; |
<> | 154:37f96f9d4de2 | 491 | |
<> | 154:37f96f9d4de2 | 492 | /* Clear software reset bit, this should be done by software */ |
<> | 154:37f96f9d4de2 | 493 | base->RCSR &= ~I2S_RCSR_SR_MASK; |
<> | 154:37f96f9d4de2 | 494 | |
<> | 154:37f96f9d4de2 | 495 | /* Reset all Rx register values */ |
<> | 154:37f96f9d4de2 | 496 | base->RCR2 = 0; |
<> | 154:37f96f9d4de2 | 497 | base->RCR3 = 0; |
<> | 154:37f96f9d4de2 | 498 | base->RCR4 = 0; |
<> | 154:37f96f9d4de2 | 499 | base->RCR5 = 0; |
<> | 154:37f96f9d4de2 | 500 | base->RMR = 0; |
<> | 154:37f96f9d4de2 | 501 | } |
<> | 154:37f96f9d4de2 | 502 | |
<> | 154:37f96f9d4de2 | 503 | void SAI_TxEnable(I2S_Type *base, bool enable) |
<> | 154:37f96f9d4de2 | 504 | { |
<> | 154:37f96f9d4de2 | 505 | if (enable) |
<> | 154:37f96f9d4de2 | 506 | { |
<> | 154:37f96f9d4de2 | 507 | /* If clock is sync with Rx, should enable RE bit. */ |
<> | 154:37f96f9d4de2 | 508 | if (((base->TCR2 & I2S_TCR2_SYNC_MASK) >> I2S_TCR2_SYNC_SHIFT) == 0x1U) |
<> | 154:37f96f9d4de2 | 509 | { |
<> | 154:37f96f9d4de2 | 510 | base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK); |
<> | 154:37f96f9d4de2 | 511 | } |
<> | 154:37f96f9d4de2 | 512 | base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK); |
<> | 154:37f96f9d4de2 | 513 | } |
<> | 154:37f96f9d4de2 | 514 | else |
<> | 154:37f96f9d4de2 | 515 | { |
<> | 154:37f96f9d4de2 | 516 | /* Should not close RE even sync with Rx */ |
<> | 154:37f96f9d4de2 | 517 | base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~I2S_TCSR_TE_MASK)); |
<> | 154:37f96f9d4de2 | 518 | } |
<> | 154:37f96f9d4de2 | 519 | } |
<> | 154:37f96f9d4de2 | 520 | |
<> | 154:37f96f9d4de2 | 521 | void SAI_RxEnable(I2S_Type *base, bool enable) |
<> | 154:37f96f9d4de2 | 522 | { |
<> | 154:37f96f9d4de2 | 523 | if (enable) |
<> | 154:37f96f9d4de2 | 524 | { |
<> | 154:37f96f9d4de2 | 525 | /* If clock is sync with Tx, should enable TE bit. */ |
<> | 154:37f96f9d4de2 | 526 | if (((base->RCR2 & I2S_RCR2_SYNC_MASK) >> I2S_RCR2_SYNC_SHIFT) == 0x1U) |
<> | 154:37f96f9d4de2 | 527 | { |
<> | 154:37f96f9d4de2 | 528 | base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK); |
<> | 154:37f96f9d4de2 | 529 | } |
<> | 154:37f96f9d4de2 | 530 | base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK); |
<> | 154:37f96f9d4de2 | 531 | } |
<> | 154:37f96f9d4de2 | 532 | else |
<> | 154:37f96f9d4de2 | 533 | { |
<> | 154:37f96f9d4de2 | 534 | base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~I2S_RCSR_RE_MASK)); |
<> | 154:37f96f9d4de2 | 535 | } |
<> | 154:37f96f9d4de2 | 536 | } |
<> | 154:37f96f9d4de2 | 537 | |
<> | 154:37f96f9d4de2 | 538 | void SAI_TxSetFormat(I2S_Type *base, |
<> | 154:37f96f9d4de2 | 539 | sai_transfer_format_t *format, |
<> | 154:37f96f9d4de2 | 540 | uint32_t mclkSourceClockHz, |
<> | 154:37f96f9d4de2 | 541 | uint32_t bclkSourceClockHz) |
<> | 154:37f96f9d4de2 | 542 | { |
<> | 154:37f96f9d4de2 | 543 | uint32_t bclk = format->sampleRate_Hz * 32U * 2U; |
<> | 154:37f96f9d4de2 | 544 | |
<> | 154:37f96f9d4de2 | 545 | /* Compute the mclk */ |
<> | 154:37f96f9d4de2 | 546 | #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) |
<> | 154:37f96f9d4de2 | 547 | /* Check if master clock divider enabled, then set master clock divider */ |
<> | 154:37f96f9d4de2 | 548 | if (base->MCR & I2S_MCR_MOE_MASK) |
<> | 154:37f96f9d4de2 | 549 | { |
<> | 154:37f96f9d4de2 | 550 | SAI_SetMasterClockDivider(base, format->masterClockHz, mclkSourceClockHz); |
<> | 154:37f96f9d4de2 | 551 | } |
<> | 154:37f96f9d4de2 | 552 | #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */ |
<> | 154:37f96f9d4de2 | 553 | |
<> | 154:37f96f9d4de2 | 554 | /* Set bclk if needed */ |
<> | 154:37f96f9d4de2 | 555 | if (base->TCR2 & I2S_TCR2_BCD_MASK) |
<> | 154:37f96f9d4de2 | 556 | { |
<> | 154:37f96f9d4de2 | 557 | base->TCR2 &= ~I2S_TCR2_DIV_MASK; |
<> | 154:37f96f9d4de2 | 558 | base->TCR2 |= I2S_TCR2_DIV((bclkSourceClockHz / bclk) / 2U - 1U); |
<> | 154:37f96f9d4de2 | 559 | } |
<> | 154:37f96f9d4de2 | 560 | |
<> | 154:37f96f9d4de2 | 561 | /* Set bitWidth */ |
<> | 154:37f96f9d4de2 | 562 | if (format->protocol == kSAI_BusRightJustified) |
<> | 154:37f96f9d4de2 | 563 | { |
<> | 154:37f96f9d4de2 | 564 | base->TCR5 = I2S_TCR5_WNW(31U) | I2S_TCR5_W0W(31U) | I2S_TCR5_FBT(31U); |
<> | 154:37f96f9d4de2 | 565 | } |
<> | 154:37f96f9d4de2 | 566 | else |
<> | 154:37f96f9d4de2 | 567 | { |
<> | 154:37f96f9d4de2 | 568 | base->TCR5 = I2S_TCR5_WNW(31U) | I2S_TCR5_W0W(31U) | I2S_TCR5_FBT(format->bitWidth - 1); |
<> | 154:37f96f9d4de2 | 569 | } |
<> | 154:37f96f9d4de2 | 570 | |
<> | 154:37f96f9d4de2 | 571 | /* Set mono or stereo */ |
<> | 154:37f96f9d4de2 | 572 | base->TMR = (uint32_t)format->stereo; |
<> | 154:37f96f9d4de2 | 573 | |
<> | 154:37f96f9d4de2 | 574 | /* Set data channel */ |
<> | 154:37f96f9d4de2 | 575 | base->TCR3 &= ~I2S_TCR3_TCE_MASK; |
<> | 154:37f96f9d4de2 | 576 | base->TCR3 |= I2S_TCR3_TCE(1U << format->channel); |
<> | 154:37f96f9d4de2 | 577 | |
<> | 154:37f96f9d4de2 | 578 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 579 | /* Set watermark */ |
<> | 154:37f96f9d4de2 | 580 | base->TCR1 = format->watermark; |
<> | 154:37f96f9d4de2 | 581 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 582 | } |
<> | 154:37f96f9d4de2 | 583 | |
<> | 154:37f96f9d4de2 | 584 | void SAI_RxSetFormat(I2S_Type *base, |
<> | 154:37f96f9d4de2 | 585 | sai_transfer_format_t *format, |
<> | 154:37f96f9d4de2 | 586 | uint32_t mclkSourceClockHz, |
<> | 154:37f96f9d4de2 | 587 | uint32_t bclkSourceClockHz) |
<> | 154:37f96f9d4de2 | 588 | { |
<> | 154:37f96f9d4de2 | 589 | uint32_t bclk = format->sampleRate_Hz * 32U * 2U; |
<> | 154:37f96f9d4de2 | 590 | |
<> | 154:37f96f9d4de2 | 591 | /* Compute the mclk */ |
<> | 154:37f96f9d4de2 | 592 | #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) |
<> | 154:37f96f9d4de2 | 593 | /* Check if master clock divider enabled */ |
<> | 154:37f96f9d4de2 | 594 | if (base->MCR & I2S_MCR_MOE_MASK) |
<> | 154:37f96f9d4de2 | 595 | { |
<> | 154:37f96f9d4de2 | 596 | SAI_SetMasterClockDivider(base, format->masterClockHz, mclkSourceClockHz); |
<> | 154:37f96f9d4de2 | 597 | } |
<> | 154:37f96f9d4de2 | 598 | #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */ |
<> | 154:37f96f9d4de2 | 599 | |
<> | 154:37f96f9d4de2 | 600 | /* Set bclk if needed */ |
<> | 154:37f96f9d4de2 | 601 | if (base->RCR2 & I2S_RCR2_BCD_MASK) |
<> | 154:37f96f9d4de2 | 602 | { |
<> | 154:37f96f9d4de2 | 603 | base->RCR2 &= ~I2S_RCR2_DIV_MASK; |
<> | 154:37f96f9d4de2 | 604 | base->RCR2 |= I2S_RCR2_DIV((bclkSourceClockHz / bclk) / 2U - 1U); |
<> | 154:37f96f9d4de2 | 605 | } |
<> | 154:37f96f9d4de2 | 606 | |
<> | 154:37f96f9d4de2 | 607 | /* Set bitWidth */ |
<> | 154:37f96f9d4de2 | 608 | if (format->protocol == kSAI_BusRightJustified) |
<> | 154:37f96f9d4de2 | 609 | { |
<> | 154:37f96f9d4de2 | 610 | base->RCR5 = I2S_RCR5_WNW(31U) | I2S_RCR5_W0W(31U) | I2S_RCR5_FBT(31U); |
<> | 154:37f96f9d4de2 | 611 | } |
<> | 154:37f96f9d4de2 | 612 | else |
<> | 154:37f96f9d4de2 | 613 | { |
<> | 154:37f96f9d4de2 | 614 | base->RCR5 = I2S_RCR5_WNW(31U) | I2S_RCR5_W0W(31U) | I2S_RCR5_FBT(format->bitWidth - 1); |
<> | 154:37f96f9d4de2 | 615 | } |
<> | 154:37f96f9d4de2 | 616 | |
<> | 154:37f96f9d4de2 | 617 | /* Set mono or stereo */ |
<> | 154:37f96f9d4de2 | 618 | base->RMR = (uint32_t)format->stereo; |
<> | 154:37f96f9d4de2 | 619 | |
<> | 154:37f96f9d4de2 | 620 | /* Set data channel */ |
<> | 154:37f96f9d4de2 | 621 | base->RCR3 &= ~I2S_RCR3_RCE_MASK; |
<> | 154:37f96f9d4de2 | 622 | base->RCR3 |= I2S_RCR3_RCE(1U << format->channel); |
<> | 154:37f96f9d4de2 | 623 | |
<> | 154:37f96f9d4de2 | 624 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 625 | /* Set watermark */ |
<> | 154:37f96f9d4de2 | 626 | base->RCR1 = format->watermark; |
<> | 154:37f96f9d4de2 | 627 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 628 | } |
<> | 154:37f96f9d4de2 | 629 | |
<> | 154:37f96f9d4de2 | 630 | void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size) |
<> | 154:37f96f9d4de2 | 631 | { |
<> | 154:37f96f9d4de2 | 632 | uint32_t i = 0; |
<> | 154:37f96f9d4de2 | 633 | uint8_t bytesPerWord = bitWidth / 8U; |
<> | 154:37f96f9d4de2 | 634 | |
<> | 154:37f96f9d4de2 | 635 | for (i = 0; i < size; i++) |
<> | 154:37f96f9d4de2 | 636 | { |
<> | 154:37f96f9d4de2 | 637 | /* Wait until it can write data */ |
<> | 154:37f96f9d4de2 | 638 | while (!(base->TCSR & I2S_TCSR_FWF_MASK)) |
<> | 154:37f96f9d4de2 | 639 | { |
<> | 154:37f96f9d4de2 | 640 | } |
<> | 154:37f96f9d4de2 | 641 | |
<> | 154:37f96f9d4de2 | 642 | SAI_WriteNonBlocking(base, channel, bitWidth, buffer, bytesPerWord); |
<> | 154:37f96f9d4de2 | 643 | buffer += bytesPerWord; |
<> | 154:37f96f9d4de2 | 644 | } |
<> | 154:37f96f9d4de2 | 645 | |
<> | 154:37f96f9d4de2 | 646 | /* Wait until the last data is sent */ |
<> | 154:37f96f9d4de2 | 647 | while (!(base->TCSR & I2S_TCSR_FWF_MASK)) |
<> | 154:37f96f9d4de2 | 648 | { |
<> | 154:37f96f9d4de2 | 649 | } |
<> | 154:37f96f9d4de2 | 650 | } |
<> | 154:37f96f9d4de2 | 651 | |
<> | 154:37f96f9d4de2 | 652 | void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size) |
<> | 154:37f96f9d4de2 | 653 | { |
<> | 154:37f96f9d4de2 | 654 | uint32_t i = 0; |
<> | 154:37f96f9d4de2 | 655 | uint8_t bytesPerWord = bitWidth / 8U; |
<> | 154:37f96f9d4de2 | 656 | |
<> | 154:37f96f9d4de2 | 657 | for (i = 0; i < size; i++) |
<> | 154:37f96f9d4de2 | 658 | { |
<> | 154:37f96f9d4de2 | 659 | /* Wait until data is received */ |
<> | 154:37f96f9d4de2 | 660 | while (!(base->RCSR & I2S_RCSR_FWF_MASK)) |
<> | 154:37f96f9d4de2 | 661 | { |
<> | 154:37f96f9d4de2 | 662 | } |
<> | 154:37f96f9d4de2 | 663 | |
<> | 154:37f96f9d4de2 | 664 | SAI_ReadNonBlocking(base, channel, bitWidth, buffer, bytesPerWord); |
<> | 154:37f96f9d4de2 | 665 | buffer += bytesPerWord; |
<> | 154:37f96f9d4de2 | 666 | } |
<> | 154:37f96f9d4de2 | 667 | } |
<> | 154:37f96f9d4de2 | 668 | |
<> | 154:37f96f9d4de2 | 669 | void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData) |
<> | 154:37f96f9d4de2 | 670 | { |
<> | 154:37f96f9d4de2 | 671 | assert(handle); |
<> | 154:37f96f9d4de2 | 672 | |
<> | 154:37f96f9d4de2 | 673 | s_saiHandle[SAI_GetInstance(base)][0] = handle; |
<> | 154:37f96f9d4de2 | 674 | |
<> | 154:37f96f9d4de2 | 675 | handle->callback = callback; |
<> | 154:37f96f9d4de2 | 676 | handle->userData = userData; |
<> | 154:37f96f9d4de2 | 677 | |
<> | 154:37f96f9d4de2 | 678 | /* Set the isr pointer */ |
<> | 154:37f96f9d4de2 | 679 | s_saiTxIsr = SAI_TransferTxHandleIRQ; |
<> | 154:37f96f9d4de2 | 680 | |
<> | 154:37f96f9d4de2 | 681 | /* Enable Tx irq */ |
<> | 154:37f96f9d4de2 | 682 | EnableIRQ(s_saiTxIRQ[SAI_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 683 | } |
<> | 154:37f96f9d4de2 | 684 | |
<> | 154:37f96f9d4de2 | 685 | void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData) |
<> | 154:37f96f9d4de2 | 686 | { |
<> | 154:37f96f9d4de2 | 687 | assert(handle); |
<> | 154:37f96f9d4de2 | 688 | |
<> | 154:37f96f9d4de2 | 689 | s_saiHandle[SAI_GetInstance(base)][1] = handle; |
<> | 154:37f96f9d4de2 | 690 | |
<> | 154:37f96f9d4de2 | 691 | handle->callback = callback; |
<> | 154:37f96f9d4de2 | 692 | handle->userData = userData; |
<> | 154:37f96f9d4de2 | 693 | |
<> | 154:37f96f9d4de2 | 694 | /* Set the isr pointer */ |
<> | 154:37f96f9d4de2 | 695 | s_saiRxIsr = SAI_TransferRxHandleIRQ; |
<> | 154:37f96f9d4de2 | 696 | |
<> | 154:37f96f9d4de2 | 697 | /* Enable Rx irq */ |
<> | 154:37f96f9d4de2 | 698 | EnableIRQ(s_saiRxIRQ[SAI_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 699 | } |
<> | 154:37f96f9d4de2 | 700 | |
<> | 154:37f96f9d4de2 | 701 | status_t SAI_TransferTxSetFormat(I2S_Type *base, |
<> | 154:37f96f9d4de2 | 702 | sai_handle_t *handle, |
<> | 154:37f96f9d4de2 | 703 | sai_transfer_format_t *format, |
<> | 154:37f96f9d4de2 | 704 | uint32_t mclkSourceClockHz, |
<> | 154:37f96f9d4de2 | 705 | uint32_t bclkSourceClockHz) |
<> | 154:37f96f9d4de2 | 706 | { |
<> | 154:37f96f9d4de2 | 707 | assert(handle); |
<> | 154:37f96f9d4de2 | 708 | |
<> | 154:37f96f9d4de2 | 709 | if ((mclkSourceClockHz < format->sampleRate_Hz) || (bclkSourceClockHz < format->sampleRate_Hz)) |
<> | 154:37f96f9d4de2 | 710 | { |
<> | 154:37f96f9d4de2 | 711 | return kStatus_InvalidArgument; |
<> | 154:37f96f9d4de2 | 712 | } |
<> | 154:37f96f9d4de2 | 713 | |
<> | 154:37f96f9d4de2 | 714 | /* Copy format to handle */ |
<> | 154:37f96f9d4de2 | 715 | handle->bitWidth = format->bitWidth; |
<> | 154:37f96f9d4de2 | 716 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 717 | handle->watermark = format->watermark; |
<> | 154:37f96f9d4de2 | 718 | #endif |
<> | 154:37f96f9d4de2 | 719 | handle->channel = format->channel; |
<> | 154:37f96f9d4de2 | 720 | |
<> | 154:37f96f9d4de2 | 721 | SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); |
<> | 154:37f96f9d4de2 | 722 | |
<> | 154:37f96f9d4de2 | 723 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 724 | } |
<> | 154:37f96f9d4de2 | 725 | |
<> | 154:37f96f9d4de2 | 726 | status_t SAI_TransferRxSetFormat(I2S_Type *base, |
<> | 154:37f96f9d4de2 | 727 | sai_handle_t *handle, |
<> | 154:37f96f9d4de2 | 728 | sai_transfer_format_t *format, |
<> | 154:37f96f9d4de2 | 729 | uint32_t mclkSourceClockHz, |
<> | 154:37f96f9d4de2 | 730 | uint32_t bclkSourceClockHz) |
<> | 154:37f96f9d4de2 | 731 | { |
<> | 154:37f96f9d4de2 | 732 | assert(handle); |
<> | 154:37f96f9d4de2 | 733 | |
<> | 154:37f96f9d4de2 | 734 | if ((mclkSourceClockHz < format->sampleRate_Hz) || (bclkSourceClockHz < format->sampleRate_Hz)) |
<> | 154:37f96f9d4de2 | 735 | { |
<> | 154:37f96f9d4de2 | 736 | return kStatus_InvalidArgument; |
<> | 154:37f96f9d4de2 | 737 | } |
<> | 154:37f96f9d4de2 | 738 | |
<> | 154:37f96f9d4de2 | 739 | /* Copy format to handle */ |
<> | 154:37f96f9d4de2 | 740 | handle->bitWidth = format->bitWidth; |
<> | 154:37f96f9d4de2 | 741 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 742 | handle->watermark = format->watermark; |
<> | 154:37f96f9d4de2 | 743 | #endif |
<> | 154:37f96f9d4de2 | 744 | handle->channel = format->channel; |
<> | 154:37f96f9d4de2 | 745 | |
<> | 154:37f96f9d4de2 | 746 | SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); |
<> | 154:37f96f9d4de2 | 747 | |
<> | 154:37f96f9d4de2 | 748 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 749 | } |
<> | 154:37f96f9d4de2 | 750 | |
<> | 154:37f96f9d4de2 | 751 | status_t SAI_TransferSendNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer) |
<> | 154:37f96f9d4de2 | 752 | { |
<> | 154:37f96f9d4de2 | 753 | assert(handle); |
<> | 154:37f96f9d4de2 | 754 | |
<> | 154:37f96f9d4de2 | 755 | /* Check if the queue is full */ |
<> | 154:37f96f9d4de2 | 756 | if (handle->saiQueue[handle->queueUser].data) |
<> | 154:37f96f9d4de2 | 757 | { |
<> | 154:37f96f9d4de2 | 758 | return kStatus_SAI_QueueFull; |
<> | 154:37f96f9d4de2 | 759 | } |
<> | 154:37f96f9d4de2 | 760 | |
<> | 154:37f96f9d4de2 | 761 | /* Add into queue */ |
<> | 154:37f96f9d4de2 | 762 | handle->transferSize[handle->queueUser] = xfer->dataSize; |
<> | 154:37f96f9d4de2 | 763 | handle->saiQueue[handle->queueUser].data = xfer->data; |
<> | 154:37f96f9d4de2 | 764 | handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize; |
<> | 154:37f96f9d4de2 | 765 | handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE; |
<> | 154:37f96f9d4de2 | 766 | |
<> | 154:37f96f9d4de2 | 767 | /* Set the state to busy */ |
<> | 154:37f96f9d4de2 | 768 | handle->state = kSAI_Busy; |
<> | 154:37f96f9d4de2 | 769 | |
<> | 154:37f96f9d4de2 | 770 | /* Enable interrupt */ |
<> | 154:37f96f9d4de2 | 771 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 772 | /* Use FIFO request interrupt and fifo error*/ |
<> | 154:37f96f9d4de2 | 773 | SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable); |
<> | 154:37f96f9d4de2 | 774 | #else |
<> | 154:37f96f9d4de2 | 775 | SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable); |
<> | 154:37f96f9d4de2 | 776 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 777 | |
<> | 154:37f96f9d4de2 | 778 | /* Enable Tx transfer */ |
<> | 154:37f96f9d4de2 | 779 | SAI_TxEnable(base, true); |
<> | 154:37f96f9d4de2 | 780 | |
<> | 154:37f96f9d4de2 | 781 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 782 | } |
<> | 154:37f96f9d4de2 | 783 | |
<> | 154:37f96f9d4de2 | 784 | status_t SAI_TransferReceiveNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer) |
<> | 154:37f96f9d4de2 | 785 | { |
<> | 154:37f96f9d4de2 | 786 | assert(handle); |
<> | 154:37f96f9d4de2 | 787 | |
<> | 154:37f96f9d4de2 | 788 | /* Check if the queue is full */ |
<> | 154:37f96f9d4de2 | 789 | if (handle->saiQueue[handle->queueUser].data) |
<> | 154:37f96f9d4de2 | 790 | { |
<> | 154:37f96f9d4de2 | 791 | return kStatus_SAI_QueueFull; |
<> | 154:37f96f9d4de2 | 792 | } |
<> | 154:37f96f9d4de2 | 793 | |
<> | 154:37f96f9d4de2 | 794 | /* Add into queue */ |
<> | 154:37f96f9d4de2 | 795 | handle->transferSize[handle->queueUser] = xfer->dataSize; |
<> | 154:37f96f9d4de2 | 796 | handle->saiQueue[handle->queueUser].data = xfer->data; |
<> | 154:37f96f9d4de2 | 797 | handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize; |
<> | 154:37f96f9d4de2 | 798 | handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE; |
<> | 154:37f96f9d4de2 | 799 | |
<> | 154:37f96f9d4de2 | 800 | /* Set state to busy */ |
<> | 154:37f96f9d4de2 | 801 | handle->state = kSAI_Busy; |
<> | 154:37f96f9d4de2 | 802 | |
<> | 154:37f96f9d4de2 | 803 | /* Enable interrupt */ |
<> | 154:37f96f9d4de2 | 804 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 805 | /* Use FIFO request interrupt and fifo error*/ |
<> | 154:37f96f9d4de2 | 806 | SAI_RxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable); |
<> | 154:37f96f9d4de2 | 807 | #else |
<> | 154:37f96f9d4de2 | 808 | SAI_RxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable); |
<> | 154:37f96f9d4de2 | 809 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 810 | |
<> | 154:37f96f9d4de2 | 811 | /* Enable Rx transfer */ |
<> | 154:37f96f9d4de2 | 812 | SAI_RxEnable(base, true); |
<> | 154:37f96f9d4de2 | 813 | |
<> | 154:37f96f9d4de2 | 814 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 815 | } |
<> | 154:37f96f9d4de2 | 816 | |
<> | 154:37f96f9d4de2 | 817 | status_t SAI_TransferGetSendCount(I2S_Type *base, sai_handle_t *handle, size_t *count) |
<> | 154:37f96f9d4de2 | 818 | { |
<> | 154:37f96f9d4de2 | 819 | assert(handle); |
<> | 154:37f96f9d4de2 | 820 | |
<> | 154:37f96f9d4de2 | 821 | status_t status = kStatus_Success; |
<> | 154:37f96f9d4de2 | 822 | |
<> | 154:37f96f9d4de2 | 823 | if (handle->state != kSAI_Busy) |
<> | 154:37f96f9d4de2 | 824 | { |
<> | 154:37f96f9d4de2 | 825 | status = kStatus_NoTransferInProgress; |
<> | 154:37f96f9d4de2 | 826 | } |
<> | 154:37f96f9d4de2 | 827 | else |
<> | 154:37f96f9d4de2 | 828 | { |
<> | 154:37f96f9d4de2 | 829 | *count = (handle->transferSize[handle->queueDriver] - handle->saiQueue[handle->queueDriver].dataSize); |
<> | 154:37f96f9d4de2 | 830 | } |
<> | 154:37f96f9d4de2 | 831 | |
<> | 154:37f96f9d4de2 | 832 | return status; |
<> | 154:37f96f9d4de2 | 833 | } |
<> | 154:37f96f9d4de2 | 834 | |
<> | 154:37f96f9d4de2 | 835 | status_t SAI_TransferGetReceiveCount(I2S_Type *base, sai_handle_t *handle, size_t *count) |
<> | 154:37f96f9d4de2 | 836 | { |
<> | 154:37f96f9d4de2 | 837 | assert(handle); |
<> | 154:37f96f9d4de2 | 838 | |
<> | 154:37f96f9d4de2 | 839 | status_t status = kStatus_Success; |
<> | 154:37f96f9d4de2 | 840 | |
<> | 154:37f96f9d4de2 | 841 | if (handle->state != kSAI_Busy) |
<> | 154:37f96f9d4de2 | 842 | { |
<> | 154:37f96f9d4de2 | 843 | status = kStatus_NoTransferInProgress; |
<> | 154:37f96f9d4de2 | 844 | } |
<> | 154:37f96f9d4de2 | 845 | else |
<> | 154:37f96f9d4de2 | 846 | { |
<> | 154:37f96f9d4de2 | 847 | *count = (handle->transferSize[handle->queueDriver] - handle->saiQueue[handle->queueDriver].dataSize); |
<> | 154:37f96f9d4de2 | 848 | } |
<> | 154:37f96f9d4de2 | 849 | |
<> | 154:37f96f9d4de2 | 850 | return status; |
<> | 154:37f96f9d4de2 | 851 | } |
<> | 154:37f96f9d4de2 | 852 | |
<> | 154:37f96f9d4de2 | 853 | void SAI_TransferAbortSend(I2S_Type *base, sai_handle_t *handle) |
<> | 154:37f96f9d4de2 | 854 | { |
<> | 154:37f96f9d4de2 | 855 | assert(handle); |
<> | 154:37f96f9d4de2 | 856 | |
<> | 154:37f96f9d4de2 | 857 | /* Stop Tx transfer and disable interrupt */ |
<> | 154:37f96f9d4de2 | 858 | SAI_TxEnable(base, false); |
<> | 154:37f96f9d4de2 | 859 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 860 | /* Use FIFO request interrupt and fifo error */ |
<> | 154:37f96f9d4de2 | 861 | SAI_TxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable); |
<> | 154:37f96f9d4de2 | 862 | #else |
<> | 154:37f96f9d4de2 | 863 | SAI_TxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable); |
<> | 154:37f96f9d4de2 | 864 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 865 | |
<> | 154:37f96f9d4de2 | 866 | handle->state = kSAI_Idle; |
<> | 154:37f96f9d4de2 | 867 | |
<> | 154:37f96f9d4de2 | 868 | /* Clear the queue */ |
<> | 154:37f96f9d4de2 | 869 | memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE); |
<> | 154:37f96f9d4de2 | 870 | handle->queueDriver = 0; |
<> | 154:37f96f9d4de2 | 871 | handle->queueUser = 0; |
<> | 154:37f96f9d4de2 | 872 | } |
<> | 154:37f96f9d4de2 | 873 | |
<> | 154:37f96f9d4de2 | 874 | void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle) |
<> | 154:37f96f9d4de2 | 875 | { |
<> | 154:37f96f9d4de2 | 876 | assert(handle); |
<> | 154:37f96f9d4de2 | 877 | |
<> | 154:37f96f9d4de2 | 878 | /* Stop Tx transfer and disable interrupt */ |
<> | 154:37f96f9d4de2 | 879 | SAI_RxEnable(base, false); |
<> | 154:37f96f9d4de2 | 880 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 881 | /* Use FIFO request interrupt and fifo error */ |
<> | 154:37f96f9d4de2 | 882 | SAI_RxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable); |
<> | 154:37f96f9d4de2 | 883 | #else |
<> | 154:37f96f9d4de2 | 884 | SAI_RxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable); |
<> | 154:37f96f9d4de2 | 885 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 886 | |
<> | 154:37f96f9d4de2 | 887 | handle->state = kSAI_Idle; |
<> | 154:37f96f9d4de2 | 888 | |
<> | 154:37f96f9d4de2 | 889 | /* Clear the queue */ |
<> | 154:37f96f9d4de2 | 890 | memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE); |
<> | 154:37f96f9d4de2 | 891 | handle->queueDriver = 0; |
<> | 154:37f96f9d4de2 | 892 | handle->queueUser = 0; |
<> | 154:37f96f9d4de2 | 893 | } |
<> | 154:37f96f9d4de2 | 894 | |
<> | 154:37f96f9d4de2 | 895 | void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle) |
<> | 154:37f96f9d4de2 | 896 | { |
<> | 154:37f96f9d4de2 | 897 | assert(handle); |
<> | 154:37f96f9d4de2 | 898 | |
<> | 154:37f96f9d4de2 | 899 | uint8_t *buffer = handle->saiQueue[handle->queueDriver].data; |
<> | 154:37f96f9d4de2 | 900 | uint8_t dataSize = handle->bitWidth / 8U; |
<> | 154:37f96f9d4de2 | 901 | |
<> | 154:37f96f9d4de2 | 902 | /* Handle Error */ |
<> | 154:37f96f9d4de2 | 903 | if (base->TCSR & I2S_TCSR_FEF_MASK) |
<> | 154:37f96f9d4de2 | 904 | { |
<> | 154:37f96f9d4de2 | 905 | /* Clear FIFO error flag to continue transfer */ |
<> | 154:37f96f9d4de2 | 906 | SAI_TxClearStatusFlags(base, kSAI_FIFOErrorFlag); |
<> | 154:37f96f9d4de2 | 907 | |
<> | 154:37f96f9d4de2 | 908 | /* Call the callback */ |
<> | 154:37f96f9d4de2 | 909 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 910 | { |
<> | 154:37f96f9d4de2 | 911 | (handle->callback)(base, handle, kStatus_SAI_TxError, handle->userData); |
<> | 154:37f96f9d4de2 | 912 | } |
<> | 154:37f96f9d4de2 | 913 | } |
<> | 154:37f96f9d4de2 | 914 | |
<> | 154:37f96f9d4de2 | 915 | /* Handle transfer */ |
<> | 154:37f96f9d4de2 | 916 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 917 | if (base->TCSR & I2S_TCSR_FRF_MASK) |
<> | 154:37f96f9d4de2 | 918 | { |
<> | 154:37f96f9d4de2 | 919 | /* Judge if the data need to transmit is less than space */ |
<> | 154:37f96f9d4de2 | 920 | uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), |
<> | 154:37f96f9d4de2 | 921 | (size_t)((FSL_FEATURE_SAI_FIFO_COUNT - handle->watermark) * dataSize)); |
<> | 154:37f96f9d4de2 | 922 | |
<> | 154:37f96f9d4de2 | 923 | /* Copy the data from sai buffer to FIFO */ |
<> | 154:37f96f9d4de2 | 924 | SAI_WriteNonBlocking(base, handle->channel, handle->bitWidth, buffer, size); |
<> | 154:37f96f9d4de2 | 925 | |
<> | 154:37f96f9d4de2 | 926 | /* Update the internal counter */ |
<> | 154:37f96f9d4de2 | 927 | handle->saiQueue[handle->queueDriver].dataSize -= size; |
<> | 154:37f96f9d4de2 | 928 | handle->saiQueue[handle->queueDriver].data += size; |
<> | 154:37f96f9d4de2 | 929 | } |
<> | 154:37f96f9d4de2 | 930 | #else |
<> | 154:37f96f9d4de2 | 931 | if (base->TCSR & I2S_TCSR_FWF_MASK) |
<> | 154:37f96f9d4de2 | 932 | { |
<> | 154:37f96f9d4de2 | 933 | uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), dataSize); |
<> | 154:37f96f9d4de2 | 934 | |
<> | 154:37f96f9d4de2 | 935 | SAI_WriteNonBlocking(base, handle->channel, handle->bitWidth, buffer, size); |
<> | 154:37f96f9d4de2 | 936 | |
<> | 154:37f96f9d4de2 | 937 | /* Update internal counter */ |
<> | 154:37f96f9d4de2 | 938 | handle->saiQueue[handle->queueDriver].dataSize -= size; |
<> | 154:37f96f9d4de2 | 939 | handle->saiQueue[handle->queueDriver].data += size; |
<> | 154:37f96f9d4de2 | 940 | } |
<> | 154:37f96f9d4de2 | 941 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 942 | |
<> | 154:37f96f9d4de2 | 943 | /* If finished a blcok, call the callback function */ |
<> | 154:37f96f9d4de2 | 944 | if (handle->saiQueue[handle->queueDriver].dataSize == 0U) |
<> | 154:37f96f9d4de2 | 945 | { |
<> | 154:37f96f9d4de2 | 946 | memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t)); |
<> | 154:37f96f9d4de2 | 947 | handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE; |
<> | 154:37f96f9d4de2 | 948 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 949 | { |
<> | 154:37f96f9d4de2 | 950 | (handle->callback)(base, handle, kStatus_SAI_TxIdle, handle->userData); |
<> | 154:37f96f9d4de2 | 951 | } |
<> | 154:37f96f9d4de2 | 952 | } |
<> | 154:37f96f9d4de2 | 953 | |
<> | 154:37f96f9d4de2 | 954 | /* If all data finished, just stop the transfer */ |
<> | 154:37f96f9d4de2 | 955 | if (handle->saiQueue[handle->queueDriver].data == NULL) |
<> | 154:37f96f9d4de2 | 956 | { |
<> | 154:37f96f9d4de2 | 957 | SAI_TransferAbortSend(base, handle); |
<> | 154:37f96f9d4de2 | 958 | } |
<> | 154:37f96f9d4de2 | 959 | } |
<> | 154:37f96f9d4de2 | 960 | |
<> | 154:37f96f9d4de2 | 961 | void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle) |
<> | 154:37f96f9d4de2 | 962 | { |
<> | 154:37f96f9d4de2 | 963 | assert(handle); |
<> | 154:37f96f9d4de2 | 964 | |
<> | 154:37f96f9d4de2 | 965 | uint8_t *buffer = handle->saiQueue[handle->queueDriver].data; |
<> | 154:37f96f9d4de2 | 966 | uint8_t dataSize = handle->bitWidth / 8U; |
<> | 154:37f96f9d4de2 | 967 | |
<> | 154:37f96f9d4de2 | 968 | /* Handle Error */ |
<> | 154:37f96f9d4de2 | 969 | if (base->RCSR & I2S_RCSR_FEF_MASK) |
<> | 154:37f96f9d4de2 | 970 | { |
<> | 154:37f96f9d4de2 | 971 | /* Clear FIFO error flag to continue transfer */ |
<> | 154:37f96f9d4de2 | 972 | SAI_RxClearStatusFlags(base, kSAI_FIFOErrorFlag); |
<> | 154:37f96f9d4de2 | 973 | |
<> | 154:37f96f9d4de2 | 974 | /* Call the callback */ |
<> | 154:37f96f9d4de2 | 975 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 976 | { |
<> | 154:37f96f9d4de2 | 977 | (handle->callback)(base, handle, kStatus_SAI_RxError, handle->userData); |
<> | 154:37f96f9d4de2 | 978 | } |
<> | 154:37f96f9d4de2 | 979 | } |
<> | 154:37f96f9d4de2 | 980 | |
<> | 154:37f96f9d4de2 | 981 | /* Handle transfer */ |
<> | 154:37f96f9d4de2 | 982 | #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) |
<> | 154:37f96f9d4de2 | 983 | if (base->RCSR & I2S_RCSR_FRF_MASK) |
<> | 154:37f96f9d4de2 | 984 | { |
<> | 154:37f96f9d4de2 | 985 | /* Judge if the data need to transmit is less than space */ |
<> | 154:37f96f9d4de2 | 986 | uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), (handle->watermark * dataSize)); |
<> | 154:37f96f9d4de2 | 987 | |
<> | 154:37f96f9d4de2 | 988 | /* Copy the data from sai buffer to FIFO */ |
<> | 154:37f96f9d4de2 | 989 | SAI_ReadNonBlocking(base, handle->channel, handle->bitWidth, buffer, size); |
<> | 154:37f96f9d4de2 | 990 | |
<> | 154:37f96f9d4de2 | 991 | /* Update the internal counter */ |
<> | 154:37f96f9d4de2 | 992 | handle->saiQueue[handle->queueDriver].dataSize -= size; |
<> | 154:37f96f9d4de2 | 993 | handle->saiQueue[handle->queueDriver].data += size; |
<> | 154:37f96f9d4de2 | 994 | } |
<> | 154:37f96f9d4de2 | 995 | #else |
<> | 154:37f96f9d4de2 | 996 | if (base->RCSR & I2S_RCSR_FWF_MASK) |
<> | 154:37f96f9d4de2 | 997 | { |
<> | 154:37f96f9d4de2 | 998 | uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), dataSize); |
<> | 154:37f96f9d4de2 | 999 | |
<> | 154:37f96f9d4de2 | 1000 | SAI_ReadNonBlocking(base, handle->channel, handle->bitWidth, buffer, size); |
<> | 154:37f96f9d4de2 | 1001 | |
<> | 154:37f96f9d4de2 | 1002 | /* Update internal state */ |
<> | 154:37f96f9d4de2 | 1003 | handle->saiQueue[handle->queueDriver].dataSize -= size; |
<> | 154:37f96f9d4de2 | 1004 | handle->saiQueue[handle->queueDriver].data += size; |
<> | 154:37f96f9d4de2 | 1005 | } |
<> | 154:37f96f9d4de2 | 1006 | #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ |
<> | 154:37f96f9d4de2 | 1007 | |
<> | 154:37f96f9d4de2 | 1008 | /* If finished a blcok, call the callback function */ |
<> | 154:37f96f9d4de2 | 1009 | if (handle->saiQueue[handle->queueDriver].dataSize == 0U) |
<> | 154:37f96f9d4de2 | 1010 | { |
<> | 154:37f96f9d4de2 | 1011 | memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t)); |
<> | 154:37f96f9d4de2 | 1012 | handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE; |
<> | 154:37f96f9d4de2 | 1013 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1014 | { |
<> | 154:37f96f9d4de2 | 1015 | (handle->callback)(base, handle, kStatus_SAI_RxIdle, handle->userData); |
<> | 154:37f96f9d4de2 | 1016 | } |
<> | 154:37f96f9d4de2 | 1017 | } |
<> | 154:37f96f9d4de2 | 1018 | |
<> | 154:37f96f9d4de2 | 1019 | /* If all data finished, just stop the transfer */ |
<> | 154:37f96f9d4de2 | 1020 | if (handle->saiQueue[handle->queueDriver].data == NULL) |
<> | 154:37f96f9d4de2 | 1021 | { |
<> | 154:37f96f9d4de2 | 1022 | SAI_TransferAbortReceive(base, handle); |
<> | 154:37f96f9d4de2 | 1023 | } |
<> | 154:37f96f9d4de2 | 1024 | } |
<> | 154:37f96f9d4de2 | 1025 | |
<> | 154:37f96f9d4de2 | 1026 | #if defined(I2S0) |
<> | 154:37f96f9d4de2 | 1027 | #if defined(FSL_FEATURE_SAI_INT_SOURCE_NUM) && (FSL_FEATURE_SAI_INT_SOURCE_NUM == 1) |
<> | 154:37f96f9d4de2 | 1028 | void I2S0_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1029 | { |
<> | 154:37f96f9d4de2 | 1030 | if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag))) |
<> | 154:37f96f9d4de2 | 1031 | { |
<> | 154:37f96f9d4de2 | 1032 | s_saiRxIsr(I2S0, s_saiHandle[0][1]); |
<> | 154:37f96f9d4de2 | 1033 | } |
<> | 154:37f96f9d4de2 | 1034 | if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag))) |
<> | 154:37f96f9d4de2 | 1035 | { |
<> | 154:37f96f9d4de2 | 1036 | s_saiTxIsr(I2S0, s_saiHandle[0][0]); |
<> | 154:37f96f9d4de2 | 1037 | } |
<> | 154:37f96f9d4de2 | 1038 | } |
<> | 154:37f96f9d4de2 | 1039 | #else |
<> | 154:37f96f9d4de2 | 1040 | void I2S0_Tx_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1041 | { |
<> | 154:37f96f9d4de2 | 1042 | assert(s_saiHandle[0][0]); |
<> | 154:37f96f9d4de2 | 1043 | s_saiTxIsr(I2S0, s_saiHandle[0][0]); |
<> | 154:37f96f9d4de2 | 1044 | } |
<> | 154:37f96f9d4de2 | 1045 | |
<> | 154:37f96f9d4de2 | 1046 | void I2S0_Rx_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1047 | { |
<> | 154:37f96f9d4de2 | 1048 | assert(s_saiHandle[0][1]); |
<> | 154:37f96f9d4de2 | 1049 | s_saiRxIsr(I2S0, s_saiHandle[0][1]); |
<> | 154:37f96f9d4de2 | 1050 | } |
<> | 154:37f96f9d4de2 | 1051 | #endif /* FSL_FEATURE_SAI_INT_SOURCE_NUM */ |
<> | 154:37f96f9d4de2 | 1052 | #endif /* I2S0*/ |
<> | 154:37f96f9d4de2 | 1053 | |
<> | 154:37f96f9d4de2 | 1054 | #if defined(I2S1) |
<> | 154:37f96f9d4de2 | 1055 | void I2S1_Tx_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1056 | { |
<> | 154:37f96f9d4de2 | 1057 | assert(s_saiHandle[1][0]); |
<> | 154:37f96f9d4de2 | 1058 | s_saiTxIsr(I2S1, s_saiHandle[1][0]); |
<> | 154:37f96f9d4de2 | 1059 | } |
<> | 154:37f96f9d4de2 | 1060 | |
<> | 154:37f96f9d4de2 | 1061 | void I2S1_Rx_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1062 | { |
<> | 154:37f96f9d4de2 | 1063 | assert(s_saiHandle[1][1]); |
<> | 154:37f96f9d4de2 | 1064 | s_saiRxIsr(I2S1, s_saiHandle[1][1]); |
<> | 154:37f96f9d4de2 | 1065 | } |
<> | 154:37f96f9d4de2 | 1066 | #endif |