home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / ISC366.ZIP / SERIAL / SERIALSE.CPP < prev    next >
Text File  |  1993-09-01  |  8KB  |  270 lines

  1. ///////////////////////////////////////////////////////////////////////////
  2. //                                                                       //
  3. //            File: serialse.cpp                                         //
  4. //            started on: 5/2/92                                         //
  5. //                                                                       //
  6. ///////////////////////////////////////////////////////////////////////////
  7. //                                                                       //
  8. //  This class sends and receives data via interrupt driven Serial       //
  9. //  engine. very comfortable interface (I think). Might not work on      //
  10. //  slow machines in high baud rates (after all it's written in a high   //
  11. //  level language).                                                     //
  12. //                                                                       //
  13. ///////////////////////////////////////////////////////////////////////////
  14. //                                                                       //
  15. //                    by Ofer Laor (AKA LeucroTTA)                       //
  16. //                                                                       //
  17. ///////////////////////////////////////////////////////////////////////////
  18.  
  19. #include "serial.h" // SERIAL_PORT
  20. #include <dos.h>    // outportb, inportb
  21.  
  22. const unsigned long SERIAL_PORT::BAUD_CONST = 115200L;
  23.  
  24. const unsigned BUFF_SIZE= 256; // communication buffer size.
  25.  
  26. // sets the imr to enable the hardware interrupt request line.
  27. //
  28. void SERIAL_PORT::set_imr(void)
  29. {
  30.     outportb (com_pic_port+ PIC_IMR, (inportb (com_pic_port+ PIC_IMR) & com_imr_mask));
  31. }
  32.  
  33. // sends an eoi to the pic.
  34. //
  35. void SERIAL_PORT::eoi(void)
  36. {
  37.     outportb (com_pic_port+ PIC_DATA, 0x20); // send pic eoi message.
  38. }
  39.  
  40. // update flow_enabled.
  41. //
  42. void SERIAL_PORT::flow_check(void)
  43. {
  44.     flow_enabled= TRUE;
  45. }
  46.  
  47. // error has been received.
  48. //
  49. void SERIAL_PORT::com_error(void)
  50. {
  51.     // read twice to try and free the error.
  52.     inportb(com_port+ DATA);
  53.     inportb(com_port+ DATA);
  54. }
  55.  
  56. // set up the serial port.
  57. //
  58. void SERIAL_PORT::set_up_port( const long baud_rate, const BYTE word_len,
  59.                                const BYTE parity, const BYTE stop_bits)
  60. {
  61.     // if already initialized, exit.
  62.     //
  63.     if (InitFlag)
  64.        return;
  65.  
  66.     outportb (com_port+ LCR, 0x80); // set DLAB
  67.  
  68.     outport (com_port+ BAUDLOW, (unsigned)(BAUD_CONST / baud_rate));
  69.  
  70.     // LCR is eventual going to be set to temp.
  71.     //
  72.     BYTE temp= 0; // DLAB= 0;
  73.  
  74.     temp&=0xc7; // clear parity.
  75.     switch (parity) {
  76.            case 'N': // no parity
  77.                      temp|= 0x0;
  78.                      break;
  79.            case 'O': // ODD parity.
  80.                      temp|= 0x8;
  81.                      break;
  82.            case 'E': // EVEN parity.
  83.                      temp|= 0x18;
  84.                      break;
  85.            case 'M': // MARK.
  86.                      temp|= 0x28;
  87.                      break;
  88.            case 'S': // SPACE.
  89.                      temp|= 0x38;
  90.                      break;
  91.     }
  92.  
  93.     temp&=0xfb; // clear stop bits.
  94.     switch (stop_bits) {
  95.            case 1: // one stop bit.
  96.                    break;
  97.            case 2: // two stop bits.
  98.                    temp|= 0x4;
  99.     }
  100.  
  101.     temp&=0xfc; // clear word len.
  102.     switch (word_len) {
  103.            case 5: // word len= 5.
  104.                    break;
  105.            case 6: // word len= 6.
  106.                    temp|= 0x1;
  107.                    break;
  108.            case 7: // word len= 7.
  109.                    temp|= 0x2;
  110.                    break;
  111.            case 8: // word len= 8.
  112.                    temp|= 0x3;
  113.                    break;
  114.     }
  115.  
  116.     outportb (com_port+ LCR, temp); // set LCR to options.
  117.  
  118. }
  119.  
  120. // the constructor gets as parameters- the port number associated with the
  121. // serial port, as well as the HARDWARE interrupt number it is attached to,
  122. // the software interrupt it generates and the PIC port that holds it.
  123. //
  124.  
  125. SERIAL_PORT::SERIAL_PORT (const unsigned port_num,
  126.                          const unsigned irq_line_num,
  127.                          const unsigned int_num,
  128.                          const unsigned pic_port_num= 0x20) : ISC()
  129. {
  130.     InitFlag= FALSE;
  131.  
  132.     // setup serial_port parameters.
  133.     activate(port_num, irq_line_num, int_num, pic_port_num);
  134. }
  135.  
  136. void SERIAL_PORT::activate (const unsigned port_num,
  137.                            const unsigned irq_line_num,
  138.                            const unsigned int_num,
  139.                            const unsigned pic_port_num= 0x20)
  140. {
  141.     // if already initialized, exit.
  142.     //
  143.     if (InitFlag)
  144.        return;
  145.  
  146.     // initializing do_send vars.
  147.     do_send_recursive_count= 0;
  148.     do_send_recursive_flag= FALSE;
  149.  
  150.     // resize I/O buffers.
  151.  
  152.     in_buff.reset_size(BUFF_SIZE, TRUE);
  153.     out_buff.reset_size(BUFF_SIZE, TRUE);
  154.  
  155.     // the serial's port.
  156.     com_port= port_num;
  157.  
  158.     // hardware interrupt request line num.
  159.  
  160.     com_imr_mask= ~(0x1 << irq_line_num); // all "1" except a "0" on the line request...
  161.  
  162.     // hardware interrupt num.
  163.     com_int= int_num;
  164.  
  165.     // default imr_port is 0x20.
  166.     //
  167.     com_pic_port= pic_port_num;
  168.  
  169.     // now hook interrupts via ISC.
  170.     //
  171.     ISC::activate(com_int);
  172.  
  173.     outportb (com_port+ IER, 0xF); //  enable UART interrupts on all calls!!!
  174.  
  175.     // clear RCV buffers
  176.     inportb (com_port+ LSR);  // clear LSR.
  177.     inportb (com_port+ DATA); // clear RX register.
  178.     inportb (com_port+ MSR);  // clear MSR register.
  179.  
  180.     inportb (com_port+ IID);  // read IID register (to clear it's Flip-Flop flag).
  181.  
  182.     // repeat all readings to be sure they are clear.
  183.     if (inportb (com_port+ IID) & 1) {
  184.        // repeat the clearing...
  185.        inportb (com_port+ LSR);  // clear LSR
  186.        inportb (com_port+ DATA); // clear RX register
  187.        inportb (com_port+ MSR);  // clear MSR register
  188.     }
  189.  
  190.     // and now enable the modem's interrupt enable.
  191.  
  192.     outportb (com_port+ MCR, (inportb(com_port+ MCR)| 8));  // write it into MCR. (turn on OUT2).
  193.  
  194.     // 8259A programming...
  195.     set_imr(); // setup imr.
  196.  
  197.     eoi();     // send pic an EOI just to be sure.
  198.  
  199.     // allow derived classes to extend the initialization of the port.
  200.     //
  201.     extended_init();
  202.  
  203.     // default port settings.
  204.     set_up_port (9600,8,'N',1);
  205. }
  206.  
  207. // this constructor gets a single number from 1 to 4 (must be a legal serial
  208. // port- it does not test it's validity), and hooks to it.
  209. //
  210. SERIAL_PORT::SERIAL_PORT (const unsigned com_num) : ISC()
  211. {
  212.     InitFlag= FALSE;
  213.  
  214.     // setup serial port parameters.
  215.     activate(com_num);
  216. }
  217.  
  218. // setup parameters.
  219. //
  220. void SERIAL_PORT::activate(const unsigned com)
  221. {
  222.     unsigned com_num= com;
  223.  
  224.     // exit if already initialized.
  225.     if (InitFlag)
  226.        return;
  227.  
  228.     com_num--;
  229.     com_num%= 4;  // now com_num is between 0-3 (and can be used for offsets!).
  230.  
  231.     unsigned huge *port_num= (unsigned huge *)0x00000400L; // bios data area.
  232.  
  233.     com_port= *(port_num+ com_num); // access bios data area and retrieve the com port...
  234.  
  235.     unsigned com_irq_line;
  236.     switch (com_num) {
  237.  
  238.            // com1 & com3.
  239.  
  240.            case 0:
  241.            case 2:
  242.                 com_irq_line= 4;
  243.                 com_int= 0xc;
  244.                 break;
  245.  
  246.            // com2 & com4.
  247.  
  248.            case 1:
  249.            case 3:
  250.                 com_irq_line= 3;
  251.                 com_int= 0xb;
  252.                 break;
  253.     }
  254.  
  255.  
  256.     // now reuse activate.
  257.     //
  258.     activate(com_port, com_irq_line, com_int);
  259. }
  260.  
  261. SERIAL_PORT::SERIAL_PORT() : ISC()
  262. {
  263.     InitFlag= FALSE;
  264. }
  265.  
  266. SERIAL_PORT::~SERIAL_PORT()
  267. {
  268.     outportb (com_port+ IER, 0); //  disable UART interrupts on all calls!!!
  269. }
  270.