#ifndef AD_PARAMETER_IDENTIFICATION_H
#define AD_PARAMETER_IDENTIFICATION_H

#include <stdint.h>

#include "ad_project_config.h"

#ifndef AD_PARAM_ID_ENABLE_POWER_TESTS
#define AD_PARAM_ID_ENABLE_POWER_TESTS 0
#endif

#ifndef AD_PARAM_ID_DEFAULT_PWM_DUTY_LIMIT
#define AD_PARAM_ID_DEFAULT_PWM_DUTY_LIMIT (0.08f)
#endif

#ifndef AD_PARAM_ID_DEFAULT_ROTATION_FREQUENCY_HZ
#define AD_PARAM_ID_DEFAULT_ROTATION_FREQUENCY_HZ (3.0f)
#endif

#ifndef AD_PARAM_ID_MAX_ROTATION_FREQUENCY_HZ
#define AD_PARAM_ID_MAX_ROTATION_FREQUENCY_HZ (200.0f)
#endif

#ifndef AD_PARAM_ID_DEFAULT_ROTATION_MODULATION
#define AD_PARAM_ID_DEFAULT_ROTATION_MODULATION (0.35f)
#endif

#ifndef AD_PARAM_ID_DEFAULT_ROTATION_RAMP_TIME_MS
#define AD_PARAM_ID_DEFAULT_ROTATION_RAMP_TIME_MS (3000U)
#endif

#ifndef AD_PARAM_ID_MIN_ROTATION_RAMP_TIME_MS
#define AD_PARAM_ID_MIN_ROTATION_RAMP_TIME_MS (100U)
#endif

#ifndef AD_PARAM_ID_MAX_ROTATION_RAMP_TIME_MS
#define AD_PARAM_ID_MAX_ROTATION_RAMP_TIME_MS (60000U)
#endif

#ifndef AD_PARAM_ID_DEFAULT_POLE_PAIRS
#define AD_PARAM_ID_DEFAULT_POLE_PAIRS (1U)
#endif

#ifndef AD_PARAM_ID_MAX_POLE_PAIRS
#define AD_PARAM_ID_MAX_POLE_PAIRS (64U)
#endif

#define AD_PARAM_ID_TIMEOUT_US_DEFAULT (20000000UL)

typedef enum
{
    AD_PARAM_ID_MOTOR_CONTROL_AD = 0,
    AD_PARAM_ID_MOTOR_CONTROL_BLDC = 1
} AD_ParamID_MotorControl_t;

typedef enum
{
    AD_MOTOR_PARAM_VALID_RS = (1UL << 0),
    AD_MOTOR_PARAM_VALID_RR = (1UL << 1),
    AD_MOTOR_PARAM_VALID_LS = (1UL << 2),
    AD_MOTOR_PARAM_VALID_LR = (1UL << 3),
    AD_MOTOR_PARAM_VALID_LM = (1UL << 4),
    AD_MOTOR_PARAM_VALID_LL = (1UL << 5),
    AD_MOTOR_PARAM_VALID_J = (1UL << 6),
    AD_MOTOR_PARAM_VALID_B = (1UL << 7),
    AD_MOTOR_PARAM_VALID_NOMINALS = (1UL << 8),
    AD_MOTOR_PARAM_VALID_POLE_PAIRS = (1UL << 9)
} AD_MotorParamValidFlag_t;

typedef enum
{
    AD_MEAS_STATUS_OVERCURRENT = (1UL << 0),
    AD_MEAS_STATUS_OVERVOLTAGE = (1UL << 1),
    AD_MEAS_STATUS_UNDERVOLTAGE = (1UL << 2),
    AD_MEAS_STATUS_OVERTEMPERATURE = (1UL << 3),
    AD_MEAS_STATUS_DRIVER_FAULT = (1UL << 4),
    AD_MEAS_STATUS_EMERGENCY_STOP = (1UL << 5)
} AD_MeasurementStatusFlag_t;

