#include <modbus_hmi.h>

#include "control_station.h"
#include "modbus_table_v2.h"
#include "options_table.h"
#include "RS_modbus_pult.h"
#include "DSP281x_Device.h"
#include "CRC_Functions.h"
#include "RS_Functions.h"
#include "RS_modbus_svu.h"



//#pragma DATA_SECTION(p_analog_data_in, ".logs");
MODBUS_REG_STRUCT *p_analog_data_in;

//#pragma DATA_SECTION(p_analog_data_out, ".logs");
MODBUS_REG_STRUCT *p_analog_data_out;

//#pragma DATA_SECTION(p_discrete_data_out, ".logs");
MODBUS_REG_STRUCT *p_discrete_data_out;

//#pragma DATA_SECTION(p_discrete_data_in, ".logs");
MODBUS_REG_STRUCT *p_discrete_data_in;

static int adres_wait_answer_cmd1 = 0;
static int count_registers_wait_answer = 0;

void ModbusRTUsetDataArrays(MODBUS_REG_STRUCT *array_in, MODBUS_REG_STRUCT *array_out)
{
	p_analog_data_in = array_in;
	p_analog_data_out = array_out;
}

void ModbusRTUsetDiscretDataArray(MODBUS_REG_STRUCT *discrete_in, MODBUS_REG_STRUCT *discrete_out)
{
	p_discrete_data_in = discrete_in;
	p_discrete_data_out = discrete_out;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************/
/***************************************************************/
/*  Отправка запроса данных по протоколу ModBus - команда 1
    Чтение Ячеек данных Digital Output Holding Registers   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend1(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start, unsigned int count_bits)
{
	// КонтрольнаЯ сумма
	unsigned int crc;
	unsigned int count_data_bytes;

	count_data_bytes = (count_bits % 8) == 0 ? count_bits / 8 : count_bits / 8 + 1;

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

	crc = 0xffff;
	crc = GetCRC16_IBM(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_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;

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


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

		RS_Len[CMD_RS232_MODBUS_1] = 5 + count_data_bytes;
		count_registers_wait_answer = count_bits;
		adres_wait_answer_cmd1 = adr_start;
		RS_SetControllerLeading(rs_arr, true);
		RS_SetAdrAnswerController(rs_arr, adr_contr);
	}

	return;
}

/***************************************************************/
/***************************************************************/
/*  Ответ с данными по протоколу ModBus - команда 1
    Чтение Ячеек данных Digital Output Holding Registers   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceiveAnswer1(RS_DATA_STRUCT *RS232_Arr)
{
	unsigned int first_word, end_byte_number, count_data_bytes, current_register, last_register;
	unsigned int displacement_start, displacement, displacement_end, bits_in_last_byte, byte, mask = 0, mask_start, mask_end;
	unsigned int i = 0, b = 0, buffer_position = 0, j = 0;
//	unsigned char byte_buffer[SIZE_MODBUS_TABLE_DISCRET * 2];

	/* получили начальный адрес чтениЯ. */
	first_word = (adres_wait_answer_cmd1 % 16 == 0) && (adres_wait_answer_cmd1 != 0)
												 ? adres_wait_answer_cmd1 / 16 + 1
												 : adres_wait_answer_cmd1 / 16;
	displacement_start = adres_wait_answer_cmd1 % 16;
	displacement = adres_wait_answer_cmd1 % 16;
	count_data_bytes = RS232_Arr->RS_Header[2];
	current_register = adres_wait_answer_cmd1;
	last_register = adres_wait_answer_cmd1 + count_registers_wait_answer;
	displacement_end = last_register % 16;
	/////////////////////////////////////////////////

	mask = 0;
	mask_start = 0;
	mask_end = 0;
	for (i = 0; i < displacement_start; ++i)
	{
		mask_start |= 1 << i;
		mask_end |= 1 << i;
	}
	mask_start = ~mask_start;
	displacement = displacement_start;
	for (i = 0; i < count_data_bytes; ++i)
	{
		byte = RS232_Arr->RS_Header[3 + i];
		mask = 0;
		if ((last_register - current_register) > 8) {
			mask = 0xFF;
		} else {
			for (j = 0; j < (last_register - current_register); ++j) {
				mask |= 1 << j;
			}
		}
		if (displacement < 8)
		{
			//mask = mask << displacement;
			p_discrete_data_out[first_word].all &= ~(mask << displacement);
			p_discrete_data_out[first_word].all |= (byte & mask) << displacement;
		} else {
			mask_start = (mask << displacement) & 0xFF00;
			p_discrete_data_out[first_word].all &= ~mask_start;
			p_discrete_data_out[first_word].all |= (byte & mask) << displacement;
			mask_end = (mask >> (16 - displacement)) & 0xFF;
			p_discrete_data_out[first_word].all &= ~mask_end;
			p_discrete_data_out[first_word + 1].all |= (byte & mask) >> (16 - displacement);
		}
		
		
		displacement += 8;
		if (displacement >= 16) {
			displacement -= 16;
			first_word += 1;
		}
		current_register += 8;
		
	}
	
	RS_SetControllerLeading(RS232_Arr, false);
	RS_SetAdrAnswerController(RS232_Arr, 0);
	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

/***************************************************************/
/***************************************************************/
/*  Запрос данных от мастера по протоколу ModBus - команда 3
    Чтение Ячеек данных Analog Input Registers		    		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceive3(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] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB;
//			RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB;
            RS232_Arr->buffer[3 + i * 2] = p_analog_data_out[Address_MB + i].byte.HB;
            RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB + 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;
//    RS232_Arr->RS_DataWillSend = 1;
	RS_Send(RS232_Arr, RS232_Arr->buffer, Length_MB * 2 + 7);

	return;
}

/***************************************************************/
/***************************************************************/
/*  Отправка запроса данных по протоколу ModBus - команда 3
    Чтение Ячеек данных Analog Input Registers			 		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend3(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] = 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);

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

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

	rs_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;

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

	/* ждем ответа     */
	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;
}

