示例#1
0
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;
    }
}
示例#2
0
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 = *((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 = *((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 = *((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 = *((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 = *((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);
    }
}
示例#3
0
void CodecController::stop(){
  I2S_Disable();
//   clearPin(GPIOA, GPIO_Pin_7); // DEBUG
  setActive(false);
}