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; } }
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); } }
void CodecController::stop(){ I2S_Disable(); // clearPin(GPIOA, GPIO_Pin_7); // DEBUG setActive(false); }