typedef enum
{
    AD_PARAM_ID_STATUS_ACTIVE = (1UL << 0),
    AD_PARAM_ID_STATUS_POWER_TEST_BLOCKED = (1UL << 1),
    AD_PARAM_ID_STATUS_POWER_STAGE_ARMED = (1UL << 2),
    AD_PARAM_ID_STATUS_FAULT_LATCHED = (1UL << 3),
    AD_PARAM_ID_STATUS_TIMEOUT = (1UL << 4),
    AD_PARAM_ID_STATUS_LOCKED_ROTOR_BLOCKED = (1UL << 5),
    AD_PARAM_ID_STATUS_SAFETY_LIMITS_UNKNOWN = (1UL << 6),
    AD_PARAM_ID_STATUS_DATA_VALID = (1UL << 7),
    AD_PARAM_ID_STATUS_COMPLETE = (1UL << 8),
    AD_PARAM_ID_STATUS_PARTIAL_COMPLETE = (1UL << 9),
    AD_PARAM_ID_STATUS_STEP_FAILED = (1UL << 10),
    AD_PARAM_ID_STATUS_LOCKED_ROTOR_SKIPPED = (1UL << 11)
} AD_ParamID_StatusFlag_t;

typedef enum
{
    AD_PARAM_ID_FAULT_OVERCURRENT = (1UL << 0),
    AD_PARAM_ID_FAULT_OVERVOLTAGE = (1UL << 1),
    AD_PARAM_ID_FAULT_UNDERVOLTAGE = (1UL << 2),
    AD_PARAM_ID_FAULT_OVERTEMPERATURE = (1UL << 3),
    AD_PARAM_ID_FAULT_DRIVER = (1UL << 4),
    AD_PARAM_ID_FAULT_EMERGENCY_STOP = (1UL << 5),
    AD_PARAM_ID_FAULT_TIMEOUT = (1UL << 6),
    AD_PARAM_ID_FAULT_NULL_INPUT = (1UL << 7)
} AD_ParamID_FaultFlag_t;

typedef enum
{
    AD_PARAM_ID_MODE_IDLE = 0,
    AD_PARAM_ID_MODE_STATOR_RESISTANCE = 1,
    AD_PARAM_ID_MODE_NO_LOAD_MAGNETIZING = 2,
    AD_PARAM_ID_MODE_LOCKED_ROTOR_LEAKAGE = 3,
    AD_PARAM_ID_MODE_INERTIA_FRICTION = 4,
    AD_PARAM_ID_MODE_DATA_LOGGING = 5,
    AD_PARAM_ID_MODE_PWM_TEST_UH = 6,
    AD_PARAM_ID_MODE_PWM_TEST_UL = 7,
    AD_PARAM_ID_MODE_PWM_TEST_VH = 8,
    AD_PARAM_ID_MODE_PWM_TEST_VL = 9,
    AD_PARAM_ID_MODE_PWM_TEST_WH = 10,
    AD_PARAM_ID_MODE_PWM_TEST_WL = 11,
    AD_PARAM_ID_MODE_PWM_TEST_ALL = 12,
    AD_PARAM_ID_MODE_AUTO_IDENTIFICATION = 13,
    AD_PARAM_ID_MODE_ROTATION_3HZ = 14
} AD_ParamID_Mode_t;

typedef struct
{
    float Rs_ohm;
    float Rr_ohm;
    float Ls_H;
    float Lr_H;
    float Lm_H;
    float Ll_H;
    float J_kg_m2;
    float B_Nm_s;
    float pole_pairs;
    float nominal_voltage_V;
    float nominal_current_A;
    float nominal_frequency_Hz;
    float nominal_power_W;
    float nominal_speed_rpm;
    uint32_t valid_mask;
} AD_MotorParameters_t;

