* sim/ucsim/*.*, sim/ucsim/configure, sim/ucsim/configure.in:
[fw/sdcc] / sim / ucsim / s51.src / serial.cc
index 3b5436d0c70176487f9ea3e5fd27256ab0f01045..e36fb422b05d924451a3f461a045e1ab97a12759 100644 (file)
@@ -2,7 +2,7 @@
  * Simulator of microcontrollers (serial.cc)
  *
  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
- * 
+ *
  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
  *
  */
@@ -30,12 +30,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
+#ifdef HAVE_TERMIOS_H
 #include <termios.h>
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/time.h>
 #include <strings.h>
+#include <assert.h>
 
 // prj
 #include "globals.h"
@@ -44,36 +49,47 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "serialcl.h"
 #include "regs51.h"
 #include "uc51cl.h"
+#include "cmdutil.h"
 
 
 cl_serial::cl_serial(class cl_uc *auc):
   cl_hw(auc, HW_UART, 0, "uart")
-{}
+{
+  serial_in= serial_out= NIL;
+}
 
 cl_serial::~cl_serial(void)
 {
+  if (serial_in != serial_out && serial_in)
+    {
+#ifdef HAVE_TERMIOS_H
+      if (isatty(fileno(serial_in)))
+        tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
+#endif
+      fclose(serial_in);
+    }
   if (serial_out)
     {
+#ifdef HAVE_TERMIOS_H
       if (isatty(fileno(serial_out)))
-       tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
+        tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
+#endif
       fclose(serial_out);
     }
-  if (serial_in)
-    {
-      if (isatty(fileno(serial_in)))
-       tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
-      fclose(serial_in);
-    }
+  delete serial_in_file_option;
+  delete serial_out_file_option;
 }
 
 int
 cl_serial::init(void)
 {
-  class cl_mem *sfr;
+#ifdef HAVE_TERMIOS_H
   int i;
   struct termios tattr;
+#endif
 
-  sfr= uc->mem(MEM_SFR);
+  set_name("mcs51_uart");
+  sfr= uc->address_space(MEM_SFR_ID);
   if (sfr)
     {
       //sbuf= sfr->register_hw(SBUF, this, 0);
@@ -84,57 +100,81 @@ cl_serial::init(void)
       register_cell(sfr, SCON, &scon, wtd_restore_write);
     }
 
-  serial_in = (FILE*)application->args->get_parg(0, "Ser_in");
-  serial_out= (FILE*)application->args->get_parg(0, "Ser_out");
-  if (serial_in)
+  serial_in_file_option= new cl_optref(this);
+  serial_in_file_option->init();
+  serial_in_file_option->use("serial_in_file");
+  serial_out_file_option= new cl_optref(this);
+  serial_out_file_option->init();
+  serial_out_file_option->use("serial_out_file");
+
+  //char *fni, *fno;
+  /*if ((fni= serial_in_file_option->get_value((char*)0)))
+    serial_in= fopen(fni, "r");
+  if ((fno= serial_out_file_option->get_value((char*)0)))
+  serial_out= fopen(fno, "w");*/
+
+  //serial_in = (FILE*)application->args->get_parg(0, "Ser_in");
+  //serial_out= (FILE*)application->args->get_parg(0, "Ser_out");
+  serial_in = (FILE*)serial_in_file_option->get_value((void*)0);
+  serial_out= (FILE*)serial_out_file_option->get_value((void*)0);
+
+  if (serial_in != serial_out && serial_in)
     {
       // making `serial' unbuffered
       if (setvbuf(serial_in, NULL, _IONBF, 0))
-       perror("Unbuffer serial input channel");
+        perror("Unbuffer serial input channel");
+#ifdef _WIN32
+      if (CH_SERIAL != get_handle_type((HANDLE)_get_osfhandle(fileno(serial_in))))
+#elif defined HAVE_TERMIOS_H
       // setting O_NONBLOCK
       if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)
-       perror("Get flags of serial input");
+        perror("Get flags of serial input");
       i|= O_NONBLOCK;
       if (fcntl(fileno(serial_in), F_SETFL, i) < 0)
-       perror("Set flags of serial input");
+        perror("Set flags of serial input");
       // switching terminal to noncanonical mode
       if (isatty(fileno(serial_in)))
-       {
-         tcgetattr(fileno(serial_in), &saved_attributes_in);
-         tcgetattr(fileno(serial_in), &tattr);
-         tattr.c_lflag&= ~(ICANON|ECHO);
-         tattr.c_cc[VMIN] = 1;
-         tattr.c_cc[VTIME]= 0;
-         tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);
-       }
+        {
+          tcgetattr(fileno(serial_in), &saved_attributes_in);
+          tcgetattr(fileno(serial_in), &tattr);
+          tattr.c_lflag&= ~(ICANON|ECHO);
+          tattr.c_cc[VMIN] = 1;
+          tattr.c_cc[VTIME]= 0;
+          tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);
+        }
       else
