//=========================================================================
// Summary  : */
// Filename : SerialDevice.h
// Author   : */
// Project  : */
// Revision : 1
// Created  : 2000/08/19
// Modified : 2000/08/19
//=========================================================================
// Description :
//=========================================================================
#ifndef _SERIALDEVICE_H
#define _SERIALDEVICE_H

#include "Windows.h"
#include "Exception.h"
#include <stdio.h>
#include <string>


//#define ERROR -1
#define OK     0
typedef long speed_t;


class SerialDevice 
{
public:

  class TimedOut : public Exception {

  public:

    TimedOut(int nBytesRead);

    int nBytesRead();

  protected: 

    // Number of bytes read before timeout occurred
    int _nBytes;
  };
   

  class BufferFull : public Exception {

  public:

    BufferFull();

  };

  class BadSystemCall : public Exception {

  public:

    BadSystemCall(char *systemCall);

  };


  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] ttyName: /dev/name for serial device
  SerialDevice(const char *ttyName);

  virtual ~SerialDevice();

  ///////////////////////////////////////////////////////////////////
  // getFd - Returns file descriptor for tty device
  int getFd();

  ///////////////////////////////////////////////////////////////////
  // devName - Returns device name for tty device
  const char* devName();

  ///////////////////////////////////////////////////////////////////
  // nonBlocking - Sets device to non-blocking mode
  int nonBlocking();

  ///////////////////////////////////////////////////////////////////
  // blocking - Sets device to blocking mode
  int blocking();

  ///////////////////////////////////////////////////////////////////
  // raw - Sets device to a "raw" input mode
  int raw();

  ///////////////////////////////////////////////////////////////////
  // nonRaw - Sets device to a "cooked" input mode
  int nonRaw();

  ///////////////////////////////////////////////////////////////////
  // sendBreak - Sends a break to the device
  int sendBreak();

  ///////////////////////////////////////////////////////////////////
  // sendBreak - Send break of user specified duration to device
  int sendBreak(int milliseconds);

  ///////////////////////////////////////////////////////////////////
  // read - reads chars from port into the string reply until a
  // termination character is received or until timeout (in millisecs)
  // elapses. A timeout value of 0 performs a blocking read 
  // assumes memory already allocated for reply.
  // log diagnostics if enable by CommDebugMode
  virtual int readNChars( char *buf, int count, int timeout );

  virtual int read(char *buf, int maxBytes, int timeout);
//    throw (TimedOut, BadSystemCall);


  ///////////////////////////////////////////////////////////////////
  // writeData - clear read buffer, then send message to port,
  // log diagnostics if enable by CommDebugMode
  virtual int write(const char *buf, int nBytes);
  virtual int writeRepeat( const char *buf, int nBytes, int reps );

  // dummy version to parallel the QNX side
  virtual int writeFlush(const char *buf, int nBytes)
	{ return write(buf,nBytes); };

  ///////////////////////////////////////////////////////////////////
  // Reset device
  virtual void reset();

  enum CommsDebugMode {
    DebugOn, DebugOff
  };

  ///////////////////////////////////////////////////////////////////
  // commsDebugMode - Sets Communications Debug Mode (Default is off)
  void commsDebugMode(CommsDebugMode mode);

  ///////////////////////////////////////////////////////////////////
  struct lineFormat {
       speed_t baud;
       int data, stop;
       const char *parity;
  };

  ///////////////////////////////////////////////////////////////////
  // SetLineFormat
  // [input] baud: baud rate
  // [input] data: data bits
  // [input] stop: stop bits (1 or 2)
  // [input] parity: parity setting (NONE, EVEN, ODD)
  int setLineFormat(speed_t baud, int data, int stop, const char *parity);
  inline int setLineFormat( lineFormat *inFmt ) 
    { return setLineFormat( inFmt->baud, inFmt->data, 
			    inFmt->stop, inFmt->parity ); };

  ///////////////////////////////////////////////////////////////////
  // nRecvdBytes - Returns number of bytes in the receive buffer
  int nRecvdBytes();

  void clearPort();

  ///////////////////////////////////////////////////////////////////
  // flushReceiveBuf - checks to see if there are any chars to read from port,
  // and if so it reads and discards them.
  int flushReceiveBuf();

  ///////////////////////////////////////////////////////////////////
  // reads characters into buffer until string is received from device
//  int readUntil(char *buf, int maxBytes, char *term, int timeout) 
//    throw (TimedOut, BufferFull, BadSystemCall);

  ///////////////////////////////////////////////////////////////////
  // Confirm that a string was received from device
//  int readUntil(char *term, int timeout)
//    throw (TimedOut, BadSystemCall);

  ///////////////////////////////////////////////////////////////////
  // Confirm that a string was received from device
  int confirm(char *term, int timeout);

  void printTermios();

protected:

  int NonBlocking();
  int Blocking();

private:

  HANDLE _hComm;   // the port handle
  char* _pcName;

  CommsDebugMode  _commsDebugMode;

  int csetStopBits(struct termios *termios_p, int stopBits );
  int csetDataBits(struct termios *termios_p, int dataBits );
  int csetParityBits(struct termios *termios_p, const char *parity);

  int _baud;
};

#endif


