/**
**************************************************************************
* @file   modbus_data.h
* @brief    Заголовочный файл с описанием даты MODBUS.
* @details  Данный файл необходимо подключается в rs_message.h. После rs_message.h
* подключается к основному проекту.
*
* @defgroup MODBUS_DATA
* @ingroup  MODBUS
* @brief    Modbus data description
*
*************************************************************************/




#ifndef _MODBUS_DATA_H_
#define _MODBUS_DATA_H_


// DEFINES FOR INPUT REGISTERS ARRAYS
#define   R_INPUT_ADDR                                       0
#define   R_INPUT_QNT                                        2000

// DEFINES FOR HOLDING REGISTERS ARRAYS
#define   R_HOLDING_ADDR                             0
#define   R_HOLDING_QNT                              2000

// RTC holding registers: write time/date here and set apply=1.
#define   R_HOLDING_RTC_ADDR                         200
#define   R_HOLDING_RTC_HOURS_ADDR                   (R_HOLDING_RTC_ADDR + 0)
#define   R_HOLDING_RTC_MINUTES_ADDR                 (R_HOLDING_RTC_ADDR + 1)
#define   R_HOLDING_RTC_SECONDS_ADDR                 (R_HOLDING_RTC_ADDR + 2)
#define   R_HOLDING_RTC_DATE_ADDR                    (R_HOLDING_RTC_ADDR + 3)
#define   R_HOLDING_RTC_MONTH_ADDR                   (R_HOLDING_RTC_ADDR + 4)
#define   R_HOLDING_RTC_YEAR_ADDR                    (R_HOLDING_RTC_ADDR + 5)
#define   R_HOLDING_RTC_WEEKDAY_ADDR                 (R_HOLDING_RTC_ADDR + 6)
#define   R_HOLDING_RTC_APPLY_ADDR                   (R_HOLDING_RTC_ADDR + 7)
#define   R_HOLDING_RTC_STATUS_ADDR                  (R_HOLDING_RTC_ADDR + 8)

// RTC input registers: current time/date.
#define   R_INPUT_RTC_ADDR                           1201
#define   R_INPUT_RTC_HOURS_ADDR                     (R_INPUT_RTC_ADDR + 0)
#define   R_INPUT_RTC_MINUTES_ADDR                   (R_INPUT_RTC_ADDR + 1)
#define   R_INPUT_RTC_SECONDS_ADDR                   (R_INPUT_RTC_ADDR + 2)
#define   R_INPUT_RTC_DATE_ADDR                      (R_INPUT_RTC_ADDR + 3)
#define   R_INPUT_RTC_MONTH_ADDR                     (R_INPUT_RTC_ADDR + 4)
#define   R_INPUT_RTC_YEAR_ADDR                      (R_INPUT_RTC_ADDR + 5)
#define   R_INPUT_RTC_WEEKDAY_ADDR                   (R_INPUT_RTC_ADDR + 6)
#define   R_INPUT_RTC_APPLY_ADDR                     (R_INPUT_RTC_ADDR + 7)
#define   R_INPUT_RTC_STATUS_ADDR                    (R_INPUT_RTC_ADDR + 8)

#define   MB_RTC_APPLY_SET                           1U
#define   MB_RTC_STATUS_IDLE                         0U
#define   MB_RTC_STATUS_SET_OK                       1U
#define   MB_RTC_STATUS_VALUE_ERROR                  2U
#define   MB_RTC_STATUS_HAL_ERROR                    3U

// DEFINES FOR COIL ARRAYS
#define C_CONTROL_ADDR                                   0
#define C_CONTROL_QNT                                    1000



#include "stdint.h"
#include "ds18b20_driver.h"
#include "PROJ_setup.h"


