/**
 ******************************************************************************
 * @file    kpm32xx_ddl_sci_spi.h
 * @author  Kiwi Software Team
 * @brief   Header file of SCI SPI DDL module.
 * @note
 *		   V1.0.0, 2024/12/20.
 *
 * Copyright (c) 2024, Kiwi Instruments Co,. Ltd.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *	1. Redistributions of source code must retain the above copyright notice,
 *	   this list of conditions and the following disclaimer.
 *
 *	2. Redistributions in binary form must reproduce the above copyright notice,
 *	   this list of conditions and the following disclaimer in the documentation
 *	   and/or other materials provided with the distribution.
 *
 *	3. Neither the name of the copyright holder nor the names of its contributors
 *	   may be used to endorse or promote products derived from this software without
 *	   specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************
 */


#ifndef __KPM32xx_DDL_SCI_SPI_H
#define __KPM32xx_DDL_SCI_SPI_H

#ifdef __cplusplus
extern "C" {
#endif

#include "kpm32xx_ddl_def.h"
#include "kpm32xx_ddl_sci_common.h"


/* Clock phase setting type definitions */
typedef enum
{
	CLK_NOR      = 0,
	CLK_INV      = 1
} SCISPI_ClkPhase_T;

/* Data phase setting type definitions */
typedef enum
{
	DATA_NOR     = 0,
	DATA_INV     = 1
} SCISPI_DatPhase_T;

/* SPI Master or Slave mode */
typedef enum
{
	SCISPI_MASTER = 0,
	SCISPI_SLAVE  = 1
} SCISPI_WorkMode_T;

/* SPI Tx or Rx mode */
typedef enum
{
	SCISPI_TX     = 0x01,
	SCISPI_RX     = 0x02,
	SCISPI_TXRX   = 0x04,
}SCISPI_TxRxMode_T;

/* SPI CS Pin configuration */
typedef struct
{
	GPIO_Type    *GPIOx;
	uint32_t      gpioPin;
} SCISPI_CSPinCfg_T;

typedef struct
{
	uint32_t          clkPres;             /* SCI SPI baudrate */
    uint32_t          brDiv1And2;          /* SCI SPI baudrate */
	uint32_t          mlsb;                /* MSB or LSB */
	uint32_t          workMode;            /* Master or Slave mode */
	uint32_t          dataFlt;             /* SCI SPI Data Filter Function */
	uint32_t          clkFlt;              /* SCI SPI Clock Filter Function */

	SCISPI_CSPinCfg_T csPInCfg;            /* Serial Unit CSI CS pin configuration*/
	SCISPI_ClkPhase_T clkPhase;            /* To decide the initial output level on CLK pin */
	SCISPI_DatPhase_T datPhase;            /* To decide the initial output level on Data pin */
} SCISPI_Init_T;


/* SCI SPI dummy data set */
#define __SPI_08BIT_DUMMY_DATA__                      0x5A

/* SCI SPI prescaler maximum set */
#define __SPI_1ST_PRESCALER_MAXIMUM__                 15
#define __SPI_2ND_PRESCALER_MAXIMUM__                 512

/* MSB or LSB first */
#define SCISPI_LSB_FIRST        SCI_MC_DATDIR
#define SCISPI_MSB_FIRST        0

/* SCI SPI Tx and Rx mode */
#define SCISPI_MODE_RX                        ((uint32_t)0x00000001U)    /* RX mode        */
#define SCISPI_MODE_TX                        ((uint32_t)0x00000002U)    /* TX mode        */
#define SCISPI_MODE_TX_RX                     ((uint32_t)0x00000004U)    /* RX and TX mode */

#define IS_SCISPI_MODE(__MODE__)             (((__MODE__) == SCISPI_MODE_RX)        || \
                                              ((__MODE__) == SCISPI_MODE_TX)        || \
                                              ((__MODE__) == SCISPI_MODE_TX_RX))

#define IS_SCISPI_INSTANCE(__INSTANCE__)     (((__INSTANCE__) == SCI0)  || \
                                              ((__INSTANCE__) == SCI1)  || \
                                              ((__INSTANCE__) == SCI2))

/* SPI dataphs and clkphs config */
#define __DDL_SCISPI_DATPHS_NORMAL(__INSTANCE__)	               CLEAR_BIT((__INSTANCE__)->MSPI, SCI_MSPI_DATPHS)
#define __DDL_SCISPI_DATPHS_INVERS(__INSTANCE__)	               SET_BIT((__INSTANCE__)->MSPI,   SCI_MSPI_DATPHS)
#define __DDL_SCISPI_CLKPHS_NORMAL(__INSTANCE__)                   CLEAR_BIT((__INSTANCE__)->MSPI, SCI_MSPI_CLKPHS)
#define __DDL_SCISPI_CLKPHS_INVERS(__INSTANCE__)		    	   SET_BIT((__INSTANCE__)->MSPI,   SCI_MSPI_CLKPHS)

