/***************************************************************************
These C++ classes are copyright 1990, by William Herrera.
All those who put this code or its derivatives in a commercial product MUST
mention this copyright in their documentation for users of the products in
which this code or its derivative classes are used.  Otherwise, this code
may be freely distributed and freely used for any purpose.

Enhancements: 1991 by David Orme
	*  General cleanup.
			- I/O now takes advantage of C++ overloading.
			- Serial port I/O functionality now only in Serial class.
			- Modem functionality now only in Modem class.
	*  Possible to easily implement file Xfr prots now.
	*  CCITT CRC-16 class added							-- 2-20-1991
	*  BIOS Timer class added								-- 2-22-1991
	*  Optional timeout on all input routines added	-- 2-25-1991

***************************************************************************/

// File comports.hpp
// Class definition for COM1, COM2, COM3, and COM4 classes.

#ifndef COMPORTS_HPP
#define COMPORTS_HPP 1

#include "uart.hpp"
#include "charqueu.hpp"

static void DoNothing() { return; }

#ifdef __TURBOC__


#define DECLARE_COMXa(COM, x, driver)                           \
                                                                \
class COM##x : public uart                                      \
{                                                               \
    friend void interrupt driver##x(...);                       \
    friend class SerialPort;                                    \
protected:                                                      \
    static CharQueue * inq;                                     \
    static CharQueue * outq;                                    \
    static DRIVER driver;                                       \
    static COM##x * this_ptr;/* allows driver to get to this */ \
	void (*DoIfNoCarrier)(); /* by default does nothing. */     \
	void (*DoOnRing)();		 /* by default does nothing. */     \
public:                                                         \
    COM##x();                                                   \
    ~COM##x();                                                  


#define DECLARE_COMXc(COM, x, driver)                           \
    virtual void SetDoIfNoCarrier(void (*f)());                 \
	virtual void SetDoOnRing(void (*f)());						\
    virtual void SendChar(char ch);                             \
    virtual int GetChar();                                      \
    void PurgeInput() { inq->Purge(); }                         \
    void FlushOutput();                                         \
    void PurgeOutput() { outq->Purge(); }                       \
    boolean InputEmpty() { return inq->IsEmpty(); }             \
    boolean OutputEmpty() { return outq->IsEmpty(); }           \
    boolean OutputReady() { return (boolean)!outq->IsFull(); }  \
};                                                              \
void interrupt driver##x(...);                                  




#else ifdef __ZTC__

#define DECLARE_COMXa(COM, x, driver)                           \
                                                                \
class COM##x : public uart                                      \
{                                                               \
    friend int _cdecl driver##x(struct INT_DATA *);             \
    friend class SerialPort;                                    \
protected:                                                      \
    static CharQueue * inq;                                     \
    static CharQueue * outq;                                    \
    static DRIVER driver;                                       \
    static COM##x * this_ptr;/* allows driver to get to this */ \
    void (*DoIfNoCarrier)(); /* by default does nothing. */     \
	void (*DoOnRing)();		 /* by default does nothing. */     \
public:                                                         \
    COM##x();                                                   \
    ~COM##x();                                                  


#define DECLARE_COMXc(COM, x, driver)					    \
    virtual void SetDoIfNoCarrier(void (*f)());                 \
	virtual void SetDoOnRing(void (*f)());						\
    virtual void SendChar(char ch);                             \
    virtual int GetChar();                                      \
    void PurgeInput() { inq->Purge(); }                         \
    void FlushOutput();                                         \
    void PurgeOutput() { outq->Purge(); }                       \
    boolean InputEmpty() { return inq->IsEmpty(); }             \
    boolean OutputEmpty() { return outq->IsEmpty(); }           \
    boolean OutputReady() { return (boolean)!outq->IsFull(); }  \
};                                                              \
int _cdecl driver##x(struct INT_DATA *);

                        

#endif



#define DECLARE_COMXb1                                          \
    unsigned int LCR() { return 0x3FB; }                        \
    unsigned int DLL() { return 0x3F8; }                        \
    unsigned int DLM() { return 0x3F9; }                        \
    unsigned int LSR() { return 0x3FD; }                        \
    unsigned int MCR() { return 0x3FC; }                        \
    unsigned int MSR() { return 0x3FE; }                        \
    unsigned int THR() { return 0x3F8; }                        \
    unsigned int RBR() { return 0x3F8; }                        \
    unsigned int IER() { return 0x3F9; }                        \
    unsigned int IIR() { return 0x3FA; }                        

#define DECLARE_COMXb2                                          \
    unsigned int LCR() { return 0x2FB; }                        \
    unsigned int DLL() { return 0x2F8; }                        \
    unsigned int DLM() { return 0x2F9; }                        \
    unsigned int LSR() { return 0x2FD; }                        \
    unsigned int MCR() { return 0x2FC; }                        \
    unsigned int MSR() { return 0x2FE; }                        \
    unsigned int THR() { return 0x2F8; }                        \
    unsigned int RBR() { return 0x2F8; }                        \
    unsigned int IER() { return 0x2F9; }                        \
    unsigned int IIR() { return 0x2FA; }                        

#define DECLARE_COMXb3                                          \
    unsigned int LCR() { return 0x2EB; }                        \
    unsigned int DLL() { return 0x2E8; }                        \
    unsigned int DLM() { return 0x2E9; }                        \
    unsigned int LSR() { return 0x2ED; }                        \
    unsigned int MCR() { return 0x2EC; }                        \
    unsigned int MSR() { return 0x2EE; }                        \
    unsigned int THR() { return 0x2E8; }                        \
    unsigned int RBR() { return 0x2E8; }                        \
    unsigned int IER() { return 0x2E9; }                        \
    unsigned int IIR() { return 0x2EA; }                        

#define DECLARE_COMXb4                                          \
    unsigned int LCR() { return 0x3EB; }                        \
    unsigned int DLL() { return 0x3E8; }                        \
    unsigned int DLM() { return 0x3E9; }                        \
    unsigned int LSR() { return 0x3ED; }                        \
    unsigned int MCR() { return 0x3EC; }                        \
    unsigned int MSR() { return 0x3EE; }                        \
    unsigned int THR() { return 0x3E8; }                        \
    unsigned int RBR() { return 0x3E8; }                        \
    unsigned int IER() { return 0x3E9; }                        \
    unsigned int IIR() { return 0x3EA; }                        



// declare COM1 through COM4 here.

#define DECLARE_COM1              \
DECLARE_COMXa(COM, 1, driver)     \
DECLARE_COMXb1                    \
DECLARE_COMXc(COM, 1, driver)     

#define DECLARE_COM2              \
DECLARE_COMXa(COM, 2, driver)     \
DECLARE_COMXb2                    \
DECLARE_COMXc(COM, 2, driver)     

#define DECLARE_COM3              \
DECLARE_COMXa(COM, 3, driver)     \
DECLARE_COMXb3                    \
DECLARE_COMXc(COM, 3, driver)     

#define DECLARE_COM4              \
DECLARE_COMXa(COM, 4, driver)     \
DECLARE_COMXb4                    \
DECLARE_COMXc(COM, 4, driver)     


// here we declare COM1 through COM4. Change to suit

DECLARE_COM1

DECLARE_COM2

DECLARE_COM3

DECLARE_COM4

#endif

