[ucsim] Update email and file info, fix stm8 flash controller
[sdcc.git] / sdcc / sim / ucsim / src / sims / oisc.src / uart.cc
blobd413adead06cbe46f536086754b1d17615f7510a
1 /*
2 * Simulator of microcontrollers (oisc.src/uart.cc)
4 * Copyright (C) 2024 Drotos Daniel
5 *
6 * To contact author send email to dr.dkdb@gmail.com
8 */
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
25 02111-1307, USA. */
26 /*@1@*/
28 #include <ctype.h>
30 #include "ddconfig.h"
32 // sim
33 #include "argcl.h"
34 #include "itsrccl.h"
36 #include "uartcl.h"
38 cl_uart::cl_uart(class cl_uc *auc, int aid, t_addr abase):
39 cl_serial_hw(auc, aid, "uart")
41 base= abase;
44 cl_uart::~cl_uart(void)
48 int
49 cl_uart::init(void)
51 int i;
53 //set_name("uart");
54 cl_serial_hw::init();
55 cfg_set(serconf_nl, 13);
56 /*
57 for (i= 0; i < dev_size(); i++)
58 regs[i]= register_cell(uc->rom, base+i);
60 map(uc->rom, base);
62 ten= true;
63 ren= true;
64 s_sending= false;
65 s_receiving= false;
67 show_readable(false);
68 show_writable(true);
70 cl_var *v;
71 chars pn= chars("", "uart%d_", id);
72 uc->vars->add(v= new cl_var(pn+"base", cfg, uart_cfg_base, cfg_help(uart_cfg_base)));
73 v->init();
75 return(0);
78 const char *
79 cl_uart::cfg_help(t_addr addr)
81 switch (addr)
83 case uart_cfg_base:
84 return "Base address of UART registers (int, RW)";
85 /* case acia_cfg_cr:
86 return "Copy of written CR value";
87 case acia_cfg_sr:
88 return "Simulated SR value";
89 case acia_cfg_req:
90 return "Req mode of ACIA 'i'=IRQ 'f'=FIRQ 'n'=NMI";*/
92 return cl_serial_hw::cfg_help(addr);
95 t_mem
96 cl_uart::read(class cl_memory_cell *cell)
98 if (cell == regs[rdr])
100 cfg_set(serconf_able_receive, 1);
101 show_readable(false);
102 return s_in;
104 /*if (cell == regs[stat])
105 return r_sr->read();*/
106 conf(cell, NULL);
107 return cell->get();
110 void
111 cl_uart::write(class cl_memory_cell *cell, t_mem *val)
113 if (conf(cell, val))
114 return;
115 if (cell == regs[rstat])
117 *val= regs[rstat]->get();
119 if (cell == regs[tstat])
121 *val= regs[tstat]->get();
123 else
125 cell->set(*val);
126 if (cell == regs[tdr])
128 s_txd= *val & 0xff;
129 s_tx_written= true;
130 show_writable(false);
131 if (!s_sending)
133 start_send();
140 t_mem
141 cl_uart::conf_op(cl_memory_cell *cell, t_addr addr, t_mem *val)
143 if (addr < serconf_nr)
144 return cl_serial_hw::conf_op(cell, addr, val);
145 switch ((enum uart_cfg)addr)
147 case uart_cfg_base:
148 if (val)
150 int i;
151 if (uc->rom->valid_address(*val))
154 for (i= 0; i < dev_size(); i++)
155 unregister_cell(regs[i]);
156 base= *val;
157 init();
159 map(uc->rom, (*val)&0xffff);
162 else
164 cell->set(base);
166 break;
168 case acia_cfg_req:
169 if (val)
171 //is_r->set_pass_to(*val);
172 //is_t->set_pass_to(*val);
173 is_r->set_parent(uc->search_it_src(*val));
174 is_t->set_parent(uc->search_it_src(*val));
176 break;
179 case acia_cfg_cr: break;
182 case acia_cfg_sr:
183 if (val)
185 cell->set(*val&= 0x7f);
187 break;
189 default:
190 break;
192 return cell->get();
195 bool
196 cl_uart::set_cmd(class cl_cmdline *cmdline,
197 class cl_console_base *con)
199 class cl_cmd_arg *params[2]= {
200 cmdline->param(0),
201 cmdline->param(1)
204 if (cmdline->syntax_match(uc, NUMBER))
206 int i;
207 t_addr a= params[0]->value.number;
208 if (!uc->rom->valid_address(a))
210 con->dd_printf("Address must be between 0x%x and 0x%x\n",
211 AU(uc->rom->lowest_valid_address()),
212 AU(uc->rom->highest_valid_address()));
213 return true;
216 for (i= 0; i < dev_size(); i++)
217 unregister_cell(regs[i]);
218 base= a;
219 init();
221 map(uc->rom, a);
222 return true; // handled
224 return cl_serial_hw::set_cmd(cmdline, con);
227 void
228 cl_uart::set_help(class cl_console_base *con)
230 con->dd_printf("set hardware uart[%d] address\n", id);
231 cl_serial_hw::set_help(con);
235 cl_uart::tick(int cycles)
237 char c;
239 if (!on)
240 return 0;
242 if (!prediv_bitcnt(cycles))
243 return 0;
245 if (s_sending &&
246 (s_tr_bit >= bits))
248 cl_f *fo= io->get_fout();
249 if ((fo == NULL) || (fo->writable()))
251 s_sending= false;
252 io->write((char*)&s_out, 1);
253 s_tr_bit-= 8;
254 if (s_tx_written)
255 restart_send();
256 else
257 finish_send();
260 if (/*(ren) &&*/
261 //io->get_fin() &&
262 !s_receiving)
264 if (cfg_get(serconf_check_often))
266 if (io->get_fin())
268 if (io->input_avail())
269 io->proc_input(0);
272 if (input_avail)
274 s_receiving= true;
275 s_rec_bit= 0;
277 else
278 show_idle(true);
280 if (s_receiving &&
281 (s_rec_bit >= bits))
284 c= get_input();
285 //input_avail= false;
286 s_in= c;
287 received();
289 s_receiving= false;
290 s_rec_bit-= 8;
293 return(0);
296 void
297 cl_uart::start_send()
299 //if (ten)
301 s_out= s_txd;
302 s_tx_written= false;
303 s_sending= true;
304 s_tr_bit= 0;
305 show_writable(true);
309 void
310 cl_uart::restart_send()
312 //if (ten)
314 s_out= s_txd;
315 s_tx_written= false;
316 s_sending= true;
317 s_tr_bit= 0;
318 show_writable(true);
322 void
323 cl_uart::finish_send()
325 show_writable(true);
326 show_tx_complete(true);
329 void
330 cl_uart::received()
332 set_rdr(s_in);
333 cfg_write(serconf_received, s_in);
334 show_readable(true);
337 void
338 cl_uart::reset(void)
340 show_writable(true);
341 show_readable(false);
342 regs[rcpb]->set(cpb= 217);
343 pick_div();
344 pick_ctrl();
347 void
348 cl_uart::happen(class cl_hw *where, enum hw_event he,
349 void *params)
354 void
355 cl_uart::pick_div()
357 cpb= regs[rcpb]->get();
358 mcnt= 0;
361 void
362 cl_uart::pick_ctrl()
364 //u32_t r= regs[ctrl]->get();
365 //ren= r & 1;
366 //ten= r & 2;
367 s_rec_bit= s_tr_bit= 0;
368 s_receiving= false;
369 s_tx_written= false;
370 bits= 10;
374 void
375 cl_uart::show_writable(bool val)
377 u32_t r= regs[tstat]->get();
378 if (!val)
379 r|= 1;
380 else
381 r&= ~1;
382 regs[tstat]->set(r);
385 void
386 cl_uart::show_readable(bool val)
388 u32_t r= regs[rstat]->get();
389 if (!val)
390 r|= 1;
391 else
392 r&= ~1;
393 regs[rstat]->set(r);
396 void
397 cl_uart::show_tx_complete(bool val)
399 show_writable(val);
402 void
403 cl_uart::show_idle(bool val)
407 void
408 cl_uart::set_rdr(t_mem val)
410 regs[rdr]->set(val);
413 void
414 cl_uart::print_info(class cl_console_base *con)
416 u8_t ru8= regs[rstat]->get();
417 u8_t tu8= regs[tstat]->get();
418 con->dd_printf("%s[%d] at 0x%06x %s\n", id_string, id, base, on?"on ":"off");
419 con->dd_printf("Input: ");
420 class cl_f *fin= io->get_fin(), *fout= io->get_fout();
421 if (fin)
422 con->dd_printf("%30s/%3d ", fin->get_file_name(), fin->file_id);
423 con->dd_printf("Output: ");
424 if (fout)
425 con->dd_printf("%30s/%3d", fout->get_file_name(), fout->file_id);
426 con->dd_printf("\n");
427 con->dd_printf("mcnt=%d\n", mcnt);
428 con->dd_printf("Sending: %s, en, %2d/8 bits\n",
429 s_sending?"yes":"no ",
430 //ten?"en ":"dis",
431 s_tr_bit);
432 con->dd_printf("Receiving: %s, en, %2d/8 bits\n",
433 s_receiving?"yes":"no ",
434 //ren?"en ":"dis",
435 s_rec_bit);
436 //con->dd_printf("CR: ");
437 //con->print_bin(regs[ctrl]->get(), 8);
438 //con->dd_printf(" 0x%02x", regs[ctrl]->get());
439 con->dd_printf("Cpb=%8d bits=8\n", cpb);
440 con->dd_printf("RXSR: ");
441 con->print_bin(ru8, 8);
442 con->dd_printf(" 0x%02x", ru8);
443 con->dd_printf(" TXSR: ");
444 con->print_bin(tu8, 8);
445 con->dd_printf(" 0x%02x", tu8);
446 con->dd_printf(" RXNE=%d TC=%d\n",
447 (ru8&1)?1:0,
448 (tu8&1)?1:0);
449 //print_cfg_info(con);
452 /* End of oisc.src/uart.cc */