#include <stdio.h>
#include <unistd.h>

#include "../hubolib.h"
#include "../hubocfg.h"

using namespace HuboLib;

/*
Compile and link: 
	g++ SlaveCycleTimeDivider.cpp -L../ -lhubo -lpthread -lrt -o SlaveCycleTimeDivider.out
Run:
	sudo ./SlaveCycleTimeDivider.out
Purpose:
	While the Hubo master module does get updated with the frequency as specified by a call to SetCycleTime()
	Hubo slaves can get updated slower by setting the cycle tick divider to a value greater than 1. 
	By default the cycle tick devider is set to 1 resulting in the same update speed for the slaves.
	Note - while this example only demonstrates the behaviour for the digital outputs - it applies to the
	digital inputs too!
*/

int main(void)
{
	// If required - set the I2C device to work with. The Raspberry Pi uses "/dev/i2c-1" which is default, the Banana Pi uses "/dev/i2c-0"
	#ifdef BPI
	    g_I2CConfig.m_sI2CDevice = "/dev/i2c-0";
	#endif

	// Let slaves update only every 5th call of a cycle tick.
	g_I2CConfig.m_MCP23017SlaveCycleTickDivider  = 5;

	// The slave would follow immediately.
	// g_I2CConfig.m_MCP23017SlaveCycleTickDivider  = 1;
	
	// Initialize the library once in your program.
	if (!Initialize())
	{
		printf ("Error: Initialize\n");
		return 1;
	}

	// Let the master update every 10th second.
	// Therefore the update interval for slaves evaluates to only 2 Hz (divider is set to 5)!
	Set_Cycle_Time(100);

	// Makes every thing a little "faster" but still keeps the delay between master and slave.
	// Set_Cycle_Time(10);
	
	int slaveNo = 0;
	
	for (int i=0; i<10; i++)
	{
		// Set all channels.
		printf ("Setting all channels\n");
		Set_DO_Channels(0xFF);
		Set_Slave_DO_Channels(slaveNo, 0xFF);
		usleep (2000000);

		// Reset all channels.
		printf ("Clearing all channels\n");
		Set_DO_Channels(0x00);
		Set_Slave_DO_Channels(slaveNo, 0x00);
		usleep (2000000);
	}
	// Conclusion: You will notice that the slave will be delayed when performing its operation.
	// While the master (nearly) immediately switches his outputs, the slave will be delayed as for 
	// it's devide value. 
	// Decreasing the Cycle time would of cause also decrease the delay - it would however, still 
	// remain. Setting the divider to 1 would have the effect that the slave immediately follws
	// the actions of the master.
	
	// If you omit this "wait" then it might happen that the last call to Set_Slave_DO_Channels(0xFF) is not 
	// sent to the hardware anymore since the Uninitialize() call below has terminated before!
	usleep (1000000);
	
	// Free library resources.
	Uninitialize();
	
	return 0;
}
