

/**
 ******************************************************************************
 *
 * @file        Sample_main_wizard.C
 *
 * @brief       This is the C code file.
 *
 * @par         Project
 *              MG32
 * @version     V1.05
 * @date        2023/04/20
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 * @note        Test APP "HC藍芽助手"
 *
 ******************************************************************************* 
 * @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_DRV.h"
#include "MG32_ChipInit.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
#define BufferSize              64              // DataBuffer size
// For EventFlag
#define TxEventFlag             0x01            // TX event flag
#define RxEventFlag             0x02            // RX event flag
// For StateFlag
#define State_ConnectFail       0x01            // State, connect fail flag
#define State_VersionFail       0x02            // State, got version fail flag
#define State_NameFail          0x04            // State, set name fail flag
#define State_PINFail           0x08            // State, set PIN fail flag
#define State_BaudrateFail      0x10            // State, set baud rate fail flag

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
volatile static uint8_t     EventFlag;                              // Event flag 
volatile static uint8_t     StateFlag;                              // State flag
volatile static uint8_t     DataBuffer[BufferSize] = {0};           // TX/RX data buffer 
volatile static uint8_t*    URT_RX_2_DataBufferIndex;               // URT0 RX to DataBuffer index
volatile static uint8_t     URT_RX_2_DataBufferReceivedNumber;      // URT0 RX to DataBuffer received number
volatile static uint8_t*    URT_TX_SourceIndex;                     // URT0 TX source index
volatile static uint8_t     URT_TX_SourceUntransferredNumber;       // URT0 TX untransferred number

volatile static uint32_t    DataBufferUpdatedIndex;                 // DataBuffer updated index
volatile static uint8_t     DataBufferUpdatedNumber;                // DataBuffer updated number
volatile static uint8_t     DataBufferGetTheMessageEnable;          // DataBuffer gets the message enable, 
                                                                    // when = 0, "DataBufferUpdatedIndex" and "DataBufferUpdatedNumber" will not update.
                                                                    // when = 1, "DataBufferUpdatedIndex" and "DataBufferUpdatedNumber" will update.
volatile static uint8_t     UpdateCnt;                              // Updaet "DataBuffer updated index" and "updated" counter.


static uint8_t AT[]             = {"AT"};
static uint8_t AT_VERSION[]     = {"AT+VERSION"};
static uint8_t AT_BAUDx[]       = {"AT+BAUD4"};
static uint8_t AT_NAME[]        = {"AT+NAMEHC-06 BLE Module"};
static uint8_t AT_PIN[]         = {"AT+PIN8888"};

/* Private function prototypes -----------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
//void URT0_IRQ (void);
//void WWDT_IRQ (void);
DRV_Return InitTick(uint32_t TickClock, uint32_t TickPriority);
void Delay(__IO uint32_t DelayTime);
void BLE_TransmitData (uint8_t* TX_Index, uint8_t TX_Number);
void SysTick_Handler(void);
void URT0_IRQHandler(void);
void Sample_URT0_Init (void);

/* External vairables --------------------------------------------------------*/



/**
 *******************************************************************************
 * @brief       If the device implements the SysTick timer, a SysTick exception 
 *              is an exception the system timer generates when it reaches zero. 
 *              Software can also generate a SysTick exception. In an OS 
 *              environment, the device can use this exception as system tick.
 * @return      No
 *******************************************************************************
 */
void SysTick_Handler(void)
{
    // ------------------------------------------------------------------------
    // SysTick ISR
    // ------------------------------------------------------------------------
    /* USER CODE BEGIN SysTick_IRQ 0 */
    // to do...
    /* USER CODE END SysTick_IRQ 0 */
    IncTick();
    
    UpdateCnt++;                                                            // UpdateCnt +1
    // When UpdateCnt count 20ms
    if(UpdateCnt >= 20)
        UpdateCnt = 0;
    
    // When "DataBufferGetTheMessageEnable" = 1 and count 20ms
    if((UpdateCnt == 0) && (DataBufferGetTheMessageEnable != 0))
    {
        // When URTx RX buffer is not empty.
        if(URT_RX_2_DataBufferReceivedNumber != 0)                         
        {
            EventFlag |= RxEventFlag;                                       // Enable RxEventFlag;
            DataBufferUpdatedNumber = URT_RX_2_DataBufferReceivedNumber;    // Update DataBufferUpdatedNumber
            DataBufferUpdatedIndex = (uint32_t) URT_RX_2_DataBufferIndex;   // Update DataBufferUpdatedIndex
            URT_RX_2_DataBufferReceivedNumber = 0;                          // Clear URT_RX_2_DataBufferReceivedNumber
        }
    }
}


/**
 *******************************************************************************
 * @brief       WWDT module interrupt service routine.
 * @details     Refresh WWDT counter & clear interrup flag.
 * @return      No
 *******************************************************************************
 */
