home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / PCL4C34 / TERM.C < prev    next >
Text File  |  1993-01-01  |  11KB  |  402 lines

  1. /*
  2. **                    ---  term.c ---
  3. **
  4. **  EXAMPLE CODE: Terminal emulator. Can transfer files using
  5. **  XMODEM, YMODEM, and YMODEM-G protocols.
  6. **
  7. **  See TERM.H for configuration parameters.
  8. **
  9. **  Link with TERM_IO, MODEM_IO, DIR_IO, CRC, DOS, XYMODEM, and XYPACKET.
  10. **  See TERM makefiles.
  11. **
  12. **  Do NOT select YMODEM-G when using a null modem cable unless you are
  13. **  certain that RTS & CTS are reversed ( this is usually not true ).
  14. **
  15. **  This example program (not the PCL4C library) is donated to
  16. **  the Public Domain by MarshallSoft Computing, Inc. It is
  17. **  provided as an example of the use of the PCL4C.
  18. **
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <sys\types.h>
  24. #include <sys\stat.h>
  25. #include "pcl4c.h"
  26. #include "ascii.h"
  27. #include "term.h"
  28. #include "dir_io.h"
  29.  
  30. #define FALSE 0
  31. #define TRUE !FALSE
  32. #define NORMAL 0x07
  33. #define INVERSE 0x70
  34. #define MESSAGE_POS 48
  35.  
  36. void MyCrtWrite();
  37. void MyStart();
  38. void ProcessESC();
  39. void ShowProtocol();
  40. void ShowMessage();
  41. void MyExit();
  42. void SayFilename();
  43. void ErrorCheck();
  44.  
  45. /*** Global variables ***/
  46.  
  47. int Port;               /* current COM port [0..3] */
  48. char FileSpec[15];      /* file name specification */
  49. char Filename[15];      /* file name buffer */
  50. char Buffer[1024];      /* block buffer */
  51. char RxBuf[2048];       /* receive buffer */
  52. char *BaudRate[10] =  {"300","600","1200","2400","4800","9600",
  53.                        "19200","38400","57600","115200"};
  54. int BaudCode;           /* baud rate code ( index into BaudRate[] ) */
  55. char *ModelText[4] = {"Small","Compact","Medium","Large"};
  56. char NCGchar  = NAK;
  57. int OneKflag  = FALSE;
  58. int BatchFlag = FALSE;
  59. char Protocol = 'X';
  60.  
  61. /*** main program ***/
  62.  
  63. main(argc,argv)
  64. int argc;
  65. char *argv[];
  66. {int DataFlag = FALSE;
  67.  char c;
  68.  int i, k;
  69.  int n, rc;
  70.  int Delta;         /* delta port status */
  71.  int Status;        /* port status */
  72.  char Version;
  73.  char temp[81];
  74.  /* right number of parameters ? */
  75.  if(argc!=3)
  76.      {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600'\n");
  77.       exit(1);
  78.      }
  79.  /* get port number from command line */
  80.  Port = atoi(argv[1]) - 1;
  81.  if((Port<0) || (Port>3))
  82.      {printf("Port must be 1 to 4\n");
  83.       exit(1);
  84.      }
  85.  /* get baud rate from command line */
  86.  BaudCode = BaudMatch(argv[2]);
  87.  if(BaudCode<0)
  88.      {printf("Cannot recognize baud rate = %s\n",argv[2]);
  89.       exit(1);
  90.      }
  91.  /*** Custom Configuration ***/
  92. #if 0
  93.  /* use IRQ2 for COM3 */
  94.  SioIRQ(COM3,IRQ2,ThirdISR);
  95.  /* use IRQ5 for COM4 */
  96.  SioIRQ(COM4,IRQ5,FourthISR);
  97. #endif
  98.  /* setup receive buffer */
  99.  ErrorCheck( SioRxBuf(Port,RxBuf,Size2K) );
  100.  /* set parms & reset (initialize) COM port */
  101.  ErrorCheck( SioParms(Port,NoParity,OneStopBit,WordLength8) );
  102.  MyStart(Port,BaudCode);
  103.  /* set DTR and RTS */
  104.  SioDTR(Port,'S');
  105.  SioRTS(Port,'S');
  106.  /* init CRC table */
  107.  InitCRC();
  108.  /* initialize screen */
  109.  Scroll(0,0,24,79,0,NORMAL);
  110.  /* display status message */
  111.  sprintf(temp," COM%d %s %c 'ESC for menu'  ",1+Port,BaudRate[BaudCode],Protocol);
  112.  ShowMessage(0,temp);
  113.  Position(1,0);
  114.  /* display some info */
  115.  puts("TERM 10/30/92");
  116.  Version = SioInfo('V');
  117.  printf("Library = %d.%d\n",Version/16,Version%16);
  118.  printf("Memory Model = %s\n",ModelText[3&SioInfo('M')] );
  119. #if RTS_CTS_CONTROL
  120.  SioFlow(Port,7*ONE_SECOND);
  121.  printf("Flow Control enabled. CTS = ");
  122.  if(SioCTS(Port)) puts("ON");
  123.  else puts("OFF");
  124. #endif
  125.  /* Set FIFO level */
  126.  if( SioFIFO(Port,LEVEL_14) ) puts("INS16550 detected");
  127.  /* clear PCL4C receive buffer */
  128.  ErrorCheck( SioRxFlush(Port) );
  129.  
  130.  /* see TERM.H for definition of AT_COMMAND_SET */
  131. #if AT_COMMAND_SET
  132.  /* wait for Modem to say its ready */
  133.  printf("Waiting for Modem DSR.");
  134.  while( !SioDSR(Port) )
  135.      {
  136.       if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
  137.       putchar('.');
  138.       SioDelay(18);
  139.      }
  140.  putchar('\n');
  141.  /* initialize (Hayes compatible) modem */
  142.  SendTo(Port,"!AT!!~");
  143.  SendTo(Port,"!AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
  144.  if(WaitFor(Port,"OK")) printf("\nMODEM READY\n");
  145.  else printf("\nWARNING: Expected OK not received\n");
  146. #endif
  147.  
  148.  /* enter terminal loop */
  149.  SioRxFlush(Port);
  150.  while(1)
  151.      {/* Control-BREAK ? */
  152.       if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
  153.       /* was key pressed ? */
  154.       if(SioKeyPress())
  155.           {/* read key press */
  156.            i = SioKeyRead();
  157.            if((char)i==ESC)
  158.                {/* process user's request */
  159.                 ProcessESC();
  160.                 ShowMessage(strlen(BaudRate[BaudCode])+9,"'ESC for Menu' ");
  161.                 continue;
  162.                }
  163.            else PutChar(Port,i);
  164.           }
  165.       /* was break detected ? */
  166.       if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
  167.       /* any incoming over serial port ? */
  168.       i = GetChar(Port,0);
  169.       if(i>-1)
  170.           {/* good character */
  171.            if(DataFlag&((i<0x20)||(i>0x7e)))
  172.                {MyCrtWrite('^');
  173.                 MyCrtWrite('@'+i);
  174.                }
  175.            else MyCrtWrite(i);
  176.           }
  177.       /* any change in DCD or DSR ? */
  178.       Delta = SioModem(Port,DeltaDCD|DeltaDSR);
  179.       if(Delta)
  180.           {/* display new status */
  181.            Status = SioModem(Port,(char)(DCD|DSR));
  182.            if(!Status&DeltaDCD) MyExit(0,"Dropped DSD");
  183.            if(!Status&DeltaDSR) MyExit(0,"Dropped DSR");
  184.           }
  185.      } /* end -- key pressed */
  186. }
  187.  
  188. /*** write to screen except for bottom line ***/
  189.  
  190. void MyCrtWrite(ch)
  191. char ch;
  192. {/* write character */
  193.  SioCrtWrite(ch);
  194.  /* scroll all but bottom line */
  195.  if(GetRow()==24)
  196.     {Scroll(0,0,23,79,1,NORMAL);
  197.      Position(23,0);
  198.     }
  199. }
  200.  
  201. /*** make multiple attempts to reset port ***/
  202.  
  203. void MyStart(Port,BaudCode)
  204. int Port;
  205. int BaudCode;
  206. {int i, rc;
  207.  /* try up to 3 times to reset COM port */
  208.  for(i=0;i<3;i++)
  209.      {printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
  210.       if( (rc = SioReset(Port,BaudCode))==0) return;
  211.       if(rc<0) MyExit(rc,"Error resetting port");
  212.       SioDone(Port);
  213.       /* display errors */
  214.       if(rc&OverrunError) puts("Overrun Error");
  215.       if(rc&ParityError)  puts("Parity Error");
  216.       if(rc&FramingError) puts("Framing Error");
  217.       if(rc&BreakDetect)  puts("Break Detect");
  218.      }
  219.  exit(1);
  220. }
  221.  
  222. /*** find baud rate string in table ***/
  223.  
  224. int BaudMatch(ptr)
  225. char *ptr;
  226. {int i;
  227.  /* find baud rate in table */
  228.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  229.  return(-1);
  230. }
  231.  
  232. /*** user pressed Escape */
  233.  
  234. void ProcessESC()
  235. {int i;
  236.  int rc;
  237.  int c1, c2;
  238.  char Answer[2]; /* array for 1 char answer */
  239.  int row, col;
  240.  /* user pressed <ESC> */
  241.  Answer[0] = '?';
  242.  Answer[1] = '\0';
  243.  DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
  244.  if(strlen(Answer)) switch(toupper(Answer[0]))
  245.      {
  246.       case 'P':
  247. #if RTS_CTS_CONTROL
  248.           DisplayLine("X) xmodem Y) ymodem G) ymodem-g: ",Answer,1);
  249. #else
  250.           DisplayLine("X) xmodem Y) ymodem: ",Answer,1);
  251. #endif
  252.           if(strlen(Answer)) switch( toupper(Answer[0]) )
  253.                {
  254.                 case 'X':
  255.                     Protocol = 'X';
  256.                     ShowProtocol();
  257.                     OneKflag = FALSE;
  258.                     BatchFlag = FALSE;
  259.                     NCGchar = NAK;
  260.                     DisplayLine("Protocol = XMODEM",NULL,1);
  261.                     break;
  262.                 case 'Y':
  263.                     Protocol = 'Y';
  264.                     ShowProtocol();
  265.                     OneKflag = TRUE;
  266.                     BatchFlag = TRUE;
  267.                     NCGchar = 'C';
  268.                     DisplayLine("Protocol = YMODEM",NULL,1);
  269.                     break;
  270. #if RTS_CTS_CONTROL
  271.                 case 'G':
  272.                     Protocol = 'G';
  273.                     ShowProtocol();
  274.                     OneKflag = TRUE;
  275.                     BatchFlag = TRUE;
  276.                     NCGchar = 'G';
  277.                     DisplayLine("Protocol = YMODEM-G",NULL,1);
  278.                     break;
  279. #endif
  280.                 default:
  281.                     DisplayLine("Must answer X, Y, or G",NULL,1);
  282.                     break;
  283.                }
  284.           break;
  285.       case 'Q':
  286.           MyExit(0,"User pressed ESC");
  287.           break;
  288.       case 'R':
  289.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  290.           /* XMODEM / YMODEM receive */
  291.           if(BatchFlag)
  292.                {do
  293.                     {/* receive files till get empty filename */
  294.                      RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  295.                      if(SioKeyPress()) break;
  296.                     } while(Filename[0]!='\0');
  297.                }
  298.           else /* not Batch */
  299.                {DisplayLine("Enter filename:",Filename,15);
  300.                 if(strlen(Filename)==0) break;
  301.                 RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  302.                }
  303.           break;
  304.       case 'S':
  305.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  306.           DisplayLine("Enter filename:",FileSpec,15);
  307.           if(strlen(FileSpec)==0) break;
  308.           if(BatchFlag)
  309.                {/* YMODEM send */
  310.                 if(FindFirst(FileSpec,Filename))
  311.                   {SayFilename(Filename);
  312.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  313.                    while(FindNext(Filename))
  314.                      {SioDelay(4);
  315.                       SayFilename(Filename);
  316.                       TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  317.                      }
  318.                    /* send empty filename */
  319.                    Filename[0] = '\0';
  320.                    SioDelay(5);
  321.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  322.                   }
  323.                }
  324.           else
  325.                {/* XMODEM send */
  326.                 TxyModem(Port,FileSpec,Buffer,OneKflag,BatchFlag);
  327.                }
  328.           break;
  329.      default:
  330.           DisplayLine("Must answer Q, P, S, or R",NULL,0);
  331.           break;
  332.     } /* end switch */
  333. }
  334.  
  335. /*** show protocol choosen ***/
  336.  
  337. void ShowProtocol()
  338. {int SaveRow;
  339.  int SaveCol;
  340.  SaveRow = GetRow();
  341.  SaveCol = GetCol();
  342.  Position(24,MESSAGE_POS+strlen(BaudRate[BaudCode])+7);
  343.  AttrWrite(Protocol,INVERSE);
  344.  Position(SaveRow,SaveCol);
  345. }
  346.  
  347. /*** show chosen message ***/
  348.  
  349. void ShowMessage(Pos,Msg)
  350. int Pos;
  351. char *Msg;
  352. {int i;
  353.  int SaveRow;
  354.  int SaveCol;
  355.  int Col;
  356.  SaveRow = GetRow();
  357.  SaveCol = GetCol();
  358.  Col = MESSAGE_POS+Pos;
  359.  for(i=0;i<strlen(Msg);i++)
  360.    {Position(24,Col++);
  361.     AttrWrite(Msg[i],INVERSE);
  362.    }
  363.  Position(SaveRow,SaveCol);
  364. }
  365.  
  366. /*** exit program ***/
  367.  
  368. void MyExit(code,msg)
  369. int code;
  370. char *msg;
  371. {int rc;
  372.  if(code<0) SioError(code);
  373.  /* Assert UART break & sign off */
  374.  SioBrkSig(Port,'A');
  375.  printf("\nTERMINATING: %s\n",msg);
  376.  SioDelay(ONE_SECOND/2);
  377.  SioDone(Port);
  378.  exit(0);
  379. }
  380.  
  381. /*** display file name in status area ***/
  382.  
  383. void SayFilename(Text)
  384. char *Text;
  385. {char Temp[40];
  386.  strcpy(Temp,"Sending ");
  387.  strcat(Temp,Text);
  388.  DisplayLine(Temp,NULL,0);
  389.  SioDelay(ONE_SECOND/2);
  390. }
  391.  
  392. /*** check for error ***/
  393.  
  394. void ErrorCheck(Code)
  395. int Code;
  396. {/* trap PCL error codes */
  397.  if(Code<0)
  398.      {SioError(Code);
  399.       SioDone(Port);
  400.       exit(1);
  401.      }
  402. } /* end ErrorCheck */