/***************************************************************/
/***************************************************************/
/*  Ответ с данными по протоколу ModBus - команда 3
    Чтение Ячеек данных Analog Input Registers			   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceiveAnswer3(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];
//		p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].all = elementData.all;
		if ((Address_MB + i)<SIZE_MODBUS_ANALOG_REMOUTE)  // защита от переполнения
		    p_analog_data_out[Address_MB + i].all = elementData.all;

	}

	RS_SetControllerLeading(RS232_Arr, false);
	RS_SetAdrAnswerController(RS232_Arr, 0);

	err_modbus3 = 0;
	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

/***************************************************************/
/***************************************************************/
/*  Отправка запроса данных по протоколу ModBus - команда 4
    Чтение Ячеек данных Analog Output Holding Registers   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend4(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] = LOBYTE(adr_contr);
	rs_arr->buffer[1] = CMD_RS232_MODBUS_4;
	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);

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

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

	rs_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;

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

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

		RS_Len[CMD_RS232_MODBUS_4] = 5 + count_word * 2;

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

	return;
}

/***************************************************************/
/***************************************************************/
/*  Ответ с данными по протоколу ModBus - команда 4
    Чтение Ячеек данных Analog Output Holding Registers   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceiveAnswer4(RS_DATA_STRUCT *RS232_Arr)
{
	unsigned int Address_MB, Length_MB, i;
	static unsigned int prev_Address_MB = 0;

	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];
//		p_analog_data_in[Address_MB - ADR_MODBUS_TABLE + i].all = elementData.all;
		if ((Address_MB + i)<SIZE_MODBUS_ANALOG_REMOUTE)  // защита от переполнения
		    p_analog_data_in[Address_MB + i].all = elementData.all;

	}

	RS_SetControllerLeading(RS232_Arr, false);
	RS_SetAdrAnswerController(RS232_Arr, 0);

	if (Address_MB == 0 && prev_Address_MB != 0)
	    RS232_Arr->RS_DataReadyFullUpdate = 1;

	prev_Address_MB = Address_MB;

	return;
}

/***************************************************************/
/***************************************************************/
/*  Запрос данных от мастера по протоколу ModBus - команда 4
    Чтение Ячеек данных Analog Output Holding Registers	   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceive4(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_4;
	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] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB;
//			RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB;
            RS232_Arr->buffer[3 + i * 2] = p_analog_data_out[Address_MB  + i].byte.HB;
            RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB + 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;
//	RS232_Arr->RS_DataWillSend = 1;
	RS_Send(RS232_Arr, RS232_Arr->buffer, Length_MB * 2 + 7);

	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

/***************************************************************/
/***************************************************************/
/*  Отправка запроса данных по протоколу ModBus - команда 5
    Чтение Ячеек данных Analog Output Holding Registers   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend5(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start)
{
	// КонтрольнаЯ сумма
	unsigned int crc;
	unsigned int byte_number;
	unsigned int bit_number;
	byte_number = adr_start / 16;
	bit_number = adr_start % 16;


	rs_arr->buffer[0] = LOBYTE(adr_contr);
	rs_arr->buffer[1] = CMD_RS232_MODBUS_5;
	rs_arr->buffer[2] = HIBYTE(adr_start);
	rs_arr->buffer[3] = LOBYTE(adr_start);
	if ((p_discrete_data_out[byte_number].all >> bit_number) & 1) {
		rs_arr->buffer[4] = 0xFF;
		rs_arr->buffer[5] = 0;
	} else {
		rs_arr->buffer[4] = 0;
		rs_arr->buffer[5] = 0;
	}
	crc = 0xffff;
	crc = GetCRC16_IBM(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_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;
	RS_Send(rs_arr, rs_arr->buffer, 10);

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

		RS_Len[CMD_RS232_MODBUS_5] = 8;

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

	return;
}

/****************************************************************/
/****************************************************************/
/*  Ответ с данными по протоколу ModBus - команда 5
    Запись Ячееки данных Digital Output Holding Registers   		*/