void URT0_IRQHandler(void)
{ 
    // When URT0 received data
    if((URT0->STA.W & URT_IT_RX) != 0)
    {
        *URT_RX_2_DataBufferIndex = URT0->RDAT.B[0];                    // URTx RX data to DataBuffer
        URT_RX_2_DataBufferIndex++;                                     // URT_RX_2_DataBufferIndex ++
        URT_RX_2_DataBufferReceivedNumber++;                            // RURT_RX_2_DataBufferReceivedNumber ++
        
        // When URT_RX_2_DataBufferIndex over DataBuffer range
        if(URT_RX_2_DataBufferIndex > &DataBuffer[63])                  // When next store address over DataBuffer range
        {
            URT_RX_2_DataBufferIndex = &DataBuffer[0];                  // Update URT_RX_2_DataBufferIndex to DataBuffer start address
        }
        URT0->STA.W = URT_IT_RX;                                        // Clear URTx RX event flag
    }
    // When TXF or TCF happened
    if((URT0->STA.W & ((URT0->INT.W) & (URT_IT_TX | URT_IT_TC))) != 0)
    {
        URT0->STA.W = (URT_IT_TX | URT_IT_TC);                          // Clear URTx TXF and TCF event flag
        
        // When URT_TX_SourceUntransferredNumber not 0
        if(URT_TX_SourceUntransferredNumber != 0)
        {
            URT_TX_SourceIndex++;                                       // URT_TX_SourceIndex ++
            
            // When URT_TX_SourceIndex is between &DataBuffer[0] and &DataBuffer[63]+1
            if((URT_TX_SourceIndex >= &DataBuffer[0]) &&
               (URT_TX_SourceIndex <= (&DataBuffer[63]+1)))
            {
                
                // When URT_TX_SourceIndex overflow DataBuffer[63]
                if(URT_TX_SourceIndex > &DataBuffer[63])
                {
                    URT_TX_SourceIndex = &DataBuffer[0];                // Update URT_TX_SourceIndex to DataBuffer start address
                }
            }
            
            URT_TX_SourceUntransferredNumber--;                         // URT_TX_SourceUntransferredNumber --
            URT0->TDAT.B[0] = *URT_TX_SourceIndex;                      // Move date to URT TDAT
        }
    }
}


 /**
 *******************************************************************************
 * @brief	   Sample URT0 initial (TX at PC0, RX at PC1)
 * @details    
 * @return      
 * @exception   No
 * @note
 * @par         Example
 * @code        
    Sample_URT0_Init();
 * @endcode
 *******************************************************************************
 */
