
 /**
 ******************************************************************************
 *
 * @file        MG32_ARGB_WS2812.c
 * @brief      The code is Using URT of MG32 to control ARGB 
 
 * @par         Project
 *              MG32
 * @version     V1.04
 * @date        2025/06/10
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 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__Common_DRV.h"
#include "MG32_GPIO_DRV.h"
#include "MG32_EXIC_DRV.h"
#include "MG32_TM_DRV.h"
#include "MG32_URT_DRV.h"
#include "MG32_SPI_DRV.h"
#include "MG32_ARGB_WS2812.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SMP_ARGB_PIECE            14            /*!< Sample 14 pieces ARGB (The define can not to equal 1 )*/
#define SMP_ARGB_COLLOR_MAX       50            /*!< The ARGB sample code max color.*/ 
            
#define SMP_ARGB_DATASIZE         3 
#define SMP_ARGB_G                0             /*!< ARGB green color data shift.*/
#define SMP_ARGB_R                1             /*!< ARGB red color data shift.*/
#define SMP_ARGB_B                2             /*!< ARGB bule color data shift.*/
    
#define SMP_ARGB_DEFAULT_COLOR    6             /*!< Total Color setting.*/

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ARGBCTR_TypeDef   ARGB0;                        /*!< Control ARGB parameter.*/
static uint8_t volatile  ARGB_UpdateFlag;              /*!< Calculate next data flag.*/
    
static uint8_t SMP_ARGB_UpdateBUF[SMP_ARGB_PIECE][3];  /*!< ARGB update buffer.*/                
                                                
static uint8_t SMP_ARGB_DramaBUF[SMP_ARGB_PIECE][3];   /*!<.The buffer is use for ARGB calculate.*/

static uint8_t SMP_ARGBDefault_TABLE[SMP_ARGB_DEFAULT_COLOR][3] = {
                                                                    {   0 ,  50 ,   0},    // ARGB0 (Input first): [G : R : B ] = [  0, 50,  0]
                                                                    {  50 ,  50 ,   0},    // ARGB1              : [G : R : B ] = [ 50, 50,  0]
                                                                    {  50 ,   0 ,   0},    // ARGB2              : [G : R : B ] = [ 50,  0,  0] 
                                                                    {  50 ,   0 ,  50},    // ARGB3              : [G : R : B ] = [ 50,  0, 50] 
                                                                    {   0 ,   0 ,  50},    // ARGB4              : [G : R : B ] = [  0,  0, 50] 
                                                                    {   0 ,  50 ,  50}     // ARGB5              : [G : R : B ] = [  0, 50, 50]
                                                                  };


/* Private function prototypes -----------------------------------------------*/                                                            
void Delay_us(uint8_t DLY);
void Sample_URT_ARGB_SendData( ARGBCTR_TypeDef* sARGB, uint32_t UpDate_ARGBCount);
void Sample_URT_ARGB_SendData_IT( ARGBCTR_TypeDef* sARGB , uint32_t UpDate_ARGBCount);                                                                  
void ARGB_IRQHandler( ARGBCTR_TypeDef* sARGB);
void Sample_URT_ARGB_Update(ARGBCTR_TypeDef* sARGB , uint32_t UpDate_ARGBCount );
void Sample_URT_RGB_CloseAll(ARGBCTR_TypeDef* sARGB );
void ARGB_UpdateDramaMode( ARGBCTR_TypeDef* sARGB );
void SMP_ARGB_PercentageTable( uint8_t* ARGB_PEBuf, uint32_t molecular ,uint32_t Denominator, uint8_t LoopTime);
void SMP_ARGB_SignalColorDrama(ARGBCTR_TypeDef* sARGB);
void SMP_ARGB_BreathDrama(ARGBCTR_TypeDef* sARGB);
void SMP_ARGB_RainBowDrama(ARGBCTR_TypeDef* sARGB);
void SMP_ARGB_MapphingDrama(ARGBCTR_TypeDef* sARGB);
void SMP_ARGB_WDropDrama( ARGBCTR_TypeDef* sARGB );
void SMP_ARGB_MovingDrama( ARGBCTR_TypeDef* sARGB );
void SMP_ARGB_TwoMovingDrama( ARGBCTR_TypeDef* sARGB );
void ARGB_UpdateDrama( ARGBCTR_TypeDef* sARGB );
 
void EXINT0_IRQHandler(void);                                                                  
void URT0_IRQHandler(void);
void URT123_IRQHandler(void);
void SPI0_IRQHandler(void);
void TM0x_IRQHandler(void);

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



/**
 * @name	Control ARGB  Function.
 *   		
 */ 
///@{
/**
 *******************************************************************************
 * @brief       Delay us
 * @details  
 * @param[in]   DLY:
 *  @arg\b          0 ~ 255.
 * @return
 * @note
 * @par         Example
 * @code
    Delay_us(80);
 * @endcode
 *******************************************************************************
 */
void Delay_us(uint8_t DLY)
{
    uint8_t CNT;

    CNT = DLY;
    do
    {
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();    __NOP();    __NOP();    __NOP();    __NOP();
        __NOP();
        CNT--;
    }while(CNT>0);
}                                                           
 /**
 *******************************************************************************
 * @brief	   UART use blocking mode to update ARGB  
 * @details     
 * @param      sARGB            : ARGB handle.
 * @param      UpDate_ARGBCount : Update ARGB numbers.
 * @return      
 * @note       No
 *******************************************************************************
 */
void Sample_URT_ARGB_SendData( ARGBCTR_TypeDef* sARGB, uint32_t UpDate_ARGBCount)
{
    uint8_t  DataBitCnt;
    uint8_t  pTXData;
    uint8_t  pDataBitCmp;
    ctype    pDataBit;

    
    sARGB->State = ARGB_BUSY;
    
    //===============================================================================================
    //Set ARGB handle parameter.
    sARGB->TotalCount   = (UpDate_ARGBCount * 3);        //ARGB data byte is 3 bytes in the sample code.
    sARGB->DataCount    = 0;
    sARGB->DataBitCmp   = 0;
    
    pTXData = 0;
    //===============================================================================================
    //Enable timeout timer & timeout timer interrupt.
    if( (sARGB->ARGB_UsePeripheral & ARGB_PERIPHERAL_MASK) == ARGB_PERIPHERAL_URT_MASK)
    {
        SET_BIT( *(sARGB->ARGB_REG_TMO) , URT_TMOUT_TMO_RST_mask_w); 
        SET_BIT( *(sARGB->ARGB_REG_STA) , sARGB->ARGB_STA_TMO); 
        SET_BIT( *(sARGB->ARGB_REG_TMO) , sARGB->ARGB_TMO_EN);
        
        while( (READ_REG( *(sARGB->ARGB_REG_STA)) & sARGB->ARGB_STA_TMO)==0);
        CLEAR_BIT( *(sARGB->ARGB_REG_TMO) , sARGB->ARGB_TMO_EN);
        
        SET_BIT( *(sARGB->ARGB_REG_CRX) , URT_CR4_TDAT_CLR_mask_w); 
    }
    else
    {
        SET_BIT( *(sARGB->ARGB_REG_CRX) , SPI_CR1_TDAT_CLR_mask_w);
        WRITE_REG( *(sARGB->ARGB_REG_TXData) , 0);
        Delay_us ((sARGB->TRES));
        
    }

    //===============================================================================================
    //Blocking mode update ARGB data
    do{
        if( sARGB->DataBitCmp == 0x00)
        {
            pTXData    = sARGB->updateBuf[ sARGB->DataCount];            
            pDataBitCmp = 0x80;
        }
        else
        {
            pDataBitCmp = sARGB->DataBitCmp; 
            sARGB->TotalCount = sARGB->TotalCount - 1;
            sARGB->DataCount  = sARGB->DataCount  + 1;
        }
        for(DataBitCnt = 0; DataBitCnt < 4; DataBitCnt++)
        {
            if((pTXData & pDataBitCmp)==0)
            {
                pDataBit.B[DataBitCnt] = sARGB->ARGB_LOGIC_0;
            }
            else
            {
                pDataBit.B[DataBitCnt] = sARGB->ARGB_LOGIC_1;
            }
            pDataBitCmp = pDataBitCmp >> 1;
        }
        while( (READ_REG(*(sARGB->ARGB_REG_STA)) & sARGB->ARGB_STA_TX) == 0);
        WRITE_REG( *(sARGB->ARGB_REG_TXData) , pDataBit.W);
        sARGB->DataBitCmp = pDataBitCmp;

    }while(sARGB->TotalCount!=0 );
    
     //===============================================================================================
    //Wait last data for transmission end.
    while( (READ_REG(*(sARGB->ARGB_REG_STA)) & sARGB->ARGB_STA_TC) == 0);
    
    
    sARGB->State = ARGB_READY;
}

 /**
 *******************************************************************************
 * @brief	  UART use interrupt mode to update ARGB  
 * @details     
 * @param      sARGB            : ARGB handle.
 * @param      UpDate_ARGBCount : Update ARGB numbers.
 * @return      
 * @note       No
 *******************************************************************************
 */
