/*
* Copyright (c) 2023-2028, SpaceTouch Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date          Author      Notes
* 2023-04-18    dongx       the first version
*/

#ifndef _HAL_TIMER_H_
#define _HAL_TIMER_H_

#include "platform.h"

typedef enum
{
    TIM0 = 0,
    TIM1 = 1,
    TIM2 = 2,
    TIM3 = 3,
    TIMx_MAX
} tim_base_t;
#define TIM(n)      (n)

typedef enum
{
    TIM_CLOCK_SOUREC_OSC_ADC = DEV_CMU_TIMERnCLK_SEL_OSC_ADC,
    TIM_CLOCK_SOUREC_OSC_DEV = DEV_CMU_TIMERnCLK_SEL_OSC_DEV,
    TIM_CLOCK_SOUREC_OSC_XTAL = DEV_CMU_TIMERnCLK_SEL_OSC_XTAL,
    TIM_CLOCK_SOUREC_OSC_USB = DEV_CMU_TIMERnCLK_SEL_OSC_USB,
    TIM_CLOCK_SOUREC_PLL_CORE = DEV_CMU_TIMERnCLK_SEL_PLL_CORE,
    TIM_CLOCK_SOUREC_PLL_AUDIO = DEV_CMU_TIMERnCLK_SEL_PLL_AUDIO,
    TIM_CLOCK_SOUREC_USB_SOF = DEV_CMU_TIMERnCLK_SEL_USB_SOF,
    TIM_CLOCK_SOUREC_EXT_CLK = DEV_CMU_TIMERnCLK_SEL_EXT_CLK
} tim_clock_source_t;

typedef enum
{
    TIM_CLOCK_PRESCALE_1 = (0u << 20),
    TIM_CLOCK_PRESCALE_2 = (1u << 20),
    TIM_CLOCK_PRESCALE_3 = (2u << 20),
    TIM_CLOCK_PRESCALE_4 = (3u << 20),
    TIM_CLOCK_PRESCALE_5 = (4u << 20),
    TIM_CLOCK_PRESCALE_6 = (5u << 20),
    TIM_CLOCK_PRESCALE_7 = (6u << 20),
    TIM_CLOCK_PRESCALE_8 = (7u << 20),
    TIM_CLOCK_PRESCALE_9 = (8u << 20),
    TIM_CLOCK_PRESCALE_10 = (9u << 20),
    TIM_CLOCK_PRESCALE_11 = (10u << 20),
    TIM_CLOCK_PRESCALE_12 = (11u << 20),
    TIM_CLOCK_PRESCALE_13 = (12u << 20),
    TIM_CLOCK_PRESCALE_14 = (13u << 20),
    TIM_CLOCK_PRESCALE_15 = (14u << 20),
    TIM_CLOCK_PRESCALE_16 = (15u << 20),
    TIM_CLOCK_PRESCALE_17 = (16u << 20),
    TIM_CLOCK_PRESCALE_18 = (17u << 20),
    TIM_CLOCK_PRESCALE_19 = (18u << 20),
    TIM_CLOCK_PRESCALE_20 = (19u << 20),
    TIM_CLOCK_PRESCALE_21 = (20u << 20),
    TIM_CLOCK_PRESCALE_22 = (21u << 20),
    TIM_CLOCK_PRESCALE_23 = (22u << 20),
    TIM_CLOCK_PRESCALE_24 = (23u << 20),
    TIM_CLOCK_PRESCALE_25 = (24u << 20),
    TIM_CLOCK_PRESCALE_26 = (25u << 20),
    TIM_CLOCK_PRESCALE_27 = (26u << 20),
    TIM_CLOCK_PRESCALE_28 = (27u << 20),
    TIM_CLOCK_PRESCALE_29 = (28u << 20),
    TIM_CLOCK_PRESCALE_30 = (29u << 20),
    TIM_CLOCK_PRESCALE_31 = (30u << 20),
    TIM_CLOCK_PRESCALE_32 = (31u << 20)
} tim_clock_prescale_t;
#define TIM_CLOCK_PRESCALE(n)   (((n)-1) << 20)

typedef enum
{
    TIM_MODE_TIMER = DEV_TIMER_CTL_MODE_TIMER,
    TIM_MODE_COUNTER = DEV_TIMER_CTL_MODE_COUNTER,
    TIM_MODE_CAPTURE = DEV_TIMER_CTL_MODE_CAPTURE
} tim_mode_t;

