added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Sep 02 15:07:44 2016 +0100
Revision:
144:ef7eb2e8f9f7
This updates the lib to the mbed lib v125

Who changed what in which revision?

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