#ifndef AD_INVERTER_H
#define AD_INVERTER_H

#include <stdint.h>

#include "ad_project_config.h"

#ifndef AD_INVERTER_ENABLE_OUTPUTS
#define AD_INVERTER_ENABLE_OUTPUTS 0
#endif

#define AD_INVERTER_PWM_POLARITY_MAIN_INVERTED  (1U << 0)
#define AD_INVERTER_PWM_POLARITY_COMP_INVERTED  (1U << 1)
#define AD_INVERTER_PWM_POLARITY_MASK           (AD_INVERTER_PWM_POLARITY_MAIN_INVERTED | \
                                                 AD_INVERTER_PWM_POLARITY_COMP_INVERTED)

#ifndef AD_INVERTER_DEFAULT_PWM_POLARITY_FLAGS
#define AD_INVERTER_DEFAULT_PWM_POLARITY_FLAGS  AD_INVERTER_PWM_POLARITY_MAIN_INVERTED
#endif

typedef enum
{
    AD_INVERTER_PWM_TIMING_UP = 0,
    AD_INVERTER_PWM_TIMING_CENTER = 1
} AD_InverterPwmTimingMode_t;

typedef struct
{
    uint8_t enable;
    float duty_a;
    float duty_b;
    float duty_c;
} AD_InverterCommand_t;

typedef struct
{
    uint8_t initialized;
    uint8_t pwm_running;
    uint8_t outputs_allowed_by_build;
    float duty_a;
    float duty_b;
    float duty_c;
    float electrical_frequency_Hz;
    float electrical_angle_rad;
    float requested_test_duty;
    float applied_test_duty;
    uint16_t pwm_polarity_flags;
    uint16_t pwm_timing_mode;
    uint8_t service_output;
    uint8_t service_pwm_running;
    uint8_t id_stage;
} AD_InverterState_t;

typedef enum
{
    AD_INVERTER_PWM_OUTPUT_NONE = 0,
    AD_INVERTER_PWM_OUTPUT_UH = 1,
    AD_INVERTER_PWM_OUTPUT_UL = 2,
    AD_INVERTER_PWM_OUTPUT_VH = 3,
    AD_INVERTER_PWM_OUTPUT_VL = 4,
    AD_INVERTER_PWM_OUTPUT_WH = 5,
    AD_INVERTER_PWM_OUTPUT_WL = 6,
    AD_INVERTER_PWM_OUTPUT_ALL = 7
} AD_InverterPwmOutput_t;

void AD_Inverter_Init(void);
void AD_Inverter_Disable(void);
uint8_t AD_Inverter_Enable(void);
uint8_t AD_Inverter_ApplyCommand(const AD_InverterCommand_t *command);
uint8_t AD_Inverter_StartPwmOutput(uint8_t output, float duty);
void AD_Inverter_SetDuty(float duty_a, float duty_b, float duty_c);
void AD_Inverter_SetPwmPolarityFlags(uint16_t flags);
uint16_t AD_Inverter_GetPwmPolarityFlags(void);
void AD_Inverter_SetPwmTimingMode(uint16_t mode);
uint16_t AD_Inverter_GetPwmTimingMode(void);
const AD_InverterState_t* AD_Inverter_GetState(void);

#endif
