
/******************************************************************************
 *	COMMENTS....
 *****************************************************************************/


#include "serial_deviceMG.h" 

SerialDeviceMG serialSensors;
SerialDeviceMG serialActuators;

SerialDeviceMG::SerialDeviceMG()
{
	SerDevDB.reserve(10);
	FD_ZERO(&rfds);
	maxfd = 0;
	turn = 0;
}


SerialDeviceMG::~SerialDeviceMG()
{
	cout << "serial_deviceMG.cpp : SerialDeviceMG is destructed\n";
}


bool SerialDeviceMG::init()
{
	return false;
}


bool SerialDeviceMG::registerDev(SerialDevice* sDevicePtr)
{
	int type = sDevicePtr->type_();

	if ((type == 0) || (type = 2)) FD_SET(sDevicePtr->handle(), &rfds);  // sensor type
	SerDevDB.push_back(sDevicePtr);
	if (sDevicePtr->handle() > maxfd) maxfd = sDevicePtr->handle();
	return true;
}


void SerialDeviceMG::runSensors()
	// This is where the thread excutes as recieve serial ports [tms, ship, vision, overlay]
{
	int retval = -1;
	extern int serial_port_receive_thread_timer;

	//the select below fires at whatever is coming in on any
	//of the serial ports, as this is indeterminate, it can result
	//in some strange subtle behavior changes depending on what is
	//turned on etc.  We need the select to fire at least once a
	//second or soi so the gui status updates even if all telemetry
	//on serial ports is stopped. Thus I have implemented a timeout
	//on the select. R.Schramm - Oct2012

	struct timeval Timeout;
	while (1) {

		//this must be reset each time thru the select
		Timeout.tv_usec = 0;
		Timeout.tv_sec = 1;
		for (int i = 0; i < SerDevDB.size(); i++)
			FD_SET(SerDevDB[i]->handle(), &rfds);

		//and below you can see the timeout parm in use
		retval = select(maxfd + 1, &rfds, NULL, NULL, &Timeout);
		
		//if (retval == 0) {
		//	fprintf(stderr,"Serial DeviceMG: select timeout\n ");
		//}	
		
		for (int i = 0; i < SerDevDB.size(); i++)
		{
			if (SerDevDB[i]->parse()) {}   // copy RX string into internal buffer
			SerDevDB[i]->setSystemData();  // parses and sets data to our ints and floats
		} 

		// We need this to be taken out for the serial string timers; Dave
		// or do the timers in a different place.  retval blocks.
		// Maybe OK as if nothing received thread not going???
		
		if(serial_port_receive_thread_timer < 100000) serial_port_receive_thread_timer++;	
	} //end while
} //end method


void SerialDeviceMG::runActuate()
	// This is where the thread excutes as transmitt serial ports [logging, vision,
	// depth, rov heading,ship heading]
{
	int count = 0;
	int i = 0;
	pthread_t temp;

	turn = 0;
	// create a queue of workers
	for (int i = 0; i < SerDevDB.size(); i++) {
		cout << "Serial DeviceMG : Creating Serial Port Tx Thread: " << i << endl;
		temp = pthread_create(&workers[i], NULL, send_t, this);
		while (turn == i);
	}
}


void SerialDeviceMG::runTest()
{
	for (int i = 0; i < SerDevDB.size(); i++)
		{
		cout << "=======================\n";
		cout << "name: " << SerDevDB[i]->name() << endl;
		cout << "handle: " << SerDevDB[i]->handle() << endl;
		SerDevDB[i]->parse();
		SerDevDB[i]->setSystemData();
		}
}


void SerialDeviceMG::dump()
{
	for (int i = 0; i < SerDevDB.size(); i++)
		{
		cout << "=======================\n";
		cout << "name: " << SerDevDB[i]->name() << endl;
		cout << "handle: " << SerDevDB[i]->handle() << endl;
		}
}


void *send_t(void *p)
{
	extern int serial_device_transmit_thread_timer;
	SerialDeviceMG* mg = (SerialDeviceMG*)(p);

	int i = mg->turn;	

	mg->turn++;

	while(1) {
		mg->SerDevDB[i]->send();
		if(serial_device_transmit_thread_timer < 100000) serial_device_transmit_thread_timer ++;
		}
	return NULL;
}

