/*!
 * @file        main.c
 *
 * @brief       Main program body
 *
 * @version     V1.0.3
 *
 * @date        2025-05-31
 *
 * @attention
 *
 *  Copyright (C) 2023-2025 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

/* Includes */
#include "main.h"

/** @addtogroup Examples
  @{
*/

/** @addtogroup WUPT
  @{
*/

/** @defgroup WUPT_Functions Functions
  @{
*/

/* Measure the LIRC frequency */
uint32_t LIRCMeasurment(void);
/* Enable low power configuration */
void ConfigLowPowerMode(void);
/* WUPT init */
void WUPT_Init(void);
/* KeyProcess */
void KeyProc(void);

/*!
 * @brief       Main program
 *
 * @param       None
 *
 * @retval      None
 */
int main(void)
{
    APM_MINI_LEDInit(LED2);
    APM_MINI_LEDInit(LED3);
    APM_DelayInit(APM_DELAY_MS);
    APM_MINI_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);
    ConfigLowPowerMode();
    WUPT_Init();
    while(1)
    {
        KeyProc();
    }
}

/*!
 * @brief       Measure the LIRC frequency
 *
 * @param       None
 *
 * @retval      LIRC frequency in HZ
 */
uint32_t LIRCMeasurment(void)
{
    uint16_t icValue[2];
    uint32_t freqLIRC;
    uint32_t freqMasterClk;
    TMR1_ICConfig_T icConfig;

    freqMasterClk = RCM_GetMasterClockFreq();

    WUPT_EnableLIRCMeasurement();

    icConfig.channel = TMR1_CHANNEL_1;
    icConfig.div = TMR1_IC_DIV_8;
    icConfig.filter = 0;
    icConfig.polarity = TMR1_IC_POLARITY_FALLING;
    icConfig.selection = TMR1_IC_SELECT_DIRECTTI;
    TMR1_ConfigInputCapture(TMR1, &icConfig);
    TMR1_Enable(TMR1);

    while(TMR1_ReadStatusFlag(TMR1, TMR1_FLAG_CH1CC) == RESET);
    icValue[0] = TMR1_ReadCompareCapture(TMR1, TMR1_CHANNEL_1);
    TMR1_ClearStatusFlag(TMR1, TMR1_FLAG_CH1CC);

    while(TMR1_ReadStatusFlag(TMR1, TMR1_FLAG_CH1CC) == RESET);
    icValue[1] = TMR1_ReadCompareCapture(TMR1, TMR1_CHANNEL_1);
    TMR1_ClearStatusFlag(TMR1, TMR1_FLAG_CH1CC);

    TMR1_DisableCompareCapture(TMR1, TMR1_CHANNEL_1);
    TMR1_Disable(TMR1);

    freqLIRC = (8 * freqMasterClk) / (icValue[1] - icValue[0]);

    WUPT_DisableLIRCMeasurement();

    return freqLIRC;
}

/*!
 * @brief       WUPT init
 *
 * @param       None
 *
 * @retval      None
 */
void WUPT_Init(void)
{
    uint32_t freqLIRC = 0;

    freqLIRC = LIRCMeasurment();
    WUPT_CalibrationLIRC(freqLIRC);
    WUPT_Config(AWU_TIMEBASE_2S);

    NVIC_EnableIRQRequest(WUPT_IRQn, 0X01);
}

/*!
 * @brief       Configuration low power mode
 *
 * @param       None
 *
 * @retval      None
 */
void ConfigLowPowerMode(void)
{
    uint32_t optByte;
    FMC_UserConfig_T optConfig;
    FMC_Unlock();
    optByte = FMC_ReadOptionByteUser();
    optConfig.wwdtSw    = ((optByte & 0x04) >> 2) == 0 ? FMC_OB_WWDT_HW : FMC_OB_WWDT_SW;
    optConfig.iwdtSw    = ((optByte & 0x10) >> 4) == 0 ? FMC_OB_IWDT_HW : FMC_OB_IWDT_SW;
    optConfig.wwdtHalt  = ((optByte & 0x08) >> 3) == 0 ? FMC_OB_WWDT_HALT_RST : FMC_OB_WWDT_HALT_NORST;
    optConfig.LIRCen    = ((optByte & 0x20) >> 5) == 0 ? FMC_OB_LIRCEN_ENABLE : FMC_OB_LIRCEN_DISABLE;
    optConfig.trimHIRC  = ((optByte & 0x40) >> 6) == 0 ? FMC_OB_HIRC_TRIM_4 : FMC_OB_HIRC_TRIM_3;
    if (optConfig.LIRCen == FMC_OB_LIRCEN_DISABLE)
    {
        optConfig.LIRCen = FMC_OB_LIRCEN_ENABLE;
        FMC_ConfigOptionByteUser(&optConfig);
        NVIC_SystemReset();
    }

    RCM_EnableLIRC();
    RCM_SwitchClockStruct_T switchClockStruct;
    switchClockStruct.currentClkState = RCM_CLOCK_STATE_OFF;
    switchClockStruct.intEnable = DISABLE;
    switchClockStruct.clockSource = RCM_MCLKSRC_LIRC;
    switchClockStruct.mode = RCM_SWITCH_MODE_AUTO;
    RCM_ConfigClockSwitch(&switchClockStruct);
    while(RCM_ReadClockFlag(RCM_CLOCK_FLAG_CSBSY));
}

/*!
 * @brief       WUPT interrupt service routine
 *
 * @param       None
 *
 * @retval      None
 */
void WUPT_Isr(void)
{
    if(WUPT_ReadIntFlag() == SET)
    {
        APM_MINI_LEDOn(LED2);
    }
}

/*!
 * @brief       Key process
 *
 * @param       None
 *
 * @retval      None
 */
void KeyProc(void)
{
    uint8_t i;

    if(APM_MINI_ReadPBState(BUTTON_KEY1) == BIT_RESET)
    {
        while(APM_MINI_ReadPBState(BUTTON_KEY1) == BIT_RESET);

        for(i = 0; i < 5; i++)
        {
            APM_Delay(500);
            APM_MINI_LEDToggle(LED2);
            APM_MINI_LEDToggle(LED3);
        }
        APM_MINI_LEDOff(LED2);
        APM_MINI_LEDOff(LED3);

        PMU_EnterHaltModeWFI();

        APM_MINI_LEDOn(LED2);
        APM_MINI_LEDOn(LED3);
    }
}

/**@} end of group WUPT_Functions */
/**@} end of group WUPT */
/**@} end of group Examples */
