//==========================================================================
//
//  Communication package: Definitions
//
//  E. Franssen                 (C) n.v. dZine
//
//==========================================================================

#ifndef COM_INCLUDED
#define COM_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

#ifndef uchar
  #define uchar unsigned char
#endif

#ifndef uint
  #define uint  unsigned int
#endif

#ifndef ulong
  #define ulong unsigned long
#endif

/*----------------------------------------------------------------------*/
/*                      COMMUNICATION structure                         */
/*----------------------------------------------------------------------*/
typedef struct scom
{
    /*------------------------------------------------------------------*/
    uchar far *r_begin;         /* ptr to buffer receive begin          */
    uchar far *r_end;           /* ptr to buffer receive end            */
    uchar far *r_put;           /* ptr to put next byte received        */
    uchar far *r_get;           /* ptr to get next byte received        */
    /*------------------------------------------------------------------*/
    uchar far *t_begin;         /* ptr to buffer transmit begin         */
    uchar far *t_end;           /* ptr to buffer transmit end           */
    uchar far *t_put;           /* ptr to put next transmit byte        */
    uchar far *t_get;           /* ptr to get next transmit byte        */
    /*------------------------------------------------------------------*/
    uint  r_count;              /* count of unread bytes received       */
    uint  t_count;              /* count of untransmitted bytes         */
    uint  r_error;              /* error count of received bytes        */
    uchar l_ctrl;               /* 8250 line control                    */
    uchar l_stat;               /* 8250 line status                     */
    uchar m_ctrl;               /* 8250 modem control                   */
    uchar m_stat;               /* 8250 modem status                    */
    uint  i8250;                /* 8250 I/O base address                */
    int unget;                  /* value from unget_8250()              */
    uchar irq;                  /* 8250 interrupt level                 */
    uchar handshake;            /* buffer hardware handshake            */
    uchar f_tstop;              /* transmit stop flow                   */
    uchar f_tstart;             /* transmit restart flow                */
    uchar f_rstop;              /* receive stop flow                    */
    uchar f_rstart;             /* receive restart flow                 */
    uchar f_status;             /* flow soft status - b0: rx, b1: tx    */
    uchar t_idle;               /* 1 = idle, 0 = Tx-ing under interrupt */
    /*------------------------------------------------------------------*/
    void (interrupt far *oldhandler)(); /* Old interrupt handler        */
    uchar old_ier;              /* Old registers, saved in com_open(),  */
    uchar old_l_ctrl;           /* and restored in com_close()          */
    uchar old_m_ctrl;           /*        Old values                    */
    uchar old_pic_state;        /*         "    "                       */
    uint  old_baudrate;         /*         "    "                       */
    /*------------------------------------------------------------------*/
    uint (_far *urx)(uchar c,void *uptr);
                                /* Ptr to User interrupt Rx handler     */
    uint (_far *utx)(void *uptr);
                                /* Ptr to User interrupt Tx handler     */
    void *uptr;                 /* Ptr to user data                     */
} COM;

/*----------------------------------------------------------------------*/
/*              Definitions used in communication driver                */
/*----------------------------------------------------------------------*/
enum COM_PORT
{                                       /* Com port definitions         */
    COM_1 = 0,
    COM_2,
    COM_3,
    COM_4,
    COM_5,
    COM_6,
    COM_7,
    COM_8,
    COM_PCOUNT,
    DIGICOM_PFIRST = COM_PCOUNT,
    DIGICOM_1 = DIGICOM_PFIRST,
    DIGICOM_2,
    DIGICOM_3,
    DIGICOM_4,
    DIGICOM_5,
    DIGICOM_6,
    DIGICOM_7,
    DIGICOM_8,
    DIGICOM_9,
    DIGICOM_10,
    DIGICOM_11,
    DIGICOM_12,
    DIGICOM_13,
    DIGICOM_14,
    DIGICOM_15,
    DIGICOM_16,
    DIGICOM_PCOUNT = 16
};

