/******************************************************************************
 * @file     main.c
 * @brief    Main program body
 * @version  V1.8.0
 * @date     31-Dec-2021
 *
 * @note
 * Copyright (C) 2021 Spintrol Limited Corporation. All rights reserved.
 *
 * @attention
 * THIS SOFTWARE JUST PROVIDES CUSTOMERS WITH CODING INFORMATION REGARDING
 * THEIR PRODUCTS, WHICH AIMS AT SAVING TIME FOR THEM. SPINTROL SHALL NOT BE
 * LIABLE FOR THE USE OF THE SOFTWARE. SPINTROL DOES NOT GUARANTEE THE
 * CORRECTNESS OF THIS SOFTWARE AND RESERVES THE RIGHT TO MODIFY THE SOFTWARE
 * WITHOUT NOTIFICATION.
 *
 ******************************************************************************/

#include"spc1168.h"
#include"spd1178.h"
#include<stdio.h>

/* This macro is used to get the PWM period with a specified frequency */
#define                     PWMPeriod(u32PWMFreqHz)           ((CLOCK_GetModuleClock(PWM_MODULE))/u32PWMFreqHz)/2;

#define                     PRE_DRIVER0_PWM_U                             PWM2
#define                     PRE_DRIVER0_PWM_V                             PWM1
#define                     PRE_DRIVER0_PWM_W                             PWM0
#define                     PRE_DRIVER1_PWM_U                             PWM5
#define                     PRE_DRIVER1_PWM_V                             PWM4
#define                     PRE_DRIVER1_PWM_W                             PWM3
#define                     PRE_DRIVER0_LINK_PWM_U                        SEL_PWM2
#define                     PRE_DRIVER1_LINK_PWM_U                        SEL_PWM5
#define                     PRE_DRIVER0_PWM_FREQ                          1000                  /* 1kHz PWM */
#define                     PRE_DRIVER1_PWM_FREQ                          1000                  /* 1kHz PWM */
#define                     PWM_DB_NS                                     1000                  /* 1us */

uint32_t                    u32PWMPeriod;
uint8_t                     u8PREDRIID                                    = 0;                 /* PRE-DRIVER mode ID */
uint8_t                     u8PREDRIDATA;                                                       /* Data read from PRE-DRIVER */
ErrorStatus                 eErrorState;
uint32_t                    u32SSPBaundrate                               = 1000000;           /* The baundrate of SSP communicating with PRE-DRIVER mode */
uint32_t                    u32Timeout                                    = 500;               /* The number of times try to get PRE-DRIVER mode ID */


 /*************************************************************************************************************************
 *
 * @brief      This case show how to use PWM waveform to control PRE-DRIVER, there gives sketch map about the relationship
 *             between MCU and PRE-DRIVER.
 *
 *                                ----------                ---------
 *                               |  MCU     |   PWM0~2     |   PRE   |---------X  VBOOT(U/V/W)
 *                               |          |--------------| DRIVER0 |---------X  HO   (U/V/W)
 *                               |          |              |         |---------X  PX   (U/V/W)
 *                               |          |              |         |---------X  LO   (U/V/W)
 *                               |          |               ---------
 *                               |          |               ---------
 *                               |          |   PWM3~5     |   PRE   |---------X  VBOOT(U/V/W)
 *                               |          |--------------| DRIVER1 |---------X  HO   (U/V/W)
 *                               |          |              |         |---------X  PX   (U/V/W)
 *                               |          |              |         |---------X  LO   (U/V/W)
 *                                ----------                ---------
 *
 *             Details:
 *                     <1> When MCU and PRE-DRIVER is initialized ok, pwm waveform will be sent to the PRE-DRIVER mode
 *                         (Warnning : the dead-band of the pair complementary waveform of one PWM channel must not be
 *                         larger then 100ns, that is to say, the third parameter of the 'PWM_ComplementaryPairChannelInit()'
 *                         must not equal zero, bigger than 600 is recommanded.)
 *                     <2> PWM output waveform with a stable duty(75%), as a result:
 *                         (#1) VBOOT : output 75% duty(about 75% duty) square wave with the voltage change from 0 to VBAT + VDDG.
 *                         (#2) HO    : output 75% duty(about 75% duty) square wave with the voltage change from PX voltage to VBAT.
 *                         (#3) PX    : output 75% duty(about 75% duty) square wave with the voltage change from 0(about 0V) to VBAT.
 *                         (#4) LO    : output 75% duty(about 75% duty) square wave with the voltage change from 0 to VDDG.
 *
 *             Key point:
 *             PRE-DRIVER init include two step,
 *                                              <1> Init the communication circuits(SSP circyits) with MCU, we call this
 *                                                  step 'Init PRE-DRIVER module'.
 *                                              <2> Init PRE-DRIVER socket itself, we call this step 'Power up PRE-DRIVER mode'.
 *
 *************************************************************************************************************************/


