/// @file eyebot_sensors.hh
/// @author Joshua Petitt <petitj01@tartarus.uwa.edu.au>
/// @author Stefan Schmitt <sschmitt@ee.uwa.edu.au>
/// @version 1.0
/// @date 2003-06
/// 
/// Wrapper classes for EyeBot sensors.

#ifdef EYEBOT
#ifndef EYEBOT_SENSORS_HH
#define EYEBOT_SENSORS_HH

#include "base/base.hh"
#include "base/templates.hh"
#include "eyebot_hardware_sem.h"

namespace EyeMind {

/// Keypad sensor wrapper; Singleton
#if 0
class Keypad : public Port
{
private:
	/// Last key read.
	int key;

	/// Default constructor; initialize data members.
	Keypad();

	NO_COPYING(Keypad); ///< Prevent copying.
	
public:
	SINGLETON(Keypad);
		
	/// Returns read key.
	int Key(){ return key; }

	/// Read new key.
	virtual bool Update();
};
#endif


/// Number of Psd objects in static Psd list.
const unsigned PSD_LIST_SIZE = 4;


/// Psd sensor wrapper. This class cannot be instantiated directly (protected
/// constructor). You will have to derive a class calling the constructor with
/// the desired semantics in its default constructor.

class Psd : public Port
{
private:
	static Psd *psds[PSD_LIST_SIZE]; ///< List of other Psd objects.
	PSDHandle handle; ///< Handle for PSD functions.
	int x; ///< Distance.
	int dx;///< Differential distance.
	bool rawmode; ///< PSDGetRaw() or PSDGet()?

protected:
	Psd(DeviceSemantics device);

public:
	virtual ~Psd();

	/// @name Attribute manipulation functions
	//@{
	/// Choose PSDGet() or PSDGetRaw().
	void RawMode(bool m){ rawmode = m; dx = 0; x = 0; }
	bool RawMode(){ return rawmode; } ///< Return current mode setting.
	int X(){ return x; }   ///< Returns measured distance (mm or raw).
	int DX(){ return dx; } ///< Returns difference since last measurement.
	//@}

	/// Reread PSD data.
	virtual bool Update();
};



/// Left PSD wrapper; Singleton.

class PsdLeft : public Psd
{
private:
	///Default constructor; calls Psd constructor.
	PsdLeft() : Psd(PSD_LEFT){}

public:
	SINGLETON(PsdLeft);
};



/// Right PSD wrapper; Singleton.

class PsdRight : public Psd
{
private:
	///Default constructor; calls Psd constructor.
	PsdRight() : Psd(PSD_RIGHT){}

public:
	SINGLETON(PsdRight);
};



/// Front PSD wrapper; Singleton.

class PsdFront : public Psd
{
private:
	///Default constructor; calls Psd constructor.
	PsdFront() : Psd(PSD_FRONT){}

public:
	SINGLETON(PsdFront);
};



/// Front PSD wrapper; Singleton.

class PsdBack : public Psd
{
private:
	///Default constructor; calls Psd constructor.
	PsdBack() : Psd(PSD_BACK){}

public:
	SINGLETON(PsdBack);
};



/// Camera sensor class; Singleton.

class Camera : public Port
{
private:
	int cam_id; ///< Camera handle.
	colimage image; ///< Image taken by Camera.

	///Default constructor; init camera.
	Camera();

	NO_COPYING(Camera); ///< Prevent copying.

public:
	SINGLETON(Camera)

	/// Destructor; release camera.
	virtual ~Camera();

	/// Returns image.
	colimage* Image();

	/// Update image data.
	virtual bool Update();
};


// IRtv class; Singleton.
/// Returns last key press detected by IR.
class IRtv : public Port
{
private:
        int key;        ///< key currently pressed

        IRtv();         ///< Constructor
        NO_COPYING(IRtv);

public:
        SINGLETON(IRtv);
        virtual ~IRtv();

        virtual bool Update();

        int Key(){return key;}
};




/**Compass class; Singleton.
 * 
 * Returns an angle between -180 and 180 degrees
 *
 */
class Compass : public Port
{
private:
	int angle; ///< Current angle (degrees).

