home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / C / COMM.ZIP / COMM.C
Encoding:
Text File  |  1985-06-03  |  5.3 KB  |  309 lines

  1.  
  2.  
  3. COMM.C.1
  4.  
  5.  
  6.  
  7.  
  8. /* NOTE: this code is indented using tabs set every 4 columns, not 8. */
  9.  
  10.  
  11. /*
  12.  
  13.  * Rudimentary communication program; written in C with I/O
  14.  
  15.  * routines in assembler, using "#asm" construct in DeSmet C.
  16.  
  17.  */
  18.  
  19.  
  20. #define TRUE 1
  21.  
  22. #define FALSE 0
  23.  
  24. #define NULL 0
  25.  
  26.  
  27. #define comm_stat head!=tail
  28.  
  29.  
  30. int head=0,
  31.  
  32.     tail=0;
  33.  
  34.  
  35. char comm_buffer[8192];
  36.  
  37.  
  38. main()
  39.  
  40. {
  41.  
  42.     char commget();
  43.  
  44.  
  45.     int c,
  46.  
  47.         echo=FALSE,
  48.  
  49.         verbose=FALSE;
  50.  
  51.  
  52.     initcomm();
  53.  
  54.  
  55.     goto inside;
  56.  
  57.     while((c=my_ci())<256) /* alt's and function keys are >=256 */
  58.  
  59.     {
  60.  
  61.         commput(c);
  62.  
  63.         if(echo)
  64.  
  65.             my_co(c);
  66.  
  67. inside:    while(my_stat()==0)
  68.  
  69.             if(comm_stat)
  70.  
  71.                 if(is_nice(c=commget()))
  72.  
  73.                     my_co(c);
  74.  
  75.                 else
  76.  
  77.                     if(verbose)
  78.  
  79.                     {
  80.  
  81.                         my_co('^');
  82.  
  83.                         my_co(127&(c+'@'));
  84.  
  85.                     }
  86.  
  87.     }
  88.  
  89.     switch(c>>8) /* process function key */
  90.  
  91.     {
  92.  
  93.         case '\060': /* b    send break    */
  94.  
  95.             make_break();
  96.  
  97.             my_puts("** break **\n");
  98.  
  99.             break;
  100.  
  101.         case '\022': /* e    echo toggle    */
  102.  
  103.             echo = !echo;
  104.  
  105.             if(echo)
  106.  
  107.                 my_puts("** echo on **\n");
  108.  
  109.             else
  110.  
  111.                 my_puts("** echo off **\n");
  112.  
  113.             break;
  114.  
  115.         case '\020': /* q    quit        */
  116.  
  117.             my_puts("** returning to DOS **\n");
  118.  
  119.             goto byebye;
  120.  
  121.         case '\057': /* v    verbose        */
  122.  
  123.             verbose = !verbose;
  124.  
  125.             if(verbose)
  126.  
  127.                 my_puts("** verbose on **\n");
  128.  
  129.             else
  130.  
  131.                 my_puts("** verbose off **\n");
  132.  
  133.             break;
  134.  
  135.     }
  136.  
  137.     goto inside;
  138.  
  139.  
  140. byebye:
  141.  
  142.     killcomm();
  143.  
  144. }
  145.  
  146.  
  147. initcomm()
  148.  
  149. {
  150.  
  151. #asm
  152.  
  153.  
  154. ; initialize communication port,
  155.  
  156. ; and install interrupt handler
  157.  
  158.  
  159. ; save dseg for interrupt handler
  160.  
  161.     mov        ax,ds
  162.  
  163.     mov        cs:dssave,ax
  164.  
  165.  
  166. ; set int vector to my handler
  167.  
  168.     push    ds
  169.  
  170.     xor        ax,ax
  171.  
  172.     mov        ds,ax
  173.  
  174.     mov        [30h],offset handler
  175.  
  176.     mov        ax,cs
  177.  
  178.     mov        [32h],ax
  179.  
  180.     pop        ds
  181.  
  182.  
  183. ; assert DTR, RTS, and OUT2
  184.  
  185.     mov        dx,3fch
  186.  
  187.     mov        al,11
  188.  
  189.     out        dx,al
  190.  
  191.  
  192. ; enable interrupts for data ready
  193.  
  194.     mov        dx,3f9h
  195.  
  196.     mov        al,1
  197.  
  198.     out        dx,al
  199.  
  200.  
  201. ; clear any outstanding int
  202.  
  203.     mov        dx,3f8h
  204.  
  205.     in        al,dx
  206.  
  207.  
  208. ; enable interrupts
  209.  
  210.     sti
  211.  
  212.  
  213. ; enable IRQ4 on 8259A
  214.  
  215.     in        al,21h
  216.  
  217.     and        al,0efh
  218.  
  219.     out        21h,al
  220.  
  221.  
  222. ; and return
  223.  
  224.     jmp        init_finis
  225.  
  226.  
  227. dssave:    dw 0
  228.  
  229.  
  230. handler:
  231.  
  232.     push    ds
  233.  
  234.     push    ax
  235.  
  236.     push    dx
  237.  
  238.     push    bx
  239.  
  240.  
  241. ; restore appropriate dseg
  242.  
  243.     mov        ax,cs:dssave
  244.  
  245.     mov        ds,ax
  246.  
  247.  
  248. ; grab the byte from comm port
  249.  
  250.     mov        dx,3f8h
  251.  
  252.     in        al,dx
  253.  
  254.  
  255. ; put it in the buffer
  256.  
  257.     mov        bx,tail_
  258.  
  259.     mov        comm_buffer_[bx],al
  260.  
  261.  
  262. ; tail=tail+1 (mod 8192)
  263.  
  264.     inc        bx
  265.  
  266.     cmp        bx,8192
  267.  
  268.     jl        handler_around
  269.  
  270.     xor        bx,bx
  271.  
  272.  
  273. handler_around:
  274.  
  275.     mov        tail_,bx
  276.  
  277.  
  278. ; tell the 8259A EOI
  279.  
  280.     mov        dx,20h
  281.  
  282.     mov        al,32
  283.  
  284.     out        dx,al
  285.  
  286.  
  287.     pop        bx
  288.  
  289.     pop        dx
  290.  
  291.     pop        ax
  292.  
  293.     pop        ds
  294.  
  295.  
  296. ; reenable interrupts
  297.  
  298.     sti
  299.  
  300.  
  301.     iret
  302.  
  303.  
  304. init_finis:
  305.  
  306. #
  307.  
  308. }
  309.  
  310.  
  311. commput(c)
  312.  
  313. int c;
  314.  
  315. {
  316.  
  317. #asm
  318.  
  319. ; put the character out the port
  320.  
  321.     mov        dx,3f8h
  322.  
  323.     mov        ax,[bp+4]
  324.  
  325.     out        dx,al
  326.  
  327. #
  328.  
  329. }
  330.  
  331.  
  332. char commget()
  333.  
  334. {
  335.  
  336.     char temp;
  337.  
  338.  
  339.         temp=comm_buffer[head++];
  340.  
  341.         head%=8192;
  342.  
  343.         return(temp);
  344.  
  345. }
  346.  
  347.  
  348. killcomm()
  349.  
  350. {
  351.  
  352. #asm
  353.  
  354. ; disconnect the interrupt handler
  355.  
  356.     in        al,21h
  357.  
  358.     or        al,10h
  359.  
  360.     out        21h,al
  361.  
  362. #
  363.  
  364. }
  365.  
  366.  
  367. make_break()
  368.  
  369. {
  370.  
  371. #asm
  372.  
  373. ; set bit on LCR
  374.  
  375.     mov        dx,3fbh
  376.  
  377.     in        al,dx
  378.  
  379.     push    ax
  380.  
  381.     or        al,40h
  382.  
  383.     out        dx,al
  384.  
  385.  
  386. ; wait a wee bit (~200 ms)
  387.  
  388.     mov        bx,8
  389.  
  390. outer:
  391.  
  392.     mov        cx,7000
  393.  
  394. tight:
  395.  
  396.     loop    tight
  397.  
  398.     dec        bx
  399.  
  400.     jnz        outer
  401.  
  402.  
  403. ; and turn break back off
  404.  
  405.     pop        ax
  406.  
  407.     out        dx,al
  408.  
  409. #
  410.  
  411. }
  412.  
  413.  
  414. is_nice(c) /* true for those characters that "should" be received */
  415.  
  416. char c;
  417.  
  418. {
  419.  
  420.     c&=127;
  421.  
  422.     if(c>=' ' && c<='~')    /* printable */
  423.  
  424.         return(TRUE);
  425.  
  426.     if(c>6 && c<11)            /* BEL, BS, HT, LF */
  427.  
  428.         return(TRUE);
  429.  
  430.     if(c==13 || c==27)        /* CR, ESC */
  431.  
  432.         return(TRUE);
  433.  
  434.     return(FALSE);
  435.  
  436. }
  437.  
  438.  
  439. my_puts(s) /* puts, using my_co() */
  440.  
  441. char *s;
  442.  
  443. {
  444.  
  445.     while(*s)
  446.  
  447.     {
  448.  
  449.         if(*s=='\n')
  450.  
  451.             my_co('\r');
  452.  
  453.         my_co(*(s++));
  454.  
  455.     }
  456.  
  457. }
  458.  
  459.  
  460. my_co(c) /* character output, smaller and faster than DeSmet's,
  461.  
  462.             using DOS function call 2.00 */
  463.  
  464. char c;
  465.  
  466. {
  467.  
  468. #asm
  469.  
  470.     mov        ah,2
  471.  
  472.     mov        dx,[bp+4]
  473.  
  474.     int        21h
  475.  
  476. #
  477.  
  478. }
  479.  
  480.  
  481. my_stat() /* true if character is ready from keyboard */
  482.  
  483. {
  484.  
  485. #asm
  486.  
  487.     mov        ah,1
  488.  
  489.     int        16h
  490.  
  491.     jz        stat_no_char
  492.  
  493.     mov        ax,1
  494.  
  495.     jmp        stat_finis
  496.  
  497.  
  498. stat_no_char:
  499.  
  500.     xor        ax,ax
  501.  
  502.  
  503. stat_finis:
  504.  
  505. #
  506.  
  507. }
  508.  
  509.  
  510. my_ci() /* get character from keyboard, using BIOS function call */
  511.  
  512. {
  513.  
  514. #asm
  515.  
  516.     xor        ah,ah
  517.  
  518.     int        16h
  519.  
  520.     or        al,al
  521.  
  522.     jz        my_ci_finis
  523.  
  524.     xor        ah,ah
  525.  
  526.  
  527. my_ci_finis:
  528.  
  529. #
  530.  
  531. }
  532.  
  533. ------------------------------------------------------------------------------
  534.  
  535. The termcap for DOS 2.00 with ansi device driver follows:
  536.  
  537. ------------------------------------------------------------------------------
  538.  
  539. pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\
  540.  
  541.     :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
  542.  
  543.     :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
  544.  
  545.     :pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt:
  546.  
  547. pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\
  548.  
  549.     :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
  550.  
  551.     :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
  552.  
  553.     :pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt:
  554.  
  555. ------------------------------------------------------------------------------
  556.  
  557. and that's it! Enjoy. I place this in the public domain, and would appreciate
  558.  
  559. feedback. Improvements and bug reports especially desired. If the code is too
  560.  
  561. cryptic or uncommented, feel free to send questions to:
  562.  
  563.                     Bennett Todd
  564.  
  565.                     ...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet
  566.  
  567.