#include "RS_modbus_svu.h"

#include <message2.h>
#include <message2test.h>

#include "modbus_table_v2.h"
#include "options_table.h"
#include "DSP281x_Device.h"
#include "CRC_Functions.h"
#include "MemoryFunctions.h"
#include "RS_Functions.h"


int err_modbus3 = 1;
int err_modbus16 = 1;
int cmd_3_or_16 = 0;
int err_send_log_16 = 0;			//Switch between command 3 and 16
unsigned int flag_send_answer_rs = 0;	//This flag enables fast answer to SVU when values changed


unsigned int adr_read_from_modbus3 = 0;
unsigned int flag_received_first_mess_from_MPU = 0;




void ReceiveCommandModbus3(RS_DATA_STRUCT *RS232_Arr)
{
	// Контрольнаy сумма
	unsigned int crc, Address_MB, Length_MB, i/*, Data*/;
//	int buf_out[200];  
	
/* получили начальный адрес чтениy. */
	Address_MB =(RS232_Arr->RS_Header[2] << 8) | RS232_Arr->RS_Header[3];

/* получили количество слов данных */
	Length_MB = (RS232_Arr->RS_Header[4] << 8 ) | RS232_Arr->RS_Header[5];
	                                         
	/////////////////////////////////////////////////
	// Отсылка
	/* Посчитали контрольную сумму перед самой посылкой */	
	
//	f.RScount	= SECOND*3;
	
	RS232_Arr->buffer[0] =  RS232_Arr->addr_recive; //CNTRL_ADDR;
	RS232_Arr->buffer[1] =  CMD_RS232_MODBUS_3;
	RS232_Arr->buffer[2] =  Length_MB*2;

	for (i=0;i<Length_MB;i++)
	{
	   if (Address_MB>=ADR_MODBUS_TABLE && Address_MB<0xe00)
	   {
	    RS232_Arr->buffer[3+i*2  ]=modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].byte.HB;
        RS232_Arr->buffer[3+i*2+1]=modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].byte.LB;
	   }

	   if (Address_MB>=0xe00 && Address_MB<0xf00)
	   {
	    RS232_Arr->buffer[3+i*2  ]=options_controller[Address_MB-0xe00+i].byte.HB;
        RS232_Arr->buffer[3+i*2+1]=options_controller[Address_MB-0xe00+i].byte.LB;
	   }

	}
		
    crc = 0xffff;
	crc = GetCRC16_IBM(crc, RS232_Arr->buffer, Length_MB*2+3);

	RS232_Arr->buffer[Length_MB*2+3] = LOBYTE(crc);
	RS232_Arr->buffer[Length_MB*2+4] = HIBYTE(crc);
	
	RS232_Arr->buffer[Length_MB*2+5] = 0;
	RS232_Arr->buffer[Length_MB*2+6] = 0;
	RS_Send(RS232_Arr,RS232_Arr->buffer, Length_MB*2+7);

	return;
}

/***************************************************************/
/***************************************************************/
/*  Запрос данных по протоколу ModBus - команда 3
    Чтение Ячеек данных    		*/
/***************************************************************/
/***************************************************************/
void SendCommandModbus3(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start,unsigned int count_word)
{
	// КонтрольнаЯ сумма
	unsigned int crc; //, Address_MB, Length_MB, i, Data;
//	int buf_out[200];
//	int buf_in[200];

//	rs_arr->buffer[0]=
	rs_arr->buffer[0] =  LOBYTE(adr_contr);
	rs_arr->buffer[1] =  CMD_RS232_MODBUS_3;
	rs_arr->buffer[2] =  HIBYTE(adr_start);
	rs_arr->buffer[3] =  LOBYTE(adr_start);
	rs_arr->buffer[4] =  0;
	rs_arr->buffer[5] =  LOBYTE(count_word);

    	crc = 0xffff;
		crc = GetCRC16_IBM( crc, rs_arr->buffer, 6);
//		crc = get_crc_ccitt( crc, rs_arr->buffer, 6);


	rs_arr->buffer[6] = LOBYTE(crc);
	rs_arr->buffer[7] = HIBYTE(crc);

	rs_arr->buffer[8] = 0;
	rs_arr->buffer[9] = 0;

	RS_Send(rs_arr,rs_arr->buffer, 11);

    /* ждем ответа     */
    if (adr_contr>0 && adr_contr<0xff)
    {

      RS_Len[CMD_RS232_MODBUS_3]=5+count_word*2;

      adr_read_from_modbus3=adr_start;
      RS_SetControllerLeading(rs_arr,true);
      RS_SetAdrAnswerController(rs_arr,adr_contr);

    }


	return;
}


