home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 8
/
CDASC08.ISO
/
NEWS
/
677
/
ISC
/
SERIAL
/
SERIAL.CPP
< prev
next >
Wrap
Text File
|
1993-10-07
|
5KB
|
201 lines
///////////////////////////////////////////////////////////////////////////
// //
// File: serial.cpp //
// started on: 5/2/92 //
// //
///////////////////////////////////////////////////////////////////////////
// //
// This class sends and receives data via interrupt driven Serial //
// engine. very comfortable interface (I think). Might not work on //
// slow machines in high baud rates (after all it's written in a high //
// level language). //
// //
///////////////////////////////////////////////////////////////////////////
// //
// by Ofer Laor (AKA LeucroTTA) //
// //
///////////////////////////////////////////////////////////////////////////
#include "serial.h"; // SERIAL_PORT.
#include <dos.h> // inportb, outportb, enable, disable.
// sends top byte out.
//
void SERIAL_PORT::do_send(void)
{
BYTE out_byte;
BUFF_OP buff_op;
if (out_buff.len()==0) {
return;
}
do_send_recursive_count++;
if (do_send_recursive_flag)
return;
do_send_recursive_flag= TRUE;
// add one more to the recursive_count, just in case
// a misplaced interrupt does not occur (spare...).
//
for (do_send_recursive_count++ ;do_send_recursive_count!= 0;do_send_recursive_count--) {
if (out_buff.len()==0) {
do_send_recursive_count= 0;
break;
}
// check for flow control.
//
flow_check();
// if flow is not enabled, exit outtahere.
//
if (!flow_enabled) {
do_send_recursive_flag= FALSE;
return;
}
// TX_REGS EMPTY!
buff_op= (out_buff>> out_byte);
if (buff_op> BUFF_OK_START_POINT) {
// sending a byte, so turn send_sema on.
while (!(inportb(com_port+ LSR) & 0x20))
;//TX REGS not both empty!
outportb (com_port+ DATA, out_byte);
}
}
do_send_recursive_flag= FALSE;
}
// serial_port - interrupt service routine.
//
void SERIAL_PORT::isr ()
{
INT_ID cause;
BYTE temp;
do {
cause= INT_ID(inportb(com_port+ IID));
switch (cause) {
case RX_INT:
temp= inportb(com_port+ DATA);
if (!flow_set(temp))
in_buff<< temp;
break;
case TX_INT:
do_send();
break;
case MODEM_STATUS_INT:
// call msr_int with the new msr.
//
msr_int(inportb (com_port+ MSR));
do_send();
break;
case LINE_STATUS_INT:
temp= inportb(com_port+ LSR);
// break has been received.
//
if (temp& 0x10)
com_break();
// error has been received.
//
if (temp& 0xe)
com_error();
break;
case NO_INT_ACTIVE:
default:
// support other com handlers...
// (*old_vect)();
break;
}
} while (cause!= NO_INT_ACTIVE);
eoi(); // 8259A EOI.
set_imr(); // fix td's Bpt BUG!!!!
}
// outputting a char (to the serial_port).
//
OPERATION SERIAL_PORT::operator << (const BYTE out_byte)
{
BUFF_OP buff_op;
buff_op= out_buff<< out_byte;
if ((inportb(com_port+ LSR)& 0x20))
do_send();
return ((buff_op== BUFF_OVERFLOW)? OP_FAILURE: OP_SUCCESSFUL);
}
// inputting a char (from the serial_port).
//
OPERATION SERIAL_PORT::operator >> (BYTE& in_byte)
{
if ((in_buff>> in_byte)< BUFF_OK_START_POINT)
return OP_FAILURE;
return OP_SUCCESSFUL;
}
// peeking on the input char...
//
OPERATION SERIAL_PORT::operator > (BYTE& peek_byte)
{
if ((in_buff> peek_byte)< BUFF_OK_START_POINT)
return OP_FAILURE;
return OP_SUCCESSFUL;
}
unsigned SERIAL_PORT::output_buff_len(void)
{
return out_buff.len();
}
unsigned SERIAL_PORT::input_buff_len(void)
{
return in_buff.len();
}
// empty both in and out buffers.
//
void SERIAL_PORT::empty_io_buffers(void)
{
out_buff.empty_buff();
in_buff.empty_buff();
}
// set controls...
//
void SERIAL_PORT::set_controls(BYTE mcr)
{
mcr|= 0x8; // out2= on.
outportb(com_port+ MCR, mcr);
}