From fa60c8874d6399f0f745378bdf09637b9be49cbc Mon Sep 17 00:00:00 2001 From: Couriersud Date: Thu, 15 May 2014 00:03:27 +0000 Subject: Analog input updates now send to queue. Reduces risk of stack overflows. Fixed a bug which caused NAND astable multivibrator to oscillate. 74123 improvements --- src/emu/netlist/analog/nld_solver.c | 70 +++++++++++++++++++++++++++++-------- src/emu/netlist/analog/nld_solver.h | 10 ++++-- src/emu/netlist/devices/nld_74123.c | 31 ++++++++++++---- src/emu/netlist/devices/nld_74123.h | 8 +++-- src/emu/netlist/nl_base.c | 2 +- src/emu/netlist/nl_base.h | 2 ++ 6 files changed, 98 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/emu/netlist/analog/nld_solver.c b/src/emu/netlist/analog/nld_solver.c index 8248b75ec9c..7ede33a2664 100644 --- a/src/emu/netlist/analog/nld_solver.c +++ b/src/emu/netlist/analog/nld_solver.c @@ -18,6 +18,19 @@ #define SOLVER_VERBOSE_OUT(x) do {} while (0) //#define SOLVER_VERBOSE_OUT(x) printf x +ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t() +: m_owner(NULL) +{ +} + +ATTR_COLD netlist_matrix_solver_t::~netlist_matrix_solver_t() +{ +#if NEW_INPUT + for (int i = 0; i < m_inps.count(); i++) + delete m_inps[i]; +#endif +} + ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &aowner) { m_owner = &aowner; @@ -66,10 +79,24 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLI NL_VERBOSE_OUT(("Added terminal\n")); break; case netlist_terminal_t::INPUT: - if (!m_inps.contains(p)) - m_inps.add(p); - NL_VERBOSE_OUT(("Added input\n")); - break; + { +#if NEW_INPUT + // FIXME: multiple outputs per net ... + netlist_analog_output_t *m = new netlist_analog_output_t(); + m->init_object(*this, this->name() + "." + pstring::sprintf("m%d", m_inps.count())); + //register_output("m", *m); + m_inps.add(m); + m->m_proxied_net = &p->net(); + m->net().register_con(*p); + // FIXME: repeated + m->net().rebuild_list(); +#else + if (!m_inps.contains(p)) + m_inps.add(p) +#endif + NL_VERBOSE_OUT(("Added input\n")); + } + break; default: owner().netlist().error("unhandled element found\n"); break; @@ -81,6 +108,18 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLI ATTR_HOT void netlist_matrix_solver_t::update_inputs() { + +#if NEW_INPUT + // avoid recursive calls. Inputs are updated outside this call + for (netlist_analog_output_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + if ((*p)->m_proxied_net->m_last_Analog != (*p)->m_proxied_net->m_cur_Analog) + (*p)->set_Q((*p)->m_proxied_net->m_cur_Analog); + for (netlist_analog_output_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + { + if ((*p)->m_proxied_net->m_last_Analog != (*p)->m_proxied_net->m_cur_Analog) + (*p)->m_proxied_net->m_last_Analog = (*p)->m_proxied_net->m_cur_Analog; + } +#else for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) { if ((*p)->net().m_last_Analog != (*p)->net().m_cur_Analog) @@ -93,6 +132,7 @@ ATTR_HOT void netlist_matrix_solver_t::update_inputs() if ((*p)->net().m_last_Analog != (*p)->net().m_cur_Analog) (*p)->net().m_last_Analog = (*p)->net().m_cur_Analog; } +#endif } @@ -156,14 +196,15 @@ ATTR_HOT bool netlist_matrix_solver_t::solve() netlist_time now = owner().netlist().time(); netlist_time delta = now - m_last_step; - if (delta < netlist_time::from_nsec(1)) // always update capacitors - delta = netlist_time::from_nsec(1); - { - NL_VERBOSE_OUT(("Step!\n")); - /* update all terminals for new time step */ - m_last_step = now; - step(delta); - } + // We are already up to date. Avoid oscillations. + if (delta < netlist_time::from_nsec(1)) + return true; + + NL_VERBOSE_OUT(("Step!\n")); + /* update all terminals for new time step */ + m_last_step = now; + //printf("usecs: %f\n", delta.as_double()*1000000.0); + step(delta); if (is_dynamic()) { @@ -832,11 +873,12 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start() ms->m_params.m_nr_loops = m_nr_loops.Value(); ms->m_params.m_nt_sync_delay = m_sync_delay.Value(); - ms->setup(groups[i], *this); register_sub(*ms, pstring::sprintf("Solver %d",m_mat_solvers.count())); - m_mat_solvers.add(ms); + ms->setup(groups[i], *this); + + m_mat_solvers.add(ms); netlist().log("Solver %s", ms->name().cstr()); netlist().log(" # %d ==> %d nets %s", i, groups[i].count(), (*(*groups[i].first())->m_core_terms.first())->name().cstr()); diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h index 0a2c1788a46..5d592cbd0f5 100644 --- a/src/emu/netlist/analog/nld_solver.h +++ b/src/emu/netlist/analog/nld_solver.h @@ -9,6 +9,8 @@ #include "../nl_setup.h" #include "../nl_base.h" +#define NEW_INPUT (1) + // ---------------------------------------------------------------------------------------- // Macros // ---------------------------------------------------------------------------------------- @@ -40,8 +42,8 @@ public: typedef netlist_list_t list_t; typedef netlist_core_device_t::list_t dev_list_t; - netlist_matrix_solver_t() : m_owner(NULL) {} - virtual ~netlist_matrix_solver_t() {} + ATTR_COLD netlist_matrix_solver_t(); + ATTR_COLD virtual ~netlist_matrix_solver_t(); ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner); @@ -75,7 +77,11 @@ protected: netlist_net_t::list_t m_nets; dev_list_t m_dynamic; +#if NEW_INPUT + netlist_list_t m_inps; +#else netlist_core_terminal_t::list_t m_inps; +#endif dev_list_t m_steps; netlist_time m_last_step; diff --git a/src/emu/netlist/devices/nld_74123.c b/src/emu/netlist/devices/nld_74123.c index 5a40f51987a..aef93f6ab06 100644 --- a/src/emu/netlist/devices/nld_74123.c +++ b/src/emu/netlist/devices/nld_74123.c @@ -6,7 +6,7 @@ #include "nld_74123.h" #define R_OFF (1E20) -#define R_ON (1) +#define R_ON (m_RI.Value()) NETLIB_START(74123) { @@ -27,20 +27,36 @@ NETLIB_START(74123) register_subalias("C", m_RN.m_N); register_subalias("RC", m_RN.m_P); + register_param("K", m_K, 0.4); + register_param("RI", m_RI, 400.0); // around 250 for HC series, 400 on LS/TTL, estimated from datasheets + connect(m_RN.m_P, m_RP.m_N); connect(m_CV, m_RN.m_P); save(NAME(m_last_trig)); save(NAME(m_state)); + save(NAME(m_KP)); + + m_KP = 1.0 / (1.0 + exp(m_K.Value())); } NETLIB_UPDATE(74123) { - // FIXME: CLR! - const netlist_sig_t m_trig = (INPLOGIC(m_A) ^ 1) & INPLOGIC(m_B) & INPLOGIC(m_CLRQ); - if (!m_last_trig && m_trig) + if (!INPLOGIC(m_CLRQ)) + { + OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(10)); + OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(10)); + /* quick charge until trigger */ + /* FIXME: SGS datasheet shows quick charge to 5V, + * though schematics indicate quick charge to Vhigh only. + */ + m_RP.set_R(R_ON); + m_RN.set_R(R_OFF); + m_state = 2; //charging (quick) + } + else if (!m_last_trig && m_trig) { // FIXME: Timing! OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(10)); @@ -54,7 +70,8 @@ NETLIB_UPDATE(74123) if (m_state == 1) { - if (INPANALOG(m_CV) < 1.3) + const double vLow = m_KP * TERMANALOG(m_RP.m_P); + if (INPANALOG(m_CV) < vLow) { m_RN.set_R(R_OFF); m_state = 2; // charging @@ -62,8 +79,10 @@ NETLIB_UPDATE(74123) } else if (m_state == 2) { - if (INPANALOG(m_CV) > 3.7) + const double vHigh = TERMANALOG(m_RP.m_P) * (1.0 - m_KP); + if (INPANALOG(m_CV) > vHigh) { + m_RP.set_R(R_OFF); OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(10)); OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(10)); m_state = 0; // waiting diff --git a/src/emu/netlist/devices/nld_74123.h b/src/emu/netlist/devices/nld_74123.h index 67a313d9846..6a81b9bac7c 100644 --- a/src/emu/netlist/devices/nld_74123.h +++ b/src/emu/netlist/devices/nld_74123.h @@ -3,7 +3,7 @@ /* * nld_74123.h * - * 74123: PRECISION TIMERS + * 74123: Dual Retriggerable One-Shot with Clear and Complementary Outputs * * +--------------+ * A1 |1 ++ 16| VCC @@ -43,8 +43,12 @@ public: netlist_analog_input_t m_CV; - netlist_sig_t m_last_trig; + netlist_sig_t m_last_trig; UINT8 m_state; + double m_KP; + + netlist_param_double_t m_K; + netlist_param_double_t m_RI; ); diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index a64fb784a9e..b274bde868b 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -841,7 +841,7 @@ ATTR_HOT void netlist_analog_output_t::set_Q(const double newQ) if (newQ != net().m_new_Analog) { net().m_new_Analog = newQ; - net().push_to_queue(NLTIME_FROM_NS(0)); + net().push_to_queue(NLTIME_FROM_NS(1)); } } diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index 1664d98b54e..cd820bf1c27 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -723,6 +723,8 @@ public: ATTR_HOT void set_Q(const double newQ); + netlist_net_t *m_proxied_net; // only for proxy nets in analog input logic + }; // ---------------------------------------------------------------------------------------- -- cgit v1.2.3