void Sample_URT_ARGB_SendData_IT( ARGBCTR_TypeDef* sARGB , uint32_t UpDate_ARGBCount)
{
    
    //===============================================================================================
    //Set ARGB handle parameter.
    sARGB->State        = ARGB_BUSY;
    sARGB->DataBitCmp   = 0;
    sARGB->TotalCount   = (UpDate_ARGBCount * 3);
    sARGB->DataCount    = 0;
    //===============================================================================================
    //Enable timeout timer & timeout timer interrupt.
    WRITE_REG( *(sARGB->ARGB_REG_STA), sARGB->ARGB_STA_TMO);
    if( (sARGB->ARGB_UsePeripheral & ARGB_PERIPHERAL_MASK) == ARGB_PERIPHERAL_URT_MASK)
    {
        SET_BIT( *(sARGB->ARGB_REG_TMO) , URT_TMOUT_TMO_RST_mask_w); 
        SET_BIT( *(sARGB->ARGB_REG_CRX) , URT_CR4_TDAT_CLR_mask_w); 
        SET_BIT( *(sARGB->ARGB_REG_INT) , sARGB->ARGB_STA_TMO); 
        SET_BIT( *(sARGB->ARGB_REG_TMO) , sARGB->ARGB_TMO_EN);
    }
    else
    {
        SET_BIT( *(sARGB->ARGB_REG_CRX) , SPI_CR1_TDAT_CLR_mask_w);
        WRITE_REG( *(sARGB->ARGB_REG_TXData) , 0x00);
        Delay_us ((sARGB->TRES));
        SET_BIT( *(sARGB->ARGB_REG_INT) , sARGB->ARGB_STA_TX);
    }
}


 /**
 *******************************************************************************
 * @brief	   Handle ARGB (URT) interrupt request. 
 * @details     
 * @param[in]  sARGB : ARGB handle.
 * @return      
 * @note       No
 *******************************************************************************
 */
void ARGB_IRQHandler( ARGBCTR_TypeDef* sARGB)
{
    uint32_t URTIRQ_Flag;
    uint8_t  DataBitCnt;
    uint8_t  DataBitCmp;
    ctype    DataBit;

    URTIRQ_Flag = (READ_REG(*(sARGB->ARGB_REG_STA)) & READ_REG( (*sARGB->ARGB_REG_INT)));      // Get Interrupt flag.
     
    //===============================================================================================
    // In transmit.
    if( URTIRQ_Flag & sARGB->ARGB_STA_TX)
    {
        //--------------------------------------------------------
        //Transmit bit7 ~ bit4.
        if( sARGB->DataBitCmp == 0x00)
        {
            sARGB->TXData = sARGB->updateBuf[ sARGB->DataCount];         
            DataBitCmp = 0x80;
        }
        //--------------------------------------------------------
        //Transmit bit3 ~ bit0.
        else
        {
            DataBitCmp = sARGB->DataBitCmp; 
            sARGB->TotalCount = sARGB->TotalCount - 1;
            sARGB->DataCount  = sARGB->DataCount  + 1;
        }
        //--------------------------------------------------------
        //Regroup data.
        for(DataBitCnt = 0; DataBitCnt < 4; DataBitCnt++)
        {
            if((sARGB->TXData & DataBitCmp)==0)
            {
                DataBit.B[DataBitCnt] = sARGB->ARGB_LOGIC_0;
            }
            else
            {
                DataBit.B[DataBitCnt] = sARGB->ARGB_LOGIC_1;
            }
            DataBitCmp = DataBitCmp >> 1;
        }
        WRITE_REG( *(sARGB->ARGB_REG_TXData) , DataBit.W);
        sARGB->DataBitCmp = DataBitCmp;

        //--------------------------------------------------------
        if(sARGB->TotalCount!=0)
        {
            return;
        }
        //--------------------------------------------------------
        //Last data write to TX data.
        else
        {
            *(sARGB->ARGB_REG_INT) |= sARGB->ARGB_STA_TC;
            *(sARGB->ARGB_REG_INT) &= (~sARGB->ARGB_STA_TX);
        }
    }
    ///===============================================================================================
    // Reset time handle.
    else if( URTIRQ_Flag & sARGB->ARGB_STA_TMO)
    {
        *(sARGB->ARGB_REG_TMO) &= (~sARGB->ARGB_TMO_EN);
        *(sARGB->ARGB_REG_INT) &= (~sARGB->ARGB_STA_TMO);
        *(sARGB->ARGB_REG_STA) = (sARGB->ARGB_STA_TMO | sARGB->ARGB_STA_UG);
        *(sARGB->ARGB_REG_INT) |= sARGB->ARGB_STA_TX;
        return;
    }
    //===============================================================================================
    // Wrap up transmission 
    if( READ_REG(*(sARGB->ARGB_REG_STA)) & sARGB->ARGB_STA_TC)
    {
        *(sARGB->ARGB_REG_INT) &= (~sARGB->ARGB_STA_TC);
        sARGB->State = ARGB_READY;
        return;
    }
}
 /**
 *******************************************************************************
 * @brief	  URT initial
 * @details    
 * @param[in] sARGB : ARGB Handle. (only need set following parameter)
 *   @arg\b   URTX :  URT register basic address.
 *   @arg\b   TRES :  ARGB reset time. ( 0 ~ 255 ARGB bit time)
 * @return       
 * @note       
 *    \n  Because URT one character data is ARGB one bit data , 
 *    \n  (1 / (Baudrate * 12)) have to equal (1.25us +/- 150ns if ARGB is  WS2812).       
 *******************************************************************************
 */
