#ifndef HUBOLIB_H
	#define HUBOLIB_H

	
#include <vector>
#include <string>

namespace HuboLib
{
	/**
	@defgroup LibraryInitialization Functions for initialization and uninitialization
	*/
	/**
	@defgroup LibraryTiming Timing and monitoring support
	*/
	/**
	@defgroup DigitalInputHandling Digital input support
	*/
	/**
	@defgroup DigitalOutputHandling Digital output support
	*/
	/**
	@defgroup AnalogInputHandling Analog input support
	*/
	/**
	@defgroup Miscellaneous Miscellaneous helper functions
	*/
	/**
	@defgroup W1Support 1wire support
	*/



	// ************************************************************************************************
	// Definitions
	// ************************************************************************************************

	#ifndef MAX_MCP3x08_CHANNELS
		#define MAX_MCP3x08_CHANNELS (8)
	#endif

	#ifndef MAX_MCP23017_SLAVES
		#define MAX_MCP23017_SLAVES (7)
	#endif

	#ifndef __int64
		#define __int64 long long
	#endif

	/**
	 * @brief Prototype definition of the callback function beeing called an every cycle time tick.
	 *
	 * Once registered the background thread will call this function right after latching input from 
	 * the digital and analog inputs and propagating changes to the digital outputs. 
	 * Since the calling frequency is determined by the call to Set_Cycle_Time() care needs to be 
	 * taken that the operations performed do not exceed the time slice of one cycle tick.
	 * \n
	 * It also needs to be considered that the background thread runs at the maximum priority possible
	 * hence the entire rest of the application will be blocked during the execution of the callback.
	 * While the callback is executed the background thread still owns the internal mutex protecting
	 * IO buffers from access. So an application (regardless to its threads scheduling policy and priority) 
	 * calling into the library will be blocked until the callback returns. 
	 * This is to ensure that - if a cycle time should be violated - the library get as many CPU time 
	 * granted in order to catch up with cycle ticks that are delayed.
	 * @param pADChannelValues Pointer to the buffer of the analog input values.
	 * @param pDigitalInputValues Pointer to the buffer of the digital input values.
	 * @param pDigitalOutputValues Pointer to the buffer of the digital output values.
	 * @see Register_CycleTickCallback(), Unregister_CycleTickCallback(), Set_Cycle_Time(), Register_ChannelDelayCallback(), Set_MCP3x08_Oversampling()
	 * @see For an example on how to register and use the cycle tick callback function refer to the demo SampleCallbacks.cpp.
	 * @note Be aware of that the callback routine will be executed within the background thread!
	 * @ingroup LibraryTiming
	*/
	typedef void (*T_pfn_CycleTickCallback)		(unsigned long* pADChannelValues, unsigned char* pDigitalInputValues, unsigned char* pDigitalOutputValues);

	/**
	 * @brief Prototype definition of the callback function beeing called when the cycle time slice has been 
	 * violated.
	 *
	 * Registering a callback routine provides a way to an application to get notified whenever the 
	 * background thread was not able to finish its work in the cycle time as being defined. 
	 * This is might be required for applications the require a precise timing e.g. a controller
	 * calculating new set points from sample deviation and time. 
	 * Just like the cycle tick callback this function is also called by the background thread - thus all
	 * timing considerations also apply to this callback function. 
	 * The channel delay callback is being called as the last callback function within one time slice.
	 * @param cycleCount The number of the cycle currently being executed. 
	 * @param t_Overrun_ms Time in ms the cycle time is violated. Note that this value is at least as big
	 * 		               as the cycle time itself, otherwise the callback would not be called.
	 * @param pDigitalOutputValues Pointer to the buffer of the digital output values.
	 * @see Register_ChannelDelayCallback(), Unregister_ChannelDelayCallback(), Register_CycleTickCallback(),  Set_Cycle_Time(), Set_MCP3x08_Oversampling()
	 * @see For an example on how to register and use the channel delay callback function refer to the demo SampleCallbacks.cpp.
	 * @note Be aware of that the callback routine will be executed within the background thread!
	 * @ingroup LibraryTiming 
	*/
	typedef void (*T_pfn_ChannelDelayCallback)	(__int64 cycleCount, __int64 t_Overrun_ms);

	/**
	 * @brief Prototype definition of the callback function beeing called whenever a change of any of the digital inputs 
	 * is detected. 
	 *
	 * Registering a callback routine provides a way to an application to get notified whenever the 
	 * background thread detects the changing of an digital input.
	 * This can be usefull to an application that does not want to poll for changes on the digital inputs but use 
	 * the background threads cycle time for detection instead. 
	 * The callback is executed after inputs and outputs have been processed by the background thread but prior to calls
	 * to the callbacks for the cycle tick and the channel delay.\n
	 * Just like the cycle tick callback this function is also called by the background thread - thus all
	 * timing considerations also apply to this callback function. 
	 * @param changedDigitalInputValues The bit mask indicating a changed input via the bit set.
	 * @param digitalInputValues The current state of the digital inputs. 
	 * @see For an example on how to register and use the digital input changed callback function refer to the demo DigitalInput5.cpp.
	 * @note Be aware of that the callback routine will be executed within the background thread!
	 * @ingroup DigitalInputHandling
	*/
	typedef void (*T_pfn_DIChangedCallback)		(unsigned char  changedDigitalInputValues, unsigned char digitalInputValues);





	// ************************************************************************************************
	// Hubo initialization
	// ************************************************************************************************

	/**
	 * @brief Initializes the library.
	 *
	 * Call this function once prior to work with most of the other functions. 
	 * On failure it is not possible to call any other function that communicates to the board.
	 * Note that initalization regularly fails when the SPI/I2c kernel modules
	 * are not loaded or the user does not have sufficient right to use them. In such a case try 
	 * running the application as sudo.
	 * @return Initialize returns true whenever at least one hardware component could be found. 
	 * Hence there is no guarantee that all hardware components could be initialized.
	 * @see For an example on how to use Initialize() refer to the demo DigitalInput3.cpp.
	 * @see Uninitialize()
	 * @note Changes to the configuration (e.g. SPI chip select, I2C address selection) must be 
	 * made prior to a call to Initialize().
	 * @ingroup LibraryInitialization
	*/
	bool 			Initialize 						 ();