-       fprintf(stderr, "Warning: serial input interface connected to a "
-               "non-terminal file.\n");
+#endif
+        fprintf(stderr, "Warning: serial input interface connected to a "
+                "non-terminal file.\n");
     }
   if (serial_out)
     {
       // making `serial' unbuffered
       if (setvbuf(serial_out, NULL, _IONBF, 0))
-       perror("Unbuffer serial output channel");
+        perror("Unbuffer serial output channel");
+#ifdef _WIN32
+      if (CH_SERIAL != get_handle_type((HANDLE)_get_osfhandle(fileno(serial_out))))
+#elif defined HAVE_TERMIOS_H
       // setting O_NONBLOCK
       if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)
-       perror("Get flags of serial output");
+        perror("Get flags of serial output");
       i|= O_NONBLOCK;
       if (fcntl(fileno(serial_out), F_SETFL, i) < 0)
-       perror("Set flags of serial output");
+        perror("Set flags of serial output");
       // switching terminal to noncanonical mode
       if (isatty(fileno(serial_out)))
-       {
-         tcgetattr(fileno(serial_out), &saved_attributes_out);
-         tcgetattr(fileno(serial_out), &tattr);
-         tattr.c_lflag&= ~(ICANON|ECHO);
-         tattr.c_cc[VMIN] = 1;
-         tattr.c_cc[VTIME]= 0;
-         tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);
-       }
+        {
+          tcgetattr(fileno(serial_out), &saved_attributes_out);
+          tcgetattr(fileno(serial_out), &tattr);
+          tattr.c_lflag&= ~(ICANON|ECHO);
+          tattr.c_cc[VMIN] = 1;
+          tattr.c_cc[VTIME]= 0;
+          tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);
+        }
       else
-       fprintf(stderr, "Warning: serial output interface connected to a "
-               "non-terminal file.\n");
+#endif
+        fprintf(stderr, "Warning: serial output interface connected to a "
+                "non-terminal file.\n");
     }
 
   class cl_hw *t2= uc->get_hw(HW_TIMER, 2, 0);
@@ -156,7 +196,7 @@ cl_serial::new_hw_added(class cl_hw *new_hw)
       new_hw->id == 2)
     {
       there_is_t2= DD_TRUE;
-      t_mem d= uc->mem(MEM_SFR)->get(T2CON);
+      t_mem d= sfr->get(T2CON);
       t2_baud= d & (bmRCLK | bmTCLK);
     }
 }
@@ -165,13 +205,13 @@ void
 cl_serial::added_to_uc(void)
 {
   uc->it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,
-                                   "serial transmit", 6));
+                                    "serial transmit", 6));
   uc->it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,
-                                   "serial receive", 6));
+                                    "serial receive", 6));
 }
 
 t_mem
-cl_serial::read(class cl_cell *cell)
+cl_serial::read(class cl_memory_cell *cell)
 {
   if (cell == sbuf)
     return(s_in);
@@ -180,7 +220,7 @@ cl_serial::read(class cl_cell *cell)
 }
 
 void
