1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_NE555.c
*
*/
#include "nld_ne555.h"
#include "analog/nld_twoterm.h"
#include <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_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") // Pin 3
, m_last_out(*this, "m_last_out", false)
, m_ff(*this, "m_ff", 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
connect_late(m_R1.m_N, m_R2.m_P);
connect_late(m_R2.m_N, m_R3.m_P);
connect_late(m_RDIS.m_N, m_R3.m_N);
}
NETLIB_UPDATEI();
NETLIB_RESETI();
protected:
NETLIB_SUB(R) m_R1;
NETLIB_SUB(R) m_R2;
NETLIB_SUB(R) m_R3;
NETLIB_SUB(R) m_RDIS;
logic_input_t m_RESET;
analog_input_t m_THRES;
analog_input_t m_TRIG;
analog_output_t m_OUT;
private:
state_var<bool> m_last_out;
state_var<bool> m_ff;
inline nl_double clamp(const nl_double v, const nl_double a, const nl_double b);
};
NETLIB_OBJECT_DERIVED(NE555_dip, NE555)
{
NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555)
{
register_subalias("1", m_R3.m_N); // Pin 1
register_subalias("2", m_TRIG); // Pin 2
register_subalias("3", m_OUT); // Pin 3
register_subalias("4", m_RESET); // Pin 4
register_subalias("5", m_R1.m_N); // Pin 5
register_subalias("6", m_THRES); // Pin 6
register_subalias("7", m_RDIS.m_P); // Pin 7
register_subalias("8", m_R1.m_P); // Pin 8
}
};
inline nl_double NETLIB_NAME(NE555)::clamp(const nl_double v, const nl_double a, const nl_double b)
{
nl_double ret = v;
nl_double vcc = TERMANALOG(m_R1.m_P);
if (ret > vcc - a)
ret = vcc - a;
if (ret < b)
ret = b;
return ret;
}
NETLIB_RESET(NE555)
{
m_R1.do_reset();
m_R2.do_reset();
m_R3.do_reset();
m_RDIS.do_reset();
m_R1.set_R(5000);
m_R2.set_R(5000);
m_R3.set_R(5000);
m_RDIS.set_R(R_OFF);
m_last_out = true;
}
NETLIB_UPDATE(NE555)
{
// FIXME: assumes GND is connected to 0V.
nl_double vt = clamp(TERMANALOG(m_R2.m_P), 0.7, 1.4);
bool bthresh = (INPANALOG(m_THRES) > vt);
bool btrig = (INPANALOG(m_TRIG) > clamp(TERMANALOG(m_R2.m_N), 0.7, 1.4));
if (!btrig)
{
m_ff = true;
}
else if (bthresh)
{
m_ff = false;
}
bool out = (!INPLOGIC(m_RESET) ? false : m_ff);
if (m_last_out && !out)
{
m_RDIS.update_dev();
OUTANALOG(m_OUT, TERMANALOG(m_R3.m_N));
m_RDIS.set_R(R_ON);
}
else if (!m_last_out && out)
{
m_RDIS.update_dev();
// FIXME: Should be delayed by 100ns
OUTANALOG(m_OUT, TERMANALOG(m_R1.m_P));
m_RDIS.set_R(R_OFF);
}
m_last_out = out;
}
NETLIB_DEVICE_IMPL(NE555)
NETLIB_DEVICE_IMPL(NE555_dip)
} //namespace devices
} // namespace netlist
|