#ifndef _requester
#define _requester
#include "main.h"
#include "can.h"
#include "rtc.h"
#include "tim.h"

#define _DEMO

#define ONLINE 1;
#define OFFLINE 0;

// TIM defines
#define TIM_REQUESTER_Prescaler 64000

//CAN Settings
#define _HCAN hcan

//CAN Speed
#define CAN_SPEED_PRSC_1000KB 2
#define CAN_SPEED_PRSC_500KB 4
#define CAN_SPEED_PRSC_250KB 8
#define CAN_SPEED_PRSC_125KB 16
#define CAN_SPEED_PRSC_50KB 40
#define CAN_CURRENT_SPEED CAN_SPEED_PRSC_250KB

//CAN Filter
#define ID_MAIN_DEVICE 0x000

#define CURRENT_TYPE_DEVICE 0b001
#define CURRENT_ID_DEVICE 0b0010

#define CAN_IDE_32 0b00000100            // Для 32-х битного масштаба

#define CAN_DATA_TYPE_FILTER 0x1F000000
#define CAN_DEVICE_ID_FILTER 0x000000FF
#define CAN_SENSOR_TYPE_FILTER 0x00F80000
#define CAN_SENSOR_ID_FILTER 0x0007FF00

typedef union{
	struct bitfield{
		unsigned bit0:1;
		unsigned bit1:1;
		unsigned bit2:1;
		unsigned bit3:1;
		unsigned bit4:1;
		unsigned bit5:1;
		unsigned bit6:1;
		unsigned bit7:1;
	}Bitfield;
	char AllBit;
}Byte;

/**
  * @brief  HAL Status structures definition
  */
typedef enum
{
  CRR_OK       = 0x00U,
  CRR_ERROR    = 0x01U,
  CRR_BUSY     = 0x02U,
  CRR_TIMEOUT  = 0x03U
} CRR_Status;

_Bool IsLeapYear(uint8_t year);

#define COUNT_OF_MODBUS_SECTIONS 1
#define MODBUS_SECTION_MASK 0
#define MODBUS_SECTION_FILTER 1

#define SensorToModbusRegister(SensorType, SensorID) SensorType << 11 | SensorID
#define HighByteOfWord(WORD) (WORD>>8)&0xFF
#define LowByteOfWord(WORD) WORD&0xFF

//Priority level
#define PRIORITY_CRITICAL 0
#define PRIORITY_STANDARD 1

//Route mode
#define ROUTE_MASTER 1
#define ROUTE_SLAVE 0

//Data Types
#define DATA_TYPE_BROADCAST 0b0000
#define DATA_TYPE_DISCRETE 0b0001
#define DATA_TYPE_ANALOG 0b0010
#define DATA_TYPE_GENERAL_ADDRESS_SPACE 0b0011
#define DATA_TYPE_MODBUS_COIL 0b0100
#define DATA_TYPE_MODBUS_DISCRETE 0b0101
#define DATA_TYPE_MODBUS_HOLDING 0b0110
#define DATA_TYPE_MODBUS_INPUT 0b0111
#define DATA_TYPE_ERROR 0b1000
#define DATA_TYPE_PULSE 0b1111

//Sensor Types for DATA_TYPE_BROADCAST
#define SENSOR_TYPE_BROADCAST_STATUS 0b000000000000
#define SENSOR_TYPE_BROADCAST_ONOFF 0b000000000001
#define SENSOR_TYPE_BROADCAST_RESTARTDEVICE 0b000000000010
#define SENSOR_TYPE_BROADCAST_RTCSETUP 0b000000000011

//Sensor Types for DATA_TYPE_DISCRETE
#define SENSOR_TYPE_DISCRETE_ACCIDENT 0b0000
#define SENSOR_TYPE_DISCRETE_WARNING 0b0001
#define SENSOR_TYPE_DISCRETE_CONTROL_SIGNALS 0b0010
#define SENSOR_TYPE_DISCRETE_FLAGS 0b0011
#define SENSOR_TYPE_DISCRETE_RESET 0b0100
#define SENSOR_TYPE_DISCRETE_CHANGE_MODE 0b0101
#define SENSOR_TYPE_DISCRETE_REQUEST_LIST_OF_PARAMETERS 0b0110

//Sensor Types for DATA_TYPE_ANALOG
#define SENSOR_TYPE_ANALOG_UNIVERSAL 0b0000
#define SENSOR_TYPE_ANALOG_USTAVKI 0b0001
#define SENSOR_TYPE_ANALOG_U 0b0010
#define SENSOR_TYPE_ANALOG_I 0b0011
#define SENSOR_TYPE_ANALOG_T 0b0100

//Error Code
#define NONEXISTENT_ELEMENT 0x01

#define HighIdFilter(x) x<<24

struct controlflags{
	unsigned IsPulse:1;
	unsigned IsRtrMode:1;
};

//Device settings
typedef union{
    struct msgBody_Broadcast{
        unsigned Page:4;
        unsigned BroadcastType:12;
    }Fields;
    unsigned Body:16;
}msgBroadcastType;

typedef union{
    struct msgBody_Discrete{
        unsigned Body:12;
        unsigned Type:4;
    }Fields;
    unsigned Body:16;
}msgDiscreteType;

typedef union{
    struct msgBody_Analog{
        unsigned SensorID:12;
        unsigned SensorType:4;
    }Fields;
    unsigned Body:16;
}msgAnalogType;

typedef union{
    struct msgBody_Modbus{
        unsigned RegCount:4;
        unsigned StrAdr:12;
    }Fields;
    unsigned Body:16;
}msgModbusType;

typedef union{
    struct msgBody_Error{
        unsigned ErrorCode:8;
        unsigned Info:8;
    }Fields;
    unsigned Body:16;
}msgErrorType;