typedef enum
{
    TIM_DEBOUNCE_0_CYCLE = DEV_TIMER_CTL_DEBOUNCE_0US,
    TIM_DEBOUNCE_24_CYCLE = DEV_TIMER_CTL_DEBOUNCE_1US,
    TIM_DEBOUNCE_48_CYCLE = DEV_TIMER_CTL_DEBOUNCE_2US,
    TIM_DEBOUNCE_96_CYCLE = DEV_TIMER_CTL_DEBOUNCE_4US,
    TIM_DEBOUNCE_192_CYCLE = DEV_TIMER_CTL_DEBOUNCE_8US,
    TIM_DEBOUNCE_384_CYCLE = DEV_TIMER_CTL_DEBOUNCE_16US,
    TIM_DEBOUNCE_768_CYCLE = DEV_TIMER_CTL_DEBOUNCE_32US,
    TIM_DEBOUNCE_1536_CYCLE = DEV_TIMER_CTL_DEBOUNCE_64US
} tim_debounce_t;

typedef enum
{
    TIM_GPIO_SRC_GPIO0 = (0u << 8),
    TIM_GPIO_SRC_GPIO1 = (1u << 8),
    TIM_GPIO_SRC_GPIO2 = (2u << 8),
    TIM_GPIO_SRC_GPIO3 = (3u << 8),
    TIM_GPIO_SRC_GPIO4 = (4u << 8),
    TIM_GPIO_SRC_GPIO5 = (5u << 8),
    TIM_GPIO_SRC_GPIO6 = (6u << 8),
    TIM_GPIO_SRC_GPIO7 = (7u << 8),
    TIM_GPIO_SRC_GPIO8 = (8u << 8),
    TIM_GPIO_SRC_GPIO9 = (9u << 8),
    TIM_GPIO_SRC_GPIO10 = (10u << 8),
    TIM_GPIO_SRC_GPIO11 = (11u << 8),
    TIM_GPIO_SRC_GPIO12 = (12u << 8),
    TIM_GPIO_SRC_GPIO13 = (13u << 8),
    TIM_GPIO_SRC_GPIO14 = (14u << 8),
    TIM_GPIO_SRC_GPIO15 = (15u << 8),
    TIM_GPIO_SRC_GPIO16 = (16u << 8),
    TIM_GPIO_SRC_GPIO17 = (17u << 8),
    TIM_GPIO_SRC_GPIO18 = (18u << 8),
    TIM_GPIO_SRC_GPIO19 = (19u << 8),
    TIM_GPIO_SRC_GPIO20 = (20u << 8),
    TIM_GPIO_SRC_GPIO21 = (21u << 8),
    TIM_GPIO_SRC_GPIO22 = (22u << 8),
    TIM_GPIO_SRC_GPIO23 = (23u << 8),
    TIM_GPIO_SRC_GPIO24 = (24u << 8),
    TIM_GPIO_SRC_GPIO25 = (25u << 8),
    TIM_GPIO_SRC_GPIO26 = (26u << 8),
    TIM_GPIO_SRC_GPIO27 = (27u << 8),
    TIM_GPIO_SRC_GPIO28 = (28u << 8),
    TIM_GPIO_SRC_GPIO29 = (29u << 8),
    TIM_GPIO_SRC_GPIO30 = (30u << 8),
    TIM_GPIO_SRC_GPIO31 = (31u << 8)
} tim_gpio_src_t;
#define TIM_GPIO_SRC_GPIO(n)    ((n) << 8)

typedef enum
{
    /*timer mode edge config*/
    TIM_EDGE_TIMER_FREE_RUN = DEV_TIMER_CTL_EDGE_FREERUN,
    TIM_EDGE_TIMER_HIGH_LEVEL = DEV_TIMER_CTL_EDGE_HIGHLEVEL,
    TIM_EDGE_TIMER_LOW_LEVEL = DEV_TIMER_CTL_EDGE_LOWLEVEL,

    /*tcounter mode edde config*/
    TIM_EDGE_COUNTER_RISE = DEV_TIMER_CTL_EDGE_FREERUN,
    TIM_EDGE_COUNTER_FALL = DEV_TIMER_CTL_EDGE_HIGHLEVEL,
    TIM_EDGE_COUNTER_BOTH = DEV_TIMER_CTL_EDGE_LOWLEVEL,

    /*capture mode edge config*/
    TIM_EDGE_CAPTURE_RISE = DEV_TIMER_CTL_EDGE_FREERUN,
    TIM_EDGE_CAPTURE_FALL = DEV_TIMER_CTL_EDGE_HIGHLEVEL,
    TIM_EDGE_CAPTURE_BOTH = DEV_TIMER_CTL_EDGE_LOWLEVEL,
    TIM_EDGE_CAPTURE_RISE_FALL = DEV_TIMER_CTL_EDGE_MASK | DEV_TIMER_CTL_CAP_POL_RISE_FALL,
    TIM_EDGE_CAPTURE_FALL_RISE = DEV_TIMER_CTL_EDGE_MASK | DEV_TIMER_CTL_CAP_POL_FALL_RISE
} tim_edge_t;

