

/**
 ******************************************************************************
 *
 * @file        BLE_SPI.C
 * @brief       BLE_MG126 SPI c Code. 
 *
 * @par         Project
 *              MG32
 * @version     V1.03
 * @date        2021/06/23
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2020 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.
 *******************************************************************************
 *******************************************************************************
 */


#include "BSP.h"
#include "MG32__Common_DRV.h"
#include "MG32_Common_MID.h"
#include "MG32_SPI_MID.h"


static unsigned char Temp8;
static unsigned short Temp16;
static unsigned long Temp24;
static unsigned long Temp32;

// volatile uint8_t SPI_RDAT;                      /* Add volatile */
static volatile boolean CPU_CLK_FAST_ENABLE = FALSE;   /* Add volatile */

DRV_Return SPIx_Init (uint32_t ProcessClockRate, uint32_t BLEClockRate __attribute__((unused)));
unsigned char SPI_WriteBuf(unsigned char reg, unsigned char const *pBuf, unsigned char len);
unsigned char SPI_ReadBuf(unsigned char reg, unsigned char *pBuf, unsigned char len);
void SysClk8to48(void);
void SysClk48to8(void);
void DisableEnvINT(void);
void EnableEnvINT(void);
void UpdateLEDValueAll(void);
void McuGotoSleepAndWakeup(void);
unsigned char aes_encrypt_HW(unsigned char *_data, unsigned char *_key);

/**
 *******************************************************************************
 * @brief       SPI0 module initial
 * @details
 * @param[in]   ProcessClockRate
 *  @arg\b          12000000 ~ 48000000
 * @param[in]   BLEClockRate
 *  @arg\b          0, is auto setting BLE clock rate 6000000 ~ 10000000.
 *  @arg\b          6000000 ~ 10000000, setting BLE clock rate.
 * @return      None
 * @note
 * @par         Example
 * @code
    SPIx_Init(12000000, 0);
 * @endcode
 *******************************************************************************
 */