void Sample_ARGB_Init(ARGBCTR_TypeDef *sARGB )
{
    URT_BRG_TypeDef  URT_BRG;
    URT_Data_TypeDef DataDef;
    URT_Struct*      ARGB_URTX;
    SPI_Struct*      ARGB_SPIX;

    sARGB->State = ARGB_BUSY;

    
    
    if( (sARGB->ARGB_UsePeripheral & ARGB_PERIPHERAL_MASK) == ARGB_PERIPHERAL_URT_MASK)
    {
        switch( sARGB->ARGB_UsePeripheral)
        {
            #if defined(URT0_Base)
            case ARGB_PERIPHERAL_URT0:
                                      ARGB_URTX = URT0;
                                      sARGB->ARGB_IRQ  = URT0_IRQn;
                                      break;
            #endif
            #if defined(URT1_Base)
            case ARGB_PERIPHERAL_URT1:
                                      ARGB_URTX = URT1;
                                      sARGB->ARGB_IRQ   = URT123_IRQn;
                                      break;
            #endif
            #if defined(URT2_Base)
            case ARGB_PERIPHERAL_URT2:
                                      ARGB_URTX = URT2;
                                      sARGB->ARGB_IRQ   = URT123_IRQn;
                                      break;
            #endif
            #if defined(URT3_Base)
            case ARGB_PERIPHERAL_URT3:
                                      ARGB_URTX = URT3;
                                      sARGB->ARGB_IRQ   = URT123_IRQn;
                                      break;
            #endif
            default:
                                      sARGB->State = ARGB_FAIL;
                                      return;
        }
        //===============================================================================================
        //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  = 0;	                        //Set RLR
        URT_BaudRateGenerator_Config(ARGB_URTX, &URT_BRG);		        //Baudrate = f(CK_URTx)/(PSR+1)/(RLR+1)/(OS_NUM+1)
        URT_BaudRateGenerator_Cmd(ARGB_URTX, ENABLE);	                //Enable BaudRateGenerator
        
        //--------------------------------------------------------
        //TX/RX Clock
        URT_TXClockSource_Select(ARGB_URTX, URT_TXClock_Internal);	    //URT_TX use BaudRateGenerator
        URT_RXClockSource_Select(ARGB_URTX, URT_RXClock_Internal);	    //URT_RX use BaudRateGenerator
        URT_TXOverSamplingSampleNumber_Select(ARGB_URTX, 4);	        //Set TX OS_NUM
        URT_RXOverSamplingSampleNumber_Select(ARGB_URTX, 4);	        //Set RX OS_NUM
        URT_RXOverSamplingMode_Select(ARGB_URTX, URT_RXSMP_3TIME);
        URT_TX_Cmd(ARGB_URTX, ENABLE);	                                //Enable TX
        URT_RX_Cmd(ARGB_URTX, ENABLE);	                                //Enable RX (for Timeout timer )
        //===============================================================================================
        //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_MSB;
        DataDef.URT_RX_DataOrder   = URT_DataTyped_MSB;
        DataDef.URT_TX_Parity      = URT_Parity_All_H;
        DataDef.URT_RX_Parity      = URT_Parity_All_H;
        DataDef.URT_TX_StopBits    = URT_StopBits_2_0;
        DataDef.URT_RX_StopBits    = URT_StopBits_2_0;
        DataDef.URT_TX_DataInverse = DISABLE;
        DataDef.URT_RX_DataInverse = DISABLE;
        URT_DataCharacter_Config(ARGB_URTX, &DataDef);
        
        //--------------------------------------------------------
        //Set Mode Select
        URT_Mode_Select(ARGB_URTX, URT_URT_mode);
        
        //--------------------------------------------------------
        //Set DataLine Select
        URT_DataLine_Select(ARGB_URTX, URT_DataLine_2);
        
        
        //===============================================================================================
        //Set Data Control
        URT_TXGuardTime_Select(ARGB_URTX, 0);    
        URT_TXInverse_Cmd( ARGB_URTX , ENABLE);                              // Data output signal invere.
        
        //===============================================================================================
        //TRst time setting. (Use timeout timer of URT )
        URT_TimeoutMode_Select(ARGB_URTX , URT_TMOMDS_General);              
        URT_TimeoutTimerClockSource_Select( ARGB_URTX, URT_TMOCLK_BitTime);
        URT_SetTimeoutTimerCompare(ARGB_URTX, (sARGB->TRES *12));
        URT_TimeroutTimer_Cmd( ARGB_URTX, DISABLE);
        
        //===============================================================================================
        //Enable URT Interrupt
        URT_IT_Config(ARGB_URTX, (URT_IT_TMO | URT_IT_TX | URT_IT_TC),  DISABLE);
        URT_IT_Config( ARGB_URTX , URT_IT_UG , ENABLE);
        URT_ITEA_Cmd(ARGB_URTX,ENABLE);
        NVIC_EnableIRQ(sARGB->ARGB_IRQ );
        
        //===============================================================================================
        //Enable URT
        URT_Cmd(ARGB_URTX, ENABLE);
        //===============================================================================================
        //Set ARGB handle state.
        sARGB->ARGB_LOGIC_0    = ARGB_LOGIC_URT_0;
        sARGB->ARGB_LOGIC_1    = ARGB_LOGIC_URT_1;
        
        sARGB->ARGB_REG_INT    = &(ARGB_URTX->INT.W);
        sARGB->ARGB_REG_STA    = &(ARGB_URTX->STA.W);
        sARGB->ARGB_REG_TXData = &(ARGB_URTX->TDAT.W);
        sARGB->ARGB_REG_TMO    = &(ARGB_URTX->TMOUT.W);
        sARGB->ARGB_REG_CRX    = &(ARGB_URTX->CR4.W);
        
        sARGB->ARGB_STA_TX     = URT_STA_TXF_mask_w;
        sARGB->ARGB_STA_TC     = URT_STA_TCF_mask_w;
        sARGB->ARGB_STA_TMO    = URT_STA_TMOF_mask_w;
        sARGB->ARGB_STA_UG     = URT_STA_UGF_mask_w;
        sARGB->ARGB_TMO_EN     = URT_TMOUT_TMO_EN_mask_w;
    }
    else
    {
        switch( sARGB->ARGB_UsePeripheral)
        {
            case ARGB_PERIPHERAL_SPI0:
                                      ARGB_SPIX = SPI0;
                                      sARGB->ARGB_IRQ  = SPI0_IRQn;
                                      break;
            default:
                                      sARGB->State = ARGB_FAIL;
                                      return;
        }
        
        //========================================================
        //Set Clock
        
        //--------------------------------------------------------
        //Set BaudRate
        SPI_PreDivider_Select(ARGB_SPIX, SPI_PDIV_1);
        SPI_Prescaler_Select(ARGB_SPIX, SPI_PSC_3);
        SPI_Divider_Select(ARGB_SPIX, SPI_DIV_2);
        SPI_Clock_Select(ARGB_SPIX, SPI_CK_SPIx_PR);
        
        //========================================================
        //Set Mode
        SPI_ModeAndNss_Select(ARGB_SPIX, SPI_MasterWithNss);
        SPI_SingleMasterModeNssPulse_Cmd(ARGB_SPIX, ENABLE);

#if defined(MG32_2ND) || defined(MG32_3RD)
        SPI_NssIdleTime_Select(ARGB_SPIX, SPI_IDT_1T);
        SPI_IdleStateDataMode_Select(ARGB_SPIX, SPI_OutputWithTristate);
#endif         
        //--------------------------------------------------------
        //Set Data character config
        SPI_ClockPhase_Select(ARGB_SPIX, SPI_TrailingEdge);
        SPI_ClockPolarity_Select(ARGB_SPIX, SPI_Low);
        SPI_FirstBit_Select(ARGB_SPIX, SPI_MSB);
        
        //--------------------------------------------------------
        //Set DataLine Select
        SPI_DataLine_Select(ARGB_SPIX, SPI_Standard);
        SPI_DataSize_Select(ARGB_SPIX, SPI_8bits);
        
        
        //========================================================
        sARGB->ARGB_LOGIC_0    = ARGB_LOGIC_SPI_0;
        sARGB->ARGB_LOGIC_1    = ARGB_LOGIC_SPI_1;
        
        sARGB->ARGB_REG_INT    = &(ARGB_SPIX->INT.W);
        sARGB->ARGB_REG_STA    = &(ARGB_SPIX->STA.W);
        sARGB->ARGB_REG_TXData = &(ARGB_SPIX->TDAT.W);
        sARGB->ARGB_REG_CRX    = &(ARGB_SPIX->CR1.W);

        sARGB->ARGB_STA_TX     = SPI_STA_TXF_mask_w;
        sARGB->ARGB_STA_TC     = SPI_STA_TCF_mask_w;
        sARGB->ARGB_STA_UG     = 0;
        sARGB->ARGB_STA_TMO    = 0;
        //========================================================
        //Enable URT Interrupt
        CLEAR_BIT( *(sARGB->ARGB_REG_INT), ( sARGB->ARGB_STA_TX | sARGB->ARGB_STA_TC));

        SPI_ITEA_Cmd(ARGB_SPIX,ENABLE);
        NVIC_EnableIRQ(sARGB->ARGB_IRQ);
        
        //========================================================
        //Enable SPI
        SPI_Cmd(ARGB_SPIX, ENABLE);
    }
    
    sARGB->State = ARGB_READY;
    
}
///@}


/**
 * @name    Sample code is that use blocking and interrupt mode to control ARGB.
 *   		
 */ 
///@{

/**
 *******************************************************************************
 * @brief	   To trigger change the ARGBs mode.  
 * @details     
 * @param[in]  ARGB_Mode : New ARGB mode.  
 * @note       
 *******************************************************************************
 */
void Sample_URT_ARGB_UpdateTrigger( uint8_t  ARGB_Mode)
{
    ARGB0.DramaMode  = ARGB_Mode;

    ARGB0.UpdateTRG  = ARGB_UPDATE_MODE;
}
 /**
 *******************************************************************************
 * @brief	   Update ARGB status.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .
 * @param[in]  UpDate_ARGBCount : Update ARGB pieces.     
 * @note       
 *******************************************************************************
 */
