/**************************************************************************//**
 * @file     main.c
 * @brief    Main program body
 * @version  V4.0.1
 * @date     30-July-2026
 *
 * @note
 * Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd.. 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 "spd1188.h"
#include <stdio.h>

/* Define for debugging */
#define PRINT_INFO(fmt, args...)        printf("[Info][%s] " fmt "\n", __FUNCTION__, ##args)
#define PRINT_ERR(fmt, args...)         printf("[Error][%s, %d] " fmt "\n", __FUNCTION__, __LINE__, ##args)
#define PRINT_DEBUG(fmt, args...)       printf("[Debug][%s, %d] " fmt "\n", __FUNCTION__, __LINE__, ##args)
#define PRINT(fmt, args...)             printf(fmt, ##args)

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

#define                     PRE_DRIVER_PWM_U                             PWM5
#define                     PRE_DRIVER_PWM_V                             PWM4
#define                     PRE_DRIVER_PWM_W                             PWM3
#define                     PRE_DRIVER_LINK_PWM_U                        SEL_PWM5
#define                     PRE_DRIVER_PWM_FREQ                          10000                  /* 10kHz 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 */
uint8_t                     u8Count;


 /*************************************************************************************************************************
 *
 * @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.
 *
 *                                ----------
 *                               |          |               ---------
 *                               |          |   PWM3~5     |   PRE   |---------X  VBOOT(U/V/W)
 *                               |   MCU    |--------------| DRIVER  |---------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 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(void)
{
  FLASH_WALLOW();
  FLASH_SetTiming(200000000);
  /* Disable flash write access after flash operation had done */
  FLASH_WDIS();

  CLOCK_InitWithRCO(CLOCK_HCLK_50MHZ);

  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 'Init PRE-DRIVER module') 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);
  }

  /* PDRVCTL register can only be writable when CTLKEY=0x99 */
  eErrorState = HV_WriteReg(HV_REG_CTLKEY, CTLKEY_ALL_KEY_BUCKEN);
  if(eErrorState == ERROR)
  {
    printf("Write CTLKEY register FAIL\n");
    return 0;
  }

  /* Power up PRE-DRIVER mode(this step means 'Power up PRE-DRIVER mode') */
  eErrorState = HV_WriteReg(HV_REG_PDRVCTL, PDRVCTL_ALL_EN_ENABLE);
  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 become enable */
  u8Count = 0;
  do{
    eErrorState = HV_ReadReg(HV_REG_GLBSTS0, &u8PREDRIDATA);
    if(eErrorState == ERROR)
    {
      printf("PRE-DRIVER enable FAIL[%02x]\n",u8PREDRIDATA);
      return 0;
    }
    
    u8Count++;
    
    if(u8Count >= 10)
    {
      printf("PRE-DRIVER enable timeout\n");
      return 0;
    }
  }while(((u8PREDRIDATA & GLBSTS0_ALL_CPRDY_READY) == 0) && (u8Count < 10));

  /* 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_DRIVER_PWM_U, PRE_DRIVER_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER_PWM_V, PRE_DRIVER_PWM_FREQ, PWM_DB_NS);
  PWM_ComplementaryPairChannelInit(PRE_DRIVER_PWM_W, PRE_DRIVER_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_DRIVER_PWM_V, PRE_DRIVER_LINK_PWM_U);
  PWM_LinkCMPA(PRE_DRIVER_PWM_W, PRE_DRIVER_LINK_PWM_U);

  /* Set PWM5A output 75% duty waveform */
  u32PWMPeriod = PWMPeriod(PRE_DRIVER_PWM_FREQ);
  PWM_SetCMPA(PRE_DRIVER_PWM_U, u32PWMPeriod / 4);
  
  /* Set PWM of PRE-DRIVER start to count */
  PWM_RunCounter(PRE_DRIVER_PWM_U);
  PWM_RunCounter(PRE_DRIVER_PWM_V);
  PWM_RunCounter(PRE_DRIVER_PWM_W);
  
  GPIO_SetPinChannel(GPIO_36,GPIO36_PWM5A);
  GPIO_SetPinChannel(GPIO_37,GPIO37_PWM5B);

  while(1)
  {
  }
}