void Sample_URT0_Init (void)
{
    URT_BRG_TypeDef  URT_BRG;
    URT_Data_TypeDef DataDef;
    PIN_InitTypeDef PINX_InitStruct;
    
    
    
    //==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
    PINX_InitStruct.PINX_Mode				= PINX_Mode_Quasi_IO;           // Setting URT0_TX at PC0, URT_RX at PC1
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Enable;
    PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;
    PINX_InitStruct.PINX_OUTDrive           = PINX_OUTDrive_Level0;
    PINX_InitStruct.PINX_FilterDivider      = PINX_FilterDivider_Bypass;
    PINX_InitStruct.PINX_Inverse            = PINX_Inverse_Disable;
    PINX_InitStruct.PINX_Alternate_Function = 10;
    GPIO_PinMode_Config(PINC(0),&PINX_InitStruct);
    GPIO_PinMode_Config(PINC(1),&PINX_InitStruct);
    
    //=====Set Clock=====//
    //---Set BaudRate---//
    URT_BRG.URT_InternalClockSource = URT_BDClock_PROC;
    URT_BRG.URT_BaudRateMode = URT_BDMode_Separated;
    URT_BRG.URT_PrescalerCounterReload = 0;	                //Set PSR
    URT_BRG.URT_BaudRateCounterReload = 155;	            //Set RLR
    URT_BaudRateGenerator_Config(URT0, &URT_BRG);   		//BR9600 = f(CK_URTx)/(PSR+1)/(RLR+1)/(OS_NUM+1)
    URT_BaudRateGenerator_Cmd(URT0, ENABLE);	            //Enable BaudRateGenerator
    //---TX/RX Clock---//
    URT_TXClockSource_Select(URT0, URT_TXClock_Internal);	//URT_TX use BaudRateGenerator
    URT_RXClockSource_Select(URT0, URT_RXClock_Internal);	//URT_RX use BaudRateGenerator
    URT_TXOverSamplingSampleNumber_Select(URT0, 7);	        //Set TX OS_NUM
    URT_RXOverSamplingSampleNumber_Select(URT0, 7);	        //Set RX OS_NUM
    URT_RXOverSamplingMode_Select(URT0, URT_RXSMP_3TIME);
    URT_TX_Cmd(URT0, ENABLE);	                            //Enable TX
    URT_RX_Cmd(URT0, ENABLE);	                            //Enable RX
    
    //=====Set Mode=====//
    //---Set Data character config---//
    DataDef.URT_TX_DataLength  = URT_DataLength_8;
    DataDef.URT_RX_DataLength  = URT_DataLength_8;
    DataDef.URT_TX_DataOrder   = URT_DataTyped_LSB;
    DataDef.URT_RX_DataOrder   = URT_DataTyped_LSB;
    DataDef.URT_TX_Parity      = URT_Parity_No;
    DataDef.URT_RX_Parity      = URT_Parity_No;
    DataDef.URT_TX_StopBits    = URT_StopBits_1_0;
    DataDef.URT_RX_StopBits    = URT_StopBits_1_0;
    DataDef.URT_TX_DataInverse = DISABLE;
    DataDef.URT_RX_DataInverse = DISABLE;
    URT_DataCharacter_Config(URT0, &DataDef);
    //---Set Mode Select---//
    URT_Mode_Select(URT0, URT_URT_mode);
    //---Set DataLine Select---//
    URT_DataLine_Select(URT0, URT_DataLine_2);
    
    //=====Set Error Control=====//
    // to do...
    
    //=====Set Bus Status Detect Control=====//
    // to do...
    
    //=====Set Data Control=====//
//    URT_RXShadowBufferThreshold_Select(URT0, URT_RXTH_1BYTE);
//    URT_IdlehandleMode_Select(URT0, URT_IDLEMode_No);
//    URT_TXGuardTime_Select(URT0, 0);
    // to do...
    
    //=====Enable URT Interrupt=====//
    URT_IT_Config(URT0, (URT_IT_TC | URT_IT_TX | URT_IT_RX) , ENABLE);      // Enable URT0 TX_IE, RX_IE and TC_IE
    URT_ITEA_Cmd(URT0, ENABLE);                                             // Enable URT0 interrupt all enable
    NVIC_EnableIRQ(URT0_IRQn);                                              // M0 NVIC URT0 configure.
    NVIC_SetPriority(URT0_IRQn, 0x0);                                       // M0 NVIC URT0 Priority.

    //=====Enable URT=====//
    URT_Cmd(URT0, ENABLE);
		
	//==See MG32_URT0_IRQ.c when interrupt in
}


/**
 *******************************************************************************
 * @brief	    BLE transmit data
 * @details     
 * @param[in]   TX_Index:
 *  @arg\b          0x20000000 ~ 0x20001000.
 * @param[in]   TX_Number:
 *  @arg\b          1 ~255
 * @return      None.
 * @exception   No
 * @note 
 * @par         Example
 * @code
    BLE_TransmitData(&DataBuffer[0], 64);
 * @endcode
 *******************************************************************************
 */
void BLE_TransmitData (uint8_t* TX_Index, uint8_t TX_Number)
{
    URT_TX_SourceUntransferredNumber += (TX_Number - 1);    // Update URT_TX_SourceUntransferredNumber
    URT_TX_SourceIndex = TX_Index;                          // Update URT_TX_SourceIndex
    
    // When URT_TX_SourceIndex is between &DataBuffer[0] and &DataBuffer[63]+1
    if((URT_TX_SourceIndex >= &DataBuffer[0]) &&
       (URT_TX_SourceIndex <= (&DataBuffer[63]+1)))
    {
        // When URT_TX_SourceIndex overflow DataBuffer[63]
        if(URT_TX_SourceIndex > &DataBuffer[63])
        {
            URT_TX_SourceIndex = &DataBuffer[0];            // Update URT_TX_SourceIndex to DataBuffer start address
        }
    }
    URT0->TDAT.B[0] = *URT_TX_SourceIndex;                  // Move date to URT TDAT
}