	Compass();  ///< Default constructor.

	NO_COPYING(Compass);

public:
	SINGLETON(Compass);

	virtual ~Compass();

	/// Returns current angle between -180 and 180
	int Angle();

	/// Update angle.
	virtual bool Update();
};


const unsigned DEFAULT_MICROPHONE_BUFFER_LENGTH = 100;
const unsigned DEFAULT_MICROPHONE_FREQUENCY = 5461;
const unsigned DEFAULT_MICROPHONE_SOUND_THRESHOLD = 256;
#if 0
/// Microphone class; Singleton.
class Microphone : public Port
{
private:
        int length;
        long freq;
        BYTE sndbuffer[DEFAULT_MICROPHONE_BUFFER_LENGTH];
        int sndthreshold;

        Microphone();   ///< Constructor
        NO_COPYING(Microphone);

public:
        SINGLETON(Microphone);
        virtual ~Microphone();

        ///< returns true if current sound level is above sndthreshold
        virtual bool Update();

        /// Record for length BYTES
        void Record(int length);

        /// Get a pointer to sound buffer with length of sample
        void GetSample(BYTE* b, unsigned* len);
};


const unsigned DEFAULT_RS232_BUFFER_LENGTH = 64;

/// SerialRS232 interface
class SerialRS232 : public Port
{
private:
        BYTE ibuffer[DEFAULT_RS232_BUFFER_LENGTH]; ///< incoming message buffer.
        BYTE obuffer[DEFAULT_RS232_BUFFER_LENGTH]; ///< outgoing message buffer.

        int ibuffer_length;             ///< length of message buffer.
        int obuffer_length;             ///< length of message buffer.
        int max_buffer_length;          ///< maximum length of message buffer.

        bool msg_flag;                  ///< true if new message in buffer

        SerialRS232();                  ///< constructor
        NO_COPYING(SerialRS232);

 public:
        SINGLETON(SerialRS232);
        virtual ~SerialRS232();

        /// Send/Receive the data.
        virtual bool Update();

        char* Message();                ///< Get the current message
        int Message(BYTE* mes);         ///< Send a message
        int Message(const char*);       ///< Send a message

        ///@name Attributes
        ///@{
        bool NewMessage(){ return msg_flag;}
        int MessageLength(){ return ibuffer_length; }
        void MessageLength(int l){obuffer_length=l; }
        int MaxMessageLength(){ return max_buffer_length; }
        void MaxMessageLength(int l){ max_buffer_length = l; }
        ///@}
};
#endif



const unsigned DEFAULT_RADIO_BUFFER_LENGTH = 64;

/// Wraps the radio comm.
/// @bug Sparingly documented.
class RadioComm:public Port
{
private:
	BYTE ibuffer[DEFAULT_RADIO_BUFFER_LENGTH]; ///< incoming message buffer.
	BYTE obuffer[DEFAULT_RADIO_BUFFER_LENGTH]; ///< outgoing message buffer.
	BYTE radio_id;                             ///< identification number.
	BYTE sender_id;                            ///< id number of message sender.

	int ibuffer_length;                ///< length of message buffer.
	int obuffer_length;	           ///< length of message buffer.
	int max_buffer_length;            ///< maximum length of message buffer.

	int error;                    ///< error flag.
	int error_count;              ///< error count.
	int max_error_count;          ///< maximum error count.

	bool msg_flag;                     

	
	RadioComm();   ///< Constructor
	
	NO_COPYING(RadioComm);

 public:
 
	SINGLETON(RadioComm);

	virtual ~RadioComm();

	/// Send/Receive the data.
	virtual bool Update();

	char* Message();              ///< Get the current message
	int Message(BYTE* mes);       ///< Send a message
	int Message(const char*);


	bool NewMessage(){ return msg_flag;}
	int MessageLength(){ return ibuffer_length; }
	void MessageLength(int l){obuffer_length=l; }
	int MaxMessageLength(){ return max_buffer_length; }
	void MaxMessageLength(int l){ max_buffer_length = l; }

	int RadioID(){return radio_id;}
};

}; // namespace EyeMind

#endif // EYEBOT_SENSORS_HH
#endif // EYEBOT



