/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved. * Use, distribution and modification of this code is permitted under the * terms stated in the Alif Semiconductor Software License Agreement * * You should have received a copy of the Alif Semiconductor Software * License Agreement with this file. If not, please write to: * contact@alifsemi.com, or visit: https://alifsemi.com/license * */ /**************************************************************************//** * @file i2s.h * @author Sudhir Sreedharan * @email sudhir@alifsemi.com * @version V1.0.0 * @date 23-05-2023 * @brief Low Level Header file for I2S * @bug None. * @Note None ******************************************************************************/ #ifndef I2S_H_ #define I2S_H_ #include #include #ifdef __cplusplus } #endif /** * @brief I2S (I2S) */ typedef struct { /*!< I2S Structure */ volatile uint32_t I2S_IER; /*!< (@ 0x00000000) I2S Enable Register */ volatile uint32_t I2S_IRER; /*!< (@ 0x00000004) I2S Receiver Block Enable Register */ volatile uint32_t I2S_ITER; /*!< (@ 0x00000008) I2S Transmitter Block Enable Register */ volatile uint32_t I2S_CER; /*!< (@ 0x0000000C) Clock Enable Register */ volatile uint32_t I2S_CCR; /*!< (@ 0x00000010) Clock Configuration Register */ volatile uint32_t I2S_RXFFR; /*!< (@ 0x00000014) Receiver Block FIFO Reset Register */ volatile uint32_t I2S_TXFFR; /*!< (@ 0x00000018) Transmitter Block FIFO Reset Register */ volatile const uint32_t RESERVED; union { volatile const uint32_t I2S_LRBR0; /*!< (@ 0x00000020) Left Receive Buffer Register 0 */ volatile uint32_t I2S_LTHR0; /*!< (@ 0x00000020) Left Transmit Holding Register 0 */ }; union { volatile const uint32_t I2S_RRBR0; /*!< (@ 0x00000024) Right Receive Buffer Register 0 */ volatile uint32_t I2S_RTHR0; /*!< (@ 0x00000024) Right Transmit Holding Register 0 */ }; volatile uint32_t I2S_RER0; /*!< (@ 0x00000028) Receive Enable Register 0 */ volatile uint32_t I2S_TER0; /*!< (@ 0x0000002C) Transmit Enable Register 0 */ volatile uint32_t I2S_RCR0; /*!< (@ 0x00000030) Receive Configuration Register 0 */ volatile uint32_t I2S_TCR0; /*!< (@ 0x00000034) Transmit Configuration Register 0 */ volatile const uint32_t I2S_ISR0; /*!< (@ 0x00000038) Interrupt Status Register 0 */ volatile uint32_t I2S_IMR0; /*!< (@ 0x0000003C) Interrupt Mask Register 0 */ volatile const uint32_t I2S_ROR0; /*!< (@ 0x00000040) Receive Overrun Register 0 */ volatile const uint32_t I2S_TOR0; /*!< (@ 0x00000044) Transmit Overrun Register 0 */ volatile uint32_t I2S_RFCR0; /*!< (@ 0x00000048) Receive FIFO Configuration Register 0 */ volatile uint32_t I2S_TFCR0; /*!< (@ 0x0000004C) Transmit FIFO Configuration Register 0 */ volatile uint32_t I2S_RFF0; /*!< (@ 0x00000050) Receive FIFO Flush Register 0 */ volatile uint32_t I2S_TFF0; /*!< (@ 0x00000054) Transmit FIFO Flush Register 0 */ volatile const uint32_t RESERVED1[90]; volatile const uint32_t I2S_RXDMA; /*!< (@ 0x000001C0) Receiver Block DMA Register */ volatile const uint32_t RESERVED2; volatile uint32_t I2S_TXDMA; /*!< (@ 0x000001C8) Transmitter Block DMA Register */ volatile const uint32_t RESERVED3[9]; volatile const uint32_t I2S_COMP_PARAM_2; /*!< (@ 0x000001F0) Module Configuration Register 2 */ volatile const uint32_t I2S_COMP_PARAM_1; /*!< (@ 0x000001F4) Module Configuration Register 1 */ volatile const uint32_t I2S_COMP_VERSION; /*!< (@ 0x000001F8) Reserved */ volatile const uint32_t I2S_COMP_TYPE; /*!< (@ 0x000001FC) Reserved */ volatile uint32_t I2S_DMACR; /*!< (@ 0x00000200) DMA Control Register */ } I2S_Type; /*!< Size = 516 (0x204) */ /*!< Number of bytes for 16/32bit resolution*/ #define I2S_16BIT_BUF_TYPE_BYTES 2 #define I2S_32BIT_BUF_TYPE_BYTES 4 /*!< Max Audio Resolution for Tx/Rx Channel */ #define I2S_RX_WORDSIZE_MAX 32 #define I2S_TX_WORDSIZE_MAX 32 /*!< FIFO Depth for Tx & Rx */ #define I2S_FIFO_DEPTH 16 #define I2S_FIFO_TRIGGER_LEVEL_MAX 15 /* Register fields and masks */ /* I2S IER.IEN: Global Enable */ #define I2S_IER_IEN 0x1U /* I2S IRER.RXEN: RX block Enable */ #define I2S_IRER_RXEN 0x1U /* I2S ITER.TXEN: TX block Enable */ #define I2S_ITER_TXEN 0x1U /* I2S CER.CLKEN: Clock Enable */ #define I2S_CER_CLKEN 0x1U /* I2S CCR.SCLKG: Clock Gating */ #define I2S_CCR_SCLKG_Pos 0U #define I2S_CCR_SCLKG_Msk (0x7U << I2S_CCR_SCLKG_Pos) /* I2S CCR.WSS: Word Select length */ #define I2S_CCR_WSS_Pos 3U #define I2S_CCR_WSS_Msk (0x3U << I2S_CCR_WSS_Pos) /* I2S RXFFR.RXFFR: Rx Block FIFO Reset */ #define I2S_RXFFR_RXFFR 0x1U /* I2S TXFFR.TXFFR: Tx Block FIFO Reset */ #define I2S_TXFFR_TXFFR 0x1U /* I2S RER.RXCHEN: Rx Channel Enable */ #define I2S_RER_RXCHEN 0x1U /* I2S TER.TXCHEN: Tx Channel Enable */ #define I2S_TER_TXCHEN 0x1U /* I2S RCR.WLEN: Data Resolution of Rx */ #define I2S_RCR_WLEN_Pos 0U #define I2S_RCR_WLEN_Msk (0x7U << I2S_RCR_WLEN_Pos) /* I2S TCR.WLEN: Data Resolution of Tx */ #define I2S_TCR_WLEN_Pos 0U #define I2S_TCR_WLEN_Msk (0x7U << I2S_TCR_WLEN_Pos) /* I2S ISR.RXDA: Status of Rx Data Available interrupt */ #define I2S_ISR_RXDA 0x1U /* I2S ISR.RXFO: Status of Data Overrun interrupt of Rx */ #define I2S_ISR_RXFO (0x1U << 1) /* I2S ISR.TXFE: Status of Tx Empty Trigger Interrupt */ #define I2S_ISR_TXFE (0x1U << 4) /* I2S ISR.TXFO: Status of Data Overrun Interrupt for Tx */ #define I2S_ISR_TXFO (0x1U << 5) /* I2S IMR.RXDAM: Mask Rx Data Available interrupt */ #define I2S_IMR_RXDAM 0x1U /* I2S IMR.RXFOM: Mask Data Overrun interrupt of Rx */ #define I2S_IMR_RXFOM (0x1U << 1) /* I2S IMR.TXFEM: Mask Tx Empty Interrupt */ #define I2S_IMR_TXFEM (0x1U << 4) /* I2S IMR.TXFOM: Mask Data Overrun Interrupt for Tx */ #define I2S_IMR_TXFOM (0x1U << 5) /* I2S ROR.RXCHO: Clear Rx Data Overrun interrupt */ #define I2S_ROR_RXCHO 0x1U /* I2S TOR.TXCHO: Clear Tx Data Overrun interrupt */ #define I2S_TOR_TXCHO 0x1U /* I2S RFCR.RXCHDT: Rx FIFO Trigger Level */ #define I2S_RFCR_RXCHDT_Pos 0U #define I2S_RFCR_RXCHDT_Msk (0xFU << I2S_RFCR_RXCHDT_Pos) /* I2S TFCR.TXCHET: Tx FIFO Trigger Level */ #define I2S_TFCR_TXCHET_Pos 0U #define I2S_TFCR_TXCHET_Msk (0xFU << I2S_TFCR_TXCHET_Pos) /* I2S RFF.RXCHFR: Rx Channel FIFO Reset */ #define I2S_RFF_RXCHFR_Msk 0x1U /* I2S TFF.TXCHFR: Tx Channel FIFO Reset */ #define I2S_TFF_TXCHFR_Msk 0x1U /* I2S DMACR.DMAEN_RXBLOCK: DMA Enable for Rx Block */ #define I2S_DMACR_DMAEN_RXBLOCK (0x1U << 16) /* I2S DMACR.DMAEN_TXBLOCK: DMA Enable for Tx Block */ #define I2S_DMACR_DMAEN_TXBLOCK (0x1U << 17) /* I2S DMA TX and RX register offset */ #define I2S_RXDMA_OFFSET (0x1C0) #define I2S_TXDMA_OFFSET (0x1C8) /** * enum I2S_WSS * I2S Word Select Size */ typedef enum _I2S_WSS { I2S_WSS_SCLK_CYCLES_16, /*!< 16 sclk cycles */ I2S_WSS_SCLK_CYCLES_24, /*!< 24 sclk cycles */ I2S_WSS_SCLK_CYCLES_32, /*!< 32 sclk cycles */ I2S_WSS_SCLK_CYCLES_MAX } I2S_WSS; /** * enum I2S_SCLKG * I2S Serial Clock gating */ typedef enum _I2S_SCLKG { I2S_SCLKG_NONE, /*!< Gating is disabled */ I2S_SCLKG_CLOCK_CYCLES_12, /*!< Gating after 12 sclk cycles */ I2S_SCLKG_CLOCK_CYCLES_16, /*!< Gating after 16 sclk cycles */ I2S_SCLKG_CLOCK_CYCLES_20, /*!< Gating after 20 sclk cycles */ I2S_SCLKG_CLOCK_CYCLES_24, /*!< Gating after 24 sclk cycles */ I2S_SCLKG_CLOCK_CYCLES_MAX } I2S_SCLKG; /** * enum I2S_WLEN * I2S Word length. Specifies the data resolution of the receiver. */ typedef enum _I2S_WLEN { I2S_WLEN_RES_NONE, /*!< Word length ignored */ I2S_WLEN_RES_12_BIT, /*!< 12 bit Data Resolution */ I2S_WLEN_RES_16_BIT, /*!< 16 bit Data Resolution */ I2S_WLEN_RES_20_BIT, /*!< 20 bit Data Resolution */ I2S_WLEN_RES_24_BIT, /*!< 24 bit Data Resolution */ I2S_WLEN_RES_32_BIT, /*!< 32 bit Data Resolution */ } I2S_WLEN; /** * enum I2S_TRANSFER_STATUS. * Status of an ongoing I2S transfer. */ typedef enum _I2S_TRANSFER_STATUS { I2S_TRANSFER_STATUS_NONE = (0U), /**< Transfer status none */ I2S_TRANSFER_STATUS_TX_COMPLETE = (1U << 0), /**< TX Transfer status complete */ I2S_TRANSFER_STATUS_RX_COMPLETE = (1U << 1), /**< RX Transfer status complete */ I2S_TRANSFER_STATUS_RX_OVERFLOW = (1U << 2), /**< Transfer status Rx overflow */ I2S_TRANSFER_STATUS_TX_OVERFLOW = (1U << 3) /**< Transfer status Rx overflow */ } I2S_TRANSFER_STATUS; typedef struct _i2s_transfer_t { volatile uint32_t tx_current_cnt; /**< Current Tx Transfer count */ volatile uint32_t rx_current_cnt; /**< Current Rx Transfer count */ uint32_t tx_total_cnt; /**< Tx Total count to transfer */ uint32_t rx_total_cnt; /**< Rx Total count to transfer */ const void *tx_buff; /**< Pointer to TX buffer */ void *rx_buff; /**< Pointer to Rx buffer */ volatile uint32_t status; /**< I2S_TRANSFER_STATUS Transfer status */ bool mono_mode; /**< Mono mode enable status */ } i2s_transfer_t; /** \fn void i2s_enable(I2S_Type *i2s) \brief Enable I2S \param[in] i2s Pointer to I2S register map */ static inline void i2s_enable(I2S_Type *i2s) { i2s->I2S_IER = I2S_IER_IEN; } /** \fn void i2s_disable(I2S_Type *i2s) \brief Disable I2S \param[in] i2s Pointer to I2S register map */ static inline void i2s_disable(I2S_Type *i2s) { i2s->I2S_IER &= ~I2S_IER_IEN; } /** \fn void i2s_rxblock_enable(I2S_Type *i2s) \brief Enable I2S Receiver Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_rxblock_enable(I2S_Type *i2s) { i2s->I2S_IRER = I2S_IRER_RXEN; } /** \fn void i2s_rxblock_disable(I2S_Type *i2s) \brief Disable I2S Receiver Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_rxblock_disable(I2S_Type *i2s) { i2s->I2S_IRER &= ~I2S_IRER_RXEN; } /** \fn void i2s_txblock_enable(I2S_Type *i2s) \brief Enable I2S Transmitter Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_txblock_enable(I2S_Type *i2s) { i2s->I2S_ITER = I2S_ITER_TXEN; } /** \fn void i2s_txblock_disable(I2S_Type *i2s) \brief Disable I2S Transmitter Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_txblock_disable(I2S_Type *i2s) { i2s->I2S_ITER &= ~I2S_ITER_TXEN; } /** \fn void i2s_clock_enable(I2S_Type *i2s) I2S_SCLKG sclkg, I2S_WSS wss_len) \brief Enable Clock in Master Mode. \param[in] i2s Pointer to I2S register map \param[in] sclkg sclk gating value \param[in] wss_len word select length */ static inline void i2s_clock_enable(I2S_Type *i2s, I2S_SCLKG sclkg, I2S_WSS wss_len) { i2s->I2S_CCR = (((sclkg << I2S_CCR_SCLKG_Pos) & I2S_CCR_SCLKG_Msk) | ((wss_len << I2S_CCR_WSS_Pos) & I2S_CCR_WSS_Msk)); i2s->I2S_CER = I2S_CER_CLKEN; } /** \fn void i2s_clock_disable(I2S_Type *i2s) \brief Disable I2S Clock in Master Mode \param[in] i2s Pointer to I2S register map */ static inline void i2s_clock_disable(I2S_Type *i2s) { i2s->I2S_CER &= ~I2S_CER_CLKEN; } /** \fn void i2s_rxchannel_enable(I2S_Type *i2s) \brief Enable I2S Receiver Channel \param[in] i2s Pointer to I2S register map */ static inline void i2s_rxchannel_enable(I2S_Type *i2s) { i2s->I2S_RER0 = I2S_RER_RXCHEN; } /** \fn void i2s_rxchannel_disable(I2S_Type *i2s) \brief Disable I2S Receiver Channel \param[in] i2s Pointer to I2S register map */ static inline void i2s_rxchannel_disable(I2S_Type *i2s) { i2s->I2S_RER0 &= ~I2S_RER_RXCHEN; } /** \fn void i2s_txchannel_enable(I2S_Type *i2s) \brief Enable I2S Transmit Channel \param[in] i2s Pointer to I2S register map */ static inline void i2s_txchannel_enable(I2S_Type *i2s) { i2s->I2S_TER0 = I2S_TER_TXCHEN; } /** \fn void i2s_txchannel_disable(I2S_Type *i2s) \brief Disable I2S Transmit Channel \param[in] i2s Pointer to I2S register map */ static inline void i2s_txchannel_disable(I2S_Type *i2s) { i2s->I2S_TER0 &= ~I2S_TER_TXCHEN; } /** \fn void i2s_set_rx_wlen(I2S_Type *i2s, I2S_WLEN wlen) \brief Set Wlen in Receive Configuration Register Should be called with RXCHEN disabled. \param[in] i2s Pointer to I2S register map \param[in] wlen word length */ static inline void i2s_set_rx_wlen(I2S_Type *i2s, I2S_WLEN wlen) { i2s->I2S_RCR0 = (wlen << I2S_RCR_WLEN_Pos) & I2S_RCR_WLEN_Msk; } /** \fn void i2s_set_tx_wlen(I2S_Type *i2s, I2S_WLEN wlen) \brief Set Wlen in Transmit Configuration Register Should be called with TXCHEN disabled. \param[in] i2s Pointer to I2S register map \param[in] wlen word length */ static inline void i2s_set_tx_wlen(I2S_Type *i2s, I2S_WLEN wlen) { i2s->I2S_TCR0 = (wlen << I2S_TCR_WLEN_Pos) & I2S_TCR_WLEN_Msk; } /** \fn void i2s_clear_rx_overrun(I2S_Type *i2s) \brief Clear Receiver FIFO Data Overrun Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_clear_rx_overrun(I2S_Type *i2s) { (void) (i2s->I2S_ROR0); } /** \fn void i2s_clear_tx_overrun(I2S_Type *i2s) \brief Clear Transmit FIFO Data Overrun Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_clear_tx_overrun(I2S_Type *i2s) { (void) (i2s->I2S_TOR0); } /** \fn void i2s_set_rx_triggerLevel(I2S_Type *i2s, uint8_t trigger_level) \brief Set the Trigger Level in RxFIFO The channel must be disabled before doing this \param[in] i2s Pointer to I2S register map */ static inline void i2s_set_rx_triggerLevel(I2S_Type *i2s, uint8_t trigger_level) { i2s->I2S_RFCR0 = trigger_level; } /** \fn void i2s_set_tx_triggerLevel(I2S_Type *i2s uint8_t trigger_level) \brief Set the Trigger Level in TxFIFO The channel must be disabled before doing this \param[in] i2s Pointer to I2S register map */ static inline void i2s_set_tx_triggerLevel(I2S_Type *i2s, uint8_t trigger_level) { i2s->I2S_TFCR0 = trigger_level; } /** \fn void i2s_reset_rx_fifo(I2S_Type *i2s) \brief Reset the Rx Channel FIFO \param[in] i2s Pointer to I2S register map */ static inline void i2s_reset_rx_fifo(I2S_Type *i2s) { i2s->I2S_RFF0 = 0x1; } /** \fn void i2s_reset_tx_fifo(I2S_Type *i2s) \brief Reset the Tx Channel FIFO \param[in] i2s Pointer to I2S register map */ static inline void i2s_reset_tx_fifo(I2S_Type *i2s) { i2s->I2S_TFF0 = 0x1; } /** \fn void i2s_rx_dma_enable(I2S_Type *i2s) \brief Enable I2S Rx DMA Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_rx_dma_enable(I2S_Type *i2s) { i2s->I2S_DMACR |= I2S_DMACR_DMAEN_RXBLOCK; } /** \fn void i2s_rx_dma_disable(I2S_Type *i2s) \brief Disable I2S Rx DMA Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_rx_dma_disable(I2S_Type *i2s) { i2s->I2S_DMACR &= ~I2S_DMACR_DMAEN_RXBLOCK; } /** \fn void i2s_tx_dma_enable(I2S_Type *i2s) \brief Enable I2S Tx DMA Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_tx_dma_enable(I2S_Type *i2s) { i2s->I2S_DMACR |= I2S_DMACR_DMAEN_TXBLOCK; } /** \fn void i2s_tx_dma_disable(I2S_Type *i2s) \brief Disable I2S Tx DMA Block \param[in] i2s Pointer to I2S register map */ static inline void i2s_tx_dma_disable(I2S_Type *i2s) { i2s->I2S_DMACR &= ~I2S_DMACR_DMAEN_TXBLOCK; } /** \fn void i2s_enable_tx_interrupt(I2S_Type *i2s) \brief Enable I2S Tx Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_enable_tx_interrupt(I2S_Type *i2s) { uint32_t imr; imr = i2s->I2S_IMR0; imr &= ~(I2S_IMR_TXFEM | I2S_IMR_TXFOM); i2s->I2S_IMR0 = imr; } /** \fn void i2s_disable_tx_interrupt(I2S_Type *i2s) \brief Disable I2S Tx Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_disable_tx_interrupt(I2S_Type *i2s) { uint32_t imr; imr = i2s->I2S_IMR0; imr |= (I2S_IMR_TXFEM | I2S_IMR_TXFOM); i2s->I2S_IMR0 = imr; } /** \fn void i2s_enable_rx_interrupt(I2S_Type *i2s) \brief Enable I2S Rx Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_enable_rx_interrupt(I2S_Type *i2s) { uint32_t imr; imr = i2s->I2S_IMR0; imr &= ~(I2S_IMR_RXDAM | I2S_IMR_RXFOM); i2s->I2S_IMR0 = imr; } /** \fn void i2s_disable_rx_interrupt(I2S_Type *i2s) \brief Disable I2S Rx Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_disable_rx_interrupt(I2S_Type *i2s) { uint32_t imr; imr = i2s->I2S_IMR0; imr |= (I2S_IMR_RXDAM | I2S_IMR_RXFOM); i2s->I2S_IMR0 = imr; } /** \fn void i2s_enable_rx_overflow_interrupt(I2S_Type *i2s) \brief Enable I2S Rx Overflow Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_enable_rx_overflow_interrupt(I2S_Type *i2s) { uint32_t imr; imr = i2s->I2S_IMR0; imr &= ~I2S_IMR_RXFOM; i2s->I2S_IMR0 = imr; } /** \fn void i2s_disable_rx_overflow_interrupt(I2S_Type *i2s) \brief Disable I2S Rx Overflow Interrupt \param[in] i2s Pointer to I2S register map */ static inline void i2s_disable_rx_overflow_interrupt(I2S_Type *i2s) { uint32_t imr; imr = i2s->I2S_IMR0; imr |= I2S_IMR_RXFOM; i2s->I2S_IMR0 = imr; } /** \fn void* i2s_get_dma_tx_addr(I2S_Type *i2s) \brief Return the DMA Tx Address \param[in] i2s Pointer to I2S register map \return \ref Return the address */ static inline void* i2s_get_dma_tx_addr(I2S_Type *i2s) { return ((uint8_t*)i2s + I2S_TXDMA_OFFSET); } /** \fn void* i2s_get_dma_rx_addr(I2S_Type *i2s) \brief Return the DMA Rx Address \param[in] i2s Pointer to I2S register map \return \ref Return the address */ static inline void* i2s_get_dma_rx_addr(I2S_Type *i2s) { return ((uint8_t*)i2s + I2S_RXDMA_OFFSET); } /** \fn uint32_t i2s_get_sclk_frequency(uint32_t sample_rate, I2S_WSS wss_len) \brief Calculate the sclk frequency \param[in] sample_rate Audio sample rate \param[in] wss_len Word Select Size \return \ref Serial clock frequency */ static inline uint32_t i2s_get_sclk_frequency(uint32_t sample_rate, I2S_WSS wss_len) { const uint32_t num_sclk_cycles[I2S_WSS_SCLK_CYCLES_MAX] = {16, 24, 32}; uint32_t sclk_freq; /* Calculate sclk = 2 x no of sclk cycles in wss_out x sample Rate */ sclk_freq = 2 * num_sclk_cycles[wss_len] * sample_rate; return sclk_freq; } /** \fn void i2s_send(I2S_Type *i2s) \brief Prepare the I2S instance for transmission \param[in] i2s Pointer to the I2S register map \return none */ static inline void i2s_send(I2S_Type *i2s) { /* Clear Overrun interrupt if any */ i2s_clear_tx_overrun(i2s); /* Enable Tx Channel */ i2s_txchannel_enable(i2s); /* Enable Tx Interrupt */ i2s_enable_tx_interrupt(i2s); } /** \fn void i2s_receive(I2S_Type *i2s) \brief Prepare the I2S instance for reception \param[in] i2s Pointer to the I2S register map \return none */ static inline void i2s_receive(I2S_Type *i2s) { /* Clear Overrun interrupt if any */ i2s_clear_rx_overrun(i2s); /* Enable Rx Channel */ i2s_enable_rx_interrupt(i2s); /* Enable Rx Channel */ i2s_rxchannel_enable(i2s); } /** \fn void i2s_dma_receive(I2S_Type *i2s) \brief Prepare the I2S instance for reception using DMA \param[in] i2s Pointer to the I2S register map \return none */ static inline void i2s_dma_receive(I2S_Type *i2s) { /* Clear Overrun interrupt if any */ i2s_clear_rx_overrun(i2s); /* Enable the Rx Overflow interrupt */ i2s_enable_rx_overflow_interrupt(i2s); /* Enable Rx Channel */ i2s_rxchannel_enable(i2s); } /** \fn void i2s_dma_send(I2S_Type *i2s) \brief Prepare the I2S instance for transmission using DMA \param[in] i2s Pointer to the I2S register map \return none */ static inline void i2s_dma_send(I2S_Type *i2s) { /* Clear Overrun interrupt if any */ i2s_clear_tx_overrun(i2s); /* Enable Tx Channel */ i2s_txchannel_enable(i2s); } /** \fn void i2s_tx_irq_handler(I2S_Type *i2s, i2s_transfer_t *transfer) \brief Handle interrupts for the I2S Tx. \param[in] i2s Pointer to the I2S register map \param[in] transfer The transfer structure for the I2S instance \return none */ void i2s_tx_irq_handler(I2S_Type *i2s, i2s_transfer_t *transfer); /** \fn void i2s_rx_irq_handler(I2S_Type *i2s, i2s_transfer_t *transfer) \brief Handle interrupts for the I2S Rx. \param[in] i2s Pointer to the I2S register map \param[in] transfer The transfer structure for the I2S instance \return none */ void i2s_rx_irq_handler(I2S_Type *i2s, i2s_transfer_t *transfer); /** \fn void i2s_send_blocking(I2S_Type *i2s, i2s_transfer_t *transfer) \brief Execute a blocking I2S send described by the transfer structure. \param[in] i2s Pointer to the I2S register map \param[in] transfer Pointer to transfer structure \return none */ void i2s_send_blocking(I2S_Type *i2s, i2s_transfer_t *transfer); /** \fn void i2s_receive_blocking(I2S_Type *i2s, i2s_transfer_t *transfer) \brief Execute a blocking I2S receive described by the transfer structure. \param[in] i2s Pointer to the I2S register map \param[in] transfer Pointer to transfer structure \return none */ void i2s_receive_blocking(I2S_Type *i2s, i2s_transfer_t *transfer); #ifdef __cplusplus } #endif #endif /* I2S_H_ */