void Sample_URT_ARGB_Update(ARGBCTR_TypeDef* sARGB , uint32_t UpDate_ARGBCount )
{
    uint32_t SMP_ARGB_UpdateTmp;
    
    if( (ARGB0.UpdateTRG & ARGB_UPDATE_DATA) && ARGB0.State == ARGB_READY)
    {
        ARGB0.UpdateTRG &= (~ARGB_UPDATE_DATA);
        
        for( SMP_ARGB_UpdateTmp = 0; SMP_ARGB_UpdateTmp < (UpDate_ARGBCount * SMP_ARGB_DATASIZE); SMP_ARGB_UpdateTmp++)
        {
            sARGB->updateBuf[SMP_ARGB_UpdateTmp]= sARGB->DramaBuf[SMP_ARGB_UpdateTmp];
        }
        
        if(sARGB->TXMode == ARGB_BLOCKING_MODE)
        {
            Sample_URT_ARGB_SendData(&ARGB0, UpDate_ARGBCount);
        }
        else
        {
            Sample_URT_ARGB_SendData_IT(&ARGB0 , UpDate_ARGBCount);
        }
    }
}
 /**
 *******************************************************************************
 * @brief	   Close the all ARGB.  
 * @details     
 * @param[in]  sARGB : Control ARGB data line .  
 * @note       Close ARGB piece according to SMP_ARGB_PIECE
 *******************************************************************************
 */
void Sample_URT_RGB_CloseAll(ARGBCTR_TypeDef* sARGB )
{
    uint32_t SMP_ARGB_CloseTmp;
    
    for( SMP_ARGB_CloseTmp = 0; SMP_ARGB_CloseTmp < (SMP_ARGB_PIECE * SMP_ARGB_DATASIZE); SMP_ARGB_CloseTmp++)
    {
        sARGB->DramaBuf[SMP_ARGB_CloseTmp]= 0x00;
    }
    
    sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
    
    Sample_URT_ARGB_Update(&ARGB0, SMP_ARGB_PIECE);
    
    while( sARGB->State != ARGB_READY);
    
    do{
        if( ARGB_UpdateFlag == 1)
        {
            ARGB_UpdateFlag = 0;
            SMP_ARGB_CloseTmp = SMP_ARGB_CloseTmp + 1;
        }
    }while(SMP_ARGB_CloseTmp<100);
}
 /**
 *******************************************************************************
 * @brief	   Update the sARGB line mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .
 * @return      
 * @note       
 *******************************************************************************
 */
void ARGB_UpdateDramaMode( ARGBCTR_TypeDef* sARGB )
{
    sARGB->DramaAct       = 0;  
    sARGB->DramaScene     = 0;    
    sARGB->DramaTime      = 0;    
    
    switch( sARGB->DramaMode)
    {
        case ARGB_DRAMA_STATIC:
                                    sARGB->DramaActMax    = 1;
                                    sARGB->DramaSceneMax  = 0; 
                                    sARGB->DramaTimeMax   = 0;
                                    break;
        case ARGB_DRAMA_BREATH:     
                                    sARGB->DramaActMax    = (SMP_ARGB_DEFAULT_COLOR - 1) * 2;
                                    sARGB->DramaSceneMax  = 100; 
                                    sARGB->DramaTimeMax   = 0;
                                    break;
        case ARGB_DRAMA_RAINBOW:    
                                    sARGB->DramaActMax    = 6;
                                    sARGB->DramaSceneMax  = SMP_ARGB_COLLOR_MAX;
                                    sARGB->DramaTimeMax   = 4;
                                    break;
        case ARGB_DRAMA_MORPHING:   
                                    sARGB->DramaActMax    = SMP_ARGB_DEFAULT_COLOR;
                                    sARGB->DramaSceneMax  = 100; 
                                    sARGB->DramaTimeMax   = 0;
                                    break;
        case ARGB_DRAMA_WDROP:      
                                    sARGB->DramaActMax    = 18;
                                    sARGB->DramaSceneMax  = 4;                          
                                    sARGB->DramaTimeMax   = 3;
                                    break;
        case ARGB_DRAMA_MOVING:     
                                    sARGB->DramaActMax    = ( SMP_ARGB_DEFAULT_COLOR * 2);
                                    sARGB->DramaSceneMax  = SMP_ARGB_PIECE;                          
                                    sARGB->DramaTimeMax   = 3;
                                    break;
        case ARGB_DRAMA_2MOVING:          
                                    sARGB->DramaActMax    = SMP_ARGB_DEFAULT_COLOR * 2;
                                    sARGB->DramaSceneMax  = (SMP_ARGB_PIECE - 1);            
                                    sARGB->DramaTimeMax   = 3;
                                    break;
        case ARGB_DRAMA_DISABLE:
        default:
                                    break;
    }
    
    sARGB->UpdateTRG = 0;
    
    Sample_URT_RGB_CloseAll(sARGB);
    
    ARGB_UpdateFlag = 0;
    
} 