	/**
	 * @brief Releases any resources bound to the library. 
	 *
	 * Call this function to free up any ressources allocated by a previous call to Initialize().
	 * @see For an example on how to use Uninitialize() refer to the demo DigitalInput3.cpp.
	 * @see Initialize()
	 * @ingroup LibraryInitialization
	*/
	void			Uninitialize					 ();

	/**
	 * @brief Low level initialization of the MCP23017 IO expander. 
	 *
	 * This function is used internally by Initialize() for initializing the digital IO expander. 
	 * The function should not be called directly for any other purpose than trouble shooting!
	 * @see Initialize()
	 * @ingroup LibraryInitialization
	 * @deprecated This function might get dropped in future versions of the library.
	*/
	bool			Initialize_MCP23017				 ();

	/**
	* @brief Waits until input and output buffers of the MCP23017 master are initialized from the hardware.
	*
	* Call this function once after a call to Initialize() in order to ensure that further
	* read operations are not accessing the buffers prior to their first initialization by the
	* libraries background thread. 
	* @return The function returns true once the buffers are filled. It returns false if the
	*         initialization failed or the background thread is not running.
	* @see For an example on how to use Wait_For_MCP23017_Buffered_Values() refer to the demo DigitalInput6.cpp.
	* @see Wait_For_MCP23017_Slaves_Buffered_Values(), Wait_For_MCP3x08_Buffered_Values
	* @note You should not call this function prior to a successfull call of Initialize().
	* @ingroup LibraryInitialization
	*/
	bool			Wait_For_MCP23017_Buffered_Values();

	/**
	 * @brief Low level initialization of the MCP23017 IO expander slaves. 
	 *
	 * This function is used internally by Initialize() for initializing the digital IO expander slaves. 
	 * The function should not be called directly for any other purpose than trouble shooting!
	 * @see Initialize()
	 * @ingroup LibraryInitialization
	 * @deprecated This function might get dropped in future versions of the library.
	*/
	bool			Initialize_MCP23017_Slaves		();
	
	/**
	* @brief Waits until input and output buffers of the MCP23017 slaves are initialized from the hardware.
	*
	* Call this function once after a call to Initialize() in order to ensure that further
	* read operations are not accessing the buffers prior to their first initialization by the
	* libraries background thread.
	* @return The function returns true once the buffers are filled. It returns false if the
	*         initialization failed or the background thread is not running.
	* @see For an example on how to use Wait_For_MCP23017_Slaves_Buffered_Values() refer to the demo DigitalSlaveOutput3.cpp.
	* @see Wait_For_MCP23017_Buffered_Values(), Wait_For_MCP3x08_Buffered_Values
	* @note You should not call this function prior to a successfull call of Initialize().
	* @ingroup LibraryInitialization
	*/
	bool			Wait_For_MCP23017_Slaves_Buffered_Values();

	/**
	 * @brief Low level initialization of the MCP3x08 analog input chip. 
	 *
	 * This function is used internally by Initialize() for initializing the analog input chip. 
	 * The function should not be called directly for any other purpose than trouble shooting!
	 * @see Initialize()
	 * @ingroup LibraryInitialization
	 * @deprecated This function might get dropped in future versions of the library.
	*/
	bool			Initialize_MCP3x08				();

	/**
	* @brief Waits until the input buffer of the MCP3x08 are initialized from the hardware.
	*
	* Call this function once after a call to Initialize() in order to ensure that further
	* read operations are not accessing the buffers prior to their first initialization by the
	* libraries background thread.
	* @return The function returns true once the buffers are filled. It returns false if the
	*         initialization failed or the background thread is not running.
	* @see For an example on how to use Wait_For_MCP3x08_Buffered_Values() refer to the demo AnalogInput5.cpp.
	* @see Wait_For_MCP23017_Buffered_Values(), Wait_For_MCP23017_Slaves_Buffered_Values()
	* @note You should not call this function prior to a successfull call of Initialize().
	* @ingroup LibraryInitialization
	*/
	bool			Wait_For_MCP3x08_Buffered_Values();




	// ************************************************************************************************
	// Timing and monitoring support
	// ************************************************************************************************

	/**
	 * @brief Sets the backgrounds threads polling interval in ms.
	 *
	 * When reading or writing digital values to the IO expander or rading analog values from the ADC
	 * these operations are not performed on the real hardware. Instead calls to Get_DO_Channels(), 
	 * Set_DO_Channels(), Get_AI_Channel() etc. are accessing internal buffers that contain the values latched 
	 * or to be written by the background thread. The speed at which these buffers are latched or transmitted
	 * to the hardware is determined by the so called cycle time. While the background thread runs at the highest
	 * priority possible other threads usually would not break the cycle time slice.
	 * There are however, limitations for setting the time slice. Setting it to 1ms will heavily stress the OS 
	 * scheduler and therefore is not recommended. Also the number of analog channels latched and oversampled
	 * as specified by a call to Set_MCP3x08_Oversampling() will heavily impact the CPU time consumed in one
	 * cycle tick. Therefore a call to Set_Cycle_Time() will perform a brief check on plausibility prior to 
	 * accepting a new cycle time. \n
	 * The default for the cycle time upon initializing the library is 10ms thus resulting in a cycle tick of 100Hz.\n
	 * Note that a change to the cycle time value will first take effect after the background thread has finished 
	 * the current cycle tick.
	 * @param cycleTime Defines the cycle time of the background thread in ms. 
	 * @return For a plausible cycle time the function returns true, false otherwise.
	 * @see Register_CycleTickCallback(), Unregister_CycleTickCallback(), Register_ChannelDelayCallback(), Set_MCP3x08_Oversampling()
	 * @see For an example on how to use Set_Cycle_Time() refer to the demo SetCycleTime.cpp.
	 * @ingroup LibraryTiming
	*/
	bool			Set_Cycle_Time					(long cycleTime);