typedef union{
    struct extID_Fields{
        unsigned MsgBody:16;	
        unsigned MsgType:4;
        unsigned DeviceID:4;
        unsigned DeviceType:3;
        unsigned Route:1;
        unsigned Priority:1;
    }Fields;
    unsigned int BitAll:29;	
}extID;

//			typedef union{
//	struct extID_Fields{
//		union{
//			msgBodyBroadcast Broadcast;
//			msgBodyDiscrete Discrete;
//			msgBodyAnalog Analog;
//			msgBodyModbus Modbus;
//			msgBodyError Error;
//			unsigned Body:16;
//			}Msg;		
//		unsigned MsgType:4;
//		unsigned DeviceID:4;
//		unsigned DeviceType:3;
//		unsigned Route:1;
//		unsigned Priority:1;
//	}Fields;
//	unsigned int BitAll:29;	
//}extID;
			
struct device{
	unsigned Status:1;
	extID ExtID;
	unsigned TimeFromLastPulse;
	unsigned LastPulseStep;
};

struct data{
	struct T_sens{
		char info[256];
		unsigned SensID;
		unsigned AvrgValue;
		unsigned LastTenValues[10];
	}TS;
	
	struct U_sens{
		char info[256];
		unsigned SensID;
		unsigned AvrgValue;
		unsigned LastTenValues[10];
	}Uu, Uv, Uw;
	
	struct I_sens{
		char info[256];
		unsigned SensID;
		unsigned AvrgValue;
		unsigned LastTenValues[10];		
	}Iu, Iv, Iw;
};

struct received_request{
	extID RequestedExtID;
	unsigned RequestedDLC;
	uint8_t RxData[8]; 
	
	//DATA_TYPE_DISCRETIC
	union discreticflags{
		struct discretictype{
			unsigned Request_Accident:1;
			unsigned Request_Warning:1;
			unsigned Request_Control_Signals:1;
			unsigned Request_Flags:1;
			unsigned Request_Reset:1;
			unsigned Request_List_of_Parameters:1;
		}DiscreticType;
		unsigned AllFlags:5;
	}DiscreticFlags;
	
	//DATA_TYPE_BROADCAST
	union broadcastflags{
		struct broadcasttype{
			unsigned Request_Status:1;
			unsigned Request_OnOff:1;
			unsigned Request_RTC_Setup:1;
		}BroadcastType;
		unsigned AllFlags:3;
	}BroadcastFlags;
	
	//DATA_TYPE_ANALOG
	union analogflags{
		struct analogtype{
			unsigned Request_Universal_Sens:1;
			unsigned Request_U_Sens:1;
			unsigned Request_I_Sens:1;
			unsigned Request_T_Sens:1;
		}AnalogType;
		unsigned AllFlags:4;
	}AnalogFlags;
	
	//DATA_TYPE_MODBUS
	union modbusflags{
		struct modbustype{
			unsigned Coil:1;
			unsigned Discrete:1;
			unsigned Holding:1;
			unsigned Input:1;
		}ModbusType;
		unsigned AllFlags:4;
	}ModbusFlags;
	
	union sensor_To_Modbus{
		struct modbus{
			unsigned Count:8;
			unsigned StrAdr:8;
		}Modbus;
		unsigned Sensor:16;
	}SensorToModbus;
	
	unsigned ModbusFlag:1;
};

#define CAN_RX_BUFFER_SIZE 128

struct RXMsg{
	struct INFO{
		unsigned EXT:1;
		unsigned RTR:1;
	}info;
	extID eID;
	uint16_t DLC;
	uint8_t Data[8];
};

uint16_t AvailableCanRxMsg(void);

void REQUESTER_Init(void);
void REQUESTER_MainWhile(void);
void Boot_SystemClock_Config(void);

CRR_Status REQUESTER_AnalogProcessing(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToAnalogUniversal(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToAnalogUSTAVKI(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToAnalogUSens(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToAnalogISens(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToAnalogTSens(struct RXMsg _rxMsg);

CRR_Status REQUESTER_BroadcastProcessing(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToBroadcastStatus(struct RXMsg _rxMsg);
void CanRequestToBroadcastOnOff(struct RXMsg _rxMsg);
void CanRequestToBroadcastRestart(struct RXMsg _rxMsg);
void CanRequestToBroadcastRtcSetup(struct RXMsg _rxMsg);

CRR_Status REQUESTER_DiscreticProcessing(struct RXMsg _rxMsg);
void CanRequestToDiscreteAccident(struct RXMsg _rxMsg);
void CanRequestToDiscreteWarning(struct RXMsg _rxMsg);
void CanRequestToDiscreteControlSignals(struct RXMsg _rxMsg);
void CanRequestToDiscreteFlags(struct RXMsg _rxMsg);
void CanRequestToDiscreteReset(struct RXMsg _rxMsg);
void CanRequestToDiscreteChangeMode(struct RXMsg _rxMsg);
void CanRequestToDiscreteRequestListOfParameters(struct RXMsg _rxMsg);

void REQUESTER_GeneralAddressSpace_Answer(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestError(struct RXMsg _rxMsg);

CRR_Status REQUESTER_ModbusProcessing(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToModbusCoil(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToModbusDiscrete(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToModbusHolding(struct RXMsg _rxMsg);
HAL_StatusTypeDef CanRequestToModbusInput(struct RXMsg _rxMsg);

void REQUESTER_RTC_SYNC(uint8_t *data);
void REQUESTER_Pulse_TIM_Handler(void);
void Boot_SystemClock_Config(void);
void REQUESTER_CAN_FILTERS(void);
#endif