/**
 *******************************************************************************
 * @brief	   Calculate color.
 * @details     
 * @param[in]  ARGB_PEBuf  : Refer to Color.
 * @param[in]  molecular   : Calculate molecular.
 * @param[in]  Denominator : Calculate Denominator.
 * @param[in]  LoopTime    : Calculate time.  
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_PercentageTable( uint8_t* ARGB_PEBuf, uint32_t molecular ,uint32_t Denominator, uint8_t LoopTime)
{
    uint8_t  SMP_ARGB_PETmp;
    uint8_t  SMP_ARGB_PETmp2;
    uint32_t SMP_ARGB_PEDataTmp;
    
    for( SMP_ARGB_PETmp2 = 0; SMP_ARGB_PETmp2 < LoopTime ; SMP_ARGB_PETmp2++)
    {
        for(SMP_ARGB_PETmp = 0; SMP_ARGB_PETmp < 3; SMP_ARGB_PETmp++)
        {
            SMP_ARGB_PEDataTmp         = molecular * ARGB_PEBuf[SMP_ARGB_PETmp];
            ARGB_PEBuf[SMP_ARGB_PETmp] = (uint8_t)(SMP_ARGB_PEDataTmp / Denominator);
        }
    }
}
 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_STATIC mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .     
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_SignalColorDrama(ARGBCTR_TypeDef* sARGB)
{
    uint32_t SMP_ARGB_SIGDTmp;
    uint32_t SMP_ARGB_SIGDAdr;
    
    if( sARGB->DramaActMax !=0)
    {
        sARGB->DramaActMax = 0;
        
        for( SMP_ARGB_SIGDTmp = 0; SMP_ARGB_SIGDTmp < SMP_ARGB_PIECE ; SMP_ARGB_SIGDTmp++)
        {
            SMP_ARGB_SIGDAdr = (SMP_ARGB_SIGDTmp * 3);
            
            sARGB->DramaBuf[ SMP_ARGB_SIGDAdr + SMP_ARGB_G] = SMP_ARGBDefault_TABLE[0][ SMP_ARGB_G];
            sARGB->DramaBuf[ SMP_ARGB_SIGDAdr + SMP_ARGB_R] = SMP_ARGBDefault_TABLE[0][ SMP_ARGB_R];
            sARGB->DramaBuf[ SMP_ARGB_SIGDAdr + SMP_ARGB_B] = SMP_ARGBDefault_TABLE[0][ SMP_ARGB_B];
        }
        
        sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
    }
}
/**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_BREATH mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .   
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_BreathDrama(ARGBCTR_TypeDef* sARGB)
{
    uint32_t SMP_ARGB_BRDTmp;

    
    sARGB->DramaTmp[SMP_ARGB_G] = SMP_ARGBDefault_TABLE[(sARGB->DramaAct >> 1)][SMP_ARGB_G];
    sARGB->DramaTmp[SMP_ARGB_R] = SMP_ARGBDefault_TABLE[(sARGB->DramaAct >> 1)][SMP_ARGB_R];
    sARGB->DramaTmp[SMP_ARGB_B] = SMP_ARGBDefault_TABLE[(sARGB->DramaAct >> 1)][SMP_ARGB_B];
    
    if( sARGB->DramaAct & 0x01)
    {
        SMP_ARGB_PercentageTable( &sARGB->DramaTmp[0] , ( sARGB->DramaSceneMax -  sARGB->DramaScene ) , sARGB->DramaSceneMax ,2);
    }
    else
    {
        SMP_ARGB_PercentageTable( &sARGB->DramaTmp[0] , sARGB->DramaScene, sARGB->DramaSceneMax , 2);
    }
    
    
    if( sARGB->DramaScene == sARGB->DramaSceneMax)
    {
        if( sARGB->DramaAct > sARGB->DramaActMax)
        {
            sARGB->DramaAct = 0;
        }
        else
        {
            sARGB->DramaAct = sARGB->DramaAct + 1;
        }
        sARGB->DramaScene = 0;        
    }
    else
    {
        sARGB->DramaScene = sARGB->DramaScene + 1;
    }
    
    for( SMP_ARGB_BRDTmp = 0; SMP_ARGB_BRDTmp < SMP_ARGB_PIECE ; SMP_ARGB_BRDTmp++)
    {
        sARGB->DramaBuf[ (SMP_ARGB_BRDTmp * 3) + SMP_ARGB_G] = sARGB->DramaTmp[ SMP_ARGB_G];
        sARGB->DramaBuf[ (SMP_ARGB_BRDTmp * 3) + SMP_ARGB_R] = sARGB->DramaTmp[ SMP_ARGB_R];
        sARGB->DramaBuf[ (SMP_ARGB_BRDTmp * 3) + SMP_ARGB_B] = sARGB->DramaTmp[ SMP_ARGB_B];
    }
    
    sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
}

 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_RAINBOW mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .     
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_RainBowDrama(ARGBCTR_TypeDef* sARGB)
{
    uint32_t SMP_ARGB_RBDTmp;
    
    for( SMP_ARGB_RBDTmp = 0; SMP_ARGB_RBDTmp < (SMP_ARGB_PIECE - 1); SMP_ARGB_RBDTmp++)
    {
        sARGB->DramaBuf[ (SMP_ARGB_RBDTmp * 3) + SMP_ARGB_G] = sARGB->DramaBuf[ ((SMP_ARGB_RBDTmp + 1)* 3) + SMP_ARGB_G];
        sARGB->DramaBuf[ (SMP_ARGB_RBDTmp * 3) + SMP_ARGB_R] = sARGB->DramaBuf[ ((SMP_ARGB_RBDTmp + 1)* 3) + SMP_ARGB_R];
        sARGB->DramaBuf[ (SMP_ARGB_RBDTmp * 3) + SMP_ARGB_B] = sARGB->DramaBuf[ ((SMP_ARGB_RBDTmp + 1)* 3) + SMP_ARGB_B];
    }
    
    SMP_ARGB_RBDTmp = 0;
    
    switch(sARGB->DramaAct)
    {
        case 2:
        case 5:
                SMP_ARGB_RBDTmp = 1;
                break;
        case 1:
        case 4:
                SMP_ARGB_RBDTmp = 2;
                break;
        case 0:
        case 3:
                break;
        default:
                return;
    }
    
    if( (sARGB->DramaAct & 0x01)==0)
    {
        sARGB->DramaScene = sARGB->DramaScene + sARGB->DramaTimeMax;
        sARGB->DramaBuf[ ((SMP_ARGB_PIECE - 1) * 3) + SMP_ARGB_RBDTmp] = (uint8_t)sARGB->DramaScene;
        
        if( sARGB->DramaScene > sARGB->DramaSceneMax)
        {
            sARGB->DramaAct ++;
        }
    }
    else
    {
        sARGB->DramaScene = sARGB->DramaScene - sARGB->DramaTimeMax;
        sARGB->DramaBuf[ ((SMP_ARGB_PIECE - 1) * 3) + SMP_ARGB_RBDTmp] = (uint8_t)sARGB->DramaScene;
        if( sARGB->DramaScene == 0)
        {
            sARGB->DramaAct ++;
            
            if( sARGB->DramaAct == sARGB->DramaActMax)
            {
                sARGB->DramaAct = 0;
            }
        }
    }
    
    sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
}
 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_MORPHING mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .     
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_MapphingDrama(ARGBCTR_TypeDef* sARGB)
{
    uint32_t SMP_ARGB_MPDTmp;
    uint8_t  SMP_ARGB_COLOR1[3];
    uint8_t  SMP_ARGB_COLOR2[3];
    
    //========================================================================================
    sARGB->DramaTmp[SMP_ARGB_G] = SMP_ARGBDefault_TABLE[ sARGB->DramaAct  ][SMP_ARGB_G];
    sARGB->DramaTmp[SMP_ARGB_R] = SMP_ARGBDefault_TABLE[ sARGB->DramaAct  ][SMP_ARGB_R];
    sARGB->DramaTmp[SMP_ARGB_B] = SMP_ARGBDefault_TABLE[ sARGB->DramaAct  ][SMP_ARGB_B];
    
    SMP_ARGB_PercentageTable( &sARGB->DramaTmp[0] , ( sARGB->DramaSceneMax -  sARGB->DramaScene ) , sARGB->DramaSceneMax ,1);
    
    SMP_ARGB_COLOR1[SMP_ARGB_G] = sARGB->DramaTmp[SMP_ARGB_G];
    SMP_ARGB_COLOR1[SMP_ARGB_R] = sARGB->DramaTmp[SMP_ARGB_R];
    SMP_ARGB_COLOR1[SMP_ARGB_B] = sARGB->DramaTmp[SMP_ARGB_B];
    
    //========================================================================================
    if( sARGB->DramaAct == 5)
    {
        sARGB->DramaTmp[SMP_ARGB_G] = SMP_ARGBDefault_TABLE[ 0 ][SMP_ARGB_G];
        sARGB->DramaTmp[SMP_ARGB_R] = SMP_ARGBDefault_TABLE[ 0 ][SMP_ARGB_R];
        sARGB->DramaTmp[SMP_ARGB_B] = SMP_ARGBDefault_TABLE[ 0 ][SMP_ARGB_B];
    }
    else
    {
        sARGB->DramaTmp[SMP_ARGB_G] = SMP_ARGBDefault_TABLE[ (sARGB->DramaAct + 1) ][SMP_ARGB_G];
        sARGB->DramaTmp[SMP_ARGB_R] = SMP_ARGBDefault_TABLE[ (sARGB->DramaAct + 1) ][SMP_ARGB_R];
        sARGB->DramaTmp[SMP_ARGB_B] = SMP_ARGBDefault_TABLE[ (sARGB->DramaAct + 1) ][SMP_ARGB_B];
    }
    
    SMP_ARGB_PercentageTable( &sARGB->DramaTmp[0] , sARGB->DramaScene, sARGB->DramaSceneMax , 1);
    
    SMP_ARGB_COLOR2[SMP_ARGB_G] = sARGB->DramaTmp[SMP_ARGB_G];
    SMP_ARGB_COLOR2[SMP_ARGB_R] = sARGB->DramaTmp[SMP_ARGB_R];
    SMP_ARGB_COLOR2[SMP_ARGB_B] = sARGB->DramaTmp[SMP_ARGB_B];
    
    
    //========================================================================================
    
    sARGB->DramaTmp[ SMP_ARGB_G] = SMP_ARGB_COLOR1[ SMP_ARGB_G ] + SMP_ARGB_COLOR2[ SMP_ARGB_G];
    sARGB->DramaTmp[ SMP_ARGB_R] = SMP_ARGB_COLOR1[ SMP_ARGB_R ] + SMP_ARGB_COLOR2[ SMP_ARGB_R];
    sARGB->DramaTmp[ SMP_ARGB_B] = SMP_ARGB_COLOR1[ SMP_ARGB_B ] + SMP_ARGB_COLOR2[ SMP_ARGB_B];
    
    
    if( sARGB->DramaScene < sARGB->DramaSceneMax)
    {
        sARGB->DramaScene = sARGB->DramaScene + 1;
    }
    else
    {
        sARGB->DramaScene = 0;
        
        if( sARGB->DramaAct < (sARGB->DramaActMax - 1))
        {
            sARGB->DramaAct = sARGB->DramaAct + 1;
        }
        else
        {
            sARGB->DramaAct = 0;
        }
        
    }
    
    for( SMP_ARGB_MPDTmp = 0; SMP_ARGB_MPDTmp < SMP_ARGB_PIECE ; SMP_ARGB_MPDTmp++)
    {
        sARGB->DramaBuf[ (SMP_ARGB_MPDTmp * 3) + SMP_ARGB_G] = sARGB->DramaTmp[ SMP_ARGB_G];
        sARGB->DramaBuf[ (SMP_ARGB_MPDTmp * 3) + SMP_ARGB_R] = sARGB->DramaTmp[ SMP_ARGB_R];
        sARGB->DramaBuf[ (SMP_ARGB_MPDTmp * 3) + SMP_ARGB_B] = sARGB->DramaTmp[ SMP_ARGB_B];
    }
    
    sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
   
}

 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_WDROP mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .     
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_WDropDrama( ARGBCTR_TypeDef* sARGB )
{
    uint32_t SMP_ARGB_WVDTmp;

    if( sARGB->DramaTime < ( sARGB->DramaTimeMax - 1))
    {
        sARGB->DramaTime = sARGB->DramaTime + 1;
    }
    else
    {
        sARGB->DramaTime = 0;
        
        for( SMP_ARGB_WVDTmp = 0; SMP_ARGB_WVDTmp < (SMP_ARGB_PIECE - 1); SMP_ARGB_WVDTmp++)
        {
            sARGB->DramaBuf[ (SMP_ARGB_WVDTmp * 3) + SMP_ARGB_G] = sARGB->DramaBuf[ ((SMP_ARGB_WVDTmp + 1)* 3) + SMP_ARGB_G];
            sARGB->DramaBuf[ (SMP_ARGB_WVDTmp * 3) + SMP_ARGB_R] = sARGB->DramaBuf[ ((SMP_ARGB_WVDTmp + 1)* 3) + SMP_ARGB_R];
            sARGB->DramaBuf[ (SMP_ARGB_WVDTmp * 3) + SMP_ARGB_B] = sARGB->DramaBuf[ ((SMP_ARGB_WVDTmp + 1)* 3) + SMP_ARGB_B];
        }
        
        
        if( sARGB->DramaScene < sARGB->DramaSceneMax)
        {
            sARGB->DramaScene = sARGB->DramaScene +  1;
            
            sARGB->DramaBuf[ (( SMP_ARGB_PIECE - 1)* 3) + SMP_ARGB_G ] = 0;
            sARGB->DramaBuf[ (( SMP_ARGB_PIECE - 1)* 3) + SMP_ARGB_R ] = 0;    
            sARGB->DramaBuf[ (( SMP_ARGB_PIECE - 1)* 3) + SMP_ARGB_B ] = 0;
        }        
        else
        {
            sARGB->DramaTmp[SMP_ARGB_G] = SMP_ARGBDefault_TABLE[ 0 ][SMP_ARGB_G];
            sARGB->DramaTmp[SMP_ARGB_R] = SMP_ARGBDefault_TABLE[ 0 ][SMP_ARGB_R];
            sARGB->DramaTmp[SMP_ARGB_B] = SMP_ARGBDefault_TABLE[ 0 ][SMP_ARGB_B];
            
            
            SMP_ARGB_PercentageTable( &sARGB->DramaTmp[0] , ( sARGB->DramaActMax -  sARGB->DramaAct ) , sARGB->DramaActMax ,4);
            
            
            sARGB->DramaBuf[ (( SMP_ARGB_PIECE - 1)* 3) + SMP_ARGB_G ] = sARGB->DramaTmp[ SMP_ARGB_G ];
            sARGB->DramaBuf[ (( SMP_ARGB_PIECE - 1)* 3) + SMP_ARGB_R ] = sARGB->DramaTmp[ SMP_ARGB_R ];    
            sARGB->DramaBuf[ (( SMP_ARGB_PIECE - 1)* 3) + SMP_ARGB_B ] = sARGB->DramaTmp[ SMP_ARGB_B ];
            
            
            if( sARGB->DramaAct < sARGB->DramaActMax)
            {
                sARGB->DramaAct = sARGB->DramaAct + 1;
            }
            else
            {
                sARGB->DramaAct = 0;
                sARGB->DramaScene  = 0;
            }
            
            
        }
        sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
    }
}
 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_MOVING mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .      
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_MovingDrama( ARGBCTR_TypeDef* sARGB )
{
    uint8_t    SMP_ARGB_MOVDColor;
    uint32_t   SMP_ARGB_MOVDUpdate;
    
    if( sARGB->DramaTime < sARGB->DramaTimeMax)
    {
        sARGB->DramaTime = sARGB->DramaTime + 1;
    }
    else
    {
        sARGB->DramaTime = 0;
        
        if( sARGB->DramaAct & 0x01)
        {
            SMP_ARGB_MOVDUpdate = (sARGB->DramaScene* 3);
            
            sARGB->DramaBuf[ SMP_ARGB_MOVDUpdate + SMP_ARGB_G ] = 0;
            sARGB->DramaBuf[ SMP_ARGB_MOVDUpdate + SMP_ARGB_R ] = 0;    
            sARGB->DramaBuf[ SMP_ARGB_MOVDUpdate + SMP_ARGB_B ] = 0;
        }
        else
        {
            SMP_ARGB_MOVDColor = sARGB->DramaAct >> 1;
            SMP_ARGB_MOVDUpdate = ((( sARGB->DramaSceneMax - 1) - sARGB->DramaScene )* 3);
            
            sARGB->DramaBuf[ SMP_ARGB_MOVDUpdate + SMP_ARGB_G ] = SMP_ARGBDefault_TABLE[ SMP_ARGB_MOVDColor ][ SMP_ARGB_G ];
            sARGB->DramaBuf[ SMP_ARGB_MOVDUpdate + SMP_ARGB_R ] = SMP_ARGBDefault_TABLE[ SMP_ARGB_MOVDColor ][ SMP_ARGB_R ];    
            sARGB->DramaBuf[ SMP_ARGB_MOVDUpdate + SMP_ARGB_B ] = SMP_ARGBDefault_TABLE[ SMP_ARGB_MOVDColor ][ SMP_ARGB_B ];
            
        }
        
        if( sARGB->DramaScene < (sARGB->DramaSceneMax - 1))
        {
            sARGB->DramaScene = sARGB->DramaScene + 1;
        }
        else
        {
            sARGB->DramaScene = 0;
            
            if( sARGB->DramaAct < (sARGB->DramaActMax - 1))
            {
                sARGB->DramaAct = sARGB->DramaAct + 1;
            }
            else
            {
                sARGB->DramaAct = 0;
            }
            
        }
        
        sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
    }
}

 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data in ARGB_DRAMA_2MOVING mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .     
 * @note       
 *******************************************************************************
 */
