#ifndef __WEIGHT_READ_H

#define __WEIGHT_READ_H

#include "gpio.h"
#include "tim.h"
#include "stdbool.h"
#include "stdlib.h"

#define ROUND_OFF 0.5f
#define ALLOW_VALUE 15.0f
#define VALUE_MID 2
#define N 9

#define MAX_ZERO 10.0f
#define MIN_ZERO -5.0f

#define SENSOR_NUM 3
#define SAMPLE_NUM 5

#define HALF_HOUR 1800000
#define CREEP_VALUE 1.2f

#define BASE_VALUE (uint32_t)0x800000
#define OFF_VALUE (uint32_t)0x3000
typedef union
{
    float f;
    uint8_t i[4];
} F32;

typedef enum
{
    higher = 0,
    equal = 1,
    lower = 2,
} WARN_INIT;

struct SENSOR
{
    GPIO_TypeDef *SCK_GPIO_Port;
    GPIO_TypeDef *DOUT_GPIO_Port;
    uint16_t SCK_Pin;
    uint16_t DOUT_Pin;
    uint32_t GrossWeight;
    uint32_t Raw_Value;
    float Real_Variation;
    float Real_Weight;
    F32 K;
    float base_k;
    float Scale;
    uint32_t raw_init_value;
    WARN_INIT init_flag;
    bool licence_flag;
    bool err_flag;
    uint8_t Num;
};

// typedef struct __WEIGHING_DEVICE WEIGHING_DEVICE;

typedef struct
{
    float (*get_weight)(void);
    void (*get_allgrossweight)(void);
    void (*processing_data)(void);
    void (*filter_init)(void);
} WEIGHING_OPS;

typedef struct
{
    struct SENSOR *sensor[SENSOR_NUM];
    // uint32_t creep_time;
    // float creep_snap;
    float Weight_last;
    float Weight_current;
    uint16_t rate;
    // uint8_t creep_count;
    bool check_self_flag;
    uint8_t sensor_num_mask;
    float correct_k;
    WEIGHING_OPS *_ops;
} WEIGHING_DEVICE;

WEIGHING_DEVICE *Get_Device_Handle(void);
void Filter_Value(uint32_t* data);
void Convert_Into_Weight(void);
uint32_t Read_Value(struct SENSOR *sensor);

static inline float constrain_float(float x, float low, float high)
{
    if (x < low)
        return low;
    else if (x > high)
        return high;
    else
        return x;
}

#define Min(a, b)                      \
    ({                                 \
        typeof(a) _min1 = a;           \
        typeof(b) _min2 = b;           \
        (void)(&_min1 == &_min2);      \
        _min1 < _min2 ? _min1 : _min2; \
    })

#define Max(a, b)                      \
    ({                                 \
        typeof(a) _max1 = a;           \
        typeof(b) _max2 = b;           \
        (void)(&_max1 == &_max2);      \
        _max1 > _max2 ? _max1 : _max2; \
    })

#endif