/****************************************************************/
/****************************************************************/
void ModbusRTUreceiveAnswer5(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;

	RS_SetControllerLeading(RS232_Arr, false);
	RS_SetAdrAnswerController(RS232_Arr, 0);

	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

/***************************************************************/
/***************************************************************/
/*  Отправка запроса данных по протоколу ModBus - команда 6
    запись Ячееки данных Analog Output Holding Registers   		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend6(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start)
{
	// КонтрольнаЯ сумма
	unsigned int crc; //, Address_MB, Length_MB, i, Data;
					  //	int buf_out[200];
					  //	int buf_in[200];

	rs_arr->buffer[0] = LOBYTE(adr_contr);
	rs_arr->buffer[1] = CMD_RS232_MODBUS_6;
	rs_arr->buffer[2] = HIBYTE(adr_start);
	rs_arr->buffer[3] = LOBYTE(adr_start);
	rs_arr->buffer[4] = HIBYTE(p_analog_data_out[adr_start].all);
	rs_arr->buffer[5] = LOBYTE(p_analog_data_out[adr_start].all);

	crc = 0xffff;
	crc = GetCRC16_IBM(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_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;

	RS_Send(rs_arr, rs_arr->buffer, 10);
//	control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;
	/* ждем ответа     */
	if (adr_contr > 0 && adr_contr < 0xff)
	{

		RS_Len[CMD_RS232_MODBUS_6] = 8;

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

	return;
}

/****************************************************************/
/****************************************************************/
/*  Ответ с данными по протоколу ModBus - команда 6
    Чтение Ячеек данных Analog Output Holding Registers   		*/
/****************************************************************/
/****************************************************************/
void ModbusRTUreceiveAnswer6(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;

	RS_SetControllerLeading(RS232_Arr, false);
	RS_SetAdrAnswerController(RS232_Arr, 0);

	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

/***************************************************************/
/***************************************************************/
/*  Отправка запроса данных по протоколу ModBus - команда 15
    Запись дискретных данных данных Discrete Output Coils  		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend15(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start, unsigned int count_bits)
{
	// КонтрольнаЯ сумма
	unsigned int crc;
	unsigned int start_byte_number, end_byte_number, count_data_bytes;
	unsigned int displacement_start, bits_in_last_byte, mask_start, mask_end;
	unsigned int i = 0;

//	char byte_buffer[SIZE_MODBUS_TABLE_DISCRET * 2];

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

	start_byte_number = adr_start / 8;
	end_byte_number = (adr_start + (count_bits - 1)) / 8;
	count_data_bytes = (count_bits % 8) == 0 ? count_bits / 8 
											: count_bits / 8 + 1;
	rs_arr->buffer[6] = count_data_bytes;
	
	displacement_start = adr_start % 8;
	bits_in_last_byte = count_bits % 8;
	if (bits_in_last_byte == 0) { bits_in_last_byte = 0xFF; }
	
	mask_start = 0;
	for(i = 0; (i < (8 - displacement_start)) && (i < 8); i++) {
		mask_start |= (1 << (7 - i));
	}

	mask_end = 0;
	for(i = 0; (i < bits_in_last_byte) && (i < 8); i++) {
		mask_end |= (1 << i);
	}

	for (i = 0; i < count_data_bytes; i++)
	{
		if (i < count_data_bytes - 1) {
			rs_arr->buffer[7 + i] = 0;
			if (((i + start_byte_number) & 1) == 0)
			{
				rs_arr->buffer[7 + i] |= 
					(p_discrete_data_out[(i + start_byte_number) / 2].all >> displacement_start) & 0xFF;
			}
			if (((i + start_byte_number) & 1) == 1)
			{
				rs_arr->buffer[7 + i] |= 
					(((p_discrete_data_out[(i + start_byte_number) / 2].all >> 8) & mask_start) >> displacement_start);
				rs_arr->buffer[7 + i] |= 
					(((p_discrete_data_out[(i + start_byte_number) / 2 + 1].all) & ~mask_start) << (8 - displacement_start));
			}
		} else {
			rs_arr->buffer[7 + i] = 0;
			if (((i + start_byte_number) & 1) == 0)
			{
				rs_arr->buffer[7 + i] |= 
					((p_discrete_data_out[(i + start_byte_number) / 2].all) >> displacement_start) & mask_end;
			}
			if (((i + start_byte_number) & 1) == 1)
			{
				rs_arr->buffer[7 + i] |= 
					(((p_discrete_data_out[(i + start_byte_number) / 2].all >> 8) & mask_start) >> displacement_start);
				rs_arr->buffer[7 + i] |= 
					(((p_discrete_data_out[(i + start_byte_number) / 2 + 1].all) & ~mask_start) << (8 - displacement_start)) & mask_end;
			}
		}
	}

	crc = 0xffff;
	crc = GetCRC16_IBM(crc, rs_arr->buffer, count_data_bytes + 7);
	rs_arr->buffer[count_data_bytes + 7] = LOBYTE(crc);
	rs_arr->buffer[count_data_bytes + 8] = HIBYTE(crc);

	rs_arr->buffer[count_data_bytes + 9] = 0;
	rs_arr->buffer[count_data_bytes + 10] = 0;

	rs_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;

//	RS_Send(rs_arr, rs_arr->buffer, (count_data_bytes + 10 + 2));
    RS_Send(rs_arr, rs_arr->buffer, (count_data_bytes + 10));
//	control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;
	/* ждем ответа     */
	if (adr_contr > 0 && adr_contr < 0xff)
	{
		RS_Len[CMD_RS232_MODBUS_15] = 8;
		RS_SetControllerLeading(rs_arr, true);
		RS_SetAdrAnswerController(rs_arr, adr_contr);
	}

	return;
}

/***************************************************************/
/***************************************************************/
/***************************************************************/
/*  Ответ на передачу данных по протоколу ModBus - команда 15
    Запись дискретных данных Discrete Output Coils		   		*/
/***************************************************************/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceiveAnswer15(RS_DATA_STRUCT *RS232_Arr)
{
	RS_SetAdrAnswerController(RS232_Arr, 0);
	RS_SetControllerLeading(RS232_Arr, false);

}

/***************************************************************/
/***************************************************************/
/*  Получение данных от мастера по протоколу ModBus - команда 15
    Запись дискретных данных данных Discrete Output Coils  		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceive15(RS_DATA_STRUCT *RS232_Arr)
{
	// Контрольнаy сумма
	unsigned int crc, register_address, array_address, length, byte_count, quantity;
	unsigned int d_word, mask_start, mask_end;
	unsigned int i1, i2, i;
	unsigned int word_number, displacement_start, displacement_end;

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

	/* получили количество байт данных   */
	byte_count = RS232_Arr->RS_Header[6];

	length = (byte_count & 0x1) ? (byte_count >> 1) + 1 : (byte_count >> 1);

	word_number = register_address / 16;
	displacement_end = register_address % 16;
	displacement_start = 16 - displacement_end;
	mask_start = 0;
	for(i = 0; (i < displacement_end) && (i < 15); i++) {
		mask_start |= (1 << i);
	}
	mask_end = 0;
	for(i = 0; (i < displacement_start) && (i < 15); i++) {
		mask_end |= (1 << (15 - i));
	}
	for (i = 0; i < length; i++)
	{
//		if (register_address >= ADR_MODBUS_TABLE && Address_MB < 0xe00)
		if (register_address < 0xe00)
		{
			d_word = (RS232_Arr->buffer[7 + i * 2] << 8) | RS232_Arr->RS_Header[7 + i * 2 + 1];
			p_discrete_data_out[array_address + i].all &= mask_start;
			p_discrete_data_out[array_address + i].all |= (d_word >> displacement_start) | mask_start;
			if(i < length - 1) {
				p_discrete_data_out[array_address + i].all &= mask_end;
				p_discrete_data_out[array_address + i].all |= (d_word << displacement_end) | mask_end;
			}
		}
	}

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

	RS232_Arr->buffer[0] = RS232_Arr->addr_recive;
	RS232_Arr->buffer[1] = CMD_RS232_MODBUS_15;
	RS232_Arr->buffer[2] = HIBYTE(register_address);
	RS232_Arr->buffer[3] = LOBYTE(register_address);
	RS232_Arr->buffer[4] = HIBYTE(quantity);
	RS232_Arr->buffer[5] = LOBYTE(quantity);

	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;
//	RS232_Arr->RS_DataWillSend = 1;
	RS_Send(RS232_Arr, RS232_Arr->buffer, 10);

	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

/***************************************************************/
/***************************************************************/
/***************************************************************/
/*  Передача данных по протоколу ModBus - команда 16
    Передача данных    		*/
/***************************************************************/
/***************************************************************/
/***************************************************************/
void ModbusRTUsend16(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] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB;
//		rs_arr->buffer[7 + i * 2 + 1] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB;
        rs_arr->buffer[7 + i * 2] = p_analog_data_out[Address_MB + i].byte.HB;
        rs_arr->buffer[7 + i * 2 + 1] = p_analog_data_out[Address_MB + i].byte.LB;
	}

	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_arr->RS_DataWillSend = 1;
	rs_arr->RS_DataWillSend2 = 1;

	RS_Send(rs_arr, rs_arr->buffer, (count_word * 2 + 10));
