📄 biosport.cpp
字号:
case 0 :
sprintf( buffer,
"Derived class: BIOSPort "
"RI: %2d CD: %2d CTS: %2d DSR: %2d",
Ri(), Cd(), Cts(), Dsr() );
break;
case 1 :
Ri();
sprintf( buffer,
"Parity Err: %d "
"Break Det: %d "
"Overrun Err: %d "
"Framing Err: %d",
( line_status & LSR_PARITY_ERROR ) ? 1 : 0,
( line_status & LSR_BREAK_DETECT ) ? 1 : 0,
( line_status & LSR_OVERRUN_ERROR ) ? 1 : 0,
( line_status & LSR_FRAMING_ERROR ) ? 1 : 0 );
break;
default :
return RS232_ILLEGAL_LINE_NUMBER;
}
return RS232_SUCCESS;
}
// The read_buffer routine is set up to continue reading in data
// as long as the data ready bit is set in the LSR. With a true
// BIOS, this means that it will generally only read in a single
// byte before returning to the Read() routine. It is up to the
// calling program to make sure a time value is set up so that
// multiple bytes can be read in. Note that a BIOS emulation system
// will usually be able to feed in an entire buffer with a single
// call.
int BIOSPort::read_buffer( char *buffer, unsigned int count )
{
union REGS rin;
union REGS rout;
ByteCount = 0;
if ( error_status < 0 )
return error_status;
rin.x.dx = port_name;
while ( count > 0 ) {
rin.h.ah = 3;
int86( 0x14, &rin, &rout );
line_status |= rout.h.ah;
if ( ( rout.h.ah & LSR_DATA_READY ) == 0 )
break;
rin.h.ah = 2;
int86( 0x14, &rin, &rout );
line_status |= rout.h.ah;
if ( rout.h.ah & 0x80 )
break;
*buffer++ = rout.h.al;
count--;
ByteCount++;
}
*buffer = '\0';
if ( count > 0 )
return RS232_TIMEOUT;
else
return RS232_SUCCESS;
}
// Like read_buffer(), the write_buffer routine will usually only
// be able to write a single byte when using a true BIOS
// implementation. It is up to the caller to invoke Write() with
// a long enough time delay to be able to send the entire buffer.
// A BIOS emulation system will usually be able to take in the
// entire buffer with one call to write_buffer().
int BIOSPort::write_buffer( char *buffer, unsigned int count )
{
union REGS rin;
union REGS rout;
rin.x.dx = port_name;
ByteCount = 0;
if ( error_status < 0 )
return error_status;
while ( count > 0 ) {
rin.h.ah = 3;
int86( 0x14, &rin, &rout );
line_status |= rout.h.ah;
if ( ( rout.h.ah & LSR_THRE ) == 0 )
break;
rin.h.ah = 1;
rin.h.al = (char) *buffer++;
int86( 0x14, &rin, &rout );
if ( rout.h.ah & 0x80 )
break;
line_status |= rout.h.ah;
buffer++;
count--;
ByteCount++;
}
if ( count > 0 )
return RS232_TIMEOUT;
else
return RS232_SUCCESS;
}
// If the THRE bit is set, there is room for one byte, if clear, there
// is room for 0 bytes.
int BIOSPort::TXSpaceFree( void )
{
union REGS r;
if ( error_status < RS232_SUCCESS )
return error_status;
r.x.dx = port_name;
r.h.ah = 3;
int86( 0x14, &r, &r );
line_status |= r.h.ah;
if ( r.h.ah & LSR_THRE )
return 1;
else
return 0;
}
// If the data ready bit is set, there is one byte present in the
// buffer, else 0.
int BIOSPort::RXSpaceUsed( void )
{
union REGS r;
if ( error_status < RS232_SUCCESS )
return error_status;
r.x.dx = port_name;
r.h.ah = 3;
int86( 0x14, &r, &r );
line_status |= r.h.ah;
if ( r.h.ah & LSR_DATA_READY )
return 1;
else
return 0;
}
// EBIOSPort has a few extra functions above and beyond BIOSPort.
// It has the ability to read in the old state of DTR and RTS,
// and can send a break signal. It also has a few extra baud rates
// and other line settings.
EBIOSPort::EBIOSPort( RS232PortName port,
long baud_rate,
char parity,
int word_length,
int stop_bits,
int dtr,
int rts,
int xon_xoff,
int rts_cts,
int dtr_dsr )
{
port_name = port;
error_status = RS232_SUCCESS;
first_debug_output_line = BIOSPort::FormatDebugOutput();
debug_line_count = FormatDebugOutput();
read_settings();
saved_settings = settings;
settings.Adjust( baud_rate,
parity,
word_length,
stop_bits,
dtr,
rts,
xon_xoff,
rts_cts,
dtr_dsr );
break_on = 0;
write_settings();
line_status = 0;
}
EBIOSPort::~EBIOSPort( void )
{
}
// The only additional information that I have to offer with this
// output routine is the setting of the break flag, which will
// usually be clear.
int EBIOSPort::FormatDebugOutput( char *buffer, int line_number )
{
if ( buffer == 0 )
return( first_debug_output_line + 1 );
if ( line_number < first_debug_output_line )
return BIOSPort::FormatDebugOutput( buffer, line_number );
switch( line_number - first_debug_output_line ) {
case 0 :
sprintf( buffer,
"Derived class: EBIOSPort "
"Break flag: %2d",
break_on );
break;
default :
return RS232_ILLEGAL_LINE_NUMBER;
}
return RS232_SUCCESS;
}
// There are exactly two settings that I can read here: the state
// of Dtr and Rts. It isn't much, but I read them both in and
// set the rest of the values to be invalid.
void EBIOSPort::read_settings( void )
{
union REGS r;
r.x.dx = port_name;
r.h.ah = 5;
r.h.al = 0;
int86( 0x14, &r, &r );
settings.Dtr = ( ( r.h.bl & 0x1 ) != 0 );
settings.Rts = ( ( r.h.bl & 0x2 ) != 0 );
settings.BaudRate = -1L;
settings.Parity = '?';
settings.WordLength = -1;
settings.StopBits = -1;
settings.XonXoff = -1;
settings.RtsCts = -1;
settings.DtrDsr = -1;
}
// write_settings() uses a different function for the EBIOS, so it has
// a few extra settings to support.
RS232Error EBIOSPort::write_settings( void )
{
union REGS r;
RS232Error status = RS232_SUCCESS;
r.x.dx = port_name;
r.h.ah = 4;
if ( break_on )
r.h.al = 1;
else
r.h.al = 0;
switch ( toupper( settings.Parity ) ) {
case 'E' : r.h.bh = 1; break;
case 'O' : r.h.bh = 2; break;
default : settings.Parity = 'N';
status = RS232_ILLEGAL_PARITY_SETTING;
case 'N' : r.h.bh = 0; break;
}
switch ( settings.StopBits ) {
case 1 : r.h.bl = 0; break;
default : settings.StopBits = 2;
status = RS232_ILLEGAL_STOP_BITS;
case 2 : r.h.bl = 1; break;
}
switch ( settings.WordLength ) {
case 5 : r.h.ch = 0; break;
case 6 : r.h.ch = 1; break;
case 7 : r.h.ch = 2; break;
default : settings.WordLength = 8;
status = RS232_ILLEGAL_WORD_LENGTH;
case 8 : r.h.ch = 3; break;
}
switch ( settings.BaudRate ) {
case 110L : r.h.cl = 0x00; break;
case 150L : r.h.cl = 0x01; break;
case 300L : r.h.cl = 0x02; break;
case 600L : r.h.cl = 0x03; break;
case 1200L : r.h.cl = 0x04; break;
case 2400L : r.h.cl = 0x05; break;
case 4800L : r.h.cl = 0x06; break;
default : settings.BaudRate = 9600L;
status = RS232_ILLEGAL_BAUD_RATE;
case 9600L : r.h.cl = 0x07; break;
case 19200L : r.h.cl = 0x08; break;
}
int86( 0x14, &r, &r );
r.x.dx = port_name;
r.h.ah = 5;
r.h.al = 1;
r.h.bl = (unsigned char) ( ( settings.Dtr ) ? 1 : 0 );
r.h.bl |= ( settings.Rts ) ? 2 : 0;
int86( 0x14, &r, &r );
if ( settings.RtsCts != -1 ) {
settings.RtsCts = -1;
status = RS232_RTS_CTS_NOT_SUPPORTED;
}
if ( settings.DtrDsr != -1 ) {
settings.DtrDsr = -1;
status = RS232_DTR_DSR_NOT_SUPPORTED;
}
if ( settings.XonXoff != -1 ) {
settings.XonXoff = -1;
status = RS232_XON_XOFF_NOT_SUPPORTED;
}
return status;
}
// EBIOSPort can set Dtr and Rts, BIOSPort can't.
int EBIOSPort::Dtr( int setting )
{
if ( setting != UNCHANGED ) {
settings.Dtr = ( setting != 0 );
write_settings();
}
return ( settings.Dtr != 0 );
}
int EBIOSPort::Rts( int setting )
{
if ( setting != UNCHANGED ) {
settings.Rts = ( setting != 0 );
write_settings();
}
return ( settings.Rts != 0 );
}
int EBIOSPort::Break( long milliseconds )
{
long timer;
if ( error_status < RS232_SUCCESS )
return error_status;
timer = ReadTime() + milliseconds;
break_on = 1;
write_settings();
while ( ReadTime() < timer )
IdleFunction();
break_on = 0;
write_settings();
return RS232_SUCCESS;
}
RS232Error EBIOSPort::Set( long baud_rate,
int parity,
int word_length,
int stop_bits )
{
settings.Adjust( baud_rate,
parity,
word_length,
stop_bits,
UNCHANGED,
UNCHANGED,
UNCHANGED,
UNCHANGED,
UNCHANGED );
return write_settings();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -