/* 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) 2023. 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.
 */

/*!
 * @file system_ac7803x.h
 *
 * @brief This file provides system clock config integration functions interfaces.
 *
 */

#ifndef _SYSTEM_AC7803X_H
#define _SYSTEM_AC7803X_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* ===========================================  Includes  =========================================== */
#include "ac780x_ckgen.h"
#include "ac780x_spm.h"
#include "device_assert.h"
#include "ac7803x_debugout.h"

/* ============================================  Define  ============================================ */
/*!< Watchdog disable */
#define WDG_DISABLE              (1UL)

/*!< LVR disable */
#define LVR_DISABLE              (0UL)

/*!< System clock configure */
#define IC_CLOCK_SRC_HSI         0U  /*!< HSI 8MHz */
#define IC_CLOCK_SRC_HSE         2U  /*!< XOSC(8-30MHz) or XOSC bypass(up to 30MHz) */
#define IC_CLOCK_SRC_HSI_PLL     3U  /*!< HSI + PLL */
#define IC_CLOCK_SRC_HSE_PLL     4U  /*!< HSE + PLL */

#define CKGEN_HSE_BYPASS_ENABLE    0U  /*!< HSE XOSC bypass mode enable */
#define CKGEN_XOSC_MONITOR_ENABLE  0U  /*!< HSE XOSC monitor enable */

#define AC780X_CLOCK_SRC  IC_CLOCK_SRC_HSE_PLL /*!< define mcu clock source */

#define HSI_FREQ      8000000UL   /*!< Internal 8M RC clock */

#define XTAL_8M       8000000UL   /*!< extern crystal oscillator 8M  */
#define XTAL_12M     12000000UL   /*!< extern crystal oscillator 12M */
#define XTAL_16M     16000000UL   /*!< extern crystal oscillator 16M */
#define XTAL_30M     30000000UL   /*!< extern crystal oscillator 30M */

#define USE_XTAL     XTAL_8M      /*!< Select the actual crystal frequency */

#define CKGEN_AUTO_CHANGE_CLK  1U  /*!< Auto change system clock to internal clock after detect xosc or pll fail */

/*!< PLL configure */
#ifndef PLL_CONFIG_72M  /* Output 64MHz */
#if USE_XTAL == XTAL_8M
#define PLL_POSDIV   PLL_POSDIV_8
#define PLL_FBKDIV   64U
#define PLL_PREDIV   PLL_PREDIV_1
#elif USE_XTAL == XTAL_12M
#define PLL_POSDIV   PLL_POSDIV_12
#define PLL_FBKDIV   64U
#define PLL_PREDIV   PLL_PREDIV_1
#elif USE_XTAL == XTAL_16M
#define PLL_POSDIV   PLL_POSDIV_8
#define PLL_FBKDIV   64U
#define PLL_PREDIV   PLL_PREDIV_2
#elif USE_XTAL == XTAL_30M  /* Output 60MHz */
#define PLL_POSDIV   PLL_POSDIV_20
#define PLL_FBKDIV   160U
#define PLL_PREDIV   PLL_PREDIV_4
#else
#error
#endif

#else  /* Output 72MHz */
#if USE_XTAL == XTAL_8M
#define PLL_POSDIV   PLL_POSDIV_8
#define PLL_FBKDIV   72U
#define PLL_PREDIV   PLL_PREDIV_1
#elif USE_XTAL == XTAL_12M
#define PLL_POSDIV   PLL_POSDIV_12
#define PLL_FBKDIV   72U
#define PLL_PREDIV   PLL_PREDIV_1
#elif USE_XTAL == XTAL_16M
#define PLL_POSDIV   PLL_POSDIV_8
#define PLL_FBKDIV   72U
#define PLL_PREDIV   PLL_PREDIV_2
#elif USE_XTAL == XTAL_30M
#define PLL_POSDIV   PLL_POSDIV_10
#define PLL_FBKDIV   96U
#define PLL_PREDIV   PLL_PREDIV_4
#else
#error
#endif
#endif