//--------------DEFINES FOR REGISTERS---------------
// DEFINES FOR ARRAYS
/**
  * @addtogroup MODBUS_DATA_RERISTERS_DEFINES
  * @ingroup    MODBUS_DATA
  * @brief      Defines for registers
  Структура дефайна адресов
  @verbatim
  Для массивов регистров:
    R_<NAME_ARRAY>_ADDR   -  модбас адресс первого регистра в массиве
    R_<NAME_ARRAY>_QNT    -  количество регистров в массиве

  При добавлении новых массивов регистров, необходимо их добавить в функцию MB_DefineRegistersAddress

        if(MB_Check_Address_For_Arr(Addr, Qnt, R_<NEW_ARRAY>_ADDR, R_<NEW_ARRAY>_QNT) == NO_ERRORS)
        {
            *pRegs = MB_Set_Register_Ptr(&<NEW_ARRAY>, Addr);   // начало регистров хранения/входных
        }
  @endverbatim
  * @{
  */


/**
  * @brief Регистры хранения
  */


/**
 * @brief Определить размер структуры в регистрах модбас (16-бит слова)
 */
#define mb_sizeof(_struct_)   (sizeof(_struct_)/sizeof(uint16_t))
/**
 * @brief Определить количество резервных байт для выравнивания
 * @details   Выравнивает так, чтобы количество регистров в  _struct_ и reserved равнялось _align_.
 *
 */
#define mb_fill_rsv(_align_, _struct_)  ((_align_ > mb_sizeof(_struct_)) ? (_align_ - mb_sizeof(_struct_)) : 0)
#define mb_fill_gap(_from_, _to_, _struct_) (((_to_) > ((_from_) + mb_sizeof(_struct_))) ? ((_to_) - (_from_) - mb_sizeof(_struct_)) : 0)

#define R_INPUT_ROOM_ADDR                           400
#define R_INPUT_ID_ADDR                             1000
#define R_INPUT_NUM_TSENS_ADDR                      1200
#define R_HOLDING_HYST_ADDR                         100
#define R_HOLDING_ROOM_ADDR                         300

#define MB_ROOM_TEMP_SCALE                          10U
#define MB_ROOM_VALVE_ANGLE_MAX_DEFAULT             90U
#define ROOM_MODE_AUTO                              0U
#define ROOM_MODE_MANUAL                            1U
#define ROOM_COMMAND_STOP                           0U
#define ROOM_COMMAND_OPEN                           1U
#define ROOM_COMMAND_CLOSE                          2U






typedef __PACKED_STRUCT
{
    uint16_t hours;
    uint16_t minutes;
    uint16_t seconds;
    uint16_t date;
    uint16_t month;
    uint16_t year;
    uint16_t weekday;
    uint16_t apply;
    uint16_t status;
} MB_RtcCalendarRegsTypeDef;

typedef __PACKED_STRUCT
{
    uint16_t channel;
    uint16_t location;
    uint16_t ds18b20_id[4];
    uint16_t temperature_x10;
    uint16_t setpoint_x10;
    uint16_t hysteresis_x10;
    uint16_t valve_position_pct;
    uint16_t valve_angle_deg;
    uint16_t valve_angle_max_deg;
    uint16_t is_connected;
    uint16_t valve_open;
    uint16_t valve_close;
    uint16_t mode;
    uint16_t command_state;
    uint16_t reserved;
} MB_RoomInputRegsTypeDef;


typedef __PACKED_STRUCT
{
    uint16_t setpoint_x10;
    uint16_t hysteresis_x10;
    uint16_t valve_position_pct;
    uint16_t valve_angle_max_deg;
    uint16_t mode;
    uint16_t command;
    uint16_t location;
    uint16_t apply;
} MB_RoomHoldingRegsTypeDef;