int main()
{
  FLASH_WALLOW();
  FLASH_SetTiming(200000000);
  /* Disable flash write access after flash operation had done */
  FLASH_WDIS();

  CLOCK_InitWithRCO(CLOCK_HCLK_200MHZ);

  Delay_Init();

  /*
   * Init the UART
   *
   * 1.Set the GPIO34/35 as UART FUNC
   *
   * 2.Enable the UART CLK
   *
   * 3.Set the rest para
   */
  GPIO_SetPinChannel(GPIO_34,GPIO34_UART_TXD);
  GPIO_SetPinChannel(GPIO_35,GPIO35_UART_RXD);
  CLOCK_EnableModule(UART_MODULE);
  UART_Init(UART,38400);
  
  /* Init PRE-DRIVER module(this step means ) and get the ID */
  eErrorState = HV_Init(u32SSPBaundrate, &u8PREDRIID, u32Timeout);
  if(eErrorState == ERROR)
  {
    printf("Init PRE-DRIVER mode FAIL\n");
    return 0;
  }
  else
  {
    printf("Init PRE-DRIVER mode SUCCESS[ID:%d]\n",u8PREDRIID);
  }
  
  /* Power up PRE-DRIVER mode(VDDG is enable at this step) */
  eErrorState = HV_WriteReg(HV_REG_PWRUPKEY, PWRUPKEY_ALL_PUKEY_(0x9));
  if(eErrorState == ERROR)
  {
    printf("Power up PRE-DRIVER FAIL\n");
    return 0;
  }
  
  /* Delay 100us to wait for the VDDG LDO ready */
  Delay_Us(100);
  
  /* Wait for PRE-DRIVER mode is power ok */
  eErrorState = HV_ReadReg(HV_REG_GLBSTS, &u8PREDRIDATA);
  if((u8PREDRIDATA & 0x3) == 0)
  {
    printf("PRE-DRIVER power on FAIL[%02x]\n",u8PREDRIDATA);
    return 0;
  }
  
  /* additional delay after VDDG ready, for final power settling */
  Delay_Us(100);
  
  /* 
   * Init PWM0~5
   *
   * Warnning : 
   *           when PWM is used for PRE-DRIVER, the dead-band of the pair complementary waveform of one PWM channel
   *           must not equal zero, bigger than 600 is recommanded.
   */
  PWM_ComplementaryPairChannelInit(PRE_DRIVER1_PWM_U, PRE_DRIVER0_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER1_PWM_V, PRE_DRIVER0_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER1_PWM_W, PRE_DRIVER0_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER0_PWM_U, PRE_DRIVER1_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER0_PWM_V, PRE_DRIVER1_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER0_PWM_W, PRE_DRIVER1_PWM_FREQ, PWM_DB_NS);

  /* 
   * PWM_U set CMPA and loading the same value to PWM_V/PWM_W synchronously, LINK must be set earlier than CAMP value is set,
   * otherwaise, the LINK function will be invalid.
   */
  PWM_LinkCMPA(PRE_DRIVER1_PWM_V, PRE_DRIVER1_LINK_PWM_U);
  PWM_LinkCMPA(PRE_DRIVER1_PWM_W, PRE_DRIVER1_LINK_PWM_U);

  /* Set PWM5A output 75% duty waveform */
  u32PWMPeriod = PWMPeriod(PRE_DRIVER1_PWM_FREQ);
  PWM_SetCMPA(PRE_DRIVER1_PWM_U, u32PWMPeriod / 4);
  
  /* PWM_U set CMPA and loading the same value to PWM_V/PWM_W synchronously */
  PWM_LinkCMPA(PRE_DRIVER0_PWM_V, PRE_DRIVER0_LINK_PWM_U);
  PWM_LinkCMPA(PRE_DRIVER0_PWM_W, PRE_DRIVER0_LINK_PWM_U);
  
  /* Set PWM5A output 75% duty waveform */
  u32PWMPeriod = PWMPeriod(PRE_DRIVER0_PWM_FREQ);
  PWM_SetCMPA(PRE_DRIVER0_PWM_U, u32PWMPeriod / 4);

  /* Set PWM of PRE-DRIVER 0 start to count */
  PWM_RunCounter(PRE_DRIVER0_PWM_U);
  PWM_RunCounter(PRE_DRIVER0_PWM_V);
  PWM_RunCounter(PRE_DRIVER0_PWM_W);
  
  /* Set PWM of PRE-DRIVER 1 start to count */
  PWM_RunCounter(PRE_DRIVER1_PWM_U);
  PWM_RunCounter(PRE_DRIVER1_PWM_V);
  PWM_RunCounter(PRE_DRIVER1_PWM_W);
  
  while(1)
  {
    
  }
}