//	control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] = 1;

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

/***************************************************************/
/***************************************************************/
/*  Получение данных от мастера по протоколу ModBus - команда 16
    Передача данных    		*/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceive16(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)
		{
//			p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB = RS232_Arr->buffer[3 + i * 2];
//			p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB = RS232_Arr->buffer[3 + i * 2 + 1];
            p_analog_data_out[Address_MB + i].byte.HB = RS232_Arr->buffer[3 + i * 2];
            p_analog_data_out[Address_MB + i].byte.LB = RS232_Arr->buffer[3 + i * 2 + 1];
		}

		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;
//	RS232_Arr->RS_DataWillSend = 1;
	RS_Send(RS232_Arr, RS232_Arr->buffer, 10);

	return;
}

/***************************************************************/
/***************************************************************/
/***************************************************************/
/*  Ответ на передачу данных по протоколу ModBus - команда 16
    Передача данных    		*/
/***************************************************************/
/***************************************************************/
/***************************************************************/
void ModbusRTUreceiveAnswer16(RS_DATA_STRUCT *RS232_Arr)
{
	// КонтрольнаЯ сумма
	unsigned int Address_MB;	//, crc, 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);
//	if (Address_MB == ADRES_LOG_REGISTERS) {
//	}
	err_send_log_16 = 0;

	/* получили количество слов данных */
	//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;
	return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
