/**
  ******************************************************************************
 *
 * @file        Sample_MID_TM36_PWM_DMA.c
 *
 * @brief       TM36 PWM output that ITR and DMA control the update timing.
 *
 * @par         Project
 *              MG32
 * @version     V1.14
 * @date        2021/05/27
 * @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_TM_MID.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static TM_HandleTypeDef    mTM36;
static DMA_HandleTypeDef   PWMChannel0, PWMChannel1, PWMChannel2;

static uint16_t            DChaneel0[] = {100, 200, 300};
static uint16_t            DChaneel1[] = {400, 500, 600};
static uint16_t            DChaneel2[] = {700, 800, 900};

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

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



/**
 *******************************************************************************
 * @brief	    TM36 PWM output that ITR and DMA control the update timing.
 * @details     1.Initial TM36 for 16-bit of PWM.
 *    \n        2.Initial TM36 clock mode.
 *    \n        3.PWM Output channel configuration.
 *    \n        4.Initial DMA.
 *    \n        5.Start PWM output with DMA.
 *    \n        6.Config OC/PWM update timing.
 *    \n        7.Initial TM10 for 16-bit counter.
 *    \n        8.Initial TM10 clock mode.
 *    \n        9.Initial TM10 TRGO.
 *    \n        10.Start TM10.
 * @return      None
 *******************************************************************************
 */
