/* File name: set200.c by Mingfu Cai 02/17/00
ACT-IR200L ASK/SIR Programming Guide
set the mode of IR200L
written in TC++ 3.0 and MS VC++1.52
**Function**
int set_200Mode( unsigned short port, int mode );
port: 0x3f8: COM1, 0x2f8: COM2
mode: 0..1: ASK mode 9600, 19200,
2..6: IrDA mode 9600, 19200, 38400, 57600, 115200
Return: 0-OK, others-FAIL
ASK mode: power level = 1, LED short circuit protected, no echo, 8-O-1
(0x45, 0x0B)
IrDA mode: power level = 3, LED short circuit protected, no echo, 8-N-1
(0x47, 0x03)
EXAMPLE 1:
Use COM1 (IO base address = 0x3f8), set speed to IrDA 115200
status = set_200Mode( IOBASE_COM1, Mode115200IRDA);
EXAMPLE 2:
Use COM2 (IO base address = 0x2f8), set speed to ASK 9600
status = set_200Mode( IOBASE_COM2, Mode9600ASK);
**invoke by batch file**
set200 <port> <mode>
Status will be in DOS errorlevel.
0: OK, 1: FAIL
EXAMPLE 1:
Use COM1 (IO base address = 0x3f8), set speed to 115200IrDA
set200 com1 6
EXAMPLE 2:
Use COM2 (IO base address = 0x2f8), set speed to 9600ASK
set200 com2 0
NOTE:
1. Check the io base address of the COM port you use
and use the correct one if you call with the predefined id.
2. The function delay() may not give you the precise delay time you
want. The MSDOS is not a real-time OS. The time interrupt request
happens every 55 ms. You need to make sure that it will be longer than
0.5us
and not too longe that cause timeout on the another communication side
if
it is waiting for you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OK 0
#define FAIL 1
#define TIMEOUT -1
typedef unsigned char u8;
typedef unsigned short u16;
#define TC30 //for MS VC undefined it
#ifdef TC30
#include <dos.h>
// void outportb(int portid, unsigned char value);
#else //MS VC++
#include <conio.h>
#include <time.h>
#define outportb _outp
#define inportb _inp
//int _outp( unsigned port, int databyte );
/* Pauses for a specified number of clock ticks. Here CLOCKS_PER_SEC
is 1000,
so that this funtion will sleep a specified mini seconds.
*/
void delay( clock_t _wait )
{
clock_t goal;
goal = _wait + clock();
while( goal > clock() );
}
#endif
//default io base address of COM ports
#define IOBASE_COM1 0X3F8
#define IOBASE_COM2 0X2F8
#define IOBASE_COM3 0X3E8
#define IOBASE_COM4 0X2E8
#define Mode9600ASK 0
#define Mode19200ASK 1
#define Mode9600IRDA 2
#define Mode38400IRDA 3
#define Mode19200IRDA 4
#define Mode57600IRDA 5
#define Mode115200IRDA 6
//0..12: IR200L Mode string
//13: COM divider, 14:COM data mode
//ASK mode: power level = 1, LED short circuit protected, no echo, 8-O-1
(0x45, 0x0B)
//IrDA mode: power level = 3, LED short circuit protected, no echo,
8-N-1 (0x47, 0x03)
static const unsigned char IR200ModeStr[7][15] = {
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x45,0x21,0x30,0x50,0x91,0x87,0x15,0x0C,0x0B},
//9.6 Kbps ASK
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x45,0x21,0x30,0x50,0x91,0x87,0x15,0x06,0x0B},
//19.2 Kbps ASK
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x47,0x53,0x53,0x53,0x91,0x87,0x15,0x0C,0x03},
//9.6 Kbps IrDA
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x47,0x53,0x53,0x53,0x90,0x8B,0x15,0x06,0x03},
//19.2 Kbps IrDA
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x47,0x53,0x53,0x53,0x90,0x85,0x15,0x03,0x03},
//38.6 Kbps IrDA
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x47,0x53,0x53,0x53,0x90,0x83,0x15,0x02,0x03},
//57.6 Kbps IrDA
{0x03,0xD1,0x56,0xD0,0x76,0x63,0x47,0x51,0x51,0x51,0x90,0x81,0x15,0x01,0x03}
//115.2 Kbps IrDA
};
//timeout = 10ms.
//return 0: ok, -1: timeout
static int recv_byte( int port, unsigned char *pdata )
{
int ii, status;
for( ii=0; ii<10; ii++ ) {
if( inportb( (u16)( port+5 )) & 0x01 ) { //LSR: RXDA (Rx Data Available)
*pdata = inportb( (u16)( port ));
break;
}
else delay( 1 );
}
if( ii < 10 ) status = OK;
else status = TIMEOUT;
return status;
}
static void send_byte(int port, unsigned char data )
{
while( (inportb( (u16)( port+5 )) & 0x20) != 0x20 ) { /*wait for
TxReady*/ };
outportb((u16)port, data);
}
static void read_all( int port )
{
inportb( (u16)port ); //RXD
inportb( (u16)( port+2 )); //EIR
inportb( (u16)( port+5 )); //LSR
inportb( (u16)( port+6 )); //MSR
}
static void setPortMode( u16 port, int mode )
{
unsigned char dtFmt = IR200ModeStr[mode][14];
outportb((u16)(port+3), 0xff); //set to bank1
outportb((u16)port, IR200ModeStr[mode][13]); //low byte of divisor
outportb((u16)(port+1), 0); //high byte of divisor
outportb((u16)(port+3), dtFmt); //set data format and back to bank0
read_all(port);
}
//OK: return 0, otherwise -1.
static int reset_200( u16 portBase )
{
unsigned char bData;
int status;
//IER (Interrup Enable Register). Disable all interrupts
outportb( (u16)( portBase + 1), 0);
//1. set the UART to 8-N-1 and set TxD to low (inactive).
outportb( (u16)( portBase + 3), 0x03); //Line Ctrl Reg.
//2. Set both RTS and DTR high
outportb( (u16)( portBase + 4), 0x0b); //Modem Ctrl Reg.
delay( 100 ); // >=100 ms
//4. reset it by set RTS low. DTR remains high.
outportb( (u16)( portBase + 4), 0x09); //Modem Ctrl Reg.
//5. Set TxD high (break) to provide power during reset.
outportb( (u16)( portBase + 3), 0x43); //Line Ctrl Reg.
delay( 50 ); // >=50 ms
outportb( (u16)( portBase + 3), 0x03); //Line Ctrl Reg.
//8. Set RTS high. DTR remains high.
outportb( (u16)( portBase + 4), 0x0b); //Modem Ctrl Reg.
delay( 50 ); // >=50 ms
//10. Set DTR low. RTS remains high. TxD remains low (inactive).
outportb( (u16)( portBase + 4), 0x0a); //Modem Ctrl Reg.
//--- checkReset ---
//set baud rate to 9600
setPortMode( portBase, Mode9600IRDA );
read_all( portBase );
outportb( (u16)( portBase+4), 0x0A ); //set DTR low and RTS high
//11. Send the hex byte F0 to TxD (using data format 9600-N-8-1).
outportb( (u16)portBase, 0xf0 );
//12. Wait up to 10 msec or until RxD received a byte (which ever
// happen first).
delay( 10 );
status = recv_byte( portBase, &bData );
outportb( (u16)( portBase+4), 0x0B ); //set both RTS and DTR high
//13. If a byte is received, and has the hex value F4 or F5, the Reset
is accomplished.
//14. If no byte is received, or the byte received has a value other
than hex F4 or F5, repeat Steps 2 through 12 above.
if( (status < 0) && (bData != 0xF4) && (bData !=
0xF5) ) return -1;
else return 0;
}
//mode: 0-1 ASK, 2-6 IrDA
int set_200Mode( unsigned short port, int mode )
{
int ii;
//printf( "---- Reset the IR200L ... ----\n");
for( ii=0; ii<5; ii++) {
if(reset_200( port ) == OK ) break;
else continue;
}
if( ii >= 5 ) return FAIL;
outportb( (u16)(port+4), 0x0A ); //set RTS high and DTR low
setPortMode( port, Mode9600IRDA );
for( ii=0; ii<13; ii++) {
send_byte(port, IR200ModeStr[mode][ii]);
}
delay( 10 );
outportb( (u16)(port+4), 0x0B ); //set both RTS and DTR high
return OK;
}
//exit with 1 if fail to reset the dongle IR200L
// 0: OK
void main(int argc, char *argv[])
{
int mode;
u16 port;
if ( (argc != 3) ||
(stricmp(argv[1], "com1") && stricmp(argv[1], "com2"))
||
((mode = atoi(argv[2])) < 0) || (mode > 6) ) {
printf("*** Incorrect command tail ***\n");
printf("set200 <port> <mode>\r\n");
printf("where <port> := ""com1"" | ""com2""\n");
printf(" <mode> := 0..6\a\n");
printf("mode0: 9600ASK, 1:19200ASK,\n");
printf(" 2:9600IrDA, 3:19200IrDA, 4:38400IrDA, 5:57600IrDA, 6:115200IrDA\n");
exit( 1 );
}
port = (stricmp(argv[1], "com1")) ? 0x2F8:0x3F8;
//setPortMode( port, Mode9600IRDA );
//set IR200L Mode and speed
if( set_200Mode( port, mode ) != OK ) {
//printf( "---- failed to reset the IR200L ----\n");
exit( FAIL );
}
setPortMode( port, mode ); //set COM port to the required mode
exit( OK );
}
|