2022-03-28 17:19:25 +08:00

1332 lines
39 KiB
C

#include "wm_i2s.h"
#include <math.h>
#define SYS_I2S_CLK (160000000)
static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma);
static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma);
static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s);
static void I2S_EndTransmit_IT(I2S_HandleTypeDef *hi2s);
static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s);
static void I2S_TxRxDMAHalfCplt(DMA_HandleTypeDef *hdma);
static void I2S_TxRxDMACplt(DMA_HandleTypeDef *hdma);
/**
* @brief Initializes the I2S according to the specified parameters
* in the I2S_InitTypeDef and create the associated handle.
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s)
{
uint32_t mclk_div, ws_div, datalen = 0;
if (hi2s == NULL)
{
return HAL_ERROR;
}
assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
assert_param(IS_I2S_MODE(hi2s->Init.Mode));
assert_param(IS_I2S_STANDARD(hi2s->Init.Standard));
assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat));
assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput));
assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq));
assert_param(IS_I2S_CHANNEL(hi2s->Init.Channel));
if (hi2s->State == HAL_I2S_STATE_RESET)
{
hi2s->Lock = HAL_UNLOCKED;
HAL_I2S_MspInit(hi2s);
}
hi2s->State = HAL_I2S_STATE_BUSY;
hi2s->Instance->CR = 0;
WRITE_REG(hi2s->Instance->CR, (hi2s->Init.Mode | hi2s->Init.Standard | hi2s->Init.DataFormat | hi2s->Init.Channel));
SET_BIT(hi2s->Instance->CR, (I2S_CR_RXFIFO_CLR | I2S_CR_TXFIFO_CLR | I2S_CR_RXFIFO_TH_1 | I2S_CR_TXFIFO_TH_4));
if (hi2s->Init.Channel == I2S_CHANNEL_MONO)
{
assert_param(IS_I2S_CHANNELSEL(hi2s->Init.ChannelSel));
SET_BIT(hi2s->Instance->CR, hi2s->Init.ChannelSel);
}
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
datalen = 8;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
datalen = 16;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_24B)
{
datalen = 24;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_32B)
{
datalen = 32;
}
ws_div = round((SYS_I2S_CLK / (hi2s->Init.AudioFreq * datalen * 2)));
if (hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE)
{
mclk_div = round(SYS_I2S_CLK / (hi2s->Init.AudioFreq * 256));
if (mclk_div > 63)
{
mclk_div = 63;
}
MODIFY_REG(RCC->I2S_CLK, (RCC_I2S_CLK_MCLKDIV | RCC_I2S_CLK_MCLK_EN), ((mclk_div << RCC_I2S_CLK_MCLKDIV_Pos) | RCC_I2S_CLK_MCLK_EN));
}
MODIFY_REG(RCC->I2S_CLK, RCC_I2S_CLK_BCLKDIV, (ws_div << RCC_I2S_CLK_BCLKDIV_Pos));
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->State = HAL_I2S_STATE_READY;
return HAL_OK;
}
/**
* @brief DeInitializes the I2S peripheral
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s)
{
if (hi2s == NULL)
{
return HAL_ERROR;
}
assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
hi2s->State = HAL_I2S_STATE_BUSY;
__HAL_I2S_DISABLE(hi2s);
HAL_I2S_MspDeInit(hi2s);
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->State = HAL_I2S_STATE_RESET;
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief I2S MSP Init
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief I2S MSP DeInit
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Transmit an amount of data in blocking mode
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pData a 32-bit pointer to data buffer.
* @param Size number of data sample to be sent:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to send 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to send 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to send 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to send 100 32bit data sample, Size = 100
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint32_t *pData, uint32_t Size, uint32_t Timeout)
{
uint32_t tickstart = 0U, fifo_count = 0, i = 0;
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
if (hi2s->State != HAL_I2S_STATE_READY)
{
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
hi2s->State = HAL_I2S_STATE_BUSY_TX;
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
tickstart = HAL_GetTick();
hi2s->pTxBuffPtr = pData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->TxXferSize = (Size + 3) / 4;
hi2s->TxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->TxXferSize = (Size + 1) / 2;
hi2s->TxXferCount = (Size + 1) / 2;
}
else
{
hi2s->TxXferSize = Size;
hi2s->TxXferCount = Size;
}
SET_BIT(hi2s->Instance->CR, I2S_CR_TXFIFO_CLR);
while (hi2s->TxXferCount > 0)
{
fifo_count = I2S_FIFO_FULL - __HAL_I2S_GET_TXFIFO(hi2s);
fifo_count = (fifo_count > hi2s->TxXferCount) ? hi2s->TxXferCount : fifo_count;
for (i = 0; i < fifo_count; i++)
{
hi2s->Instance->TXDR = (*hi2s->pTxBuffPtr);
hi2s->pTxBuffPtr++;
hi2s->TxXferCount--;
}
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
if ((hi2s->Instance->CR & I2S_CR_TXEN) != I2S_CR_TXEN)
{
__HAL_I2S_ENABLE_TX(hi2s);
}
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0))
{
__HAL_I2S_DISABLE_TX(hi2s);
hi2s->ErrorCode = HAL_I2S_ERROR_TIMEOUT;
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
}
while (__HAL_I2S_GET_IT(hi2s, I2S_IF_TX_UNDERFLOW) != I2S_IF_TX_UNDERFLOW)
{
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0))
{
__HAL_I2S_DISABLE_TX(hi2s);
hi2s->ErrorCode = HAL_I2S_ERROR_TIMEOUT;
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
}
__HAL_I2S_DISABLE_TX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Receive an amount of data in blocking mode
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pData a 32-bit pointer to data buffer.
* @param Size number of data sample to be received:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to receive 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to receive 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to receive 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to receive 100 32bit data sample, Size = 100
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint32_t *pData, uint32_t Size, uint32_t Timeout)
{
uint32_t tickstart = 0, fifo_count = 0, i = 0;
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
if (hi2s->State != HAL_I2S_STATE_READY)
{
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
hi2s->State = HAL_I2S_STATE_BUSY_RX;
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->pRxBuffPtr = pData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->RxXferSize = (Size + 3) / 4;
hi2s->RxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->RxXferSize = (Size + 1) / 2;
hi2s->RxXferCount = (Size + 1) / 2;
}
else
{
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
__HAL_I2S_ENABLE_RX(hi2s);
while (hi2s->RxXferCount > 0)
{
fifo_count = __HAL_I2S_GET_RXFIFO(hi2s);
fifo_count = (fifo_count > hi2s->RxXferCount) ? hi2s->RxXferCount : fifo_count;
for (i = 0; i < fifo_count; i++)
{
(*hi2s->pRxBuffPtr) = (uint32_t)hi2s->Instance->RXDR;
hi2s->pRxBuffPtr++;
hi2s->RxXferCount--;
}
if (__HAL_I2S_GET_IT(hi2s, I2S_IF_RX_OVERFLOW))
{
__HAL_I2S_CLEAR_IT(hi2s, I2S_IF_RX_OVERFLOW);
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_RXERR);
}
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0))
{
__HAL_I2S_DISABLE_RX(hi2s);
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
}
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Full-Duplex Transmit/Receive data in blocking mode.
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pTxData a 32-bit pointer to the Transmit data buffer.
* @param pRxData a 32-bit pointer to the Receive data buffer.
* @param Size number of data sample to be transmission:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to transmission 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to transmission 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to transmission 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to transmission 100 32bit data sample, Size = 100
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_TransmitReceive(I2S_HandleTypeDef *hi2s, uint32_t *pTxData, uint32_t *pRxData,
uint32_t Size, uint32_t Timeout)
{
HAL_StatusTypeDef errorcode = HAL_OK;
uint32_t tickstart = 0U, fifo_count = 0, i = 0;
if (hi2s->State != HAL_I2S_STATE_READY)
{
errorcode = HAL_BUSY;
goto error;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
hi2s->pTxBuffPtr = pTxData;
hi2s->pRxBuffPtr = pRxData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->TxXferSize = (Size + 3) / 4;
hi2s->TxXferCount = (Size + 3) / 4;
hi2s->RxXferSize = (Size + 3) / 4;
hi2s->RxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->TxXferSize = (Size + 1) / 2;
hi2s->TxXferCount = (Size + 1) / 2;
hi2s->RxXferSize = (Size + 1) / 2;
hi2s->RxXferCount = (Size + 1) / 2;
}
else
{
hi2s->TxXferSize = Size;
hi2s->TxXferCount = Size;
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->State = HAL_I2S_STATE_BUSY_TXRX;
tickstart = HAL_GetTick();
SET_BIT(hi2s->Instance->CR, I2S_CR_TXFIFO_CLR);
SET_BIT(hi2s->Instance->CR, I2S_CR_RXFIFO_CLR);
fifo_count = I2S_FIFO_FULL - __HAL_I2S_GET_TXFIFO(hi2s);
fifo_count = (fifo_count > hi2s->TxXferCount) ? hi2s->TxXferCount : fifo_count;
for (i = 0; i < fifo_count; i++)
{
hi2s->Instance->TXDR = (*hi2s->pTxBuffPtr);
hi2s->pTxBuffPtr++;
hi2s->TxXferCount--;
}
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
if ((hi2s->Instance->CR & I2S_CR_TXEN) != I2S_CR_TXEN)
{
__HAL_I2S_ENABLE_TX(hi2s);
}
if ((hi2s->Instance->CR & I2S_CR_RXEN) != I2S_CR_RXEN)
{
__HAL_I2S_ENABLE_RX(hi2s);
}
while ((hi2s->RxXferCount > 0U) || (hi2s->TxXferCount > 0U))
{
fifo_count = I2S_FIFO_FULL - __HAL_I2S_GET_TXFIFO(hi2s);
fifo_count = (fifo_count > hi2s->TxXferCount) ? hi2s->TxXferCount : fifo_count;
for (i = 0; i < fifo_count; i++)
{
hi2s->Instance->TXDR = (*hi2s->pTxBuffPtr);
hi2s->pTxBuffPtr++;
hi2s->TxXferCount--;
}
if (__HAL_I2S_GET_IT(hi2s, I2S_IF_TX_UNDERFLOW))
{
__HAL_I2S_CLEAR_IT(hi2s, I2S_IF_TX_UNDERFLOW);
if (hi2s->TxXferCount > 0)
{
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TXERR);
}
}
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0))
{
__HAL_I2S_DISABLE_TX(hi2s);
__HAL_I2S_DISABLE_RX(hi2s);
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
errorcode = HAL_ERROR;
goto error;
}
fifo_count = __HAL_I2S_GET_RXFIFO(hi2s);
fifo_count = (fifo_count > hi2s->RxXferCount) ? hi2s->RxXferCount : fifo_count;
for (i = 0; i < fifo_count; i++)
{
(*hi2s->pRxBuffPtr) = (uint32_t)hi2s->Instance->RXDR;
hi2s->pRxBuffPtr++;
hi2s->RxXferCount--;
}
if (__HAL_I2S_GET_IT(hi2s, I2S_IF_RX_OVERFLOW))
{
__HAL_I2S_CLEAR_IT(hi2s, I2S_IF_RX_OVERFLOW);
if (hi2s->RxXferCount > 0)
{
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_RXERR);
}
}
}
if (hi2s->ErrorCode != HAL_I2S_ERROR_NONE)
{
errorcode = HAL_ERROR;
}
error :
__HAL_I2S_DISABLE_TX(hi2s);
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return errorcode;
}
/**
* @brief Transmit an amount of data in non-blocking mode with Interrupt
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pData a 32-bit pointer to data buffer.
* @param Size number of data sample to be sent:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to send 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to send 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to send 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to send 100 32bit data sample, Size = 100
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint32_t *pData, uint32_t Size)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
if (hi2s->State != HAL_I2S_STATE_READY)
{
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
hi2s->State = HAL_I2S_STATE_BUSY_TX;
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->pTxBuffPtr = pData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->TxXferSize = (Size + 3) / 4;
hi2s->TxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->TxXferSize = (Size + 1) / 2;
hi2s->TxXferCount = (Size + 1) / 2;
}
else
{
hi2s->TxXferSize = Size;
hi2s->TxXferCount = Size;
}
__HAL_I2S_CLEAR_IT(hi2s, (I2S_IF_TXTH | I2S_IF_TXDONE | I2S_IF_TX_UNDERFLOW | I2S_IF_TX_OVERFLOW));
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IM_TXDONE | I2S_IM_TXTH | I2S_IM_TX_UNDERFLOW));
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
I2S_Transmit_IT(hi2s);
__HAL_I2S_ENABLE_TX(hi2s);
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Receive an amount of data in non-blocking mode with Interrupt
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pData a 32-bit pointer to the Receive data buffer.
* @param Size number of data sample to be received:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to receive 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to receive 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to receive 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to receive 100 32bit data sample, Size = 100
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint32_t *pData, uint32_t Size)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
if (hi2s->State != HAL_I2S_STATE_READY)
{
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
hi2s->State = HAL_I2S_STATE_BUSY_RX;
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->pRxBuffPtr = pData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->RxXferSize = (Size + 3) / 4;
hi2s->RxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->RxXferSize = (Size + 1) / 2;
hi2s->RxXferCount = (Size + 1) / 2;
}
else
{
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
__HAL_I2S_CLEAR_IT(hi2s, (I2S_IF_RXTH | I2S_IF_RXDONE | I2S_IF_RX_OVERFLOW | I2S_IF_RX_UNDERFLOW));
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IM_RXDONE | I2S_IM_RXTH | I2S_IM_RX_OVERFLOW));
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
__HAL_I2S_ENABLE_RX(hi2s);
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Full-Duplex Transmit/Receive data in non-blocking mode using Interrupt
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pTxData a 32-bit pointer to the Transmit data buffer.
* @param pRxData a 32-bit pointer to the Receive data buffer.
* @param Size number of data sample to be transmission:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to transmission 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to transmission 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to transmission 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to transmission 100 32bit data sample, Size = 100
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_TransmitReceive_IT(I2S_HandleTypeDef *hi2s, uint32_t *pTxData, uint32_t *pRxData,
uint32_t Size)
{
if (hi2s->State != HAL_I2S_STATE_READY)
{
return HAL_BUSY;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
hi2s->pTxBuffPtr = pTxData;
hi2s->pRxBuffPtr = pRxData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->TxXferSize = (Size + 3) / 4;
hi2s->TxXferCount = (Size + 3) / 4;
hi2s->RxXferSize = (Size + 3) / 4;
hi2s->RxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->TxXferSize = (Size + 1) / 2;
hi2s->TxXferCount = (Size + 1) / 2;
hi2s->RxXferSize = (Size + 1) / 2;
hi2s->RxXferCount = (Size + 1) / 2;
}
else
{
hi2s->TxXferSize = Size;
hi2s->TxXferCount = Size;
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->State = HAL_I2S_STATE_BUSY_TXRX;
SET_BIT(hi2s->Instance->CR, I2S_CR_TXFIFO_CLR);
SET_BIT(hi2s->Instance->CR, I2S_CR_RXFIFO_CLR);
__HAL_I2S_CLEAR_IT(hi2s, (I2S_IF_TXTH | I2S_IF_TXDONE | I2S_IF_TX_UNDERFLOW | I2S_IF_TX_OVERFLOW |
I2S_IF_RXTH | I2S_IF_RXDONE | I2S_IF_RX_UNDERFLOW | I2S_IF_RX_OVERFLOW));
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IM_TXDONE | I2S_IM_TXTH | I2S_IM_TX_UNDERFLOW |
I2S_IM_RXDONE | I2S_IM_RXTH | I2S_IM_RX_OVERFLOW));
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
I2S_Transmit_IT(hi2s);
__HAL_I2S_ENABLE_TX(hi2s);
__HAL_I2S_ENABLE_RX(hi2s);
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Transmit an amount of data in non-blocking mode with DMA
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pData a 32-bit pointer to the Transmit data buffer.
* @param Size number of data sample to be sent:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to receive 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to receive 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to receive 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to receive 100 32bit data sample, Size = 100
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint32_t *pData, uint32_t Size)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
if (hi2s->State != HAL_I2S_STATE_READY)
{
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
hi2s->State = HAL_I2S_STATE_BUSY_TX;
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->pTxBuffPtr = pData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->TxXferSize = (Size + 3) / 4;
hi2s->TxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->TxXferSize = (Size + 1) / 2;
hi2s->TxXferCount = (Size + 1) / 2;
}
else
{
hi2s->TxXferSize = Size;
hi2s->TxXferCount = Size;
}
hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt;
hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt;
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx,
(uint32_t)hi2s->pTxBuffPtr,
(uint32_t)&hi2s->Instance->TXDR,
(hi2s->TxXferSize * 4)))
{
hi2s->ErrorCode = HAL_I2S_ERROR_DMA;
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
if ((hi2s->Instance->CR & I2S_CR_TXDMA_EN) != I2S_CR_TXDMA_EN)
{
SET_BIT(hi2s->Instance->CR, I2S_CR_TXDMA_EN);
}
__HAL_I2S_ENABLE_IT(hi2s, I2S_IF_TX_UNDERFLOW);
__HAL_I2S_ENABLE_TX(hi2s);
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Receive an amount of data in non-blocking mode with DMA
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pData a 32-bit pointer to the Receive data buffer.
* @param Size number of data sample to be received:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to receive 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to receive 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to receive 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to receive 100 32bit data sample, Size = 100
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint32_t *pData, uint32_t Size)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
if (hi2s->State != HAL_I2S_STATE_READY)
{
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
hi2s->State = HAL_I2S_STATE_BUSY_RX;
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->pRxBuffPtr = pData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->RxXferSize = (Size + 3) / 4;
hi2s->RxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->RxXferSize = (Size + 1) / 2;
hi2s->RxXferCount = (Size + 1) / 2;
}
else
{
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx,
(uint32_t)&hi2s->Instance->RXDR,
(uint32_t)hi2s->pRxBuffPtr,
(hi2s->RxXferSize * 4)))
{
hi2s->ErrorCode = HAL_I2S_ERROR_DMA;
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
if ((hi2s->Instance->CR & I2S_CR_RXDMA_EN) != I2S_CR_RXDMA_EN)
{
SET_BIT(hi2s->Instance->CR, I2S_CR_RXDMA_EN);
}
__HAL_I2S_ENABLE_RX(hi2s);
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Full-Duplex Transmit/Receive data in non-blocking mode using DMA
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @param pTxData a 32-bit pointer to the Transmit data buffer.
* @param pRxData a 32-bit pointer to the Receive data buffer.
* @param Size number of data sample to be transmission:
* @note When DataFormat = I2S_DATAFORMAT_8B, 1 pData : 4 data sample. E.g: if you want to transmission 100 8bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_16B, 1 pData : 2 data sample. E.g: if you want to transmission 100 16bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_24B, 1 pData : 1 data sample. E.g: if you want to transmission 100 24bit data sample, Size = 100
* When DataFormat = I2S_DATAFORMAT_32B, 1 pData : 1 data sample. E.g: if you want to transmission 100 32bit data sample, Size = 100
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_TransmitReceive_DMA(I2S_HandleTypeDef *hi2s, uint32_t *pTxData, uint32_t *pRxData,
uint32_t Size)
{
if (hi2s->State != HAL_I2S_STATE_READY)
{
return HAL_BUSY;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
__HAL_LOCK(hi2s);
hi2s->pTxBuffPtr = pTxData;
hi2s->pRxBuffPtr = pRxData;
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_8B)
{
hi2s->TxXferSize = (Size + 3) / 4;
hi2s->TxXferCount = (Size + 3) / 4;
hi2s->RxXferSize = (Size + 3) / 4;
hi2s->RxXferCount = (Size + 3) / 4;
}
else if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
{
hi2s->TxXferSize = (Size + 1) / 2;
hi2s->TxXferCount = (Size + 1) / 2;
hi2s->RxXferSize = (Size + 1) / 2;
hi2s->RxXferCount = (Size + 1) / 2;
}
else
{
hi2s->TxXferSize = Size;
hi2s->TxXferCount = Size;
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->State = HAL_I2S_STATE_BUSY_TXRX;
hi2s->hdmatx->XferHalfCpltCallback = I2S_TxRxDMAHalfCplt;
hi2s->hdmatx->XferCpltCallback = I2S_TxRxDMACplt;
hi2s->hdmarx->XferHalfCpltCallback = I2S_TxRxDMAHalfCplt;
hi2s->hdmarx->XferCpltCallback = I2S_TxRxDMACplt;
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx,
(uint32_t)hi2s->pTxBuffPtr,
(uint32_t)&hi2s->Instance->TXDR,
(hi2s->TxXferSize * 4)))
{
hi2s->ErrorCode = HAL_I2S_ERROR_DMA;
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx,
(uint32_t)&hi2s->Instance->RXDR,
(uint32_t)hi2s->pRxBuffPtr,
(hi2s->RxXferSize * 4)))
{
hi2s->ErrorCode = HAL_I2S_ERROR_DMA;
hi2s->State = HAL_I2S_STATE_READY;
__HAL_UNLOCK(hi2s);
return HAL_ERROR;
}
SET_BIT(hi2s->Instance->CR, (I2S_CR_TXDMA_EN | I2S_CR_RXDMA_EN));
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
__HAL_I2S_ENABLE_TX(hi2s);
__HAL_I2S_ENABLE_RX(hi2s);
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Pauses the audio DMA Stream/Channel playing from the Media.
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s)
{
__HAL_LOCK(hi2s);
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
{
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_TXDMA_EN);
}
if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
{
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_RXDMA_EN);
}
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Resumes the audio DMA Stream/Channel playing from the Media.
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s)
{
__HAL_LOCK(hi2s);
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
{
SET_BIT(hi2s->Instance->CR, I2S_CR_TXDMA_EN);
if ((hi2s->Instance->CR & I2S_CR_TXEN) != I2S_CR_TXEN)
{
__HAL_I2S_ENABLE_TX(hi2s);
}
}
if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
{
SET_BIT(hi2s->Instance->CR, I2S_CR_RXDMA_EN);
if ((hi2s->Instance->CR & I2S_CR_RXEN) != I2S_CR_RXEN)
{
__HAL_I2S_ENABLE_RX(hi2s);
}
}
if ((hi2s->Instance->CR & I2S_CR_EN) != I2S_CR_EN)
{
__HAL_I2S_ENABLE(hi2s);
}
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
/**
* @brief Stops the audio DMA Stream/Channel playing from the Media.
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s)
{
HAL_StatusTypeDef errorcode = HAL_OK;
if ((hi2s->Instance->CR & I2S_CR_TXEN) == I2S_CR_TXEN)
{
if (hi2s->hdmatx != NULL)
{
if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx))
{
hi2s->ErrorCode = HAL_I2S_ERROR_DMA;
errorcode = HAL_ERROR;
}
}
__HAL_I2S_DISABLE_TX(hi2s);
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_TXDMA_EN);
hi2s->State = HAL_I2S_STATE_READY;
}
if ((hi2s->Instance->CR & I2S_CR_RXEN) == I2S_CR_RXEN)
{
if (hi2s->hdmarx != NULL)
{
if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx))
{
hi2s->ErrorCode = HAL_I2S_ERROR_DMA;
errorcode = HAL_ERROR;
}
}
__HAL_I2S_DISABLE_RX(hi2s);
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_RXDMA_EN);
hi2s->State = HAL_I2S_STATE_READY;
}
__HAL_I2S_DISABLE(hi2s);
return errorcode;
}
/**
* @brief This function handles I2S interrupt request.
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s)
{
uint32_t itmask = hi2s->Instance->IM;
uint32_t itflag = hi2s->Instance->IF;
__HAL_I2S_CLEAR_IT(hi2s, itflag);
if ((hi2s->Instance->CR & I2S_CR_TXEN) == I2S_CR_TXEN)
{
if (((itflag & I2S_IF_TXTH) == I2S_IF_TXTH) && ((itmask & I2S_IM_TXTH) == RESET))
{
I2S_Transmit_IT(hi2s);
}
if (((itflag & I2S_IF_TXDONE) == I2S_IF_TXDONE) && ((itmask & I2S_IM_TXDONE) == RESET))
{
I2S_Transmit_IT(hi2s);
}
if (((itflag & I2S_IF_TX_UNDERFLOW) == I2S_IF_TX_UNDERFLOW) && ((itmask & I2S_IM_TX_UNDERFLOW) == RESET))
{
I2S_EndTransmit_IT(hi2s);
}
}
if ((hi2s->Instance->CR & I2S_CR_RXEN) == I2S_CR_RXEN)
{
if (((itflag & I2S_IF_RXTH) == I2S_IF_RXTH) && ((itmask & I2S_IM_RXTH) == RESET))
{
I2S_Receive_IT(hi2s);
}
if (((itflag & I2S_IF_RXDONE) == I2S_IF_RXDONE) && ((itmask & I2S_IM_RXDONE) == RESET))
{
I2S_Receive_IT(hi2s);
}
if (((itflag & I2S_IF_RX_OVERFLOW) == I2S_IF_RX_OVERFLOW) && ((itmask & I2S_IM_RX_OVERFLOW) == RESET))
{
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_RXERR);
HAL_I2S_ErrorCallback(hi2s);
}
}
}
/**
* @brief Tx Transfer Half completed callbacks
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Tx Transfer completed callbacks
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Rx Transfer half completed callbacks
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Rx Transfer completed callbacks
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Tx and Rx Transfer half completed callback
* @param hi2s I2S handle
* @retval None
*/
__attribute__((weak)) void HAL_I2S_TxRxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Tx and Rx Transfer completed callback
* @param hi2s I2S handle
* @retval None
*/
__attribute__((weak)) void HAL_I2S_TxRxCpltCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief I2S error callbacks
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
__attribute__((weak)) void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
{
UNUSED(hi2s);
}
/**
* @brief Return the I2S state
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval HAL state
*/
HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s)
{
return hi2s->State;
}
/**
* @brief Return the I2S error code
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval I2S Error Code
*/
uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s)
{
return hi2s->ErrorCode;
}
/**
* @brief DMA I2S transmit process complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
if ((hdma->Init.Mode == DMA_MODE_NORMAL_SINGLE) || (hdma->Init.Mode == DMA_MODE_LINK_SINGLE))
{
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_TXDMA_EN);
// __HAL_I2S_DISABLE_TX(hi2s);
hi2s->TxXferCount = 0;
// hi2s->State = HAL_I2S_STATE_READY;
}
// HAL_I2S_TxCpltCallback(hi2s);
}
/**
* @brief DMA I2S transmit process half complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
HAL_I2S_TxHalfCpltCallback(hi2s);
}
/**
* @brief DMA I2S receive process complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
if ((hdma->Init.Mode == DMA_MODE_NORMAL_SINGLE) || (hdma->Init.Mode == DMA_MODE_LINK_SINGLE))
{
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_RXDMA_EN);
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->RxXferCount = 0;
hi2s->State = HAL_I2S_STATE_READY;
}
HAL_I2S_RxCpltCallback(hi2s);
}
/**
* @brief DMA I2S receive process half complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
HAL_I2S_RxHalfCpltCallback(hi2s);
}
/**
* @brief DMA I2S transmit receive process complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2S_TxRxDMACplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
if ((hdma->Init.Mode == DMA_MODE_NORMAL_SINGLE) || (hdma->Init.Mode == DMA_MODE_LINK_SINGLE))
{
if (hi2s->hdmarx == hdma)
{
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_RXDMA_EN);
hi2s->RxXferCount = 0;
if (hi2s->TxXferCount == 0U)
{
__HAL_I2S_DISABLE_TX(hi2s);
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2S_TxRxCpltCallback(hi2s);
}
}
if (hi2s->hdmatx == hdma)
{
CLEAR_BIT(hi2s->Instance->CR, I2S_CR_TXDMA_EN);
hi2s->TxXferCount = 0;
if (hi2s->RxXferCount == 0U)
{
__HAL_I2S_DISABLE_TX(hi2s);
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2S_TxRxCpltCallback(hi2s);
}
}
}
}
/**
* @brief DMA I2S transmit receive process half complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2S_TxRxDMAHalfCplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
HAL_I2S_TxRxHalfCpltCallback(hi2s);
}
/**
* @brief Transmit an amount of data in non-blocking mode with Interrupt
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s)
{
uint32_t fifo_count = I2S_FIFO_FULL - __HAL_I2S_GET_TXFIFO(hi2s);
if (fifo_count > hi2s->TxXferCount)
{
fifo_count = hi2s->TxXferCount;
}
while (fifo_count > 0)
{
hi2s->Instance->TXDR = *(hi2s->pTxBuffPtr);
hi2s->pTxBuffPtr++;
hi2s->TxXferCount--;
fifo_count--;
}
}
/**
* @brief Wraps up transmission in non-blocking mode with Interrupt
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
static void I2S_EndTransmit_IT(I2S_HandleTypeDef *hi2s)
{
if (hi2s->TxXferCount == 0)
{
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IM_TXDONE | I2S_IM_TXTH | I2S_IM_TX_UNDERFLOW));
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
{
__HAL_I2S_DISABLE_TX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2S_TxCpltCallback(hi2s);
}
else if ((hi2s->State == HAL_I2S_STATE_BUSY_TXRX) && (hi2s->RxXferCount == 0))
{
__HAL_I2S_DISABLE_TX(hi2s);
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2S_TxRxCpltCallback(hi2s);
}
}
else
{
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TXERR);
}
}
/**
* @brief Receive an amount of data in non-blocking mode with Interrupt
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
* the configuration information for I2S module
* @retval None
*/
static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s)
{
uint32_t fifo_count = __HAL_I2S_GET_RXFIFO(hi2s);
if (fifo_count > hi2s->RxXferCount)
{
fifo_count = hi2s->RxXferCount;
}
while (fifo_count > 0)
{
(*hi2s->pRxBuffPtr) = (uint32_t)hi2s->Instance->RXDR;
hi2s->pRxBuffPtr++;
hi2s->RxXferCount--;
fifo_count--;
}
if (hi2s->RxXferCount == 0)
{
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IF_RXTH | I2S_IF_RXDONE | I2S_IF_RX_OVERFLOW));
if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
{
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2S_RxCpltCallback(hi2s);
}
else if ((hi2s->State == HAL_I2S_STATE_BUSY_TXRX) && (hi2s->TxXferCount == 0))
{
__HAL_I2S_DISABLE_TX(hi2s);
__HAL_I2S_DISABLE_RX(hi2s);
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2S_TxRxCpltCallback(hi2s);
}
}
}