home *** CD-ROM | disk | FTP | other *** search
- /*
- ** --- term.c ---
- **
- ** EXAMPLE CODE: Terminal emulator. Can transfer files using
- ** XMODEM, YMODEM, and YMODEM-G protocols.
- **
- ** See TERM.H for configuration parameters.
- **
- ** Link with TERM_IO, MODEM_IO, DIR, CRC, DOS, XYMODEM, and XYPACKET.
- ** See TERM makefiles.
- **
- ** Do NOT select YMODEM-G when using a null modem cable unless you are
- ** certain that RTS & CTS are reversed ( this is usually not true ).
- **
- ** This example program (not the PCL4C library) is donated to
- ** the Public Domain by MarshallSoft Computing, Inc. It is
- ** provided as an example of the use of the PCL4C.
- **
- */
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include "pcl4c.h"
- #include "ascii.h"
- #include "term.h"
-
- #define FALSE 0
- #define TRUE !FALSE
- #define NORMAL 0x07
- #define INVERSE 0x70
- #define MESSAGE_POS 48
-
- void MyCrtWrite();
- void MyStart();
- void ProcessESC();
- void ShowProtocol();
- void ShowMessage();
- void MyExit();
- void SayFilename();
- void ErrorCheck();
-
- /*** Global variables ***/
-
- int Port; /* current COM port [0..3] */
- char Filename[15]; /* file name buffer */
- char Buffer[1024]; /* block buffer */
- char RxBuf[2048]; /* receive buffer */
- char *BaudRate[10] = {"300","600","1200","2400","4800","9600",
- "19200","38400","57600","115200"};
- int BaudCode; /* baud rate code ( index into BaudRate[] ) */
- char *ModelText[4] = {"Small","Compact","Medium","Large"};
- char DTAbuffer[128];
- char NCGchar = NAK;
- int OneKflag = FALSE;
- int BatchFlag = FALSE;
- char Protocol = 'X';
-
- /*** main program ***/
-
- main(argc,argv)
- int argc;
- char *argv[];
- {int DataFlag = FALSE;
- char c;
- int i, k;
- int n, rc;
- int Delta; /* delta port status */
- int Status; /* port status */
- char Version;
- char temp[81];
- /* right number of parameters ? */
- if(argc!=3)
- {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600'\n");
- exit(1);
- }
- /* get port number from command line */
- Port = atoi(argv[1]) - 1;
- if((Port<0) || (Port>3))
- {printf("Port must be 1 to 4\n");
- exit(1);
- }
- /* get baud rate from command line */
- BaudCode = BaudMatch(argv[2]);
- if(BaudCode<0)
- {printf("Cannot recognize baud rate = %s\n",argv[2]);
- exit(1);
- }
- /* setup transmit & receive buffer */
- ErrorCheck( SioRxBuf(Port,RxBuf,Size2048) );
- /* set parms & reset (initialize) COM port */
- ErrorCheck( SioParms(Port,NoParity,OneStopBit,WordLength8) );
- MyStart(Port,BaudCode);
- /* set DTR and RTS */
- SioDTR(Port,'S');
- SioRTS(Port,'S');
- /* init CRC table */
- InitCRC();
- /* initialize screen */
- Scroll(0,0,24,79,0,NORMAL);
- /* display status message */
- sprintf(temp," COM%d %s %c 'ESC for menu' ",1+Port,BaudRate[BaudCode],Protocol);
- ShowMessage(0,temp);
- Position(1,0);
- /* display some info */
- puts("TERM 5/1/92");
- Version = SioInfo('V');
- printf("Library = %d.%d\n",Version/16,Version%16);
- printf("Memory Model = %s\n",ModelText[3&SioInfo('M')] );
- #if RTS_CTS_CONTROL
- SioFlow(Port,7*ONE_SECOND);
- printf("Flow Control enabled. CTS = ");
- if(SioCTS(Port)) puts("ON");
- else puts("OFF");
- #endif
- /* Set FIFO level */
- if( SioFIFO(Port,LEVEL_14) ) puts("INS16550 detected");
- /* clear PCL4C receive buffer */
- ErrorCheck( SioRxFlush(Port) );
-
- /* see TERM.H for definition of AT_COMMAND_SET */
- #if AT_COMMAND_SET
- /* wait for Modem to say its ready */
- printf("Waiting for Modem DSR.");
- while( !SioDSR(Port) )
- {
- if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
- putchar('.');
- SioDelay(18);
- }
- putchar('\n');
- /* initialize (Hayes compatible) modem */
- SendTo(Port,"!AT!!~");
- SendTo(Port,"!AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
- if(WaitFor(Port,"OK")) printf("\nMODEM READY\n");
- else printf("\nWARNING: Expected OK not received\n");
- #endif
-
- /* enter terminal loop */
- SioRxFlush(Port);
- while(1)
- {/* Control-BREAK ? */
- if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
- /* was key pressed ? */
- if(SioKeyPress())
- {/* read key press */
- i = SioKeyRead();
- if((char)i==ESC)
- {/* process user's request */
- ProcessESC();
- ShowMessage(strlen(BaudRate[BaudCode])+9,"'ESC for Menu' ");
- continue;
- }
- else PutChar(Port,i);
- }
- /* was break detected ? */
- if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
- /* any incoming over serial port ? */
- i = GetChar(Port,0);
- if(i>-1)
- {/* good character */
- if(DataFlag&((i<0x20)||(i>0x7e)))
- {MyCrtWrite('^');
- MyCrtWrite('@'+i);
- }
- else MyCrtWrite(i);
- }
- /* any change in DCD or DSR ? */
- Delta = SioModem(Port,DeltaDCD|DeltaDSR);
- if(Delta)
- {/* display new status */
- Status = SioModem(Port,(char)(DCD|DSR));
- if(!Status&DeltaDCD) MyExit(0,"Dropped DSD");
- if(!Status&DeltaDSR) MyExit(0,"Dropped DSR");
- }
- } /* end -- key pressed */
- }
-
- /*** write to screen except for bottom line ***/
-
- void MyCrtWrite(ch)
- char ch;
- {/* write character */
- SioCrtWrite(ch);
- /* scroll all but bottom line */
- if(GetRow()==24)
- {Scroll(0,0,23,79,1,NORMAL);
- Position(23,0);
- }
- }
-
- /*** make multiple attempts to reset port ***/
-
- void MyStart(Port,BaudCode)
- int Port;
- int BaudCode;
- {int i, rc;
- /* try up to 3 times to reset COM port */
- for(i=0;i<3;i++)
- {printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
- if( (rc = SioReset(Port,BaudCode))==0) return;
- if(rc<0) MyExit(rc,"Error resetting port");
- SioDone(Port);
- /* display errors */
- if(rc&OverrunError) puts("Overrun Error");
- if(rc&ParityError) puts("Parity Error");
- if(rc&FramingError) puts("Framing Error");
- if(rc&BreakDetect) puts("Break Detect");
- }
- exit(1);
- }
-
- /*** find baud rate string in table ***/
-
- int BaudMatch(ptr)
- char *ptr;
- {int i;
- /* find baud rate in table */
- for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
- return(-1);
- }
-
- /*** user pressed Escape */
-
- void ProcessESC()
- {int i;
- int rc;
- int c1, c2;
- char Answer[2]; /* array for 1 char answer */
- int row, col;
- /* user pressed <ESC> */
- Answer[0] = '?';
- Answer[1] = '\0';
- DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
- if(strlen(Answer)) switch(toupper(Answer[0]))
- {
- case 'P':
- #if RTS_CTS_CONTROL
- DisplayLine("X) xmodem Y) ymodem G) ymodem-g: ",Answer,1);
- #else
- DisplayLine("X) xmodem Y) ymodem: ",Answer,1);
- #endif
- if(strlen(Answer)) switch( toupper(Answer[0]) )
- {
- case 'X':
- Protocol = 'X';
- ShowProtocol();
- OneKflag = FALSE;
- BatchFlag = FALSE;
- NCGchar = NAK;
- DisplayLine("Protocol = XMODEM",NULL,1);
- break;
- case 'Y':
- Protocol = 'Y';
- ShowProtocol();
- OneKflag = TRUE;
- BatchFlag = TRUE;
- NCGchar = 'C';
- DisplayLine("Protocol = YMODEM",NULL,1);
- break;
- #if RTS_CTS_CONTROL
- case 'G':
- Protocol = 'G';
- ShowProtocol();
- OneKflag = TRUE;
- BatchFlag = TRUE;
- NCGchar = 'G';
- DisplayLine("Protocol = YMODEM-G",NULL,1);
- break;
- #endif
- default:
- DisplayLine("Must answer X, Y, or G",NULL,1);
- break;
- }
- break;
- case 'Q':
- MyExit(0,"User pressed ESC");
- break;
- case 'R':
- ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
- /* XMODEM / YMODEM receive */
- if(BatchFlag)
- {do
- {/* receive files till get empty filename */
- RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
- if(SioKeyPress()) break;
- } while(Filename[0]!='\0');
- }
- else /* not Batch */
- {DisplayLine("Enter filename:",Filename,15);
- if(strlen(Filename)==0) break;
- RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
- }
- break;
- case 'S':
- ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
- DisplayLine("Enter filename:",Filename,15);
- if(strlen(Filename)==0) break;
- if(BatchFlag)
- {/* YMODEM send */
- setDTA(DTAbuffer);
- if(FindFirst(Filename))
- {SayFilename(&DTAbuffer[30]);
- TxyModem(Port,&DTAbuffer[30],Buffer,OneKflag,BatchFlag);
- while(FindNext())
- {SioDelay(4);
- SayFilename(&DTAbuffer[30]);
- TxyModem(Port,&DTAbuffer[30],Buffer,OneKflag,BatchFlag);
- }
- /* send empty filename */
- Filename[0] = '\0';
- SioDelay(5);
- TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
- }
- }
- else
- {/* XMODEM send */
- TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
- }
- break;
- default:
- DisplayLine("Must answer Q, P, S, or R",NULL,0);
- break;
- } /* end switch */
- }
-
- /*** show protocol choosen ***/
-
- void ShowProtocol()
- {int SaveRow;
- int SaveCol;
- SaveRow = GetRow();
- SaveCol = GetCol();
- Position(24,MESSAGE_POS+strlen(BaudRate[BaudCode])+7);
- AttrWrite(Protocol,INVERSE);
- Position(SaveRow,SaveCol);
- }
-
- /*** show chosen message ***/
-
- void ShowMessage(Pos,Msg)
- int Pos;
- char *Msg;
- {int i;
- int SaveRow;
- int SaveCol;
- int Col;
- SaveRow = GetRow();
- SaveCol = GetCol();
- Col = MESSAGE_POS+Pos;
- for(i=0;i<strlen(Msg);i++)
- {Position(24,Col++);
- AttrWrite(Msg[i],INVERSE);
- }
- Position(SaveRow,SaveCol);
- }
-
- /*** exit program ***/
-
- void MyExit(code,msg)
- int code;
- char *msg;
- {int rc;
- if(code<0) SioError(code);
- /* Assert UART break & sign off */
- SioBrkSig(Port,'A');
- printf("\nTERMINATING: %s\n",msg);
- SioDelay(ONE_SECOND/2);
- SioDone(Port);
- exit(0);
- }
-
- /*** display file name in status area ***/
-
- void SayFilename(Text)
- char *Text;
- {char Temp[40];
- strcpy(Temp,"Sending ");
- strcat(Temp,Text);
- DisplayLine(Temp,NULL,0);
- SioDelay(ONE_SECOND/2);
- }
-
- /*** check for error ***/
-
- void ErrorCheck(Code)
- int Code;
- {/* trap PCL error codes */
- if(Code<0)
- {SioError(Code);
- exit(1);
- }
- } /* end ErrorCheck */