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


#ifndef SPV_HAL_PWM_H
#define SPV_HAL_PWM_H

#ifdef __cplusplus
extern "C"
{
#endif


#include "platform.h"


//#define DBG_HAL_PWM

#if defined(DBG_HAL_PWM)
#define HAL_PWM_LOG(fmt, ...)      rt_kprintf(fmt, ##__VA_ARGS__)
#else
#define HAL_PWM_LOG(fmt, ...)
#endif


typedef enum
{
    PWM0 = 0,
    PWM1 = 1,
    PWM2 = 2,
    PWM3 = 3,
    PWM4 = 4,
    PWM5 = 5,
    PWM6 = 6,
    PWM7 = 7,
    PWM_NUM,
} pwm_port_t;

#define HAL_PWM_EOK                          0               /**< There is no error */
#define HAL_PWM_ERROR                        1               /**< A generic error happens */

#define PWM_ENABLE                          (0x1UL<<0)
#define PWM_CLK_OUT                         (0x1UL<<25)

/*
 * pwm mode
 * All pwm channels have the duty and breath mode, and only pwm0 and pwm2 additionally have the soft mode and the pdm mode
 */
typedef enum
{
    PWM_DUTY_MODE       = DEV_PWM_CTL_PDMMode_MODE_NORMALMODE, //duty mode
    PWM_BREATH_MODE = DEV_PWM_CTL_PDMMode_MODE_BREATHMODE, //breath mode
    PWM_SOFT_MODE       = DEV_PWM_CTL_PDMMode_MODE_SOFTMODE,      //soft mode
    PWM_PDM_MODE        = DEV_PWM_CTL_PDMMode_MODE_PDMMODE        //pdm mode
} pwm_mode_t;

/*
 * duty mode config struct
 */
typedef struct
{
    uint32_t mode;                  /* mode selection:The parameter is specified in pwm_mode_t */
    uint32_t period_cycles;         /* PWM Length(set=Total Cycle-1)
                                       scope: 0~255*/
    uint32_t duty_cycles;           /* PWM Duty, High level cycle
                                       scope: 0~255*/
    uint32_t pending_number;        /* after pending_number pwms,generate BTH_PD pending
                                       scope: 0~63*/
} pwm_dutymode_init_t;

/*
 * breath mode config struct
 */
typedef struct
{
    uint8_t mode;                   /* mode selection:The parameter is specified in pwm_mode_t */
    uint32_t high_cycles;           /* High Number(Real Number is (set+1))
                                       scope: 0~255*/
    uint32_t low_cycles;            /* Low Number(Real Number is (set+1))
                                       scope: 0~255*/
    uint8_t rise_fall_cycles;       /* The number cycles from 0 to 100% and from 100% to 0(Real Number is 32 * (set+1))
                                       scope: 0~15*/
} pwm_breathmode_init_t;

/*
 * soft mode config struct
 */
typedef struct
{
    uint32_t mode;                  /* mode selection:The parameter is specified in pwm_mode_t */
    uint32_t idle_out_enable;       /* set whether output value when pwm idle
                                       scope: [0: disable],[1:enable]*/
    uint32_t idle_out_value;        /* the output value when pwm idle
                                       scope: 0~3*/
    uint32_t modulate_enable;       /* the modulation clock selection of pwm output
                                       scope: [Carrier Signal is PWM_CLK],[Modulation Signal is PWM_OUT]*/
    uint32_t clk_out_enable;        /* The pwm output as a clock output selection
                                       scope: [0: disable],[1:enable]*/
    uint32_t signed_format;         /* Symbolbit representation of the data
                                       scope: [0: Signed Magnitude],[1: Signed Complement]*/
    uint32_t out_format;            /* The output mode of the data
                                       scope: [0: Single End],[1:Over Turn],[2: Difference],[3: Class-D]*/
    uint32_t data_len_format;       /* Total cycle form of each pwm of the output
                                       scope: [0: 256/512/1024â€¦65536],[1: 250/500/1000~64000]*/
    uint32_t fifo_empty_active;     /* Stop sending or continue sending when there is no data in fifo, if continue sending, will continue sending the last number in fifo
                                       scope: [0: Stop When FIFO Empty],[1: Continue When FIFO Empty.Output Last PWM_TX_DAT]*/
    uint32_t data_place_format;     /* The number of data stored in each fifo
                                       scope: [0: 1 data],[1: 2 data],[2:3 data],[3:4 Data]*/
    uint32_t data_repeat;           /* Number of duplicate output times for each data
                                       scope: 0~15*/
    uint32_t data_width_format;     /* Actual effective bits of each FIFO data(Real PWM Data Width is (set+8))
                                       scope: 0~8*/
} pwm_softmode_init_t;

/*
 * pdm mode config struct
 */
typedef struct
{
    uint8_t mode;                    /* mode selection:The parameter is specified in pwm_mode_t */
    uint16_t fifo_empty_active;      /* Stop sending or continue sending when there is no data in fifo
                                       scope: [0: Stop When FIFO Empty],[1: Continue When FIFO Empty.Output Last PWM_TX_DAT]*/
} pwm_pdmmode_init_t;


void hal_pwm_dutymode_config(pwm_port_t pwm_port, pwm_dutymode_init_t *pwm_dutymode_init);
void hal_pwm_set_periodcycles(pwm_port_t pwmX, uint32_t period_cycles);
uint32_t hal_pwm_get_periodcycles(pwm_port_t pwm_port);
void hal_pwm_set_dutycycles(pwm_port_t pwmX, uint32_t duty_cycles);
uint32_t hal_pwm_get_dutycycles(pwm_port_t pwm_port);

void hal_pwm_set_pendingnum(pwm_port_t pwmX, uint32_t pending_num);

void hal_pwm_breathmode_config(pwm_port_t pwm_port, pwm_breathmode_init_t *pwm_breathmode_init);
void hal_pwm_set_highcycles(pwm_port_t pwm_port, uint16_t high_cycles);
void hal_pwm_set_lowcycles(pwm_port_t pwm_port, uint16_t low_cycles);
void hal_pwm_set_risefallcycles(pwm_port_t pwm_port, uint8_t rise_fall_cycles);

void hal_pwm_softmode_config(pwm_port_t pwm_port, pwm_softmode_init_t *pwm_softmode_init);

void hal_pwm_pdmmode_config(pwm_port_t pwm_port, pwm_pdmmode_init_t *pwm_pdmmode_init);

void hal_pwm_set_fifo_threshold(pwm_port_t pwm_port, uint8_t Threshold);
void hal_pwm_write_fifo_data(pwm_port_t pwm_port, uint32_t data);
void hal_pwm_set_fifo_reset(pwm_port_t pwm_port);
uint32_t hal_pwm_get_fifo_status(pwm_port_t pwm_port, uint32_t pwm_flag);

void hal_pwm_cmd(pwm_port_t pwm_port, uint32_t state);
void hal_pwm_clockoutput_cmd(pwm_port_t pwm_port, uint32_t state);
void hal_pwm_it_config(uint32_t pwm_ie, uint32_t state);
uint32_t hal_pwm_get_it_status(uint32_t pwm_pd);
void hal_pwm_clear_it_pending_bit(uint32_t pwm_pd);

uint32_t hal_pwm_get_clk(pwm_port_t pwm_port);

int32_t hal_pwm_dutymode_init(pwm_port_t pwm_port);

#ifdef __cplusplus
}
#endif

#endif