	/**
	 * @brief Registers a callback function called on every cycle tick.
	 *
	 * This function is used to register a callback routine that is called on each cycle tick after the
	 * input of the hardware has been latched and new output values have been written. Registering such a 
	 * callback is useful when acurate timing is essential to e.g. a controller algorithm requiring to 
	 * get called equidistant in time. 
	 * The callback routine will have access to the internal buffers of the IO area.\n
	 * Unregistration is performed by calling Unregister_ChannelDelayCallback().
	 * @param pFnCycleTickCallback Pointer to the callback function to be called on each cycle tick. 
	 *        Function pointers are not chained. Passing 0 as an argument disables the callback.
	 * @return The function returns true if the new callback could be registered. If the maximum number of
	 *         callback functions has been reached the function returns false.
	 * @see Unregister_CycleTickCallback(), Register_ChannelDelayCallback(), Set_MCP3x08_Oversampling()
	 * @see For an example on how to use Register_CycleTickCallback() refer to the demo SampleCallbacks.cpp.
	 * @note Be aware of that the callback routine will be executed within the background thread!
	 *       In order to avoid dead lock situations callback routines must not call any of the functions  
	 *       as exposed by the hubolib.h interface (unless otherwise stated e.g. for xxx_Raw()-routines)!
	 * @ingroup LibraryTiming
	*/
	bool			Register_CycleTickCallback		(T_pfn_CycleTickCallback	pFnCycleTickCallback);

	/**
	 * @brief Unregister a callback previouly registered by a call to Register_CycleTickCallback().
	 *
	 * This function is used to unregister a single callback routine previously added. 
	 * If pFnCycleTickCallback is 0 then the call will unregister all callback routines.
	 * @param pFnCycleTickCallback Pointer to the callback to be unregistered from the list of callback functions 
	 *        or 0 if all callback functions are to be removed from the list.
	 * @return The function returns true if the callback could be found and unregistered.
	 * @see Register_CycleTickCallback()
	 * @see For an example on how to use Unregister_CycleTickCallback() refer to the demo SampleCallbacks.cpp.
	 * @ingroup LibraryTiming
	*/
	bool			Unregister_CycleTickCallback		(T_pfn_CycleTickCallback	pFnCycleTickCallback);
	
	/**
	 * @brief Register a callback to be called whenever the cycle time has been violated by more than one cycle time.
	 *
	 * This function is used to register a callback routine that is called whenever the cycle time is 
	 * delayed for at least the time of one cycle time. The callback routine receives information on the 
	 * number of the cycle as well as the absolute delay in ms.\n
	 * Unregistration is performed by calling Unregister_ChannelDelayCallback().
	 * @param pFnChannelDelayCallback Pointer to the callback function to be called whenever the cycle time 
	 * 		  is violated by more then 1 cycle tick. 
	 *        Function pointers are not chained. Passing 0 as an argument disables the callback.
	 * @return The function returns true if the new callback could be registered. If the maximum number of
	 *         callback functions has been reached the function returns false.
	 * @see Unregister_ChannelDelayCallback(), Register_CycleTickCallback(), Set_MCP3x08_Oversampling()
	 * @see For an example on how to use Register_ChannelDelayCallback() refer to the demo SampleCallbacks.cpp.
	 * @note Be aware of that the callback routine will be executed within the background thread!
	 *       In order to avoid dead lock situations callback routines must not call any of the functions  
	 *       as exposed by the hubolib.h interface (unless otherwise stated e.g. for xxx_Raw()-routines)! \n
	 *       Also be aware of that frequently breaking the cycle time indicates that the background worker
     *       thread is overloaded. Since this thread is owning the mutex for accessing the data (which indirectly
     *       is also being used by other library functions) - calls into the library will be blocked for the 
	 *       time the cycle time is broken. This is even true for a call to Register_CycleTickCallback(0) 
	 *       or any other callback that has been registered) which potentially could even "solve" the situation 
	 *       by removing the cause of the cycle time to break. \n
	 *       If you experience you application to not properly terminate then check for the cycle time to not be
	 *       broken (e.g. for debugging purposes register a callback routine that asserts when the cycle time 
	 *       gets broken).\n
	 *       See the comments within the code of SampleCallbacks.cpp for more information on this problem.
	 * @ingroup LibraryTiming
	*/
	bool			Register_ChannelDelayCallback	(T_pfn_ChannelDelayCallback pFnChannelDelayCallback);

	/**
	 * @brief Unregister a callback previouly registered by a call to Register_ChannelDelayCallback().
	 *
	 * This function is used to unregister a single callback routine previously added. 
	 * If pFnChannelDelayCallback is 0 then the call will unregister all callback routines.
	 * @param pFnChannelDelayCallback Pointer to the callback to be unregistered from the list of callback functions 
	 *        or 0 if all callback functions are to be removed from the list.
	 * @return The function returns true if the callback could be found and unregistered.
	 * @see Register_ChannelDelayCallback()
	 * @see For an example on how to use Unregister_ChannelDelayCallback() refer to the demo SampleCallbacks.cpp.
	 * @ingroup LibraryTiming
	*/
	bool			Unregister_ChannelDelayCallback	(T_pfn_ChannelDelayCallback pFnChannelDelayCallback);




	// ************************************************************************************************
	// Digital output support
	// ************************************************************************************************

