summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/devices/nld_74166.cpp
blob: 243281ca52794b805342b975a6d03497b4090ab5 (plain) (blame)
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
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/*
 * nld_74166.cpp
 *
 *  74166: Parallel-Load 8-Bit Shift Register
 *
 *          +--------------+
 *      SER |1     ++    16| VCC
 *        A |2           15| SH/LDQ
 *        B |3           14| H
 *        C |4    74166  13| QH
 *        D |5           12| G
 *   CLKINH |6           11| F
 *      CLK |7           10| E
 *      GND |8            9| CLRQ
 *          +--------------+
 *
 * SH/LDQ: Shift / !Load
 * CLKINH: Clock Inhibit
 * SER: Serial In
 *
 *  Naming convention attempts to follow Texas Instruments datasheet
 *
 */

#include "nld_74166.h"
#include "nl_base.h"

// FIXME: separate handlers for inputs

namespace netlist
{
	namespace devices
	{
	NETLIB_OBJECT(74166)
	{
		NETLIB_CONSTRUCTOR(74166)
		, m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" }, NETLIB_DELEGATE(inputs))
		, m_SER(*this, "SER", NETLIB_DELEGATE(inputs))
		, m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs))
		, m_SH_LDQ(*this, "SH_LDQ", NETLIB_DELEGATE(inputs))
		, m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs))
		, m_CLKINH(*this, "CLKINH", NETLIB_DELEGATE(inputs))
		, m_QH(*this, "QH")
		, m_shifter(*this, "m_shifter", 0)
		, m_last_CLRQ(*this, "m_last_CLRQ", 0)
		, m_last_CLK(*this, "m_last_CLK", 0)
		, m_power_pins(*this)
		{
		}

	private:
		NETLIB_RESETI()
		{
			m_shifter = 0;
			m_last_CLRQ = 0;
			m_last_CLK = 0;
		}

		NETLIB_HANDLERI(inputs)
		{
			netlist_sig_t old_qh = m_QH.net().Q();
			netlist_sig_t qh = 0;

			netlist_time delay = NLTIME_FROM_NS(26);
			if (m_CLRQ())
			{
				bool clear_unset = !m_last_CLRQ;
				if (clear_unset)
				{
					delay = NLTIME_FROM_NS(35);
				}

				if (!m_CLK() || m_CLKINH())
				{
					qh = old_qh;
				}
				else if (!m_last_CLK)
				{
					if (!m_SH_LDQ())
					{
						m_shifter = 0;
						for (std::size_t i=0; i<8; i++)
							m_shifter |= (m_DATA[i]() << i);
					}
					else
					{
						unsigned high_bit = m_SER() ? 0x80 : 0;
						m_shifter = high_bit | (m_shifter >> 1);
					}

					qh = m_shifter & 1;
					if (!qh && !clear_unset)
					{
						delay = NLTIME_FROM_NS(30);
					}
				}
			}

			m_last_CLRQ = m_CLRQ();
			m_last_CLK = m_CLK();

			m_QH.push(qh, delay); //FIXME
		}

		object_array_t<logic_input_t, 8> m_DATA;
		logic_input_t m_SER;
		logic_input_t m_CLRQ;
		logic_input_t m_SH_LDQ;
		logic_input_t m_CLK;
		logic_input_t m_CLKINH;
		logic_output_t m_QH;

		state_var<unsigned> m_shifter;
		state_var<unsigned> m_last_CLRQ;
		state_var<unsigned> m_last_CLK;
		nld_power_pins m_power_pins;
	};

	NETLIB_DEVICE_IMPL(74166,    "TTL_74166", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ,@VCC,@GND")

	} //namespace devices
} // namespace netlist