/*
 * modbus.h
 *
 * Created: 03.09.2012 08:39:40
 *  Author: Falko
 */ 


#ifndef MODBUS_H_
#define MODBUS_H_
  
  #if MODBUS_SUPPORT == TRUE

    #include "stdint.h"
    #include "stdbool.h"
    #include "main.h"
	#include "sysdata.h"

    //! brief Anzahl der Startbits, nach Modbus Spezifikation immer 1, stop bits werden aus den Einstellungen geladen
    #define NUMBER_OF_STARTBITS				1U
  
    //! brief Anzahl der Datenbits, nach Modbus Spezifikation immer 8
    #define NUMBER_OF_DATABITS				8U
  
    //! brief Max Timeput zwischen zwei gesendeten char
    #define TIMEOUT_BETWEEN_CHARACTERS		1.5
  
    //! brief Timeput bei dem fertig gesendetes Frame erkannt wird
    #define TIMEOUT_FRAME_COMPLETE			3.5
  
    //! define der Größe der Ein- und Ausgangsbuffer
    #define RXBUFFERSIZE                    256
    #define TXBUFFERSIZE                    256
  
    #define FORWARD_DATA                    TRUE
    #define SEND_TO_LOKALBUS				1
    #define RESPOND_TO_QUERY				2	

    #define MAX_ADRESS                      ((sizeof(sys_data_struct_t) / 2)-1)
    
    #define MODBUS_UART_PARITY_EVEN         0
    #define MODBUS_UART_PARITY_ODD          1
    #define MODBUS_UART_PARITY_NONE         2

	#define MODBUS_BROADCAST_ADDRESS        0x00
	#define FC_READ_COILS                   0x01
	#define FC_READ_HOLDING_REGISTERS       0x03
	#define FC_WRITE_SINGLE_REGISTER        0x06
	#define FC_WRITE_MULTIPLE_REGISTER      0x10

//    typedef union bword
//    {
//      uint16_t    w;
//       int16_t    sw;
//       uint8_t    lb;
//        int8_t    slb;
//       uint8_t    b[2];
//        int8_t    sb[2];
//    } 
//    bword_t;

    typedef enum mb_error_codes_enum
    {
      MB_ERROR_NOTHING              = 0,
      MB_ERROR_TIMEOUT              = 1,
      MB_ERROR_CRC                  = 2,
      MB_ERROR_SLAVE_ADRESS         = 3,
      MB_ERROR_FUNCTION_CODE        = 4,
      MB_ERROR_BYTE_COUNT           = 5,
      MB_ERROR_START_ADRESS         = 6,
      MB_ERROR_UART_PE              = 7,										//Parity 
      MB_ERROR_UART_NE              = 8,										//Noise
      MB_ERROR_UART_FE              = 9,										//Frame
      MB_ERROR_UART_ORE             = 10,										//Overrun
    } 
    mb_error_codes_t;



    typedef enum
    {
      MB_QUERY_NOTHING,
      MB_QUERY_READ_IDENT,
      MB_QUERY_READ_DATA,
      MB_QUERY_READ_LIPRO_DATA,
      MB_QUERY_WRITE_LIPRO_BALANCER_VOLTAGE, 
      MB_QUERY_WRITE_BUTTONS,
      MB_QUERY_GSM_GATEWAY,
      MB_QUERY_REMOTEBUS_GATEWAY,
      MB_QUERY_WRITE_TO_GC,
      MB_QUERY_SEND_DEVICE_ADDRESS,
      MB_QUERY_SEND_SAVE_COMMAND,
      MB_QUERY_GATEWAY,
      MB_QUERY_SEND_DATA
    } 
    mb_status_t;


    typedef struct
    {
      //TIM_HandleTypeDef             * timer;                                  //  Timer config
      //TIM_OC_InitTypeDef            * timerOcConfig;                          //  Zeiger auf TimerInit Struktur
      UART_HandleTypeDef            * uart;										//  Zeiger auf das Uart Modul
      GPIO_TypeDef *                driverEnableGPIO;							//  Zuständiger einschalt Port
      uint16_t                      driverEnableGPIOPin;						//  Zuständiger einschalt Pin
      uint32_t                      mb_t15_total_timer_ticks;					//  max timeout zwischen einzelnen char
      uint32_t                      mb_t35_total_timer_ticks;					//  timeout frame complete
      volatile bool                 mb_rx_frame_complete;						//  frame complete ja/nein
      uint32_t                      response_timeout_counter;					//  antwort Timeout
																				//  QUERY (Anfrage):
      uint8_t                       last_query_slave_adress;					//  zugehörige Slave Andresse
      uint8_t                       last_query_function_code;					//  function Code
      bword_t                       last_query_start_adress;					//  start Adresse
      bword_t                       last_query_number_of_register;				//  Anzahl der Register
      bool                          last_query_timeout;							//  Timeout
      bword_t                       last_query_tcp_id;							//  stack ID
      mb_status_t                   current_query;								//  Zeiger auf Statusstruktur
      uint8_t                       rx_buffer[RXBUFFERSIZE];					//  Bufferarray Empfangen
      uint8_t                       tx_buffer[TXBUFFERSIZE];					//  Bufferarray Senden
      uint32_t                      rx_head;									//  
      uint32_t                      tx_head;									//  
      volatile bool                 setTxLed;									//  status Led
      volatile bool                 setRxLed;									//  status Led
    } 
    modbus_t;



    //Public Functions Modbus
  
                          // Timer Interrupt erkennt Fehler bei Framekomplettierung
    void                  mbTimerIsr                                  (modbus_t * mb_data);
                          // Initialiserung des Moduls muss mit den passenden Parametern gefüllt werden
   void mbInit(modbus_t * mb_data, uint32_t baudrate, uint32_t parityMode, uint16_t stopBits, UART_HandleTypeDef * usart);
                          // überprüft ob ein Frame komplett ist
    bool                  mbGetFrameComplete                          (modbus_t * mb_data);
                        
    void                  mbClearRxFrame                              (modbus_t * mb_data);
                          // handelt den Interrupt
    void                  mbUartIsr                                   (modbus_t* mb_data);


    //Public Fuctions Modbus SLAVE
  
                          // Umgang mit ankommenden Anfragen und Verarbeitung dieser
    void                  mbSlaveProcessRtuQuery                      (modbus_t * mb_data);
                          // Bedeutung der Anfrage und wie mit dieser umgegangen werden soll
    uint32_t              mbSlaveCheckModbusRtuQuery                  (modbus_t * mb_data);
    //                    Verarbeite eine Anfrage
    uint32_t              mbSlaveProcessPdu( uint8_t* response_string, uint8_t * msg, uint32_t tx_position, uint8_t deviceID);

    //Public Fuctions Modbus MASTER
    void                  mbMasterStartRtuReadHoldingRegister         (uint8_t slave_adress,  uint16_t start_adress, uint16_t number_of_registers, modbus_t * mb_data);
    bool                  mbMasterGetTimeout                          (modbus_t * mb_data);	
    void                  mbMasterCheckResponseTimeout                (modbus_t * mb_data);
    mb_error_codes_t      mbMasterCheckReadMultipleRegisterResponse   (modbus_t * mb_data) ;
    mb_error_codes_t      check_write_multiple_register_response      (modbus_t * mb_data) ;	
    void                  mb_start_rtu_write_multiple_register        (uint8_t slave_adress, uint16_t adress, uint16_t * values, uint8_t number_of_registers, modbus_t  * mb_data);
    void MODBUS_UART_IRQHandler(UART_HandleTypeDef *huart);
  #endif
#endif /* MODBUS_H_ */