	/**
	 * @brief Requests the background thread to update all 8 bits of the digital output to the value specified.
	 *
	 * This function tells the background thread to transfer the values as specified to the IO expander
	 * during its next cycle time. 
	 * @param value The bit mask representing the state of the digital outputs as to be set. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the IO expander is present and has properly been initialized.
	 * @see Set_DO_Channel(), Set_Slave_DO_Channels()
	 * @see For an example on how to write the digital outputs refer to the demos DigitalOutput1.cpp, 
	 *      DigitalOutput2.cpp and LoadTest.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool			Set_DO_Channels					(unsigned char  value);

	/**
	 * @brief Requests the background thread to update all 8 bits of the digital output to the value specified for a given slave.
	 *
	 * This function behaves like Set_DO_Channels() but works on a slave as specified.
	 * @param slaveNo The slave index in the list of slave addresses as specified by g_I2CConfig.m_MCP23017SlaveDeviceAddressList. 
	 * @param value The bit mask representing the state of the digital outputs as to be set. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the slave is present and has properly been initialized.
	 * @see Set_DO_Channels(), Set_Slave_DO_Channel()
	 * @see For an example on how to write the digital outputs refer to the demos DigitalSlaveOutput1.cpp 
	 *      and DigitalSlaveOutput2.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool			Set_Slave_DO_Channels			(int slaveNo, unsigned char  value);

	/**
	 * @brief Requests the background thread to set one of the digital outputs to the value specified.
	 * 
	 * This function tells the background thread to set a dedicated digital output to the value specified
	 * during its next cycle time. 
	 * @param channel The digital output channel to be set. Valid ranges are 0 through 7.
	 * @param bValue If true then the output is set, otherwise it is reset.
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the IO expander is present, has properly been initialized and
	 *         the channel value is within the allowed range of 0..7.
	 * @see Set_DO_Channels(), Set_Slave_DO_Channel()
	 * @see For an example on how to write individual digital outputs refer to the demo DigitalOutput1.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool			Set_DO_Channel					(int channel, bool bValue);

	/**
	 * @brief Requests the background thread to set one of the digital outputs to the value specified for a given slave.
	 * 
	 * This function behaves like Set_DO_Channel() but works on a slave as specified.
	 * @param slaveNo The slave index in the list of slave addresses as specified by g_I2CConfig.m_MCP23017SlaveDeviceAddressList. 
	 * @param channel The digital output channel to be set. Valid ranges are 0 through 7.
	 * @param bValue If true then the output is set, otherwise it is reset.
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the slave is present, has properly been initialized and
	 *         the channel value is within the allowed range of 0..7.
	 * @see Set_DO_Channel(), Set_Slave_DO_Channels()
	 * @see For an example on how to write individual digital outputs refer to the demo DigitalSlaveOutput1.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool			Set_Slave_DO_Channel			(int slaveNo, int channel, bool bValue);

	/**
	 * @brief Retrieves the requested digital output value from the output buffer.
	 * 
	 * This function retrieves the value of the current output buffer. The output buffer gets modified 
	 * by calls to Set_DO_Channel() and Set_DO_Channels().\n
	 * Both functions - Get_DO_Channels() and Readback_DO_Channels() - can be used to verify whether
	 * an output request via Set_DO_Channel() or Set_DO_Channels() has already been performed by the 
	 * IO expander. As long as the output has not been written, the values returned by Get_DO_Channels() 
	 * and Readback_DO_Channels() differ.
	 * @param value The bit mask representing the state of the digital output buffer. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the IO expander is present and has properly been initialized.
	 * @see Readback_DO_Channels(), Set_DO_Channels(), Set_DO_Channel(), Get_Slave_DO_Channels()
	 * @see For an example on how to read and write individual digital outputs refer to the demo DigitalOutput2.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool			Get_DO_Channels					(unsigned char& value);

	/**
	 * @brief Retrieves the requested digital output value from the output buffer for a given slave.
	 * 
	 * This function behaves like Get_DO_Channels() but works on a slave as specified.
	 * @param slaveNo The slave index in the list of slave addresses as specified by g_I2CConfig.m_MCP23017SlaveDeviceAddressList. 
	 * @param value The bit mask representing the state of the digital output buffer. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the slave is present and has properly been initialized.
	 * @see Get_DO_Channels, Readback_Slave_DO_Channels(), Set_Slave_DO_Channel()
	 * @see For an example on how to read and write individual digital outputs refer to the demo DigitalSlaveOutput1.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool			Get_Slave_DO_Channels			(int slaveNo, unsigned char& value);

	/**
	 * @brief Reads back the digital output latchs of the IO expander. 
	 * 
	 * The output latches of the IO expander chip are frequently read back during each cycle time tick
	 * of the background thread. This function retrieves these buffered output latch values of the IO expander. \n
	 * Both functions - Get_DO_Channels() and Readback_DO_Channels() - can be used to verify whether
	 * an output request via Set_DO_Channel() or Set_DO_Channels() has already been performed by the 
	 * IO expander. As long as the output has not been written, the values returned by Get_DO_Channels() 
	 * and Readback_DO_Channels() differ.
	 * @param value The bit mask representing the buffered state of the IO expanders digital output latchs. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the IO expander is present and has properly been initialized.
	 * @see Get_DO_Channels(), Set_DO_Channels(), Set_DO_Channel(), Readback_Slave_DO_Channels()
	 * @see For an example on how to read back the IO expanders output latches refer to the demo DigitalOutput2.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool 			Readback_DO_Channels			(unsigned char& value);

	/**
	 * @brief Reads back the digital output latchs of the IO expander for a given slave. 
	 * 
	 * This function behaves like Readback_DO_Channels() but works on a slave as specified.
	 * @param slaveNo The slave index in the list of slave addresses as specified by g_I2CConfig.m_MCP23017SlaveDeviceAddressList. 
	 * @param value The bit mask representing the buffered state of the IO expanders digital output latchs. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the slave is present and has properly been initialized.
	 * @see Readback_DO_Channels, Get_Slave_DO_Channels(), Set_Slave_DO_Channels()
	 * @see For an example on how to read back the IO expanders output latches refer to the demo DigitalSlaveOutput2.cpp.
	 * @ingroup DigitalOutputHandling
	*/
	bool 			Readback_Slave_DO_Channels		(int slaveNo, unsigned char& value);





	// ************************************************************************************************
	// Digital input support
	// ************************************************************************************************

	/**
	 * @brief Retrieves the value of all digital inputs.
	 *
	 * This function returns the buffered value of the last latched digital inputs. 
	 * @param value The bit mask representing the current state of the digital inputs. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the IO expander is present and has properly been initialized.
	 * @see Get_DI_Channel(), Get_Slave_DI_Channels()
	 * @see For an example on how to read the digital inputs refer to the demos DigitalInput4.cpp and 
	 *      SetCycleTime.cpp.
	 * @ingroup DigitalInputHandling
	*/
	bool			Get_DI_Channels					(unsigned char& value);

	/**
	 * @brief Retrieves the unbuffered values of all digital inputs (of the Hubo master module).
	 *
	 * While this function requires a proper initialization by a call to Initialize() it does not require
	 * any further operations. It does not provide a check for correct initialization but directly accesses
	 * the hardware without storing the results in the buffers associated with the digital inputs.
	 * The function should be used in cases where very fast access to digital input values is required (up to 
	 * 2kHz) which cannot be achieved by further decreasing of the cycle time. This can be handy when 
	 * trying to follow (or capture) a signal once a certain condition is met.
	 * However, remember that the background thread runs at a very high priority likely to prevent the 
	 * rest of the system from running. So make sure your callback routine is taking this into account.
	 * @param value The bit mask representing the current state of the digital inputs. 
	 * @return Since a call to this function will directly access the hardware it might return false when 
	 *         failing to read a new input value. Otherwise the return value is true.
	 * @see Get_DI_Channel(), Get_AI_Channel_Raw()
	 * @see For an example on how to raw read the digital inputs refer to the demo DigitalRawInput.cpp.
	 * @ingroup DigitalInputHandling
	*/
	bool			Get_DI_Channels_Raw				(unsigned char& values);