/* SPI TX and RX config */
#define __DDL_SCISPI_SET_TX_MODE(__INSTANCE__) 	                   SET_BIT((__INSTANCE__)->MC,   SCI_MC_TXEN);
#define __DDL_SCISPI_CLEAR_TX_MODE(__INSTANCE__) 	               CLEAR_BIT((__INSTANCE__)->MC, SCI_MC_TXEN);
#define __DDL_SCISPI_SET_RX_MODE(__INSTANCE__)                     SET_BIT((__INSTANCE__)->MC,   SCI_MC_RXEN);
#define __DDL_SCISPI_CLEAR_RX_MODE(__INSTANCE__)                   CLEAR_BIT((__INSTANCE__)->MC, SCI_MC_RXEN);

/* SPI DMA enable or disable config */
#define __DDL_SCISPI_DMA_ENABLE(__INSTANCE__)                      SET_BIT((__INSTANCE__)->MC,   SCI_MC_DMAEN)
#define __DDL_SCISPI_DMA_DISABLE(__INSTANCE__)                     CLEAR_BIT((__INSTANCE__)->MC, SCI_MC_DMAEN)

#define __DDL_SCISPI_INTRENABLE(__INSTANCE__, __INTERRUPTS__)      SET_BIT((__INSTANCE__)->IE, (__INTERRUPTS__))
#define __DDL_SCISPI_INTRDISABLE(__INSTANCE__, __INTERRUPTS__)     CLEAR_BIT((__INSTANCE__)->IE, (__INTERRUPTS__))

/* SPI as Master or Slave */
#define __DDL_SCISPI_AS_MASTER(__INSTANCE__)                       CLEAR_BIT((__INSTANCE__)->MSPI, SCI_MSPI_MODSEL)
#define __DDL_SCISPI_AS_SLAVE(__INSTANCE__)                        SET_BIT((__INSTANCE__)->MSPI, SCI_MSPI_MODSEL)

/* SPI CS enable or disable */
#define __DDL_SCISPI_CSPIN_ENABLE(__INSTANCE__)                    SET_BIT((__INSTANCE__)->MSPI, SCI_MSPI_CSEN)
#define __DDL_SCISPI_CSPIN_DISABLE(__INSTANCE__)                   CLEAR_BIT((__INSTANCE__)->MSPI, SCI_MSPI_CSEN)

/* SPI CS active or deactive */
#define __DDL_SCISPI_CSPIN_ACTIVE(__INSTANCE__)                    CLEAR_BIT((__INSTANCE__)->MSPI, SCI_MSPI_CSDEACT)
#define __DDL_SCISPI_CSPIN_DEACTIVE(__INSTANCE__)                  SET_BIT((__INSTANCE__)->MSPI, SCI_MSPI_CSDEACT)


/**
  * @brief  Enable SCI SPI TX or RX interrupt.
  *
  * @param  SCIx Pointer to SCI SPI instance.
  * @param  intrMask SCI SPI TX and RX mask.
  *
  * @retval None
  */
void DDL_SCISPI_IntEnable(SCI_Type *SCIx, uint32_t intrMask);


/**
  * @brief  Disable SCI SPI TX or RX interrupt.
  *
  * @param  SCIx Pointer to SCI SPI instance.
  * @param  intrMask SCI SPI TX and RX mask.
  *
  * @retval None
  */
void DDL_SCISPI_IntDisable(SCI_Type *SCIx, uint32_t intrMask);


/**
  * @brief  Configure the elements of structure SCISPI_Init_T to default values.
  *
  * @param  pSCISPIStruct Pointer to a SCISPI_Init_T structure that contains
  *                  the configuration information for the given SCI SPI module.
  *
  * @retval None
  */
void DDL_SCISPI_StructInit(SCISPI_Init_T *pSCISPIStruct);

/**
  * @brief  Initializes the SCI SPI by the specified parameters
  *         in the SCISPI_Init_T and initialize the associated handle.
  * @param  SCIx Pointer to SCI SPI instance.
  * @param  pSCISPIStruct  pointer to a SCISPI_Init_T structure that contains
  *                  the configuration information for the specified SPI.
  *
  * @retval None
  */
void DDL_SCISPI_Init(SCI_Type *SCIx, SCISPI_Init_T *pSCISPIStruct);

/**
  * @brief  SCI SPI as master or slave (Half-Duplex) transmits an amount of data through polling mode.
  * @param  SCIx     Pointer to SCI SPI instance.
  * @param  pData    pointer to data buffer.
  * @param  size     the amount of data to be sent.
  * @param  timeout  timeout duration.
  *
  * @retval DDL status
  */
DDL_Status_T DDL_SCISPI_Transmit(SCI_Type *SCIx, uint8_t *pData, uint16_t size, uint32_t timeout);

/**
  * @brief  SCI SPI as master or slave (Half-Duplex) receives an amount of data through polling mode.
  * @param  SCIx     Pointer to SCI SPI instance.
  * @param  pData    pointer to data buffer.
  * @param  size     the amount of data to be sent.
  * @param  timeout  timeout duration.
  *
  * @retval DDL status
  */
DDL_Status_T DDL_SCISPI_Receive(SCI_Type *SCIx, uint8_t *pData, uint16_t size, uint32_t timeout);


#ifdef __cplusplus
}
#endif

#endif /* __KPM32xx_DDL_SCI_SPI_H */
