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

#include "../hubolib.h"
#include "../hubocfg.h" // Required for changing default I2C device.

using namespace HuboLib;

/*
Compile and link: 
	g++ DigitalRawInput.cpp -L../ -lhubo -lpthread -lrt -o DigitalRawInput.out
Run:
	sudo ./DigitalRawInput.out
Purpose:
	Sometimes it is necessary to keep track of a fast changing signal. Since the Linux scheduler cannot work efficient 
	at higher rates than 1ms further decreasing of the cycle time would not help. Too much time would be wasted due to 
	thread context changes...
	However, from within any of the callbacks provided by the library it is save to call Get_DI_Channels_Raw() in order
	to low level access the MCP23017 chip of the master module. 
	Make sure to not use Get_DI_Channels_Raw() from any other thread but the libraries background thread! 
	Maximum frequencies that can be achieved this way are around 2kHz. However, note that nearly no other application
	will run during the "blocking" of a callback function due to the high priority it runs at!
*/

void 			CycleTickCallback 	(unsigned long* pADChannelValues, unsigned char* pDigitalInputValues, unsigned char* pDigitalOutputValues);

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

	// Initialize the library once in your program.
	if (!Initialize())
	{
		printf ("Error: Initialize\n");
		return 1;
	}
	
	// Let's sample every 1s (1Hz).
	Set_Cycle_Time (1000);

	// Register the callback.
	Register_CycleTickCallback (CycleTickCallback);

	// Let the main thread run a while... in between use the cycle tick callback for latching digital inputs.
	for (int i=0; i<10; i++)
	{
		printf ("Main thread waiting...\n");
		usleep(1000000);
	}

	// Once not needed anymore the callbacks can be unregistered.
	Unregister_CycleTickCallback (CycleTickCallback);
	
	// Free library resources.
	Uninitialize();
	
	return 0;
}

void CycleTickCallback (unsigned long* pADChannelValues, unsigned char* pDigitalInputValues, unsigned char* pDigitalOutputValues)
{
	// Usually we'd avoid lengthily operations in callback routines as this would lead the cycle tick to get broken.
	// However, this time we'll demonstrate how fast we can latch 1000 digital inputs. 
	
	printf ("CycleTickCallback called.\n");
	
	unsigned char value = 0;
	unsigned long long startTime = GetTime_MicroSeconds();

	// Read the input 1000 times.
	for (int i=0; i<1000; i++)
	{
		if (!Get_DI_Channels_Raw (value))
			assert (false);
	}
	unsigned long long stopTime = GetTime_MicroSeconds();
		
	printf ("Reading digital inputs 1000 times lasts %lfms.\n", (stopTime-startTime)/1000.0);
	// Reading digital inputs 1000 times lasts 473.426000ms.
	// Note - this refers to the standard I2C clock speed of 100kHz. The speed can be changed by adding the following line
	// to /boot/config.txt:
	// dtparam=i2c1_baudrate=50000 
	// The above line will lower the clock speed to 50kHz. Double check the speed active in the system via:
	// sudo cat /sys/module/i2c_bcm2708/parameters/baudrate
}