void ReceiveCommandModbus16(RS_DATA_STRUCT *RS232_Arr)
{
	// Контрольнаy сумма
	unsigned int crc, Address_MB, Length_MB, Bytecnt_MB, i/*, Data1,Data2,Quantity*/;
	int /*Data,*/i1,i2;

/* получили начальный адрес чтениy.  */
	Address_MB = RS232_Arr->RS_Header[3] | ( RS232_Arr->RS_Header[2] << 8);

/* получили quantity. */
	//Quantity = RS232_Arr->RS_Header[5] | ( RS232_Arr->RS_Header[4] << 8);

/* получили количество байт данных   */
//	Length_MB = (RS232_Arr->RS_Header[4] << 8 ) | RS232_Arr->RS_Header[5];
	
	Bytecnt_MB = RS232_Arr->RS_Header[6];

	Length_MB = Bytecnt_MB>>1;
	

	for (i=0;i<Length_MB;i++)
	{
	   if (Address_MB>=ADR_MODBUS_TABLE && Address_MB<0xe00)
	   {
	    RS232_Arr->buffer[3+i*2  ]=modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].byte.HB;
        RS232_Arr->buffer[3+i*2+1]=modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].byte.LB;
	   }

	   if (Address_MB>=0xe00 && Address_MB<0xf00)
	   {
        options_controller[Address_MB-0xe00+i].byte.HB=RS232_Arr->RS_Header[7+i*2  ];
		options_controller[Address_MB-0xe00+i].byte.LB=RS232_Arr->RS_Header[7+i*2+1];
	   }

	}


    if (Address_MB>=0xe00 && Address_MB<0xf00)
	{
	 i1 = options_controller[0].all;
	 i2 = options_controller[1].all;
     store_data_flash(options_controller,sizeof(options_controller));
     SetCntrlAddr(i1, i2);	/*	Установка адреса контроллера	*/
    }


		/////////////////////////////////////////////////
		// Отсылка
		// Посчитали контрольную сумму перед самой посылкой 

		RS232_Arr->buffer[0] =  RS232_Arr->addr_recive;
		RS232_Arr->buffer[1] =  CMD_RS232_MODBUS_16;
		RS232_Arr->buffer[2] =  HIBYTE(Address_MB);
		RS232_Arr->buffer[3] =  LOBYTE(Address_MB);
		RS232_Arr->buffer[4] =  0;
		RS232_Arr->buffer[5] =  2;

    	crc = 0xffff;
		crc = GetCRC16_IBM( crc, RS232_Arr->buffer, 6);

		RS232_Arr->buffer[6] = LOBYTE(crc);
		RS232_Arr->buffer[7] = HIBYTE(crc);

		RS232_Arr->buffer[8] = 0;
		RS232_Arr->buffer[9] = 0;
		RS_Send(RS232_Arr,RS232_Arr->buffer, 10);
		
		return;


}
/***************************************************************/
/***************************************************************/
/***************************************************************/
/*  Передача данных по протоколу ModBus - команда 16
    Передача данных    		*/
/***************************************************************/
/***************************************************************/
/***************************************************************/

void SendCommandModbus16(RS_DATA_STRUCT *rs_arr,int adr_contr, unsigned int adr_start,unsigned int count_word)
{

	// КонтрольнаЯ сумма
	unsigned int crc, Address_MB, i;	//, Length_MB; //, Bytecnt_MB, Data1,Data2;
//	int Data, digital, ust_I, ust_Time;

    //Length_MB  = count_word;
    Address_MB = adr_start;


	// Отсылка
	// Посчитали контрольную сумму перед самой посылкой

	rs_arr->buffer[0] =  adr_contr;
	rs_arr->buffer[1] =  CMD_RS232_MODBUS_16;

	rs_arr->buffer[2] =  HIBYTE(adr_start);
	rs_arr->buffer[3] =  LOBYTE(adr_start);

	rs_arr->buffer[4] =  HIBYTE(count_word);
	rs_arr->buffer[5] =  LOBYTE(count_word);

	rs_arr->buffer[6] =  LOBYTE(count_word*2);



	for (i=0;i<count_word;i++)
	{
	   rs_arr->buffer[7+i*2  ]=modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].byte.HB;
	   rs_arr->buffer[7+i*2+1]=modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].byte.LB;//LOBYTE(buffer_out_data[Address_MB+i]);
	}

    crc = 0xffff;
