//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#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_2SALTMETER.h"
#include "IDIBUS_3Thermo1HT.h"
#include "IDIBUS_Speedster.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(115200,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
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

uint8_t				Wire1Count = 0;
uint8_t				Th3Count = 0;
uint8_t				Salt2Count = 0;
const uint8_t		MaxCount = 6;

IdiBus_1Wire		IDB1WIRE[MaxCount];
IdiBus_3Thermo1HT	IDB3TH[MaxCount];
IdiBus_2SALT		IDBSALT[MaxCount];

void FindModules();

void SendRequest();

void GetData();

void loop()
{
	if(Serial.available() == 0) return; 
	
	String cmd = Serial.readString();

	if (cmd == "s\n") {
		FindModules();
	} else if (cmd == "r\n") {
		SendRequest();
	} else if (cmd == "d\n") {
		GetData();
	} else {
		Serial.print("e\n");
	} 
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void FindModules() {
	IdiBusSlave idbSlave(&Serial_Line1,128);

	Wire1Count = 0;
	Th3Count = 0;
	Salt2Count = 0;
	
	for (uint8_t i = 32; i < 127; i++) {
		idbSlave.Init(&Serial_Line1,i);
		uint8_t ErrorCode = idbSlave.c_Init();	
		if (ErrorCode != IDIER_NOPE) continue;
		
		delay(500);
		idbSlave.c_ReadDevFullSN_MS();
		switch(idbSlave.getModuleSN().SN.FIX.ModuleType[0]) {
			case '1' : {
				if (Wire1Count == MaxCount) break;
				IDB1WIRE[Wire1Count].Init(&Serial_Line1,i); 
				IDB1WIRE[Wire1Count].startAllOneShotConversions();
				Wire1Count++;
				break;	
			} 
			case 'T' : {
				if (Th3Count == MaxCount) break;
				IDB3TH[Th3Count].Init(&Serial_Line1,i); 
				IDB3TH[Th3Count].THERMO_DEV.startAllOneShotConversions(); 
				Th3Count++;
				break;	
			} 
			case 'S' : {
				if (Salt2Count == MaxCount) break;
				IDBSALT[Salt2Count].Init(&Serial_Line1,i); 
				IDBSALT[Salt2Count].setAllCh(1);
				Salt2Count++;
				break;	
			} 
			default : {
			}
		}
	}
	
	_delay_ms(1500);

	Serial.print("W:");
	Serial.print(Wire1Count);
	Serial.print("\n");
	for(uint8_t i = 0; i < Wire1Count; i++){
		uint8_t chCount = 0;
		IDB1WIRE[i].getAllChTemperature();
		for (uint8_t ch = 0; ch < IDIBUS_1Wire_CH_COUNT; ch++){
			if (IDB1WIRE[i].getChData(ch).MMES_Error == IDIER_NOPE)
				chCount+=(1<<ch);
		}
		Serial.print(IDB1WIRE[i].getAddress());
		Serial.print(":");
		Serial.print(chCount);
		Serial.print("\n");
	}

	Serial.print("T:");
	Serial.print(Th3Count);
	Serial.print("\n");
	for(uint8_t i = 0; i < Th3Count; i++){
		uint8_t chCount = 0;
		IDB3TH[i].THERMO_DEV.getAllChTemperature();
		for (uint8_t ch = 0; ch < IDIBUS_3Thermo1HT_Thermo_CH_COUNT; ch++){
			if (IDB3TH[i].THERMO_DEV.getChData(ch).MMES_Error == IDIER_NOPE)
				chCount+=(1<<ch);
		}
		Serial.print(IDB3TH[i].getAddress());
		Serial.print(":");
		Serial.print(chCount);
		Serial.print("\n");
	}

	Serial.print("S:");
	Serial.print(Salt2Count);
	Serial.print("\n");
	for(uint8_t i = 0; i < Salt2Count; i++){
		Serial.print(IDBSALT[i].getAddress());
		Serial.print(":");
		Serial.print(3);
		Serial.print("\n");
	}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void SendRequest() {
	for (uint8_t i = 0; i < Salt2Count; i++) {
		IDBSALT[i].startAllOneShot();
	}

	for (uint8_t i = 0; i < Wire1Count; i++) {
		IDB1WIRE[i].startAllOneShotConversions();
	}

	for (uint8_t i = 0; i < Th3Count; i++) {
		IDB3TH[i].THERMO_DEV.startAllOneShotConversions();
	}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void GetData() {
	for (uint8_t i = 0; i < Salt2Count; i++) {
		IDBSALT[i].getAllChsSaltData();
		//Serial.print("S;");
		Serial.print(IDBSALT[i].getAddress());
		for (uint8_t ch = 0; ch < IDIBUS_2SALT_CH_COUNT; ch++) {
			Serial.print(";");
			if (IDBSALT[i].getChData(ch).MMES_Error == IDIER_NOPE)
				Serial.print(IDBSALT[i].getChData(ch).Voltage);
			else
				Serial.print("e");
		}
		Serial.print("\n");
	}

	for (uint8_t i = 0; i < Wire1Count; i++) {
		IDB1WIRE[i].getAllChTemperature();
		//Serial.print("W;");
		Serial.print(IDB1WIRE[i].getAddress());
		for (uint8_t ch = 0; ch < IDIBUS_1Wire_CH_COUNT; ch++) {
			Serial.print(";");
			if (IDB1WIRE[i].getChData(ch).MMES_Error == IDIER_NOPE)
				Serial.print(IDB1WIRE[i].getChData(ch).Temperature);
			else
				Serial.print("e");
		}
		Serial.print("\n");
	}

	for (uint8_t i = 0; i < Th3Count; i++) {
		IDB3TH[i].THERMO_DEV.getAllChTemperature();
		//Serial.print("T;");
		Serial.print(IDB3TH[i].getAddress());
		for (uint8_t ch = 0; ch < IDIBUS_3Thermo1HT_Thermo_CH_COUNT; ch++) {
			Serial.print(";");
			if (IDB3TH[i].THERMO_DEV.getChData(ch).MMES_Error == IDIER_NOPE)
				Serial.print(IDB3TH[i].THERMO_DEV.getChData(ch).Temperature);
			else
				Serial.print("e");
		}
		Serial.print("\n");
	}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 /*
 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);
	}
*/
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------