enum COM_BAUDRATE
{                                       /* Baudrate definitions         */
    COM_B50 = 0,
    COM_B75,
    COM_B110,
    COM_B150,
    COM_B300,
    COM_B600,
    COM_B1200,
    COM_B2400,
    COM_B4800,
    /*COM_B6776,*/
    COM_B7200,
    COM_B9600,
    COM_B11520,
    COM_B12800,
    COM_B14400,
    COM_B19200,
    COM_B38400,
    COM_B57600,
    COM_B115200,
    COM_BCOUNT
};

enum COM_FORMAT
{                                       /* Format definitions           */
    COM_F7BNP1S = 0,
    COM_F7BNP2S,
    COM_F7BEP1S,
    COM_F7BEP2S,
    COM_F7BOP1S,
    COM_F7BOP2S,
    COM_F8BNP1S,
    COM_F8BNP2S,
    COM_F8BEP1S,
    COM_F8BOP1S,
    COM_F8BEP2S,
    COM_F8BOP2S,
    COM_FCOUNT
};

#define COM_URX_NONE        (0x0000)
#define COM_URX_PROCESS     (0x0100)
#define COM_UTX_FINISHED    (0x0000)
#define COM_UTX_PROCESS     (0x0100)
#define COM_UTX_LAST        (0x0200)    // Same functionality as UTX_PROCESS
                                        // (compatibility with CDF on a digicom)

#define COM_CURRENT     (-1)            /* Current value for dtr, rts, ...  */
#define COM_RESTORE     (-2)            /*    "      "   ,see com_close()   */

#define COM_CTS         0x10
#define COM_DSR         0x20
#define COM_RI          0x40
#define COM_DCD         0x80
#define COM_RTS         0x02

/*----------------------------------------------------------------------*/
/*                              Macro's                                 */
/*----------------------------------------------------------------------*/

/*----------------------------------------------------------------------*/
/*              Functions declarations for strong type checking         */
/*----------------------------------------------------------------------*/
uint com_define(uint port,uint irq,uint addr,uchar _far *rxbuffer,
                uint rxsize,uchar _far *txbuffer,uint txsize,COM *com);
uint com_open(int baudrate,int format,int dtr,int rts,COM *com);
uint com_close(int baudrate,int format,int dtr,int rts,COM *com);
uint com_undefine(COM *com);
void com_reset(COM *com);
int  com_rx(COM *com);
int  com_tx(uchar c,COM *com);
int  com_tx_buf(void *pbuf, int buflen, COM *com);
int  com_tx_string(char *s, COM *com);
uint com_rx_available(COM *com);
uint com_tx_free(COM *com);
uint com_tx_busy(COM *com);
uint com_baudrate(int baudrate,COM *com);
uint com_format(int format,COM *com);
uint com_dtr(int dtr,COM *com);
uint com_rts(int rts,COM *com);
uint com_handshake(uint mode,COM *com);
uint com_status(COM *com);
uint com_check(uint i8250);
int  com_num_to_baudrate(long num_baudrate);
long com_baudrate_to_num(int baudrate);
uint (_far *com_set_urxhandler(uint (_far *urx)(uchar c,void *uptr), COM *com))();
uint (_far *com_set_utxhandler(uint (_far *utx)(void *uptr), COM *com))();
void com_start_tx(uchar c,COM *com);
void *com_set_uptr(void *uptr,COM *com);
void digicom_bg(COM *com); 

/**************************************************************************
*
* Instruct the COM to switch to a local stack when calling
* an URX and/or UTX handler from within interrupt.
*
* ustack:       ptr to the buffer
* ustack_size:  size of buffer
*
* use ustack_size == 0 to remove the local stack
*
* !!! WARNING: size must be big enough, e.g. 512 bytes
*              (depends on stack usage by u?x handlers)
*
* Return:       none
*
*/
void com_set_ustack(char __far *ustack, int ustack_size);

#ifdef __cplusplus
}
#endif

#endif
