/*---------------------------------------------------------------
	FILE: CSonarSRF10.h

   Part of the MRPT Library
   ISA - Universidad de Malaga - http://www.isa.uma.es

   Antonio J. Ortiz de Galisteo Duarte					Sept 2007
---------------------------------------------------------------*/
#ifndef CSonarSRF10_H
#define CSonarSRF10_H

#include <MRPT/HWDRIVERS/CInterfaceFTDI.h>
#include <MRPT/HWDRIVERS/CInterfaceFTDIMessages.h>
#include <MRPT/UTILS/CMRPTMessage.h>
#include <MRPT/UTILS/SYNCH.h>
#include <MRPT/UTILS/CDebugOutputCapable.h>
#include <MRPT/UTILS/CConfigFileBase.h>
#include <MRPT/MRML/CObservationRange.h>


//	NOTA MUY IMPORTANTE!!!!!
//		Para que el PC reconozca cualquier placa controladora de los Sonares, PRIMERO hay que conectar la placa al PC y
//		posteriormente conectar la alimentación de los sonares mediante el bus I2C, en otro caso el PC no reconocerá el dispositivo


namespace HWDRIVERS
{
	/**   This "software driver" implements the communication protocol for interfacing a Ultrasonic range finder SRF10 through a custom
	  *   USB RS-422 interface board.
      *   In this class the "bind" is ignored since it is designed for USB connections only, thus it internally generate the required object for simplicity of use.
	  *   The serial number of the USB device is used to open it on the first call to "doProcess", thus you must call "loadConfig" before this, or manually
	  *     call "setDeviceSerialNumber". The default serial number is "SONAR001"
	  *
	  * Warning: Avoid defining an object of this class in a global scope if you want to catch all potential
	  *      exceptions during the constructors (like USB interface DLL not found, etc...)
	  *
	  *  \code
	  *  PARAMETERS IN THE ".INI"-LIKE CONFIGURATION STRINGS:
	  * -------------------------------------------------------
	  *   [supplied_section_name]
	  *   SONAR_serialNumber=SONAR001
	  *   MaxRangeScan=350  //Maximun measured distance in cm
	  *   DeviceAddress = 0,1,2,3,..,15
	  *   Gain=6			//Gain = [0..15]
	  *
	  *		¡¡¡FALTA PONER UNA ESTRUCTURILLA PARA ALMACENAR LA POSE3D DE LOS 16 SONARES SOBRE EL ROBOT!!!
	  *
	  *  \endcode
	  *
	  */
	class CSonarSRF10 : public CDebugOutputCapable
	{
		private:
			CInterfaceFTDIMessages	m_usbConnection;
			UTILS::CMRPTMessage		msg;
			std::string				m_serialNumber;
			float					m_max_range_scan;
			int						m_gain;
			std::vector<int>		device_address;

			bool 		checkControllerIsConnected();

		public:
			/** Constructor
			  */
			CSonarSRF10();

			/** Destructor
			  */
			~CSonarSRF10(){}

			/** Loads specific configuration for the device from a given source of configuration parameters, for example, an ".ini" file,
			  *  loading from the section "[iniSection]" (see UTILS::CConfigFileBase and derived classes)
			  *  See HWDRIVERS::CSonarSRF10 for the possible parameters
		      */
			void  loadConfig(	const CConfigFileBase *configSource,
								const std::string	  &iniSection );

			void  loadConfig(	const std::string	&serial,
								const float			&maxrange,
								const int			&gain,
								int					&first_dir);

			/** Changes the serial number of the device to open (call prior to 'doProcess')
			  */
			void  setDeviceSerialNumber(const std::string &deviceSerialNumber)
			{
				m_serialNumber = deviceSerialNumber;
			}

			/** Loads specific configuration (max_range and gain)into the ultrasonic device previously loaded from a given source of configuration parameters
			  *  or the default one, in other case.
			  *	Si no se pone ninguna direccion se manda a toda la lista previamente almacenada, si se usa una direccion solo se configura
			  * el dispositivo especifico de esa dir.
			  */
			bool SetConfigToDevice(int direcc=-1);

			/** Specific Ultrasonic range finder "software drivers" must process here new data from the I/O stream.
			  *  This method will be typically called in a different thread than other methods, and will be called in a timely fashion.
			  *  The parameter "type" set the measurement format:
			  *		type = 0 --> cm
			  *		type = 1 --> inch
			  *		type = 2 --> time of flight
			  *
			  *		SI OUTOBSERVATION ES UNA LISTA VACIA SE ESCRIBE LA MEDIDA EN LA PRIMERA POSICIÓN, SI YA CONTIENE ALGUN VALOR
			  *		SE REDIMENSIONA Y SE AÑADE LA MEDICIÓN AL FINAL
			  *
			  *		SI LA LECTURA ES DE TODOS LOS SONARES, ¡¡NO!! HAY INTERFERENCIA ENTRE SUS MEDIDAS YA QUE ES SECUENCIAL, NO SIMULTANEA ;D
			  *
			  */
			void  doProcess(MRML::CObservationRange	&outObservation,
							 int						type=0,
							 int						direcc=-1);

	};	// End of class

} // End of namespace


#endif
