#include "log_to_memory.h"
#include <message_modbus.h>
#include <modbus_hmi.h>
#include <modbus_hmi_update.h>
#include <vector.h>

#include "control_station.h"
#include "global_time.h"
#include "modbus_table_v2.h"
#include "RS_modbus_pult.h"
#include "DSP281x_Device.h"
#include "MemoryFunctions.h"
#include "RS_modbus_svu.h"
#include "log_params.h"


#pragma DATA_SECTION(modbus_table_discret_in,".logs");
MODBUS_REG_STRUCT modbus_table_discret_in[SIZE_MODBUS_TABLE_DISCRET_REMOUTE];   //registers 10001-19999 modbus RTU

#pragma DATA_SECTION(modbus_table_discret_out,".logs");
MODBUS_REG_STRUCT modbus_table_discret_out[SIZE_MODBUS_TABLE_DISCRET_REMOUTE];  //registers 1-9999 modbus RTU

#pragma DATA_SECTION(modbus_table_analog_in, ".logs");
MODBUS_REG_STRUCT modbus_table_analog_in[SIZE_MODBUS_ANALOG_REMOUTE];   //registers 30001-39999 modbus RTU

#pragma DATA_SECTION(modbus_table_analog_out, ".logs");
//MODBUS_REG_STRUCT modbus_table_analog_out[700];  //registers 40001-49999 modbus RTU
MODBUS_REG_STRUCT modbus_table_analog_out[SIZE_MODBUS_ANALOG_REMOUTE];  //registers 40001-49999 modbus RTU

//#pragma DATA_SECTION(modbus_table_analog_out2, ".logs");
//MODBUS_REG_STRUCT modbus_table_analog_out[700];  //registers 40001-49999 modbus RTU
//MODBUS_REG_STRUCT modbus_table_analog_out2[SIZE_MODBUS_ANALOG_REMOUTE];  //registers 40001-49999 modbus RTU


//unsigned int flag_waiting_answer = 1;
//unsigned int flag_message_sent = 0;


///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
void clear_table_remoute(void)
{
   int i;

   for (i=0;i<SIZE_MODBUS_TABLE_DISCRET_REMOUTE;i++)
   {
       modbus_table_discret_in[i].all = 0;
       modbus_table_discret_out[i].all = 0;
   }

   for (i=0;i<SIZE_MODBUS_ANALOG_REMOUTE;i++)
   {
       modbus_table_analog_in[i].all = 0;
       modbus_table_analog_out[i].all = 0;
       //modbus_table_analog_out2[i].all = 0;
   }




}

///////////////////////////////////////////////////
///
///////////////////////////////////////////////////

void setRegisterDiscreteOutput(int value, int adres) 
{
  int word_number = 0;
  int bit_number = 0;

    if (adres >= 0 && adres < SIZE_MODBUS_TABLE_DISCRET_BITS)
    {
//        word_number = (adres % 16 == 0) && (adres != 0) ? adres / 16 + 1 :
//                                                          adres / 16;
        word_number = (adres % 16 == 0) && (adres != 0) ? adres / 16 :
                                                          adres / 16;
        bit_number = adres % 16;
        
        if (word_number<SIZE_MODBUS_TABLE_DISCRET_REMOUTE)
        {
         if (value)
            modbus_table_discret_out[word_number].all |= 1 << bit_number;
		 else
		    modbus_table_discret_out[word_number].all &= ~(1 << bit_number);
        }
    }
}

///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
int getRegisterDiscreteOutput(int adres) {
    int word_number = 0;
    int bit_number = 0;

    if (adres >= 0 && adres < SIZE_MODBUS_TABLE_DISCRET_BITS) {
        word_number = adres / 16;
        bit_number = adres % 16;
        return (modbus_table_discret_out[word_number].all >> bit_number) & 1;
    }

	return 0;
}

///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
int readDiscreteOutputsFromRemote()
{
    int succed = 0;
    static unsigned int time_tick_modbus = 0;
    static unsigned int old_PWM_ticks = 0;
    static unsigned int count_write_to_modbus = 0;
    static int cur_position_buf_modbus1 = 0;

   ModbusRTUsetDiscretDataArray(modbus_table_discret_out, modbus_table_discret_out);

//    if (global_time.pwm_tics != old_PWM_ticks)
//    {
//        if (global_time.pwm_tics > old_PWM_ticks)
//            time_tick_modbus = time_tick_modbus + (global_time.pwm_tics - old_PWM_ticks);
//        else
//            time_tick_modbus++;
//    }
//    old_PWM_ticks = global_time.pwm_tics;
//    if (TIME_PAUSE_MODBUS < time_tick_modbus)
//    {
        if (!rs_b.flag_LEADING)
        {
//            time_tick_modbus = 0;

            if (control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] == 0)
                cur_position_buf_modbus1 = cur_position_buf_modbus1 + SIZE_BUF_WRITE_TO_MODBUS1_REMOUTE;

            if (cur_position_buf_modbus1 >= SIZE_MODBUS_TABLE_DISCRET_REMOUTE)
                cur_position_buf_modbus1 = 0;

            if ((cur_position_buf_modbus1 + SIZE_BUF_WRITE_TO_MODBUS1_REMOUTE) > SIZE_MODBUS_TABLE_DISCRET_REMOUTE)
                count_write_to_modbus = SIZE_MODBUS_TABLE_DISCRET_REMOUTE - cur_position_buf_modbus1;
            else
                count_write_to_modbus = SIZE_BUF_WRITE_TO_MODBUS1_REMOUTE;

            ModbusRTUsend1(&rs_b, 2,
                           ADR_MODBUS_TABLE_REMOUTE + cur_position_buf_modbus1,
                           count_write_to_modbus);
			succed = 1;
 //           control_station.flag_message_sent[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;
        }
