+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);
+ }
+}
+