/*!< VCO = (SRC_CLK / PLL_PREDIV) * PLL_FBKDIV;
     SYSCLK_FREQ = VCO / PLL_POSDIV / SYSCLK_DIV;
     APB_BUS_FREQ = SYSCLK_FREQ / APBCLK_DIV
*/
#define SYSCLK_DIV   SYSCLK_DIVIDER_1
#define APBCLK_DIV   APBCLK_DIVIDER_2

#if (AC780X_CLOCK_SRC == IC_CLOCK_SRC_HSI)
#define SYSCLK_FREQ  (HSI_FREQ / ((uint32_t)SYSCLK_DIV + 1U))
#elif (AC780X_CLOCK_SRC == IC_CLOCK_SRC_HSE)
#define SYSCLK_FREQ  (USE_XTAL / ((uint32_t)SYSCLK_DIV + 1U))
#elif (AC780X_CLOCK_SRC == IC_CLOCK_SRC_HSI_PLL)
#define SYSCLK_FREQ  (((HSI_FREQ / ((uint32_t)PLL_PREDIV + 1U)) * ((uint32_t)PLL_FBKDIV)) / \
                      ((uint32_t)PLL_POSDIV * 2U) / ((uint32_t)SYSCLK_DIV + 1U))
#elif (AC780X_CLOCK_SRC == IC_CLOCK_SRC_HSE_PLL)
#define SYSCLK_FREQ  (((USE_XTAL / ((uint32_t)PLL_PREDIV + 1U)) * ((uint32_t)PLL_FBKDIV)) / \
                      ((uint32_t)PLL_POSDIV * 2U) / ((uint32_t)SYSCLK_DIV + 1U))
#else
error
#endif
#define APB_BUS_FREQ (SYSCLK_FREQ / ((uint32_t)APBCLK_DIV + 1U))

#define __SYSTEM_CLOCK    SYSCLK_FREQ

/*!< Global interrupt control */
#define EnableInterrupts  __ASM(" CPSIE i");
#define DisableInterrupts __ASM(" CPSID i");

/*!< Global fault control */
#define EnableFatules     __ASM(" CPSIE F");
#define DisableFatules    __ASM(" CPSID F");

/* ===========================================  Typedef  ============================================ */
/*!
 * @brief Driver status.
 */
typedef enum
{
    /* Generic error codes */
    STATUS_SUCCESS                         = 0x000U,    /*!< Generic operation success status */
    STATUS_ERROR                           = 0x001U,    /*!< Generic operation failure status */
    STATUS_BUSY                            = 0x002U,    /*!< Generic operation busy status */
    STATUS_TIMEOUT                         = 0x003U,    /*!< Generic operation timeout status */
    STATUS_UNSUPPORTED                     = 0x004U,    /*!< Generic operation unsupported status */
    /* I2C specific error codes */
    STATUS_I2C_RECEIVED_NACK               = 0x200U,    /*!< NACK signal received  */
    STATUS_I2C_TX_UNDERRUN                 = 0x201U,    /*!< TX underrun error */
    STATUS_I2C_RX_OVERRUN                  = 0x202U,    /*!< RX overrun error */
    STATUS_I2C_ARBITRATION_LOST            = 0x203U,    /*!< Arbitration lost */
    STATUS_I2C_ABORTED                     = 0x204U,    /*!< A transfer was aborted */
    STATUS_I2C_BUS_BUSY                    = 0x205U,    /*!< I2C bus is busy, cannot start transfer */
    /* SPI specific error codes */
    STATUS_SPI_TX_UNDERRUN                 = 0x500U,    /*!< TX underrun error */
    STATUS_SPI_RX_OVERRUN                  = 0x501U,    /*!< RX overrun error */
    STATUS_SPI_ABORTED                     = 0x502U,    /*!< A transfer was aborted */
    /* UART specific error codes */
    STATUS_UART_TX_UNDERRUN                = 0x600U,    /*!< TX underrun error */
    STATUS_UART_RX_OVERRUN                 = 0x601U,    /*!< RX overrun error */
    STATUS_UART_ABORTED                    = 0x602U,    /*!< A transfer was aborted */
    STATUS_UART_FRAMING_ERROR              = 0x603U,    /*!< Framing error */
    STATUS_UART_PARITY_ERROR               = 0x604U,    /*!< Parity error */
    STATUS_UART_BREAK_ERROR                = 0x605U,    /*!< Break error */
    STATUS_UART_NOISE_ERROR                = 0x606U,    /*!< Noise error */
    /* I2S specific error codes */
    STATUS_I2S_TX_UNDERRUN                 = 0x700U,    /*!< TX underrun error */
    STATUS_I2S_RX_OVERRUN                  = 0x701U,    /*!< RX overrun error */
    STATUS_I2S_ABORTED                     = 0x702U,    /*!< A transfer was aborted */
} status_t;

