#include <dos.h>
#include "SerComm.h"
void interrupt(*oldvects[2])(...);
void interrupt com1_int(...);
void interrupt com2_int(...);
class ComClass
{
public:
ComClass(const int comPortVal);
void comInt(void);
void sendChar(const char ch);
int receiveChar(char *ch);
void comOff(void);
int setCom(const int baud, const int para);
void comMainRun(void);
private:
int comPort;
int comBase;
int comIRQ;
int comVect;
int comOldVect;
int onFlag;
int inHead;
int inTail;
int outHead;
int outTail;
char *inBuf;
char *outBuf;
};
ComClass::ComClass(const int comPortVal)
{
comPort = comPortVal;
onFlag = 0;
inHead = 0;
inTail = 0;
outHead = 0;
outTail = 0;
switch(comPortVal)
{
case COM1:
comBase = COM1_BASE;
comIRQ = COM1_IRQ;
comVect = COM1_VECT;
comOldVect = COM1_OLD_VECT;
break;
case COM2:
comBase = COM2_BASE;
comIRQ = COM2_IRQ;
comVect = COM2_VECT;
comOldVect = COM2_OLD_VECT;
break;
default:
break;
}
}
void ComClass::comInt(void)
{
if (!onFlag)
return;
disable();
int temp = (inportb(comBase+IIR)) & IIR_MASK;
switch(temp)
{
case 0x00: // modem status changed
inportb(comBase+MSR); // read in useless char
break;
case 0x02: // Request To Send char
if (outHead != outTail) // there's a char to send
{
outportb(comBase+TXR, outBuf[outHead++]); // send the character
if (outHead == OBUF_LEN)
outHead = 0; // if at end of buffer, reset pointer
}
break;
case 0x04: // character ready to be read in
inBuf[inHead++] = inportb(comBase+RXR);// read character into inbuffer
if (inHead == IBUF_LEN) // if at end of buffer
inHead = 0; // reset pointer
break;
case 0x06: // line status has changed
inportb(comBase+LSR); // read in useless char
break;
default:
break;
}
outportb(PIC8259_ICR, PIC8259_EOI); // Signal end of hardware interrupt
enable(); // reenable interrupts at the end of the handler
}
void ComClass::sendChar(const char ch)
{
if (onFlag)
{
disable(); // make sure nothing happens while changing buffer
outBuf[outTail++] = ch; // insert character into buffer;
if (outTail == OBUF_LEN) // if at end of out buffer
{
outTail = 0; // reset pointer
}
enable(); // re-enable interrupts
}
}
int ComClass::receiveChar(char *ch)
{
if(onFlag)
{
if (inHead != inTail) // there is a character
{
disable(); // disable irqs while getting char
*ch = inBuf[inTail++]; // get character from buffer
if (inTail == IBUF_LEN) //if at end of in buffer
inTail = 0; // reset pointer
enable(); // re-enable interrupt
return TRUE;
}
}
return FALSE;
}
void ComClass::comOff(void)
{
if(onFlag)
{
disable();
int temp = inportb(PIC8259_IMR) | ~comIRQ;
outportb(PIC8259_IMR, temp);
outportb(comBase + IER, 0);
outportb(comBase + MCR, 0);
enable();
setvect(comVect, oldvects[comOldVect]);
onFlag = FALSE;
delete [] inBuf;
delete [] outBuf;
}
}
int ComClass::setCom(const int baud, const int para)
{
if (baud == 0)
return FALSE;
int divisor = (int)(115200L/baud);
//申请空间
inBuf = new char[IBUF_LEN];
outBuf = new char[OBUF_LEN];
disable();
char c = inportb(comBase + LCR);
outportb(comBase + LCR, (c | 0x80));
outportb(comBase + DLL, (divisor & 0x00FF));
outportb(comBase + DLH, ((divisor >> 8) & 0x00FF));
outportb(comBase + LCR, c);
outportb(comBase + LCR, para);
enable();
oldvects[comOldVect] = getvect(comVect);
switch(comPort)
{
case COM1:
setvect(comVect, com1_int);
break;
case COM2:
setvect(comVect, com2_int);
break;
default:
break;
}
disable();
int temp = inportb(comBase + MCR) | 0x0f;
outportb(comBase + MCR, temp);
temp = (inportb(comBase + IER)) | IER_RX_INT;
outportb(comBase + IER, temp);
temp = inportb(PIC8259_IMR) & comIRQ;
outportb(PIC8259_IMR, temp);
enable();
onFlag = TRUE;
return TRUE;
}
void ComClass::comMainRun(void)
{
if (onFlag)
{
disable();
if (outHead != outTail)
{
outportb(comBase+IER,IER_TX_INT);
}
else
{
outportb(comBase+IER,IER_RX_INT);
}
enable();
}
}
ComClass com1(COM1);
ComClass com2(COM2);
void interrupt com1_int(...)
{
com1.comInt();
}
void interrupt com2_int(...)
{
com2.comInt();
}
int SerComOn(int comport)
{
if ((comport == COM1) || (comport == COM2))
return TRUE;
else
return FALSE;
}
int SetSerCom(const int comport, int baud, int para)
{
switch(comport)
{
case COM1:
return com1.setCom(baud, para);
case COM2:
return com2.setCom(baud, para);
default:
return FALSE;
}
}
//关闭串口
void SerComOff(const int comport)
{
switch(comport)
{
case COM1:
com1.comOff();
break;
case COM2:
com2.comOff();
break;
default:
break;
}
}
//关闭全部串口
void OffAllSerial(void)
{
com1.comOff();
com2.comOff();
}
void SendChar(const int comport, const char ch)
{
switch(comport)
{
case COM1:
com1.sendChar(ch);
break;
case COM2:
com2.sendChar(ch);
break;
default:
break;
}
}
void SendChars(const int comport, unsigned int strlen, char *buf, unsigned int *sendlen)
{
for(int i=0; i<strlen; i++)
{
SendChar( comport, *(buf+i) );
}
*sendlen = strlen;
}
int ReceiveChar(const int comport, char *ch)
{
switch(comport)
{
case COM1:
return com1.receiveChar(ch);
case COM2:
return com2.receiveChar(ch);
default:
return FALSE;
}
}
//例行扫描
void comMainRun(void)
{
com1.comMainRun();
com2.comMainRun();
}