1 | var Board = require("./board");
|
2 | var Collection = require("./mixins/collection");
|
3 | var util = require("util");
|
4 | var priv = new Map();
|
5 |
|
6 | function ShiftRegister(opts) {
|
7 | if (!(this instanceof ShiftRegister)) {
|
8 | return new ShiftRegister(opts);
|
9 | }
|
10 |
|
11 | if (Array.isArray(opts)) {
|
12 |
|
13 | opts = {
|
14 | pins: {
|
15 | data: opts[0],
|
16 | clock: opts[1],
|
17 | latch: opts[2],
|
18 | reset: opts.length === 4 ? opts[3] : null,
|
19 | }
|
20 | };
|
21 | } else if (typeof opts.pins === "object" && Array.isArray(opts.pins)) {
|
22 | opts.pins = {
|
23 | data: opts.pins[0],
|
24 | clock: opts.pins[1],
|
25 | latch: opts.pins[2],
|
26 | reset: opts.pins.length === 4 ? opts.pins[3] : null,
|
27 | };
|
28 | }
|
29 |
|
30 | Board.Component.call(
|
31 | this, opts = Board.Options(opts)
|
32 | );
|
33 |
|
34 | this.size = opts.size || 1;
|
35 | this.pins.reset = typeof opts.pins.reset !== "undefined" ? opts.pins.reset : null;
|
36 |
|
37 | var isAnode = typeof opts.isAnode !== "undefined" ? opts.isAnode : false;
|
38 | var clear = isAnode ? 255 : 0;
|
39 | var state = {
|
40 | isAnode: isAnode,
|
41 | value: new Array(this.size).fill(clear),
|
42 | encoded: encoded[isAnode ? "anode" : "cathode"],
|
43 | clear: clear,
|
44 | };
|
45 |
|
46 | priv.set(this, state);
|
47 |
|
48 | Object.defineProperties(this, {
|
49 | isAnode: {
|
50 | get: function() {
|
51 | return isAnode;
|
52 | }
|
53 | },
|
54 | value: {
|
55 | get: function() {
|
56 | return state.value;
|
57 | }
|
58 | },
|
59 | });
|
60 | }
|
61 |
|
62 | var encoded = {
|
63 | cathode: [63, 6, 91, 79, 102, 109, 125, 7, 127, 103],
|
64 | anode: [64, 121, 36, 48, 25, 18, 2, 120, 0, 24],
|
65 | };
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | ShiftRegister.prototype.display = function(value) {
|
72 | var state = priv.get(this);
|
73 | var chars;
|
74 |
|
75 | if (typeof value === "number") {
|
76 |
|
77 | return this.display(String(value));
|
78 | }
|
79 |
|
80 | if (typeof value === "string") {
|
81 | var matches = value.match(/([0-9]{1}\.*)/g);
|
82 |
|
83 | if (matches && matches.length) {
|
84 | chars = matches.map(function(char) {
|
85 |
|
86 | if (char.length === 1) {
|
87 | return state.encoded[char] | (1 << 7);
|
88 | }
|
89 |
|
90 | return state.encoded[char[0]];
|
91 | });
|
92 | }
|
93 | }
|
94 |
|
95 | this.send(chars);
|
96 |
|
97 | state.value = chars;
|
98 |
|
99 | return this;
|
100 | };
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | ShiftRegister.prototype.send = function(value) {
|
108 | var state = priv.get(this);
|
109 | var args = Array.from(arguments);
|
110 |
|
111 | if (args.length === 1) {
|
112 | args = [value];
|
113 | }
|
114 |
|
115 | if (Array.isArray(value)) {
|
116 | args = value;
|
117 | }
|
118 |
|
119 |
|
120 | this.io.digitalWrite(this.pins.latch, this.io.LOW);
|
121 |
|
122 | args.forEach(function(arg) {
|
123 | if (typeof arg === "string") {
|
124 | arg = arg.charCodeAt(0);
|
125 | }
|
126 | if (this.isAnode &&
|
127 | (arg !== 255 && !state.encoded.includes(arg) && !state.encoded.includes(arg & ~(1 << 7)))) {
|
128 |
|
129 | var index = encoded.anode.findIndex(function(value) {
|
130 | return value === arg;
|
131 | });
|
132 |
|
133 | if (index !== -1) {
|
134 | arg = encoded.cathode[index];
|
135 | }
|
136 | }
|
137 | this.board.shiftOut(this.pins.data, this.pins.clock, true, arg);
|
138 | }, this);
|
139 |
|
140 |
|
141 | this.io.digitalWrite(this.pins.latch, this.io.HIGH);
|
142 |
|
143 | state.value = args;
|
144 |
|
145 | return this;
|
146 | };
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 | ShiftRegister.prototype.clear = function() {
|
153 | var state = priv.get(this);
|
154 | return this.send(Array(this.size).fill(state.clear));
|
155 | };
|
156 |
|
157 | ShiftRegister.prototype.reset = function() {
|
158 | if (this.pins.reset === null) {
|
159 | throw new Error("ShiftRegister was not initialized with a reset pin");
|
160 | }
|
161 | this.io.digitalWrite(this.pins.clock, this.io.LOW);
|
162 | this.io.digitalWrite(this.pins.reset, this.io.LOW);
|
163 | this.io.digitalWrite(this.pins.clock, this.io.HIGH);
|
164 | this.io.digitalWrite(this.pins.reset, this.io.HIGH);
|
165 |
|
166 | return this;
|
167 | };
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 | function ShiftRegisters(numsOrObjects) {
|
177 | if (!(this instanceof ShiftRegisters)) {
|
178 | return new ShiftRegisters(numsOrObjects);
|
179 | }
|
180 |
|
181 | Object.defineProperty(this, "type", {
|
182 | value: ShiftRegister
|
183 | });
|
184 |
|
185 | Collection.call(this, numsOrObjects);
|
186 | }
|
187 |
|
188 | util.inherits(ShiftRegisters, Collection);
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 | Collection.installMethodForwarding(
|
210 | ShiftRegisters.prototype, ShiftRegister.prototype
|
211 | );
|
212 |
|
213 |
|
214 | ShiftRegister.Collection = ShiftRegisters;
|
215 |
|
216 |
|
217 | if (!!process.env.IS_TEST_MODE) {
|
218 | ShiftRegister.purge = function() {
|
219 | priv.clear();
|
220 | };
|
221 | }
|
222 |
|
223 | module.exports = ShiftRegister;
|