home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C++ Games Programming
/
CPPGAMES.ISO
/
thx
/
source
/
theatrix
/
serial.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-09
|
4KB
|
143 lines
// --------- serial.cpp
#include "serial.h"
static void interrupt (*oldtimer)(...);
static void interrupt (*oldcomint)(...);
Timer CommPort::serialtimer;
CommPort *CommPort::mp_CommPort;
// ------ ISRs to count timer ticks
void interrupt newtimer(...)
{
(*oldtimer)();
if (CommPort::serialtimer.running())
CommPort::serialtimer.countdown();
}
// ---- serial input interrupt service routine
void interrupt newcomint(...)
{
CommPort::mp_CommPort->CommInterrupt();
}
void CommPort::CommInterrupt()
{
int c;
outp(PIC00,EOI);
if (mp_nextin == mp_recvbuff+BufSize)
mp_nextin = mp_recvbuff; // circular buffer
c = inp(RxData()); // read the input
if (xonxoff_enabled)
if (c == xoff) /* test XON */
waiting_for_xon = true;
else if (c == xon) /* test XOFF */
waiting_for_xon = false;
if (!xonxoff_enabled || (c != xon && c != xoff)) {
*mp_nextin++ = (char) c; /* put char in buff*/
buffer_count++;
}
if (xonxoff_enabled && !waiting_to_send_xon &&
buffer_count > Threshold) {
while ((inp(LineStatus()) & XmitDataReady) == 0)
;
outp(TxData(), xoff); /* send XOFF */
waiting_to_send_xon = true;
}
}
CommPort::CommPort(const CommParameters& cp) : commparms(cp)
{
mp_CommPort = this;
mp_recvbuff = new char[BufSize];
mp_nextin = mp_nextout = mp_recvbuff;
xonxoff_enabled = true;
buffer_count = 0;
waiting_for_xon = false;
waiting_to_send_xon = false;
oldtimer = 0;
oldcomint = 0;
timeout = 10;
Initialize();
}
CommPort::~CommPort()
{
delete mp_recvbuff;
if (oldcomint) {
setvect(vector(), oldcomint);
oldcomint = 0;
}
if (oldtimer) {
setvect(systimer, oldtimer);
oldtimer = 0;
}
}
/* -------- initialize the com port ----------- */
void CommPort::Initialize()
{
initcom.initbits.parity = commparms.parity == 2 ? 3 : commparms.parity;
initcom.initbits.stopbits = commparms.stopbits-1;
initcom.initbits.wordlen = commparms.databits-5;
initcom.initbits.brk = 0;
initcom.initbits.divlatch = 1;
outp(LineCtl(), initcom.initchar);
outp(DivLSB(), (char) ((115200L/commparms.baud) & 255));
outp(DivMSB(), (char) ((115200L/commparms.baud) >> 8));
initcom.initbits.divlatch = 0;
outp(LineCtl(), initcom.initchar);
/* ---- intercept the timer interrupt vector ----- */
if (oldtimer == 0) {
oldtimer = getvect(systimer);
setvect(systimer, newtimer);
}
/* ------ hook serial interrupt vector --------- */
if (oldcomint == 0) {
oldcomint = getvect(vector());
setvect(vector(), newcomint);
}
outp(ModemCtl(), (inp(ModemCtl()) | DTR | RTS | OUT2));
outp(PIC01, (inp(PIC01) & ComIRQ()));
outp(IntEnable(), DataReady);
outp(PIC00, EOI);
/* ----- flush any old interrupts ------ */
inp(RxData());
inp(IntIdent());
inp(LineStatus());
inp(ModemStatus());
}
int CommPort::readcomm()
{
CommPort::serialtimer.set(timeout);
while (!input_char_ready())
if (CommPort::serialtimer.timed_out())
return 0;
if (mp_nextout == mp_recvbuff+BufSize)
mp_nextout = mp_recvbuff;
--buffer_count;
if (waiting_to_send_xon && buffer_count < SafetyLevel) {
waiting_to_send_xon = false;
writecomm(xon);
}
return *mp_nextout++;
}
bool CommPort::writecomm(int ch)
{
while (waiting_for_xon)
;
CommPort::serialtimer.set(timeout);
while ((inp(LineStatus()) & XmitDataReady) == 0)
if (CommPort::serialtimer.timed_out())
return false;
outp(TxData(), ch);
return true;
}
void CommPort::clear_serial_queue()
{
mp_nextin = mp_nextout = mp_recvbuff;
buffer_count = 0;
}