	/**
	 * @brief Retrieves the value of all digital inputs.
	 *
	 * This function returns the buffered value of the last latched digital inputs for a given slave.
	 * This function behaves like Get_DI_Channels() but works on a slave as specified.
	 * @param slaveNo The slave index in the list of slave addresses as specified by g_I2CConfig.m_MCP23017SlaveDeviceAddressList. 
	 * @param value The bit mask representing the current state of the digital inputs. 
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the slave is present and has properly been initialized.
	 * @see Get_DI_Channels(), Get_Slave_DI_Channel()
	 * @see For an example on how to read the digital inputs refer to the demo DigitalSlaveInput2.cpp.
	 * @ingroup DigitalInputHandling
	*/
	bool			Get_Slave_DI_Channels			(int slaveNo, unsigned char& value);

	/**
	 * @brief Retrieves the value of one digital input.
	 *
	 * This function returns the buffered value of the last latched digital inputs. 
	 * @param channel The digital input channel to retrieve the state from. Valid ranges are 0 through 7.
	 * @param bValue If the channel is being set bValue is true, otherwise false.
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the IO expander is present, has properly been initialized and
	 *         the channel value is within the allowed range of 0..7.
	 * @see Get_DI_Channels(), Get_Slave_DI_Channel()
	 * @see For an example on how to read a single digital inputs refer to the demos DigitalInput1.cpp, 
	 *      DigitalInput2.cpp and DigitalInput3.cpp.
	 * @ingroup DigitalInputHandling
	*/
	bool			Get_DI_Channel					(int channel,  bool& bValue);

	/**
	 * @brief Retrieves the value of one digital input for a given slave.
	 *
	 * This function behaves like Get_DI_Channel() but works on a slave as specified.
	 * @param slaveNo The slave index in the list of slave addresses as specified by g_I2CConfig.m_MCP23017SlaveDeviceAddressList. 
	 * @param channel The digital input channel to retrieve the state from. Valid ranges are 0 through 7.
	 * @param bValue If the channel is being set bValue is true, otherwise false.
	 * @return Since a call to this function will access the internal buffers, a call will always 
	 *         return true as long as the slave is present, has properly been initialized and
	 *         the channel value is within the allowed range of 0..7.
	 * @see Get_DI_Channel(), Get_Slave_DI_Channels()
	 * @see For an example on how to read a single digital inputs refer to the demo DigitalSlaveInput1.cpp.
	 * @ingroup DigitalInputHandling
	*/
	bool			Get_Slave_DI_Channel			(int slaveNo, int channel,  bool& bValue);


	/**
	 * @brief Register a callback to be called whenever one or more of the digital inputs have changed.
	 *
	 * This function is used to register a callback routine that is called whenever one or more of the
	 * digital inputs have changed during the last cycle time. 
	 * The callback routine receives information on the bit mask the input changes as well as the current 
	 * state of the inputs.\n
	 * Unregistration is performed by Unregister_DIChangedCallback().
	 * @param pFnDIChangedCallback Pointer to the callback function to be called whenever one or more
	 *        digital inputs have changed their state. 
	 *        Function pointers are not chained. Passing 0 as an argument disables the callback.
	 * @return The function returns true if the new callback could be registered. If the maximum number of
	 *         callback functions has been reached the function returns false.
	 * @see Unregister_DIChangedCallback(), T_pfn_DIChangedCallback
	 * @see For an example on how to use Register_DIChangedCallback() refer to the demo DigitalInput5.cpp.
	 * @note Be aware of that the callback routine will be executed within the background thread!
	 *       In order to avoid dead lock situations callback routines must not call any of the functions  
	 *       as exposed by the hubolib.h interface (unless otherwise stated e.g. for xxx_Raw()-routines)!
	 * @ingroup DigitalInputHandling
	*/
	bool			Register_DIChangedCallback		(T_pfn_DIChangedCallback pFnDIChangedCallback);

	/**
	 * @brief Unregister a callback previouly registered by a call to Register_DIChangedCallback().
	 *
	 * This function is used to unregister a single callback routine previously added. 
	 * If pFnDIChangedCallback is 0 then the call will unregister all callback routines.
	 * @param pFnDIChangedCallback Pointer to the callback to be unregistered from the list of callback functions 
	 *        or 0 if all callback functions are to be removed from the list.
	 * @return The function returns true if the callback could be found and unregistered.
	 * @see Register_DIChangedCallback()
	 * @see For an example on how to use Unregister_DIChangedCallback() refer to the demo DigitalInput5.cpp.
	 * @ingroup DigitalInputHandling
	*/
	bool			Unregister_DIChangedCallback	(T_pfn_DIChangedCallback pFnDIChangedCallback);




	
	// ************************************************************************************************
	// Analog input support
	// ************************************************************************************************

	/**
	 * @brief Set the reference voltage value for the ADC.
	 *
	 * This function is to adjust the reference voltage of the ADC according to a measured value
	 * as being provided by the high precision reference voltage TL431. \n
	 * The new reference voltage is effective beginning with the next cycle tick count.
	 * @param volt The reference voltage of the TL431 to be adjusted. 
	 * @see Get_VRef(), Get_AI_Channel(), Set_MCP3x08_Oversampling
	 * @see For an example on how to read and set the reference voltage refer to the demo AnalogInput4.cpp.
	 * @note The default reference voltage is 2.53V and usually does not need to be changed. If so - use a 
	 * 		 high precision instrument to measure the TL431's reference voltage.
	 * @ingroup AnalogInputHandling
	*/
	void			Set_VRef						(double volt);

	/**
	 * @brief Retrieves the reference voltage value used for ADC count convertion.
	 *
	 * This function retrieves the reference voltage of the ADC taken into account when calculating 
	 * an absolut voltage from an ADC count.
	 * @return The reference voltage currently being in used for convertion. 
	 * @see Set_VRef(), Get_AI_Channel(), Set_MCP3x08_Oversampling
	 * @see For an example on how to read and set the reference voltage refer to the demo AnalogInput4.cpp.
	 * @ingroup AnalogInputHandling
	*/
	double			Get_VRef						();

