summaryrefslogtreecommitdiff
path: root/sim/ucsim/s51.src/pca.cc
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/s51.src/pca.cc
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'sim/ucsim/s51.src/pca.cc')
-rw-r--r--sim/ucsim/s51.src/pca.cc365
1 files changed, 365 insertions, 0 deletions
diff --git a/sim/ucsim/s51.src/pca.cc b/sim/ucsim/s51.src/pca.cc
new file mode 100644
index 0000000..2aa8899
--- /dev/null
+++ b/sim/ucsim/s51.src/pca.cc
@@ -0,0 +1,365 @@
+/*
+ * Simulator of microcontrollers (pca.cc)
+ *
+ * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
+ *
+ * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
+ *
+ */
+
+/* This file is part of microcontroller simulator: ucsim.
+
+UCSIM is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+UCSIM is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with UCSIM; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+/*@1@*/
+
+#include <ctype.h>
+
+// sim.src
+#include "itsrccl.h"
+
+// local
+#include "pcacl.h"
+#include "regs51.h"
+#include "types51.h"
+
+
+cl_pca::cl_pca(class cl_uc *auc, int aid):
+ cl_hw(auc, HW_PCA, aid, "pca")
+{
+ t0_overflows= ECI_edge= 0;
+ int i;
+ for (i= 0; i < 5; cex_pos[i]= cex_neg[i]= false, i++) ;
+}
+
+int
+cl_pca::init(void)
+{
+ cl_hw::init();
+ sfr= uc->address_space(MEM_SFR_ID);
+ //t_addr CCAPL[5]= {CCAPL[0], CCAPL[1], CCAPL[2], CCAPL[3], CCAPL[4]};
+ //t_addr CCAPH[5]= {CCAPH[0], CCAPH[1], CCAPH[2], CCAPH[3], CCAPH[4]};
+ //t_addr CCAPM[5]= {CCAPM[0], CCAPM[1], CCAPM[2], CCAPM[3], CCAPM[4]};
+ t_addr CCAPL[5]= {CCAP0L, CCAP1L, CCAP2L, CCAP3L, CCAP4L};
+ t_addr CCAPH[5]= {CCAP0H, CCAP1H, CCAP2H, CCAP3H, CCAP4H};
+ t_addr CCAPM[5]= {CCAPM0, CCAPM1, CCAPM2, CCAPM3, CCAPM4};
+ int i;
+
+ if (!sfr)
+ {
+ fprintf(stderr, "No SFR to register PCA[%d] into\n", id);
+ }
+ cell_cmod= register_cell(sfr, CMOD);
+ cell_ccon= register_cell(sfr, CCON);
+ for (i= 0; i < 5; i++)
+ {
+ cell_ccapl[i]= sfr->get_cell(CCAPL[i]);//use_cell(sfr, CCAPL[i]);
+ cell_ccaph[i]= sfr->get_cell(CCAPH[i]);//use_cell(sfr, CCAPH[i]);
+ cell_ccapm[i]= register_cell(sfr, CCAPM[i]);
+ }
+ cell_cl= sfr->get_cell(CL);//use_cell(sfr, CL);
+ cell_ch= sfr->get_cell(CH);//use_cell(sfr, CH);
+ cl_address_space *bas= uc->address_space("bits");
+ cell_cr= register_cell(bas, 0xda);
+ return(0);
+}
+
+void
+cl_pca::added_to_uc(void)
+{
+ class cl_address_space *sfr= uc->address_space(MEM_SFR_ID);
+ class cl_it_src *is;
+
+ uc->it_sources->add_at(4, is= new cl_it_src(uc, bmEC,
+ sfr->get_cell(IE), bmEC,
+ sfr->get_cell(CCON), bmCCF4,
+ 0x0033, false, false,
+ "PCA module #4", 5));
+ is->init();
+ uc->it_sources->add_at(4, is= new cl_it_src(uc, bmEC,
+ sfr->get_cell(IE), bmEC,
+ sfr->get_cell(CCON), bmCCF3,
+ 0x0033, false, false,
+ "PCA module #3", 5));
+ is->init();
+ uc->it_sources->add_at(4, is= new cl_it_src(uc, bmEC,
+ sfr->get_cell(IE), bmEC,
+ sfr->get_cell(CCON), bmCCF2,
+ 0x0033, false, false,
+ "PCA module #2", 5));
+ is->init();
+ uc->it_sources->add_at(4, is= new cl_it_src(uc, bmEC,
+ sfr->get_cell(IE), bmEC,
+ sfr->get_cell(CCON), bmCCF1,
+ 0x0033, false, false,
+ "PCA module #1", 5));
+ is->init();
+ uc->it_sources->add_at(4, is= new cl_it_src(uc, bmEC,
+ sfr->get_cell(IE), bmEC,
+ sfr->get_cell(CCON), bmCCF0,
+ 0x0033, false, false,
+ "PCA module #0", 5));
+ is->init();
+ uc->it_sources->add_at(4, is= new cl_it_src(uc, bmEC,
+ sfr->get_cell(IE), bmEC,
+ sfr->get_cell(CCON), bmCF,
+ 0x0033, false, false,
+ "PCA counter", 5));
+ is->init();
+}
+
+void
+cl_pca::write(class cl_memory_cell *cell, t_mem *val)
+{
+ //uchar bmCEX[5]= {bmCEX0, bmCEX1, bmCEX2, bmCEX3, bmCEX4};
+ //uchar bmCCF[5]= {bmCCF0, bmCCF1, bmCCF2, bmCCF3, bmCCF4};
+
+ if (cell == cell_cmod)
+ {
+ bit_CIDL= *val & bmCIDL;
+ bit_WDTE= *val & bmWDTE;
+ bit_ECF = *val & bmECF;
+ t_mem o= clk_source;
+ if ((clk_source= *val & (bmCPS1|bmCPS0)) != o)
+ t0_overflows= ECI_edge= 0;
+ }
+ else if (cell == cell_ccon)
+ {
+ bit_CR= *val & bmCR;
+ }
+ else if (cell == cell_cr)
+ {
+ bit_CR= *val;
+ }
+ else
+ {
+ int i;
+ for (i= 0; i < 5; i++)
+ {
+ if (cell == cell_ccapm[i])
+ {
+ t_mem o= ccapm[i];
+ ccapm[i]= *val & 0xff;
+ if (o != ccapm[i])
+ cex_neg[i]= cex_pos[i]= false;
+ }
+ else
+ {
+ if (ccapm[i] & (bmMAT|bmTOG))
+ {
+ if (cell == cell_ccapl[i])
+ {
+ cell_ccapm[i]->set_bit0(bmECOM);
+ ccapm[i]= cell_ccapm[i]->get();
+ }
+ else if (cell == cell_ccaph[i])
+ {
+ cell_ccapm[i]->set_bit1(bmECOM);
+ ccapm[i]= cell_ccapm[i]->get();
+ }
+ }
+ }
+ }
+ }
+}
+
+/*void
+cl_pca::mem_cell_changed(class cl_m *mem, t_addr addr)
+{
+ class cl_m *sfr= uc->mem(MEM_SFR);
+
+ if (mem && sfr && mem == sfr)
+ {
+ if (addr == addr_ccapXl)
+ ccapXl= sfr->get_cell(addr_ccapXl);
+ else if (addr == addr_ccapXh)
+ ccapXh= sfr->get_cell(addr_ccapXh);
+ else if (addr == addr_ccapmX)
+ ccapmX= sfr->get_cell(addr_ccapmX);
+ }
+}*/
+
+int
+cl_pca::tick(int cycles)
+{
+ int ret= resGO;
+
+ if (!bit_CR)
+ return(resGO);
+ if (uc->state == stIDLE &&
+ bit_CIDL)
+ return(resGO);
+
+ switch (clk_source)
+ {
+ case 0:
+ do_pca_counter(cycles);
+ break;
+ case bmCPS0:
+ do_pca_counter(cycles*3);
+ break;
+ case bmCPS1:
+ do_pca_counter(t0_overflows);
+ t0_overflows= 0;
+ break;
+ case (bmCPS0|bmCPS1):
+ do_pca_counter(ECI_edge);
+ ECI_edge= 0;
+ break;
+ }
+ return(ret);
+}
+
+void
+cl_pca::do_pca_counter(int cycles)
+{
+ //class cl_m *sfr= uc->mem(MEM_SFR);
+
+ while (cycles--)
+ {
+ if (cell_cl->add(1) == 0)
+ {
+ int i;
+ for (i= 0; i < 5; i++)
+ if (ccapm[i] & bmPWM)
+ cell_ccapl[i]->set(cell_ccaph[i]->get());
+ if (cell_ch->add(1) == 0)
+ {
+ // CH,CL overflow
+ cell_ccon->set_bit1(bmCF);
+ do_pca_module(0);
+ do_pca_module(1);
+ do_pca_module(2);
+ do_pca_module(3);
+ do_pca_module(4);
+ }
+ }
+ }
+}
+
+void
+cl_pca::do_pca_module(int nr)
+{
+ uchar bmCEX[5]= {bmCEX0, bmCEX1, bmCEX2, bmCEX3, bmCEX4};
+ uchar bmCCF[5]= {bmCCF0, bmCCF1, bmCCF2, bmCCF3, bmCCF4};
+ //uint p1= sfr->get(P1);
+
+ bool capture= false;
+ if ((ccapm[nr] & bmCAPP) &&
+ cex_pos[nr])
+ {
+ capture= true;
+ cex_pos[nr]= false;
+ }
+ if ((ccapm[nr] & bmCAPN) &&
+ cex_neg[nr])
+ {
+ capture= true;
+ cex_pos[nr]= false;
+ }
+ if (capture)
+ {
+ // Capture
+ cell_ccapl[nr]->set(cell_cl->get());
+ cell_ccaph[nr]->set(cell_ch->get());
+ cell_ccon->set_bit1(bmCCF[nr]);
+ }
+
+ if (ccapm[nr] & bmECOM)
+ {
+ // Comparator enabled
+ if (cell_cl->get() == cell_ccapl[nr]->get() &&
+ cell_ch->get() == cell_ccaph[nr]->get())
+ {
+ // Match
+ if (nr == 4 &&
+ (bit_WDTE))
+ {
+ reset();
+ return;
+ }
+ cell_ccon->set_bit1(bmCCF[nr]);
+ if (ccapm[nr] & bmTOG)
+ {
+ // Toggle
+ sfr->set(P1, sfr->get(P1) ^ bmCEX[nr]);
+ }
+ }
+ if (ccapm[nr] & bmPWM)
+ {
+ // PWM
+ /*if (cell_cl->get() == 0)
+ cell_ccapl[nr]->set(cell_ccaph[nr]->get());*/
+ if (cell_cl->get() < cell_ccapl[nr]->get())
+ //sfr->set(P1, sfr->get(P1) & ~(bmCEX[nr]));
+ sfr->set_bit1(P1, bmCEX[nr]);
+ else
+ sfr->set_bit1(P1, bmCEX[nr]);
+ }
+ }
+}
+
+void
+cl_pca::reset(void)
+{
+ t0_overflows= ECI_edge= 0;
+ int i;
+ for (i= 0; i < 5; cex_pos[i]= cex_neg[i]= false, i++) ;
+}
+
+void
+cl_pca::happen(class cl_hw *where, enum hw_event he, void *params)
+{
+ struct ev_port_changed *ep= (struct ev_port_changed *)params;
+ uchar bmCEX[5]= {bmCEX0, bmCEX1, bmCEX2, bmCEX3, bmCEX4};
+
+ 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 & bmECI) &&
+ (p1o & bmECI))
+ ECI_edge++;
+ int i;
+ for (i= 0; i < 5; i++)
+ {
+ if (!(p1n & bmCEX[i]) &&
+ (p1o & bmCEX[i]))
+ cex_neg[i]= true;
+ else if ((p1n & bmCEX[i]) &&
+ !(p1o & bmCEX[i]))
+ cex_pos[i]= true;
+ }
+ }
+ else if (where->cathegory == HW_TIMER &&
+ he == EV_OVERFLOW &&
+ where->id == 0)
+ {
+ t0_overflows++;
+ }
+}
+
+
+void
+cl_pca::print_info(class cl_console_base *con)
+{
+ con->dd_printf("%s[%d] FIXME\n", id_string, id);
+ print_cfg_info(con);
+}
+
+
+/* End of s51.src/pca.cc */