typedef enum
{
    TIM_DIRECTION_INCREASE = DEV_TIMER_CTL_DIRECTION_INCREASE,
    TIM_DIRECTION_DECREASE = DEV_TIMER_CTL_DIRECTION_DECREASE
} tim_counter_dire_t;

typedef enum
{
    TIM_RELOAD_DISABLE = DEV_TIMER_CTL_RELOAD_EN_SINGLEMODE,
    TIM_RELOAD_ENABLE = DEV_TIMER_CTL_RELOAD_EN_RELOADMODE
} tim_reload_t;

typedef enum
{
    TIM_CAPTURE_DMA_0 = DEV_TIMER_IE_DMA_EN0_MASK,
    TIM_CAPTURE_DMA_1 = DEV_TIMER_IE_DMA_EN1_MASK,
    TIM_CAPTURE_DMA_2 = DEV_TIMER_IE_DMA_EN2_MASK,
    TIM_CAPTURE_DMA_3 = DEV_TIMER_IE_DMA_EN3_MASK
} tim_capture_dma_en_t;
#define TIM_CAPTURE_DMA(n)  (1u << ((n) + 16))

typedef enum
{
    TIM_IT_CAPTURE0 = DEV_TIMER_IE_CAPTURE0_MASK,
    TIM_IT_CAPTURE1 = DEV_TIMER_IE_CAPTURE1_MASK,
    TIM_IT_CAPTURE2 = DEV_TIMER_IE_CAPTURE2_MASK,
    TIM_IT_CAPTURE3 = DEV_TIMER_IE_CAPTURE3_MASK
} tim_capture_int_en_t;
#define TIM_IT_CAPTURE(n)   (1u << ((n) + 8))


typedef enum
{
    TIM_IT_TIMER0 = DEV_TIMER_IE_TIMER0_MASK,
    TIM_IT_TIMER1 = DEV_TIMER_IE_TIMER1_MASK,
    TIM_IT_TIMER2 = DEV_TIMER_IE_TIMER2_MASK,
    TIM_IT_TIMER3 = DEV_TIMER_IE_TIMER3_MASK,
} tim_counter_int_en_t;
#define TIM_IT_TIMER(n)     (1u << (n))


void hal_tim_init(void);

void hal_tim_deinit(void);

void hal_tim_mode_config(tim_base_t tim_n, tim_mode_t mode);

void hal_tim_prediv_config(tim_base_t tim_n, tim_clock_prescale_t div);

void hal_tim_gpio_src_config(tim_base_t tim_n, tim_gpio_src_t gpio);

void hal_tim_gpio_debounce_config(tim_base_t tim_n, tim_debounce_t deb_time);

void hal_tim_reload_config(tim_base_t tim_n, tim_reload_t reload);

void hal_tim_edge_config(tim_base_t tim_n, tim_edge_t edge);

void hal_tim_counter_dire_config(tim_base_t tim_n, tim_counter_dire_t direction);

void hal_tim_run_cmd(tim_base_t tim_n, uint32_t en);

void hal_tim_restart(tim_base_t tim_n);

void hal_tim_set_reload_value(tim_base_t tim_n, uint32_t value);

uint32_t hal_tim_get_counter_value(tim_base_t tim_n);

uint32_t hal_tim_get_capture_value(tim_base_t tim_n);

void hal_tim_capture_dma_enable(tim_base_t tim_n);

void hal_tim_capture_dma_disable(tim_base_t tim_n);

void hal_tim_capture_interrupt_enable(tim_base_t tim_n);

void hal_tim_capture_interrupt_disable(tim_base_t tim_n);

void hal_tim_timer_interrupt_enable(tim_base_t tim_n);

void hal_tim_timer_interrupt_disable(tim_base_t tim_n);

uint32_t hal_tim_get_interrupt_pending(void);

void hal_tim_clear_interrupt_pending(uint32_t tim_it_s);

#endif /* _HAL_TIMER_H_ */