	/**
	 * @brief Retrieves the reference voltage value used for ADC count convertion.
	 *
	 * This function retrieves the reference voltage of the ADC taken into account when calculating 
	 * an absolut voltage from an ADC count.
	 * @return The reference voltage currently being in used for convertion. 
	 * @see Get_VRef(), Get_AI_Channel_Raw()
	 * @see For an example on how to read the reference voltage from a callback function refer to the demo 
	 * AnalogRawInput.cpp.
	 * @note A call to this function is only allowed from the background thread - hence one of the several
	 *       callback functions. Do not call this function from any other thread - e.g. the main thread!
	 * @ingroup AnalogInputHandling
	*/
	double			Get_VRef_Raw					();

	/**
	 * @brief Specifies the ADC channels to be sampled as well as the number they get oversampled.
	 *
	 * The library supports up to 8 analog channels that can be sampled within one cycle tick. However,
	 * not all applications might require all 8 analog channels to be sampled but on the other hand
	 * might require some of the channels be oversampled in order to gain a higher resolution. \n
	 * With a call to Set_MCP3x08_Oversampling() an array of 8 shorts is provided from which each short
	 * represents a number that defines whether the channel should be sampled and if so how many times
	 * it should get (over-) sampled. So a value of 0 means to skip the channel for sampling, 1 will sample
	 * exactly once a cycle tick and a value of 10 means to add 10 ADC counts to the internal analog 
	 * input buffer.\n
	 * Specifying large values for the oversampling values can lead to heavy CPU usage. Therefore a 
	 * call to the function might not succeed e.g. when the etsimated amount of time for all cycles
	 * exceeds the cycle time as specified by a call to Set_Cycle_Time().\n
	 * After initialization of the library no analog channel will be acquired. So using analog channels
	 * first requires a successfull call to Set_MCP3x08_Oversampling().
	 * @param overSampling A vector specifying how many ADC samples should be taken per analog channel for 
	 * 		  calculating the analog voltage.
	 * @return If the estimation of the CPU load required for sampling at a given cycle time and oversampling 
	 *         shows up to not break the cycle time then the result will be true and the oversampling values
	 *         are being used. Otherwise the function will return false and the old valued are being used.
	 * @see Set_VRef(), Get_AI_Channel(), Set_Cycle_Time()
	 * @see For a simple example on how to sample one analog channel refer to the demo AnalogInput1.cpp.\n
	 *      AnalogInput2.cpp illustrates how to oversample a channel 4 times.  \n
	 * 		Testing ranges that can be used for oversampling is shown in AnalogInput3.cpp.\n
	 * 		The impact of the reference voltage when calculating absolut voltage values from ADC counts 
	 *      can be seen in AnalogInput4.cpp.
	 * @note The new oversampling values are effective beginning with the next cycle tick count.
	 * @ingroup AnalogInputHandling
	*/
	bool			Set_MCP3x08_Oversampling		(unsigned short overSampling[MAX_MCP3x08_CHANNELS]);

	/**
	 * @brief Get the buffered and oversampled data from the MCP3x08.
	 *
	 * For a channel being specified a call to Get_AI_Channel() returns the buffered and oversampled
	 * ADC counts during the last cycle time. Using the reference voltage as specified by a call to 
	 * Set_VRef() the voltage of this channel is computed as well. 
	 * @param channel Specifies the analog channel from which to retrieve the data.
	 * @param count Contains the oversampled (simply added) ADC counts taken during the last cycle time.
	 *              Counts are not averaged but just added for the number of times as specified in the 
	 *              oversampling vector.
	 * @param volt Contains the voltage as being calculated from the (over-) sampled values taken during the 
	 *             last cycle time.
	 * @return The function returns true if the ADC chip was successfully initialized, an oversampling 
			   count > 0 was specified for the channel given and the channel is within the allowed range. 
			   Otherwise the return value is false.
	 * @see Set_MCP3x08_Oversampling(), Set_VRef(), Set_Cycle_Time()
	 * @see For a simple example on how to sample one analog channel refer to the demo AnalogInput1.cpp.\n
	 *      AnalogInput2.cpp illustrates how to increase the resolution by oversampling a channel 4 times.
	 * @ingroup AnalogInputHandling
	*/
	bool			Get_AI_Channel					(int channel, unsigned long& count, double& volt);

	/**
	 * @brief Gets an unbuffered value from the MCP3x08.
	 *
	 * For a channel being specified a call to Get_AI_Channel_Raw() returns the unbuffered counts of
	 * the ADC.
	 * While this function requires a proper initialization by a call to Initialize() it does not require
	 * any further operations. Since Get_AI_Channel_Raw() bypasses all buffers but directly accesses 
	 * the hardware instead - it does not need other preceeding operations such as setting the the 
	 * oversampling array.
	 * The function should be used in cases where very fast access to analog values is required (up to 
	 * 8kHz) which cannot be achieved by further decreasing of the cycle time. This can be handy when 
	 * trying to follow (or capture) a signal once a certain condition is met.
	 * However, remember that the background thread runs at a very high priority likely to prevent the 
	 * rest of the system from running. So make sure your callback routine is taking this into account.
	 * @param channel Specifies the analog channel from which to retrieve the data.
	 * @param value The analog count of the ADC.
	 * @return True if the analog value could be read, otherwise false.
	 * @see Get_AI_Channel()
	 * @see For a an example on how to sample raw data refer to the demo AnalogRawInput.cpp.
	 * @note A call to this function is only allowed from the background thread - hence one of the several
	 *       callback functions. Do not call this function from any other thread - e.g. the main thread!
	 * @ingroup AnalogInputHandling
	*/
	bool	Get_AI_Channel_Raw				(int channel, unsigned short& value);



	// ************************************************************************************************
	// Miscellaneous 
	// ************************************************************************************************

	/**
	 * @brief Prints version information and other stuff regarding to the library to the console. 
	 *
	 * Use this function to get information of the version of the library and other stuff. 
	 * @see For a simple example on how to call VersionInfo() refer to the demo VersionInfo.cpp.\n
	 * @note  This call does not require a prior initialization of the library.
	 * @ingroup Miscellaneous
	*/
	void 			VersionInfo						();

