// license:GPL-2.0+ // copyright-holders:Couriersud /*! * \file nld_NE555.cpp * * \page NE555 NE555: PRECISION TIMERS * * The Swiss army knife for timing purposes * * \section ne555_1 Synopsis * * \snippet devsyn.dox.h NE555 synopsis * \snippet devsyn.dox.h NE555_DIP synopsis * \section ne555_11 "C" Synopsis * * \snippet devsyn.dox.h NE555 csynopsis * \snippet devsyn.dox.h NE555_DIP csynopsis * * For the \c NE555 use verbose pin assignments like \c name.TRIG or \c name.OUT. * For the \c NE555_DIP use pin numbers like \c name.1. * * \section ne555_2 Connection Diagram * *
 *          +--------+
 *      GND |1  ++  8| VCC
 *     TRIG |2      7| DISCH
 *      OUT |3      6| THRES
 *    RESET |4      5| CONT
 *          +--------+
 *  
* * Naming conventions follow Texas Instruments datasheet * * \section ne555_3 Function Table * * Please refer to the datasheet. * * \section ne555_4 Limitations * * Internal resistor network currently fixed to 5k. * * \section ne555_5 Example * \snippet ne555_astable.c ne555 example */ #include "nld_ne555.h" #include "netlist/analog/nlid_twoterm.h" #include "netlist/solver/nld_solver.h" #define R_OFF (1E20) #define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2 namespace netlist { namespace devices { NETLIB_OBJECT(NE555) { NETLIB_CONSTRUCTOR(NE555) , m_R1(*this, "R1") , m_R2(*this, "R2") , m_R3(*this, "R3") , m_ROUT(*this, "ROUT") , m_RDIS(*this, "RDIS") , m_RESET(*this, "RESET") // Pin 4 , m_THRES(*this, "THRESH") // Pin 6 , m_TRIG(*this, "TRIG") // Pin 2 , m_OUT(*this, "_OUT") // to Pin 3 via ROUT , m_last_out(*this, "m_last_out", false) , m_ff(*this, "m_ff", false) , m_last_reset(*this, "m_last_reset", false) { register_subalias("GND", m_R3.m_N); // Pin 1 register_subalias("CONT", m_R1.m_N); // Pin 5 register_subalias("DISCH", m_RDIS.m_P); // Pin 7 register_subalias("VCC", m_R1.m_P); // Pin 8 register_subalias("OUT", m_ROUT.m_P); // Pin 3 connect(m_R1.m_N, m_R2.m_P); connect(m_R2.m_N, m_R3.m_P); connect(m_RDIS.m_N, m_R3.m_N); connect(m_OUT, m_ROUT.m_N); } NETLIB_UPDATEI(); NETLIB_RESETI(); private: analog::NETLIB_SUB(R_base) m_R1; analog::NETLIB_SUB(R_base) m_R2; analog::NETLIB_SUB(R_base) m_R3; analog::NETLIB_SUB(R_base) m_ROUT; analog::NETLIB_SUB(R_base) m_RDIS; logic_input_t m_RESET; analog_input_t m_THRES; analog_input_t m_TRIG; analog_output_t m_OUT; state_var m_last_out; state_var m_ff; state_var m_last_reset; nl_double clamp(const nl_double v, const nl_double a, const nl_double b) { nl_double ret = v; nl_double vcc = m_R1.m_P(); if (ret > vcc - a) ret = vcc - a; if (ret < b) ret = b; return ret; } }; NETLIB_OBJECT_DERIVED(NE555_dip, NE555) { NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555) { register_subalias("1", "GND"); // Pin 1 register_subalias("2", "TRIG"); // Pin 2 register_subalias("3", "OUT"); // Pin 3 register_subalias("4", "RESET"); // Pin 4 register_subalias("5", "CONT"); // Pin 5 register_subalias("6", "THRESH"); // Pin 6 register_subalias("7", "DISCH"); // Pin 7 register_subalias("8", "VCC"); // Pin 8 } }; NETLIB_RESET(NE555) { m_R1.reset(); m_R2.reset(); m_R3.reset(); m_ROUT.reset(); m_RDIS.reset(); /* FIXME make resistances a parameter, properly model other variants */ m_R1.set_R(5000); m_R2.set_R(5000); m_R3.set_R(5000); m_ROUT.set_R(20); m_RDIS.set_R(R_OFF); m_last_out = true; } NETLIB_UPDATE(NE555) { // FIXME: assumes GND is connected to 0V. const auto reset = m_RESET(); if (!reset && m_last_reset) { m_ff = false; } else { const nl_double vt = clamp(m_R2.m_P(), 0.7, 1.4); const bool bthresh = (m_THRES() > vt); const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), 0.7, 1.4)); if (!btrig) m_ff = true; else if (bthresh) m_ff = false; } const bool out = (!reset ? false : m_ff); if (m_last_out && !out) { m_RDIS.update(); m_OUT.push(m_R3.m_N()); m_RDIS.set_R(R_ON); } else if (!m_last_out && out) { m_RDIS.update(); // FIXME: Should be delayed by 100ns m_OUT.push(m_R1.m_P()); m_RDIS.set_R(R_OFF); } m_last_reset = reset; m_last_out = out; } NETLIB_DEVICE_IMPL(NE555, "NE555", "") NETLIB_DEVICE_IMPL(NE555_dip, "NE555_DIP", "") NETLIB_DEVICE_IMPL_ALIAS(MC1455P, NE555, "MC1455P", "") NETLIB_DEVICE_IMPL_ALIAS(MC1455P_dip, NE555_dip, "MC1455P_DIP", "") } //namespace devices } // namespace netlist