void SMP_ARGB_TwoMovingDrama( ARGBCTR_TypeDef* sARGB )
{
    uint8_t SMP_ARGB_TMDTmp;
    uint8_t SMP_ARGB_TMDMode;
    
    if( sARGB->DramaTime < sARGB->DramaTimeMax)
    {
        sARGB->DramaTime = sARGB->DramaTime + 1;
    }
    else
    {
        sARGB->DramaTime = 0;
        
        SMP_ARGB_TMDTmp   = sARGB->DramaAct & 0x7F;
        SMP_ARGB_TMDMode  = sARGB->DramaAct & 0x80;
        
        if( SMP_ARGB_TMDMode == 0)
        {
            if( sARGB->DramaScene != 0)
            {
                sARGB->DramaBuf[ ((sARGB->DramaScene - 1) * 3) + SMP_ARGB_G ]    = 0;
                sARGB->DramaBuf[ ((sARGB->DramaScene - 1) * 3) + SMP_ARGB_R ]    = 0;    
                sARGB->DramaBuf[ ((sARGB->DramaScene - 1) * 3) + SMP_ARGB_B ]    = 0;
            }
            if( sARGB->DramaSceneMax != (SMP_ARGB_PIECE-1))
            {
                sARGB->DramaBuf[ ((sARGB->DramaSceneMax + 1) * 3) + SMP_ARGB_G ] = 0;
                sARGB->DramaBuf[ ((sARGB->DramaSceneMax + 1) * 3) + SMP_ARGB_R ] = 0;    
                sARGB->DramaBuf[ ((sARGB->DramaSceneMax + 1) * 3) + SMP_ARGB_B ] = 0;
            }
        }
        else
        {
            sARGB->DramaBuf[ ((sARGB->DramaScene + 1) * 3) + SMP_ARGB_G ]       = 0;
            sARGB->DramaBuf[ ((sARGB->DramaScene + 1) * 3) + SMP_ARGB_R ]       = 0;    
            sARGB->DramaBuf[ ((sARGB->DramaScene + 1) * 3) + SMP_ARGB_B ]       = 0;
            
            sARGB->DramaBuf[ ((sARGB->DramaSceneMax - 1) * 3) + SMP_ARGB_G ]    = 0;
            sARGB->DramaBuf[ ((sARGB->DramaSceneMax - 1) * 3) + SMP_ARGB_R ]    = 0;    
            sARGB->DramaBuf[ ((sARGB->DramaSceneMax - 1) * 3) + SMP_ARGB_B ]    = 0;
        }
        
        sARGB->DramaBuf[ (sARGB->DramaScene * 3) + SMP_ARGB_G ]    = SMP_ARGBDefault_TABLE[ SMP_ARGB_TMDTmp ][ SMP_ARGB_G ];
        sARGB->DramaBuf[ (sARGB->DramaScene * 3) + SMP_ARGB_R ]    = SMP_ARGBDefault_TABLE[ SMP_ARGB_TMDTmp ][ SMP_ARGB_R ];    
        sARGB->DramaBuf[ (sARGB->DramaScene * 3) + SMP_ARGB_B ]    = SMP_ARGBDefault_TABLE[ SMP_ARGB_TMDTmp ][ SMP_ARGB_B ];
        
        sARGB->DramaBuf[ (sARGB->DramaSceneMax * 3) + SMP_ARGB_G ] = SMP_ARGBDefault_TABLE[ SMP_ARGB_TMDTmp ][ SMP_ARGB_G ];
        sARGB->DramaBuf[ (sARGB->DramaSceneMax * 3) + SMP_ARGB_R ] = SMP_ARGBDefault_TABLE[ SMP_ARGB_TMDTmp ][ SMP_ARGB_R ];    
        sARGB->DramaBuf[ (sARGB->DramaSceneMax * 3) + SMP_ARGB_B ] = SMP_ARGBDefault_TABLE[ SMP_ARGB_TMDTmp ][ SMP_ARGB_B ];
        
        if( SMP_ARGB_TMDMode == 0)
        {
            if( (sARGB->DramaScene + 1) < sARGB->DramaSceneMax)
            {
                sARGB->DramaScene    = sARGB->DramaScene + 1;
                sARGB->DramaSceneMax = sARGB->DramaSceneMax - 1;
            }                
            else
            {
                sARGB->DramaAct = sARGB->DramaAct | 0x80;
                
                if( ( (sARGB->DramaAct & 0x7F) == ( SMP_ARGB_DEFAULT_COLOR - 1)))
                {
                    sARGB->DramaAct = sARGB->DramaAct & (~0x7F);
                }
                else
                {
                    sARGB->DramaAct = sARGB->DramaAct + 1;
                }
            }
        }
        else
        {
            if(sARGB->DramaScene == 0) 
            {
                sARGB->DramaAct = sARGB->DramaAct & (~0x80);
            }
            else
            {
                sARGB->DramaScene    = sARGB->DramaScene    - 1;
                sARGB->DramaSceneMax = sARGB->DramaSceneMax + 1;
            }
        }
        
        sARGB->UpdateTRG |= ARGB_UPDATE_DATA;
    }
}
 /**
 *******************************************************************************
 * @brief	   Calculate ARGB next data according to ARGB mode.
 * @details     
 * @param[in]  sARGB : Control ARGB data line .
 * @note       
 *******************************************************************************
 */