	/**
	 * @brief Converts a voltage value of an MCP9701 temperature sensor into the equivalent temperature.
	 *
	 * Use this function to convert the voltage of a MCP7901 temperature sensor into its equivalent 
	 * temperature given in °C.\n
	 * Note that no checks are being made for the voltage ranges that are specified in the data sheet of 
	 * the sensor. Thus just any voltage value would result in "some" temperature.
	 * @param volt The voltage of the output of the sensor.
	 * @return The temperature calculated from the voltage of the sensor.
	 * @see For a simple example on how to call Get_MCP7901_Temperature() refer to the demo MCP790x.cpp.
	 * @note  This call does not require a prior initialization of the library.
	 * @ingroup Miscellaneous
	*/
	double 			Get_MCP9701_Temperature 		(double volt);

	/**
	 * @brief Converts a voltage value of an MCP9700 temperature sensor into the equivalent temperature.
	 *
	 * Use this function to convert the voltage of a MCP7900 temperature sensor into its equivalent 
	 * temperature given in °C.\n
	 * Note that no checks are being made for the voltage ranges that are specified in the data sheet of 
	 * the sensor. Thus just any voltage value would result in "some" temperature.
	 * @param volt The voltage of the output of the sensor.
	 * @return The temperature calculated from the voltage of the sensor.
	 * @see For a simple example on how to call Get_MCP7900_Temperature() refer to the demo MCP790x.cpp.
	 * @note  This call does not require a prior initialization of the library. It is highly recomended 
	 *        to perform a calibration of the sensors!
	 * @ingroup Miscellaneous
	*/
	double			Get_MCP9700_Temperature			(double volt);

	/**
	 * @brief Returns the list of I2C addresses of the MCP23017 slaves.
	 *
	 * Use this function to retrieve a list of all MCP23017 IO expanders that are cascaded to the Hubo
	 * master module. 
	 * @param slaveAddressList The list containing the I2C addresses detected.
	 * @return True if the function succeeded and at least one slave could be found.
	 * @note  This call does not require a prior initialization of the library. However, the results 
	 *        are only valid after a call to Initialize(). 
	 * @ingroup Miscellaneous
	*/
	bool			GetSlaveDeviceList				(std::vector<int>& slaveAddressList);

	/**
	 * @brief Returns the number of micro seconds.
	 *
	 * Use this function to retrieve the number of µs regardless of timezone changes, daylight saving...
	 * @return The number of µs. 
	 * @see For an example on how to use GetTime_MicroSeconds() refer to the demos GPIOInputOutput.cpp and RCSocket.cpp.
	 * @note  This call does not require a prior initialization of the library. 
	 * @ingroup Miscellaneous
	*/
	unsigned long long 	GetTime_MicroSeconds		();

	/**
	 * @brief delays the execution of the calling thread for the given number of micro seconds.
	 *
	 * Use this function to suspend a thread for the number of µs. While µsleep() does have an overhead
	 * of 100µs-300µs this function "will hard wait" remainder delays not greater than 300µs in a loop - thus
	 * achieving results "as accurate as possible".
	 * @param delay_micros The time in µs to suspend the calling thread.
	 * @see For an example on how to use Delay_MicroSeconds() refer to the demos GPIOInputOutput.cpp and RCSocket.cpp.
	 * @note  This call does not require a prior initialization of the library. 
	 * @ingroup Miscellaneous
	*/
	void 			Delay_MicroSeconds				(unsigned long delay_micros);




	// ************************************************************************************************
	// 1wire support 
	// ************************************************************************************************

	/**
	 * @brief Returns a list of 1wire devices found on the bus. 
	 *
	 * Use this function to retrieve the list of 1wire devices found on the bus. 
	 * This function uses the path to the devices as specified in the W1_Config class. 
	 * @param deviceList Vector holding a list of 1wire device names.
	 * @return True if the path to the devices exist, false otherwise. 
	 *         That does however, not mean that a device has been found!
	 * @see For a simple example on how to use Get_1w_Devices() refer to the demo DS18x20.cpp.\n
	 * @note  This call does not require a prior initialization of the library.
	 * @ingroup W1Support
	*/
	bool 			Get_1w_Devices					(std::vector<std::string>& deviceList);

	/**
	 * @brief Check whether a 1wire device name refers to a DS18S20 or DS18B20 temperature sensor. 
	 *
	 * Use this function to check whether a 1wire device is kind of a temperature sensor DS18x20.
	 * @param pSensorID Device name to check.
	 * @return True if the device is a temperature sensor, otherwise false.
	 * @see For a simple example on how to use Is_DS18x20_Devices() refer to the demo DS18x20.cpp.\n
	 * @note  This call does not require a prior initialization of the library.
	 * @ingroup W1Support
	*/
	bool 			Is_DS18x20_Devices				(const char* pSensorID);

	/**
	 * @brief Retrieve temperature, CRC value and the time that was required to read the temperature.
	 *
	 * Use this function to check a DS18S20 sensor for its temperature in degree Celsius. The CRC
	 * value determines whether the transmission from the sensor was correct. The duration that was needed
	 * to retrieve the temperature value might get some indication on the noise of the bus. Typically
	 * the value should be below one second. 
	 * @param pSensorID Device name of sensor to retrieve the temperature from.
	 * @param temperature The temperature of the sensor. Note that a value of plain 85.000 degree Celsius 
	 *                    might refer to the power up default value and might not indicate a correct temperature!
	 * @param bCRC This value determines whether the transmission was correct or not.
	 * @param t_duration_ms This is the time that was required to get the temperature from the sensor.
	 * @return True if the device could be found, the temperature could be read and the CRC was correct.
	 * @see For a simple example on how to use Get_DS18x20_Temperature() refer to the demo DS18x20.cpp.\n
	 * @note  This call does not require a prior initialization of the library.
	 * @ingroup W1Support
	*/
	bool			Get_DS18x20_Temperature			(const char* pSensorID, double& temperature, bool& bCRC, long& t_duration_ms);




	// ************************************************************************************************
	// Deprecated functions
	// ************************************************************************************************