void Sample_MID_TM36_PWM_DMA(void)
{      
    TM_OC_InitTypeDef       sConfig;    
    TM_ClockConfigTypeDef   CKConfig;
    
    TM_HandleTypeDef        mTM10;
    TM_MasterConfigTypeDef  mTM10_TRGO;

    // make sure :
    
    //===Set CSC init====
    //MG32_CSC_Init.h(Configuration Wizard)
    //Select CK_HS source = CK_IHRCO
    //Select IHRCO = 12M
    //  Select CK_PLLI Divider = CK_HS/2
    //  Select CK_PLL Multiplication factor = CK_PLLIx16
    //  Select CK_PLLO Divider = CK_PLL/4
    //Select CK_MAIN Source = CK_PLLO
    //Configure PLL->Select APB Prescaler = CK_MAIN/1
    //Configure Peripheral On Mode Clock->TM36 = Enable
    //Configure Peripheral On Mode Clock->DMA = Enable
    //Configure Peripheral On Mode Clock->GPIOC = Enable
    //Configure Peripheral On Mode Clock->GPIOD = Enable
	
    //==Set GPIO init 
    //MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOC->PC0,PC2
    //GPIO port initial is 0xFFFF
    //PC0,PC2 mode is PPO
    //PC0,PC2 function TM36_OC00, TM36_OC10
        
    //MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOD->PD0
    //GPIO port initial is 0xFFFF
    //PD0 mode is PPO
    //PD0 function TM36_OC2
        
    // ------------------------------------------------------------------------
    // 1.Initial TM36 for 16-bit of PWM.
    // ------------------------------------------------------------------------
    mTM36.Instance                  = TM36;
    mTM36.Init.TM_CounterMode       = TM_SEPARATE_UP;
    mTM36.Init.TM_Period            = 1023;
    mTM36.Init.TM_Prescaler         = 0;
    MID_TM_PWM_Init(&mTM36);
    
    // ------------------------------------------------------------------------
    // 2.Initial TM36 clock mode.
    // ------------------------------------------------------------------------
    CKConfig.TM_ClockSource         = TM_INTERNAL_CLOCK;
    CKConfig.TM_ExternalClockSource = TM_EXTERNAL_ITR0;             // Setup ITR0 from TM10_TRGO
    CKConfig.TM_INTClockDivision    = TM_INTERNALCLOCK_DIVDER_DIV1;
    CKConfig.TM_InternalClockSource = TM_INTERNALCLOCK_PROC;
    
    MID_TM_ConfigClockSource(&mTM36, &CKConfig);  
    
    // ------------------------------------------------------------------------
    // 3.PWM Output channel configuration.
    // ------------------------------------------------------------------------
    MID_TM_OC_Struct_Init(&sConfig);                                // default initial (output state)
    sConfig.OCMode                  = TM_CH_16bit_PWM;
    sConfig.Pulse                   = 0;                            // Duty cycle
    MID_TM_PWM_ConfigChannel(&mTM36, &sConfig, MID_TM_Channel0);
    MID_TM_PWM_ConfigChannel(&mTM36, &sConfig, MID_TM_Channel1);    
    MID_TM_PWM_ConfigChannel(&mTM36, &sConfig, MID_TM_Channel2);    

    // ------------------------------------------------------------------------
    // 4.Initial DMA. (M2P)
    // ------------------------------------------------------------------------
    // DMAChannel0
    PWMChannel0.Instance            = DMA;
	PWMChannel0.DMAChannelIndex     = DMAChannel0;                  // DMA channel0 can support M2P mode  
	PWMChannel0.Init.SrcPeri        = MID_DMA_MEMORY_READ;          // Source symbol is Memory
	PWMChannel0.Init.DesPeri        = MID_DMA_TM36_CC0B_WRITE;      // Destination symbol is TM36_OC0
	PWMChannel0.Init.BSize          = DMA_BSIZE_2BYTE;              // Burst size is 2 byte
	PWMChannel0.Init.MEMMode        = MID_DMA_MEMORY_NORMAL;        // Normal memory access mode    
    PWMChannel0.Init.LoopMode       = DMA_LOOP_DISABLE;             // DISABLE Loop mode
    PWMChannel0.Parent              = &mTM36;
	
    MID_DMA_Init(&PWMChannel0);

    // DMAChannel1
    PWMChannel1.Instance            = DMA;
	PWMChannel1.DMAChannelIndex     = DMAChannel1;                  // DMA channel0 can support M2P mode  
	PWMChannel1.Init.SrcPeri        = MID_DMA_MEMORY_READ;          // Source symbol is Memory
	PWMChannel1.Init.DesPeri        = MID_DMA_TM36_CC1B_WRITE;      // Destination symbol is TM36_OC1
	PWMChannel1.Init.BSize          = DMA_BSIZE_2BYTE;              // Burst size is 2 byte
	PWMChannel1.Init.MEMMode        = MID_DMA_MEMORY_NORMAL;        // Normal memory access mode    
    PWMChannel1.Init.LoopMode       = DMA_LOOP_DISABLE;             // DISABLE Loop mode
    PWMChannel1.Parent              = &mTM36;
    
	MID_DMA_Init(&PWMChannel1);

    // DMAChannel2
    PWMChannel2.Instance            = DMA;
	PWMChannel2.DMAChannelIndex     = DMAChannel2;                  // DMA channel0 can support M2P mode  
	PWMChannel2.Init.SrcPeri        = MID_DMA_MEMORY_READ;          // Source symbol is Memory
	PWMChannel2.Init.DesPeri        = MID_DMA_TM36_CC2B_WRITE;      // Destination symbol is TM36_OC2
	PWMChannel2.Init.BSize          = DMA_BSIZE_2BYTE;              // Burst size is 2 byte
	PWMChannel2.Init.MEMMode        = MID_DMA_MEMORY_NORMAL;        // Normal memory access mode    
    PWMChannel2.Init.LoopMode       = DMA_LOOP_DISABLE;             // DISABLE Loop mode
    PWMChannel2.Parent              = &mTM36;
    
	MID_DMA_Init(&PWMChannel2);
    
    // ------------------------------------------------------------------------
    // 5.Start PWM output with DMA.
    // ------------------------------------------------------------------------
    // User maybe modify DMA parameters after DMA complete. 
    // So, user can modify 'MG32_IRQHandler.c'.
    // Like this.
    // void DMA_IRQHandler(void)
    // {
    //     MID_DMA_IRQHandler(&PWMChannel0);
    //     MID_DMA_IRQHandler(&PWMChannel1);
    //     MID_DMA_IRQHandler(&PWMChannel2);
    // }
    
    mTM36.hDMA[0] = &PWMChannel0;
    mTM36.hDMA[1] = &PWMChannel1;
    mTM36.hDMA[2] = &PWMChannel2;
    
    // for [-Wcast-align] issue
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wcast-align"
        MID_TM_PWM_Start_DMA(&mTM36, MID_TM_Channel0, (uint32_t *) &DChaneel0, 6);
        MID_TM_PWM_Start_DMA(&mTM36, MID_TM_Channel1, (uint32_t *) &DChaneel1, 6);
        MID_TM_PWM_Start_DMA(&mTM36, MID_TM_Channel2, (uint32_t *) &DChaneel2, 6);
    #pragma clang diagnostic pop
#else
    MID_TM_PWM_Start_DMA(&mTM36, MID_TM_Channel0, (uint32_t *) &DChaneel0, 6);
    MID_TM_PWM_Start_DMA(&mTM36, MID_TM_Channel1, (uint32_t *) &DChaneel1, 6);
    MID_TM_PWM_Start_DMA(&mTM36, MID_TM_Channel2, (uint32_t *) &DChaneel2, 6);
#endif
    
    // ------------------------------------------------------------------------
    // 6.Config OC/PWM update timing.
    // ------------------------------------------------------------------------
    __DRV_TM_SET_DMA_UPLOAD_TIMING(&mTM36, TM_ITR_EVENT_TIMING);        // Default TM36 internal trigger signals is TM10_TRGO       
//    __DRV_TM_SET_DMA_UPLOAD_TIMING(&mTM36, TM_UPDATEG_EVENT_TIMING);    // Default update mode 
    
    // ------------------------------------------------------------------------
    // 7.Initial TM10 for 16-bit counter.
    // ------------------------------------------------------------------------
    mTM10.Instance                  = TM10;
    mTM10.Init.TM_CounterMode       = TM_SEPARATE_UP;
    mTM10.Init.TM_Period            = 4095;
    mTM10.Init.TM_Prescaler         = 0;
    MID_TM_Base_Init(&mTM10);
    
    // ------------------------------------------------------------------------
    // 8.Initial TM10 clock mode.
    // ------------------------------------------------------------------------
    MID_TM_ConfigClockSource(&mTM10, &CKConfig);

    // ------------------------------------------------------------------------
    // 9.Initial TM10 TRGO.
    // ------------------------------------------------------------------------
    mTM10_TRGO.MasterOutputPolarity = TM_MASTEROUTPUT_BYPASS;
    mTM10_TRGO.MasterOutputTrigger  = TM_TRGO_UPDATE;
    mTM10_TRGO.MasterUpdateEvent    = TM_UPDATE_OVERFLOW;
    
    MID_TM_MasterConfigSynchronization(&mTM10, &mTM10_TRGO);

    // ------------------------------------------------------------------------
    // 10.Start TM10.
    // ------------------------------------------------------------------------
    MID_TM_Base_Start(&mTM10);
    
}