void ARGB_UpdateDrama( ARGBCTR_TypeDef* sARGB )
{   
    if( sARGB->UpdateTRG & ARGB_UPDATE_DATA)
    {
        return;
    }
    else
    {
        switch( sARGB->DramaMode)
        {
            case ARGB_DRAMA_STATIC:
                                       SMP_ARGB_SignalColorDrama(sARGB);
                                       break;
            case ARGB_DRAMA_BREATH:    
                                       SMP_ARGB_BreathDrama( sARGB);
                                       break;
            case ARGB_DRAMA_RAINBOW:   
                                       SMP_ARGB_RainBowDrama( sARGB);
                                       break;
            case ARGB_DRAMA_MORPHING:  
                                       SMP_ARGB_MapphingDrama( sARGB);
                                       break;
            case ARGB_DRAMA_WDROP:     
                                       SMP_ARGB_WDropDrama(sARGB);
                                       break;
            case ARGB_DRAMA_MOVING:    
                                       SMP_ARGB_MovingDrama(sARGB);
                                       break;
            case ARGB_DRAMA_2MOVING:   
                                       SMP_ARGB_TwoMovingDrama(sARGB);
                                       break;
            case ARGB_DRAMA_DISABLE:
            default: 
                                       break;
        }
    } 
} 
 /**
 *******************************************************************************
 * @brief	   The sample code is that UART use blocking mode to update ARGB
 * @details     
 * @return      
 * @note       No
 *******************************************************************************
 */