//    }
    return succed;
}

///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
int writeSigleDiscreteDataToRemote(unsigned int adres)
{
	ModbusRTUsetDiscretDataArray(modbus_table_discret_out, modbus_table_discret_out);
	if (!rs_b.flag_LEADING && !control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] &&
	        (adres < SIZE_MODBUS_TABLE_DISCRET_BITS)) {
        ModbusRTUsend5(&rs_b, 2, ADR_MODBUS_TABLE_REMOUTE + adres);
		return 1;
    }
	return 0;
}

///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
int writeSingleAnalogOutputToRemote(unsigned int adres)
{
	ModbusRTUsetDataArrays(modbus_table_analog_in, modbus_table_analog_out);
	if (!rs_b.flag_LEADING && !control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] &&
	        (adres < SIZE_MODBUS_ANALOG_REMOUTE)) {
        ModbusRTUsend6(&rs_b, 2, ADR_MODBUS_TABLE_REMOUTE + adres);
		return 1;
    }
	return 0;
}




///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
int writeDiscreteDataToRemote()
{
    int succed = 0;
    static unsigned int old_time = 0;

    static unsigned int count_write_to_modbus = 0;
    static int cur_position_buf_modbus15 = 0;

    //ModbusRTUsetDiscretDataArray(modbus_table_discret_out, modbus_table_discret_out);
    ModbusRTUsetDiscretDataArray(modbus_table_discret_in, modbus_table_discret_out);


    if (!rs_b.flag_LEADING)
    {

//        if (rs_b.RS_DataReadyAnswerAnalyze)
//        {
//            cur_position_buf_modbus15 += SIZE_BUF_WRITE_TO_MODBUS15_REMOUTE;
//        }

        if (cur_position_buf_modbus15 >= (SIZE_MODBUS_TABLE_DISCRET_REMOUTE))
            cur_position_buf_modbus15 = 0;

        if ((cur_position_buf_modbus15 + SIZE_BUF_WRITE_TO_MODBUS15_REMOUTE) > (SIZE_MODBUS_TABLE_DISCRET_REMOUTE))
            count_write_to_modbus = SIZE_MODBUS_TABLE_DISCRET_REMOUTE - cur_position_buf_modbus15;
        else
            count_write_to_modbus = SIZE_BUF_WRITE_TO_MODBUS15_REMOUTE;

        //          count_write_to_modbus = SIZE_BUF_WRITE_TO_MODBUS16;
        //		  cur_position_buf_modbus=0;

        ModbusRTUsend15(&rs_b, 2, ADR_MODBUS_TABLE_REMOUTE + cur_position_buf_modbus15*16,
                        count_write_to_modbus*16);
//        ModbusRTUsend15(&rs_a, 2, ADR_MODBUS_TABLE_REMOUTE + cur_position_buf_modbus15*16,
//                        count_write_to_modbus*16);

        cur_position_buf_modbus15 += SIZE_BUF_WRITE_TO_MODBUS15_REMOUTE;

 //       control_station.flag_message_sent[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;
 //       control_station.count_error_modbus_15[CONTROL_STATION_INGETEAM_PULT_RS485]++;

   //     hmi_watch_dog = !hmi_watch_dog; //was transmitted, need to change
        succed = 1;

    }
    return succed;
}

///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
#define ADRESS_END_FIRST_BLOCK  20
#define ADRESS_START_PROTECTION_LEVELS 91

