home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / hf / dsp / dsp4tool / serial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-20  |  4.7 KB  |  232 lines

  1. /*  SERIAL.C -- IBM Serial Port handler (with interrupts)
  2.  *
  3.  *  Copyright (C) 1989,1990,1991 by Alef Null. All rights reserved.
  4.  *  Author(s): J Vuori, E Torsti
  5.  *  Modification(s):
  6.  *    1989-Sep: COM1, COM2 and baud rate selection with
  7.  *          OpenSerial(int port, int baud)
  8.  *    1991-Apr: DTR line control function added
  9.  */
  10.  
  11.  
  12. #define BUFLEN    4096    // buffer lenght
  13.  
  14.  
  15. #include <dos.h>
  16. #include <conio.h>
  17. #include <stdlib.h>
  18. #include <malloc.h>
  19. #include <stdio.h>
  20. #include "serial.h"
  21.  
  22.  
  23. /* ring buffer definitions */
  24. #define NEXT(p) if (++(p) >= &buffer[BUFLEN]) (p) = buffer
  25. static volatile unsigned char *head, *tail;
  26. static        unsigned char *buffer;
  27.  
  28.  
  29. /* i/o-port definitions */
  30. #define PIC_MASK  0x21    // 8259 mask register
  31. #define PIC_EOI   0x20    // 8259 EOI command
  32. static const struct {
  33.     int data,        // 8250 data register
  34.     ier,        //    interrupt enable register
  35.     lcr,        //    line control register
  36.     mcr,        //    modem control register
  37.     stat;        //    status register
  38.     int intno;        // interrupt number
  39.     int mask;        // PIC mask
  40. } *comport, comports[2] = {
  41.     /* COM1 */
  42.     0x3f8, 0x3f9, 0x3fb, 0x3fc, 0x3fd,
  43.     0x0c,
  44.     0x10,
  45.  
  46.     /* COM2 */
  47.     0x2f8, 0x2f9, 0x2fb, 0x2fc, 0x2fd,
  48.     0x0b,
  49.     0x08,
  50. };
  51.  
  52.  
  53. #if defined(__TURBOC__)
  54.     /* store for old interrupt vector */
  55.     static void (interrupt far *OldHandler)(void);
  56.  
  57.     /*
  58.      * 8250 UART Interrupt server routine
  59.      */
  60.     static void interrupt far ReadChr(void) {
  61.     *head = (unsigned char)inp(comport->data);
  62.     NEXT(head);
  63.  
  64.     outp(PIC_EOI, 0x20);
  65.     }
  66. #else
  67.     /* store for old interrupt vector */
  68.     static void (interrupt far cdecl *OldHandler)(void);
  69.  
  70.     #pragma intrinsic(inp, outp)    // produces more beautiful code with this
  71.  
  72.     /*
  73.      * 8250 UART Interrupt server routine
  74.      */
  75.     #pragma check_stack(off)        // because stack check is not allowed in interrupt service routine
  76.     static void cdecl interrupt far ReadChr(void) {
  77.     *head = (unsigned char)inp(comport->data);
  78.     NEXT(head);
  79.  
  80.     outp(PIC_EOI, 0x20);
  81.     }
  82.     #pragma check_stack()
  83. #endif
  84.  
  85.  
  86. /*
  87.  * Initializes serial communication
  88.  *
  89.  * enter with:
  90.  *  port - 1 = COM1, 2 = COM2
  91.  *
  92.  * returns:
  93.  *  NULL if failed
  94.  */
  95. int OpenSerial(int port, int baud) {
  96.     comport = &comports[port-1];
  97.  
  98.     /* allocate receiving buffer */
  99.     if ((buffer = (unsigned char *)malloc(BUFLEN)) != NULL) {
  100.     /* reset buffer */
  101.     head = tail = buffer;
  102.  
  103.     /* set interrupt vector */
  104.     OldHandler = _dos_getvect(comport->intno);
  105.     _dos_setvect(comport->intno, ReadChr);
  106.  
  107.     /* set 8250 UART chip */
  108.     SetBaudRate(baud);
  109.     SetDTR(0);
  110.     outp(comport->ier, 0x01);            // enable rec interrupt
  111.  
  112.     inp(comport->data);                // make UART happy
  113.  
  114.     /* set 8259 PIC chip */
  115.     outp(PIC_MASK, inp(PIC_MASK) & ~comport->mask); // remove interrupt mask
  116.  
  117.     return(-1);
  118.     } else
  119.     return(0);
  120. }
  121.  
  122.  
  123. /*
  124.  * Terminates serial communication
  125.  */
  126. void CloseSerial(void) {
  127.     /* set 8259 PIC chip */
  128.     outp(PIC_MASK, inp(PIC_MASK) | comport->mask);  // set mask
  129.  
  130.     /* reset interrupt vector */
  131.     _dos_setvect(comport->intno, OldHandler);
  132.  
  133.     free(buffer);
  134. }
  135.  
  136.  
  137. /*
  138.  * Reads one character from serial port,
  139.  * returns -1 if there are no characters waiting
  140.  */
  141. int ReadSerial(void) {
  142.     register int c;
  143.  
  144.     if (head != tail) {
  145.     c = *tail;
  146.     NEXT(tail);
  147.     return(c);
  148.     } else
  149.     return(-1);
  150. }
  151.  
  152.  
  153. /*
  154.  * Writes one character to serial port
  155.  */
  156. int WriteSerial(int c) {
  157.     while(!(inp(comport->stat) & 0x20));    // wait TBE status
  158.  
  159.     //printf("%02X ", c & 0xff);
  160.     return(outp(comport->data, c));
  161. }
  162.  
  163.  
  164. /*
  165.  * Controls DTR-line
  166.  */
  167. void SetDTR(int state) {
  168.     outp(comport->mcr, state ? 0x0f : 0x0e);
  169. }
  170.  
  171.  
  172. /*
  173.  * Controls baud rate
  174.  */
  175. void SetBaudRate(int baud) {
  176.     outp(comport->lcr, 0x83);
  177.     outp(comport->data, (12L*9600L/(long)baud) & 0xff);
  178.     outp(comport->ier,    (12L*9600L/(long)baud) >> 8);
  179.     outp(comport->lcr, 0x03);                // 8, n, 1
  180. }
  181.  
  182.  
  183. /*
  184.  * Check if break condition detected
  185.  */
  186. int IfBreak(void) {
  187.     return (inp(comport->stat) & 0x10);
  188. }
  189.  
  190.  
  191. #if defined(DEBUG)
  192.     #include <stdio.h>
  193.     #include <signal.h>
  194.  
  195.     #define PORT    1
  196.     #define BAUD    9600
  197.  
  198.     /*
  199.      * CTRL-C handler
  200.      */
  201.     void handler(void) {
  202.     CloseSerial();
  203.     printf("disconnected\n");
  204.     exit(-1);
  205.     }
  206.  
  207.  
  208.     int main(void) {
  209.     int c;
  210.  
  211.     signal(SIGINT, handler);
  212.     if (!OpenSerial(PORT, BAUD)) {
  213.         fprintf(stderr, "Can't open serial port COM%d\n", PORT);
  214.         return(-1);
  215.     }
  216.  
  217.     printf("Simple serial port terminal [COM%1d, %4d] (%s)\n", PORT, BAUD, __DATE__);
  218.     printf("Press CTRL-C to exit\n\n");
  219.  
  220.     while (1) {
  221.         while ((c = ReadSerial()) == -1)
  222.         if (kbhit())
  223.             WriteSerial(getch());
  224.  
  225.         putchar(c & 0x7f);
  226.     }
  227.  
  228.     CloseSerial();
  229.     return(0);
  230.     }
  231. #endif
  232.