home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
ISC366.ZIP
/
SERIAL
/
SERIALSE.CPP
< prev
next >
Wrap
Text File
|
1993-09-01
|
8KB
|
270 lines
///////////////////////////////////////////////////////////////////////////
// //
// File: serialse.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> // outportb, inportb
const unsigned long SERIAL_PORT::BAUD_CONST = 115200L;
const unsigned BUFF_SIZE= 256; // communication buffer size.
// sets the imr to enable the hardware interrupt request line.
//
void SERIAL_PORT::set_imr(void)
{
outportb (com_pic_port+ PIC_IMR, (inportb (com_pic_port+ PIC_IMR) & com_imr_mask));
}
// sends an eoi to the pic.
//
void SERIAL_PORT::eoi(void)
{
outportb (com_pic_port+ PIC_DATA, 0x20); // send pic eoi message.
}
// update flow_enabled.
//
void SERIAL_PORT::flow_check(void)
{
flow_enabled= TRUE;
}
// error has been received.
//
void SERIAL_PORT::com_error(void)
{
// read twice to try and free the error.
inportb(com_port+ DATA);
inportb(com_port+ DATA);
}
// set up the serial port.
//
void SERIAL_PORT::set_up_port( const long baud_rate, const BYTE word_len,
const BYTE parity, const BYTE stop_bits)
{
// if already initialized, exit.
//
if (InitFlag)
return;
outportb (com_port+ LCR, 0x80); // set DLAB
outport (com_port+ BAUDLOW, (unsigned)(BAUD_CONST / baud_rate));
// LCR is eventual going to be set to temp.
//
BYTE temp= 0; // DLAB= 0;
temp&=0xc7; // clear parity.
switch (parity) {
case 'N': // no parity
temp|= 0x0;
break;
case 'O': // ODD parity.
temp|= 0x8;
break;
case 'E': // EVEN parity.
temp|= 0x18;
break;
case 'M': // MARK.
temp|= 0x28;
break;
case 'S': // SPACE.
temp|= 0x38;
break;
}
temp&=0xfb; // clear stop bits.
switch (stop_bits) {
case 1: // one stop bit.
break;
case 2: // two stop bits.
temp|= 0x4;
}
temp&=0xfc; // clear word len.
switch (word_len) {
case 5: // word len= 5.
break;
case 6: // word len= 6.
temp|= 0x1;
break;
case 7: // word len= 7.
temp|= 0x2;
break;
case 8: // word len= 8.
temp|= 0x3;
break;
}
outportb (com_port+ LCR, temp); // set LCR to options.
}
// the constructor gets as parameters- the port number associated with the
// serial port, as well as the HARDWARE interrupt number it is attached to,
// the software interrupt it generates and the PIC port that holds it.
//
SERIAL_PORT::SERIAL_PORT (const unsigned port_num,
const unsigned irq_line_num,
const unsigned int_num,
const unsigned pic_port_num= 0x20) : ISC()
{
InitFlag= FALSE;
// setup serial_port parameters.
activate(port_num, irq_line_num, int_num, pic_port_num);
}
void SERIAL_PORT::activate (const unsigned port_num,
const unsigned irq_line_num,
const unsigned int_num,
const unsigned pic_port_num= 0x20)
{
// if already initialized, exit.
//
if (InitFlag)
return;
// initializing do_send vars.
do_send_recursive_count= 0;
do_send_recursive_flag= FALSE;
// resize I/O buffers.
in_buff.reset_size(BUFF_SIZE, TRUE);
out_buff.reset_size(BUFF_SIZE, TRUE);
// the serial's port.
com_port= port_num;
// hardware interrupt request line num.
com_imr_mask= ~(0x1 << irq_line_num); // all "1" except a "0" on the line request...
// hardware interrupt num.
com_int= int_num;
// default imr_port is 0x20.
//
com_pic_port= pic_port_num;
// now hook interrupts via ISC.
//
ISC::activate(com_int);
outportb (com_port+ IER, 0xF); // enable UART interrupts on all calls!!!
// clear RCV buffers
inportb (com_port+ LSR); // clear LSR.
inportb (com_port+ DATA); // clear RX register.
inportb (com_port+ MSR); // clear MSR register.
inportb (com_port+ IID); // read IID register (to clear it's Flip-Flop flag).
// repeat all readings to be sure they are clear.
if (inportb (com_port+ IID) & 1) {
// repeat the clearing...
inportb (com_port+ LSR); // clear LSR
inportb (com_port+ DATA); // clear RX register
inportb (com_port+ MSR); // clear MSR register
}
// and now enable the modem's interrupt enable.
outportb (com_port+ MCR, (inportb(com_port+ MCR)| 8)); // write it into MCR. (turn on OUT2).
// 8259A programming...
set_imr(); // setup imr.
eoi(); // send pic an EOI just to be sure.
// allow derived classes to extend the initialization of the port.
//
extended_init();
// default port settings.
set_up_port (9600,8,'N',1);
}
// this constructor gets a single number from 1 to 4 (must be a legal serial
// port- it does not test it's validity), and hooks to it.
//
SERIAL_PORT::SERIAL_PORT (const unsigned com_num) : ISC()
{
InitFlag= FALSE;
// setup serial port parameters.
activate(com_num);
}
// setup parameters.
//
void SERIAL_PORT::activate(const unsigned com)
{
unsigned com_num= com;
// exit if already initialized.
if (InitFlag)
return;
com_num--;
com_num%= 4; // now com_num is between 0-3 (and can be used for offsets!).
unsigned huge *port_num= (unsigned huge *)0x00000400L; // bios data area.
com_port= *(port_num+ com_num); // access bios data area and retrieve the com port...
unsigned com_irq_line;
switch (com_num) {
// com1 & com3.
case 0:
case 2:
com_irq_line= 4;
com_int= 0xc;
break;
// com2 & com4.
case 1:
case 3:
com_irq_line= 3;
com_int= 0xb;
break;
}
// now reuse activate.
//
activate(com_port, com_irq_line, com_int);
}
SERIAL_PORT::SERIAL_PORT() : ISC()
{
InitFlag= FALSE;
}
SERIAL_PORT::~SERIAL_PORT()
{
outportb (com_port+ IER, 0); // disable UART interrupts on all calls!!!
}