typedef struct
{
    float ia_A;
    float ib_A;
    float ic_A;
    float ia_rms_A;
    float ib_rms_A;
    float ic_rms_A;
    float vdc_V;
    float va_V;
    float vb_V;
    float vc_V;
    float speed_rpm;
    float torque_Nm;
    float temperature_C;
    uint32_t timestamp_us;
    uint32_t status_flags;
    float slip_percent;
} AD_Measurements_t;

typedef struct
{
    float ia_peak_A;
    float ib_peak_A;
    float ic_peak_A;
} AD_PhaseCurrentPeaks_t;

typedef struct
{
    uint8_t enable;
    uint8_t test_mode;
    uint8_t reset_faults;
    uint16_t pwm_polarity_flags;
    uint16_t pwm_timing_mode;
    uint16_t motor_control_type;
    uint16_t rotation_ramp_time_ms;
    float pwm_duty_limit;
    float rotation_frequency_Hz;
    float rotation_modulation;
    float current_limit_A;
    float voltage_limit_V;
    float undervoltage_limit_V;
    float speed_limit_rpm;
    float temperature_limit_C;
} AD_Command_t;

typedef struct
{
    float overcurrent_A;
    float overvoltage_V;
    float undervoltage_V;
    float overtemperature_C;
    float speed_limit_rpm;
    uint32_t timeout_us;
} AD_ParamID_SafetyLimits_t;

void AD_ParamID_Init(void);
void AD_ParamID_Reset(void);
void AD_ParamID_Start(uint8_t mode);
void AD_ParamID_Stop(void);
void AD_ParamID_StepFast(const AD_Measurements_t *meas);
void AD_ParamID_StepSlow(void);
const AD_MotorParameters_t* AD_ParamID_GetParameters(void);
const AD_Measurements_t* AD_ParamID_GetLastMeasurements(void);
const AD_PhaseCurrentPeaks_t* AD_ParamID_GetPhaseCurrentPeaks(void);
void AD_ParamID_ResetPhaseCurrentPeaks(void);
uint32_t AD_ParamID_GetStatus(void);

uint8_t AD_ParamID_GetMode(void);
uint32_t AD_ParamID_GetFaults(void);
void AD_ParamID_SetParameters(const AD_MotorParameters_t *params);
void AD_ParamID_SetSafetyLimits(const AD_ParamID_SafetyLimits_t *limits);
void AD_ParamID_SetSoftwareEnable(uint8_t enable);
void AD_ParamID_SetLockedRotorAllowed(uint8_t enable);
uint8_t AD_ParamID_IsLockedRotorAllowed(void);
void AD_ParamID_SetPwmDutyLimit(float duty_limit);
float AD_ParamID_GetPwmDutyLimit(void);
void AD_ParamID_SetRotationFrequencyHz(float frequency_hz);
float AD_ParamID_GetRotationFrequencyHz(void);
void AD_ParamID_SetRotationModulation(float modulation);
float AD_ParamID_GetRotationModulation(void);
void AD_ParamID_SetRotationRampTimeMs(uint16_t ramp_time_ms);
uint16_t AD_ParamID_GetRotationRampTimeMs(void);
void AD_ParamID_SetMotorControlType(uint16_t motor_control_type);
uint16_t AD_ParamID_GetMotorControlType(void);
void AD_ParamID_SetPolePairs(uint16_t pole_pairs);
uint16_t AD_ParamID_GetPolePairs(void);
uint8_t AD_ParamID_IsPowerStageAllowed(void);
void AD_ParamID_EmergencyStop(uint32_t fault_flags);
void AD_ParamID_MarkComplete(void);
void AD_ParamID_MarkPartialComplete(void);
void AD_ParamID_MarkStepFailed(void);
void AD_ParamID_MarkLockedRotorSkipped(void);
uint8_t AD_ParamID_HardwareStep(uint8_t mode, const AD_Measurements_t *meas);
void AD_ParamID_HardwareDisable(void);

#endif
