
/**
 ******************************************************************************
 *
 * @file      BSP_ARGB.c
 * @brief     The code is using ASB of APX to control ARGB 
 *
 * @par       Project
 *            MG32x02z
 * @version   V1.01
 * @date      2022/08/01
 * @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 "BSP_ARGB.h"


/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define __BSP_ARGB_DisableDrama()\
    ARGB_CTR.DramaBuf  = ARGB_UpDramaColorTmp;\
    ARGB_CTR.DramaMode = ARGB_CTR.DramaMode & (~ARGB_ACT_MASK);\
    ARGB_CTR.Status    = ARGB_CTR.Status | ARGB_STATUS_DATAREADY

#define __BSP_ARGB_SendData(__DATA__)    APX->ASBDAT.B[ARGB_ASBChannel] = (__DATA__)

#define __BSP_ARGB_EnableChannel()       *(uint32_t*)(APX_ASBChannelCR0_Base + ( APX_ASBChannel_SHIFT * ARGB_ASBChannel)) \
                                         |= APX_ASB00_ASB0_EN_mask_w

#define __BSP_ARGB_IT_DISABLE(__INT__)   APX->INT.W = APX->INT.W & (~(__INT__))
#define __BSP_ARGB_IT_ENABLE(__INT__)    APX->INT.W = APX->INT.W | (__INT__)
#define __BSP_ARGB_RESET_SIGNAL()        *(uint32_t*)(APX_ASBChannelCR0_Base + ( APX_ASBChannel_SHIFT * ARGB_ASBChannel)) |=  APX_ASB00_ASB0_RSTTX_mask_w


/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ARGBCTR_TypeDef  ARGB_CTR;


uint8_t ARGB_DefaultColor[ARGB_Default_Color*3] = {                             // ARGB internal default color 
                                                      0,  5,  0,                // G , R , B
                                                      5,  5,  0,
                                                      5,  0,  0,
                                                      5,  0,  5,
                                                      0,  0,  5,
                                                      0,  5,  5,
                                                      5,  5,  5,
                                                  };

static uint8_t ARGB_UpDramaColorTmp[ ARGB_TOTAL_BYTE];
static uint8_t ARGB_String[ARGB_STRING_MAX];
                                                  
/* Private function prototypes -----------------------------------------------*/                                                                                      
static void BSP_ARGB_SignalColorDrama( void);
static void BSP_ARGB_CrossDrama(void);
static void BSP_ARGB_NetDrama(void);
static void BSP_ARGB_StringDrama(void);
static void BSP_ARGB_TriggerTransmit(void);                                                                                             
static void BSP_ARGB_ClearDramaBuffer(void);
static void BSP_ARGB_String(const char *ptr);

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


/**
 *******************************************************************************
 * @brief	  ARGB initial callback function  
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
__WEAK void BSP_ARGB_InitCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modifyed, when the 
    //       callback is needed, the MID_URT_RxCpltCallback 
    //       can be implemented in the user file.
}                                                  
/**
 *******************************************************************************
 * @brief	  ASB IRQHandle
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
void BSP_ASB_IRQHandle(void)
{
    uint32_t ASB_IT_Flag;

    ASB_IT_Flag = APX->STA.W & APX->INT.W;
    

    if( ASB_IT_Flag & ARGB_TXFLAG)
    {
        __BSP_ARGB_SendData(ARGB_CTR.TXBuf[ ARGB_CTR.DataCount]);
        
        switch( ARGB_CTR.DataCount)
        {
            case (ARGB_TOTAL_BYTE - 2):
                                       break;
            case (ARGB_TOTAL_BYTE - 1):
                                       __BSP_ARGB_IT_ENABLE(ARGB_TCIE);
                                       __BSP_ARGB_IT_DISABLE(ARGB_TXIE);
                                       return;
            default:
                                       ARGB_CTR.DataCount = ARGB_CTR.DataCount + 1;
                                       __BSP_ARGB_SendData(ARGB_CTR.TXBuf[ ARGB_CTR.DataCount]);
                                       break;
        }
        ARGB_CTR.DataCount = ARGB_CTR.DataCount + 1;
        return;
    }
    if( ASB_IT_Flag & ARGB_TCFLAG)
    {
        ARGB_CTR.Status = ARGB_CTR.Status & (~ARGB_STATUS_TXBUSY);
        __BSP_ARGB_IT_DISABLE(ARGB_TCIE);         
    }
}
/**
 *******************************************************************************
 * @brief	  ASB Initial  
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
void BSP_ARGB_Init(void)
{
    ASB_TypeDef          ASB_CTR;
    ASBChannel_TypeDef   ASBChannel;

    /* GPIO Initial */
    BSP_GPIO_PinConfig(ASB_P0_IOM_PIN,Data_DIR_OUT_PP,ASB_P0_IOM_AFS);
    
    /* ASB Initial ( For WS2812B) */
    ASB_CTR.SyncCode            = ASB_SYNCCODE_CODE0;
    ASB_CTR.IdleStatus          = ASB_IDLESTATUS_LOW;
    ASB_CTR.ResetStatus         = ASB_RSTSTATUS_LOW;
    ASB_CTR.ResetSync           = ASB_RST_SYNC_DISABLE;
    ASB_CTR.ClockInverse        = ASB_CLOKC_INVERSE_DISABLE;
    ASB_CTR.BitTimePrescaler    = 2  - 1; 
    ASB_CTR.BitTimeCounter      = 30 - 1;                           // Bit time = 1.25us  in 48MHz
    ASB_CTR.ResetTime           = 40 - 1;                           // Reset time = 50us in 48MHz
    ASB_CTR.Code0_HighWidthTime = 8 - 1;                            // Code0's T0H is about 0.3us in 48MHz
    ASB_CTR.Code1_HighWidthTime = 22 - 1;                           // Code1's T1H is about 0.9us in 48Mhz
    APX_ASB_Config(&ASB_CTR);
    
    ASBChannel.OutputMode       = ASB_MODE_ARGB;
    ASBChannel.DataOrder        = ASB_DATA_MSB;
    ASBChannel.DataInverse      = ASB_DATA_INVERSE_DISABLE;
    ASBChannel.SignalInverse    = ASB_SIGNAL_INVERSE_DISABLE;
    ASBChannel.PixelLength      = ASB_FRAME_PIXEL_3BYTE;
    ASBChannel.TX_FIFOThreshold = ASB_TX_FIFOTHRESHOLD_2BYTE;
    APX_ASBChannel_Config( ARGB_ASBChannel , &ASBChannel);
    
    __BSP_ARGB_EnableChannel();
    __BSP_ARGB_IT_DISABLE(( ARGB_TXIE | ARGB_TCIE));

    APX_ITEA_Cmd( APX, ENABLE);
    NVIC_EnableIRQ(APX_IRQn);
    
    /*
    Control Parameter Initial
    */
    ARGB_CTR.Status     = ARGB_STATUE_IDLE;
    ARGB_CTR.DramaMode  = (ARGB_MODE_DISABLE | ARGB_ACT_MASK);
    
    ARGB_CTR.R_Color[0] = ARGB_DefaultColor[ 0 + ARGB_R_Color];
    ARGB_CTR.G_Color[0] = ARGB_DefaultColor[ 0 + ARGB_G_Color];
    ARGB_CTR.B_Color[0] = ARGB_DefaultColor[ 0 + ARGB_B_Color];
    
    BSP_ARGB_InitCallback();
}