DRV_Return SPIx_Init (uint32_t ProcessClockRate, uint32_t BLEClockRate __attribute__((unused)))
{
//    volatile ctype    URT_RecData;              /* volatile */
    volatile uint8_t  tmp;                      /* volatile */
    volatile uint8_t  CNT;                      /* volatile */
    volatile double   SPI_Clock;                /* volatile */
    volatile uint32_t DIV;                      /* volatile */



    // When CK_AHB > 12MHz
    if(ProcessClockRate > 12000000)
    {
        CPU_CLK_FAST_ENABLE = TRUE;
    }
    else
    {
        CPU_CLK_FAST_ENABLE = FALSE;
    }


#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wunreachable-code"
    // When connect is SPI0
    if(&BLE_MODULE->STA.W == &SPI0->STA.W)
    {
    //    /*=== 1. Default Initial SPI ===*/
    //    SPI_DeInit(SPI0);

    //    /*=== 2. Configure clock divider ===*/                      // SPI clock = 1MHz
    //    SPI_Clock_Select(SPI0, SPI_CK_SPIx_PR);                     // CK_SPIx = CK_SPIx_PR
    //    SPI_PreDivider_Select(SPI0, SPI_PDIV_1);                    // PDIV outpu = CK_SPIx /2
    //    SPI_Prescaler_Select(SPI0, SPI_PSC_1);                      // Prescaler outpu = PDIV outpu /3
    //    SPI_Divider_Select(SPI0, SPI_DIV_2);                        // DIV outpu = PDIV outpu /2

    //    /*=== 3. Configure SPI data line, mode and data size... ===*/
    //    SPI_DataLine_Select(SPI0, SPI_Standard);                    // SPI Standard mode 
    //    SPI_ModeAndNss_Select(SPI0, SPI_Master);                    // Master
    //    SPI_ClockPhase_Select(SPI0, SPI_LeadingEdge);               // CPHA = 0
    //    SPI_ClockPolarity_Select(SPI0, SPI_Low);                    // CPOL = 0
    //    SPI_FirstBit_Select(SPI0, SPI_MSB);                         // MSB first
    //    SPI_DataSize_Select(SPI0, SPI_8bits);                       // Data size 8bits

    //    /*=== 4. Enable SPI ===*/
    //    SPI_Cmd(SPI0, ENABLE);                                      // Enable SPI0 module

        /* Get Prescaler setting */
        DIV = 0xFF;
        CNT = 0;
        do
        {
            CNT++;
            SPI_Clock = (double) ProcessClockRate;
            SPI_Clock = (SPI_Clock /CNT) /2;
            if((SPI_Clock >= 6000000) && (SPI_Clock < 10000000))        // When SPI clock range in 6M ~ 10M
            {
                DIV = CNT;                                              // Store DIV 
            }
        }while(CNT<8);                                                  // When 
        
        DIV--;
        if(DIV > 8)                                                     // When not get DIV
            return DRV_Failure;
        
        /*=== 1. Default Initial SPI ===*/
        BLE_MODULE->CR0.W = 0x00000000;
        BLE_MODULE->STA.W = 0x00000FD8;
        BLE_MODULE->INT.W = 0x00000000;
        BLE_MODULE->CLK.W = 0x00000000;
        BLE_MODULE->CR1.W = 0x00000000;
        BLE_MODULE->CR2.W = 0x03000100;

        /*=== 2. Configure clock divider ===*/                          // SPI clock = 1MHz
        BLE_MODULE->CLK.W = SPI_CLK_CK_SEL_proc_w |                     // CK_SPIx = CK_SPIx_PR 
                            SPI_CLK_CK_DIV_div2_w |                     // DIV outpu = PDIV outpu /1
                            (DIV << 8) |                                // Prescaler outpu = PDIV outpu /1
                            SPI_CLK_CK_PDIV_div1_w;                     // PDIV outpu = CK_SPIx /2
     
        /*=== 3. Configure SPI data line, mode and data size... ===*/
        BLE_MODULE->CR2.W |= SPI_CR2_DAT_LINE_spi_w |                   // SPI Standard mode 
                            (SPI_CR2_DSIZE_mask_w & 0x00080000);        // Data size 8bits

        BLE_MODULE->CR0.W |= SPI_CR0_MDS_master_w |
                             SPI_CR0_CPHA_leading_edge_w |
                             SPI_CR0_CPOL_low_w |
                             SPI_CR0_LSB_EN_disable_w;

        /*=== 4. Enable SPI ===*/
        BLE_MODULE->CR0.W |= SPI_CR0_EN_enable_w;                       // Enable SPI0 module
    }
    else
    {
        //==Set CSC init
        //MG32_CSC_Init.h(Configuration Wizard)
        //Select CK_HS source = CK_IHRCO
        //Select IHRCO = 11.0592M
        //Select CK_MAIN Source = CK_HS
        //Configure PLL->Select APB Prescaler = CK_MAIN/1
        //Configure Peripheral On Mode Clock->Port B/URT0 = Enable
        //Configure Peripheral On Mode Clock->URT0->Select URT0_PR Source = CK_APB(11.0592)
        
        //==Set GPIO init
        //1. MOSI Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin8
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is PPO (Push pull output)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin8 function URT0_TX
        //2. MISO Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin9
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is ODO (Open drain)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin9 function URT0_RX
        //3. SPICLK Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOC->Pin0
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is PPO (Push pull output)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin3 function URT0_CLK
        //4. NSS Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin10
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is PPO (Push pull output)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin3 function GPIO (the NSS is software control)
        
        /* Get Prescaler setting */
        DIV = 0xFF;
        CNT = 0;
        do
        {
            CNT++;
            SPI_Clock = (double) ProcessClockRate;
            SPI_Clock = (SPI_Clock /(CNT+1)) ;
            if((SPI_Clock >= 6000000) && (SPI_Clock < 10000000))        // When SPI clock range in 6M ~ 10M
            {
                DIV = CNT;                                              // Store DIV 
            }
        }while(CNT<8);                                                  // When 
        
        if(DIV > 8)                                                     // When not get DIV
            return DRV_Failure;
        
        //=====Set Clock=====//
        //---Set BaudRate---//
        BLE_MODULE->CLK.W = (BLE_MODULE->CLK.W & ~(URT_CLK_BR_MDS_mask_w | URT_CLK_CK_SEL_mask_w)) |
                             URT_CLK_CK_SEL_proc_w | URT_CLK_BR_MDS_separated_w;
        BLE_MODULE->RLR.B[0] = 0;
        BLE_MODULE->RLR.B[1] = 0;
        BLE_MODULE->CLK.W = ((BLE_MODULE->CLK.W & (~URT_CLK_BR_EN_mask_w)) |
                              URT_CLK_BR_EN_mask_w);

        //---TX/RX Clock---//
        BLE_MODULE->CLK.W = ((BLE_MODULE->CLK.W & ~(URT_CLK_TX_CKS_mask_w | URT_CLK_RX_CKS_mask_w)) | 
                              URT_CLK_TX_CKS_internal_w | URT_CLK_RX_CKS_internal_w);
        BLE_MODULE->CR1.B[3] = (uint8_t) DIV;
        BLE_MODULE->CR1.B[1] = (uint8_t) DIV;
        BLE_MODULE->CR0.W = ((BLE_MODULE->CR0.W & ~(URT_CR0_OS_MDS_mask_w)) | 
                              URT_CR0_OS_MDS_three_w);
        BLE_MODULE->CR2.W = ((BLE_MODULE->CR2.W & ~(URT_CR2_TX_EN_mask_w | URT_CR2_RX_EN_mask_w)) | 
                              URT_CR2_TX_EN_enable_w | URT_CR2_RX_EN_enable_w);

        BLE_MODULE->CR1.B[2] = URT_CR1_TXDSIZE_8bit_b2 | URT_CR1_TXMSB_EN_enable_b2 | URT_CR1_TXPAR_EN_disable_b2 | URT_CR1_TXSTP_LEN_1bit_b2;
        BLE_MODULE->CR1.B[0] = URT_CR1_RXDSIZE_8bit_b0 | URT_CR1_RXMSB_EN_enable_b0 | URT_CR1_RXPAR_EN_disable_b0 | URT_CR1_RXSTP_LEN_1bit_b0;

        tmp = BLE_MODULE->CR4.B[0] & (~(URT_CR4_RDAT_INV_mask_b0|URT_CR4_TDAT_INV_mask_b0));
        tmp = tmp | URT_CR4_RDAT_INV_disable_b0 | URT_CR4_TDAT_INV_disable_b0;
        BLE_MODULE->CR4.B[0] = tmp;

        // Set Mode Select
        BLE_MODULE->CR0.W = (BLE_MODULE->CR0.W & (~URT_CR0_MDS_mask_w) ) | URT_CR0_MDS_sync_w; 
//        BLE_MODULE->MUTE.W = BLE_MODULE->MUTE.W & (~URT_MUTE_MUTE_EN_mask_w);
        // Set DataLine Select
        BLE_MODULE->CR0.W = ((BLE_MODULE->CR0.W & (~URT_CR0_DAT_LINE_mask_w)) | URT_CR0_DAT_LINE_2_w);
        BLE_MODULE->CR3.W = ((BLE_MODULE->CR3.W & (~URT_CR3_CPHA_mask_w)) | URT_CR3_CPHA_leading_edge_w);
        BLE_MODULE->CR3.W = ((BLE_MODULE->CR3.W & (~URT_CR3_CPOL_mask_w)) | URT_CR3_CPOL_low_w);

        // Flash_nCS = FLASH_nCS_NoACTIVE;
        SPI_NSS = 1;
        // Set Data Control
        BLE_MODULE->CR3.B[2] = 0;
        // Enable CLK(SYSCLK)
        BLE_MODULE->CLK.W = (( BLE_MODULE->CLK.W & (~URT_CLK_CLK_EN_mask_w)) | ( URT_CLK_CLK_EN_mask_w * 1));
        // Enable URT
        BLE_MODULE->CR0.W = ((BLE_MODULE->CR0.W & (~URT_CR0_EN_mask_w)) | (URT_CR0_EN_mask_w * 1));

    }
    
    #pragma clang diagnostic pop
#else
    // When connect is SPI0
    if(&BLE_MODULE->STA.W == &SPI0->STA.W)
    {
    //    /*=== 1. Default Initial SPI ===*/
    //    SPI_DeInit(SPI0);

    //    /*=== 2. Configure clock divider ===*/                      // SPI clock = 1MHz
    //    SPI_Clock_Select(SPI0, SPI_CK_SPIx_PR);                     // CK_SPIx = CK_SPIx_PR
    //    SPI_PreDivider_Select(SPI0, SPI_PDIV_1);                    // PDIV outpu = CK_SPIx /2
    //    SPI_Prescaler_Select(SPI0, SPI_PSC_1);                      // Prescaler outpu = PDIV outpu /3
    //    SPI_Divider_Select(SPI0, SPI_DIV_2);                        // DIV outpu = PDIV outpu /2

    //    /*=== 3. Configure SPI data line, mode and data size... ===*/
    //    SPI_DataLine_Select(SPI0, SPI_Standard);                    // SPI Standard mode 
    //    SPI_ModeAndNss_Select(SPI0, SPI_Master);                    // Master
    //    SPI_ClockPhase_Select(SPI0, SPI_LeadingEdge);               // CPHA = 0
    //    SPI_ClockPolarity_Select(SPI0, SPI_Low);                    // CPOL = 0
    //    SPI_FirstBit_Select(SPI0, SPI_MSB);                         // MSB first
    //    SPI_DataSize_Select(SPI0, SPI_8bits);                       // Data size 8bits

    //    /*=== 4. Enable SPI ===*/
    //    SPI_Cmd(SPI0, ENABLE);                                      // Enable SPI0 module

        /* Get Prescaler setting */
        DIV = 0xFF;
        CNT = 0;
        do
        {
            CNT++;
            SPI_Clock = (double) ProcessClockRate;
            SPI_Clock = (SPI_Clock /CNT) /2;
            if((SPI_Clock >= 6000000) && (SPI_Clock < 10000000))        // When SPI clock range in 6M ~ 10M
            {
                DIV = CNT;                                              // Store DIV 
            }
        }while(CNT<8);                                                  // When 
        
        DIV--;
        if(DIV > 8)                                                     // When not get DIV
            return DRV_Failure;
        
        /*=== 1. Default Initial SPI ===*/
        BLE_MODULE->CR0.W = 0x00000000;
        BLE_MODULE->STA.W = 0x00000FD8;
        BLE_MODULE->INT.W = 0x00000000;
        BLE_MODULE->CLK.W = 0x00000000;
        BLE_MODULE->CR1.W = 0x00000000;
        BLE_MODULE->CR2.W = 0x03000100;

        /*=== 2. Configure clock divider ===*/                          // SPI clock = 1MHz
        BLE_MODULE->CLK.W = SPI_CLK_CK_SEL_proc_w |                     // CK_SPIx = CK_SPIx_PR 
                            SPI_CLK_CK_DIV_div2_w |                     // DIV outpu = PDIV outpu /1
                            (DIV << 8) |                                // Prescaler outpu = PDIV outpu /1
                            SPI_CLK_CK_PDIV_div1_w;                     // PDIV outpu = CK_SPIx /2
     
        /*=== 3. Configure SPI data line, mode and data size... ===*/
        BLE_MODULE->CR2.W |= SPI_CR2_DAT_LINE_spi_w |                   // SPI Standard mode 
                            (SPI_CR2_DSIZE_mask_w & 0x00080000);        // Data size 8bits

        BLE_MODULE->CR0.W |= SPI_CR0_MDS_master_w |
                             SPI_CR0_CPHA_leading_edge_w |
                             SPI_CR0_CPOL_low_w |
                             SPI_CR0_LSB_EN_disable_w;

        /*=== 4. Enable SPI ===*/
        BLE_MODULE->CR0.W |= SPI_CR0_EN_enable_w;                       // Enable SPI0 module
    }
    else
    {
        //==Set CSC init
        //MG32_CSC_Init.h(Configuration Wizard)
        //Select CK_HS source = CK_IHRCO
        //Select IHRCO = 11.0592M
        //Select CK_MAIN Source = CK_HS
        //Configure PLL->Select APB Prescaler = CK_MAIN/1
        //Configure Peripheral On Mode Clock->Port B/URT0 = Enable
        //Configure Peripheral On Mode Clock->URT0->Select URT0_PR Source = CK_APB(11.0592)
        
        //==Set GPIO init
        //1. MOSI Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin8
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is PPO (Push pull output)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin8 function URT0_TX
        //2. MISO Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin9
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is ODO (Open drain)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin9 function URT0_RX
        //3. SPICLK Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOC->Pin0
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is PPO (Push pull output)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin3 function URT0_CLK
        //4. NSS Pin
        //    (1).MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOB->Pin10
        //    (2).GPIO port initial is 0xFFFF
        //    (3).Pin8 mode is PPO (Push pull output)
        //    (4).Pin8 pull-up resister Enable
        //    (5).Pin3 function GPIO (the NSS is software control)
        
        /* Get Prescaler setting */
        DIV = 0xFF;
        CNT = 0;
        do
        {
            CNT++;
            SPI_Clock = (double) ProcessClockRate;
            SPI_Clock = (SPI_Clock /(CNT+1)) ;
            if((SPI_Clock >= 6000000) && (SPI_Clock < 10000000))        // When SPI clock range in 6M ~ 10M
            {
                DIV = CNT;                                              // Store DIV 
            }
        }while(CNT<8);                                                  // When 
        
        if(DIV > 8)                                                     // When not get DIV
            return DRV_Failure;
        
        //=====Set Clock=====//
        //---Set BaudRate---//
        BLE_MODULE->CLK.W = (BLE_MODULE->CLK.W & ~(URT_CLK_BR_MDS_mask_w | URT_CLK_CK_SEL_mask_w)) |
                             URT_CLK_CK_SEL_proc_w | URT_CLK_BR_MDS_separated_w;
        BLE_MODULE->RLR.B[0] = 0;
        BLE_MODULE->RLR.B[1] = 0;
        BLE_MODULE->CLK.W = ((BLE_MODULE->CLK.W & (~URT_CLK_BR_EN_mask_w)) |
                              URT_CLK_BR_EN_mask_w);

        //---TX/RX Clock---//
        BLE_MODULE->CLK.W = ((BLE_MODULE->CLK.W & ~(URT_CLK_TX_CKS_mask_w | URT_CLK_RX_CKS_mask_w)) | 
                              URT_CLK_TX_CKS_internal_w | URT_CLK_RX_CKS_internal_w);
        BLE_MODULE->CR1.B[3] = (uint8_t) DIV;
        BLE_MODULE->CR1.B[1] = (uint8_t) DIV;
        BLE_MODULE->CR0.W = ((BLE_MODULE->CR0.W & ~(URT_CR0_OS_MDS_mask_w)) | 
                              URT_CR0_OS_MDS_three_w);
        BLE_MODULE->CR2.W = ((BLE_MODULE->CR2.W & ~(URT_CR2_TX_EN_mask_w | URT_CR2_RX_EN_mask_w)) | 
                              URT_CR2_TX_EN_enable_w | URT_CR2_RX_EN_enable_w);

        BLE_MODULE->CR1.B[2] = URT_CR1_TXDSIZE_8bit_b2 | URT_CR1_TXMSB_EN_enable_b2 | URT_CR1_TXPAR_EN_disable_b2 | URT_CR1_TXSTP_LEN_1bit_b2;
        BLE_MODULE->CR1.B[0] = URT_CR1_RXDSIZE_8bit_b0 | URT_CR1_RXMSB_EN_enable_b0 | URT_CR1_RXPAR_EN_disable_b0 | URT_CR1_RXSTP_LEN_1bit_b0;

        tmp = BLE_MODULE->CR4.B[0] & (~(URT_CR4_RDAT_INV_mask_b0|URT_CR4_TDAT_INV_mask_b0));
        tmp = tmp | URT_CR4_RDAT_INV_disable_b0 | URT_CR4_TDAT_INV_disable_b0;
        BLE_MODULE->CR4.B[0] = tmp;

        // Set Mode Select
        BLE_MODULE->CR0.W = (BLE_MODULE->CR0.W & (~URT_CR0_MDS_mask_w) ) | URT_CR0_MDS_sync_w; 
//        BLE_MODULE->MUTE.W = BLE_MODULE->MUTE.W & (~URT_MUTE_MUTE_EN_mask_w);
        // Set DataLine Select
        BLE_MODULE->CR0.W = ((BLE_MODULE->CR0.W & (~URT_CR0_DAT_LINE_mask_w)) | URT_CR0_DAT_LINE_2_w);
        BLE_MODULE->CR3.W = ((BLE_MODULE->CR3.W & (~URT_CR3_CPHA_mask_w)) | URT_CR3_CPHA_leading_edge_w);
        BLE_MODULE->CR3.W = ((BLE_MODULE->CR3.W & (~URT_CR3_CPOL_mask_w)) | URT_CR3_CPOL_low_w);

        // Flash_nCS = FLASH_nCS_NoACTIVE;
        SPI_NSS = 1;
        // Set Data Control
        BLE_MODULE->CR3.B[2] = 0;
        // Enable CLK(SYSCLK)
        BLE_MODULE->CLK.W = (( BLE_MODULE->CLK.W & (~URT_CLK_CLK_EN_mask_w)) | ( URT_CLK_CLK_EN_mask_w * 1));
        // Enable URT
        BLE_MODULE->CR0.W = ((BLE_MODULE->CR0.W & (~URT_CR0_EN_mask_w)) | (URT_CR0_EN_mask_w * 1));

    }
#endif
    return DRV_Success;
}


