home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / communic / cport13 / comdemo.c next >
Encoding:
C/C++ Source or Header  |  1991-11-10  |  19.7 KB  |  884 lines

  1. /*
  2. ** COMDEMO.C
  3. **
  4. ** Serial communications demo program for the Cport communications library.
  5. ** Compiled and linked with Borland/Turbo C v2.0
  6. **
  7. ** Copyright (c) 1991 Bri Productions
  8. **
  9. */
  10.  
  11.  
  12.  
  13. #include "cport.h"
  14. #include <conio.h>
  15. #include <stdlib.h>
  16. #include <dos.h>
  17. #include <bios.h>
  18. #include <ctype.h>
  19. #include <stdio.h>
  20.  
  21.  
  22. /*
  23. **-------------------------------------
  24. **
  25. ** Queue sizes and thresholds
  26. **
  27. **-------------------------------------
  28. */
  29. #define  TXQ      4096
  30. #define  RCVQ     4096
  31. #define  THRESH   (RCVQ * 3 / 4)
  32.  
  33.  
  34. /*
  35. **-------------------------------------
  36. **
  37. ** numbers of parameters
  38. **
  39. **-------------------------------------
  40. */
  41. #define  NUM_COM     4
  42. #define  NUM_BAUD    9
  43. #define  NUM_MODE    2
  44. #define  NUM_HND     4
  45.  
  46.  
  47. /*
  48. **-------------------------------------
  49. **
  50. ** scan codes
  51. **
  52. **-------------------------------------
  53. */
  54. #define  A     0x1E00
  55. #define  B     0x3000
  56. #define  C     0x2E00
  57. #define  D     0x2000
  58. #define  E     0x1200
  59. #define  F     0x2100
  60. #define  G     0x2200
  61. #define  H     0x2300
  62. #define  I     0x1700
  63. #define  M     0x3200
  64. #define  N     0x3100
  65. #define  O     0x1800
  66. #define  P     0x1900
  67. #define  S     0x1F00
  68. #define  W     0x1100
  69. #define  X     0x2D00
  70. #define  PGDN  0x5100
  71. #define  PGUP  0x4900
  72. #define  ESC   0x1b
  73.  
  74.  
  75. /*
  76. **-------------------------------------
  77. **
  78. ** text attributes
  79. **
  80. **-------------------------------------
  81. */
  82. #define  NORM  0x07
  83. #define  BOLD  0x08
  84. #define  FAINT 0xF7
  85. #ifndef  BLINK
  86. #define  BLINK 0x80
  87. #endif
  88. #define  REVRS 0x77
  89.  
  90.  
  91. /*
  92. **-------------------------------------
  93. **
  94. ** parameter constants
  95. **
  96. **-------------------------------------
  97. */
  98. unsigned com[]    = { COM1, COM2, COM3, COM4 };
  99. int      baud[]   = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300 };
  100. byte     mode[]   = { W8|S1|NONE, W7|S1|EVEN };
  101. byte     hndshk[] = { OFF ,SOFT, HARD, HARD|SOFT };
  102.  
  103. /*
  104. **-------------------------------------
  105. **
  106. ** parameter indexes
  107. **
  108. **-------------------------------------
  109. */
  110. struct indx{
  111.    byte com;
  112.    byte baud;
  113.    byte mode;
  114.    byte ansi;
  115.    byte hndshk;
  116.    byte lf;
  117.  byte echo;
  118.    }indx = { 0, 3, 0, 1, 0, 0, 0 };
  119.  
  120.  
  121. /*
  122. **-------------------------------------
  123. **
  124. ** parameter messages
  125. **
  126. **-------------------------------------
  127. */
  128. struct{
  129.    char *com   [NUM_COM ];
  130.    char *baud  [NUM_BAUD];
  131.    char *mode  [NUM_MODE];
  132.    char *ansi  [2];
  133.    char *hndshk[NUM_HND];
  134.    char *lf    [2];
  135.    }msg={
  136.             { "COM1", "COM2", "COM3", "COM4" },
  137.             { "115k", "57600", "38400", "19200", "9600", "4800", "2400", "1200", "300"},
  138.             { "8-1-N", "7-1-E" },
  139.             { "TTY", "ANSI" },
  140.             { "NONE", "SOFT", "HARD", "BOTH" },
  141.             { "  ", "LF" }
  142.         };
  143.  
  144.  
  145. /*
  146. **-------------------------------------
  147. **
  148. ** screen coordinates
  149. **
  150. **-------------------------------------
  151. */
  152. int x = 1;                             /* cursor location               */
  153. int y = 1;
  154. byte attrib = NORM;                    /* present text attribute        */
  155. #define  ERR_X    41                   /* error message x coordinate    */
  156. #define  STAT_X   60                   /* status message x coordinate   */
  157.  
  158.  
  159. /*
  160. **-------------------------------------
  161. **
  162. ** function prototypes
  163. **
  164. **-------------------------------------
  165. */
  166. void     Init        (void);
  167. void     Uninit      (void);
  168. void     NewParam    (void);
  169. void     Ansi        (void);
  170. void     CheckError  (void);
  171. void     CheckStatus (void);
  172. void     put_ch      (char c);
  173.  
  174.  
  175. char  *Xmsg[] = { "transfer successful",
  176.                   "file not found",
  177.                   "transfer aborted"
  178.                };
  179.  
  180. struct C_param param;
  181.  
  182. /*
  183. **-------------------------------------
  184. **
  185. ** main()
  186. **
  187. **-------------------------------------
  188. */
  189. void main(void)
  190. {
  191. char c;
  192. unsigned key;
  193.  
  194.  
  195.       /* initialize  */
  196.    Init();
  197.  
  198.  
  199.    while(1)
  200.    {
  201.  
  202.          /* Poll the keyboard buffer for available keystrokes.       */
  203.          /* Meanwhile, the receive queue is checked for available    */
  204.          /* characters, check for errors and check the modem status  */
  205.  
  206.       while(!bioskey(1))
  207.       {
  208.  
  209.             /* If a character(s) is available in the receive queue,  */
  210.             /* fetch it. If it is and escape character, it must be   */
  211.             /* check to see if it is the start of an ansi sequence.  */
  212.             /* Otherwise the cursor position is updated, and the     */
  213.             /* character is printed.                                 */
  214.  
  215.          if(ComLenRx())
  216.          {
  217.             c = ComGetc();
  218.  
  219.             if(c ==  ESC && indx.ansi)
  220.             {
  221.                Ansi();
  222.                gotoxy(x, y);
  223.                continue;
  224.             }
  225.  
  226.           put_ch(c);
  227.  
  228.          }
  229.  
  230.  
  231.             /* Check for errors and changes in the modem status   */
  232.  
  233.          CheckError();
  234.          CheckStatus();
  235.       }
  236.  
  237.  
  238.          /* When a key is pressed, the key is fetched, and the    */
  239.          /* keyboard flags are checked to see if the alt key was  */
  240.          /* also pressed. If the alt key was pressed, we must     */
  241.          /* check if the key is a valid command, and if so        */
  242.          /* process it accordingly                                */
  243.  
  244.       key = bioskey(0);
  245.       if(!(key & 0x00ff))
  246.       {
  247.          switch(key)
  248.          {
  249.                /* exit  */
  250.  
  251.             case X:
  252.                Uninit();
  253.  
  254.  
  255.                /* Next com port  */
  256.  
  257.             case C:
  258.                ComParam(¶m);
  259.                indx.com++;
  260.                indx.com %= NUM_COM;
  261.                param.com = com[indx.com];
  262.                ComClose();
  263.                ComOpenS(¶m);
  264.                NewParam();
  265.                break;
  266.  
  267.  
  268.                /* Next baud rate */
  269.  
  270.             case B:
  271.                indx.baud++;
  272.                indx.baud %= NUM_BAUD;
  273.                ComBaud(baud[indx.baud]);
  274.                NewParam();
  275.                break;
  276.  
  277.  
  278.                /* Next word length  */
  279.  
  280.             case M:
  281.                indx.mode++;
  282.                indx.mode %= NUM_MODE;
  283.                ComMode(mode[indx.mode]);
  284.                NewParam();
  285.                break;
  286.  
  287.  
  288.                /* Toggle ansi terminal */
  289.  
  290.             case A:
  291.                indx.ansi ^= 1;
  292.                NewParam();
  293.                break;
  294.  
  295.  
  296.                /* Next handshake scheme   */
  297.  
  298.             case H:
  299.                indx.hndshk++;
  300.                indx.hndshk %= NUM_HND;
  301.                ComHandshake(hndshk[indx.hndshk], THRESH);
  302.                NewParam();
  303.                break;
  304.  
  305.  
  306.      /* Echo */
  307.  
  308.     case E:
  309.      indx.echo ^= 1;
  310.      break;
  311.  
  312.  
  313.                /* Toggle LF append  */
  314.  
  315.             case N:
  316.                indx.lf ^= 1;
  317.                NewParam();
  318.                break;
  319.  
  320.                /* Initialize hayes modem  */
  321.  
  322.             case I:
  323.                ComPuts("ATZ\r\n");
  324.                break;
  325.  
  326.  
  327.                /* Hayes modem dial command   */
  328.  
  329.             case D:
  330.                ComPuts("ATDT");
  331.                break;
  332.  
  333.  
  334.                /* Hayes modem hang up command   */
  335.  
  336.             case G:
  337.                ComPuts("+++");
  338.                delay(3000);
  339.                ComPuts("ATH0\r\n");
  340.                break;
  341.  
  342.             default:
  343.                continue;
  344.          }
  345.       }
  346.  
  347.  
  348.          /* If the key was not a command, put the character in the   */
  349.          /* transmit queue. If the character is a carriage return,   */
  350.          /* append a line feed to it just in case.                   */
  351.  
  352.       else
  353.       {
  354.          ComPutc((char)key);
  355.    if(indx.echo)
  356.     put_ch((char)key);
  357.          CheckStatus();
  358.          CheckError();
  359.       }
  360.    }
  361. }
  362.  
  363.  
  364. /*
  365. **-------------------------------------
  366. **
  367. ** Modified putch()
  368. **
  369. **-------------------------------------
  370. */
  371. void put_ch(char c)
  372. {
  373.  
  374.  gotoxy(x, y);
  375.  putch(c);
  376.  
  377.  
  378.    if(c == '\r' && indx.lf)
  379.          putch('\n');
  380.  
  381.    if(c == '\b')
  382.       cputs(" \b");
  383.  
  384.    x = wherex();
  385.    y = wherey();
  386. }
  387.  
  388.  
  389. /*
  390. **-------------------------------------
  391. **
  392. ** Initialize
  393. **
  394. **-------------------------------------
  395. */
  396. void Init(void)
  397. {
  398. FILE *fp;
  399.  
  400.  
  401.  
  402.       /* If an initialization file exists, load it.   */
  403.  
  404.    fp = fopen("comdemo.ini", "rb");
  405.    if(fp)
  406.       fread(&indx, sizeof(struct indx), 1, fp);
  407.  
  408.  
  409.  
  410.       /* Set up the screen */
  411.  
  412.    clrscr();
  413.    textattr(BLUE|(LIGHTGRAY<<4));
  414.    gotoxy(1,25);
  415.    cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %2s │"
  416.            " no errors    │ CTS=  DSR=   RI=  DCD=  ",
  417.                                     msg.com[indx.com],
  418.                                     msg.baud[indx.baud],
  419.                                     msg.mode[indx.mode],
  420.                                     msg.ansi[indx.ansi],
  421.                                     msg.hndshk[indx.hndshk],
  422.                                     msg.lf[indx.lf]);
  423.  
  424.  
  425.       /* Initialize the serial port to the default parameters,    */
  426.       /* set the timeout and set the DTR and RTS lines.           */
  427.  
  428.    ComClose();
  429.    ComOpen(com[indx.com], baud[indx.baud], mode[indx.mode], RCVQ, TXQ);
  430.  
  431.  
  432.       /* restore the normal screen  */
  433.  
  434.    textattr(LIGHTGRAY);
  435.    window(1,1,80,24);
  436. }
  437.  
  438.  
  439. /*
  440. **-------------------------------------
  441. **
  442. ** terminate
  443. **
  444. **-------------------------------------
  445. */
  446. void Uninit(void)
  447. {
  448. FILE *fp;
  449.  
  450.  
  451.       /* Store the present parameters in an .ini file so the program */
  452.       /* will remember next time it is executed.                     */
  453.  
  454.    fp = fopen("comdemo.ini", "wb");
  455.    if(fp)
  456.       fwrite(&indx, sizeof(struct indx), 1, fp);
  457.  
  458.  
  459.    ComClose();
  460.    system("cls");
  461.    puts("\n  ╒════════════════════════════════════════════════════════════════════════╕"
  462.         "\n  │           Cport v1.30  -  Copyright (c) 1991 Bri Productions           │"
  463.         "\n  ├────────────────────────────────────────────────────────────────────────┤"
  464.         "\n  │    Bri Productions,  P.O. Box 7121,  Fremont,  CA  94537-7121,  USA    │"
  465.         "\n  ╘════════════════════════════════════════════════════════════════════════╛"
  466.         );
  467.    exit(0);
  468. }
  469.  
  470.  
  471. /*
  472. **-------------------------------------
  473. **
  474. ** new parameter
  475. **
  476. **-------------------------------------
  477. */
  478. void NewParam(void)
  479. {
  480.  
  481.       /* Update the status line with the new parameters  */
  482.  
  483.    window(1,25, 80, 25);
  484.    textattr(BLUE|(LIGHTGRAY<<4));
  485.    cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %s │",
  486.                                     msg.com[indx.com],
  487.                                     msg.baud[indx.baud],
  488.                                     msg.mode[indx.mode],
  489.                                     msg.ansi[indx.ansi],
  490.                                     msg.hndshk[indx.hndshk],
  491.                                     msg.lf[indx.lf]);
  492.  
  493.  
  494.       /* restore the normal screen  */
  495.  
  496.    textattr(attrib);
  497.    window(1,1,80,24);
  498.  gotoxy(x, y);
  499. }
  500.  
  501.  
  502. /*
  503. **-------------------------------------
  504. **
  505. ** ansi control sequence
  506. **
  507. **-------------------------------------
  508. */
  509. void Ansi(void)
  510. {
  511. unsigned key;
  512. char c;
  513. char str[10];
  514. int Pn[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  515. int i=0,p=0;
  516. static int oldx=1;
  517. static int oldy=1;
  518.  
  519.  
  520.       /* While we are waiting for the next character, keep   */
  521.       /* checking for keys.                                  */
  522.  
  523.  
  524.    while((c = ComGetc()) == 0)
  525.  
  526.    if(bioskey(1))
  527.    {
  528.       key = bioskey(0);
  529.       ComPutc((char)key);
  530.    }
  531.  
  532.  
  533.       /* If the next character is a '[' it is probably an ansi    */
  534.       /* sequence. If the next character is not a '[', print the  */
  535.       /* previous escape character followed by the new character. */
  536.  
  537.    if(c != '[')
  538.    {
  539.       cprintf("\x1b%c",c);
  540.       return;
  541.    }
  542.  
  543.    while(1)
  544.    {
  545.  
  546.       /* Read the rest of the ansi sequence, while also checking  */
  547.       /* for keys.                                                */
  548.  
  549.       while((c = ComGetc()) == 0)
  550.  
  551.          if(bioskey(1))
  552.          {
  553.             key = bioskey(0);
  554.             ComPutc((char)key);
  555.          }
  556.  
  557.  
  558.          /* If the character is numeric, store it still it it's   */
  559.          /* ascii form                                            */
  560.  
  561.       if(isdigit(c))
  562.       {
  563.          *(str+i++) = c;
  564.          continue;
  565.       }
  566.  
  567.  
  568.          /* When no more numeric characters are received, terminate  */
  569.          /* the string and convert it to an integer, storing it in   */
  570.          /* the parameter queue.                                     */
  571.  
  572.       *(str+i) = '\0';
  573.       i=0;
  574.       Pn[p++] = atoi(str);
  575.  
  576.  
  577.          /* Check for the ';' delimiter   */
  578.  
  579.       if(c == ';')
  580.          continue;
  581.  
  582.  
  583.          /* When no more numeric parameters are received, the     */
  584.          /* command should be next. Now we can actually process   */
  585.          /* the command using the stores parameters               */
  586.  
  587.       else
  588.       {
  589.          switch(c)
  590.          {
  591.  
  592.  
  593.                /* (CUP) set cursor position  */
  594.  
  595.             case 'H':
  596.             case 'F':
  597.                y = Pn[0] ? Pn[0] : 1;
  598.                x = Pn[1] ? Pn[1] : 1;
  599.                return;
  600.  
  601.  
  602.                /* (CUU) cursor up   */
  603.  
  604.             case 'A':
  605.                y -= Pn[0];
  606.                if(y < 1)
  607.                   y = 1;
  608.                return;
  609.  
  610.  
  611.                /* (CUD) cursor down */
  612.  
  613.             case 'B':
  614.                y += Pn[0];
  615.                if(y > 24)
  616.                   y = 24;
  617.                return;
  618.  
  619.  
  620.                /* (CUF) cursor forward */
  621.  
  622.             case 'C':
  623.                x += Pn[0];
  624.                if(x >80)
  625.                   x = 80;
  626.                return;
  627.  
  628.  
  629.                /* (CUB) cursor backward   */
  630.  
  631.             case 'D':
  632.                x -= Pn[0];
  633.                if(x < 1)
  634.                   x = 1;
  635.                return;
  636.  
  637.  
  638.                /* (SCP) save cursor position */
  639.  
  640.             case 's':
  641.                oldx = x;
  642.                oldy = y;
  643.                return;
  644.  
  645.  
  646.                /* (RCP) restore cursor position */
  647.  
  648.             case 'u':
  649.                x = oldx;
  650.                y = oldy;
  651.                return;
  652.  
  653.  
  654.                /* clear screen   */
  655.  
  656.             case 'J':
  657.                if(Pn[0] == 2)
  658.                {
  659.                   clrscr();
  660.                   x=1;
  661.                   y=1;
  662.                }
  663.                else
  664.                {
  665.                   window(1,wherey(),80,24);
  666.                   clrscr();
  667.                   window(1,1,80,24);
  668.                   gotoxy(x, y);
  669.                }
  670.                return;
  671.  
  672.  
  673.                /* (EL) erase line   */
  674.  
  675.             case 'K':
  676.                clreol();
  677.                return;
  678.  
  679.  
  680.                /* An attribute command is more elaborate than the    */
  681.                /* others because it may have many numeric parameters */
  682.  
  683.             case 'm':
  684.                for(i=0; i<p; i++)
  685.                {
  686.  
  687.  
  688.                      /* values from 30 to 37 define the foreground color   */
  689.  
  690.                   if(Pn[i] >= 30 && Pn[i] <= 37)
  691.                   {
  692.                      attrib &= 0xf8;
  693.                      attrib |= (Pn[i] - 30);
  694.                   }
  695.  
  696.  
  697.                      /* values from 40 to 47 define the background color   */
  698.  
  699.                   if(Pn[i] >= 40 && Pn[i] <= 47)
  700.                   {
  701.                      attrib &= 0x8f;
  702.                      attrib |= ((Pn[i] - 40) << 4);
  703.                   }
  704.  
  705.  
  706.                      /* values from 0 to 7 define the other attributes   */
  707.  
  708.                   if(Pn[i] >= 0 && Pn[i] <= 7)
  709.                      switch(Pn[i])
  710.                      {
  711.  
  712.                         case 0:
  713.                            attrib = NORM;
  714.                            break;
  715.  
  716.                         case 1:
  717.                            attrib |= BOLD;
  718.                            break;
  719.  
  720.                         case 2:
  721.                            attrib &= FAINT;
  722.                            break;
  723.  
  724.                         case 5:
  725.                         case 6:
  726.                            attrib |= BLINK;
  727.                            break;
  728.  
  729.                         case 7:
  730.                            attrib ^= REVRS;
  731.                            break;
  732.  
  733.                         default:
  734.                            attrib = NORM;
  735.                      }
  736.                }
  737.  
  738.  
  739.                /* The red and blue bits in the ansi standard are     */
  740.                /* reversed relative to the IBM. Therefore, before we */
  741.                /* set the new attributes, if these bits are in       */
  742.                /* opposite states toggled. This must be done for     */
  743.                /* both the foreground and background.                */
  744.  
  745.                if((attrib & 0x05) == 0x04 || (attrib & 0x05) == 0x01)
  746.                   attrib ^= 0x05;
  747.  
  748.                if((attrib & 0x50) == 0x40 || (attrib & 0x50) == 0x10)
  749.                   attrib ^= 0x50;
  750.  
  751.                textattr(attrib);
  752.  
  753.             default:
  754.                return;
  755.          }
  756.       }
  757.    }
  758. }
  759.  
  760.  
  761. /*
  762. **-------------------------------------
  763. **
  764. ** check for errors
  765. **
  766. **-------------------------------------
  767. */
  768. void CheckError(void)
  769. {
  770. unsigned comerror;
  771. static unsigned last_error = 0;
  772. static int err_flg = 0;
  773. char *errmsg[]= { { "no errors    " },
  774.                   { "break detect " },
  775.                   { "frame error  " },
  776.                   { "parity error " },
  777.                   { "overrun      " },
  778.                   { "rx overflow " },
  779.                   { "tx overflow  " }
  780.                   };
  781.  
  782.    comerror = ComError();
  783.  
  784.  
  785.       /* Check if the error code has changed since the last call.    */
  786.       /* if it has not, there is no need to update the status line.  */
  787.       /* If the error code has changed, the error conditions are     */
  788.       /* checked in the order of their priority                      */
  789.  
  790.    if(comerror != last_error)
  791.    {
  792.       last_error = comerror;
  793.  
  794.       if(comerror & BREAK)
  795.          err_flg = 1;
  796.  
  797.       else if(comerror & FRAMING)
  798.          err_flg = 2;
  799.  
  800.       else if(comerror & PARITY)
  801.          err_flg = 3;
  802.  
  803.       else if(comerror & OVERUN)
  804.          err_flg = 4;
  805.  
  806.       else if(comerror & RXFULL)
  807.          err_flg = 5;
  808.  
  809.       else if(comerror & TXFULL)
  810.          err_flg = 6;
  811.  
  812.       else
  813.          err_flg = 0;
  814.  
  815.  
  816.          /* Update the status line with the new information   */
  817.  
  818.       window(1,25, 80, 25);
  819.       textattr(BLUE|(LIGHTGRAY<<4));
  820.       gotoxy(ERR_X,1);
  821.       cprintf(errmsg[err_flg]);
  822.  
  823.  
  824.          /* restore the normal screen  */
  825.  
  826.       textattr(attrib);
  827.       window(1,1,80,24);
  828.     gotoxy(x, y);
  829.    }
  830. }
  831.  
  832.  
  833. /*
  834. **-------------------------------------
  835. **
  836. ** check modem status
  837. **
  838. **-------------------------------------
  839. */
  840. void CheckStatus(void)
  841. {
  842. byte status;
  843. static byte last_status = 1;
  844. int i;
  845.  
  846.    status = ComStatus();
  847.  
  848.  
  849.       /* Check if the modem status has changed since the last call.  */
  850.       /* if it has not, there is no need to update the status line.  */
  851.       /* If the modem status has changed, each bit is checked for    */
  852.       /* it's condition and printed on the status line               */
  853.  
  854.    if(status != last_status)
  855.    {
  856.       last_status = status;
  857.       window(1,25, 80, 25);
  858.       textattr(BLUE|(LIGHTGRAY<<4));
  859.  
  860.  
  861.          /* On each iteration, i = the x coordinate in the status */
  862.          /* line. The bits are checked for left to right. The     */
  863.          /* statement !!(status & 0x10) resolves to 1 if the bit  */
  864.          /* is set or 0 if the bit is clear. By adding 0x30 the   */
  865.          /* 1 or 0 is converted to an ascii character             */
  866.  
  867.       for(i=STAT_X; i<STAT_X+6*4; i+=6)
  868.       {
  869.          gotoxy(i,1);
  870.          putch(!!(status & 0x10) + 0x30);
  871.          status >>= 1;
  872.       }
  873.  
  874.  
  875.          /* restore the normal screen  */
  876.  
  877.       textattr(attrib);
  878.       window(1,1,80,24);
  879.     gotoxy(x, y);
  880.    }
  881. }
  882.  
  883.  
  884.