/**
 *******************************************************************************
 * @brief	  Change Color0 or Color1   
 * @details     
 * @param[in] ARGBColor_Index(0 or 1): Select change Color0 or Color1
 * @param[in] ARGBColor_R (0 ~ 255): Red setting.
 * @param[in] ARGBColor_G (0 ~ 255): Green setting.
 * @param[in] ARGBColor_B (0 ~ 255): Blue setting.
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
void BSP_ARGB_ChangeColor( uint8_t ARGBColor_Index, uint8_t ARGBColor_R , uint8_t ARGBColor_G, uint8_t ARGBColor_B)
{
    ARGB_CTR.R_Color[ARGBColor_Index] = ARGBColor_R; 
    ARGB_CTR.G_Color[ARGBColor_Index] = ARGBColor_G; 
    ARGB_CTR.B_Color[ARGBColor_Index] = ARGBColor_B;   
}
/**
 *******************************************************************************
 * @brief	   Change ARGB mode 
 * @details     
 * @param[in]  ARGB_ChDrameMode:
 *   @arg\b    ARGB_MODE_DISABLE     : ARGB diable mode.
 *   @arg\b    ARGB_MODE_SINGLE_COLOR: ARGB single color mode.
 *   @arg\b    ARGB_MODE_CROSS       : ARGB cross mode.
 *   @arg\b    ARGB_MODE_NET         : ARGB net mode.
 *   @arg\b    ARGB_MODE_STRING      : ARGB string mode.
 * @param[in]  ARGB_LOOP:
 *   @arg\b    DISABLE : Once time.
 *   @arg\b    ENABLE: Loop times.
 * @return      
 * @exception  No 
 * @note        
 *******************************************************************************
 */