/**
 *******************************************************************************
 * @brief       SPI write buffer
 * @details  
 * @param[in]   reg: Command
 * @param[in]   *pBuf: Write buffer index
 * @param[in]   len: Data length
 *  @arg\b          0~255
 * @return      DRV_Return
 *  @arg\b          0
 * @note
 * @par         Example
 * @code
    SPI_WriteBuf(CMD, &TXBuf, 128);
 * @endcode
 *******************************************************************************
 */
unsigned char SPI_WriteBuf(unsigned char reg, unsigned char const *pBuf, unsigned char len)
{
    volatile signed char i=0,j=0;               /* volatile */
    
    
    
    SPI_NSS = 0;                                                    // NSS = 0
    
    BLE_MODULE->TDAT.B[0] = reg;                                    // Write 1 byte
    
    for (i=(signed char) len;i>3;i-=4)
    {                                                               // Write 4 bytes
        Temp32 = (unsigned long) (*(pBuf+j) | (*(pBuf+j+1)<<8) | (*(pBuf+j+2)<<16) | (*(pBuf+j+3)<<24));
        j+=4;
        BLE_MODULE->TDAT.W = Temp32;
        while((BLE_MODULE->STA.B[0] & SPI_STA_TXF_mask_b0) == 0);   // Wait TDAT data move to TX shadow buffer
    }
    
    for (;i>2;i-=3)
    {                                                               // Write 3 bytes
        Temp24 = (unsigned long) (*(pBuf+j) | (*(pBuf+j+1)<<8) | (*(pBuf+j+2)<<16));
        j+=3;
        BLE_MODULE->TDAT3.W = Temp24;
        while((BLE_MODULE->STA.B[0] & SPI_STA_TXF_mask_b0) == 0);   // Wait TDAT data move to TX shadow buffer
    }
    
    for (;i>1;i-=2)
    {                                                               // Write 2 bytes
        Temp16 = (unsigned short) (*(pBuf+j) | (*(pBuf+j+1)<<8));
        j+=2;                                                       // Index parameter + 2
        BLE_MODULE->TDAT.H[0] = Temp16;                             // Write 2 bytes to TX
        while((BLE_MODULE->STA.B[0] & SPI_STA_TXF_mask_b0) == 0);   // Wait TDAT data move to TX shadow buffer
    }
    
    for (;i>0;i--)
    {
        Temp8 = *(pBuf+j);                                          // Write 1 byte
        j++;
        BLE_MODULE->TDAT.B[0] = Temp8;
        while((BLE_MODULE->STA.B[0] & SPI_STA_TXF_mask_b0) == 0);   // Wait TDAT data move to TX shadow buffer
    }    
    
    
    if(&BLE_MODULE->STA.W == &SPI0->STA.W)                          // When BLE module used SPI0
    {
        while((BLE_MODULE->STA.B[0] & SPI_STA_TCF_mask_b0) == 0);   // Wait TX data transmit complete
        BLE_MODULE->CR1.B[0] = SPI_CR1_RDAT_CLR_mask_b0;            // Clear RX buffe data
        BLE_MODULE->STA.H[0] = SPI_ALLF;                            // Clear SPI all flag
    }
    else                                                            // When BLE moudle used URTx
    {
        while((BLE_MODULE->STA.B[0] & URT_STA_TCF_mask_b0) == 0);   // Wait TX data transmit complete
        BLE_MODULE->CR4.B[0] = URT_CR4_RDAT_CLR_mask_b0;            // Clear RX buffe data
        BLE_MODULE->STA.W = URT_IT_Mask;                            // Clear URTx all flag
    }

    SPI_NSS = 1;                        // NSS = 1
    return 0;
}


