/******************************************************************************
 * @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>

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 the usage of PRE-DRIVER BOD function, which detect the under-voltage and over-voltage of VDDG
 *             and VBAT.
 *
 *                                           PRE-DRIVER(High Voltage Part)
 *                                          ------------                        ------
 *                                         |   -----    | Communicate with SSP |      |
 *                                         |  |ISP  |---|----------------------| MCU  |
 *                                         |  |MODEL|   |                      |      |
 *                                         |   -----    |                      |      |
 *                                         |   -------  |                       ------
 *                                         |  |       | |                      Low voltage part
 *                                         |  |PRE-DRI| |
 *                                         |  |SOCKET | |
 *                                         |   -------  |
 *                                          ------------
 * 
 *             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);
  }

  /* Keep in mind init BOD first and then init VDDG */
  /* Enable BOD of VBAT and VDDG */
  eErrorState = HV_WriteReg(HV_REG_BODCTL, BODCTL_ALL_VDDGEN_ENABLE | BODCTL_ALL_VBATEN_ENABLE);
  if(eErrorState == ERROR)
  {
    printf("Enable DOB of VBAT and VDDG FAIL\n");
    return 0;
  }

  /* Power up PRE-DRIVER mode */
  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);

  /*
   * Set the too high threshold of VDDG (when VDDG excees 14.4V, crossponding aignal will be asserted
   * and status bit will be set, and when lowwer 11.2V, the signal will be deasserted) 
   *
   * Because of the reference voltage is not trimed, the precision of VDDG is not perfect, so we need keep an enough range for
   * the detection. eg, for 12V VDDG, BODVDDGLVTH_ALL_ASSERT_9dot6_V for too low and BODVDDGHVTH_ALL_ASSERT_14dot4_V for too
   * high assert is recommanded.
   */
  eErrorState = HV_WriteReg(HV_REG_BODVDDGHVTH, BODVDDGHVTH_ALL_DEASSERT_11dot2_V | BODVDDGHVTH_ALL_ASSERT_14dot4_V);
  if(eErrorState == ERROR)
  {
    printf("Set over-voltage threshold for VDDG is FAIL\n");
    return 0;
  }

  /*
   * Set the under-voltage threshold of VDDG (when VDDG is lowwer 9.6V, crossponding aignal will be asserted
   * and status bit will be set, and when higher then 12.8V, the signal will be deasserted)
   */
  eErrorState = HV_WriteReg(HV_REG_BODVDDGLVTH, BODVDDGLVTH_ALL_ASSERT_9dot6_V | BODVDDGLVTH_ALL_DEASSERT_12dot8_V);
  if(eErrorState == ERROR)
  {
    printf("Set under-voltage threshold for VDDG is FAIL\n");
    return 0;
  }

  /* 
   * Set the over-voltage threshold of VBAT (when VDDG excees 19.2V, crossponding aignal will be asserted
   * and status bit will be set, and when lowwer 14.4V, the signal will be deassert) 
   */
  eErrorState = HV_WriteReg(HV_REG_BODVBATHVTH, BODVBATHVTH_ALL_DEASSERT_14dot4_V | BODVBATHVTH_ALL_ASSERT_19dot2_V);
  if(eErrorState == ERROR)
  {
    printf("Set over-voltage threshold for VBAT is FAIL\n");
    return 0;
  }

  /*
   * Set the under-voltage threshold of VBAT (when VDDG is lowwer 14.4V, crossponding aignal will be asserted
   * and status bit will be set, and when higher then 19.2V, the signal will be deasserted)
   */
  eErrorState = HV_WriteReg(HV_REG_BODVBATLVTH, BODVBATLVTH_ALL_ASSERT_14dot4_V | BODVBATLVTH_ALL_DEASSERT_19dot2_V);
  if(eErrorState == ERROR)
  {
    printf("Set under-voltage threshold for VBAT is FAIL\n");
    return 0;
  }

  /* 
   * Clear status register before we start to read the status register.
   *
   * The reasons for VDDG:
   * <1> the unpredictable too high latched flag caused by BOD open pulse voltage
   * <2> the unpredictable too low latched flag caused when VDDG across 11.2V(the too low assert voltage)
   */
  eErrorState = HV_WriteReg(HV_REG_GLBSTSCLR, GLBSTSCLR_ALL_VDDGL_CLEAR
                                                          | GLBSTSCLR_ALL_VDDGH_CLEAR
                                                          | GLBSTSCLR_ALL_VBATL_CLEAR
                                                          | GLBSTSCLR_ALL_VBATH_CLEAR);
  if(eErrorState == ERROR)
  {
    printf("Clear status FAIL\n");
    return 0;
  }

  while(1)
  {
    /* Set the output voltage of VDDG as 15V to check if BOD can detect the over-voltage */
    eErrorState = HV_WriteReg(HV_REG_LDOGCTL, LDOGCTL_ALL_VREFSEL_15_V);
    if(eErrorState == ERROR)
    {
      printf("Set VDDG voltage FAIL\n");
      return 0;
    }

    /* Read the GLBSTS register of PRE-DRIVER and Check if there under-voltage or over-voltage event happened */
    eErrorState = HV_ReadReg(HV_REG_GLBSTS, &u8PREDRIDATA);
    if(eErrorState == ERROR)
    {
      printf("Read GLBSTS FAIL\n");
      return 0;
    }

    /* Chech if there is VDDG under-voltage event happened */
    if(u8PREDRIDATA & GLBSTS_ALL_VDDGL_OCCUR)
    {
      printf("VDDG under-voltage event happened\n");

      /* Clear VDDG under-voltage status*/
      eErrorState = HV_WriteReg(HV_REG_GLBSTSCLR, GLBSTSCLR_ALL_VDDGL_CLEAR);
      if(eErrorState == ERROR)
      {
        printf("Clear status FAIL\n");
        return 0;
      }
    }

    /* Chech if there is VDDG over-voltage event happened */
    if(u8PREDRIDATA & GLBSTS_ALL_VDDGH_OCCUR)
    {
      printf("VDDG over-voltage event happened\n");

      /* Clear VDDG over-voltage status*/
      eErrorState = HV_WriteReg(HV_REG_GLBSTSCLR, GLBSTSCLR_ALL_VDDGH_CLEAR);
      if(eErrorState == ERROR)
      {
        printf("Clear status FAIL\n");
        return 0;
      }
    }

    /* Chech if there is VBAT under-voltage event happened */
    if(u8PREDRIDATA & GLBSTS_ALL_VBATL_OCCUR)
    {
      printf("VBAT under-voltage event happened\n");

      /* Clear VBAT under-voltage status*/
      eErrorState = HV_WriteReg(HV_REG_GLBSTSCLR, GLBSTSCLR_ALL_VBATL_CLEAR);
      if(eErrorState == ERROR)
      {
        printf("Clear status FAIL\n");
        return 0;
      }
    }

    /* Chech if there is VBAT over-voltage event happened */
    if(u8PREDRIDATA & GLBSTS_ALL_VBATH_OCCUR)
    {
      printf("VBAT over-voltage event happened\n");

      /* Clear VBAT over-voltage status*/
      eErrorState = HV_WriteReg(HV_REG_GLBSTSCLR, GLBSTSCLR_ALL_VBATH_CLEAR);
      if(eErrorState == ERROR)
      {
        printf("Clear status FAIL\n");
        return 0;
      }
    }

    Delay_Ms(2000);
  }
}
