#ifndef __DEVICE_H__
#define __DEVICE_H__

#ifdef __cplusplus
 extern "C" {
#endif

#include "stm32f4xx.h"

/******************* device info *******************/
struct bitmap_main_s {
    uint8_t bitmap_version[4];
    uint32_t sensor_type_id;
    uint8_t sn[16];
    uint8_t produce_date[8];
    uint8_t expire_date[8];
    uint8_t manu_cali_date[8];
    uint8_t user_cali_date[8];
    uint32_t ir_source_freq;

    uint8_t gas1_bitmap_name[28];
    uint32_t gas1_sub_id;
    uint8_t gas1_gas_name[12];
    uint32_t gas1_unit_code;
    uint8_t gas1_unit_name[8];
    uint8_t gas2_bitmap_name[28];
    uint32_t gas2_sub_id;
    uint8_t gas2_gas_name[12];
    uint32_t gas2_unit_code;
    uint8_t gas2_unit_name[8];
    uint8_t gas3_bitmap_name[28];
    uint32_t gas3_sub_id;
    uint8_t gas3_gas_name[12];
    uint32_t gas3_unit_code;
    uint8_t gas3_unit_name[8];
    uint8_t gas4_bitmap_name[28];
    uint32_t gas4_sub_id;
    uint8_t gas4_gas_name[12];
    uint32_t gas4_unit_code;
    uint8_t gas4_unit_name[8];

    uint32_t filter_median[4];
    uint32_t filter_window[4];

    uint8_t res[188];
    uint32_t checksum;
    uint32_t gasn_avail_bitmap;
};

struct bitmap_gas_head_s {
    uint8_t bitmap_version[4];
    uint32_t sensor_type_id;
    uint8_t sn[16];
    uint32_t gas_number;
    uint32_t gas_sub_id;
    uint8_t gas_name[12];
    uint32_t range1;
    uint32_t range2;
    uint32_t alarm_limit1;
    uint32_t alarm_limit2;
    uint32_t stel_limit;
    uint32_t twa_limit;
    uint32_t signal_polarity;
    uint32_t drift_limit;
    uint32_t reading_divide_factor;
    uint32_t display_resolution;
    uint32_t decimal_point;
    uint32_t cali_type;
    uint32_t min_cali_value;
    uint32_t warmup_time;
    uint32_t zero_comp_type;
    float zero_comp_coef[5];
    uint32_t sensi_comp_type;
    float sensi_comp_coef[5];
    uint32_t humidity_comp_type;
    float humidity_comp_coef[5];
    uint32_t channel_number_of_1st_measured_gas;
    uint32_t channel_number_of_2st_measured_gas;
    uint32_t channel_number_of_3st_measured_gas;
    uint32_t channel_number_of_4st_measured_gas;
    uint8_t res[320];
    uint32_t checksum;
};

#define LOOKUP_TABLE_CONCENTRATION_POINTS_MAX (20)
#define LOOKUP_TABLE_TEMPERATURE_POINTS_MAX   (8)

struct lookup_table_s {
    uint32_t encryption_flag;
    uint8_t encryption_key[32];
    uint32_t concentration_points;
    uint32_t temperature_points;
    uint32_t chamber_temperature[LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint32_t detector_temperature[LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint32_t lamp_temperature[LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint32_t gas_concentration[LOOKUP_TABLE_CONCENTRATION_POINTS_MAX];
    uint32_t sig[LOOKUP_TABLE_CONCENTRATION_POINTS_MAX][LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint32_t ref[LOOKUP_TABLE_CONCENTRATION_POINTS_MAX][LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint32_t b0_value[LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint32_t delta_b_value[LOOKUP_TABLE_CONCENTRATION_POINTS_MAX][LOOKUP_TABLE_TEMPERATURE_POINTS_MAX];
    uint8_t res[384];
    uint32_t checksum;
};

struct bitmap_calib_s {
    uint32_t avail_bitmap;
    uint32_t zero_data[6];
    uint32_t span_data[5][7];
    uint8_t res[340];
    uint32_t checksum;
};

struct cross_comp_s {
    uint32_t avail_bit;
    uint32_t sub_id;
    uint8_t gas_name[12];
    uint32_t unit_code;
    uint8_t unit_name[8];
    uint32_t concentration_points;
    uint32_t temperature_points;
    uint32_t detector_temperature[2];
    uint32_t gas_concentration[20];
    uint32_t det[20][20];
    uint32_t ref[20][20];
    uint8_t res[764];
    uint32_t checksum;
};

struct bitmap_gas_s {
    struct bitmap_gas_head_s head;
    struct lookup_table_s lookup_table;
    struct bitmap_calib_s user_cali;
    struct bitmap_calib_s manuf_cali;
    struct cross_comp_s cross[4];
};

/******************* device data *******************/
struct device_data_s {
    /*** raw data of device ***/
    uint32_t detector_temperature_raw;
    uint32_t lamp_temperature_raw;
    uint32_t air_pressure_raw;
    uint32_t gas_pressure_raw;
    uint32_t gas_temperature_raw;
    uint32_t gas_humidity_raw;
    uint32_t lamp_voltage_raw;
    uint32_t lamp_current_raw;
    uint32_t gas_sig_raw[4];

    /*** processed data of device ***/
    uint32_t detector_temperature;
    uint32_t lamp_temperature;
    uint32_t air_pressure;
    uint32_t gas_pressure;
    uint32_t gas_temperature;
    uint32_t gas_humidity;
    uint32_t lamp_voltage;
    uint32_t lamp_current;
    uint32_t gas_sig[4];
    // uint32_t gas_sig_fliter[4];
    int32_t  gas_concentration[4];
    int32_t  gas_neg_concentration[4];
};

struct device_status_s {
    /*** status data of device ***/
    uint16_t cali_zero_record_status[4];
    uint16_t cali_span_record_status[4];
    uint16_t cali_activate_status;
    uint16_t cali_restore_status;
    uint16_t heat_on_off_status;
};

struct flag_s {
    uint32_t filter;
    uint32_t concentration;
    uint32_t filter_climb;
    uint32_t gas_fault;
};

extern const uint8_t * const modbus_map_ro[];
extern const struct bitmap_main_s * const bitmap_main;
extern const struct bitmap_gas_s (* const bitmap_gas)[4];
extern struct device_data_s device_data;
extern struct device_status_s device_status;
extern struct flag_s flag;

#ifdef __cplusplus
}
#endif

#endif /* __DEVICE_H__ */
