/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2022. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

/******************************************************************************
* @version: V1.0.0  demo
******************************************************************************/

/*!
 * @file spm_sample.c
 *
 * @brief This file is spm_sample.c.
 *
 */

/* ===========================================  Includes  =========================================== */
#include "gpio.h"
#include "spm_sample.h"
#include "ac780x_spm.h"


/* ============================================  Define  ============================================ */


/* ===========================================  Typedef  ============================================ */


/* ==========================================  Variables  =========================================== */


/* ====================================  Functions declaration  ===================================== */


/* ======================================  Functions define  ======================================== */

/*!
 * @brief GPIO_DeInit function
 *          used gpio or other module need config
 *          example for LED gpio user
 * @param[in] none
 *
 * @return none
 */
void GPIO_Led_Key_DeInit(void)
{
    /* Select GPIO multiplexing function */
    GPIO_SetFunc(LED1_GPIO, LED1_PIN, GPIO_FUN0);
    GPIO_SetFunc(LED2_GPIO, LED2_PIN, GPIO_FUN0);
    GPIO_SetFunc(RGBLED_R_GPIO, RGBLED_R_PIN, GPIO_FUN0);
    GPIO_SetFunc(RGBLED_G_GPIO, RGBLED_G_PIN, GPIO_FUN0);
    GPIO_SetFunc(RGBLED_B_GPIO, RGBLED_B_PIN, GPIO_FUN0);

    /*set user gpio input pullup*/
    GPIO_SetDir(LED1_GPIO, LED1_PIN, GPIO_IN);
    GPIO_SetDir(LED2_GPIO, LED2_PIN, GPIO_IN);
    GPIO_SetDir(RGBLED_R_GPIO, RGBLED_R_PIN, GPIO_IN);
    GPIO_SetDir(RGBLED_G_GPIO, RGBLED_G_PIN, GPIO_IN);
    GPIO_SetDir(RGBLED_B_GPIO, RGBLED_B_PIN, GPIO_IN);

    GPIO_SetPullup(LED1_GPIO, LED1_PIN, ENABLE);
    GPIO_SetPullup(LED2_GPIO, LED2_PIN, ENABLE);
    GPIO_SetPullup(RGBLED_R_GPIO, RGBLED_R_PIN, ENABLE);
    GPIO_SetPullup(RGBLED_G_GPIO, RGBLED_G_PIN, ENABLE);
    GPIO_SetPullup(RGBLED_B_GPIO, RGBLED_B_PIN, ENABLE);
}

/*!
 * @brief GPIO_Led_Key_DeInit_HZ function
 *          used gpio or other module need config
 *          example for LED gpio user
 * @param[in] none
 *
 * @return none
 */
void GPIO_Led_Key_DeInit_HZ(void)
{
    /* Select GPIO multiplexing function HZ*/
    GPIO_SetFunc(LED1_GPIO, LED1_PIN, GPIO_FUN6);
    GPIO_SetFunc(LED2_GPIO, LED2_PIN, GPIO_FUN6);
    GPIO_SetFunc(RGBLED_R_GPIO, RGBLED_R_PIN, GPIO_FUN6);
    GPIO_SetFunc(RGBLED_G_GPIO, RGBLED_G_PIN, GPIO_FUN6);
    GPIO_SetFunc(RGBLED_B_GPIO, RGBLED_B_PIN, GPIO_FUN6);
}


/*!
 * @brief Spm_GetWakeupSource function
 *
 * @param[in] none
 *
 * @return none
 */
void Spm_GetWakeupSource(void)
{
    uint32_t status = 0;
    status = SPM_GetModuleWakeupSourceFlag();                                                   /*get wakeup source flag*/

    printf("Wakeup Source Reg  = 0x%x\r\n", status);


    if (1 == ((status & SPM_EN_PERIPH_WAKEUP_GPIO_Msk) >> SPM_EN_PERIPH_WAKEUP_GPIO_Pos))       /*judge spm wakeup source e.g.: GPIO EXTIx_IRQHandler*/
    {
        printf("\r\n Wakeup Source is GPIO by EXTIx_IRQHandler need to clear wakeup flag\r\n");
    }

    if (1 == ((status & SPM_EN_PERIPH_WAKEUP_LVD_Msk) >> SPM_EN_PERIPH_WAKEUP_LVD_Pos))         /*judge spm wakeup source e.g.: Lvd LVD_IRQHandler*/
    {
        printf("\r\n Wakeup Source is Lvd by LVD_IRQHandler no need to clear wakeup flag\r\n");
    }
}

/*!
 * @brief Spm_GetResetStatus function
 * @param[in] none
 *
 * @return none
 */