int main(void)
{    
    uint8_t     CNT;
    uint32_t    TX_Now_Index; 
    
    
    
    
    /* Initial DataBuffer */
    // Clear DataBuffer 
    for(CNT=0; CNT<64; CNT++)
    {
        DataBuffer[CNT] = 0;
    }
    DataBufferGetTheMessageEnable = 0;                                      // Disable DataBuffer get message function.
    EventFlag = 0;                                                          // Clear EventFlag
    StateFlag = 0;                                                          // Clear StateFlag
    
    // ------------------------------------------------------------------------
    // chip initial (User can enable CSC, GPIO, TM, ADC, EXIC ... wizard)
    // ------------------------------------------------------------------------
    ChipInit();                                                             // 
    InitTick(12000000, 0);                                                  // Setting systik 1ms

    Sample_URT0_Init();                                                     // Init URT0 TX at PC0 and RX at PC1

    /* Check HC-06 connect success */
    do
    {
        StateFlag = 0;                                                      // Clear StateFlag
        URT_RX_2_DataBufferIndex = &DataBuffer[0];                          // Setting RX_BufferIndex to &DataBuffer[0]
        URT_RX_2_DataBufferReceivedNumber = 0;                              // Clear RX_B_BufferNumber
        BLE_TransmitData(&AT[0], 2);                                        // To HC-06 command "AT"
        Delay(1000);                                                        // Waiting 1s
        if((DataBuffer[0] != 'O') &&                                        // When check connect fail.
           (DataBuffer[1] != 'K'))                                               
        {
            StateFlag |= State_ConnectFail;                                 // Setting State_ConnectFail flag
        } 
    }while(StateFlag != 0);                                                 // When connect test fail.
    
    
    /* Get HC-06 version */
    URT_RX_2_DataBufferIndex = &DataBuffer[0];                              // Update URT_RX_2_DataBufferIndex to &DataBuffer[0]
    URT_RX_2_DataBufferReceivedNumber = 0;                                  // Clear URT_RX_2_DataBufferReceivedNumber
    BLE_TransmitData(&AT_VERSION[0], 2);                                    // To HC-06 command "AT+VERSION"
    Delay(1000);                                                            // Waiting 1s
    if((DataBuffer[0] != 'O') &&                                            // When get version fail.
       (DataBuffer[1] != 'K'))
    {
        StateFlag |= State_VersionFail;                                     // Setting State_VersionFail flag
    } 
    
    
    /* Setting HC-06 baud rate 9600 */
    URT_RX_2_DataBufferIndex = &DataBuffer[0];                              // Update URT_RX_2_DataBufferIndex to &DataBuffer[0]
    URT_RX_2_DataBufferReceivedNumber = 0;                                  // Clear URT_RX_2_DataBufferReceivedNumber 
    BLE_TransmitData(&AT_BAUDx[0], 8);                                      // To HC-06 command "AT+BAUD4"
    Delay(1000);                                                            // Waiting 1s
    if((DataBuffer[0] != 'O') &&                                            // When set baudrate fail
       (DataBuffer[1] != 'K'))
    {
        StateFlag |= State_BaudrateFail;                                    // Setting State_BaudrateFail flag
    } 

    
    /* Setting BLE device name */
    URT_RX_2_DataBufferIndex = &DataBuffer[0];                              // Update URT_RX_2_DataBufferIndex to &DataBuffer[0]
    URT_RX_2_DataBufferReceivedNumber = 0;                                  // Clear URT_RX_2_DataBufferReceivedNumber 
    BLE_TransmitData(&AT_NAME[0], 23);                                      // To HC-06 command "AT+NAMEHC-06 BLE Module"
    Delay(2000);                                                            // Waiting 2s            
    if((DataBuffer[0] != 'O') &&                                            // When set baudrate fail
       (DataBuffer[1] != 'K'))
    {
        StateFlag |= State_NameFail;                                        // Setting State_NameFail flag
    } 


    /* Setting PIN */
    URT_RX_2_DataBufferIndex = &DataBuffer[0];                              // Update URT_RX_2_DataBufferIndex to &DataBuffer[0]
    URT_RX_2_DataBufferReceivedNumber = 0;                                  // Clear URT_RX_2_DataBufferReceivedNumber 
    BLE_TransmitData(&AT_PIN[0], 10);                                       // To HC-06 command "AT+PIN8888"
    Delay(1000);                                                            // Waiting 1s
    if((DataBuffer[0] != 'O') &&                                            // When set baudrate fail
       (DataBuffer[1] != 'K'))                                      
    {
        StateFlag |= State_PINFail;                                         // Setting State_PINFail flag
    } 
    
    DataBufferGetTheMessageEnable = 1;                                      // Enable DataBuffer get message function. 
                                                                            // "DataBufferUpdatedIndex" and "DataBufferUpdatedNumber" will update.
    
    while(1)
    {
        // When RX event flag happened
        if((EventFlag & RxEventFlag) != 0)       
        {
            // When DataBuffer is updated, the data overflow DataBuffer[63].
            if((DataBufferUpdatedIndex - (uint32_t)&DataBuffer[0]) < DataBufferUpdatedNumber) 
            {                                                                       // Get TX_Now_Index
                TX_Now_Index = ((uint32_t) &DataBuffer[63] - (DataBufferUpdatedNumber - (DataBufferUpdatedIndex - (uint32_t) &DataBuffer[0]))) + 1;
            }
            else
            {                                                                       
                TX_Now_Index = DataBufferUpdatedIndex - DataBufferUpdatedNumber;    // Get TX_Now_Index
            }
            BLE_TransmitData((uint8_t *) TX_Now_Index, DataBufferUpdatedNumber);    // BLE TX data
            EventFlag &= ~RxEventFlag;                                              // Clear RxEventFlag
        }
    } 
}