-cl_serial::write(class cl_cell *cell, t_mem *val)
+cl_serial::write(class cl_memory_cell *cell, t_mem *val)
 {
   if (cell == sbuf)
     {
@@ -196,49 +236,48 @@ cl_serial::write(class cl_cell *cell, t_mem *val)
       _bmREN= *val & bmREN;
       _bits= 8;
       switch (_mode)
-       {
-       case 0:
-         _bits= 8;
-         _divby= 12;
-         break;
-       case 1:
-         _bits= 10;
-         _divby= _bmSMOD?16:32;
-         break;
-       case 2:
-         _bits= 11;
-         _divby= _bmSMOD?16:32;
-         break;
-       case 3:
-         _bits= 11;
-         _divby= _bmSMOD?16:32;
-         break;
-       }
+        {
+        case 0:
+          _bits= 8;
+          _divby= 12;
+          break;
+        case 1:
+          _bits= 10;
+          _divby= _bmSMOD?16:32;
+          break;
+        case 2:
+          _bits= 11;
+          _divby= _bmSMOD?16:32;
+          break;
+        case 3:
+          _bits= 11;
+          _divby= _bmSMOD?16:32;
+          break;
+        }
     }
   else if (cell == pcon)
     {
       _bmSMOD= *val & bmSMOD;
       /*switch (_mode)
-       {
-       case 1:
-         _divby= _bmSMOD?16:32;
-         break;
-       case 2:
-         _divby= _bmSMOD?16:32;
-         break;
-       case 3:
-         _divby= _bmSMOD?16:32;
-         break;
-         }*/
+        {
+        case 1:
+          _divby= _bmSMOD?16:32;
+          break;
+        case 2:
+          _divby= _bmSMOD?16:32;
+          break;
+        case 3:
+          _divby= _bmSMOD?16:32;
+          break;
+          }*/
       if (_mode)
-       _divby= _bmSMOD?16:32;
+        _divby= _bmSMOD?16:32;
     }
 }
 
 /*void
-cl_serial::mem_cell_changed(class cl_mem *mem, t_addr addr)
+cl_serial::mem_cell_changed(class cl_m *mem, t_addr addr)
 {
-  class cl_mem *sfr= uc->mem(MEM_SFR);
   t_mem d;
 
   d= sbuf->get();
@@ -279,19 +318,19 @@ cl_serial::serial_bit_cnt(void)
   if (s_sending)
     {
       while (*tr_src >= _divby)
-       {
-         (*tr_src)-= _divby;
-         s_tr_bit++;
-         //printf("serial bit sent %d\n",uc->ticks->ticks);
-       }
+        {
+          (*tr_src)-= _divby;
+          s_tr_bit++;
+          //printf("serial bit sent %d\n",uc->ticks->ticks);
+        }
     }
   if (s_receiving)
     {
       while (*rec_src >= _divby)
-       {
-         (*rec_src)-= _divby;
-         s_rec_bit++;
-       }
+        {
+          (*rec_src)-= _divby;
+          s_rec_bit++;
+        }
     }
   return(0);
 }
@@ -308,10 +347,10 @@ cl_serial::tick(int cycles)
       s_sending= DD_FALSE;
       scon->set_bit1(bmTI);
       if (serial_out)
-       {
-         putc(s_out, serial_out);
-         fflush(serial_out);
-       }
+        {
+          putc(s_out, serial_out);
+          fflush(serial_out);
+        }
       s_tr_bit-= _bits;
       //printf("serial out %d bit rems %d\n",s_tr_bit,uc->ticks->ticks);
     }
@@ -319,31 +358,33 @@ cl_serial::tick(int cycles)
       serial_in &&
       !s_receiving)
     {
-      fd_set set; static struct timeval timeout= {0,0};
-      FD_ZERO(&set);
-      FD_SET(fileno(serial_in), &set);
-      int i= select(fileno(serial_in)+1, &set, NULL, NULL, &timeout);
-      if (i > 0 &&
-         FD_ISSET(fileno(serial_in), &set))
-       {
-         s_receiving= DD_TRUE;
-         s_rec_bit= 0;
-         s_rec_tick= /*uc51->*/s_rec_t1= 0;
-       }
+#ifdef _WIN32
+      HANDLE handle = (HANDLE)_get_osfhandle(fileno(serial_in));
+      assert(INVALID_HANDLE_VALUE != handle);
+
+      if (input_avail(handle))
+#else
+      if (input_avail(fileno(serial_in)))
+#endif
+        {
+          s_receiving= DD_TRUE;
+          s_rec_bit= 0;
+          s_rec_tick= /*uc51->*/s_rec_t1= 0;
+        }
     }
   if (s_receiving &&
       (s_rec_bit >= _bits))
     {
       if (::read(fileno(serial_in), &c, 1) == 1)
-       {
-         s_in= c;
-         sbuf->set(s_in);
-         received(c);
-       }
+        {
+          s_in= c;
+          sbuf->set(s_in);
+          received(c);
+        }
       s_receiving= DD_FALSE;
       s_rec_bit-= _bits;
     }