void Spm_GetResetStatus(void)
{
    uint32_t status = 0;
    status = READ_MEM32(0x40000010);                                            /*get ckgen reset status*/
    printf("\r\n System reset status = 0x%08x\r\n", status);
    SET_BIT32(CKGEN->RESET_STATUS, CKGEN_RESET_STATUS_CLR_RESET_STATUS_Msk);    /*clear ckgen reset status*/

}

/*!
 * @brief Spm_ClearWakeupSource function
 *          if wakeup source not by SPM_IRQHandler or LVD_IRQHandler
 *          need to call this function
 * @param[in] none
 *
 * @return none
 */

void Spm_ClearWakeupSource(void)
{
    SPM_ClearWakeupSourceFlag();                            /*clear wakeup source*/
}


/*!
 * @brief   Lvd interrupt callback function
 *
 * @param   none
 * @return  none
 */
static void LVD_HandelerCallback(void *device, uint32_t wpara, uint32_t lpara)
{
    LED1_TOGGLE;                                            /*LVD callback led toggle*/
    LED2_TOGGLE;
    Spm_GetWakeupSource();                                  /*get wakeup source*/
    NVIC_ClearPendingIRQ(LVD_IRQn);                         /*clear pending interrupt*/
    NVIC_DisableIRQ(LVD_IRQn);                              /*disable lvd interrupt*/
}

/*!
 * @brief   Spm Lvd Config
 *
 * @param   none
 * @return  none
 */
void Spm_Lvd_Config(void)
{

    SPM_EnableLVD(ENABLE);                                  /*enable low voltage detection*/
    SPM_SetLVDThreshold(SPM_HIGH_THRESHOLD);                /*set low voltage detection threshold*/
    LVD_SetCallback(LVD_HandelerCallback);                  /*set low voltage detection callback*/

    SPM_EnableModuleWakeup(SPM_MODULE_LVD, ENABLE);         /*enable wakeup source Lvd*/
    mdelay(1000);                                           /*aviod always low power,can't download*/

    NVIC_ClearPendingIRQ(LVD_IRQn);
    NVIC_EnableIRQ(LVD_IRQn);
}

/*!
 * @brief   Spm Lvr Config
 *
 * @param   none
 * @return  none
 */
void Spm_Lvr_Config(void)
{

    SPM_EnableLVR(ENABLE);                                  /*enable low voltage detection*/
    SPM_SetLVRThreshold(SPM_HIGH_THRESHOLD);                /*set low voltage detection threshold*/
}


/*!
 * @brief   Spm go stop mode config
 *
 * @param   none
 * @return  none
 */
void Spm_GotoStop_Config(void)
{
    SPM_EnableModuleWakeup(SPM_MODULE_GPIO, ENABLE);        /*enable wakeup source Gpio*/
    GPIO_Led_Key_DeInit_HZ();                               /*Before go to stop,need config Gpio HZ*/
    mdelay(1000);                                           /*aviod always low power,can't download*/
}

/*!
 * @brief   Spm go standby mode config
 *
 * @param   none
 * @return  none
 */
void Spm_GotoStandby_Config(void)
{
    SPM_EnableModuleWakeup(SPM_MODULE_GPIO, ENABLE);        /*enable wakeup source Gpio*/
    GPIO_Led_Key_DeInit_HZ();                               /*Before go to stop,need config Gpio HZ*/
    mdelay(1000);                                           /*aviod always low power,can't download*/

}

/*!
 * @brief   Spm_ExitLowPowerMode_Config function
 *
 * @param   none
 * @return  none
 */
void Spm_ExitLowPowerMode_Config(void)
{
    GPIO_LedInit();
    GPIO_KeyInit();


    Spm_GetWakeupSource();                                 /*get wakeup source*/
    Spm_ClearWakeupSource();                               /*if wakeup interrupt not by spm & lvd,need clear wakeup source*/
}

/*!
 * @brief   Xosc_Clock_Monitor function
 *
 * @param   none
 * @return  none
 */
void Xosc_Clock_Monitor(void)
{
    MODIFY_REG32(CKGEN->CTRL, CKGEN_CTRL_XOSC_MON_EN_Msk, CKGEN_CTRL_XOSC_MON_EN_Pos, 1);                               /*set ckgen xosc monitor enable*/
    MODIFY_REG32(CKGEN->RESET_CTRL, CKGEN_RESET_CTRL_XOSC_LOSS_RST_EN_Msk, CKGEN_RESET_CTRL_XOSC_LOSS_RST_EN_Pos, 1);   /*set ckgen xosc monitor reset enable*/
}

/* =============================================  EOF  ============================================== */
