/**
  ******************************************************************************
 *
 * @file        Sample_SPI_TemperatureDetector.c
 *
 * @brief       For MAX31865 RTD to digital converter sample code
 *
 * @par         Project
 *              MG32
 * @version     V1.00
 * @date        2023/05/09
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2023 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 *
 ******************************************************************************
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */ 


/* Includes ------------------------------------------------------------------*/
#include "MG32_SPI_DRV.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SPI0_NSS                    PX(GPIOB_Base,0)                                    /*!< SPI0 NSS pin*/

/* Private macro -------------------------------------------------------------*/
#define PX(GPIOX,PinNum)    *((volatile uint8_t*)((uint32_t)GPIOX + PinNum + 0x10))     /*!< GPIOX pin (PinNum) read /write */

/* Private variables ---------------------------------------------------------*/
//static SPI_HandleTypeDef     mSPI0;

/* Private function prototypes -----------------------------------------------*/
void Sample_SPI_TemperatureDetector (SPI_Struct* SPIx);
void API_ReadRTDData (SPI_Struct* SPIx, uint8_t StartAddress, uint8_t *pData, uint8_t Size);
void API_WriteRTDData (SPI_Struct* SPIx, uint8_t StartAddress, uint8_t *pData, uint8_t Size);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/



/**
 *******************************************************************************
 * @brief       API read RTD data.
 * @details  
 * @param[in]   SPIx:
 *  @arg\b          SPI0
 * @param[in]   StartAddress:
 *  @arg\b          0x00h ~ 0x07h
 * @param[in]   pData pointer to reception data buffer
 * @param[in]   Size:
 *                  0 ~ 16 
 * @return      none
 * @note        Support MAX31865.
 * @par         Example
 * @code
    API_ReadRTDData(SPI0, 0x00, &RX_BUF[0], 5);
 * @endcode
 *******************************************************************************
 */
void API_ReadRTDData (SPI_Struct* SPIx, uint8_t StartAddress, uint8_t *pData, uint8_t Size)
{
    uint8_t CNT;    // Counter
    uint8_t REG;    // MAX31865 TX buffer
    
    
    
    SPI0_NSS = CLR;                         // SPI0_NSS output 0
    
    SPIx->TDAT.B[0] = StartAddress;         // TX address
    while(SPIx->STA.MBIT.RXF == 0);         // Wait RXF happened
    REG = SPIx->RDAT.B[0];                  // Clear receive data
    
    for(CNT=Size; CNT>0; CNT--) 
    {
//        SPIx->TDAT.B[0] = 0xFF;             // TX 0xFF
        SPIx->TDAT.B[0] = CNT;             // TX 0xFF  
        while(SPIx->STA.MBIT.RXF == 0);     // Wait RXF happened
        *pData = SPIx->RDAT.B[0];           // Moce RX data to destination
        pData++;                            // Increase index
    }

    SPI0_NSS = SET;                         // SPI0_NSS output 1
}


/**
 *******************************************************************************
 * @brief       API write RTD data.
 * @details  
 * @param[in]   SPIx:
 *  @arg\b          SPI0
 * @param[in]   StartAddress:
 *  @arg\b          0x00h ~ 0x07h
 * @param[in]   pData pointer to reception data buffer
 * @param[in]   Size:
 *                  0 ~ 16 
 * @return      none
 * @note        Support MAX31865.
 * @par         Example
 * @code
    API_WriteRTDData(SPI0, 0x00, &TX_BUF[0], 5);
 * @endcode
 *******************************************************************************
 */
void API_WriteRTDData (SPI_Struct* SPIx, uint8_t StartAddress, uint8_t *pData, uint8_t Size)
{
    uint8_t CNT;                            // Counter
    uint32_t REG;                           // Buffer
    
    
    
    SPI0_NSS = CLR;                         // SPI0_NSS output 0
    
    SPIx->TDAT.B[0] = StartAddress;         // Set Address
    while(SPIx->STA.MBIT.TCF == 0);         // Wait TCF happened
    
    for(CNT=Size; CNT>0; CNT--)             // Move data to MAX_TX_BUF8
    {
        SPIx->TDAT.B[0] = *pData;           // Set TX buffer
        while(SPIx->STA.MBIT.TXF == 0);     // Wait TXF
        pData++;                            // Source address +1
    }

    while(SPIx->STA.MBIT.TCF == 0);         // Wait TCF
    REG = SPIx->RDAT.W;                     // Clear RX buffer
    REG = SPIx->RDAT.W;                     // Clear RX buffer
    SPIx->STA.W = SPI_ALLF;
    
    SPI0_NSS = SET;                         // SPI0_NSS output 1
}


/**
 *******************************************************************************
 * @brief       SPI0 temperature detector 
 * @details     1.Initial SPI.
 *    \n        2.Setting TX/RX Buffer Transmit data.
 *    \n        3.Receive data.
 *    \n        4.Transmit data.
 *    \n        5.Receive data.
 * @return      None
 *******************************************************************************
 */
