X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=sim%2Fucsim%2Fs51.src%2Ftimer0.cc;h=fddf0c8242c3c2c9a024a8dc4cac92561d9581d7;hb=8c8f34ff4281a55d2f535335c02999246e9e12f2;hp=56f326cb72bec6a04e8c1d6029611ae10673393d;hpb=80b2a5b23482ecbc28c3f70566ecafa524169016;p=fw%2Fsdcc diff --git a/sim/ucsim/s51.src/timer0.cc b/sim/ucsim/s51.src/timer0.cc index 56f326cb..fddf0c82 100644 --- a/sim/ucsim/s51.src/timer0.cc +++ b/sim/ucsim/s51.src/timer0.cc @@ -27,39 +27,369 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "timer0cl.h" #include "regs51.h" +#include "types51.h" -cl_timer0::cl_timer0(class cl_uc *auc): - cl_hw(auc, HW_TIMER, 0, "timer0") -{} +cl_timer0::cl_timer0(class cl_uc *auc, int aid, char *aid_string): + cl_hw(auc, HW_TIMER, aid, aid_string) +{ + cell_tmod= cell_tcon= 0; + if (aid == 0) + { + mask_M0 = bmM00; + mask_M1 = bmM10; + mask_C_T = bmC_T0; + mask_GATE= bmGATE0; + mask_TR = bmTR0; + mask_INT = bm_INT0; + mask_TF = bmTF0; + mask_T = bmT0; + addr_tl = TL0; + addr_th = TH0; + } + else if (aid == 1) + { + mask_M0 = bmM01; + mask_M1 = bmM11; + mask_C_T = bmC_T1; + mask_GATE= bmGATE1; + mask_TR = bmTR1; + mask_INT = bm_INT1; + mask_TF = bmTF1; + mask_T = bmT1; + addr_tl = TL1; + addr_th = TH1; + } + else if (aid == 2) + { + addr_tl = TL2; + addr_th = TH2; + mask_T = bmT2; + mask_C_T = bmC_T2; + mask_TR = bmTR2; + mask_TF = bmTF2; + mask_M0= mask_M1= mask_GATE= mask_INT= 0; + } + else {} + make_partner(HW_PCA, 0); + make_partner(HW_PCA, 1); + make_partner(HW_PCA, 2); + make_partner(HW_PCA, 3); + make_partner(HW_PCA, 4); +} -/*int +int cl_timer0::init(void) { + class cl_mem *sfr= uc->mem(MEM_SFR); + + if (sfr) + { + //t_mem d; + if (id == 0 || id == 1) + { + //cell_tmod= sfr->register_hw(TMOD, this, 0); + register_cell(sfr, TMOD, &cell_tmod, wtd_restore_write); + //d= cell_tmod->get(); write(cell_tmod, &d); + //cell_tcon= sfr->register_hw(TCON, this, 0); + register_cell(sfr, TCON, &cell_tcon, wtd_restore_write); + //d= cell_tcon->get(); write(cell_tcon, &d); + INT= sfr->read(P3) & mask_INT; + } + else if (id == 2) + { + cell_tmod= 0; + //cell_tcon= sfr->register_hw(T2CON, this, 0); + register_cell(sfr, T2CON, &cell_tcon, wtd_restore_write); + //d= cell_tcon->get(); write(cell_tcon, &d); + } + //cell_tl= sfr->get_cell(addr_tl); + //cell_th= sfr->get_cell(addr_th); + use_cell(sfr, addr_tl, &cell_tl, wtd_restore); + use_cell(sfr, addr_th, &cell_th, wtd_restore); + } return(0); +} + +void +cl_timer0::added_to_uc(void) +{ + if (id == 0) + uc->it_sources->add(new cl_it_src(bmET0, TCON, bmTF0, 0x000b, true, + "timer #0", 2)); + else if (id == 1) + uc->it_sources->add(new cl_it_src(bmET1, TCON, bmTF1, 0x001b, true, + "timer #1", 4)); +} + +/*t_mem +cl_timer0::read(class cl_cell *cell) +{ + return(cell->get()); }*/ +void +cl_timer0::write(class cl_cell *cell, t_mem *val) +{ + if (cell == cell_tmod) + { + t_mem md= *val & (mask_M0|mask_M1); + if (md == mask_M0) + mode= 1; + else if (md == mask_M1) + mode= 2; + else if (md == (mask_M0|mask_M1)) + mode= 3; + else + mode= 0; + GATE= *val & mask_GATE; + C_T = *val & mask_C_T; + T_edge= 0; + } + else if (cell == cell_tcon) + { + TR= *val & mask_TR; + T_edge= 0; + } +} + +/*void +cl_timer0::mem_cell_changed(class cl_mem *mem, t_addr addr) +{ + //class cl_mem *sfr= uc->mem(MEM_SFR); + //t_mem d; + + cl_hw::mem_cell_changed(mem, addr); + + //d= cell_tmod->get(); + //write(cell_tmod, &d); + //d= cell_tcon->get(); + //write(cell_tcon, &d); + //if (addr == addr_tl) cell_tl= sfr->get_cell(addr_tl); + //if (addr == addr_th) cell_th= sfr->get_cell(addr_th); +}*/ + +int +cl_timer0::tick(int cycles) +{ + switch (mode) + { + case 0: do_mode0(cycles); break; + case 1: do_mode1(cycles); break; + case 2: do_mode2(cycles); break; + case 3: do_mode3(cycles); break; + } + return(resGO); +} + +int +cl_timer0::do_mode0(int cycles) +{ + if (!TR) + return(0); + + //t_mem p3= uc->mem(MEM_SFR)->get(P3); + if (GATE) + { + if ((/*p3 & mask_*/INT) == 0) + return(0); + } + + if (C_T) + { + /*cycles= 0; + if ((uc51->prev_p3 & mask_T) && + !(p3 & uc51->port_pins[3] & mask_T)) + cycles= 1;*/ + cycles= T_edge; + T_edge= 0; + } + while (cycles--) + { + // mod 0, TH= 8 bit t/c, TL= 5 bit precounter + t_mem tl= cell_tl->add(1); + if ((tl & 0x1f) == 0) + { + cell_tl->set(0); + if (!cell_th->add(1)) + { + cell_tcon->set_bit1(mask_TF); + overflow(); + } + } + } + + return(0); +} + +int +cl_timer0::do_mode1(int cycles) +{ + if (!TR) + return(0); + + //t_mem p3= uc->mem(MEM_SFR)->get(P3); + if (GATE) + { + if ((/*p3 & mask_*/INT) == 0) + return(0); + } + + if (C_T) + { + /*cycles= 0; + if ((uc51->prev_p3 & mask_T) && + !(p3 & uc51->port_pins[3] & mask_T)) + cycles= 1;*/ + cycles= T_edge; + T_edge= 0; + } + + while (cycles--) + { + // mod 1 TH+TL= 16 bit t/c + if (!cell_tl->add(1)) + { + if (!cell_th->add(1)) + { + cell_tcon->set_bit1(mask_TF); + overflow(); + } + } + } + + return(0); +} + +int +cl_timer0::do_mode2(int cycles) +{ + if (!TR) + return(0); + + //t_mem p3= uc->mem(MEM_SFR)->get(P3); + if (GATE) + { + if ((/*p3 & mask_*/INT) == 0) + return(0); + } + + if (C_T) + { + /*cycles= 0; + if ((uc51->prev_p3 & mask_T) && + !(p3 & uc51->port_pins[3] & mask_T)) + cycles= 1;*/ + cycles= T_edge; + T_edge= 0; + } + + //unsigned long startt= uc->ticks->ticks-(cycles*12);int i=0; + while (cycles--) + { + // mod 2 TL= 8 bit t/c auto reload from TH + if (!cell_tl->add(1)) + { + cell_tl->set(cell_th->get()); + cell_tcon->set_bit1(mask_TF); + //printf("timer%d overflow %d (%d) %d\n",id,uc->ticks->ticks,i,startt+(i*12)); + overflow(); + } + //i++; + } + return(0); +} + +int +cl_timer0::do_mode3(int cycles) +{ + int cyc= cycles; + //t_mem p3= uc->mem(MEM_SFR)->get(P3); + + if (!TR) + goto do_th; + + if (GATE) + { + if ((/*p3 & mask_*/INT) == 0) + goto do_th; + } + + if (C_T) + { + /*cycles= 0; + if ((uc51->prev_p3 & mask_T) && + !(p3 & uc51->port_pins[3] & mask_T)) + cycles= 1;*/ + cycles= T_edge; + T_edge= 0; + } + + while (cycles--) + { + if (!cell_tl->add(1)) + { + cell_tcon->set_bit1(mask_TF); + overflow(); + } + } + + do_th: + if ((cell_tcon->get() & bmTR1) != 0) + while (cyc--) + { + if (!cell_th->add(1)) + cell_tcon->set_bit1(bmTF1); + } + return(0); +} + +void +cl_timer0::overflow(void) +{ + inform_partners(EV_OVERFLOW, 0); +} + +void +cl_timer0::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 == 3) + { + t_mem p3n= ep->new_pins & ep->new_value; + t_mem p3o= ep->pins & ep->prev_value; + if ((p3n & mask_T) && + !(p3o & mask_T)) + T_edge++; + INT= p3n & mask_INT; + //printf("timer%d p%dchanged (%02x,%02x->%02x,%02x) INT=%d(%02x) edge=%d(%02x)\n",id,where->id,ep->prev_value,ep->pins,ep->new_value,ep->new_pins,INT,mask_INT,T_edge,mask_T); + } +} + void cl_timer0::print_info(class cl_console *con) { char *modes[]= { "13 bit", "16 bit", "8 bit autoreload", "2x8 bit" }; - int tmod= uc->get_mem(MEM_SFR, TMOD); + //t_mem tmod= cell_tmod->get(); int on; con->dd_printf("%s[%d] 0x%04x", id_string, id, - 256*uc->get_mem(MEM_SFR, TH0)+uc->get_mem(MEM_SFR, TL0)); - int mode= tmod & (bmM00|bmM10); + 256*cell_th->get()+cell_tl->get()); + //int mode= tmod & (bmM00|bmM10); con->dd_printf(" %s", modes[mode]); - con->dd_printf(" %s", (tmod&bmC_T0)?"counter":"timer"); - if (tmod&bmGATE0) + con->dd_printf(" %s", (/*tmod&bm*/C_T/*0*/)?"counter":"timer"); + if (/*tmod&bm*/GATE/*0*/) { con->dd_printf(" gated"); - on= uc->get_mem(MEM_SFR, P3) & uc->port_pins[3] & bm_INT0; + on= /*uc->get_mem(MEM_SFR, P3) & uc->port_pins[3] & mask_*/INT/*bm_INT0*/; } else - on= uc->get_mem(MEM_SFR, TCON) & bmTR0; + on= TR/*cell_tcon->get(TCON) & mask_TR*/; con->dd_printf(" %s", on?"ON":"OFF"); - con->dd_printf(" irq=%c", (uc->get_mem(MEM_SFR, TCON)&bmTF0)?'1':'0'); + con->dd_printf(" irq=%c", (cell_tcon->get()&mask_TF)?'1':'0'); con->dd_printf(" %s", (uc->get_mem(MEM_SFR, IE)&bmET0)?"en":"dis"); con->dd_printf(" prio=%d", uc->it_priority(bmPT0)); con->dd_printf("\n");