Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:01

0001 /*
0002  * Copyright 2017-2020 NXP
0003  * All rights reserved.
0004  *
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_spdif.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.spdif"
0014 #endif
0015 
0016 /*******************************************************************************
0017  * Definitations
0018  ******************************************************************************/
0019 /*! @brief spdif transfer state. */
0020 enum
0021 {
0022     kSPDIF_Busy = 0x0U, /*!< SPDIF is busy */
0023     kSPDIF_Idle,        /*!< Transfer is done. */
0024     kSPDIF_Error        /*!< Transfer error occurred. */
0025 };
0026 
0027 /*! @brief Typedef for spdif tx interrupt handler. */
0028 typedef void (*spdif_isr_t)(SPDIF_Type *base, spdif_handle_t *handle);
0029 /*******************************************************************************
0030  * Prototypes
0031  ******************************************************************************/
0032 
0033 /*******************************************************************************
0034  * Variables
0035  ******************************************************************************/
0036 /* Base pointer array */
0037 static SPDIF_Type *const s_spdifBases[] = SPDIF_BASE_PTRS;
0038 /*! @brief SPDIF handle pointer */
0039 static spdif_handle_t *s_spdifHandle[ARRAY_SIZE(s_spdifBases)][2];
0040 /* IRQ number array */
0041 static const IRQn_Type s_spdifIRQ[] = SPDIF_IRQS;
0042 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0043 /* Clock name array */
0044 static const clock_ip_name_t s_spdifClock[] = SPDIF_CLOCKS;
0045 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0046 /*! @brief Pointer to IRQ handler for each instance. */
0047 static spdif_isr_t s_spdifTxIsr;
0048 /*! @brief Pointer to IRQ handler for each instance. */
0049 static spdif_isr_t s_spdifRxIsr;
0050 /*! @brief Used for spdif gain */
0051 static uint8_t s_spdif_gain[8]         = {24U, 16U, 12U, 8U, 6U, 4U, 3U, 1U};
0052 static uint8_t s_spdif_tx_watermark[4] = {16, 12, 8, 4};
0053 static uint8_t s_spdif_rx_watermark[4] = {1, 4, 8, 16};
0054 
0055 /*******************************************************************************
0056  * Code
0057  ******************************************************************************/
0058 uint32_t SPDIF_GetInstance(SPDIF_Type *base)
0059 {
0060     uint32_t instance;
0061 
0062     /* Find the instance index from base address mappings. */
0063     for (instance = 0; instance < ARRAY_SIZE(s_spdifBases); instance++)
0064     {
0065         if (s_spdifBases[instance] == base)
0066         {
0067             break;
0068         }
0069     }
0070 
0071     assert(instance < ARRAY_SIZE(s_spdifBases));
0072 
0073     return instance;
0074 }
0075 
0076 /*!
0077  * brief Initializes the SPDIF peripheral.
0078  *
0079  * Ungates the SPDIF clock, resets the module, and configures SPDIF with a configuration structure.
0080  * The configuration structure can be custom filled or set with default values by
0081  * SPDIF_GetDefaultConfig().
0082  *
0083  * note  This API should be called at the beginning of the application to use
0084  * the SPDIF driver. Otherwise, accessing the SPDIF module can cause a hard fault
0085  * because the clock is not enabled.
0086  *
0087  * param base SPDIF base pointer
0088  * param config SPDIF configuration structure.
0089  */
0090 void SPDIF_Init(SPDIF_Type *base, const spdif_config_t *config)
0091 {
0092     uint32_t val = 0;
0093 
0094 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0095     /* Enable the SPDIF clock */
0096     CLOCK_EnableClock(s_spdifClock[SPDIF_GetInstance(base)]);
0097 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0098 
0099     /* Reset the internal logic */
0100     base->SCR |= SPDIF_SCR_SOFT_RESET_MASK;
0101 
0102     /* Waiting for reset finish */
0103     while ((base->SCR & SPDIF_SCR_SOFT_RESET_MASK) != 0x00U)
0104     {
0105     }
0106 
0107     /* Setting the SPDIF settings */
0108     base->SCR = SPDIF_SCR_RXFIFOFULL_SEL(config->rxFullSelect) | SPDIF_SCR_RXAUTOSYNC(config->isRxAutoSync) |
0109                 SPDIF_SCR_TXAUTOSYNC(config->isRxAutoSync) | SPDIF_SCR_TXFIFOEMPTY_SEL(config->txFullSelect) |
0110                 SPDIF_SCR_TXFIFO_CTRL(1U) | SPDIF_SCR_VALCTRL(config->validityConfig) |
0111                 SPDIF_SCR_TXSEL(config->txSource) | SPDIF_SCR_USRC_SEL(config->uChannelSrc);
0112 
0113     /* Set DPLL clock source */
0114     base->SRPC = SPDIF_SRPC_CLKSRC_SEL(config->DPLLClkSource) | SPDIF_SRPC_GAINSEL(config->gain);
0115 
0116     /* Set SPDIF tx clock source */
0117     val = base->STC & ~SPDIF_STC_TXCLK_SOURCE_MASK;
0118     val |= SPDIF_STC_TXCLK_SOURCE(config->txClkSource);
0119     base->STC = val;
0120 
0121     /* clear and diable all the interrupt */
0122     base->SIC = (uint32_t)kSPDIF_AllInterrupt;
0123     base->SIE &= ~(uint32_t)kSPDIF_AllInterrupt;
0124 }
0125 
0126 /*!
0127  * brief De-initializes the SPDIF peripheral.
0128  *
0129  * This API gates the SPDIF clock. The SPDIF module can't operate unless SPDIF_Init is called to enable the clock.
0130  *
0131  * param base SPDIF base pointer
0132  */
0133 void SPDIF_Deinit(SPDIF_Type *base)
0134 {
0135     SPDIF_TxEnable(base, false);
0136     SPDIF_RxEnable(base, false);
0137 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0138     CLOCK_DisableClock(s_spdifClock[SPDIF_GetInstance(base)]);
0139 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0140 }
0141 
0142 /*!
0143  * brief  Sets the SPDIF configuration structure to default values.
0144  *
0145  * This API initializes the configuration structure for use in SPDIF_Init.
0146  * The initialized structure can remain unchanged in SPDIF_Init, or it can be modified
0147  *  before calling SPDIF_Init.
0148  * This is an example.
0149    code
0150    spdif_config_t config;
0151    SPDIF_GetDefaultConfig(&config);
0152    endcode
0153  *
0154  * param config pointer to master configuration structure
0155  */
0156 void SPDIF_GetDefaultConfig(spdif_config_t *config)
0157 {
0158     /* Initializes the configure structure to zero. */
0159     (void)memset(config, 0, sizeof(*config));
0160 
0161     config->isTxAutoSync   = true;
0162     config->isRxAutoSync   = true;
0163     config->DPLLClkSource  = 1;
0164     config->txClkSource    = 1;
0165     config->rxFullSelect   = kSPDIF_RxFull8Samples;
0166     config->txFullSelect   = kSPDIF_TxEmpty8Samples;
0167     config->uChannelSrc    = kSPDIF_UChannelFromTx;
0168     config->txSource       = kSPDIF_txNormal;
0169     config->validityConfig = kSPDIF_validityFlagAlwaysClear;
0170     config->gain           = kSPDIF_GAIN_8;
0171 }
0172 
0173 /*!
0174  * brief Enables/disables the SPDIF Tx.
0175  *
0176  * param base SPDIF base pointer
0177  * param enable True means enable SPDIF Tx, false means disable.
0178  */
0179 void SPDIF_TxEnable(SPDIF_Type *base, bool enable)
0180 {
0181     uint32_t val = 0;
0182 
0183     if (enable)
0184     {
0185         /* Open Tx FIFO */
0186         val = base->SCR & (~SPDIF_SCR_TXFIFO_CTRL_MASK);
0187         val |= SPDIF_SCR_TXFIFO_CTRL(1U);
0188         base->SCR = val;
0189         /* Enable transfer clock */
0190         base->STC |= SPDIF_STC_TX_ALL_CLK_EN_MASK;
0191     }
0192     else
0193     {
0194         base->SCR &= ~(SPDIF_SCR_TXFIFO_CTRL_MASK | SPDIF_SCR_TXSEL_MASK);
0195         /* Disable transfer clock */
0196         base->STC &= ~SPDIF_STC_TX_ALL_CLK_EN_MASK;
0197     }
0198 }
0199 
0200 /*!
0201  * brief Configures the SPDIF Tx sample rate.
0202  *
0203  * The audio format can be changed at run-time. This function configures the sample rate.
0204  *
0205  * param base SPDIF base pointer.
0206  * param sampleRate_Hz SPDIF sample rate frequency in Hz.
0207  * param sourceClockFreq_Hz SPDIF tx clock source frequency in Hz.
0208  */
0209 void SPDIF_TxSetSampleRate(SPDIF_Type *base, uint32_t sampleRate_Hz, uint32_t sourceClockFreq_Hz)
0210 {
0211     uint32_t clkDiv     = sourceClockFreq_Hz / (sampleRate_Hz * 64U);
0212     uint32_t mod        = sourceClockFreq_Hz % (sampleRate_Hz * 64U);
0213     uint32_t val        = 0;
0214     uint8_t clockSource = (uint8_t)(((base->STC) & SPDIF_STC_TXCLK_SOURCE_MASK) >> SPDIF_STC_TXCLK_SOURCE_SHIFT);
0215 
0216     /* Compute the nearest divider */
0217     if (mod > ((sampleRate_Hz * 64U) / 2U))
0218     {
0219         clkDiv += 1U;
0220     }
0221 
0222     /* If use divided systeme clock */
0223     if (clockSource == 5U)
0224     {
0225         if (clkDiv > 256U)
0226         {
0227             val = base->STC & (~(SPDIF_STC_TXCLK_DF_MASK | SPDIF_STC_SYSCLK_DF_MASK));
0228             val |= SPDIF_STC_SYSCLK_DF((clkDiv / 128U) - 1U) | SPDIF_STC_TXCLK_DF(127U);
0229             base->STC = val;
0230         }
0231         else
0232         {
0233             val = base->STC & (~(SPDIF_STC_TXCLK_DF_MASK | SPDIF_STC_SYSCLK_DF_MASK));
0234             val |= SPDIF_STC_SYSCLK_DF(1U) | SPDIF_STC_TXCLK_DF(clkDiv - 1U);
0235             base->STC = val;
0236         }
0237     }
0238     else
0239     {
0240         /* Other clock only uses txclk div */
0241         val = base->STC & (~(SPDIF_STC_TXCLK_DF_MASK | SPDIF_STC_SYSCLK_DF_MASK));
0242         val |= SPDIF_STC_TXCLK_DF(clkDiv - 1U);
0243         base->STC = val;
0244     }
0245 }
0246 
0247 /*!
0248  * brief Configures the SPDIF Rx audio format.
0249  *
0250  * The audio format can be changed at run-time. This function configures the sample rate and audio data
0251  * format to be transferred.
0252  *
0253  * param base SPDIF base pointer.
0254  * param clockSourceFreq_Hz SPDIF system clock frequency in hz.
0255  */
0256 uint32_t SPDIF_GetRxSampleRate(SPDIF_Type *base, uint32_t clockSourceFreq_Hz)
0257 {
0258     uint64_t gain       = s_spdif_gain[((base->SRPC & SPDIF_SRPC_GAINSEL_MASK) >> SPDIF_SRPC_GAINSEL_SHIFT)];
0259     uint32_t measure    = 0;
0260     uint32_t sampleRate = 0;
0261     uint64_t temp       = 0;
0262 
0263     /* Wait the DPLL locked */
0264     while ((base->SRPC & SPDIF_SRPC_LOCK_MASK) == 0U)
0265     {
0266     }
0267 
0268     /* Get the measure value */
0269     measure = base->SRFM;
0270     temp    = (uint64_t)measure * (uint64_t)clockSourceFreq_Hz;
0271     temp /= 1024U * 1024U * 128U * gain;
0272     sampleRate = (uint32_t)temp;
0273 
0274     return sampleRate;
0275 }
0276 
0277 /*!
0278  * brief Sends data using a blocking method.
0279  *
0280  * note This function blocks by polling until data is ready to be sent.
0281  *
0282  * param base SPDIF base pointer.
0283  * param buffer Pointer to the data to be written.
0284  * param size Bytes to be written.
0285  */
0286 void SPDIF_WriteBlocking(SPDIF_Type *base, uint8_t *buffer, uint32_t size)
0287 {
0288     assert(buffer != NULL);
0289     assert((size % 6U) == 0U);
0290 
0291     uint32_t i = 0, j = 0, data = 0;
0292 
0293     while (i < size)
0294     {
0295         /* Wait until it can write data */
0296         while ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_TxFIFOEmpty) == 0x00U)
0297         {
0298         }
0299 
0300         /* Write left channel data */
0301         for (j = 0; j < 3U; j++)
0302         {
0303             data |= ((uint32_t)(*buffer) << (j * 8U));
0304             buffer++;
0305         }
0306         SPDIF_WriteLeftData(base, data);
0307 
0308         /* Write right channel data */
0309         data = 0;
0310         for (j = 0; j < 3U; j++)
0311         {
0312             data |= ((uint32_t)(*buffer) << (j * 8U));
0313             buffer++;
0314         }
0315         SPDIF_WriteRightData(base, data);
0316 
0317         i += 6U;
0318     }
0319 }
0320 
0321 /*!
0322  * brief Receives data using a blocking method.
0323  *
0324  * note This function blocks by polling until data is ready to be sent.
0325  *
0326  * param base SPDIF base pointer.
0327  * param buffer Pointer to the data to be read.
0328  * param size Bytes to be read.
0329  */
0330 void SPDIF_ReadBlocking(SPDIF_Type *base, uint8_t *buffer, uint32_t size)
0331 {
0332     assert(buffer != NULL);
0333     assert((size % 6U) == 0U);
0334 
0335     uint32_t i = 0, j = 0, data = 0;
0336 
0337     while (i < size)
0338     {
0339         /* Wait until it can write data */
0340         while ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxFIFOFull) == 0x00U)
0341         {
0342         }
0343 
0344         /* Write left channel data */
0345         data = SPDIF_ReadLeftData(base);
0346         for (j = 0; j < 3U; j++)
0347         {
0348             *buffer = ((uint8_t)(data >> (j * 8U)) & 0xFFU);
0349             buffer++;
0350         }
0351 
0352         /* Write right channel data */
0353         data = SPDIF_ReadRightData(base);
0354         for (j = 0; j < 3U; j++)
0355         {
0356             *buffer = ((uint8_t)(data >> (j * 8U)) & 0xFFU);
0357             buffer++;
0358         }
0359 
0360         i += 6U;
0361     }
0362 }
0363 
0364 /*!
0365  * brief Initializes the SPDIF Tx handle.
0366  *
0367  * This function initializes the Tx handle for the SPDIF Tx transactional APIs. Call
0368  * this function once to get the handle initialized.
0369  *
0370  * param base SPDIF base pointer
0371  * param handle SPDIF handle pointer.
0372  * param callback Pointer to the user callback function.
0373  * param userData User parameter passed to the callback function
0374  */
0375 void SPDIF_TransferTxCreateHandle(SPDIF_Type *base,
0376                                   spdif_handle_t *handle,
0377                                   spdif_transfer_callback_t callback,
0378                                   void *userData)
0379 {
0380     assert(handle != NULL);
0381 
0382     /* Zero the handle */
0383     (void)memset(handle, 0, sizeof(*handle));
0384 
0385     s_spdifHandle[SPDIF_GetInstance(base)][0] = handle;
0386 
0387     handle->callback = callback;
0388     handle->userData = userData;
0389     handle->watermark =
0390         s_spdif_tx_watermark[(base->SCR & SPDIF_SCR_TXFIFOEMPTY_SEL_MASK) >> SPDIF_SCR_TXFIFOEMPTY_SEL_SHIFT];
0391 
0392     /* Set the isr pointer */
0393     s_spdifTxIsr = SPDIF_TransferTxHandleIRQ;
0394 
0395     /* Enable Tx irq */
0396     (void)EnableIRQ(s_spdifIRQ[SPDIF_GetInstance(base)]);
0397 }
0398 
0399 /*!
0400  * brief Initializes the SPDIF Rx handle.
0401  *
0402  * This function initializes the Rx handle for the SPDIF Rx transactional APIs. Call
0403  * this function once to get the handle initialized.
0404  *
0405  * param base SPDIF base pointer.
0406  * param handle SPDIF handle pointer.
0407  * param callback Pointer to the user callback function.
0408  * param userData User parameter passed to the callback function.
0409  */
0410 void SPDIF_TransferRxCreateHandle(SPDIF_Type *base,
0411                                   spdif_handle_t *handle,
0412                                   spdif_transfer_callback_t callback,
0413                                   void *userData)
0414 {
0415     assert(handle != NULL);
0416 
0417     /* Zero the handle */
0418     (void)memset(handle, 0, sizeof(*handle));
0419 
0420     s_spdifHandle[SPDIF_GetInstance(base)][1] = handle;
0421 
0422     handle->callback = callback;
0423     handle->userData = userData;
0424     handle->watermark =
0425         s_spdif_rx_watermark[(base->SCR & SPDIF_SCR_RXFIFOFULL_SEL_MASK) >> SPDIF_SCR_RXFIFOFULL_SEL_SHIFT];
0426 
0427     /* Set the isr pointer */
0428     s_spdifRxIsr = SPDIF_TransferRxHandleIRQ;
0429 
0430     /* Enable Rx irq */
0431     (void)EnableIRQ(s_spdifIRQ[SPDIF_GetInstance(base)]);
0432 }
0433 
0434 /*!
0435  * brief Performs an interrupt non-blocking send transfer on SPDIF.
0436  *
0437  * note This API returns immediately after the transfer initiates.
0438  * Call the SPDIF_TxGetTransferStatusIRQ to poll the transfer status and check whether
0439  * the transfer is finished. If the return status is not kStatus_SPDIF_Busy, the transfer
0440  * is finished.
0441  *
0442  * param base SPDIF base pointer.
0443  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
0444  * param xfer Pointer to the spdif_transfer_t structure.
0445  * retval kStatus_Success Successfully started the data receive.
0446  * retval kStatus_SPDIF_TxBusy Previous receive still not finished.
0447  * retval kStatus_InvalidArgument The input parameter is invalid.
0448  */
0449 status_t SPDIF_TransferSendNonBlocking(SPDIF_Type *base, spdif_handle_t *handle, spdif_transfer_t *xfer)
0450 {
0451     assert(handle != NULL);
0452 
0453     /* Check if the queue is full */
0454     if (handle->spdifQueue[handle->queueUser].data != NULL)
0455     {
0456         return kStatus_SPDIF_QueueFull;
0457     }
0458 
0459     /* Add into queue */
0460     handle->transferSize[handle->queueUser]        = xfer->dataSize;
0461     handle->spdifQueue[handle->queueUser].data     = xfer->data;
0462     handle->spdifQueue[handle->queueUser].dataSize = xfer->dataSize;
0463     handle->queueUser                              = (handle->queueUser + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0464 
0465     /* Set the state to busy */
0466     handle->state = kSPDIF_Busy;
0467 
0468     /* Enable interrupt */
0469     SPDIF_EnableInterrupts(base, kSPDIF_TxFIFOEmpty);
0470 
0471     /* Enable Tx transfer */
0472     SPDIF_TxEnable(base, true);
0473 
0474     return kStatus_Success;
0475 }
0476 
0477 /*!
0478  * brief Performs an interrupt non-blocking receive transfer on SPDIF.
0479  *
0480  * note This API returns immediately after the transfer initiates.
0481  * Call the SPDIF_RxGetTransferStatusIRQ to poll the transfer status and check whether
0482  * the transfer is finished. If the return status is not kStatus_SPDIF_Busy, the transfer
0483  * is finished.
0484  *
0485  * param base SPDIF base pointer
0486  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
0487  * param xfer Pointer to the spdif_transfer_t structure.
0488  * retval kStatus_Success Successfully started the data receive.
0489  * retval kStatus_SPDIF_RxBusy Previous receive still not finished.
0490  * retval kStatus_InvalidArgument The input parameter is invalid.
0491  */
0492 status_t SPDIF_TransferReceiveNonBlocking(SPDIF_Type *base, spdif_handle_t *handle, spdif_transfer_t *xfer)
0493 {
0494     assert(handle != NULL);
0495 
0496     uint32_t enableInterrupts = (uint32_t)kSPDIF_RxFIFOFull | (uint32_t)kSPDIF_RxControlChannelChange;
0497 
0498     /* Check if the queue is full */
0499     if (handle->spdifQueue[handle->queueUser].data != NULL)
0500     {
0501         return kStatus_SPDIF_QueueFull;
0502     }
0503 
0504     /* Add into queue */
0505     handle->transferSize[handle->queueUser]        = xfer->dataSize;
0506     handle->spdifQueue[handle->queueUser].data     = xfer->data;
0507     handle->spdifQueue[handle->queueUser].dataSize = xfer->dataSize;
0508     handle->spdifQueue[handle->queueUser].udata    = xfer->udata;
0509     handle->spdifQueue[handle->queueUser].qdata    = xfer->qdata;
0510     handle->queueUser                              = (handle->queueUser + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0511 
0512     /* Set state to busy */
0513     handle->state = kSPDIF_Busy;
0514 
0515     if (xfer->qdata != NULL)
0516     {
0517         enableInterrupts |= (uint32_t)kSPDIF_QChannelReceiveRegisterFull;
0518     }
0519 
0520     if (xfer->udata != NULL)
0521     {
0522         enableInterrupts |= (uint32_t)kSPDIF_UChannelReceiveRegisterFull;
0523     }
0524 
0525     /* Enable interrupt */
0526     SPDIF_EnableInterrupts(base, enableInterrupts);
0527 
0528     /* Enable Rx transfer */
0529     SPDIF_RxEnable(base, true);
0530 
0531     return kStatus_Success;
0532 }
0533 
0534 /*!
0535  * brief Gets a set byte count.
0536  *
0537  * param base SPDIF base pointer.
0538  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
0539  * param count Bytes count sent.
0540  * retval kStatus_Success Succeed get the transfer count.
0541  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
0542  */
0543 status_t SPDIF_TransferGetSendCount(SPDIF_Type *base, spdif_handle_t *handle, size_t *count)
0544 {
0545     assert(handle != NULL);
0546 
0547     status_t status     = kStatus_Success;
0548     uint8_t queueDriver = handle->queueDriver;
0549 
0550     if (handle->state != (uint32_t)kSPDIF_Busy)
0551     {
0552         status = kStatus_NoTransferInProgress;
0553     }
0554     else
0555     {
0556         *count = (handle->transferSize[queueDriver] - handle->spdifQueue[queueDriver].dataSize);
0557     }
0558 
0559     return status;
0560 }
0561 
0562 /*!
0563  * brief Gets a received byte count.
0564  *
0565  * param base SPDIF base pointer.
0566  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
0567  * param count Bytes count received.
0568  * retval kStatus_Success Succeed get the transfer count.
0569  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
0570  */
0571 status_t SPDIF_TransferGetReceiveCount(SPDIF_Type *base, spdif_handle_t *handle, size_t *count)
0572 {
0573     assert(handle != NULL);
0574 
0575     status_t status     = kStatus_Success;
0576     uint8_t queueDriver = handle->queueDriver;
0577 
0578     if (handle->state != (uint32_t)kSPDIF_Busy)
0579     {
0580         status = kStatus_NoTransferInProgress;
0581     }
0582     else
0583     {
0584         *count = (handle->transferSize[queueDriver] - handle->spdifQueue[queueDriver].dataSize);
0585     }
0586 
0587     return status;
0588 }
0589 
0590 /*!
0591  * brief Aborts the current send.
0592  *
0593  * note This API can be called any time when an interrupt non-blocking transfer initiates
0594  * to abort the transfer early.
0595  *
0596  * param base SPDIF base pointer.
0597  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
0598  */
0599 void SPDIF_TransferAbortSend(SPDIF_Type *base, spdif_handle_t *handle)
0600 {
0601     assert(handle != NULL);
0602 
0603     /* Use FIFO request interrupt and fifo error */
0604     SPDIF_DisableInterrupts(base, kSPDIF_TxFIFOEmpty);
0605 
0606     handle->state = kSPDIF_Idle;
0607 
0608     /* Clear the queue */
0609     (void)memset(handle->spdifQueue, 0, sizeof(spdif_transfer_t) * SPDIF_XFER_QUEUE_SIZE);
0610     handle->queueDriver = 0;
0611     handle->queueUser   = 0;
0612 }
0613 
0614 /*!
0615  * brief Aborts the current IRQ receive.
0616  *
0617  * note This API can be called when an interrupt non-blocking transfer initiates
0618  * to abort the transfer early.
0619  *
0620  * param base SPDIF base pointer
0621  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
0622  */
0623 void SPDIF_TransferAbortReceive(SPDIF_Type *base, spdif_handle_t *handle)
0624 {
0625     assert(handle != NULL);
0626 
0627     /* Disable interrupt */
0628     SPDIF_DisableInterrupts(base, (uint32_t)kSPDIF_UChannelReceiveRegisterFull |
0629                                       (uint32_t)kSPDIF_QChannelReceiveRegisterFull | (uint32_t)kSPDIF_RxFIFOFull |
0630                                       (uint32_t)kSPDIF_RxControlChannelChange);
0631 
0632     handle->state = kSPDIF_Idle;
0633 
0634     /* Clear the queue */
0635     (void)memset(handle->spdifQueue, 0, sizeof(spdif_transfer_t) * SPDIF_XFER_QUEUE_SIZE);
0636     handle->queueDriver = 0;
0637     handle->queueUser   = 0;
0638 }
0639 
0640 /*!
0641  * brief Tx interrupt handler.
0642  *
0643  * param base SPDIF base pointer.
0644  * param handle Pointer to the spdif_handle_t structure.
0645  */
0646 void SPDIF_TransferTxHandleIRQ(SPDIF_Type *base, spdif_handle_t *handle)
0647 {
0648     assert(handle != NULL);
0649 
0650     uint8_t *buffer  = handle->spdifQueue[handle->queueDriver].data;
0651     uint8_t dataSize = 0;
0652     uint32_t i = 0, j = 0, data = 0;
0653 
0654     /* Do Transfer */
0655     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_TxFIFOEmpty) != 0x00U) &&
0656         ((base->SIE & (uint32_t)kSPDIF_TxFIFOEmpty) != 0x00U))
0657     {
0658         dataSize = handle->watermark;
0659         while (i < dataSize)
0660         {
0661             data = 0;
0662             /* Write left channel data */
0663             for (j = 0; j < 3U; j++)
0664             {
0665                 data |= ((uint32_t)(*buffer) << (j * 8U));
0666                 buffer++;
0667             }
0668             SPDIF_WriteLeftData(base, data);
0669 
0670             /* Write right channel data */
0671             data = 0;
0672             for (j = 0; j < 3U; j++)
0673             {
0674                 data |= ((uint32_t)(*buffer) << (j * 8U));
0675                 buffer++;
0676             }
0677             SPDIF_WriteRightData(base, data);
0678 
0679             i++;
0680         }
0681         handle->spdifQueue[handle->queueDriver].dataSize -= (uint32_t)dataSize * 6U;
0682         handle->spdifQueue[handle->queueDriver].data += dataSize * 6U;
0683 
0684         /* If finished a block, call the callback function */
0685         if (handle->spdifQueue[handle->queueDriver].dataSize == 0U)
0686         {
0687             (void)memset(&handle->spdifQueue[handle->queueDriver], 0, sizeof(spdif_transfer_t));
0688             handle->queueDriver = (handle->queueDriver + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0689             if (handle->callback != NULL)
0690             {
0691                 (handle->callback)(base, handle, kStatus_SPDIF_TxIdle, handle->userData);
0692             }
0693         }
0694 
0695         /* If all data finished, just stop the transfer */
0696         if (handle->spdifQueue[handle->queueDriver].data == NULL)
0697         {
0698             SPDIF_TransferAbortSend(base, handle);
0699         }
0700     }
0701 }
0702 
0703 /*!
0704  * brief Tx interrupt handler.
0705  *
0706  * param base SPDIF base pointer.
0707  * param handle Pointer to the spdif_handle_t structure.
0708  */
0709 void SPDIF_TransferRxHandleIRQ(SPDIF_Type *base, spdif_handle_t *handle)
0710 {
0711     assert(handle != NULL);
0712 
0713     uint8_t *buffer  = NULL;
0714     uint8_t dataSize = 0;
0715     uint32_t i = 0, j = 0, data = 0;
0716 
0717     /* Handle Cnew flag */
0718     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxControlChannelChange) != 0x00U)
0719     {
0720         /* Clear the interrupt flag */
0721         SPDIF_ClearStatusFlags(base, SPDIF_SIE_CNEW_MASK);
0722         if (handle->callback != NULL)
0723         {
0724             (handle->callback)(base, handle, kStatus_SPDIF_RxCnew, handle->userData);
0725         }
0726     }
0727 
0728     /* Handle illegal symbol */
0729     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxIllegalSymbol) != 0x00U)
0730     {
0731         SPDIF_ClearStatusFlags(base, kSPDIF_RxIllegalSymbol);
0732         if (handle->callback != NULL)
0733         {
0734             (handle->callback)(base, handle, kStatus_SPDIF_RxIllegalSymbol, handle->userData);
0735         }
0736     }
0737 
0738     /* Handle Parity Bit Error */
0739     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxParityBitError) != 0x00U)
0740     {
0741         SPDIF_ClearStatusFlags(base, kSPDIF_RxParityBitError);
0742         if (handle->callback != NULL)
0743         {
0744             (handle->callback)(base, handle, kStatus_SPDIF_RxParityBitError, handle->userData);
0745         }
0746     }
0747 
0748     /* Handle DPlocked */
0749     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxDPLLLocked) != 0x00U)
0750     {
0751         SPDIF_ClearStatusFlags(base, kSPDIF_RxDPLLLocked);
0752         if (handle->callback != NULL)
0753         {
0754             (handle->callback)(base, handle, kStatus_SPDIF_RxDPLLLocked, handle->userData);
0755         }
0756     }
0757 
0758     /* Handle Q channel full flag */
0759     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_QChannelReceiveRegisterFull) != 0x00U) &&
0760         ((base->SIE & (uint32_t)kSPDIF_QChannelReceiveRegisterFull) != 0x00U))
0761     {
0762         buffer = handle->spdifQueue[handle->queueDriver].qdata;
0763         if (buffer != NULL)
0764         {
0765             data      = SPDIF_ReadQChannel(base);
0766             buffer[0] = (uint8_t)data & 0xFFU;
0767             buffer[1] = (uint8_t)(data >> 8U) & 0xFFU;
0768             buffer[2] = (uint8_t)(data >> 16U) & 0xFFU;
0769         }
0770     }
0771 
0772     /* Handle U channel full flag */
0773     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_UChannelReceiveRegisterFull) != 0x00U) &&
0774         ((base->SIE & (uint32_t)kSPDIF_UChannelReceiveRegisterFull) != 0x00U))
0775     {
0776         buffer = handle->spdifQueue[handle->queueDriver].udata;
0777         if (buffer != NULL)
0778         {
0779             data      = SPDIF_ReadUChannel(base);
0780             buffer[0] = (uint8_t)data & 0xFFU;
0781             buffer[1] = (uint8_t)(data >> 8U) & 0xFFU;
0782             buffer[2] = (uint8_t)(data >> 16U) & 0xFFU;
0783         }
0784     }
0785 
0786     /* Handle audio data transfer */
0787     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxFIFOFull) != 0x00U) &&
0788         ((base->SIE & (uint32_t)kSPDIF_RxFIFOFull) != 0x00U))
0789     {
0790         dataSize = handle->watermark;
0791         buffer   = handle->spdifQueue[handle->queueDriver].data;
0792         while (i < dataSize)
0793         {
0794             /* Read left channel data */
0795             data = SPDIF_ReadLeftData(base);
0796             for (j = 0; j < 3U; j++)
0797             {
0798                 *buffer = (uint8_t)((data >> (j * 8U)) & 0xFFU);
0799                 buffer++;
0800             }
0801 
0802             /* Read right channel data */
0803             data = SPDIF_ReadRightData(base);
0804             for (j = 0; j < 3U; j++)
0805             {
0806                 *buffer = (uint8_t)((data >> (j * 8U)) & 0xFFU);
0807                 buffer++;
0808             }
0809 
0810             i++;
0811         }
0812         handle->spdifQueue[handle->queueDriver].dataSize -= (uint32_t)dataSize * 6U;
0813         handle->spdifQueue[handle->queueDriver].data += dataSize * 6U;
0814 
0815         /* If finished a block, call the callback function */
0816         if (handle->spdifQueue[handle->queueDriver].dataSize == 0x00U)
0817         {
0818             (void)memset(&handle->spdifQueue[handle->queueDriver], 0, sizeof(spdif_transfer_t));
0819             handle->queueDriver = (handle->queueDriver + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0820             if (handle->callback != NULL)
0821             {
0822                 (handle->callback)(base, handle, kStatus_SPDIF_RxIdle, handle->userData);
0823             }
0824         }
0825 
0826         /* If all data finished, just stop the transfer */
0827         if (handle->spdifQueue[handle->queueDriver].data == NULL)
0828         {
0829             SPDIF_TransferAbortReceive(base, handle);
0830         }
0831     }
0832 }
0833 
0834 #if defined(SPDIF)
0835 void SPDIF_DriverIRQHandler(void);
0836 void SPDIF_DriverIRQHandler(void)
0837 {
0838     if ((s_spdifHandle[0][0] != NULL) && (s_spdifTxIsr != NULL))
0839     {
0840         s_spdifTxIsr(SPDIF, s_spdifHandle[0][0]);
0841     }
0842 
0843     if ((s_spdifHandle[0][1] != NULL) && (s_spdifRxIsr != NULL))
0844     {
0845         s_spdifRxIsr(SPDIF, s_spdifHandle[0][1]);
0846     }
0847     SDK_ISR_EXIT_BARRIER;
0848 }
0849 #endif