	// Used for testing purposes only.
	// Measures 2000 analog values while switching relays at the same time. 
	// Min and max values are printed out afterwards.
	void 			Test_AD_Board					();

} // namespace HuboLib




namespace BCM2835
{

	// ************************************************************************************************
	// BCM2835 GPIO 
	// ************************************************************************************************

	/**
	@defgroup BCM2835_GPIO BCM2835 GPIO support
	* Hubo library provides basic support to configuring, reading and writing of the BCM2835 GPIO pins. 
	* In contrast to the Hubo hardware related functions the execution of the GPIO related functions will take 
	* place in the context of the callers thread - hence they will not be propagated to the Hubo background 
	* thread. However, in order to support for better multi threading behaviour a mutex is applied to 
	* each of the functions entry in order to protect operations at thread level. The usage of the mutex can
	* be controlled through BCM2835_Config which provides a member to turn off the usage of the mutex for high 
	* performance operations. \n
	* Access to the BCM2835 is gained through the chips registers directly.\n
	* Hubo library will automatically detect the type of GPIO chip (BCM2708/BCM2709) during initialization. 
	* However, note that all pin numbering follows the BCM2835 pin numbering scheme - thus is not 
	* identical to the pin numbering of the GPIO pin headers of the various hardware versions of the Raspberry Pi! 
	*/

	/**
	 * @brief Prior to using a GPIO pin it requires to get defined for its use as input, output or one of the alternative functions.
	 *
	 * @see Please refer to FunctionSelect() for more information.
	 * @note  The library currently only supports functions for input and output. Pins however, can be used for alternative 
	 * functions though.
	 * @ingroup BCM2835_GPIO
	*/
	enum FunctionSelectType
	{
		Input  		= 0x00,   /*!< Pin is used as input  0b000 		*/
		Output  	= 0x01,   /*!< Pin is used as output 0b001 		*/
		Alternate0  = 0x04,   /*!< Alt. function 0  0b100			*/
		Alternate1  = 0x05,   /*!< Alt. function 1  0b101			*/
		Alternate2  = 0x06,   /*!< Alt. function 2  0b110			*/
		Alternate3  = 0x07,   /*!< Alt. function 3  0b111			*/ 
		Alternate4  = 0x03,   /*!< Alt. function 4  0b011 			*/
		Alternate5  = 0x02,   /*!< Alt. function 5  0b010 			*/
		FSEL_MASK  	= 0x07    /*!< Function select bits mask 0b111 	*/ 
	};

	/**
	 * @brief Pins configured as input can make use of internal pull up or down resistors.
	 *
	 * If no resistors are to be used then use PUD_OFF.
	 * @see Please refer to SetPullUpDown() for more information.
	 * @ingroup BCM2835_GPIO
	*/
	enum PullUpDownType
	{
		PUD_OFF     = 0x00,   /*!< Neither pull up nor poll down	0b00 */
		PUD_DOWN    = 0x01,   /*!< Pull down active 				0b01 */
		PUD_UP      = 0x02    /*!< Pull up active         			0b10 */
	};

	/**
	 * @brief Returns the status of the initialisation of the GPIO part of the library.
	 *  
	 * @return 	True if the GPIO interface was initialized correct. If the function returns false then 
	 * none of the GPIO interface functions must get called!
	 * @see For an example on how to use IsGPIOInitialized() refer to the demos GPIOInputOutput.cpp and RCSocket.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	bool    		IsGPIOInitialized 				();

	/**
	 * @brief Use FunctionSelect() to configure the mode of a BCM2835 pin.
	 *  
	 * A failure initializing the library is usually indicating a problem with insufficient
	 * user rights creating the memory map in order to access the BCM registers.
	 * @param pin The pin to configure to operate in one of the modes.
	 * @param mode One of the values of input, output or an alternative function.
	 * @see For more information see the enum type FunctionSelectType.
	 * For an example on how to use FunctionSelectPin() refer to the demos GPIOInputOutput.cpp and RCSocket.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	void 			FunctionSelectPin				(unsigned char pin, FunctionSelectType mode);
	
	/**
	 * @brief Sets or clears a pin configured to be an output.
	 *  
	 * If value is non zero the pin gets set otherwise the pin gets cleared.
	 * @param pin The output pin to modify.
	 * @param value the value to set the pin to (0 or 1).
	 * @see See also SetPin() and ClearPin().
	 * For an example on how to use WritePin() refer to the demo GPIOInputOutput.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	void 			WritePin            			(unsigned char pin, unsigned char value);

	/**
	 * @brief Sets a pin configured as output to 1.
	 *  
	 * This function is internally be used by WritePin().
	 * @param pi The output pin to set to 1.
	 * @see See also ClearPin() and WritePin().
	 * For an example on how to use SetPin() refer to the demos GPIOInputOutput.cpp and RCSocket.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	void 			SetPin							(unsigned char pin);

	/**
	 * @brief Resets a pin configured as output to 0.
	 *  
	 * This function is internally be used by WritePin().
	 * @param pi The output pin to reset to zero.
	 * @see See also SetPin() and WritePin().
	 * For an example on how to use ClearPin() refer to the demos GPIOInputOutput.cpp and RCSocket.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	void 			ClearPin						(unsigned char pin);

	/**
	 * @brief Enables or disables the BCM2835 internal pull -up or -down resistors for a pin configured as an input.
	 *  
	 * @param pin The input pin to apply or remove pull -up or -down resistors.
	 * @param pud The value to set - hence pull up, pull down or no resistor at all. 
	 * @see See also the enum type PullUpDownType.
	 * For an example on how to use SetPullUpDown() refer to the demo GPIOInputOutput.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	void 			SetPullUpDown					(unsigned char pin, PullUpDownType pud);

	/**
	 * @brief Reads the value of an (input) pin.
	 *  
	 * While this function is mainly be used on pins configured as inputs, it can also be used to read back the 
	 * values set to an output. This can be handy in order to check the state of an output pin in a multi threaded
	 * application where multiple threads set one and the same output.
	 * @param pin The pin to read from.
	 * @return The value of the pin. This can either be 0 or 1.
	 * @see For an example on how to use ReadPin() refer to the demo GPIOInputOutput.cpp.
	 * @ingroup BCM2835_GPIO
	*/
	unsigned short 	ReadPin							(unsigned short pin);

} // namespace BCM2835
		
#endif // HUBOLIB_H