-  
+
   int l;
   s_tr_tick+= (l= cycles * uc->clock_per_cycle());
   s_rec_tick+= l;
@@ -377,41 +418,41 @@ cl_serial::happen(class cl_hw *where, enum hw_event he, void *params)
   if (where->cathegory == HW_TIMER)
     {
       if (where->id == 1)
-       {
-         //printf("serial: timer overflowed %ld\n", uc->ticks->ticks);
-         s_rec_t1++;
-         s_tr_t1++;
-       }
+        {
+          //printf("serial: timer overflowed %ld\n", uc->ticks->ticks);
+          s_rec_t1++;
+          s_tr_t1++;
+        }
       if (where->id == 2 /*&& there_is_t2*/)
-       {
-         switch (he)
-           {
-           case EV_T2_MODE_CHANGED:
-             {
-               if (!t2_baud)
-                 s_rec_t1= s_tr_t1= 0;
-               t_mem *d= (t_mem *)params;
-               t2_baud= *d & (bmRCLK | bmTCLK);
-               break;
-             }
-           case EV_OVERFLOW:
-             //printf("T2 \abaud ov r%d t%d\n",s_rec_t1,s_tr_t1);
-             s_rec_t1++;
-             s_tr_t1++;
-             break;
-           default: break;
-           }
-       }
+        {
+          switch (he)
+            {
+            case EV_T2_MODE_CHANGED:
+              {
+                if (!t2_baud)
+                  s_rec_t1= s_tr_t1= 0;
+                t_mem *d= (t_mem *)params;
+                t2_baud= *d & (bmRCLK | bmTCLK);
+                break;
+              }
+            case EV_OVERFLOW:
+              //printf("T2 \abaud ov r%d t%d\n",s_rec_t1,s_tr_t1);
+              s_rec_t1++;
+              s_tr_t1++;
+              break;
+            default: break;
+            }
+        }
     }
 }
 
 void
-cl_serial::print_info(class cl_console *con)
+cl_serial::print_info(class cl_console_base *con)
 {
-  char *modes[]= { "Shift, fixed clock",
-                  "8 bit UART timer clocked",
-                  "9 bit UART fixed clock",
-                  "9 bit UART timer clocked" };
+  const char *modes[]= { "Shift, fixed clock",
+                   "8 bit UART timer clocked",
+                   "9 bit UART fixed clock",
+                   "9 bit UART timer clocked" };
   int sc= scon->get();
 
   con->dd_printf("%s[%d]", id_string, id);
@@ -420,8 +461,8 @@ cl_serial::print_info(class cl_console *con)
   if (mode == 1 || mode == 2)
     con->dd_printf(" (timer%d)", (t2_baud)?2:1);
   con->dd_printf(" MultiProc=%s",
-                (mode&2)?((sc&bmSM2)?"ON":"OFF"):"none");
-  con->dd_printf(" irq=%s", (uc->get_mem(MEM_SFR, IE)&bmES)?"en":"dis");
+                 (mode&2)?((sc&bmSM2)?"ON":"OFF"):"none");
+  con->dd_printf(" irq=%s", (sfr->get(IE)&bmES)?"en":"dis");
   con->dd_printf(" prio=%d", uc->it_priority(bmPS));
   con->dd_printf("\n");
 
@@ -436,10 +477,10 @@ cl_serial::print_info(class cl_console *con)
   con->dd_printf(" irq=%c", (sc&bmTI)?'1':'0');
   con->dd_printf("\n");
   /*con->dd_printf("s_rec_t1=%d s_rec_bit=%d s_rec_tick=%d\n",
-                s_rec_t1, s_rec_bit, s_rec_tick);
+                 s_rec_t1, s_rec_bit, s_rec_tick);
   con->dd_printf("s_tr_t1=%d s_tr_bit=%d s_tr_tick=%d\n",
-                s_tr_t1, s_tr_bit, s_tr_tick);
-                con->dd_printf("divby=%d bits=%d\n", _divby, _bits);*/
+                 s_tr_t1, s_tr_bit, s_tr_tick);
+                 con->dd_printf("divby=%d bits=%d\n", _divby, _bits);*/
 }