void BSP_ARGB_ChangeDrama(uint32_t ARGB_ChDrameMode , FunctionalState ARGB_LOOP)
{

    ARGB_CTR.DramaMode = ARGB_CTR.DramaMode & (~ARGB_ACT_MASK);
    ARGB_CTR.Status    = ARGB_STATUE_IDLE;

    BSP_ARGB_ClearDramaBuffer();
    
    ARGB_CTR.ColorNumber = 1;
    ARGB_CTR.loop = ARGB_LOOP;
    
    ARGB_CTR.DramaMode         = ARGB_ChDrameMode;
    switch( ARGB_ChDrameMode)
    {
        case ARGB_MODE_SINGLE_COLOR:
                                    ARGB_CTR.DramaCountCompare = 100;
                                    break;
        case ARGB_MODE_CROSS:
                                    ARGB_CTR.DramaCountCompare = 10;
                                    ARGB_CTR.DramaMainCompare  = 21 - 1;
                                    ARGB_CTR.ColorIndex        = 0;
                                    break;
        case ARGB_MODE_NET:
                                    ARGB_CTR.DramaCountCompare = 4;
                                    ARGB_CTR.DramaMainCompare  = ( ARGB_ROW + ARGB_COLUMN) * 4;
                                    ARGB_CTR.DramaSubCount     = (ARGB_ROW - 1);
                                                                
                                    ARGB_CTR.ColorNumber ++;

                                    break;
        case ARGB_MODE_STRING:
                                    ARGB_CTR.DramaCountCompare = 16;
                                    BSP_ARGB_String("megawin ");
                                    ARGB_CTR.DramaSubCompare   = ( ARGB_ROW + 1);
                                    ARGB_CTR.DramaSubCount     = 0;
                                    break;
        case ARGB_MODE_DISABLE:
        default:
                                    ARGB_CTR.DramaMode         = ARGB_MODE_DISABLE;
                                    ARGB_CTR.ColorNumber = 0;
                                    ARGB_CTR.DramaCountCompare = 100;
                                    break;
    }
    ARGB_CTR.DramaMainCount    = 0;
    ARGB_CTR.DramaCount = ARGB_CTR.DramaCountCompare;
    
    ARGB_CTR.DramaMode = ARGB_CTR.DramaMode | ARGB_ACT_MASK;
}
/**
 *******************************************************************************
 * @brief	  Update ARGB next status according to the ARG mode.   
 * @details     
 * @return      
 * @exception No  
 * @note      Must call the function in isochronous time.
 *******************************************************************************
 */
