2 * Simulator of microcontrollers (serial.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
55 cl_serial::cl_serial(class cl_uc *auc):
56 cl_hw(auc, HW_UART, 0, "uart")
58 serial_in= serial_out= NIL;
61 cl_serial::~cl_serial(void)
63 if (serial_in != serial_out && serial_in)
66 if (isatty(fileno(serial_in)))
67 tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
74 if (isatty(fileno(serial_out)))
75 tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
79 delete serial_in_file_option;
80 delete serial_out_file_option;
91 set_name("mcs51_uart");
92 sfr= uc->address_space(MEM_SFR_ID);
95 //sbuf= sfr->register_hw(SBUF, this, 0);
96 //pcon= sfr->register_hw(PCON, this, 0);
97 //scon= sfr->register_hw(SCON, this, 0);
98 register_cell(sfr, SBUF, &sbuf, wtd_restore_write);
99 register_cell(sfr, PCON, &pcon, wtd_restore_write);
100 register_cell(sfr, SCON, &scon, wtd_restore_write);
103 serial_in_file_option= new cl_optref(this);
104 serial_in_file_option->init();
105 serial_in_file_option->use("serial_in_file");
106 serial_out_file_option= new cl_optref(this);
107 serial_out_file_option->init();
108 serial_out_file_option->use("serial_out_file");
111 /*if ((fni= serial_in_file_option->get_value((char*)0)))
112 serial_in= fopen(fni, "r");
113 if ((fno= serial_out_file_option->get_value((char*)0)))
114 serial_out= fopen(fno, "w");*/
116 //serial_in = (FILE*)application->args->get_parg(0, "Ser_in");
117 //serial_out= (FILE*)application->args->get_parg(0, "Ser_out");
118 serial_in = (FILE*)serial_in_file_option->get_value((void*)0);
119 serial_out= (FILE*)serial_out_file_option->get_value((void*)0);
121 if (serial_in != serial_out && serial_in)
123 // making `serial' unbuffered
124 if (setvbuf(serial_in, NULL, _IONBF, 0))
125 perror("Unbuffer serial input channel");
127 if (CH_SERIAL != get_handle_type((HANDLE)_get_osfhandle(fileno(serial_in))))
128 #elif defined HAVE_TERMIOS_H
129 // setting O_NONBLOCK
130 if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)
131 perror("Get flags of serial input");
133 if (fcntl(fileno(serial_in), F_SETFL, i) < 0)
134 perror("Set flags of serial input");
135 // switching terminal to noncanonical mode
136 if (isatty(fileno(serial_in)))
138 tcgetattr(fileno(serial_in), &saved_attributes_in);
139 tcgetattr(fileno(serial_in), &tattr);
140 tattr.c_lflag&= ~(ICANON|ECHO);
141 tattr.c_cc[VMIN] = 1;
142 tattr.c_cc[VTIME]= 0;
143 tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);
147 fprintf(stderr, "Warning: serial input interface connected to a "
148 "non-terminal file.\n");
152 // making `serial' unbuffered
153 if (setvbuf(serial_out, NULL, _IONBF, 0))
154 perror("Unbuffer serial output channel");
156 if (CH_SERIAL != get_handle_type((HANDLE)_get_osfhandle(fileno(serial_out))))
157 #elif defined HAVE_TERMIOS_H
158 // setting O_NONBLOCK
159 if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)
160 perror("Get flags of serial output");
162 if (fcntl(fileno(serial_out), F_SETFL, i) < 0)
163 perror("Set flags of serial output");
164 // switching terminal to noncanonical mode
165 if (isatty(fileno(serial_out)))
167 tcgetattr(fileno(serial_out), &saved_attributes_out);
168 tcgetattr(fileno(serial_out), &tattr);
169 tattr.c_lflag&= ~(ICANON|ECHO);
170 tattr.c_cc[VMIN] = 1;
171 tattr.c_cc[VTIME]= 0;
172 tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);
176 fprintf(stderr, "Warning: serial output interface connected to a "
177 "non-terminal file.\n");
180 class cl_hw *t2= uc->get_hw(HW_TIMER, 2, 0);
181 if ((there_is_t2= t2 != 0))
183 t_mem d= sfr->get(T2CON);
184 t2_baud= d & (bmRCLK | bmTCLK);
193 cl_serial::new_hw_added(class cl_hw *new_hw)
195 if (new_hw->cathegory == HW_TIMER &&
198 there_is_t2= DD_TRUE;
199 t_mem d= sfr->get(T2CON);
200 t2_baud= d & (bmRCLK | bmTCLK);
205 cl_serial::added_to_uc(void)
207 uc->it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,
208 "serial transmit", 6));
209 uc->it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,
210 "serial receive", 6));
214 cl_serial::read(class cl_memory_cell *cell)
223 cl_serial::write(class cl_memory_cell *cell, t_mem *val)
236 _bmREN= *val & bmREN;
246 _divby= _bmSMOD?16:32;
250 _divby= _bmSMOD?16:32;
254 _divby= _bmSMOD?16:32;
258 else if (cell == pcon)
260 _bmSMOD= *val & bmSMOD;
264 _divby= _bmSMOD?16:32;
267 _divby= _bmSMOD?16:32;
270 _divby= _bmSMOD?16:32;
274 _divby= _bmSMOD?16:32;
279 cl_serial::mem_cell_changed(class cl_m *mem, t_addr addr)
292 cl_serial::serial_bit_cnt(void)
295 int *tr_src= 0, *rec_src= 0;
302 rec_src= &s_rec_tick;
306 //divby = (/*pcon->get()&bmSMOD*/_bmSMOD)?16:32;
311 //divby = (/*pcon->get()&bmSMOD*/_bmSMOD)?16:32;
313 rec_src= &s_rec_tick;
320 while (*tr_src >= _divby)
324 //printf("serial bit sent %d\n",uc->ticks->ticks);
329 while (*rec_src >= _divby)
339 cl_serial::tick(int cycles)
343 serial_bit_cnt(/*_mode*/);
348 scon->set_bit1(bmTI);
351 putc(s_out, serial_out);
355 //printf("serial out %d bit rems %d\n",s_tr_bit,uc->ticks->ticks);
357 if ((/*scn & bmREN*/_bmREN) &&
362 HANDLE handle = (HANDLE)_get_osfhandle(fileno(serial_in));
363 assert(INVALID_HANDLE_VALUE != handle);
365 if (input_avail(handle))
367 if (input_avail(fileno(serial_in)))
370 s_receiving= DD_TRUE;
372 s_rec_tick= /*uc51->*/s_rec_t1= 0;
376 (s_rec_bit >= _bits))
378 if (::read(fileno(serial_in), &c, 1) == 1)
384 s_receiving= DD_FALSE;
389 s_tr_tick+= (l= cycles * uc->clock_per_cycle());
395 cl_serial::received(int c)
397 scon->set_bit1(bmRI);
401 cl_serial::reset(void)
409 s_sending = DD_FALSE;
410 s_receiving= DD_FALSE;
416 cl_serial::happen(class cl_hw *where, enum hw_event he, void *params)
418 if (where->cathegory == HW_TIMER)
422 //printf("serial: timer overflowed %ld\n", uc->ticks->ticks);
426 if (where->id == 2 /*&& there_is_t2*/)
430 case EV_T2_MODE_CHANGED:
433 s_rec_t1= s_tr_t1= 0;
434 t_mem *d= (t_mem *)params;
435 t2_baud= *d & (bmRCLK | bmTCLK);
439 //printf("T2
\abaud ov r%d t%d\n",s_rec_t1,s_tr_t1);
450 cl_serial::print_info(class cl_console_base *con)
452 const char *modes[]= { "Shift, fixed clock",
453 "8 bit UART timer clocked",
454 "9 bit UART fixed clock",
455 "9 bit UART timer clocked" };
458 con->dd_printf("%s[%d]", id_string, id);
459 int mode= (sc&(bmSM0|bmSM1))>>6;
460 con->dd_printf(" %s", modes[mode]);
461 if (mode == 1 || mode == 2)
462 con->dd_printf(" (timer%d)", (t2_baud)?2:1);
463 con->dd_printf(" MultiProc=%s",
464 (mode&2)?((sc&bmSM2)?"ON":"OFF"):"none");
465 con->dd_printf(" irq=%s", (sfr->get(IE)&bmES)?"en":"dis");
466 con->dd_printf(" prio=%d", uc->it_priority(bmPS));
467 con->dd_printf("\n");
469 con->dd_printf("Receiver");
470 con->dd_printf(" %s", (sc&bmREN)?"ON":"OFF");
471 con->dd_printf(" RB8=%c", (sc&bmRB8)?'1':'0');
472 con->dd_printf(" irq=%c", (sc&bmRI)?'1':'0');
473 con->dd_printf("\n");
475 con->dd_printf("Transmitter");
476 con->dd_printf(" TB8=%c", (sc&bmTB8)?'1':'0');
477 con->dd_printf(" irq=%c", (sc&bmTI)?'1':'0');
478 con->dd_printf("\n");
479 /*con->dd_printf("s_rec_t1=%d s_rec_bit=%d s_rec_tick=%d\n",
480 s_rec_t1, s_rec_bit, s_rec_tick);
481 con->dd_printf("s_tr_t1=%d s_tr_bit=%d s_tr_tick=%d\n",
482 s_tr_t1, s_tr_bit, s_tr_tick);
483 con->dd_printf("divby=%d bits=%d\n", _divby, _bits);*/
487 /* End of s51.src/serial.cc */