




/**
 ******************************************************************************
 *
 * @file        Sample_ASB_Transmit.c
 * @brief       The demo ASB initial sample C file.
 *
 * @par         Project
 *              MG32
 * @version     V1.00
 * @date        2022/01/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_APX_DRV.h"
#include "MG32_DMA_DRV.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint8_t SMP_ARGB_DMA[9] = { 10,10, 0,10, 0,10, 0,10,10};

/* Private function prototypes -----------------------------------------------*/
void Sample_ASB_Init(void);

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


/**
 *******************************************************************************
 * @brief	   Sample ASB Channel0 initial
 * @details     1. Set CSC initial.
 *     \n       2. Set GPIO initial.
 *     \n       3. Set ASB common setting.
 *     \n       5. Set ASB channel0 setting.
 * @return      
 * @exception  No
 * @note
 *******************************************************************************
 */
void Sample_ASB_Init(void)
{
    PIN_InitTypeDef      ASB_GPIO;
    ASB_TypeDef          ASB_Common;
    ASBChannel_TypeDef   ASBChannel;
    DMA_BaseInitTypeDef  ASB_DMA;
    
    /*
    Set CSC init:
        MG32_CSC_Init.h(Configuration Wizard) - 
            *Select CK_HS Source                             = CK_IHRCO
            *Configure PLL : (  CK_PLLO = ( ( CK_HS / 2 ) * 16 ) / 2                  // If CK_HS = 12MHz CK_PLLO is 48MHz
                - Select PLL Input Clock Source              = CK_HS
                - Select CK_PLLI Divider                     = CK_HSx / 2
                - Select CK_PLL MultiplicationX Factor       = 16
                - Select CK_PLLO Divider                     = CK_PLL / 2
            *Select CK_MAIN Source                           = CK_PLLO
            *Select APB Prescaler                            = CK_MAIN / 1
            *Select AHB Prescaler                            = CK_APB / 2
            *Enable APX and select APX_PR source = CK_APB in "Configure Peripheral ON Mode Clock".
            *Enable APX in "Configure Peripheral SLEEP Mode Clock" if want to run ASB in SLEEP mode.
    */
    
    
    /*
        To Inital GPIO can use GPIO Wizard opition or using the following code. 
    */
    ASB_GPIO.PINX_Mode				 = PINX_Mode_PushPull_O;           // ASB Pin is push-pull mode
    ASB_GPIO.PINX_PUResistant        = PINX_PUResistant_Disable;       // ASB pull-up resister disable
    ASB_GPIO.PINX_Speed              = PINX_Speed_High;                // ASB output high speed mode enable.
    ASB_GPIO.PINX_OUTDrive           = PINX_OUTDrive_Level0;           // ASB pin output drive strength is Level0 ( Drive strength-full)
    ASB_GPIO.PINX_FilterDivider      = PINX_FilterDivider_Bypass;      // ASB pin input deglitch filter clock divider select.
    ASB_GPIO.PINX_Inverse            = PINX_Inverse_Disable;           // ASB pin input inverse disable.
    ASB_GPIO.PINX_Alternate_Function = 2;                              // ASB pin alternate function is ASB channel0 output.
    GPIO_PinMode_Config(PINA(0),&ASB_GPIO);                            // ASB pin is PA0.
    
    /*
        Configure ASB Common part.
    */
    ASB_Common.SyncCode            = ASB_SYNCCODE_CODE0;               // ASB SYNC code = CODE0.
    ASB_Common.IdleStatus          = ASB_IDLESTATUS_LOW;               // ASB idle status is low.
    ASB_Common.ResetStatus         = ASB_RSTSTATUS_LOW;                // ASB Reset status is low.
    ASB_Common.ResetSync           = ASB_RST_SYNC_DISABLE;             // ASB RESET code synchronous mode disable.
    ASB_Common.ClockInverse        = ASB_CLOKC_INVERSE_DISABLE;        // ASB clock signal invers disable ( it is for ASB channel mode is SHFIT mode ( ex DotStar LEDs) 
    ASB_Common.BitTimePrescaler    = 2  - 1;                           // ASB Bit time clock source CK_ASB = CK_APX_PR / 2
    ASB_Common.BitTimeCounter      = 30 - 1;                           // Bit time = CK_ASB / 30                // CK_ASB     = 1.25us if CK_ASB is 24MHz                        
    ASB_Common.ResetTime           = 40 - 1;                           // Reset time  = Bit time * 40           // Reset time = 1.25 * 40 = 50us 
    ASB_Common.Code0_HighWidthTime = 8 - 1;                            // Code0's T0H = CK_ASB * 8              // T0H is about 0.3us and T0L is about 0.95 ( 1.25 - 0.3) in CK_ASB is 24MHz
    ASB_Common.Code1_HighWidthTime = 22 - 1;                           // Code1's T1H = CK_ASB * 22             // T1H is about 0.9us and T1L is about 0.35 ( 1.25 - 0.9) in CK_ASB is 24MHz
    APX_ASB_Config(&ASB_Common);
    
    /*
        Configure ASB Channel0 
    */
    ASBChannel.OutputMode       = ASB_MODE_ARGB;                    // Set ARGB Mode.        // ARGB ( NeoPixel LEDs) , ASB_MODE_SHIFT ( DotStar LEDs)
    ASBChannel.DataOrder        = ASB_DATA_MSB;                     // Data order is MSB.
    ASBChannel.DataInverse      = ASB_DATA_INVERSE_DISABLE;         // Data inverse disable
    ASBChannel.SignalInverse    = ASB_SIGNAL_INVERSE_DISABLE;       // Output inverse disable
    ASBChannel.PixelLength      = ASB_FRAME_PIXEL_3BYTE;            // ASB pixel byte is 3 bytes.
    ASBChannel.TX_FIFOThreshold = ASB_TX_FIFOTHRESHOLD_2BYTE;       // ASB Channel0 FIFO threshold is 2 bytes.
    APX_ASBChannel_Config( 0 , &ASBChannel);                        // ASB Channel0 Inital 
    
    APX_ASBChannel_Cmd( 0 , ENABLE);                                // ASB Channel0 output function enable.
    
    /*
        Configure ASB Channel0 interrupt
    */
//    APX_IT_Config( APX , ( APX_ASB0_TIE | APX_ASB0_TCIE) , ENABLE); // Enable TXF & TCF interrupt of ASB Channel0. 
//                                                                    //     * TIE  : The interrupt is ASB channeln transmit data threshold low flag.
//                                                                    //     * TCIE : The interrupt is ASB channeln transmission complete 
//    APX_ITEA_Cmd( APX, ENABLE);                                     // Enable APX interrupt.
//    NVIC_EnableIRQ(APX_IRQn);                                       // Enables APX interrupt in the NVIC interrupt controller.
    
    /*
        Sample that use polling to control 3 ARGBs ( WS2812B).
            - 3 ARGBs total is 9 bytes.
            - 1st ARGB = (G , R , B) = ( 0,10, 0)
            - 2nd ARGB = (G , R , B) = (10, 0, 0)
            - 3rd ARGB = (G , R , B) = ( 0, 0,10)            
    */
    while( APX_ASBChannel_GetResetStatus(0)!=0);                       // Check previous RESET signal already complete
    APX_ASBChannel_SendData( 0 , 0);                                   // 1st ARGB (G) = 0 
    APX_ASBChannel_SendData( 0 , 10);                                  // 1st ARGB (R) = 10
    APX_ASBChannel_SendData( 0 , 0);                                   // 1st ARGB (B) = 0
    APX_ASBChannel_SendData( 0 , 10);                                  // 2nd ARGB (G) = 10
    // FIFO max is 4bytes
    while( (APX_GetAllFlagStatus( APX) & APX_ASB0_TXF)==0);            // FIFO threshold is 2 bytes according to " Configure ASB Channel0"
    APX_ASBChannel_SendData( 0 , 0);                                   // 2nd ARGB (R) = 0
    APX_ASBChannel_SendData( 0 , 0);                                   // 2nd ARGB (B) = 0
    while( (APX_GetAllFlagStatus( APX) & APX_ASB0_TXF)==0);
    APX_ASBChannel_SendData( 0 , 0);                                   // 3rd ARGB (G) = 0
    APX_ASBChannel_SendData( 0 , 0);                                   // 3rd ARGB (R) = 0
    while( (APX_GetAllFlagStatus( APX) & APX_ASB0_TXF)==0);
    APX_ASBChannel_SendData( 0 , 10);                                  // 3rd ARGB (B) = 10
    while( (APX_GetAllFlagStatus( APX) & APX_ASB0_TCF)==0);
    APX_ASBChannel_TriggerResetSignal( 0);                             // Send RESET Signal
    
    
    /*
        Sample that use DMA to control 3 ARGBs ( WS2812B).
            - 3 ARGBs total is 9 bytes.
            - 1st ARGB = (G , R , B) = ( 10,10, 0)
            - 2nd ARGB = (G , R , B) = ( 10, 0,10)
            - 3rd ARGB = (G , R , B) = ( 10,10, 0)             
    */
    
    // Inital DMA Module
     
    DMA_BaseInitStructure_Init(&ASB_DMA);                              // Default Inital ASB_DMA parameter.
    DMA_Channel_Cmd(DMAChannel0, ENABLE);                              // DMA Channel0 Enable
    ASB_DMA.DMAChx         = DMAChannel0;                              // Use DMA channel0 to transmit.
    ASB_DMA.DMALoopCmd     = DISABLE;
    ASB_DMA.SrcSINCSel     = ENABLE; 
    ASB_DMA.DestDINCSel    = DISABLE; 
    ASB_DMA.SrcSymSel      = DMA_MEM_Read;
    ASB_DMA.DestSymSel     = DMA_ASB0_TX;
    ASB_DMA.BurstDataSize  = DMA_BurstSize_1Byte;
    ASB_DMA.DMATransferNUM = 9;
    ASB_DMA.DMASourceAddr  = SMP_ARGB_DMA;
    DMA_Base_Init(&ASB_DMA);
    DMA_Cmd( ENABLE);
    
    
    while( APX_ASBChannel_GetResetStatus(0)!=0);                      // Check previous RESET signal already complete
    APX_ASBChannel_DMA_Cmd( 0 , ENABLE);                              // Enable DMA function of ASB
    DMA_StartRequest(DMAChannel0);                                    // Trigger DMA start
    while( (APX_GetAllFlagStatus( APX) & APX_ASB0_TCF)==0);
    APX_ASBChannel_TriggerResetSignal( 0);                            // Send Reset signal

    
}