void BSP_ARGB_Drama(void)
{
    if( (ARGB_CTR.DramaMode & ARGB_ACT_MASK)==0)
    {
        return;
    }

    if( ARGB_CTR.DramaCount != ARGB_CTR.DramaCountCompare)
    {
        ARGB_CTR.DramaCount = ARGB_CTR.DramaCount + 1;
        return;
    }    
        
    ARGB_CTR.DramaCount = 0;
    
    switch( (ARGB_CTR.DramaMode & ARGB_MODE_MASK))
    {
        case ARGB_MODE_SINGLE_COLOR:
                                    BSP_ARGB_SignalColorDrama();
                                    break;
        case ARGB_MODE_DISABLE:
                                    __BSP_ARGB_DisableDrama();
                                    break;
        case ARGB_MODE_CROSS:
                                    BSP_ARGB_CrossDrama();
                                    break;
        case ARGB_MODE_NET:
                                    BSP_ARGB_NetDrama();
                                    break;
        case ARGB_MODE_STRING:
                                    BSP_ARGB_StringDrama();
                                    break;
        default:
                                    break;
    }
}
/**
 *******************************************************************************
 * @brief	  ARGB data update 
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
void BSP_ARGB_DataUpdate(void)
{
    if( ARGB_CTR.Status == ARGB_STATUS_DATAREADY)
    {
        ARGB_CTR.Status = ARGB_CTR.Status & (~ARGB_STATUS_DATAREADY);
        ARGB_CTR.DramaBuf = ARGB_UpDramaColorTmp;
        BSP_ARGB_TriggerTransmit();
    }
}
/**
 *******************************************************************************
 * @brief	  ARGB drama when ARGB mode is single color mode.  
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void BSP_ARGB_SignalColorDrama( void)
{
    uint32_t ARGB_SignalColorTmp;
    uint32_t ARGB_SignalColorShift = 0;
    
    for( ARGB_SignalColorTmp = 0; ARGB_SignalColorTmp < ARGB_TOTAL_PIECE; ARGB_SignalColorTmp++)
    {
        ARGB_SignalColorShift = (ARGB_SignalColorTmp *  ARGB_PIECE_PIXEL);
        ARGB_UpDramaColorTmp[ARGB_SignalColorShift + ARGB_R_Color] = ARGB_CTR.R_Color[0];
        ARGB_UpDramaColorTmp[ARGB_SignalColorShift + ARGB_G_Color] = ARGB_CTR.G_Color[0];
        ARGB_UpDramaColorTmp[ARGB_SignalColorShift + ARGB_B_Color] = ARGB_CTR.B_Color[0];
    }
    
    ARGB_CTR.DramaBuf  = ARGB_UpDramaColorTmp;
    ARGB_CTR.Status    = ARGB_CTR.Status | ARGB_STATUS_DATAREADY;
    ARGB_CTR.DramaMode = ARGB_CTR.DramaMode & (~ARGB_ACT_MASK);
    
}
/**
 *******************************************************************************
 * @brief	  ARGB drama when ARGB mode is cross mode.  
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_ARGB_CrossDrama(void)
{
    uint32_t ARGB_CrossDrama_Cmp1;
    uint32_t ARGB_CrossDrama_Cmp2 = 0;
    uint32_t ARGB_CrossDrama_Tmp;
    uint32_t ARGB_CrossDrama_ColumnTmp;
    uint32_t ARGB_CrossDrama_RowTmp;
    uint32_t ARGB_CrossDrama_Location;
    uint32_t ARGB_CrossDrama_NextLocation;
    
    
    ARGB_CrossDrama_Tmp = ARGB_CTR.DramaMode & ARGB_SMODE_MASK;
    
    
    if( ARGB_CTR.DramaMainCount == 0)
    {
        BSP_ARGB_ClearDramaBuffer();
        
        if( ARGB_CrossDrama_Tmp == ARGB_Default_Color)
        {
            ARGB_CTR.R_Color[0] = ARGB_DefaultColor[ 0 + ARGB_R_Color];
            ARGB_CTR.G_Color[0] = ARGB_DefaultColor[ 0 + ARGB_G_Color];
            ARGB_CTR.B_Color[0] = ARGB_DefaultColor[ 0 + ARGB_B_Color];
            ARGB_CTR.ColorIndex = 0;
        }

        for( ARGB_CrossDrama_ColumnTmp = 0; ARGB_CrossDrama_ColumnTmp < ARGB_COLUMN; ARGB_CrossDrama_ColumnTmp++)
        {
            if((ARGB_CrossDrama_ColumnTmp & 0x01) == 0)
            {
                ARGB_CrossDrama_Location = ((( ARGB_CrossDrama_ColumnTmp * ARGB_ROW ) + ( ARGB_ROW - 1)) * 3);
                
            }
            else
            {
                ARGB_CrossDrama_Location = ( ARGB_CrossDrama_ColumnTmp * ARGB_ROW ) * 3;
            }
            
            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[0];
            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[0];
            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[0];

        }
        
        ARGB_CTR.DramaSubCount   = 0;
        ARGB_CTR.DramaSubCompare = ( ARGB_ROW - 1);
    }
    else if( ARGB_CTR.DramaSubCount == ARGB_CTR.DramaSubCompare)
    {
        if( ARGB_CrossDrama_Tmp == ARGB_Default_Color)
        {
            ARGB_CTR.ColorIndex   = ARGB_CTR.ColorIndex + 1;
            ARGB_CTR.R_Color[0] = ARGB_DefaultColor[ (ARGB_CTR.ColorIndex * ARGB_PIECE_PIXEL) + ARGB_R_Color];
            ARGB_CTR.G_Color[0] = ARGB_DefaultColor[ (ARGB_CTR.ColorIndex * ARGB_PIECE_PIXEL) + ARGB_G_Color];
            ARGB_CTR.B_Color[0] = ARGB_DefaultColor[ (ARGB_CTR.ColorIndex * ARGB_PIECE_PIXEL) + ARGB_B_Color];
        }
        for( ARGB_CrossDrama_ColumnTmp = 0; ARGB_CrossDrama_ColumnTmp < ARGB_COLUMN; ARGB_CrossDrama_ColumnTmp++)
        {
            if((ARGB_CrossDrama_ColumnTmp & 0x01) == 0)
            {
                ARGB_CrossDrama_Location = ((( ARGB_CrossDrama_ColumnTmp * ARGB_ROW ) + ( ARGB_ROW - 1)) * 3);
            }
            else
            {
                ARGB_CrossDrama_Location = ( ARGB_CrossDrama_ColumnTmp * ARGB_ROW ) * 3;
            }
            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[0];
            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[0];
            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[0];
        }
        
        ARGB_CTR.DramaSubCount   = 0;
        ARGB_CTR.DramaSubCompare = ARGB_CTR.DramaSubCompare - 1;
    }
    else
    {
        for( ARGB_CrossDrama_ColumnTmp = 0; ARGB_CrossDrama_ColumnTmp < ARGB_COLUMN; ARGB_CrossDrama_ColumnTmp++)
        {
            if((ARGB_CrossDrama_ColumnTmp & 0x01) == 0)
            {
                for( ARGB_CrossDrama_RowTmp = 1; ARGB_CrossDrama_RowTmp < ARGB_ROW; ARGB_CrossDrama_RowTmp++)
                {
                    ARGB_CrossDrama_Tmp          = 0;
                    ARGB_CrossDrama_Location     = ((( ARGB_CrossDrama_ColumnTmp * ARGB_ROW) + ARGB_CrossDrama_RowTmp) * 3);
                    ARGB_CrossDrama_NextLocation = ARGB_CrossDrama_Location - 3; 
                    
                    ARGB_CrossDrama_Cmp1 = ( ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 0] +
                                             ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 1] +
                                             ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 2] );
                    
                    if( ARGB_CrossDrama_Cmp1 == 0)
                    {
                        if( ARGB_CrossDrama_RowTmp!= 1)
                        {
                            ARGB_CrossDrama_Cmp1 = ( ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2] );
                            
                            ARGB_CrossDrama_Cmp2 = ( ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation - 3] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation - 2 ] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation - 1] );
                        }
                        
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 0] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0];
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 1] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1];
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 2] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2];
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0]     = 0x00;
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1]     = 0x00;
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2]     = 0x00;
                        
                        
                        if( ARGB_CrossDrama_Cmp1!=0 && ARGB_CrossDrama_Cmp2!= 0)
                        {
                            ARGB_CrossDrama_Tmp = 1;
                        }
                    }
                    
                    if( ARGB_CrossDrama_Tmp == 1)
                    {
                        for( ARGB_CrossDrama_Tmp = 0; ARGB_CrossDrama_Tmp < (ARGB_CrossDrama_RowTmp - 1); ARGB_CrossDrama_Tmp++)
                        {
                            ARGB_CrossDrama_Location     = ((( ARGB_CrossDrama_ColumnTmp * ARGB_ROW) + ARGB_CrossDrama_Tmp) * 3);
                            
                            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 0];
                            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 1];
                            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 2];
                        }
                    }                   
                }
            }
            else
            {
                for( ARGB_CrossDrama_RowTmp = (ARGB_ROW - 1); ARGB_CrossDrama_RowTmp !=0 ; ARGB_CrossDrama_RowTmp--)
                {
                    ARGB_CrossDrama_Tmp          = 0;
                    ARGB_CrossDrama_Location     = ((( ARGB_CrossDrama_ColumnTmp * ARGB_ROW) + (ARGB_CrossDrama_RowTmp - 1)) * 3);
                    ARGB_CrossDrama_NextLocation = ARGB_CrossDrama_Location + 3; 
                    
                    ARGB_CrossDrama_Cmp1 = ( ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 0] +
                                             ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 1] +
                                             ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 2] );
                    
                    if( ARGB_CrossDrama_Cmp1 == 0)
                    {
                        if( ARGB_CrossDrama_RowTmp!= (ARGB_ROW - 1))
                        {
                            ARGB_CrossDrama_Cmp1 = ( ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2] );
                            
                            ARGB_CrossDrama_Cmp2 = ( ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 3] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 4] +
                                                     ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 5] );
                        }
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 0] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0];
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 1] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1];
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 2] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2];
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0]     = 0x00;
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1]     = 0x00;
                        ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2]     = 0x00;
                        
                        if( ARGB_CrossDrama_Cmp1!=0 && ARGB_CrossDrama_Cmp2!= 0)
                        {
                            ARGB_CrossDrama_Tmp = 1;
                        }
                    }
                    
                    if( ARGB_CrossDrama_Tmp == 1)
                    {
                        for( ARGB_CrossDrama_Tmp = (ARGB_ROW - 1); ARGB_CrossDrama_Tmp > (ARGB_CrossDrama_RowTmp - 1); ARGB_CrossDrama_Tmp--)
                        {
                            ARGB_CrossDrama_Location     = ((( ARGB_CrossDrama_ColumnTmp * ARGB_ROW) + ARGB_CrossDrama_Tmp) * 3);
                            
                            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 0] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 0];
                            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 1] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 1];
                            ARGB_UpDramaColorTmp[ARGB_CrossDrama_Location + 2] = ARGB_UpDramaColorTmp[ARGB_CrossDrama_NextLocation + 2];
                        }
                    }
                    
                    
                }
            }
        }
        
        
        ARGB_CTR.DramaSubCount = ARGB_CTR.DramaSubCount + 1; 
    }
    
    
    ARGB_CTR.DramaBuf  = ARGB_UpDramaColorTmp;
    ARGB_CTR.Status    = ARGB_CTR.Status | ARGB_STATUS_DATAREADY;

    if( ARGB_CTR.DramaMainCount == ARGB_CTR.DramaMainCompare)
    {
        if( ARGB_CTR.loop == ENABLE)
        {
            ARGB_CTR.DramaMainCount = 0;
        }
        else
        {
            ARGB_CTR.DramaMode &= (~ARGB_ACT_MASK);
        }
    }
    else
    {
        ARGB_CTR.DramaMainCount = ARGB_CTR.DramaMainCount + 1;
    }
    
}
/**
 *******************************************************************************
 * @brief	  ARGB drama when ARGB mode is net mode.  
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_ARGB_NetDrama(void)
{
    uint32_t ARGB_NetDrama_Tmp;
    uint32_t ARGB_NetDrama_ColumTmp;
    uint32_t ARGB_NetDrama_Location;
    
    if( ARGB_CTR.DramaMainCount < ARGB_COLUMN )
    {
        for( ARGB_NetDrama_Tmp = 0; ARGB_NetDrama_Tmp < ARGB_ROW; ARGB_NetDrama_Tmp++)
        {
            if( ARGB_NetDrama_Tmp == ARGB_CTR.DramaSubCount )
            {
                ARGB_NetDrama_Location = ARGB_CTR.DramaMainCount * ARGB_ROW * 3;
                ARGB_NetDrama_Location = ARGB_NetDrama_Location + ( ARGB_NetDrama_Tmp * 3);
                
                ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[0];
                ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[0];
                ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[0];
            }
        }
        if( ARGB_CTR.DramaSubCount == 0)
        {
            ARGB_CTR.DramaMainCount = ARGB_CTR.DramaMainCount + 1;
            if( ARGB_CTR.DramaMainCount == ARGB_COLUMN)
            {
                ARGB_CTR.DramaSubCount = ( ARGB_COLUMN - 1);
            }
            else
            {
                ARGB_CTR.DramaSubCount = ( ARGB_ROW - 1);
            }
        }
        else
        {
            ARGB_CTR.DramaSubCount = ARGB_CTR.DramaSubCount - 1;
        }
    }
    else if( ARGB_CTR.DramaMainCount < (ARGB_COLUMN + ARGB_ROW))
    {
        ARGB_NetDrama_ColumTmp = ARGB_CTR.DramaMainCount - ARGB_COLUMN;
        
        for( ARGB_NetDrama_Tmp = 0; ARGB_NetDrama_Tmp < ARGB_COLUMN; ARGB_NetDrama_Tmp++)
        {
            if((ARGB_NetDrama_ColumTmp % 2) == 0)
            {    
                if( (ARGB_NetDrama_Tmp == ARGB_CTR.DramaSubCount) && ( (ARGB_CTR.DramaSubCount %2) == 1))
                {
                    ARGB_NetDrama_Location = (ARGB_NetDrama_ColumTmp * ARGB_PIECE_PIXEL) + ( ARGB_NetDrama_Tmp * ARGB_ROW * ARGB_PIECE_PIXEL);
                    
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[1];
                }
            }
            if((ARGB_NetDrama_ColumTmp % 2) == 1)
            {    
                if( (ARGB_NetDrama_Tmp == ARGB_CTR.DramaSubCount) && ( (ARGB_CTR.DramaSubCount %2) == 0))
                {
                    ARGB_NetDrama_Location = (ARGB_NetDrama_ColumTmp * ARGB_PIECE_PIXEL) + ( ARGB_NetDrama_Tmp * ARGB_ROW * ARGB_PIECE_PIXEL);
                    
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[1];
                }
            }
            
        }
        if( ARGB_CTR.DramaSubCount == 0)
        {
            ARGB_CTR.DramaMainCount = ARGB_CTR.DramaMainCount + 1;
            if( ARGB_CTR.DramaMainCount == (ARGB_COLUMN + ARGB_ROW))
            {
                ARGB_CTR.DramaSubCount = ( ARGB_ROW - 1);
            }
            else
            {
                ARGB_CTR.DramaSubCount = ( ARGB_COLUMN - 1);
            }
        }
        else
        {
            ARGB_CTR.DramaSubCount = ARGB_CTR.DramaSubCount - 1;
        }
    }
    else if( ARGB_CTR.DramaMainCount < ((ARGB_COLUMN * 2) + ARGB_ROW))
    {
        ARGB_NetDrama_ColumTmp = ARGB_CTR.DramaMainCount - ( ARGB_COLUMN + ARGB_ROW);
        
        for( ARGB_NetDrama_Tmp = 0; ARGB_NetDrama_Tmp < ARGB_ROW; ARGB_NetDrama_Tmp++)
        {
            if((ARGB_NetDrama_ColumTmp % 2) == 0)
            {    
                if( (ARGB_NetDrama_Tmp == ARGB_CTR.DramaSubCount) && ( (ARGB_CTR.DramaSubCount %2) == 0))
                {
                    ARGB_NetDrama_Location = ARGB_NetDrama_ColumTmp * ARGB_ROW * 3;
                    ARGB_NetDrama_Location = ARGB_NetDrama_Location + ( ARGB_NetDrama_Tmp * 3);
                    
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[1];
                }
            }
            if((ARGB_NetDrama_ColumTmp % 2) == 1)
            {    
                if( (ARGB_NetDrama_Tmp == ARGB_CTR.DramaSubCount) && ( (ARGB_CTR.DramaSubCount %2) == 1))
                {
                    ARGB_NetDrama_Location = ARGB_NetDrama_ColumTmp * ARGB_ROW * 3;
                    ARGB_NetDrama_Location = ARGB_NetDrama_Location + ( ARGB_NetDrama_Tmp * 3);
                    
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_R_Color] = ARGB_CTR.R_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_G_Color] = ARGB_CTR.G_Color[1];
                    ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_B_Color] = ARGB_CTR.B_Color[1];
                }
            }  
        }
        
        if( ARGB_CTR.DramaSubCount == 0)
        {
            ARGB_CTR.DramaMainCount = ARGB_CTR.DramaMainCount + 1;
            if( ARGB_CTR.DramaMainCount == (ARGB_COLUMN*2 + ARGB_ROW))
            {
                ARGB_CTR.DramaSubCount = ( ARGB_COLUMN - 1);
            }
            else
            {
                ARGB_CTR.DramaSubCount = ( ARGB_ROW - 1);
            }
        }
        else
        {
            ARGB_CTR.DramaSubCount = ARGB_CTR.DramaSubCount - 1;
        }
        
    }
    else
    {
        for( ARGB_NetDrama_Tmp = 0; ARGB_NetDrama_Tmp < ARGB_COLUMN; ARGB_NetDrama_Tmp++)
        {
            ARGB_NetDrama_ColumTmp = ARGB_CTR.DramaMainCount - ( ARGB_COLUMN*2 + ARGB_ROW);
            
            if( ARGB_NetDrama_Tmp == ARGB_CTR.DramaSubCount )
            {
                ARGB_NetDrama_Location = (ARGB_NetDrama_ColumTmp * ARGB_PIECE_PIXEL) + ( ARGB_NetDrama_Tmp * ARGB_ROW * ARGB_PIECE_PIXEL);
                
                ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_R_Color] = 0;
                ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_G_Color] = 0;
                ARGB_UpDramaColorTmp[ARGB_NetDrama_Location + ARGB_B_Color] = 0;
            }
        }
        if( ARGB_CTR.DramaSubCount == 0)
        {
            ARGB_CTR.DramaMainCount = ARGB_CTR.DramaMainCount + 1;
            if( ARGB_CTR.DramaMainCount == (ARGB_COLUMN*2 + ARGB_ROW*2))
            {
                if( ARGB_CTR.loop == ENABLE)
                {
                    ARGB_CTR.DramaSubCount  = ( ARGB_ROW - 1);
                    ARGB_CTR.DramaMainCount = 0;
                }
                else
                {
                    ARGB_CTR.DramaMode &= (~ARGB_ACT_MASK);
                }
            }
            else
            {
                ARGB_CTR.DramaSubCount = ( ARGB_COLUMN - 1);
            }
        }
        else
        {
            ARGB_CTR.DramaSubCount = ARGB_CTR.DramaSubCount - 1;
        }
    }
    ARGB_CTR.DramaBuf  = ARGB_UpDramaColorTmp;
    ARGB_CTR.Status    = ARGB_CTR.Status | ARGB_STATUS_DATAREADY;
  
}
/**
 *******************************************************************************
 * @brief	  ARGB drama when ARGB mode is string mode.  
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_ARGB_StringDrama(void)
{             
    uint32_t  ARGB_StringDramaTmp;
    uint32_t  ARGB_StringDramaTmp2;
    uint32_t  ARGB_StringDramaColumn;
    uint32_t  ARGB_StringDramaRow;
    
    uint32_t  ARGB_StringDramaLocation;   
    uint32_t  ARGB_StringDramaBeforeLocation;   
    
    for( ARGB_StringDramaColumn = 0; ARGB_StringDramaColumn < ARGB_COLUMN; ARGB_StringDramaColumn++)
    {
        for( ARGB_StringDramaRow = 0; ARGB_StringDramaRow < ( ARGB_ROW - 1) ; ARGB_StringDramaRow++)
        {
            ARGB_StringDramaLocation       = (  (ARGB_ROW * 3) * ARGB_StringDramaColumn) + ( 3 * ARGB_StringDramaRow);
            ARGB_StringDramaBeforeLocation = ARGB_StringDramaLocation + 3; 
            
            ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_R_Color ] = ARGB_UpDramaColorTmp[ARGB_StringDramaBeforeLocation + ARGB_R_Color];
            ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_G_Color ] = ARGB_UpDramaColorTmp[ARGB_StringDramaBeforeLocation + ARGB_G_Color];
            ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_B_Color ] = ARGB_UpDramaColorTmp[ARGB_StringDramaBeforeLocation + ARGB_B_Color];        
        }
    }
  
    if( ARGB_CTR.DramaSubCount > (ARGB_ROW - 1) )
    {
        for( ARGB_StringDramaColumn = 0; ARGB_StringDramaColumn < ARGB_COLUMN; ARGB_StringDramaColumn++)
        {
            ARGB_StringDramaLocation  =  ((ARGB_ROW * 3) * ARGB_StringDramaColumn )+ ((ARGB_ROW - 1) * 3) ;

            ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_R_Color ] = 0;
            ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_G_Color ] = 0;
            ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_B_Color ] = 0; 
            
        }
    }
    else
    {
        ARGB_StringDramaTmp = ARGB_String[ARGB_CTR.DramaMainCount];
        
        if(  ARGB_StringDramaTmp > (ARGB_STRING_a_ASCII - 1))
        {
            ARGB_StringDramaTmp = (ARGB_STRING_a_SHIFT + (ARGB_StringDramaTmp - ARGB_STRING_a_ASCII)) * ( (ARGB_COLUMN - 1) * ARGB_ROW);
            
        }
        else if( ARGB_StringDramaTmp > ( ARGB_STRING_A_ASCII - 1))
        {
            ARGB_StringDramaTmp = (ARGB_STRING_A_SHIFT + (ARGB_StringDramaTmp - ARGB_STRING_A_ASCII)) * ( (ARGB_COLUMN - 1) * ARGB_ROW);
        }
        else if( ARGB_StringDramaTmp > ( ARGB_STRING_0_ASCII - 1))
        {
            ARGB_StringDramaTmp = (ARGB_STRING_0_SHIFT + (ARGB_StringDramaTmp - ARGB_STRING_0_ASCII)) *( ( ARGB_COLUMN - 1) * ARGB_ROW);
        }
        else
        {
            ARGB_StringDramaTmp = (ARGB_STRING_SPACE_SHIFT + (ARGB_StringDramaTmp - ARGB_STRING_SPACE_ASCII)) *( ( ARGB_COLUMN - 1) * ARGB_ROW);
        }
        
        
        for( ARGB_StringDramaColumn = 0; ARGB_StringDramaColumn < ARGB_COLUMN; ARGB_StringDramaColumn++)
        {
            ARGB_StringDramaTmp2      =  ARGB_StringDramaTmp + ARGB_CTR.DramaSubCount + ( ARGB_StringDramaColumn * ARGB_ROW);
            ARGB_StringDramaLocation  =  ((ARGB_ROW * 3) * ARGB_StringDramaColumn )+ ((ARGB_ROW - 1) * 3) ;
           
            
            if( ARGB_StringTable[ARGB_StringDramaTmp2] == 0 || ( ARGB_StringDramaColumn == ( ARGB_COLUMN - 1)) )
            {
                ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_R_Color ] = 0;
                ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_G_Color ] = 0;
                ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_B_Color ] = 0;
            }
            else
            {
                ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_R_Color ] = ARGB_CTR.R_Color[0];
                ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_G_Color ] = ARGB_CTR.G_Color[0];
                ARGB_UpDramaColorTmp[ARGB_StringDramaLocation + ARGB_B_Color ] = ARGB_CTR.B_Color[0];
            }
            
        }
    }
    if( ARGB_CTR.DramaSubCount == ARGB_CTR.DramaSubCompare)
    {
        ARGB_CTR.DramaSubCount = 0;
        
        if( ARGB_CTR.DramaMainCount == ARGB_CTR.DramaMainCompare)
        {
            if( ARGB_CTR.loop == ENABLE)
            {
                ARGB_CTR.DramaMainCount = 0;    
            }
            else
            { 
                ARGB_CTR.DramaMode &= (~ARGB_ACT_MASK);                
            }  
        }
        else
        {
            ARGB_CTR.DramaMainCount = ARGB_CTR.DramaMainCount + 1;
        }
    }
    else
    {
        ARGB_CTR.DramaSubCount = ARGB_CTR.DramaSubCount + 1;
    }
    
    
    ARGB_CTR.DramaBuf  = ARGB_UpDramaColorTmp;
    ARGB_CTR.Status    = ARGB_CTR.Status | ARGB_STATUS_DATAREADY;
}
/**
 *******************************************************************************
 * @brief	  Trigger to transmit ARGB data by ASB  
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_ARGB_TriggerTransmit(void)
{
    uint8_t  ARGB_TXTRG_RowTmp;
    uint8_t  ARGB_TXTRG_ColumnTmp;
    uint32_t ARGB_TXTRG_TXLocation;
    uint32_t ARGB_TXTRG_DramaLocation;
    
    __BSP_ARGB_RESET_SIGNAL();
    
    for( ARGB_TXTRG_RowTmp = 0; ARGB_TXTRG_RowTmp < ARGB_ROW; ARGB_TXTRG_RowTmp++)
    {
        for( ARGB_TXTRG_ColumnTmp = 0; ARGB_TXTRG_ColumnTmp < ARGB_COLUMN; ARGB_TXTRG_ColumnTmp++)
        {
            ARGB_TXTRG_TXLocation    = ( ARGB_Table[ARGB_TXTRG_ColumnTmp][ARGB_TXTRG_RowTmp] * 3);
            ARGB_TXTRG_DramaLocation = (( (ARGB_TXTRG_ColumnTmp * 6) + ARGB_TXTRG_RowTmp) * 3);
            
            ARGB_CTR.TXBuf[ ARGB_TXTRG_TXLocation + 0] = ARGB_CTR.DramaBuf[ARGB_TXTRG_DramaLocation + 0];
            ARGB_CTR.TXBuf[ ARGB_TXTRG_TXLocation + 1] = ARGB_CTR.DramaBuf[ARGB_TXTRG_DramaLocation + 1];
            ARGB_CTR.TXBuf[ ARGB_TXTRG_TXLocation + 2] = ARGB_CTR.DramaBuf[ARGB_TXTRG_DramaLocation + 2];
        } 
    }

    ARGB_CTR.DataCount  = 0;
    ARGB_CTR.Status     = ARGB_STATUS_TXBUSY;
    
    __BSP_ARGB_IT_ENABLE(ARGB_TXIE);
}
/**
 *******************************************************************************
 * @brief	  Clear ARGB drama buffer. 
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_ARGB_ClearDramaBuffer(void)
{
    memset(ARGB_UpDramaColorTmp,0,ARGB_TOTAL_BYTE);
    
    ARGB_CTR.DramaBuf = ARGB_UpDramaColorTmp;
}
/**
 *******************************************************************************
 * @brief	  Transfer string (*ptr) to ARGB_String buffer.
 * @details     
 * @return      
 * @exception No  
 * @note      The max size according to ARGB_STRING_MAX.  
 *******************************************************************************
 */
static void BSP_ARGB_String(const char *ptr)
{
    ARGB_CTR.DramaMainCompare = 0;
    
    while( *ptr != 0x00)
    {
        ARGB_String[ ARGB_CTR.DramaMainCompare] = (*ptr);
        ptr = ptr + 1;
        ARGB_CTR.DramaMainCompare = ARGB_CTR.DramaMainCompare + 1;
    }
    ARGB_CTR.DramaMainCompare  = ARGB_CTR.DramaMainCompare - 1;
}