//	crc = get_crc_ccitt(crc, rs_arr->buffer, Length_MB*2+7);
	crc = GetCRC16_IBM(crc, rs_arr->buffer, (unsigned long)(count_word*2+7));

	rs_arr->buffer[count_word*2+7] = LOBYTE(crc);
	rs_arr->buffer[count_word*2+8] = HIBYTE(crc);

	rs_arr->buffer[count_word*2+9] = 0;
	rs_arr->buffer[count_word*2+10] = 0;

	RS_Send(rs_arr,rs_arr->buffer,( count_word*2+10+2));


    // ждем ответа
    if (adr_contr>0 && adr_contr<0xff)
    {
      RS_Len[CMD_RS232_MODBUS_16]=8;
      RS_SetControllerLeading(rs_arr,true);
      RS_SetAdrAnswerController(rs_arr,adr_contr);
    }

}


void ReceiveAnswerCommandModbus3(RS_DATA_STRUCT *RS232_Arr)
{
	unsigned int Address_MB, Length_MB, i;
	MODBUS_REG_STRUCT elementData;
	
/* получили начальный адрес чтениЯ. */
	Address_MB = adr_read_from_modbus3;

/* получили количество слов данных */
	Length_MB = RS232_Arr->RS_Header[2] >> 1;
	                                         
	/////////////////////////////////////////////////
	// Отсылка
	/* Посчитали контрольную сумму перед самой посылкой */	
		
	for (i=0;i<Length_MB;i++)
	{             	
		elementData.byte.HB = RS232_Arr->RS_Header[3+i*2];
			    elementData.byte.LB = RS232_Arr->RS_Header[3+i*2+1];
			    if (elementData.all != modbus_table_rs_in[Address_MB-ADR_MODBUS_TABLE+i].all) {
			    	flag_send_answer_rs = 1;
			    }
			    modbus_table_rs_in[Address_MB-ADR_MODBUS_TABLE+i].all = elementData.all;
		//		modbus_table_rs_in[Address_MB-ADR_MODBUS_TABLE+i].byte.HB=RS232_Arr->RS_Header[3+i*2];
		//		modbus_table_rs_in[Address_MB-ADR_MODBUS_TABLE+i].byte.LB=RS232_Arr->RS_Header[3+i*2+1];
				//Commented, because of out table can be rewrited before new value had been sent to SVO
				modbus_table_rs_out[Address_MB-ADR_MODBUS_TABLE+i].all = modbus_table_rs_in[Address_MB-ADR_MODBUS_TABLE+i].all;
	}
	
	
    RS_SetControllerLeading(RS232_Arr,false);
    RS_SetAdrAnswerController(RS232_Arr, 0);
	err_modbus3=0;
	cmd_3_or_16=1;
	flag_received_first_mess_from_MPU=1;
	return;
}

void ReceiveAnswerCommandModbus16(RS_DATA_STRUCT *RS232_Arr)
{
	// КонтрольнаЯ сумма
	//unsigned int crc, Address_MB, Length_MB, Bytecnt_MB/*, i, Data1,Data2*/;
	//int Data, digital, ust_I, ust_Time;

/* получили начальный адрес чтениЯ. */
	//Address_MB = RS232_Arr->RS_Header[3] | ( RS232_Arr->RS_Header[2] << 8);

/* получили количество слов данных */
	//Length_MB = (RS232_Arr->RS_Header[4] << 8 ) | RS232_Arr->RS_Header[5];
	
	//Bytecnt_MB = RS232_Arr->RS_Header[6];

    RS_SetAdrAnswerController(RS232_Arr,0);
    RS_SetControllerLeading(RS232_Arr,false);
	err_modbus16 = 0;
	cmd_3_or_16 = 0;
	flag_received_first_mess_from_MPU=1;
	return;
}




