Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

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