int readAnalogDataFromRemote()
{
    int succed = 0;
    static unsigned int old_time = 0;

    static unsigned int count_write_to_modbus = 0;
    static int cur_position_buf_modbus3 = 0, size_buf = SIZE_BUF_READ_FROM_MODBUS16_REMOUTE;


    ModbusRTUsetDataArrays(modbus_table_analog_in, modbus_table_analog_out);



    if (!rs_b.flag_LEADING)
    {

        if (control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] == 0)
            cur_position_buf_modbus3 = cur_position_buf_modbus3 + size_buf;

        if (cur_position_buf_modbus3 >= SIZE_ANALOG_DATA_FROM_MODBUS16_REMOUTE)
            cur_position_buf_modbus3 = 0;
        //Дырка в обмене. Пропускаем.
        if ((cur_position_buf_modbus3 > ADRESS_END_FIRST_BLOCK) &&
                (cur_position_buf_modbus3 < ADRESS_START_PROTECTION_LEVELS)) {
            cur_position_buf_modbus3 = ADRESS_START_PROTECTION_LEVELS;
        }
        if((cur_position_buf_modbus3 < ADRESS_END_FIRST_BLOCK) &&
                (cur_position_buf_modbus3 + size_buf) > ADRESS_END_FIRST_BLOCK) {
            count_write_to_modbus = ADRESS_END_FIRST_BLOCK - cur_position_buf_modbus3;
        }

        if ((cur_position_buf_modbus3 + size_buf) > SIZE_ANALOG_DATA_FROM_MODBUS16_REMOUTE)
            count_write_to_modbus = SIZE_ANALOG_DATA_FROM_MODBUS16_REMOUTE - cur_position_buf_modbus3;
        else
            count_write_to_modbus = size_buf;

        //          count_write_to_modbus = SIZE_BUF_WRITE_TO_MODBUS16;
        //		  cur_position_buf_modbus=0;


        //		  SendCommandModbus3(&rs_b,1,ADR_MODBUS_TABLE+cur_position_buf_modbus3,count_write_to_modbus);
        ModbusRTUsend4(&rs_b, 2,
                       ADR_MODBUS_TABLE_REMOUTE + cur_position_buf_modbus3,
                       count_write_to_modbus);
 //       control_station.count_error_modbus_4[CONTROL_STATION_INGETEAM_PULT_RS485]++;

 //       control_station.flag_message_sent[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;
        succed = 1;
    }
    return succed;
}


int writeSingleAnalogDataToRemote(int from_adr, int count_wr)
{
    int succed = 0;
    static unsigned int old_time = 0;

    static int count_write_to_modbus = 0;
    static int cur_position_buf_modbus16 = 0;


    ModbusRTUsetDataArrays(modbus_table_analog_in, modbus_table_analog_out);


    if (!rs_b.flag_LEADING)
    {
        cur_position_buf_modbus16 = from_adr;

//        if (control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] == 0)
//            cur_position_buf_modbus16 = cur_position_buf_modbus16 + SIZE_BUF_WRITE_TO_MODBUS16_REMOUTE;
//
//        if (cur_position_buf_modbus16 >= SIZE_ANALOG_DATA_REMOUTE)
//            cur_position_buf_modbus16 = 0;

//        //Дырка в обмене. Пропускаем.
//        if ((cur_position_buf_modbus16 > ADRESS_END_FIRST_BLOCK) &&
//                (cur_position_buf_modbus16 < ADRESS_START_PROTECTION_LEVELS)) {
//            cur_position_buf_modbus16 = ADRESS_START_PROTECTION_LEVELS;
//        }

        if ((cur_position_buf_modbus16 + count_wr) > SIZE_ANALOG_DATA_REMOUTE)
            count_write_to_modbus = SIZE_ANALOG_DATA_REMOUTE - cur_position_buf_modbus16;
        else
            count_write_to_modbus = count_wr;

        ModbusRTUsend16(&rs_b, 2,
                        ADR_MODBUS_TABLE_REMOUTE + cur_position_buf_modbus16,
                        count_write_to_modbus);

        succed = 1;
    }
    return succed;
}


///////////////////////////////////////////////////
///
///////////////////////////////////////////////////
int writeAnalogDataToRemote()
{
    int succed = 0;
    static unsigned int old_time = 0;

    static int count_write_to_modbus = 0;
    static int cur_position_buf_modbus16 = 0;


    ModbusRTUsetDataArrays(modbus_table_analog_in, modbus_table_analog_out);


    if (!rs_b.flag_LEADING)
    {
        if (control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] == 0)
            cur_position_buf_modbus16 = cur_position_buf_modbus16 + SIZE_BUF_WRITE_TO_MODBUS16_REMOUTE;

        if (cur_position_buf_modbus16 >= SIZE_ANALOG_DATA_REMOUTE)
            cur_position_buf_modbus16 = 0;

//        //Дырка в обмене. Пропускаем.
//        if ((cur_position_buf_modbus16 > ADRESS_END_FIRST_BLOCK) &&
//                (cur_position_buf_modbus16 < ADRESS_START_PROTECTION_LEVELS)) {
//            cur_position_buf_modbus16 = ADRESS_START_PROTECTION_LEVELS;
//        }

        if ((cur_position_buf_modbus16 + SIZE_BUF_WRITE_TO_MODBUS16_REMOUTE) > SIZE_ANALOG_DATA_REMOUTE)
            count_write_to_modbus = SIZE_ANALOG_DATA_REMOUTE - cur_position_buf_modbus16;
        else
            count_write_to_modbus = SIZE_BUF_WRITE_TO_MODBUS16_REMOUTE;

        ModbusRTUsend16(&rs_b, 2,
                        ADR_MODBUS_TABLE_REMOUTE + cur_position_buf_modbus16,
                        count_write_to_modbus);
 //       control_station.count_error_modbus_16[CONTROL_STATION_INGETEAM_PULT_RS485]++;

  //      control_station.flag_message_sent[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;
        succed = 1;
    }
    return succed;
}





///////////////////////////////////////////////////
///
///////////////////////////////////////////////////



