2 * Simulator of microcontrollers (oisc.src/uart.cc)
4 * Copyright (C) 2024 Drotos Daniel
6 * To contact author send email to dr.dkdb@gmail.com
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
38 cl_uart::cl_uart(class cl_uc
*auc
, int aid
, t_addr abase
):
39 cl_serial_hw(auc
, aid
, "uart")
44 cl_uart::~cl_uart(void)
55 cfg_set(serconf_nl
, 13);
57 for (i= 0; i < dev_size(); i++)
58 regs[i]= register_cell(uc->rom, base+i);
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
)));
79 cl_uart::cfg_help(t_addr addr
)
84 return "Base address of UART registers (int, RW)";
86 return "Copy of written CR value";
88 return "Simulated SR value";
90 return "Req mode of ACIA 'i'=IRQ 'f'=FIRQ 'n'=NMI";*/
92 return cl_serial_hw::cfg_help(addr
);
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);
104 /*if (cell == regs[stat])
105 return r_sr->read();*/
111 cl_uart::write(class cl_memory_cell
*cell
, t_mem
*val
)
115 if (cell
== regs
[rstat
])
117 *val
= regs
[rstat
]->get();
119 if (cell
== regs
[tstat
])
121 *val
= regs
[tstat
]->get();
126 if (cell
== regs
[tdr
])
130 show_writable(false);
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
)
151 if (uc
->rom
->valid_address(*val
))
154 for (i= 0; i < dev_size(); i++)
155 unregister_cell(regs[i]);
159 map(uc
->rom
, (*val
)&0xffff);
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));
179 case acia_cfg_cr: break;
185 cell->set(*val&= 0x7f);
196 cl_uart::set_cmd(class cl_cmdline
*cmdline
,
197 class cl_console_base
*con
)
199 class cl_cmd_arg
*params
[2]= {
204 if (cmdline
->syntax_match(uc
, NUMBER
))
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()));
216 for (i= 0; i < dev_size(); i++)
217 unregister_cell(regs[i]);
222 return true; // handled
224 return cl_serial_hw::set_cmd(cmdline
, con
);
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
)
242 if (!prediv_bitcnt(cycles
))
248 cl_f
*fo
= io
->get_fout();
249 if ((fo
== NULL
) || (fo
->writable()))
252 io
->write((char*)&s_out
, 1);
264 if (cfg_get(serconf_check_often
))
268 if (io
->input_avail())
285 //input_avail= false;
297 cl_uart::start_send()
310 cl_uart::restart_send()
323 cl_uart::finish_send()
326 show_tx_complete(true);
333 cfg_write(serconf_received
, s_in
);
341 show_readable(false);
342 regs
[rcpb
]->set(cpb
= 217);
348 cl_uart::happen(class cl_hw
*where
, enum hw_event he
,
357 cpb
= regs
[rcpb
]->get();
364 //u32_t r= regs[ctrl]->get();
367 s_rec_bit
= s_tr_bit
= 0;
375 cl_uart::show_writable(bool val
)
377 u32_t r
= regs
[tstat
]->get();
386 cl_uart::show_readable(bool val
)
388 u32_t r
= regs
[rstat
]->get();
397 cl_uart::show_tx_complete(bool val
)
403 cl_uart::show_idle(bool val
)
408 cl_uart::set_rdr(t_mem val
)
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();
422 con
->dd_printf("%30s/%3d ", fin
->get_file_name(), fin
->file_id
);
423 con
->dd_printf("Output: ");
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 ",
432 con
->dd_printf("Receiving: %s, en, %2d/8 bits\n",
433 s_receiving
?"yes":"no ",
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",
449 //print_cfg_info(con);
452 /* End of oisc.src/uart.cc */