/* ==========================================  Variables  =========================================== */
extern uint32_t SystemCoreClock;     /*!< System Clock Frequency (Core Clock)  */
extern uint32_t g_periphAPBClock;    /*!< APB Clock Frequency */

/* ====================================  Functions declaration  ===================================== */
/*!
 * @brief Setup the microcontroller system. Initialize the System.
 *
 * @param[in] none
 * @return none
 */
extern void SystemInit(void);

/*!
 * @brief Get system clock frequence.
 *
 * @param[in] none
 * @return none
 */
extern void SystemCoreClockUpdate(void);

/*!
 * @brief Init delay count factor, 1s = TICKS * (1/f) s.
 *
 * @param[in] none
 * @return none
 */
extern void InitDelay(void);

/*!
 * @brief Delay us.
 *
 * @param[in] us: us for delay
 * @return none
 */
extern void udelay(uint32_t us);

/*!
 * @brief Delay ms.
 *
 * @param[in] ms: ms for delay
 * @return none
 */
extern void mdelay(uint32_t ms);

/*!
 * @brief Get CPU ID.
 *
 * @param[in] none
 * @return return the CPUID
 */
uint32_t GetCPUID(void);

/*!
 * @brief Enter the Standby mode.
 *
 * @param[in] none
 * @return none
 */
extern void SysStandby(void);

/*!
 * @brief Enter the stop mode.
 *
 * @param[in] none
 * @return none
 */
extern void SysStop(void);

/*!
 * @brief Enter the CPU sleep mode.
 *
 * @param[in] none
 * @return none
 */
extern void SysSleep(void);

/*!
 * @brief Get uuid from device.
 *
 * @param[in] uuidBuffer: uuid buffer
 * @return none
 */
extern void GetUUID(uint32_t *uuidBuffer);

/*!
 * @brief Get cpu type from device.
 *
 * @param[in] none
 * @return cpu type: AC7803
 */
extern uint32_t GetCpuType(void);

/*!
 * @brief Get reset status.
 *
 * @param[in] none
 * @return reset status
 *            - bit0: POR_RESET_STATUS
 *            - bit1: LVR_RESET_STATUS
 *            - bit2: EXT_RESET_STATUS
 *            - bit3: ECC2_RESET_STATUS
 *            - bit4: WDG_32K_RESET_STATUS
 *            - bit5: WDG_RESET_STATUS
 *            - bit6: CPU_SYSRESET_STATUS
 *            - bit7: CPU_LOCKUP_RST_STATUS
 *            - bit8: PLL_UNLOCK_RST_STATUS
 *            - bit9: XOSC_LOSS_RST_STATUS
 *            - bit10: FLASH_ECC2_RST_STATUS
 */
extern uint32_t GetResetStatus(void);

/*!
 * @brief Clear all reset status.
 *
 * @param[in] none
 * @return none
 */
extern void ClearAllResetStatus(void);

/*!
 * @brief Enable/disable external reset.
 *
 * @param[in] enable: enable state
 *                   - ENABLE
 *                   - DISABLE
 * @return none
 */
extern void SetExternalReset(ACTION_Type enable);

/*!
 * @brief Configure external reset filter.
 *
 * @param[in] enable: enable state
 *                   - ENABLE
 *                   - DISABLE
 * @param[in] value: filter value
 * @return none
 */
extern void SetExternalResetFilter(ACTION_Type enable, uint8_t value);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _SYSTEM_AC7803X_H */

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