void Sample_SPI_TemperatureDetector (SPI_Struct* SPIx)
{  
    uint8_t     TX_BUF8[10]={0};
    uint8_t     RX_BUF8[10]={0};
    uint8_t     RTD_ResistanceData[2]={0};
    uint8_t     CNT;



    // make sure :
    //===Set CSC init===
    //MG32_CSC_Init.h(Configuration Wizard)
    //Select CK_HS source = CK_IHRCO
    //Select IHRCO = 12M
    //Select CK_MAIN Source = CK_HS
    //Configure PLL->Select APB Prescaler = CK_MAIN/1
    //Configure Peripheral On Mode Clock->SPI0 = Enable
    //Configure Peripheral On Mode Clock->URT0 = Enable
    //Configure Peripheral On Mode Clock->URT1 = Enable
    //Configure Peripheral On Mode Clock->GPIOB = Enable

    /*===Set GPIO init SPI0 for SPI0===*/
    //1. MOSI Pin
    //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin3
    //    (2).GPIO port initial is 0xFFFF
    //    (3).Pin3 mode is PPO (Push pull output)
    //    (4).Pin3 pull-up resister Enable
    //    (5).Pin3 function SPI0_MOSI
    //2. MISO Pin
    //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin1
    //    (2).GPIO port initial is 0xFFFF
    //    (3).Pin1 mode is DIN (Data input)
    //    (4).Pin1 pull-up resister Enable
    //    (5).Pin1 function SPI0_MISO
    //3. SPICLK Pin
    //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin2
    //    (2).GPIO port initial is 0xFFFF
    //    (3).Pin2 mode is PPO (Push pull output)
    //    (4).Pin2 pull-up resister Enable
    //    (5).Pin2 function SPI0_CLK
    //4. NSS Pin
    //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin10
    //    (2).GPIO port initial is 0xFFFF
    //    (3).Pin0 mode is PPO (Push pull output)
    //    (4).Pin0 pull-up resister Enable
    //    (5).Pin0 function GPB0


    // ------------------------------------------------------------------------
    // 1. Initial SPI
    // ------------------------------------------------------------------------
    SPI_DeInit(SPIx);                                           // De-Initial SPI module
    SPI_ModeAndNss_Select(SPIx, SPI_Master);                    // Master
    SPI_DataLine_Select(SPIx, SPI_Standard);                    // Setting data lines
    SPI_DataSize_Select(SPIx, SPI_8bits);                       // Setting data size 8-bit
    SPI_ClockPolarity_Select(SPIx, SPI_Low);                    // CPOL = 0
    SPI_ClockPhase_Select(SPIx, SPI_LeadingEdge);               // CPHA = 0
    SPI_Clock_Select(SPIx, SPI_CK_SPIx_PR);                     // SPI clock source CK_SPIx_PR
    SPI_PreDivider_Select(SPIx, SPI_PDIV_1);                    // PDIV /1
    SPI_Prescaler_Select(SPIx, SPI_PSC_1);                      // PSC 1
    SPI_Divider_Select(SPIx, SPI_DIV_4);                        // DIV /4
    SPI_FirstBit_Select(SPIx, SPI_MSB);                         // First MSB
    SPI_Cmd(SPIx, ENABLE);                                      // Enable SPI module
    
    // ------------------------------------------------------------------------
    // 2. Setting TX/RX Buffer Transmit data.
    // ------------------------------------------------------------------------
    for(CNT=0; CNT<10; CNT++)                                   // Clear RX_BUF data                      
    {
        RX_BUF8[CNT] = CNT;       
    }

    // ------------------------------------------------------------------------
    // 3. Receive data
    // ------------------------------------------------------------------------
    API_ReadRTDData(SPI0, 0x00, &RX_BUF8[0], 8);                // Get Configuration, RTD, High Fault Threshold, Low Fault Threshol and Fault Status.
    for(CNT=0; CNT<8; CNT++)                                    // TX_BUF8[] move to RX_BUF8[];
    {
        TX_BUF8[CNT] = RX_BUF8[CNT];
    }
   
    // ------------------------------------------------------------------------
    // 4. Transmit data
    // ------------------------------------------------------------------------
    TX_BUF8[0] = 0x5A;                                          // Setting
    API_WriteRTDData(SPI0, 0x80, &TX_BUF8[0], 1);               // Configure Configuration.
    
    TX_BUF8[3] = 0x53;                                          // Setting TX_BUF8[3] High Fault Threshold MSB
    TX_BUF8[4] = 0x54;                                          // Setting High Fault Threshold LSB
    TX_BUF8[5] = 0x55;                                          // Setting Low Fault Threshold MSB
    TX_BUF8[6] = 0x56;                                          // Setting Low Fault Threshold LSB
    API_WriteRTDData(SPI0, 0x83, &TX_BUF8[3], 4);               // Configure High Fault Threshold and Low Fault Threshold.
    
    // ------------------------------------------------------------------------
    // 5. Receive data
    // ------------------------------------------------------------------------
    API_ReadRTDData(SPI0, 0x01, &RTD_ResistanceData[0], 2);     // Get RTD.
}



