//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU 16000000UL
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <Arduino.h>
#include "IdiBusSerialLine.h"
#include "IDIBUS_4DC.h"
#include "IDIBUS_4ADC.h"
#include "IDIBUS_4CNT.h"
#include "IDIBUS_1Wire.h"
#include "IDIBUS_3Thermo1HT.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//IDIBUS MASTER V0.26 beta

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSerialLine Serial_Line0;
IdiBusSerialLine Serial_Line1;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup()
{
 delay(50);		//	Power on delay for external periphery
 
 //Arduino Variant
 IDIBUS_SERIAL_INIT_TYPEDEF L0Init;
 L0Init.USART_NUMBER  = IDIBUS_SERIAL_USART2;	//	select USART
 L0Init.TIMER_NUMBER  = IDIBUS_TIMER_1;			//	select timer 
 L0Init.CONFIG        = IDIBUS_SERIAL_8N2;		//	8 bit, 2 stop
 L0Init.RS485_DIR_PIN         = 6;				//	direction pin in-out
 L0Init.BAUDRATE_DIPSW_S0_PIN = 9;				//	speed selector pins
 L0Init.BAUDRATE_DIPSW_S1_PIN = 8;
 L0Init.BAUDRATE_DIPSW_S2_PIN = 7;
 Serial_Line0.Init(&L0Init);					//	Init line with with config above	
 Serial_Line0.UpdateBaudrateFromDipSwitch();	//	speed setup
 Serial_Line0.Start();							//	run!
 
 // Standard pinout variant
 IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF L1Init;
 L1Init.USART_NUMBER  = IDIBUS_SERIAL_USART1;
 L1Init.TIMER_NUMBER  = IDIBUS_TIMER_3;
 L1Init.CONFIG        = IDIBUS_SERIAL_8N2;
 L1Init.RS485_DIR_GPIO.PORT       = &PORTL;
 L1Init.RS485_DIR_GPIO.PIN_NUM    = 6;
 L1Init.BAUDRATE_DIPSW.S0.PORT    = &PORTD;
 L1Init.BAUDRATE_DIPSW.S0.PIN_NUM = 1;
 L1Init.BAUDRATE_DIPSW.S1.PORT    = &PORTD;
 L1Init.BAUDRATE_DIPSW.S1.PIN_NUM = 0;
 L1Init.BAUDRATE_DIPSW.S2.PORT    = &PORTL;
 L1Init.BAUDRATE_DIPSW.S2.PIN_NUM = 7;
 Serial_Line1.Init(&L1Init);
 Serial_Line1.UpdateBaudrateFromDipSwitch();
 Serial_Line1.Start();
 
 Serial.begin(19200,SERIAL_8N2);	//	usart0 for debug
 
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 //	Enable power out 24V on main board (to slaves)
 #define BAUD 16000000UL/16/250000UL-1		// BAUD speed = 250000 bod	
 UBRR3 = (uint16_t)(BAUD);			//	USART BAUD RATE INIT
 UCSR3B = (1<<RXEN3)|(1<<TXEN3);	//	USART ENABLE TX RX
 while (!(UCSR3A & (1<<UDRE3)));	//	wait for send
 UDR3 = 'R';						//	send 'R'
 while (!(UCSR3A & (1<<UDRE3)));	//	wait for send
 UDR3 = '+';						//  send '+'
 delay(500);						//	Power on delay for external periphery
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
volatile uint8_t ErrorCode[10];		//	buffer for error codes
IdiBusLongOpData LopData;			//	Long operation data (not used in current example)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void loop()
{
	//IdiBus_4ADC			IDB4ADC(&Serial_Line0, 16+0);		//	Create ADC module object with slave Address=16
	//IdiBus_4CNT			IDB4CNT(&Serial_Line0, 16+1);		//	Create counter module object with slave Address=17
	//IdiBus_1Wire		IDB1Wire(&Serial_Line0, 16+2);		//	Create 1Wire module object with slave Address=18
	IdiBus_3Thermo1HT	IDB3TH1HT (&Serial_Line0, 16+4);	//	Create 3ThermoCouple+1Heater module object with slave Address=20

	//	Init Modules (send c_Init command)
	//ErrorCode[0] = IDB4ADC.c_Init();	
	//ErrorCode[1] = IDB4CNT.c_Init();
	//ErrorCode[2] = IDB1Wire.c_Init();
	ErrorCode[3] = IDB3TH1HT.c_Init();

	Serial.write("Init Module IDB4ADC ErrorCode[0]=");Serial.write('0'+ErrorCode[0]);Serial.write('\n');	//	0 - ok
	Serial.write("Init Module IDB4CNT ErrorCode[1]=");Serial.write('0'+ErrorCode[1]);Serial.write('\n');
	Serial.write("Init Module IDB1Wire ErrorCode[2]=");Serial.write('0'+ErrorCode[2]);Serial.write('\n');
	Serial.write("Init Module IDB3THHT ErrorCode[3]=");Serial.write('0'+ErrorCode[3]);Serial.write('\n');

	delay(1000);			//Wait to startup modules
	IDB4ADC.initAllChs();	//	Channels Init
	IDB4CNT.initAllChs();
	//1Wire module doesn't reqire channels initialization
	//3TH1HT module doesn't reqire channels initialization
	
	uint16_t value;			//	temporary vars
	uint32_t counts;
	int16_t temperature;
	bool GROUP_READ=false;	//	group/single read
 while (1)
	{	//	read all data
	Serial.write("Baud:");			//Print current master speed
	uint32_t baudSpeed = Serial_Line0.GetBaudrate();
	Serial.write('0' + baudSpeed/1000000%10);
	Serial.write('0' + baudSpeed/100000%10);
	Serial.write('0' + baudSpeed/10000%10);
	Serial.write('0' + baudSpeed/1000%10);
	Serial.write('0' + baudSpeed/100%10);
	Serial.write('0' + baudSpeed/10%10);
	Serial.write('0' + baudSpeed/1%10);
	Serial.write(";\n");
	
	if (GROUP_READ) IDB4ADC.getAllAdcVoltage();		//	read ADC voltage, all channels, [mV]
	Serial.write("       ADC : ");
	for (int ch_num = 0; ch_num < IDIBUS_4ADC_CH_COUNT; ch_num++)
		{
		if (!GROUP_READ) ErrorCode[2] = IDB4ADC.getChVoltage(ch_num);	//	read ADC voltage, single channel, [mV]
		//	write for debug to USATR0
		if ( (ErrorCode[2] == IDIER_NOPE && !GROUP_READ)	/* Check error code for single channel read	*/ \
			|| IDB4ADC.getChData(ch_num).MMES_Error == IDIER_NOPE /**Check error code for group channel read*/)
			{	//	OK, write for debug to USATR0
			value = IDB4ADC.getChData(ch_num).Voltage;
			//	convert to ASCII ch_num=xx.xxx
			Serial.write('0'+ch_num);
			Serial.write("=");
			Serial.write('0'+(value/10000)%10);
			Serial.write('0'+(value/1000)%10);
			Serial.write(".");
			Serial.write('0'+(value/100)%10);
			Serial.write('0'+(value/10)%10);
			Serial.write('0'+value%10);
			Serial.write(' ');
			} else
			{	//	ERROR
			Serial.write('0'+ch_num);
			Serial.write("=ERR ");
			Serial.write('0'+IDB4ADC.getChData(ch_num).MMES_Error);
			Serial.write(" ; ");
			}
		}
	Serial.write('\n');		//	Send new line char to serial

	if (GROUP_READ) IDB4CNT.getAllChsCounts();		//	read CNT counts, all channels
	Serial.write("       CNT : ");
	for (int ch_num = 0; ch_num < IDIBUS_4CNT_CH_COUNT; ch_num++)
		{
		if (!GROUP_READ) ErrorCode[3] = IDB4CNT.getChCounts(ch_num);	//	read CNT count, single channel, you can check ErrorCode[3]	
																		//	or IDB4CNT.getChData(CH_number).MMES_Error for group read
		if ( (ErrorCode[3] == IDIER_NOPE && !GROUP_READ)	/* Check error code for single channel read	*/ \
			|| IDB4CNT.getChData(ch_num).MMES_Error == IDIER_NOPE /**Check error code for group channel read*/)
			{counts = IDB4CNT.getChData(ch_num).Counter;
			Serial.write('C');
			Serial.write('1'+ch_num);
			Serial.write(':');
			Serial.write('0'+(counts/100)%10);
			Serial.write('0'+(counts/10)%10);
			Serial.write('0'+ counts%10);
			Serial.write(' ');
			}
		else
			{
			Serial.write('C');
			Serial.write('1'+ch_num);
			Serial.write(": ERR ");
	
			}
		}
	Serial.write('\n');		//	Send new line char to serial

	if (GROUP_READ) IDB1Wire.getAllChTemperature();		//	read CNT counts, all channels
	Serial.write("      1WIRE : ");
	for (int ch_num = 0; ch_num < IDIBUS_1Wire_CH_COUNT; ch_num++)
	{
		if (!GROUP_READ) ErrorCode[3] = IDB1Wire.getTemperature(ch_num);	//	read CNT count, single channel, you can check ErrorCode[3]	
		else ErrorCode[3] = IDB1Wire.getChData(ch_num).MMES_Error; 			//	or IDB4CNT.getChData(CH_number).MMES_Error for group read
		if ( ErrorCode[3] == IDIER_NOPE )	// Check error code for single channel read	 
			{temperature = IDB1Wire.getChData(ch_num).Temperature;
			Serial.write('T');
			Serial.write('1'+ch_num);
			Serial.write(':');
			if (temperature>0) Serial.write('+');  
			else Serial.write('-');
			Serial.write('0'+(temperature/1000)%10);
			Serial.write('0'+(temperature/100)%10);
			Serial.write('.');
			Serial.write('0'+(temperature/10)%10);
			Serial.write('0'+(temperature)%10);
			Serial.write(' ');
			}
		else
		{
			Serial.write('T');
			Serial.write('1'+ch_num);
			if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_CRC_ERROR) Serial.write(": ERR-CRC ");
			else if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_NO_DATA) Serial.write(": ERR-DAT ");
			else if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_NO_SENSOR) Serial.write(": ERR-SEN ");
			else {
				Serial.write(": ERR_");	
				Serial.write('0'+(ErrorCode[3]/100)%10);	
				Serial.write('0'+(ErrorCode[3]/10)%10);	
				Serial.write('0'+(ErrorCode[3]/1)%10);	
				Serial.write(" ");
			}
		}
	}
	Serial.write('\n');		//	Send new line char to serial

	if (GROUP_READ) IDB3TH1HT.THERMO_DEV.getAllChTemperature();		//	read CNT counts, all channels
	Serial.write("     3TH1HT : ");
	for (int ch_num = 0; ch_num < IDIBUS_3Thermo1HT_Thermo_CH_COUNT; ch_num++)
	{
		if (!GROUP_READ) ErrorCode[3] = IDB3TH1HT.THERMO_DEV.getTemperature(ch_num);	//	read CNT count, single channel, you can check ErrorCode[3]	
		else ErrorCode[3] = IDB3TH1HT.THERMO_DEV.getChData(ch_num).MMES_Error; 			//	or IDB4CNT.getChData(CH_number).MMES_Error for group read

		if ( ErrorCode[3] == IDIER_NOPE )	// Check error code for single channel read	 
			{temperature = IDB3TH1HT.THERMO_DEV.getChData(ch_num).Temperature>>7;
			Serial.write('T');
			Serial.write('1'+ch_num);
			Serial.write(':');
			if (temperature>0) Serial.write('+');  
			else Serial.write('-');
			Serial.write('0'+(temperature/1000)%10);
			Serial.write('0'+(temperature/100)%10);
			Serial.write('0'+(temperature/10)%10);
			Serial.write('0'+(temperature)%10);
			Serial.write(' ');
			}
		else  {
			Serial.write('T');
			Serial.write('1'+ch_num);
			if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_THERMO_CHANNEL_NO_DATA) Serial.write(": ERR-nDATA ");
			else if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_THERMO_CHANNEL_NO_SENSOR) Serial.write(": ERR-nSENS ");
			else if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_THERMO_CHANNEL_CJ_OUT_OF_RANGE) Serial.write(": ERR-CJOoR ");
			else if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_THERMO_CHANNEL_TC_OUT_OF_RANGE) Serial.write(": ERR-TCOoR ");
			else if (ErrorCode[3] == IDIBUS_CUSTDEF_ERCODE_THERMO_CHANNEL_OVER_UNDER_VOLTAGE) Serial.write(": ERR-O/U V ");
			else {
				Serial.write(": ERR_");	
				Serial.write('0'+(ErrorCode[3]/100)%10);	
				Serial.write('0'+(ErrorCode[3]/10)%10);	
				Serial.write('0'+(ErrorCode[3]/1)%10);	
				Serial.write("   ");
			}
		}
	}
	Serial.write('\n');		//	Send new line char to serial

	Serial_Line0.UpdateBaudrateFromDipSwitch();	// Update master speed (DEBUG only)	
	delay(100);			
	}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 /*
 Egor code for loop function
  
    IdiBus_4DC IDB4DC(&Serial_Line1, 122);

 //ErrorCode = IDB4DC.c_Init(10);
 ErrorCode = IDB4DC.c_Init();
 delay(1000);
 ErrorCode = IDB4DC.c_AssignGroup(IDIBUS_PSU_CNTRL_DEV, 0, 10);
 ErrorCode = IDB4DC.c_AssignGroup(IDIBUS_PSU_CNTRL_DEV, 2, 10);
 
 uint8_t TxData;
 IdiBusMMESG Group1(IDIBUS_GROUP_10_ADDR, &TxData, 1);
 Group1.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_STATE;
 
 while (1)
	{
	 Serial.write((uint8_t*)"echo", sizeof("echo")-1);
	 
	 TxData = 0;
	 Serial_Line1.sendMMESG(&Group1);
	 delay(2000);
	 TxData = 1;
	 Serial_Line1.sendMMESG(&Group1);
	 delay(2000);
	}*/
/* 
 ErrorCode[0] = IDB4DC.c_Init();
 delay(1000);
 ErrorCode[1] = IDB4DC.c_WriteSnIPv4IPv6(0xAABBCCDD, 0xA1A2A3A4, 0xA5A6A7A8, 0xB1B2B3B4, 0xB5B6B7B8);
 do { ErrorCode[2] = IDB4DC.c_CheckModuleLongOp(); }
 while ( (LopData = IDB4DC.getModuleLongOpData()).State == IDILONGOP_STATE_IN_PROC );
 
 ErrorCode[3] = IDB4DC.INPV_DEV.getInputVoltage();
 INPV_Data = IDB4DC.INPV_DEV.getChData();
 
 IDB4DC.PSUC_DEV.setAllChVoltage(5000, 6000, 7000, 8000);
 IDB4DC.PSUC_DEV.setAllChState(1);
  while (1)
	{
	 IDB4DC.PSUC_DEV.setAllChState(0, 1, 0, 1);
	 delay(2000);
	 IDB4DC.PSUC_DEV.setAllChState(1, 0, 1, 0);
	 delay(2000);
	}
*/
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------