mirror of
https://github.com/libretro/mame2016-libretro.git
synced 2024-11-27 10:40:47 +00:00
Analog input updates now send to queue. Reduces risk of stack overflows.
Fixed a bug which caused NAND astable multivibrator to oscillate. 74123 improvements
This commit is contained in:
parent
beb96a628d
commit
fa60c8874d
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -368,6 +368,7 @@ nl_examples/74123_mstable.c svneol=native#text/plain
|
||||
nl_examples/bjt.c svneol=native#text/plain
|
||||
nl_examples/bjt_eb.c svneol=native#text/plain
|
||||
nl_examples/bjt_eb_pnp.c svneol=native#text/plain
|
||||
nl_examples/breakout.c svneol=native#text/plain
|
||||
nl_examples/cd4066.c svneol=native#text/plain
|
||||
nl_examples/msx_mixer_stage.c svneol=native#text/plain
|
||||
nl_examples/ne555_astable.c svneol=native#text/plain
|
||||
|
@ -20,10 +20,10 @@ NETLIST_START(74123_mstable)
|
||||
|
||||
/* Wiring up the 74123 */
|
||||
|
||||
CLOCK(clk, 500)
|
||||
CLOCK(clk, 50)
|
||||
TTL_74123(mf)
|
||||
|
||||
RES(R, 1000)
|
||||
RES(R, 10000)
|
||||
CAP(C, 1e-6)
|
||||
|
||||
NET_C(GND, mf.GND)
|
||||
@ -38,8 +38,8 @@ NETLIST_START(74123_mstable)
|
||||
NET_C(mf.B, V5)
|
||||
NET_C(mf.A, clk.Q)
|
||||
|
||||
//LOG(logC, C.2)
|
||||
//LOG(logQ, mf.Q)
|
||||
//LOG(logX, clk.Q)
|
||||
LOG(logC, C.2)
|
||||
LOG(logQ, mf.Q)
|
||||
LOG(logX, clk.Q)
|
||||
|
||||
NETLIST_END()
|
||||
|
1460
nl_examples/breakout.c
Normal file
1460
nl_examples/breakout.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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,9 +79,23 @@ 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 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);
|
||||
m_inps.add(p)
|
||||
#endif
|
||||
NL_VERBOSE_OUT(("Added input\n"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
owner().netlist().error("unhandled element found\n");
|
||||
@ -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);
|
||||
{
|
||||
// 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,10 +873,11 @@ 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()));
|
||||
|
||||
ms->setup(groups[i], *this);
|
||||
|
||||
m_mat_solvers.add(ms);
|
||||
|
||||
netlist().log("Solver %s", ms->name().cstr());
|
||||
|
@ -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<netlist_matrix_solver_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<netlist_analog_output_t *> m_inps;
|
||||
#else
|
||||
netlist_core_terminal_t::list_t m_inps;
|
||||
#endif
|
||||
dev_list_t m_steps;
|
||||
netlist_time m_last_step;
|
||||
|
||||
|
@ -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
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* nld_74123.h
|
||||
*
|
||||
* 74123: PRECISION TIMERS
|
||||
* 74123: Dual Retriggerable One-Shot with Clear and Complementary Outputs
|
||||
*
|
||||
* +--------------+
|
||||
* A1 |1 ++ 16| VCC
|
||||
@ -45,6 +45,10 @@ public:
|
||||
|
||||
netlist_sig_t m_last_trig;
|
||||
UINT8 m_state;
|
||||
double m_KP;
|
||||
|
||||
netlist_param_double_t m_K;
|
||||
netlist_param_double_t m_RI;
|
||||
|
||||
);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user