typedef     __PACKED_STRUCT//MB_DataInRegsTypeDef
{

    uint16_t sens_Temp[MAX_SENSE];
    uint16_t reserve_to_room[mb_fill_rsv(R_INPUT_ROOM_ADDR, uint16_t[MAX_SENSE])];
    MB_RoomInputRegsTypeDef room[MAX_SENSE];
    uint16_t reserve_to_id[mb_fill_gap(R_INPUT_ROOM_ADDR, R_INPUT_ID_ADDR, MB_RoomInputRegsTypeDef[MAX_SENSE])];
    DS18B20_Drv_t ID;
    uint16_t reserve_to_num_tsens[mb_fill_gap(R_INPUT_ID_ADDR, R_INPUT_NUM_TSENS_ADDR, DS18B20_Drv_t)];
    uint16_t num_Tsens;
    MB_RtcCalendarRegsTypeDef rtc;


} MB_DataInRegsTypeDef;


/**
  * @brief Входные регистры
  */
typedef     __PACKED_STRUCT //MB_DataInRegsTypeDef
{
    uint16_t set_Temp[MAX_SENSE];
    uint16_t reserve_to_hyst[mb_fill_rsv(R_HOLDING_HYST_ADDR, uint16_t[MAX_SENSE])];
    uint16_t set_hyst[MAX_SENSE];
    uint16_t reserve_to_rtc[mb_fill_gap(R_HOLDING_HYST_ADDR, R_HOLDING_RTC_ADDR, uint16_t[MAX_SENSE])];
    MB_RtcCalendarRegsTypeDef rtc;
    uint16_t reserve_to_room_cfg[mb_fill_gap(R_HOLDING_RTC_ADDR, R_HOLDING_ROOM_ADDR, MB_RtcCalendarRegsTypeDef)];
    MB_RoomHoldingRegsTypeDef room_cfg[MAX_SENSE];
} MB_DataHoldRegsTypeDef;





/** MODBUS_DATA_RERISTERS_DEFINES
  * @}
  */

//----------------DEFINES FOR COILS-----------------
/**
  * @addtogroup MODBUS_DATA_COILS_DEFINES
  * @ingroup    MODBUS_DATA
  * @brief      Defines for coils
  @verbatim
  Структура дефайна
  Для массивов коилов:
    C_<NAME_ARRAY>_ADDR   - модбас адресс первого коила в массиве
    C_<NAME_ARRAY>_QNT    - количество коилов в массиве (минимум 16)

  При добавлении новых массивов коилов, необходимо их добавить в функцию MB_DefineCoilsAddress

    if(MB_Check_Address_For_Arr(Addr, Qnt, C_<NEW_ARRAY>_ADDR, C_<NEW_ARRAY>_QNT) == NO_ERRORS)
    {
      *pCoils = MB_Set_Coil_Reg_Ptr(&<NEW_ARRAY>, Addr);
    }

  @endverbatim
  * @{
  */



/**
  * @brief     Коилы
  * @details   Желательно с помощью reserved делать стркутуру кратной 16-битам
  */
typedef union
{
    __PACKED_STRUCT
    {
        unsigned state_val_01: 1;
        unsigned state_val_02: 1;
        unsigned state_val_03: 1;
        unsigned state_val_04: 1;
        unsigned state_val_05: 1;
        unsigned state_val_06: 1;
        unsigned state_val_07: 1;
        unsigned state_val_08: 1;
        unsigned state_val_09: 1;
        unsigned state_val_10: 1;
        unsigned state_val_11: 1;
        unsigned state_val_12: 1;
        unsigned state_val_13: 1;
        unsigned state_val_14: 1;
        unsigned state_val_15: 1;
        unsigned state_val_16: 1;
    } state_val_bit;
    uint16_t all;


} word;
typedef union
{
    __PACKED_STRUCT
    {
        unsigned Temp1_relay_isOn   : 1;
        unsigned Temp2_relay_isOn   : 1;
        unsigned Temp3_relay_isOn   : 1;
        unsigned Temp4_relay_isOn   : 1;
        unsigned Temp5_relay_isOn   : 1;
        unsigned Temp6_relay_isOn   : 1;
        unsigned Temp7_relay_isOn   : 1;
        unsigned Temp8_relay_isOn   : 1;
        unsigned Temp9_relay_isOn   : 1;
        unsigned Temp10_relay_isOn  : 1;
        unsigned Temp11_relay_isOn  : 1;
        unsigned Temp12_relay_isOn  : 1;
        unsigned Temp13_relay_isOn  : 1;
        unsigned Temp14_relay_isOn  : 1;
        unsigned Temp15_relay_isOn  : 1;
        unsigned Temp16_relay_isOn  : 1;


    } state_val_bit;
    uint16_t all;


} RELAY_Struct;