void ARGB_Main(void)
{
    PIN_InitTypeDef  PINX_InitStruct;
    EXIC_TRGSTypeDef EXIC_TRGS;
    

    //================================================================================================
    //*. CSC Initial :
    //    *. The URT sample need URT clock source is 48MHz.
    //    *. CSC Initial :
    //        1. Checked CSC checkbox of MG32_ChipInit in Manage Run-Time Environment.
    //        2. In MG32_ChipInit_Wizard of Project window use MG32_CSC_Init.h file
    //           to select that you want CSC environment ( APB = 48MHz , and AHB <= 24MHz).
    //
    //================================================================================================
    //*. GPIO Initial can :
    //    1. Checked GPIO checkbox of MG32_ChipInit in Manage Run-Time Environment.
    //       In MG32_ChipInit_Wizard of Project window use MG32_GPIO_Init.h file
    //       to select that you want GPIO environment.
    //    or
    //    2. Use GPIO_PinMode_Config to setting GPIO mode.
    PINX_InitStruct.PINX_Mode				= PINX_Mode_PushPull_O;
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;
    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 = 3;
    GPIO_PinMode_Config(PINB(8),&PINX_InitStruct);                                          // URT0 TX Pin = PB8 (push pull mode)
                                                                                            // If need the other pin to refer URT0 TX pin AFS table.
//    PINX_InitStruct.PINX_Alternate_Function = 4;
//    GPIO_PinMode_Config(PINC(8),&PINX_InitStruct);                                          // URT1 TX Pin = PC8 (push pull mode)
//                                                                                            // If need the other pin to refer URT1 TX pin AFS table.
//    PINX_InitStruct.PINX_Alternate_Function = 4;
//    GPIO_PinMode_Config(PINB(2),&PINX_InitStruct);                                          // URT2 TX Pin = PB2 (push pull mode)
//                                                                                            // If need the other pin to refer URT2 TX pin AFS table.
//    PINX_InitStruct.PINX_Alternate_Function = 4;
//    GPIO_PinMode_Config(PINB(14),&PINX_InitStruct);                                         // URT3 TX Pin = PB14 (push pull mode)
//                                                                                            // If need the other pin to refer URT3 TX pin AFS table.
//    PINX_InitStruct.PINX_Alternate_Function = 2;
//    GPIO_PinMode_Config(PINB(3),&PINX_InitStruct);                                          // SPI0 TX Pin = PB3 (push pull mode)
//                                                                                            // If need the other pin to refer SPI0 TX pin AFS table.
    
    PINX_InitStruct.PINX_Alternate_Function = 0;
    PINX_InitStruct.PINX_Mode				= PINX_Mode_OpenDrain_O;
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Enable;
    GPIO_PinMode_Config(PINA(0),&PINX_InitStruct);                                          // External input interrupt pin = PA0 (open drain with pull-up mode)
    //================================================================================================
    //*. EXIC Initial can : (Use External input interrupt pin to control ARGB mode)
    //    1. Checked EXIC checkbox of MG32_ChipInit in Manage Run-Time Environment.
    //       In MG32_ChipInit_Wizard of Project window use MG32_EXIC_Init.h file
    //       to select that you want EXIC environment.
    //    or
    //    2. Use EXIC_PxTriggerMode_Select() to select trigger event for the EXINT0.
    //    3. Use EXIC_PxTriggerOrMask_Select() to select which pin to trigger interrupt.
    //    4. Use EXIC_PxTriggerITEA_Cmd() and NVIC_EnableIRQ to enable interrupt.

    EXIC_TRGS.EXIC_Pin = EXIC_TRGS_PIN0 ;
    EXIC_TRGS.EXIC_TRGS_Mode = Edge;
    EXIC_PxTriggerMode_Select(EXIC_PA,&EXIC_TRGS);
    
    EXIC_PxTriggerOrMask_Select(EXIC_PA, EXIC_PX_PIN0);
    
    EXIC_PxTriggerITEA_Cmd(EXIC_PA_IT , ENABLE);
    NVIC_EnableIRQ( EXINT0_IRQn);
    
    //================================================================================================
    //4. Set Timer to count interval of ARGB update drama 
    //   (1). Here use TM00.
    //   (2). TM00 clock source from LS and divider 1.
    //   (3). TM00 is full counter mode.
    //   (4). TM00 overflow time is about 10 ms. ( 320 / 32KHz)
    //   (5). Enable TM00 interrupt.
    TM_InternalClockSource_Select( TM00 , TM_CK_LS);
    TM_SetInternalClockDivider(TM00, TM_IntDIV1);
    TM_CounterClock_Select(  TM00, TM_CK_INT);
    TM_PrescalerClock_Select(TM00, TM_CK_INT);
    
    TM_TimerMode_Select(TM00, Full_Counter);                            
    
    TM_Prescaler_Config( TM00 , 0x3F , 0x3F);                           
    TM_Counter_Config( TM00 , 0x01, 0x01);              
    
    TM_IT_Config( TM00 , TMx_TIE_IE , ENABLE);
    TM_ITEA_Cmd( TM00 , ENABLE);
    NVIC_EnableIRQ(TM0x_IRQn);
    
    TM_Timer_Cmd( TM00 , ENABLE);

    //================================================================================================
    //5. ARGB Initial.
    
    //----------------------------------------------------------------------
    //Peripheral option ( confirm the device whether support the peripheral or not.) 
    ARGB0.ARGB_UsePeripheral = ARGB_PERIPHERAL_URT0;                                             // Select URT0 to control ARGB0. 
//    ARGB0.ARGB_UsePeripheral = ARGB_PERIPHERAL_URT1;                                             // Select URT1 to control ARGB0.
//    ARGB0.ARGB_UsePeripheral = ARGB_PERIPHERAL_URT2;                                             // If the device have URT2 select URT2 to control ARGB0.
//    ARGB0.ARGB_UsePeripheral = ARGB_PERIPHERAL_URT3;                                             // If the device have URT3 select URT3 to control ARGB0.
//    ARGB0.ARGB_UsePeripheral = ARGB_PERIPHERAL_SPI0;                                             // Select SPI0 to control ARGB0.
                                                                                                 
                                                                                            
    ARGB0.TRES               = 50;                                                               // Set Reset time ( min time).
    ARGB0.updateBuf          = &SMP_ARGB_UpdateBUF[0][0];                                        // Control ARGB update data buffer pointer.
    ARGB0.DramaBuf           = &SMP_ARGB_DramaBUF[0][0];                                         // Control ARGB calculation buffer pointer.
                                                                                                 
//    ARGB0.TXMode             = ARGB_BLOCKING_MODE;                                               // Use URT blocking mode to send data to ARGB.
    ARGB0.TXMode             = ARGB_IT_MODE;                                                     // Use URT interrupt mode to send data to ARGB.
                                                                                                 
    Sample_ARGB_Init(&ARGB0);                                                                    // ARGB Initial.
    
    if( ARGB0.State != ARGB_FAIL)
    {
        //------------------------------------------------------------------   
        //*. ARGB default mode is static color mode.
        //*. The ARGB sample code support mode have:
        //       1. ARGB_DRAMA_DISABLE  : All ARGB close.
        //       2. ARGB_DRAMA_STATIC   : All ARGB is a static color.
        //       3. ARGB_DRAMA_BREATH   : All ARGB breath and color change according to 
        //                                SMP_ARGBDefault_TABLE.    
        //       4. ARGB_DRAMA_RAINBOW  : ARGB's process is rainbow.
        //       5. ARGB_DRAMA_MORPHING : ARGB's process is two color morphing.
        //                                Two color is according to SMP_ARGBDefault_TABLE.
        //       6. ARGB_DRAMA_WDROP    : ARGB's process is water drop.
        //       7. ARGB_DRAMA_MOVING   
        //       8. ARGB_DRAMA_2MOVING
        Sample_URT_ARGB_UpdateTrigger( ARGB_DRAMA_STATIC );                                       // ARGB default mode is static mode.
                             
        
        //------------------------------------------------------------------
        //Clear All ARGB according to SMP_ARGB_PIECE.
        Sample_URT_RGB_CloseAll(&ARGB0);                                                          // Close All ARGB.
        
        //------------------------------------------------------------------
        ARGB_UpdateFlag  = 0;                                                                     // Clear ARGB update software flag.
            
            
        //================================================================================================
        // It is main function of ARGB sample code. 
        while(1) 
        {
            //-----------------------------------------------------------------
            //Update ARGB Disaplay Mode.
            if( ARGB0.UpdateTRG & ARGB_UPDATE_MODE)                                              // To detect whether ARG mode be changed or not.
            {
                ARGB_UpdateDramaMode(&ARGB0);
            }
            else
            {
                //------------------------------------------------------------------
                //Update Data To ARGB 
                Sample_URT_ARGB_Update(&ARGB0, SMP_ARGB_PIECE);
            }
            //-----------------------------------------------------------------
            //Calculate ARGB next data.
            if( ARGB_UpdateFlag == 1)                                          
            {
                ARGB_UpdateFlag = 0;
                ARGB_UpdateDrama(&ARGB0);
            }
            
        }
    }
}

/**
 *******************************************************************************
 * @brief	   Exteranl input interrupt pin of PortA handle function.
 * @details     
 * @return      
 * @note       No
 *******************************************************************************
 */
void EXINT0_IRQHandler(void)
{
    uint32_t EXINT0IRQ_Debounce = 0;
    
    
    if( ARGB0.DramaMode == ARGB_DRAMA_2MOVING)
    {
        Sample_URT_ARGB_UpdateTrigger(0);
    }
    else
    {
        Sample_URT_ARGB_UpdateTrigger(ARGB0.DramaMode + 1);
    }
    
    do
    {
        if(PA0 ==0)
        {
            EXINT0IRQ_Debounce = 0;
        }
        else
        {
            EXINT0IRQ_Debounce = EXINT0IRQ_Debounce + 1;
        }
    }while( EXINT0IRQ_Debounce < 5000);
    
    
    EXIC_ClearPxTriggerEventFlag(EXIC_PA , EXIC_PX_PIN0);
    EXIC_ClearPxTriggerITFlag( EXIC_PA_ITF , EXIC_PX_OF);
    
}

/**
 *******************************************************************************
 * @brief	   UART0 IRQHandle function.
 * @details     
 * @return      
 * @note       No
 *******************************************************************************
 */
void URT0_IRQHandler(void)
{
    ARGB_IRQHandler(&ARGB0);
}

/**
 *******************************************************************************
 * @brief	   URT123 IRQHandle function.
 * @details     
 * @return      
 * @note       No
 *******************************************************************************
 */
void URT123_IRQHandler(void)
{
    //=============================================================
    #if defined(URT1_Base)
        if( __DRV_EXIC_GET_ID21_SOURCE() & EXIC_SRC5_ID21_urt1_b1)
        {
            ARGB_IRQHandler( &ARGB0 );   
        }
    #endif
    //=============================================================
    #if defined(URT2_Base)
        if( __DRV_EXIC_GET_ID21_SOURCE() & EXIC_SRC5_ID21_urt2_b1)
        {
            ARGB_IRQHandler( &ARGB0 );    
        }
    #endif
    //=============================================================
    #if defined(URT3_Base)
        if( __DRV_EXIC_GET_ID21_SOURCE() & EXIC_SRC5_ID21_urt3_b1)
        {
            ARGB_IRQHandler( &ARGB0 );    
        }
    #endif
}

/**
 *******************************************************************************
 * @brief	   SPI0 IRQHandle function.
 * @details     
 * @return      
 * @note       No
 *******************************************************************************
 */
void SPI0_IRQHandler(void)
{
    ARGB_IRQHandler(&ARGB0);
}
/**
 *******************************************************************************
 * @brief	   TM0x IRQHandle function.
 * @details     
 * @return      
 * @note       No
 *******************************************************************************
 */
void TM0x_IRQHandler(void)
{
    ARGB_UpdateFlag = 1;                       // Set ARGB update software flag.
    
    TM_ClearFlag( TM00 , TMx_TOF);
    
}


///@}