/**
 *******************************************************************************
 * @brief       SPI Read buffer
 * @details  
 * @param[in]   reg: Command
 * @param[in]   *pBuf: Read buffer index
 * @param[in]   len: Data length
 *  @arg\b          0~255
 * @return      DRV_Return
 *  @arg\b          0
 * @note
 * @par         Example
 * @code
    SPI_ReadBuf(CMD, &RXBuf, 128);
 * @endcode
 *******************************************************************************
 */
unsigned char SPI_ReadBuf(unsigned char reg, unsigned char *pBuf, unsigned char len)
{
    volatile unsigned char i=0;                 /* volatile */



    SPI_NSS = 0;                                                    // NSS = 0
    
    BLE_MODULE->TDAT.B[0] = reg;                                    // Write 1 byte
    if(CPU_CLK_FAST_ENABLE == FALSE)                                // When CK_AHB <= 12MHz
    {
        BLE_MODULE->TDAT.B[0] = 0xff;                                   // Write 1 byt 
    }
    while((BLE_MODULE->STA.B[0] & SPI_STA_RXF_mask_b0) == 0);       // Wait RDAT not empty
    BLE_MODULE->RDAT.B[0];                                          // Clear RDAT
    
    for (i=0;i<len;i++)                                             // Waiting  
    {
        BLE_MODULE->TDAT.B[0] = 0xff;                               // Write 1 byt
        while((BLE_MODULE->STA.B[0] & SPI_STA_RXF_mask_b0) == 0);   // Wait RDAT not empty
        *(pBuf+i) = BLE_MODULE->RDAT.B[0];                          // Read data
    }
       /*wait tCF transm complete*/
    SPI_NSS = 1;                                                    // NSS = 1
    
    if(&BLE_MODULE->STA.W == &SPI0->STA.W)                          // When BLE module used SPI0
    {
        BLE_MODULE->CR1.B[0] = SPI_CR1_RDAT_CLR_mask_b0;            // Clear RX buffe data
    }
    else
    {
        BLE_MODULE->CR4.B[0] = URT_CR4_RDAT_CLR_mask_b0;            // Clear RX buffe data
    }
    return 0;
}


//////DO NOT REMOVE, used in ble lib///////
void SysClk8to48(void)
{
}
void SysClk48to8(void)
{
}
void DisableEnvINT(void)
{
}
void EnableEnvINT(void)
{
}
void UpdateLEDValueAll(void)
{
}
void McuGotoSleepAndWakeup(void)
{
}

unsigned char aes_encrypt_HW(unsigned char *_data __attribute__((unused)), unsigned char *_key __attribute__((unused)))
{
    return 0; //Hardware AES not supported
}