typedef union
{
    __PACKED_STRUCT
    {
        unsigned Temp1_isConnected  : 1;
        unsigned Temp2_isConnected  : 1;
        unsigned Temp3_isConnected  : 1;
        unsigned Temp4_isConnected  : 1;
        unsigned Temp5_isConnected  : 1;
        unsigned Temp6_isConnected  : 1;
        unsigned Temp7_isConnected  : 1;
        unsigned Temp8_isConnected  : 1;
        unsigned Temp9_isConnected  : 1;
        unsigned Temp10_isConnected : 1;
        unsigned Temp11_isConnected : 1;
        unsigned Temp12_isConnected : 1;
        unsigned Temp13_isConnected : 1;
        unsigned Temp14_isConnected : 1;
        unsigned Temp15_isConnected : 1;
        unsigned Temp16_isConnected : 1;

    } state_val_bit;
    uint16_t all;


} STATUS_TSENS;


typedef     __PACKED_STRUCT
{
    int temp ;
    unsigned Temp_relay_on  : 1;
    unsigned Temp_relay_off : 1;
    unsigned is_connect: 1;

} Temp_sens;
extern Temp_sens temp_sens ;

typedef     __PACKED_STRUCT
{



    word coils[3];                            //48
    uint16_t reserve_coils[mb_fill_rsv(128 / 16, word[3])];
    STATUS_TSENS status_tSens[MAX_SENSE / 16]; //32
    uint16_t reserve_status_tSens[mb_fill_rsv(128 / 16, STATUS_TSENS[MAX_SENSE / 16])];
    RELAY_Struct relay_struct_on;            //16 ON
		uint16_t reserve_relay_struct_on[mb_fill_rsv(32 / 16, RELAY_Struct)];
    RELAY_Struct relay_struct_off;      	  //16 OFF
    uint16_t reserve_relay_struct_off[mb_fill_rsv(32 / 16, RELAY_Struct)];
		uint16_t reserve3[mb_fill_rsv(80 / 16, RELAY_Struct)];

    unsigned init_param: 1;                 //384
    unsigned init_Tsens: 1;                 //385
    unsigned Save_Param_to_Flash: 1; //386
    unsigned reserved2: 13;

} MB_DataCoilsTypeDef;



/** MODBUS_DATA_COILS_DEFINES
  * @}
  */


//-----------MODBUS DEVICE DATA SETTING-------------
// MODBUS DATA STRUCTTURE
/**
  * @brief Структура со всеми регистрами и коилами модбас
  * @ingroup  MODBUS_DATA
  */
typedef struct // tester modbus data
{
    MB_DataInRegsTypeDef      InRegs;     ///< Modbus input registers @ref MB_DataInRegsTypeDef

    MB_DataCoilsTypeDef       Coils;      ///< Modbus coils @ref MB_DataCoilsTypeDef

    MB_DataHoldRegsTypeDef    HoldRegs;   ///< Modbus holding registers @ref MB_DataHoldRegsTypeDef
} MB_DataStructureTypeDef;
extern MB_DataStructureTypeDef MB_DATA;

#endif //_MODBUS_DATA_H_

/////////////////////////////////////////////////////////////
///////////////////////TEMP/OUTDATE/OTHER////////////////////
