/******************************************************************************
 * @file     delay.c
 * @brief    Time-Delay firmware functions.
 * @version  V4.0.0
 * @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 "delay.h"



#if defined(__CC_ARM)
    #pragma push
    #pragma O1
#endif




/**
 *  @brief  Clock cycles per microseconds
 */
uint32_t u32DelayLoopPerUs;      /* (1) The number of loops in one us
                                    (2) Used for time out when timer is used as delay */
uint32_t u32DelayClockPerUs;




/******************************************************************************
 * @brief      Initializes the time-delay module
 *
 * @param[in]  none
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void Delay_Init(void)
{
#if   defined ( DELAY_BY_SW_SRAM )
    u32DelayLoopPerUs = ((SysInfo.u32HCLK) / 1000000) >> 2;  /* Each loop will cost 4 cycles */
    if (u32DelayLoopPerUs < 1)
    {
        u32DelayLoopPerUs = 1;
    }
#elif defined ( DELAY_BY_SW_FLASH )
    u32DelayLoopPerUs = 8;
#else
    u32DelayClockPerUs = (SysInfo.u32HCLK / 1000000);
    u32DelayLoopPerUs  = (SysInfo.u32HCLK / 1000000) << 2;

#if   defined ( DELAY_BY_HW_TIMER0 )
    CLOCK_EnableModule(TIMER0_MODULE);
#elif defined ( DELAY_BY_HW_TIMER1 )
    CLOCK_EnableModule(TIMER1_MODULE);
#elif defined ( DELAY_BY_HW_TIMER2 )
    CLOCK_EnableModule(TIMER2_MODULE);
#endif

    TIMER_EnableInt(DELAY_TIMER);
#endif
}




/******************************************************************************
 * @brief      Delays the specified milliseconds
 *
 * @param[in]  u32Delay_Ms:  The milliseconds to delay, if the system clock = 24 MHz,
 *                           the maximum time delay is 699 ms.
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void Delay_Ms(uint32_t u32Delay_Ms)
{
    Delay_Us(u32Delay_Ms * 1000);
}




/******************************************************************************
 * @brief      Delays the specified microseconds
 *
 * @param[in]  u32Delay_Us:  The microseconds to delay
 *
 * @return     none
 *
 ******************************************************************************/
#if defined(__ICCARM__)
#pragma optimize=low
#endif
void Delay_Us(uint32_t u32Delay_Us)
{
#if  defined( DELAY_BY_SW_FLASH ) || defined ( DELAY_BY_SW_SRAM )
    /* Delay by CPU */
    u32Delay_Us = (u32Delay_Us * u32DelayLoopPerUs);                      /* There is 4 cycle during for in O0~O3  */
    while (u32Delay_Us)
    {
        u32Delay_Us--;
    }
#else
    /* Delay by timer */
    volatile uint32_t u32Timeout;                                         /* Prevent optimization effect           */
    /* This timeout is suitable for O0~O3    */

    u32Timeout = u32DelayLoopPerUs;                                       /* About 1.25 us as timeout in O1~O3     */
    /* About 1.5  us as timeout in O0        */

    TIMER_Stop(DELAY_TIMER);                                              /* Stop timer                            */
    TIMER_SetReloadValue(DELAY_TIMER, u32Delay_Us * u32DelayClockPerUs);  /* Set timer reload value                */
    TIMER_ClearInt(DELAY_TIMER);                                          /* Clear timer interrupt flag            */
    TIMER_Run(DELAY_TIMER);                                               /* Timer run                             */
    while ((!TIMER_GetIntFlag(DELAY_TIMER)))                              /* Wait until (1) Timer flag enable      */
    {
        /*            (2) Timer out  occurs      */
        if ((u32Timeout--) == 0)
        {
            break;
        }
    }
#endif
}


#if defined(__CC_ARM)
    #pragma pop
#endif


/******************* Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd. ***** END OF FILE ****/
