X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=sim%2Fucsim%2Fs51.src%2Ftimer2.cc;h=a238179f93d30bc322524b94e4d50e5bb83328cd;hb=90f4aedaef8a2310573eef905f95c671f84e5cde;hp=2918eebb473496d3ac85efe5ef41aceef3e7d5de;hpb=0ac34444ce2ccdcaa5fe722e2420f96c46224039;p=fw%2Fsdcc diff --git a/sim/ucsim/s51.src/timer2.cc b/sim/ucsim/s51.src/timer2.cc index 2918eebb..a238179f 100644 --- a/sim/ucsim/s51.src/timer2.cc +++ b/sim/ucsim/s51.src/timer2.cc @@ -27,43 +27,392 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "timer2cl.h" #include "regs51.h" +#include "types51.h" -cl_timer2::cl_timer2(class cl_uc *auc): - cl_hw(auc, HW_TIMER, 2, "timer2") -{} +cl_timer2::cl_timer2(class cl_uc *auc, int aid, char *aid_string, + int afeatures): + cl_timer0(auc, /*2*/aid, /*"timer2"*/aid_string) +{ + features= afeatures; + exf2it= 0; + mask_RCLK= bmRCLK; + mask_TCLK= bmTCLK; + mask_CP_RL2= bmCP_RL2; + make_partner(HW_UART, 0); + sfr= uc->address_space(MEM_SFR_ID); + if (features & (t2_down|t2_clock_out)) + { + register_cell(sfr, T2MOD, &cell_t2mod, + wtd_restore_write); + } +} -/*int +int cl_timer2::init(void) { + cl_timer0::init(); + //cell_rcap2l= uc->mem(MEM_SFR)->get_cell(RCAP2L); + //cell_rcap2h= uc->mem(MEM_SFR)->get_cell(RCAP2H); + use_cell(sfr, RCAP2L, &cell_rcap2l, wtd_restore); + use_cell(sfr, RCAP2H, &cell_rcap2h, wtd_restore); + if (sfr) + bit_t2ex= sfr->read(P1) & bmT2EX; return(0); +} + +void +cl_timer2::added_to_uc(void) +{ + uc->it_sources->add(new cl_it_src(bmET2, T2CON, bmTF2, 0x002b, false, + "timer #2 TF2", 7)); + exf2it= new cl_it_src(bmET2, T2CON, bmEXF2, 0x002b, false, + "timer #2 EXF2", 7); + uc->it_sources->add(exf2it); +} + +/*void +cl_timer2::mem_cell_changed(class cl_mem *mem, t_addr addr) +{ + class cl_mem *sfr= uc->mem(MEM_SFR); + class cl_cell *c= 0; + + if (mem && sfr && mem == sfr) + { + switch (addr) + { + case T2CON: + c= cell_tcon= sfr->get_cell(T2CON); + break; + } + if (c) + { + t_mem d= c->get(); + write(c, &d); + } + if (addr == addr_tl) + cell_tl= sfr->get_cell(addr_tl); + if (addr == addr_th) + cell_th= sfr->get_cell(addr_th); + cell_rcap2l= sfr->get_cell(RCAP2L); + cell_rcap2h= sfr->get_cell(RCAP2H); + } +}*/ + +/*void +cl_timer2::added(class cl_hw *new_hw) +{ + if (new_hw->cathegory == HW_UART) + hws_to_inform->add(new_hw); }*/ void -cl_timer2::print_info(class cl_console *con) +cl_timer2::write(class cl_memory_cell *cell, t_mem *val) +{ + int oldmode= mode; + bool oldtr= TR; + + if (exf2it) + exf2it->activate(); + if (cell == cell_tcon) + { + C_T = *val & mask_C_T; + TR = *val & mask_TR; + RCLK= *val & mask_RCLK; + TCLK= *val & mask_TCLK; + CP_RL2= *val & mask_CP_RL2; + EXEN2 = *val & bmEXEN2; + if (!(RCLK || TCLK) && + !CP_RL2) + mode= T2MODE_RELOAD; + else if (!(RCLK || TCLK) && + CP_RL2) + mode= T2MODE_CAPTURE; + else if (RCLK || TCLK) + mode= T2MODE_BAUDRATE; + else + mode= T2MODE_OFF; + if (mode != oldmode) + inform_partners(EV_T2_MODE_CHANGED, val); + } + else if (cell == cell_t2mod) + { + bit_dcen= (*val & bmDCEN) != 0; + bit_t2oe= (*val & bmT2OE) != 0; + if ((features & t2_down) && + bit_dcen && + mode == T2MODE_RELOAD) + { + mode= T2MODE_DOWN; + if (exf2it) + exf2it->deactivate(); + } + if ((features & t2_clock_out) && + bit_t2oe) + mode= T2MODE_CLKOUT; + } + if (mode != oldmode || + TR && !oldtr || + !TR && oldtr) + T_edge= t2ex_edge= 0; +} + +int +cl_timer2::tick(int cycles) +{ + switch (mode) + { + case T2MODE_BAUDRATE: + do_t2_baud(cycles); + break; + case T2MODE_CAPTURE: + do_t2_capture(cycles); + break; + case T2MODE_RELOAD: + do_t2_reload(cycles); + break; + case T2MODE_DOWN: + do_t2_down(cycles); + break; + case T2MODE_CLKOUT: + do_t2_clock_out(cycles); + break; + default: break; + } + + return(resGO); +} + +/* + * Baud rate generator mode of Timer #2 + */ + +int +cl_timer2::do_t2_baud(int cycles) +{ + if (EXEN2 && t2ex_edge) + { + cell_tcon->set_bit1(bmEXF2); + t2ex_edge= 0; + } + + if (!TR) + return(0); + + if (C_T) + (cycles= T_edge), T_edge= 0; + else + cycles*= 6; + + while (cycles--) + { + if (!cell_tl->add(1)) + if (!cell_th->add(1)) + { + cell_th->set(cell_rcap2h->get()); + cell_tl->set(cell_rcap2l->get()); + inform_partners(EV_OVERFLOW, 0); + } + } + return(resGO); +} + + +/* + * Capture function of Timer #2 + */ + +void +cl_timer2::do_t2_capture(int cycles) +{ + if (EXEN2 && t2ex_edge) + { + cell_tcon->set_bit1(bmEXF2); + cell_rcap2h->set(cell_th->get()); + cell_rcap2l->set(cell_tl->get()); + t2ex_edge= 0; + } + + if (!TR) + return; + + if (C_T) + (cycles= T_edge), T_edge= 0; + + if (!cell_tl->add(1)) + { + if (!cell_th->add(1)) + cell_tcon->set_bit1(bmTF2); + } +} + + +/* + * Auto Reload mode of Timer #2, counting UP + */ + +void +cl_timer2::do_t2_reload(int cycles) +{ + if (EXEN2 && t2ex_edge) + { + cell_tcon->set_bit1(bmEXF2); + cell_th->set(cell_rcap2h->get()); + cell_tl->set(cell_rcap2l->get()); + t2ex_edge= 0; + } + + if (!TR) + return; + + if (C_T) + (cycles= T_edge), T_edge= 0; + + if (!cell_tl->add(1)) + { + if (!cell_th->add(1)) + { + cell_tcon->set_bit1(mask_TF); + cell_th->set(cell_rcap2h->get()); + cell_tl->set(cell_rcap2l->get()); + } + } +} + +void +cl_timer2::do_t2_down(int cycles) +{ + bool toggle= DD_FALSE; + + if (!TR) + return; + + if (C_T) + (cycles= T_edge), T_edge= 0; + + if (bit_t2ex) + // UP + while (cycles--) + if (!cell_tl->add(1)) + { + if (!cell_th->add(1)) + { + cell_tcon->set_bit1(mask_TF); + cell_th->set(cell_rcap2h->get()); + cell_tl->set(cell_rcap2l->get()); + toggle= DD_TRUE; + } + } + else + // DOWN + while (cycles--) + { + t_mem l, h; + if ((l= cell_tl->add(-1)) == 0xff) + h= cell_th->add(-1); + else + h= cell_th->get(); + if ((TYPE_UWORD)(h*256+l) < + (TYPE_UWORD)(cell_rcap2h->get()*256+cell_rcap2l->get())) + { + cell_tcon->set_bit1(mask_TF); + cell_th->set(0xff); + cell_tl->set(0xff); + toggle= DD_TRUE; + } + } + if (toggle && + sfr) + { + class cl_memory_cell *p1= sfr->get_cell(P1); + if (p1) + p1->set(p1->get() ^ bmEXF2); + } +} + +void +cl_timer2::do_t2_clock_out(int cycles) +{ + if (EXEN2 && t2ex_edge) + { + cell_tcon->set_bit1(bmEXF2); + t2ex_edge= 0; + } + + if (!TR) + return; + + if (C_T) + (cycles= T_edge), T_edge= 0; + else + cycles*= 6; + + while (cycles--) + { + if (!cell_tl->add(1)) + if (!cell_th->add(1)) + { + cell_th->set(cell_rcap2h->get()); + cell_tl->set(cell_rcap2l->get()); + inform_partners(EV_OVERFLOW, 0); + if (!C_T && + sfr) + { + // toggle T2 on P1 + class cl_memory_cell *p1= sfr->get_cell(P1); + if (p1) + p1->set(p1->get() ^ bmT2); + } + } + } +} + +void +cl_timer2::happen(class cl_hw *where, enum hw_event he, void *params) +{ + struct ev_port_changed *ep= (struct ev_port_changed *)params; + + if (where->cathegory == HW_PORT && + he == EV_PORT_CHANGED && + ep->id == 1) + { + t_mem p1n= ep->new_pins & ep->new_value; + t_mem p1o= ep->pins & ep->prev_value; + if (!(p1n & mask_T) && + (p1o & mask_T)) + T_edge++; + if (!(p1n & bmT2EX) && + (p1o & bmT2EX)) + t2ex_edge++; + bit_t2ex= p1n & bmT2EX; + } +} + +void +cl_timer2::print_info(class cl_console_base *con) { - int t2con= uc->get_mem(MEM_SFR, T2CON); + int t2con= cell_tcon->get(); - con->printf("%s[%d] 0x%04x", id_string, id, - 256*uc->get_mem(MEM_SFR, TH2)+uc->get_mem(MEM_SFR, TL2)); - if (t2con & (bmRCLK|bmTCLK)) + con->dd_printf("%s[%d] 0x%04x", id_string, id, + 256*cell_th->get()+cell_tl->get()); + if (RCLK || TCLK) { - con->printf(" baud"); - if (t2con & bmRCLK) - con->printf(" RCLK"); - if (t2con & bmTCLK) - con->printf(" TCLK"); + con->dd_printf(" baud"); + if (RCLK) + con->dd_printf(" RCLK"); + if (TCLK) + con->dd_printf(" TCLK"); } else - con->printf(" %s", (t2con&bmCP_RL2)?"capture":"reload"); - con->printf(" 0x%04x", - 256*uc->get_mem(MEM_SFR, RCAP2H)+uc->get_mem(MEM_SFR, RCAP2L)); - con->printf(" %s", (t2con&bmC_T2)?"counter":"timer"); - con->printf(" %s", (t2con&bmTR2)?"ON":"OFF"); - con->printf(" irq=%c", (t2con&bmTF2)?'1':'0'); - con->printf(" %s", (uc->get_mem(MEM_SFR, IE)&bmET2)?"en":"dis"); - con->printf(" prio=%d", uc->it_priority(bmPT2)); - con->printf("\n"); + con->dd_printf(" %s", (CP_RL2)?"capture":"reload"); + con->dd_printf(" 0x%04x", + 256*cell_rcap2h->get()+cell_rcap2l->get()); + con->dd_printf(" %s", (C_T)?"counter":"timer"); + con->dd_printf(" %s", (TR)?"ON":"OFF"); + con->dd_printf(" irq=%c", (t2con&bmTF2)?'1':'0'); + con->dd_printf(" %s", sfr?"?":((sfr->get(IE)&bmET2)?"en":"dis")); + con->dd_printf(" prio=%d", uc->it_priority(bmPT2)); + con->dd_printf("\n"); }