diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/s51.src/pca.cc | |
| download | sdcc-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.cc | 365 |
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 */ |
