123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836 |
- /*
- * The Clear BSD License
- * Copyright (c) 2016, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted (subject to the limitations in the disclaimer below) provided
- * that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fsl_i2s.h"
- #include "fsl_flexcomm.h"
- #include <string.h>
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /* Component ID definition, used by tools. */
- #ifndef FSL_COMPONENT_ID
- #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2s"
- #endif
- /* TODO - absent in device header files, should be there */
- #define I2S_FIFOCFG_TXI2SE0_MASK (0x4U)
- #define I2S_FIFOCFG_TXI2SE0_SHIFT (2U)
- #define I2S_FIFOCFG_TXI2SE0(x) (((uint32_t)(((uint32_t)(x)) << I2S_FIFOCFG_TXI2SE0_SHIFT)) & I2S_FIFOCFG_TXI2SE0_MASK)
- #define I2S_FIFOCFG_PACK48_MASK (0x8U)
- #define I2S_FIFOCFG_PACK48_SHIFT (3U)
- #define I2S_FIFOCFG_PACK48(x) (((uint32_t)(((uint32_t)(x)) << I2S_FIFOCFG_PACK48_SHIFT)) & I2S_FIFOCFG_PACK48_MASK)
- /*! @brief I2S states. */
- enum _i2s_state
- {
- kI2S_StateIdle = 0x0, /*!< Not performing transfer */
- kI2S_StateTx, /*!< Performing transmit */
- kI2S_StateTxWaitToWriteDummyData, /*!< Wait on FIFO in order to write final dummy data there */
- kI2S_StateTxWaitForEmptyFifo, /*!< Wait for FIFO to be flushed */
- kI2S_StateRx, /*!< Performing receive */
- };
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- static void I2S_Config(I2S_Type *base, const i2s_config_t *config);
- static void I2S_TxEnable(I2S_Type *base, bool enable);
- static void I2S_RxEnable(I2S_Type *base, bool enable);
- static status_t I2S_ValidateBuffer(i2s_handle_t *handle, i2s_transfer_t *transfer);
- /*******************************************************************************
- * Code
- ******************************************************************************/
- void I2S_TxInit(I2S_Type *base, const i2s_config_t *config)
- {
- uint32_t cfg = 0U;
- uint32_t trig = 0U;
- FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2S_TX);
- I2S_Config(base, config);
- /* Configure FIFO */
- cfg |= I2S_FIFOCFG_ENABLETX(1U); /* enable TX FIFO */
- cfg |= I2S_FIFOCFG_EMPTYTX(1U); /* empty TX FIFO */
- cfg |= I2S_FIFOCFG_TXI2SE0(config->txEmptyZero); /* transmit zero when buffer becomes empty or last item */
- cfg |= I2S_FIFOCFG_PACK48(config->pack48); /* set pack 48-bit format or not */
- trig |= I2S_FIFOTRIG_TXLVLENA(1U); /* enable TX FIFO trigger */
- trig |= I2S_FIFOTRIG_TXLVL(config->watermark); /* set TX FIFO trigger level */
- base->FIFOCFG = cfg;
- base->FIFOTRIG = trig;
- }
- void I2S_RxInit(I2S_Type *base, const i2s_config_t *config)
- {
- uint32_t cfg = 0U;
- uint32_t trig = 0U;
- FLEXCOMM_Init(base, FLEXCOMM_PERIPH_I2S_RX);
- I2S_Config(base, config);
- /* Configure FIFO */
- cfg |= I2S_FIFOCFG_ENABLERX(1U); /* enable RX FIFO */
- cfg |= I2S_FIFOCFG_EMPTYRX(1U); /* empty RX FIFO */
- cfg |= I2S_FIFOCFG_PACK48(config->pack48); /* set pack 48-bit format or not */
- trig |= I2S_FIFOTRIG_RXLVLENA(1U); /* enable RX FIFO trigger */
- trig |= I2S_FIFOTRIG_RXLVL(config->watermark); /* set RX FIFO trigger level */
- base->FIFOCFG = cfg;
- base->FIFOTRIG = trig;
- }
- void I2S_TxGetDefaultConfig(i2s_config_t *config)
- {
- config->masterSlave = kI2S_MasterSlaveNormalMaster;
- config->mode = kI2S_ModeI2sClassic;
- config->rightLow = false;
- config->leftJust = false;
- config->pdmData = false;
- config->sckPol = false;
- config->wsPol = false;
- config->divider = 1U;
- config->oneChannel = false;
- config->dataLength = 16U;
- config->frameLength = 32U;
- config->position = 0U;
- config->watermark = 4U;
- config->txEmptyZero = true;
- config->pack48 = false;
- }
- void I2S_RxGetDefaultConfig(i2s_config_t *config)
- {
- config->masterSlave = kI2S_MasterSlaveNormalSlave;
- config->mode = kI2S_ModeI2sClassic;
- config->rightLow = false;
- config->leftJust = false;
- config->pdmData = false;
- config->sckPol = false;
- config->wsPol = false;
- config->divider = 1U;
- config->oneChannel = false;
- config->dataLength = 16U;
- config->frameLength = 32U;
- config->position = 0U;
- config->watermark = 4U;
- config->txEmptyZero = false;
- config->pack48 = false;
- }
- static void I2S_Config(I2S_Type *base, const i2s_config_t *config)
- {
- assert(config);
- uint32_t cfg1 = 0U;
- uint32_t cfg2 = 0U;
- /* set master/slave configuration */
- cfg1 |= I2S_CFG1_MSTSLVCFG(config->masterSlave);
- /* set I2S mode */
- cfg1 |= I2S_CFG1_MODE(config->mode);
- /* set right low (channel swap) */
- cfg1 |= I2S_CFG1_RIGHTLOW(config->rightLow);
- /* set data justification */
- cfg1 |= I2S_CFG1_LEFTJUST(config->leftJust);
- /* set source to PDM dmic */
- cfg1 |= I2S_CFG1_PDMDATA(config->pdmData);
- /* set SCLK polarity */
- cfg1 |= I2S_CFG1_SCK_POL(config->sckPol);
- /* set WS polarity */
- cfg1 |= I2S_CFG1_WS_POL(config->wsPol);
- /* set mono mode */
- cfg1 |= I2S_CFG1_ONECHANNEL(config->oneChannel);
- /* set data length */
- cfg1 |= I2S_CFG1_DATALEN(config->dataLength - 1U);
- /* set frame length */
- cfg2 |= I2S_CFG2_FRAMELEN(config->frameLength - 1U);
- /* set data position of this channel pair within the frame */
- cfg2 |= I2S_CFG2_POSITION(config->position);
- /* write to registers */
- base->CFG1 = cfg1;
- base->CFG2 = cfg2;
- /* set the clock divider */
- base->DIV = I2S_DIV_DIV(config->divider - 1U);
- }
- void I2S_Deinit(I2S_Type *base)
- {
- /* TODO gate FLEXCOMM clock via FLEXCOMM driver */
- }
- static void I2S_TxEnable(I2S_Type *base, bool enable)
- {
- if (enable)
- {
- I2S_EnableInterrupts(base, kI2S_TxErrorFlag | kI2S_TxLevelFlag);
- I2S_Enable(base);
- }
- else
- {
- I2S_DisableInterrupts(base, kI2S_TxErrorFlag | kI2S_TxLevelFlag);
- I2S_Disable(base);
- base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
- }
- }
- static void I2S_RxEnable(I2S_Type *base, bool enable)
- {
- if (enable)
- {
- I2S_EnableInterrupts(base, kI2S_RxErrorFlag | kI2S_RxLevelFlag);
- I2S_Enable(base);
- }
- else
- {
- I2S_DisableInterrupts(base, kI2S_RxErrorFlag | kI2S_RxLevelFlag);
- I2S_Disable(base);
- base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
- }
- }
- static status_t I2S_ValidateBuffer(i2s_handle_t *handle, i2s_transfer_t *transfer)
- {
- assert(transfer->data);
- if (!transfer->data)
- {
- return kStatus_InvalidArgument;
- }
- assert(transfer->dataSize > 0U);
- if (transfer->dataSize <= 0U)
- {
- return kStatus_InvalidArgument;
- }
- if (handle->dataLength == 4U)
- {
- /* No alignment and data length requirements */
- }
- else if ((handle->dataLength >= 5U) && (handle->dataLength <= 8U))
- {
- assert((((uint32_t)transfer->data) % 2U) == 0U);
- if ((((uint32_t)transfer->data) % 2U) != 0U)
- {
- /* Data not 2-bytes aligned */
- return kStatus_InvalidArgument;
- }
- assert((transfer->dataSize % 2U) == 0U);
- if ((transfer->dataSize % 2U) != 0U)
- {
- /* Data not in pairs of left/right channel bytes */
- return kStatus_InvalidArgument;
- }
- }
- else if ((handle->dataLength >= 9U) && (handle->dataLength <= 16U))
- {
- assert((((uint32_t)transfer->data) % 4U) == 0U);
- if ((((uint32_t)transfer->data) % 4U) != 0U)
- {
- /* Data not 4-bytes aligned */
- return kStatus_InvalidArgument;
- }
- assert((transfer->dataSize % 4U) == 0U);
- if ((transfer->dataSize % 4U) != 0U)
- {
- /* Data lenght not multiply of 4 */
- return kStatus_InvalidArgument;
- }
- }
- else if ((handle->dataLength >= 17U) && (handle->dataLength <= 24U))
- {
- assert((transfer->dataSize % 6U) == 0U);
- if ((transfer->dataSize % 6U) != 0U)
- {
- /* Data lenght not multiply of 6 */
- return kStatus_InvalidArgument;
- }
- assert(!((handle->pack48) && ((((uint32_t)transfer->data) % 4U) != 0U)));
- if ((handle->pack48) && ((((uint32_t)transfer->data) % 4U) != 0U))
- {
- /* Data not 4-bytes aligned */
- return kStatus_InvalidArgument;
- }
- }
- else /* if (handle->dataLength >= 25U) */
- {
- assert((((uint32_t)transfer->data) % 4U) == 0U);
- if ((((uint32_t)transfer->data) % 4U) != 0U)
- {
- /* Data not 4-bytes aligned */
- return kStatus_InvalidArgument;
- }
- if (handle->oneChannel)
- {
- assert((transfer->dataSize % 4U) == 0U);
- if ((transfer->dataSize % 4U) != 0U)
- {
- /* Data lenght not multiply of 4 */
- return kStatus_InvalidArgument;
- }
- }
- else
- {
- assert((transfer->dataSize % 8U) == 0U);
- if ((transfer->dataSize % 8U) != 0U)
- {
- /* Data lenght not multiply of 8 */
- return kStatus_InvalidArgument;
- }
- }
- }
- return kStatus_Success;
- }
- void I2S_TxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData)
- {
- assert(handle);
- /* Clear out the handle */
- memset(handle, 0U, sizeof(*handle));
- /* Save callback and user data */
- handle->completionCallback = callback;
- handle->userData = userData;
- /* Remember some items set previously by configuration */
- handle->watermark = ((base->FIFOTRIG & I2S_FIFOTRIG_TXLVL_MASK) >> I2S_FIFOTRIG_TXLVL_SHIFT);
- handle->oneChannel = ((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) >> I2S_CFG1_ONECHANNEL_SHIFT);
- handle->dataLength = ((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U;
- handle->pack48 = ((base->FIFOCFG & I2S_FIFOCFG_PACK48_MASK) >> I2S_FIFOCFG_PACK48_SHIFT);
- handle->useFifo48H = false;
- /* Register IRQ handling */
- FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)I2S_TxHandleIRQ, handle);
- }
- status_t I2S_TxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer)
- {
- assert(handle);
- if (!handle)
- {
- return kStatus_InvalidArgument;
- }
- status_t result;
- result = I2S_ValidateBuffer(handle, &transfer);
- if (result != kStatus_Success)
- {
- return result;
- }
- if (handle->i2sQueue[handle->queueUser].dataSize)
- {
- /* Previously prepared buffers not processed yet */
- return kStatus_I2S_Busy;
- }
- handle->state = kI2S_StateTx;
- handle->i2sQueue[handle->queueUser].data = transfer.data;
- handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
- handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
- base->FIFOTRIG = (base->FIFOTRIG & (~I2S_FIFOTRIG_TXLVL_MASK)) | I2S_FIFOTRIG_TXLVL(handle->watermark);
- I2S_TxEnable(base, true);
- return kStatus_Success;
- }
- void I2S_TxTransferAbort(I2S_Type *base, i2s_handle_t *handle)
- {
- assert(handle);
- /* Disable I2S operation and interrupts */
- I2S_TxEnable(base, false);
- /* Reset state */
- handle->state = kI2S_StateIdle;
- /* Clear transfer queue */
- memset((void *)&handle->i2sQueue, 0U, sizeof(i2s_transfer_t) * I2S_NUM_BUFFERS);
- handle->queueDriver = 0U;
- handle->queueUser = 0U;
- }
- void I2S_RxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData)
- {
- assert(handle);
- /* Clear out the handle */
- memset(handle, 0U, sizeof(*handle));
- /* Save callback and user data */
- handle->completionCallback = callback;
- handle->userData = userData;
- /* Remember some items set previously by configuration */
- handle->watermark = ((base->FIFOTRIG & I2S_FIFOTRIG_RXLVL_MASK) >> I2S_FIFOTRIG_RXLVL_SHIFT);
- handle->oneChannel = ((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) >> I2S_CFG1_ONECHANNEL_SHIFT);
- handle->dataLength = ((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U;
- handle->pack48 = ((base->FIFOCFG & I2S_FIFOCFG_PACK48_MASK) >> I2S_FIFOCFG_PACK48_SHIFT);
- handle->useFifo48H = false;
- /* Register IRQ handling */
- FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)I2S_RxHandleIRQ, handle);
- }
- status_t I2S_RxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer)
- {
- assert(handle);
- if (!handle)
- {
- return kStatus_InvalidArgument;
- }
- status_t result;
- result = I2S_ValidateBuffer(handle, &transfer);
- if (result != kStatus_Success)
- {
- return result;
- }
- if (handle->i2sQueue[handle->queueUser].dataSize)
- {
- /* Previously prepared buffers not processed yet */
- return kStatus_I2S_Busy;
- }
- handle->state = kI2S_StateRx;
- handle->i2sQueue[handle->queueUser].data = transfer.data;
- handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
- handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
- base->FIFOTRIG = (base->FIFOTRIG & (~I2S_FIFOTRIG_RXLVL_MASK)) | I2S_FIFOTRIG_RXLVL(handle->watermark);
- I2S_RxEnable(base, true);
- return kStatus_Success;
- }
- void I2S_RxTransferAbort(I2S_Type *base, i2s_handle_t *handle)
- {
- assert(handle);
- /* Disable I2S operation and interrupts */
- I2S_RxEnable(base, false);
- /* Reset state */
- handle->state = kI2S_StateIdle;
- /* Clear transfer queue */
- memset((void *)&handle->i2sQueue, 0U, sizeof(i2s_transfer_t) * I2S_NUM_BUFFERS);
- handle->queueDriver = 0U;
- handle->queueUser = 0U;
- }
- status_t I2S_TransferGetCount(I2S_Type *base, i2s_handle_t *handle, size_t *count)
- {
- assert(handle);
- if (!handle)
- {
- return kStatus_InvalidArgument;
- }
- assert(count);
- if (!count)
- {
- return kStatus_InvalidArgument;
- }
- if (handle->state == kI2S_StateIdle)
- {
- return kStatus_NoTransferInProgress;
- }
- *count = handle->transferCount;
- return kStatus_Success;
- }
- status_t I2S_TransferGetErrorCount(I2S_Type *base, i2s_handle_t *handle, size_t *count)
- {
- assert(handle);
- if (!handle)
- {
- return kStatus_InvalidArgument;
- }
- assert(count);
- if (!count)
- {
- return kStatus_InvalidArgument;
- }
- if (handle->state == kI2S_StateIdle)
- {
- return kStatus_NoTransferInProgress;
- }
- *count = handle->errorCount;
- return kStatus_Success;
- }
- void I2S_TxHandleIRQ(I2S_Type *base, i2s_handle_t *handle)
- {
- uint32_t intstat = base->FIFOINTSTAT;
- uint32_t data;
- if (intstat & I2S_FIFOINTSTAT_TXERR_MASK)
- {
- handle->errorCount++;
- /* Clear TX error interrupt flag */
- base->FIFOSTAT = I2S_FIFOSTAT_TXERR(1U);
- }
- if (intstat & I2S_FIFOINTSTAT_TXLVL_MASK)
- {
- if (handle->state == kI2S_StateTx)
- {
- /* Send data */
- while ((base->FIFOSTAT & I2S_FIFOSTAT_TXNOTFULL_MASK) &&
- (handle->i2sQueue[handle->queueDriver].dataSize > 0U))
- {
- /* Write output data */
- if (handle->dataLength == 4U)
- {
- data = *(handle->i2sQueue[handle->queueDriver].data);
- base->FIFOWR = ((data & 0xF0U) << 12U) | (data & 0xFU);
- handle->i2sQueue[handle->queueDriver].data++;
- handle->transferCount++;
- handle->i2sQueue[handle->queueDriver].dataSize--;
- }
- else if (handle->dataLength <= 8U)
- {
- data = *((volatile uint16_t *)handle->i2sQueue[handle->queueDriver].data);
- base->FIFOWR = ((data & 0xFF00U) << 8U) | (data & 0xFFU);
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
- handle->transferCount += sizeof(uint16_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
- }
- else if (handle->dataLength <= 16U)
- {
- base->FIFOWR = *((volatile uint32_t *)(handle->i2sQueue[handle->queueDriver].data));
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
- handle->transferCount += sizeof(uint32_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
- }
- else if (handle->dataLength <= 24U)
- {
- if (handle->pack48)
- {
- if (handle->useFifo48H)
- {
- base->FIFOWR48H = *((volatile uint16_t *)(handle->i2sQueue[handle->queueDriver].data));
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
- handle->transferCount += sizeof(uint16_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
- handle->useFifo48H = false;
- }
- else
- {
- base->FIFOWR = *((volatile uint32_t *)(handle->i2sQueue[handle->queueDriver].data));
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
- handle->transferCount += sizeof(uint32_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
- handle->useFifo48H = true;
- }
- }
- else
- {
- data = (uint32_t)(*(handle->i2sQueue[handle->queueDriver].data++));
- data |= ((uint32_t)(*(handle->i2sQueue[handle->queueDriver].data++))) << 8U;
- data |= ((uint32_t)(*(handle->i2sQueue[handle->queueDriver].data++))) << 16U;
- if (handle->useFifo48H)
- {
- base->FIFOWR48H = data;
- handle->useFifo48H = false;
- }
- else
- {
- base->FIFOWR = data;
- handle->useFifo48H = true;
- }
- handle->transferCount += 3U;
- handle->i2sQueue[handle->queueDriver].dataSize -= 3U;
- }
- }
- else /* if (handle->dataLength <= 32U) */
- {
- base->FIFOWR = *((volatile uint32_t *)(handle->i2sQueue[handle->queueDriver].data));
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
- handle->transferCount += sizeof(uint32_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
- }
- if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
- {
- /* Actual data buffer sent out, switch to a next one */
- handle->queueDriver = (handle->queueDriver + 1U) % I2S_NUM_BUFFERS;
- /* Notify user */
- if (handle->completionCallback)
- {
- handle->completionCallback(base, handle, kStatus_I2S_BufferComplete, handle->userData);
- }
- /* Check if the next buffer contains anything to send */
- if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
- {
- /* Everything has been written to FIFO */
- handle->state = kI2S_StateTxWaitToWriteDummyData;
- break;
- }
- }
- }
- }
- else if (handle->state == kI2S_StateTxWaitToWriteDummyData)
- {
- /* Write dummy data */
- if ((handle->dataLength > 16U) && (handle->dataLength < 25U))
- {
- if (handle->useFifo48H)
- {
- base->FIFOWR48H = 0U;
- handle->useFifo48H = false;
- }
- else
- {
- base->FIFOWR = 0U;
- base->FIFOWR48H = 0U;
- }
- }
- else
- {
- base->FIFOWR = 0U;
- }
- /* Next time invoke this handler when FIFO becomes empty (TX level 0) */
- base->FIFOTRIG &= ~I2S_FIFOTRIG_TXLVL_MASK;
- handle->state = kI2S_StateTxWaitForEmptyFifo;
- }
- else if (handle->state == kI2S_StateTxWaitForEmptyFifo)
- {
- /* FIFO, including additional dummy data, has been emptied now,
- * all relevant data should have been output from peripheral */
- /* Stop transfer */
- I2S_Disable(base);
- I2S_DisableInterrupts(base, kI2S_TxErrorFlag | kI2S_TxLevelFlag);
- base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
- /* Reset state */
- handle->state = kI2S_StateIdle;
- /* Notify user */
- if (handle->completionCallback)
- {
- handle->completionCallback(base, handle, kStatus_I2S_Done, handle->userData);
- }
- }
- else
- {
- /* Do nothing */
- }
- /* Clear TX level interrupt flag */
- base->FIFOSTAT = I2S_FIFOSTAT_TXLVL(1U);
- }
- }
- void I2S_RxHandleIRQ(I2S_Type *base, i2s_handle_t *handle)
- {
- uint32_t intstat = base->FIFOINTSTAT;
- uint32_t data;
- if (intstat & I2S_FIFOINTSTAT_RXERR_MASK)
- {
- handle->errorCount++;
- /* Clear RX error interrupt flag */
- base->FIFOSTAT = I2S_FIFOSTAT_RXERR(1U);
- }
- if (intstat & I2S_FIFOINTSTAT_RXLVL_MASK)
- {
- while ((base->FIFOSTAT & I2S_FIFOSTAT_RXNOTEMPTY_MASK) && (handle->i2sQueue[handle->queueDriver].dataSize > 0U))
- {
- /* Read input data */
- if (handle->dataLength == 4U)
- {
- data = base->FIFORD;
- *(handle->i2sQueue[handle->queueDriver].data) = ((data & 0x000F0000U) >> 12U) | (data & 0x0000000FU);
- handle->i2sQueue[handle->queueDriver].data++;
- handle->transferCount++;
- handle->i2sQueue[handle->queueDriver].dataSize--;
- }
- else if (handle->dataLength <= 8U)
- {
- data = base->FIFORD;
- *((volatile uint16_t *)handle->i2sQueue[handle->queueDriver].data) = ((data >> 8U) & 0xFF00U) | (data & 0xFFU);
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
- handle->transferCount += sizeof(uint16_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
- }
- else if (handle->dataLength <= 16U)
- {
- data = base->FIFORD;
- *((volatile uint32_t *)handle->i2sQueue[handle->queueDriver].data) = data;
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
- handle->transferCount += sizeof(uint32_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
- }
- else if (handle->dataLength <= 24U)
- {
- if (handle->pack48)
- {
- if (handle->useFifo48H)
- {
- data = base->FIFORD48H;
- handle->useFifo48H = false;
- *((volatile uint16_t *)handle->i2sQueue[handle->queueDriver].data) = data;
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint16_t);
- handle->transferCount += sizeof(uint16_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint16_t);
- }
- else
- {
- data = base->FIFORD;
- handle->useFifo48H = true;
- *((volatile uint32_t *)handle->i2sQueue[handle->queueDriver].data) = data;
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
- handle->transferCount += sizeof(uint32_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
- }
- }
- else
- {
- if (handle->useFifo48H)
- {
- data = base->FIFORD48H;
- handle->useFifo48H = false;
- }
- else
- {
- data = base->FIFORD;
- handle->useFifo48H = true;
- }
- *(handle->i2sQueue[handle->queueDriver].data++) = data & 0xFFU;
- *(handle->i2sQueue[handle->queueDriver].data++) = (data >> 8U) & 0xFFU;
- *(handle->i2sQueue[handle->queueDriver].data++) = (data >> 16U) & 0xFFU;
- handle->transferCount += 3U;
- handle->i2sQueue[handle->queueDriver].dataSize -= 3U;
- }
- }
- else /* if (handle->dataLength <= 32U) */
- {
- data = base->FIFORD;
- *((volatile uint32_t *)handle->i2sQueue[handle->queueDriver].data) = data;
- handle->i2sQueue[handle->queueDriver].data += sizeof(uint32_t);
- handle->transferCount += sizeof(uint32_t);
- handle->i2sQueue[handle->queueDriver].dataSize -= sizeof(uint32_t);
- }
- if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
- {
- /* Actual data buffer filled with input data, switch to a next one */
- handle->queueDriver = (handle->queueDriver + 1U) % I2S_NUM_BUFFERS;
- /* Notify user */
- if (handle->completionCallback)
- {
- handle->completionCallback(base, handle, kStatus_I2S_BufferComplete, handle->userData);
- }
- if (handle->i2sQueue[handle->queueDriver].dataSize == 0U)
- {
- /* No other buffer prepared to receive data into */
- /* Disable I2S operation and interrupts */
- I2S_Disable(base);
- I2S_DisableInterrupts(base, kI2S_RxErrorFlag | kI2S_RxLevelFlag);
- base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
- /* Reset state */
- handle->state = kI2S_StateIdle;
- /* Notify user */
- if (handle->completionCallback)
- {
- handle->completionCallback(base, handle, kStatus_I2S_Done, handle->userData);
- }
- /* Clear RX level interrupt flag */
- base->FIFOSTAT = I2S_FIFOSTAT_RXLVL(1U);
- return;
- }
- }
- }
- /* Clear RX level interrupt flag */
- base->FIFOSTAT = I2S_FIFOSTAT_RXLVL(1U);
- }
- }
|