UNPKG

50.7 kBJavaScriptView Raw
1var Board = require("./board");
2var Emitter = require("events").EventEmitter;
3var util = require("util");
4var nanosleep = require("./sleep").nano;
5var Fn = require("./fn");
6var priv = new Map();
7var active = new Map();
8
9function Base() {
10 Emitter.call(this);
11
12 this.HIGH = 1;
13 this.LOW = 0;
14 this.isReady = false;
15
16 this.MODES = {};
17 this.pins = [];
18 this.analogPins = [];
19}
20
21util.inherits(Base, Emitter);
22
23var Controllers = {
24 MCP23017: {
25 ADDRESSES: {
26 value: [0x20]
27 },
28 REGISTER: {
29 value: {
30 // IO A
31 IODIRA: 0x00,
32 GPPUA: 0x0C,
33 GPIOA: 0x12,
34 OLATA: 0x14,
35 // IO B
36 IODIRB: 0x01,
37 GPPUB: 0x0D,
38 GPIOB: 0x13,
39 OLATB: 0x15,
40 }
41 },
42 initialize: {
43 value: function(opts) {
44 var state = priv.get(this);
45
46 state.iodir = [0xff, 0xff];
47 state.olat = [0xff, 0xff];
48 state.gpio = [0xff, 0xff];
49 state.gppu = [0x00, 0x00];
50
51 this.address = opts.address || this.ADDRESSES[0];
52 opts.address = this.address;
53
54 this.io.i2cConfig(opts);
55 this.io.i2cWrite(this.address, [this.REGISTER.IODIRA, state.iodir[this.REGISTER.IODIRA]]);
56 this.io.i2cWrite(this.address, [this.REGISTER.IODIRB, state.iodir[this.REGISTER.IODIRB]]);
57
58 Object.assign(this.MODES, this.io.MODES);
59
60 for (var i = 0; i < 16; i++) {
61 this.pins.push({
62 supportedModes: [
63 this.MODES.INPUT,
64 this.MODES.OUTPUT
65 ],
66 mode: 0,
67 value: 0,
68 report: 0,
69 analogChannel: 127
70 });
71
72 this.pinMode(i, this.MODES.OUTPUT);
73 this.digitalWrite(i, this.LOW);
74 }
75
76 this.name = "MCP23017";
77 this.isReady = true;
78
79 this.emit("connect");
80 this.emit("ready");
81 }
82 },
83 normalize: {
84 value: function(pin) {
85 return pin;
86 }
87 },
88 // 1.6.1 I/O DIRECTION REGISTER
89 pinMode: {
90 value: function(pin, mode) {
91 var state = priv.get(this);
92 var pinIndex = pin;
93 var port = 0;
94 var iodir = null;
95
96 if (pin < 8) {
97 port = this.REGISTER.IODIRA;
98 } else {
99 port = this.REGISTER.IODIRB;
100 pin -= 8;
101 }
102
103 iodir = state.iodir[port];
104
105 if (mode === this.io.MODES.INPUT) {
106 iodir |= 1 << pin;
107 } else {
108 iodir &= ~(1 << pin);
109 }
110
111 this.pins[pinIndex].mode = mode;
112 this.io.i2cWrite(this.address, [port, iodir]);
113
114 state.iodir[port] = iodir;
115 }
116 },
117 // 1.6.10 PORT REGISTER
118 digitalWrite: {
119 value: function(pin, value) {
120 var state = priv.get(this);
121 var pinIndex = pin;
122 var port = 0;
123 var gpio = 0;
124 // var olataddr = 0;
125 var gpioaddr = 0;
126
127 if (pin < 8) {
128 port = this.REGISTER.IODIRA;
129 // olataddr = this.REGISTER.OLATA;
130 gpioaddr = this.REGISTER.GPIOA;
131 } else {
132 port = this.REGISTER.IODIRB;
133 // olataddr = this.REGISTER.OLATB;
134 gpioaddr = this.REGISTER.GPIOB;
135 pin -= 8;
136 }
137
138 gpio = state.olat[port];
139
140 if (value === this.io.HIGH) {
141 gpio |= 1 << pin;
142 } else {
143 gpio &= ~(1 << pin);
144 }
145
146 this.pins[pinIndex].report = 0;
147 this.pins[pinIndex].value = value;
148 this.io.i2cWrite(this.address, [gpioaddr, gpio]);
149
150 state.olat[port] = gpio;
151 state.gpio[port] = gpio;
152 }
153 },
154 // 1.6.7 PULL-UP RESISTOR
155 // CONFIGURATION REGISTER
156 pullUp: {
157 value: function(pin, value) {
158 var state = priv.get(this);
159 var port = 0;
160 var gppu = 0;
161 var gppuaddr = 0;
162
163 if (pin < 8) {
164 port = this.REGISTER.IODIRA;
165 gppuaddr = this.REGISTER.GPPUA;
166 } else {
167 port = this.REGISTER.IODIRB;
168 gppuaddr = this.REGISTER.GPPUB;
169 pin -= 8;
170 }
171
172 gppu = state.gppu[port];
173
174 if (value === this.io.HIGH) {
175 gppu |= 1 << pin;
176 } else {
177 gppu &= ~(1 << pin);
178 }
179
180 this.io.i2cWrite(this.address, [gppuaddr, gppu]);
181
182 state.gppu[port] = gppu;
183 }
184 },
185 digitalRead: {
186 value: function(pin, callback) {
187 var pinIndex = pin;
188 var gpioaddr = 0;
189
190 if (pin < 8) {
191 gpioaddr = this.REGISTER.GPIOA;
192 } else {
193 gpioaddr = this.REGISTER.GPIOB;
194 pin -= 8;
195 }
196
197 this.pins[pinIndex].report = 1;
198
199 this.on("digital-read-" + pinIndex, callback);
200
201 this.io.i2cRead(this.address, gpioaddr, 1, function(data) {
202 var byte = data[0];
203 var value = byte >> pin & 0x01;
204
205 this.pins[pinIndex].value = value;
206
207 this.emit("digital-read-" + pinIndex, value);
208 }.bind(this));
209 }
210 },
211 },
212 MCP23008: {
213 ADDRESSES: {
214 value: [0x20]
215 },
216 REGISTER: {
217 value: {
218 IODIR: 0x00,
219 GPPU: 0x06,
220 GPIO: 0x09,
221 OLAT: 0x0A,
222 }
223 },
224 initialize: {
225 value: function(opts) {
226 var state = priv.get(this);
227
228 state.iodir = [0xff];
229 state.olat = [0xff];
230 state.gpio = [0xff];
231 state.gppu = [0x00];
232
233 this.address = opts.address || this.ADDRESSES[0];
234
235 opts.address = this.address;
236
237 this.io.i2cConfig(opts);
238 this.io.i2cWrite(this.address, [this.REGISTER.IODIR, state.iodir[this.REGISTER.IODIR]]);
239
240 Object.assign(this.MODES, this.io.MODES);
241
242 for (var i = 0; i < 8; i++) {
243 this.pins.push({
244 supportedModes: [
245 this.MODES.INPUT,
246 this.MODES.OUTPUT
247 ],
248 mode: 0,
249 value: 0,
250 report: 0,
251 analogChannel: 127
252 });
253
254 this.pinMode(i, this.MODES.OUTPUT);
255 this.digitalWrite(i, this.LOW);
256 }
257
258 this.name = "MCP23008";
259 this.isReady = true;
260
261 this.emit("connect");
262 this.emit("ready");
263 }
264 },
265 normalize: {
266 value: function(pin) {
267 return pin;
268 }
269 },
270 // 1.6.1 I/O DIRECTION REGISTER
271 pinMode: {
272 value: function(pin, mode) {
273 var state = priv.get(this);
274 var pinIndex = pin;
275 var port = this.REGISTER.IODIR;
276 var iodir = state.iodir[port];
277
278 if (mode === this.io.MODES.INPUT) {
279 iodir |= 1 << pin;
280 } else {
281 iodir &= ~(1 << pin);
282 }
283
284 this.pins[pinIndex].mode = mode;
285 this.io.i2cWrite(this.address, [port, iodir]);
286
287 state.iodir[port] = iodir;
288 }
289 },
290 // 1.6.10 PORT REGISTER
291 digitalWrite: {
292 value: function(pin, value) {
293 var state = priv.get(this);
294 var pinIndex = pin;
295 var port = this.REGISTER.IODIR;
296 var gpioaddr = this.REGISTER.GPIO;
297 var gpio = state.olat[port];
298
299 if (value === this.io.HIGH) {
300 gpio |= 1 << pin;
301 } else {
302 gpio &= ~(1 << pin);
303 }
304
305 this.pins[pinIndex].report = 0;
306 this.pins[pinIndex].value = value;
307 this.io.i2cWrite(this.address, [gpioaddr, gpio]);
308
309 state.olat[port] = gpio;
310 state.gpio[port] = gpio;
311 }
312 },
313 // 1.6.7 PULL-UP RESISTOR
314 // CONFIGURATION REGISTER
315 pullUp: {
316 value: function(pin, value) {
317 var state = priv.get(this);
318 var port = this.REGISTER.IODIR;
319 var gppuaddr = this.REGISTER.GPPU;
320 var gppu = state.gppu[port];
321
322 if (value === this.io.HIGH) {
323 gppu |= 1 << pin;
324 } else {
325 gppu &= ~(1 << pin);
326 }
327
328 this.io.i2cWrite(this.address, [gppuaddr, gppu]);
329
330 state.gppu[port] = gppu;
331 }
332 },
333 digitalRead: {
334 value: function(pin, callback) {
335 var pinIndex = pin;
336 var gpioaddr = this.REGISTER.GPIO;
337
338 this.pins[pinIndex].report = 1;
339
340 this.on("digital-read-" + pin, callback);
341
342 this.io.i2cRead(this.address, gpioaddr, 1, function(data) {
343 var byte = data[0];
344 var value = byte >> pin & 0x01;
345
346 this.pins[pinIndex].value = value;
347
348 this.emit("digital-read-" + pin, value);
349 }.bind(this));
350 }
351 },
352 },
353 PCF8574: {
354 ADDRESSES: {
355 value: [0x20]
356 },
357 REGISTER: {},
358 initialize: {
359 value: function(opts) {
360 var state = priv.get(this);
361
362 state.port = 0x00;
363 state.ddr = 0x00;
364 state.pins = 0x00;
365
366 this.address = opts.address || this.ADDRESSES[0];
367
368 opts.address = this.address;
369 this.io.i2cConfig(opts);
370
371 Object.assign(this.MODES, this.io.MODES);
372
373 for (var i = 0; i < 8; i++) {
374 this.pins.push({
375 supportedModes: [
376 this.MODES.INPUT,
377 this.MODES.OUTPUT
378 ],
379 mode: 1,
380 value: 0,
381 report: 0,
382 analogChannel: 127
383 });
384
385 this.pinMode(i, this.MODES.OUTPUT);
386 this.digitalWrite(i, this.LOW);
387 }
388
389 this.name = "PCF8574";
390 this.isReady = true;
391
392 this.emit("connect");
393 this.emit("ready");
394 }
395 },
396 normalize: {
397 value: function(pin) {
398 return pin;
399 }
400 },
401 pinMode: {
402 value: function(pin, mode) {
403 var state = priv.get(this);
404 var pinIndex = pin;
405 var port = state.port;
406 var ddr = state.ddr;
407 var pins = state.pins;
408
409 if (mode === this.MODES.INPUT) {
410 ddr &= ~(1 << pin);
411 port &= ~(1 << pin);
412 } else {
413 ddr |= (1 << pin);
414 port &= ~(1 << pin);
415 }
416
417 this.pins[pinIndex].mode = mode;
418
419 state.port = port;
420 state.ddr = ddr;
421
422 this.io.i2cWrite(this.address, (pins & ~ddr) | port);
423 }
424 },
425 digitalWrite: {
426 value: function(pin, value) {
427 var state = priv.get(this);
428 var pinIndex = pin;
429 var port = state.port;
430 var ddr = state.ddr;
431 var pins = state.pins;
432
433 if (value) {
434 port |= 1 << pin;
435 } else {
436 port &= ~(1 << pin);
437 }
438
439 this.pins[pinIndex].report = 0;
440 this.pins[pinIndex].value = value;
441
442 state.port = port;
443
444 this.io.i2cWrite(this.address, (pins & ~ddr) | port);
445 }
446 },
447 digitalRead: {
448 value: function(pin, callback) {
449 var state = priv.get(this);
450 var pinIndex = pin;
451
452 this.pins[pinIndex].report = 1;
453
454 this.on("digital-read-" + pin, callback);
455
456 this.io.i2cRead(this.address, 1, function(data) {
457 var byte = data[0];
458 var value = byte >> pin & 0x01;
459
460 state.pins = byte;
461
462 this.pins[pinIndex].value = value;
463
464 this.emit("digital-read-" + pin, value);
465 }.bind(this));
466 }
467 },
468 },
469 PCF8575: {
470 ADDRESSES: {
471 value: [0x20]
472 },
473 REGISTER: {},
474 initialize: {
475 value: function(opts) {
476 var state = priv.get(this);
477
478 state.port = [0x00, 0x01];
479 state.gpio = [0x00, 0x00];
480
481 this.address = opts.address || this.ADDRESSES[0];
482
483 opts.address = this.address;
484 this.io.i2cConfig(opts);
485
486 Object.assign(this.MODES, this.io.MODES);
487
488 for (var i = 0; i < 16; i++) {
489 this.pins.push({
490 supportedModes: [
491 this.MODES.INPUT,
492 this.MODES.OUTPUT
493 ],
494 mode: 1,
495 value: 0,
496 report: 0,
497 analogChannel: 127
498 });
499
500 this.pinMode(i, this.MODES.OUTPUT);
501 this.digitalWrite(i, this.LOW);
502 }
503
504 // Set all pins low on initialization
505 this.io.i2cWrite(this.address, state.gpio);
506
507 this.name = "PCF8575";
508 this.isReady = true;
509
510 this.emit("connect");
511 this.emit("ready");
512 }
513 },
514 normalize: {
515 value: function(pin) {
516 return pin;
517 }
518 },
519 pinMode: {
520 value: function(pin, mode) {
521 var pinIndex = pin;
522 this.pins[pinIndex].mode = mode;
523 }
524 },
525 digitalWrite: {
526 value: function(pin, value) {
527 var state = priv.get(this);
528 var pinIndex = pin;
529 var port;
530
531 if (pin < 8) {
532 port = 0;
533 } else {
534 port = 1;
535 pin -= 8;
536 }
537
538 if (value === this.io.HIGH) {
539 state.gpio[port] |= 1 << pin;
540 } else {
541 state.gpio[port] &= ~(1 << pin);
542 }
543
544 this.pins[pinIndex].report = 0;
545 this.pins[pinIndex].value = value;
546
547 this.io.i2cWrite(this.address, state.gpio);
548 }
549 },
550 digitalRead: {
551 value: function(pin, callback) {
552 var pinIndex = pin;
553 var port;
554
555 if (pin < 8) {
556 port = 0;
557 } else {
558 port = 1;
559 pin -= 8;
560 }
561
562 this.pins[pinIndex].report = 1;
563
564 this.on("digital-read-" + pin, callback);
565
566 this.io.i2cRead(this.address, 2, function(data) {
567 var byte = data[port];
568 var value = byte >> pin & 0x01;
569
570 this.pins[pinIndex].value = value;
571
572 this.emit("digital-read-" + pin, value);
573 }.bind(this));
574 }
575 },
576 },
577 PCA9685: {
578 ADDRESSES: {
579 value: [0x40]
580 },
581 REGISTER: {
582 value: {
583 MODE1: 0x00,
584 PRESCALE: 0xFE,
585 BASE: 0x06
586 }
587 },
588 initialize: {
589 value: function(opts) {
590 var state = priv.get(this);
591
592 // 7.3.5 PWM frequency PRE_SCALE
593 //
594 state.frequency = Board.constrain(opts.frequency || 1526, 24, 1526) * 0.9;
595
596 this.address = opts.address || this.ADDRESSES[0];
597 this.pwmRange = opts.pwmRange || [0, 4095];
598
599 Object.defineProperties(this, {
600 prescale: {
601 get: function() {
602 // PCA9685 has an on-board 25MHz clock source
603
604 // 7.3.5 PWM frequency PRE_SCALE
605 return Math.round(25000000 / (4096 * state.frequency)) - 1;
606 }
607 },
608 frequency: {
609 get: function() {
610 return state.frequency;
611 }
612 }
613 });
614
615 opts.address = this.address;
616
617 this.io.i2cConfig(opts);
618
619 // Reset
620 this.io.i2cWriteReg(this.address, this.REGISTER.MODE1, 0x00);
621 // Sleep
622 this.io.i2cWriteReg(this.address, this.REGISTER.MODE1, 0x10);
623 // Set prescalar
624 this.io.i2cWriteReg(this.address, this.REGISTER.PRESCALE, this.prescale);
625 // Wake up
626 this.io.i2cWriteReg(this.address, this.REGISTER.MODE1, 0x00);
627 // Wait 5 nanoseconds for restart
628 nanosleep(5);
629 // Auto-increment
630 this.io.i2cWriteReg(this.address, this.REGISTER.MODE1, 0xa1);
631
632 Object.assign(this.MODES, this.io.MODES);
633
634 for (var i = 0; i < 16; i++) {
635 this.pins.push({
636 supportedModes: [
637 this.MODES.OUTPUT,
638 this.MODES.PWM,
639 this.MODES.SERVO,
640 ],
641 mode: 0,
642 value: 0,
643 report: 0,
644 analogChannel: 127
645 });
646
647 this.pinMode(i, this.MODES.OUTPUT);
648 this.digitalWrite(i, this.LOW);
649 }
650
651 this.name = "PCA9685";
652 this.isReady = true;
653
654 this.emit("connect");
655 this.emit("ready");
656 }
657 },
658 normalize: {
659 value: function(pin) {
660 return this.io.name.includes("Tessel 2") ? pin - 1 : pin;
661 }
662 },
663 pinMode: {
664 value: function(pin, mode) {
665 if (this.pins[pin] === undefined) {
666 throw new RangeError("Invalid PCA9685 pin: " + pin);
667 }
668 this.pins[pin].mode = mode;
669 }
670 },
671 digitalWrite: {
672 value: function(pin, value) {
673 this.pwmWrite(pin, value ? 255 : 0);
674 }
675 },
676 analogWrite: {
677 value: function(pin, value) {
678 this.pwmWrite(pin, value);
679 }
680 },
681 servoWrite: {
682 value: function(pin, value) {
683
684 var off;
685
686 if (value < 544) {
687 value = Board.constrain(value, 0, 180);
688 off = Fn.map(value, 0, 180, this.pwmRange[0] / 4, this.pwmRange[1] / 4);
689 } else {
690 off = value / 4;
691 }
692
693 off |= 0;
694
695 this.io.i2cWrite(this.address, [
696 this.REGISTER.BASE + 4 * pin,
697 0, 0,
698 off, off >> 8
699 ]);
700 }
701 },
702 pwmWrite: {
703 value: function(pin, value) {
704
705 if (this.pins[pin] === undefined) {
706 throw new RangeError("Invalid PCA9685 pin: " + pin);
707 }
708
709 value = Board.constrain(value, 0, 255);
710
711 var on = 0;
712 var off = this.pwmRange[1] * value / 255;
713
714 if (value === 0) {
715 // Special value for signal fully off.
716 on = 0;
717 off = 4096;
718 }
719
720 if (value === 255) {
721 // Special value for signal fully on.
722 on = 4096;
723 off = 0;
724 }
725
726 this.io.i2cWrite(this.address, [
727 this.REGISTER.BASE + 4 * pin,
728 on, on >> 8,
729 off, off >> 8
730 ]);
731
732 this.pins[pin].value = value;
733 }
734 }
735 },
736 PCF8591: {
737 ADDRESSES: {
738 value: [0x48]
739 },
740 REGISTER: {},
741 initialize: {
742 value: function(opts) {
743 var state = priv.get(this);
744
745 state.control = 0x45;
746 state.reading = false;
747
748 this.address = opts.address || this.ADDRESSES[0];
749
750 opts.address = this.address;
751 this.io.i2cConfig(opts);
752
753 Object.assign(this.MODES, this.io.MODES);
754
755 for (var i = 0; i < 4; i++) {
756 this.pins.push({
757 supportedModes: [
758 this.MODES.ANALOG
759 ],
760 mode: 1,
761 value: 0,
762 report: 0,
763 analogChannel: i
764 });
765 }
766
767 this.analogPins.push(0, 1, 2, 3);
768
769 this.io.i2cWrite(this.address, state.control);
770
771 this.name = "PCF8591";
772 this.isReady = true;
773
774 this.emit("connect");
775 this.emit("ready");
776 }
777 },
778 normalize: {
779 value: function(pin) {
780 if (typeof pin === "string" && pin[0] === "A") {
781 return +pin.slice(1);
782 }
783 return pin;
784 }
785 },
786 pinMode: {
787 value: function(pin, mode) {
788 this.pins[pin].mode = mode;
789 }
790 },
791 analogRead: {
792 value: function(pin, callback) {
793 var state = priv.get(this);
794 var pinIndex = pin;
795
796 this.pins[pinIndex].report = 1;
797
798 this.on("analog-read-" + pin, callback);
799
800 // Since this operation will read all 4 pins,
801 // it only needs to be initiated once.
802 if (!state.reading) {
803 state.reading = true;
804
805 this.io.i2cRead(this.address, 4, function(data) {
806 var value;
807 for (var i = 0; i < 4; i++) {
808 value = data[i] << 2;
809 this.pins[i].value = value;
810
811 if (this.pins[i].report) {
812 this.emit("analog-read-" + i, value);
813 }
814 }
815 }.bind(this));
816 }
817 }
818 },
819 },
820 MUXSHIELD2: {
821 initialize: {
822 value: function() {
823 var state = priv.get(this);
824
825 // _S[\d] (Digital: 2, 4, 6, 7)
826 state.select = [2, 4, 6, 7];
827 // _IOS[\d] (Digital: 10, 11, 12)
828 state.ios = [null, 10, 11, 12];
829 // _IO[\d] (Analog In: "A0", "A1", "A2")
830 state.io = [null, 14, 15, 16];
831 state.aio = [null, 0, 1, 2];
832
833 state.outMode = 8;
834 state.pinMap = {};
835 state.rowReading = [false, false, false];
836 state.rowMode = [null, null, null];
837 // Each rowValue is a single uint16
838 state.rowValues = [0, 0, 0];
839
840 Object.assign(this.MODES, {
841 INPUT: 0,
842 OUTPUT: 1,
843 ANALOG: 2,
844 });
845
846 this.io.pinMode(state.select[0], this.MODES.OUTPUT);
847 this.io.pinMode(state.select[1], this.MODES.OUTPUT);
848 this.io.pinMode(state.select[2], this.MODES.OUTPUT);
849 this.io.pinMode(state.select[3], this.MODES.OUTPUT);
850
851 this.io.pinMode(state.outMode, this.MODES.OUTPUT);
852 this.io.digitalWrite(state.outMode, this.LOW);
853
854 this.io.pinMode(state.ios[1], this.MODES.OUTPUT);
855 this.io.pinMode(state.ios[2], this.MODES.OUTPUT);
856 this.io.pinMode(state.ios[3], this.MODES.OUTPUT);
857
858 var row = 1;
859 var mask = 16;
860 var index = 0;
861
862 for (var i = 0; i < 48; i++) {
863 var band = i & mask;
864
865 if (band === mask) {
866 row++;
867 mask *= 2;
868 index = 0;
869 }
870
871 state.pinMap["IO" + row + "-" + index] = i;
872
873 this.pins.push({
874 row: row,
875 index: index,
876 supportedModes: [
877 this.MODES.INPUT,
878 this.MODES.OUTPUT,
879 this.MODES.ANALOG,
880 ],
881 mode: 1,
882 value: 0,
883 report: 0,
884 analogChannel: i
885 });
886
887 this.analogPins.push(i);
888
889 // TODO: Not sure about this?
890 // this.io.pinMode(i, this.MODES.OUTPUT);
891 // this.io.digitalWrite(i, this.LOW);
892
893 index++;
894 }
895
896 this.name = "MUXSHIELD2";
897 this.isReady = true;
898
899 this.emit("connect");
900 this.emit("ready");
901 }
902 },
903 normalize: {
904 value: function(pin) {
905 return pin;
906 }
907 },
908 pinMode: {
909 value: function(pin, mode) {
910 var state = priv.get(this);
911 var pinIndex = state.pinMap[pin];
912
913 if (pinIndex === undefined) {
914 throw new Error("MUXSHIELD2: Invalid Pin number or name: " + pin);
915 }
916
917 var row = this.pins[pinIndex].row;
918 var rowModeIndex = row - 1;
919 var rowMode = state.rowMode[rowModeIndex];
920
921 if (rowMode === mode) {
922 return this;
923 }
924
925 if (rowMode !== null && rowMode !== mode) {
926 throw new Error("MUXSHIELD2: Cannot set mixed modes per IO row.");
927 }
928
929 state.rowMode[rowModeIndex] = mode;
930
931 // MUXSHIELD2 Disallows mixing modes per row.
932 // Once a mode is set for a given pin in a given row,
933 // set all the pins in that row to the same mode.
934 for (var i = 0; i < 16; i++) {
935 this.pins[rowModeIndex + i].mode = mode;
936 }
937
938 var IO = state.io[row];
939 var IOS = state.ios[row];
940
941 if (mode === this.MODES.INPUT) {
942 // Read an analog input as digital
943 this.io.pinMode(IO, this.MODES.INPUT);
944 // this.io.digitalWrite(IOS, this.LOW);
945 }
946
947 if (mode === this.MODES.OUTPUT) {
948 this.io.pinMode(IO, this.MODES.OUTPUT);
949 this.io.digitalWrite(IOS, this.HIGH);
950 }
951 }
952 },
953 digitalWrite: {
954 value: function(pin, value) {
955 var state = priv.get(this);
956 var pinIndex = state.pinMap[pin];
957
958 if (pinIndex === undefined) {
959 throw new Error("MUXSHIELD2: Invalid Pin number or name: " + pin);
960 }
961
962 var row = this.pins[pinIndex].row;
963 var rowValueIndex = row - 1;
964 var rowValue = state.rowValues[rowValueIndex];
965
966 var ioPin = row - 1;
967 var offset = ioPin * 16;
968 var channel = pinIndex - offset;
969
970 if (value) {
971 rowValue |= 1 << channel;
972 } else {
973 rowValue &= ~(1 << channel);
974 }
975
976 this.io.digitalWrite(state.select[3], this.LOW);
977 this.io.digitalWrite(state.outMode, this.HIGH);
978
979 var S = state.select[row - 1];
980 var IO = state.io[row];
981
982 for (var i = 15; i >= 0; i--) {
983 this.io.digitalWrite(S, this.LOW);
984 this.io.digitalWrite(IO, (rowValue >> i) & 1);
985 this.io.digitalWrite(S, this.HIGH);
986 }
987
988 this.io.digitalWrite(state.select[3], this.HIGH);
989 this.io.digitalWrite(state.outMode, this.LOW);
990
991 this.pins[pinIndex].value = value;
992
993 state.rowValues[rowValueIndex] = rowValue;
994 }
995 },
996 digitalRead: {
997 value: function(pin, callback) {
998 this.ioRead("digital", pin, callback);
999 }
1000 },
1001 analogRead: {
1002 value: function(pin, callback) {
1003 this.ioRead("analog", pin, callback);
1004 }
1005 },
1006 ioRead: {
1007 value: function(type, pin, callback) {
1008 var state = priv.get(this);
1009 var pinIndex = state.pinMap[pin];
1010
1011 if (pinIndex === undefined) {
1012 throw new Error("MUXSHIELD2: Invalid Pin number or name: " + pin);
1013 }
1014
1015 this.on(type + "-read-" + pinIndex, callback);
1016
1017 var isAnalog = type === "analog" ? true : false;
1018 var row = this.pins[pinIndex].row;
1019 var rowReadingIndex = row - 1;
1020 var offset = rowReadingIndex * 16;
1021 var channel = pinIndex - offset;
1022
1023 this.pins[pinIndex].report = 1;
1024 this.pins[pinIndex].channel = channel;
1025 this.pins[pinIndex].ioPin = isAnalog ? rowReadingIndex : rowReadingIndex + 14;
1026
1027 var nextPinIndex = function() {
1028 var startAt = nextPinIndex.lastPinIndex + 1;
1029
1030 for (var i = startAt; i < this.pins.length; i++) {
1031 if (this.pins[i].report === 1) {
1032 nextPinIndex.lastPinIndex = i;
1033 return nextPinIndex.lastPinIndex;
1034 }
1035 }
1036
1037 nextPinIndex.lastPinIndex = -1;
1038
1039 return nextPinIndex();
1040 }.bind(this);
1041
1042 nextPinIndex.lastPinIndex = -1;
1043
1044 var handler = function(value) {
1045 var pinIndex = nextPinIndex.lastPinIndex;
1046 var pin = this.pins[pinIndex];
1047
1048 this.emit(type + "-read-" + pinIndex, value);
1049
1050 this.io.removeListener(type + "-read-" + pin.ioPin, handler);
1051
1052 setTimeout(read, 10);
1053 }.bind(this);
1054
1055 var read = function() {
1056 var pinIndex = nextPinIndex();
1057 var pin = this.pins[pinIndex];
1058
1059 this.select(pin.channel);
1060
1061 if (isAnalog) {
1062 this.io.pinMode(pin.ioPin, this.io.MODES.ANALOG);
1063 this.io.analogRead(pin.ioPin, handler);
1064 } else {
1065 this.io.digitalRead(pin.ioPin, handler);
1066 }
1067 }.bind(this);
1068
1069 if (!state.rowReading[rowReadingIndex]) {
1070 state.rowReading[rowReadingIndex] = true;
1071 read();
1072 }
1073 }
1074 },
1075
1076
1077 select: {
1078 value: function(channel) {
1079 var state = priv.get(this);
1080 this.io.digitalWrite(state.outMode, this.LOW);
1081 this.io.digitalWrite(state.select[0], (channel & 1));
1082 this.io.digitalWrite(state.select[1], (channel & 3) >> 1);
1083 this.io.digitalWrite(state.select[2], (channel & 7) >> 2);
1084 this.io.digitalWrite(state.select[3], (channel & 15) >> 3);
1085 }
1086 }
1087 },
1088
1089 GROVEPI: {
1090 ADDRESSES: {
1091 value: [0x04]
1092 },
1093 REGISTER: {},
1094 COMMANDS: {
1095 value: {
1096 DIGITAL_READ: 0x01,
1097 DIGITAL_WRITE: 0x02,
1098 ANALOG_READ: 0x03,
1099 ANALOG_WRITE: 0x04,
1100 PIN_MODE: 0x05,
1101 PING_READ: 0x07,
1102 }
1103 },
1104 initialize: {
1105 value: function(opts) {
1106 var state = priv.get(this);
1107
1108 state.isReading = false;
1109 state.pinMap = {
1110 D2: 2,
1111 D3: 3,
1112 D4: 4,
1113 D5: 5,
1114 D6: 6,
1115 D7: 7,
1116 D8: 8,
1117 A0: 14,
1118 A1: 15,
1119 A2: 16,
1120 };
1121
1122 // Override the relevant default "isType" methods
1123 this.isPwm = function(name) {
1124 var number = typeof name === "number" ? name : parseInt(name[1]);
1125 return number === 3 || number === 5 || number === 6;
1126 };
1127
1128 this.address = opts.address || this.ADDRESSES[0];
1129 opts.address = this.address;
1130
1131 this.io.i2cConfig(opts);
1132
1133 Object.assign(this.MODES, this.io.MODES);
1134
1135 var analogChannel;
1136
1137 for (var i = 0; i < 17; i++) {
1138 analogChannel = 127;
1139
1140 if (i <= 1 || (i >= 9 && i < 14)) {
1141 // There are no connections for:
1142 // O, 1, 9, 10, 11, 12, 13
1143 this.pins.push({
1144 supportedModes: [],
1145 mode: 0,
1146 value: 0,
1147 report: 0,
1148 analogChannel: analogChannel
1149 });
1150 } else {
1151
1152 this.pins.push({
1153 supportedModes: [
1154 this.MODES.INPUT,
1155 this.MODES.OUTPUT,
1156 ],
1157 mode: 0,
1158 value: 0,
1159 report: 0,
1160 analogChannel: analogChannel
1161 });
1162
1163 // Digital pins with PWM Support
1164 // D3, D5, D6
1165 if (this.isPwm(i)) {
1166 this.pins[i].supportedModes.push(
1167 this.MODES.PWM
1168 );
1169 }
1170
1171 if (i >= 14 && i <= 17) {
1172 // A0 = 0 = 14
1173 // A1 = 1 = 15
1174 // A2 = 2 = 16
1175 //
1176 // 14 is the analog offset
1177 this.pins[i].analogChannel = i - 14;
1178
1179 // Add ANALOG "read" mode
1180 this.pins[i].supportedModes.push(
1181 this.MODES.ANALOG
1182 );
1183
1184 this.analogPins.push(i);
1185
1186 // Default all analog IO pins to
1187 // ANALOG "read"
1188 this.pinMode("A" + this.pins[i].analogChannel, this.MODES.ANALOG);
1189 } else {
1190 // Default all digital IO pins to
1191 // OUTPUT and LOW
1192 this.pinMode("D" + i, this.MODES.OUTPUT);
1193 this.digitalWrite("D" + i, this.LOW);
1194 }
1195 }
1196 }
1197
1198 this.name = "GROVEPI";
1199 this.isReady = true;
1200
1201 this.emit("connect");
1202 this.emit("ready");
1203 }
1204 },
1205 normalize: {
1206 value: function(pin) {
1207 return pin;
1208 }
1209 },
1210
1211 pinMode: {
1212 value: function(pin, mode) {
1213 var state = priv.get(this);
1214 var pinIndex = state.pinMap[pin];
1215
1216 if (mode === this.io.MODES.INPUT ||
1217 mode === this.io.MODES.ANALOG) {
1218 this.pins[pinIndex].mode = 0;
1219 } else {
1220 this.pins[pinIndex].mode = 1;
1221 }
1222
1223 this.io.i2cWrite(
1224 this.address, [
1225 this.COMMANDS.PIN_MODE,
1226 pinIndex,
1227 this.pins[pinIndex].mode,
1228 0
1229 ]
1230 );
1231 }
1232 },
1233
1234 digitalWrite: {
1235 value: function(pin, value) {
1236 var state = priv.get(this);
1237 var pinIndex = state.pinMap[pin];
1238
1239 // Any truthy value is converted to HIGH (1)
1240 value = value ? 1 : 0;
1241
1242 this.io.i2cWrite(
1243 this.address, [
1244 this.COMMANDS.DIGITAL_WRITE,
1245 pinIndex,
1246 value,
1247 0
1248 ]
1249 );
1250
1251 this.pins[pinIndex].value = value;
1252 }
1253 },
1254
1255 ioRead: {
1256 value: function(pin, type, callback) {
1257 var state = priv.get(this);
1258 var pinIndex = state.pinMap[pin];
1259 var isAnalog = type === "analog";
1260 var length = isAnalog ? 3 : 1;
1261 var command = isAnalog ? this.COMMANDS.ANALOG_READ : this.COMMANDS.DIGITAL_READ;
1262
1263 this.on(type + "-read-" + pinIndex, callback);
1264
1265 this.pins[pinIndex].report = 1;
1266 this.pins[pinIndex].command = command;
1267 this.pins[pinIndex].type = type;
1268 this.pins[pinIndex].length = length;
1269
1270 var nextPinIndex = function() {
1271 var startAt = nextPinIndex.lastPinIndex + 1;
1272
1273 for (var i = startAt; i < this.pins.length; i++) {
1274 if (this.pins[i].report === 1) {
1275 nextPinIndex.lastPinIndex = i;
1276 return nextPinIndex.lastPinIndex;
1277 }
1278 }
1279
1280 nextPinIndex.lastPinIndex = -1;
1281
1282 return nextPinIndex();
1283 }.bind(this);
1284
1285 nextPinIndex.lastPinIndex = -1;
1286
1287 var handler = function(pinIndex, value) {
1288 var pin = this.pins[pinIndex];
1289 var canEmit = true;
1290
1291 if (pin.type === "digital" && this.pins[pinIndex].value === value) {
1292 canEmit = false;
1293 }
1294
1295 this.pins[pinIndex].value = value;
1296
1297 if (canEmit) {
1298 this.emit(pin.type + "-read-" + pinIndex, value);
1299 }
1300
1301 setTimeout(read, 1);
1302 }.bind(this);
1303
1304 var read = function() {
1305 var pinIndex = nextPinIndex();
1306 var pin = this.pins[pinIndex];
1307 var isAnalog = pin.type === "analog";
1308
1309 this.io.i2cWrite(this.address, [pin.command, pinIndex, 0, 0]);
1310 this.io.i2cReadOnce(this.address, pin.length, function(data) {
1311 var value;
1312
1313 if (isAnalog) {
1314 value = (data[1] << 8) + data[2];
1315 } else {
1316 value = data[0];
1317 }
1318 handler(pinIndex, value);
1319 }.bind(this));
1320 }.bind(this);
1321
1322 if (!state.isReading) {
1323 state.isReading = true;
1324 read();
1325 }
1326 }
1327 },
1328
1329 digitalRead: {
1330 value: function(pin, callback) {
1331 this.ioRead(pin, "digital", callback);
1332 },
1333 },
1334 analogRead: {
1335 value: function(pin, callback) {
1336 this.ioRead(pin, "analog", callback);
1337 },
1338 },
1339 pingRead: {
1340 value: function(settings, callback) {
1341 var state = priv.get(this);
1342 var pinIndex = state.pinMap[settings.pin];
1343
1344 this.io.i2cWrite(
1345 this.address, [
1346 this.COMMANDS.PING_READ,
1347 pinIndex,
1348 0, 0
1349 ]
1350 );
1351
1352 setTimeout(function() {
1353 this.once("ping-read-" + settings.pin, callback);
1354
1355 this.io.i2cReadOnce(this.address, 3, function(data) {
1356 // The GrovePi firmware sends this value in CM
1357 // so the value must be converted back to duration.
1358 var value = Math.round(((data[1] << 8) + data[2]) * 29 * 2);
1359
1360 this.pins[pinIndex].value = value;
1361 this.emit("ping-read-" + settings.pin, value);
1362 }.bind(this));
1363 }.bind(this), 200);
1364 },
1365 },
1366 analogWrite: {
1367 value: function(pin, value) {
1368 this.pwmWrite(pin, value);
1369 }
1370 },
1371 pwmWrite: {
1372 writable: true,
1373 value: function(pin, value) {
1374 var state = priv.get(this);
1375 var pinIndex = state.pinMap[pin];
1376
1377 value = Board.constrain(value, 0, 255);
1378
1379 this.io.i2cWrite(
1380 this.address, [
1381 this.COMMANDS.ANALOG_WRITE,
1382 pinIndex,
1383 value,
1384 0
1385 ]
1386 );
1387
1388 this.pins[pinIndex].value = value;
1389 }
1390 }
1391 },
1392 "74HC595": {
1393 initialize: {
1394 value: function(opts) {
1395 var state = priv.get(this);
1396
1397 if (!opts.pins.data) {
1398 throw new Error("Expected pins.data");
1399 }
1400
1401 if (!opts.pins.clock) {
1402 throw new Error("Expected pins.clock");
1403 }
1404
1405 if (!opts.pins.latch) {
1406 throw new Error("Expected pins.latch");
1407 }
1408
1409 state.data = opts.pins.data;
1410 state.clock = opts.pins.clock;
1411 state.latch = opts.pins.latch;
1412 state.value = 0x00;
1413
1414 Object.assign(this.MODES, this.io.MODES);
1415
1416 // Reset pins property to empty array.
1417 this.pins = [];
1418
1419 for (var i = 0; i < 8; i++) {
1420 this.pins.push({
1421 supportedModes: [
1422 this.MODES.OUTPUT
1423 ],
1424 mode: 1,
1425 value: 0,
1426 report: 0,
1427 analogChannel: 127
1428 });
1429 }
1430
1431 this.portWrite(0, state.value);
1432
1433 this.name = "74HC595";
1434 this.isReady = true;
1435
1436 this.emit("connect");
1437 this.emit("ready");
1438 }
1439 },
1440 normalize: {
1441 value: function(pin) {
1442 return pin;
1443 }
1444 },
1445 pinMode: {
1446 value: function(pin, mode) {
1447 this.pins[pin].mode = mode;
1448 }
1449 },
1450 digitalWrite: {
1451 value: function(pin, value) {
1452 var state = priv.get(this);
1453
1454 if (value) {
1455 state.value |= 1 << pin;
1456 } else {
1457 state.value &= ~(1 << pin);
1458 }
1459
1460 this.pins[pin].value = value;
1461
1462 this.portWrite(0, state.value);
1463 }
1464 },
1465 portWrite: {
1466 writable: true,
1467 configurable: true,
1468 value: function(port, value) {
1469 var state = priv.get(this);
1470
1471 state.value = value;
1472
1473 this.board.digitalWrite(state.latch, this.io.LOW);
1474 this.board.shiftOut(state.data, state.clock, true, state.value);
1475 this.board.digitalWrite(state.latch, this.io.HIGH);
1476
1477 for (var i = 0; i < 8; i++) {
1478 this.pins[i].value = (state.value >> i) & 1;
1479 }
1480 }
1481 },
1482 },
1483 CD74HC4067: {
1484 /*
1485 | Address 1 (D9) | Address 0 (D8) | Address |
1486 | -------------- | -------------- | ------- |
1487 | 0 | 0 | 0x0A |
1488 | 0 | 1 | 0x0B |
1489 | 1 | 0 | 0x0C |
1490 | 1 | 1 | 0x0D |
1491 */
1492 ADDRESSES: {
1493 value: [0x0A, 0x0B, 0x0C, 0x0D]
1494 },
1495 REGISTER: {},
1496 initialize: {
1497 value: function(opts) {
1498 var state = priv.get(this);
1499
1500 state.reading = false;
1501
1502 this.address = opts.address || this.ADDRESSES[0];
1503
1504 opts.address = this.address;
1505 this.io.i2cConfig(opts);
1506
1507 Object.assign(this.MODES, this.io.MODES);
1508
1509 for (var i = 0; i < 16; i++) {
1510 this.pins.push({
1511 supportedModes: [
1512 this.MODES.ANALOG
1513 ],
1514 mode: 1,
1515 value: 0,
1516 report: 0,
1517 analogChannel: i
1518 });
1519 this.analogPins.push(i);
1520 }
1521
1522 this.name = "CD74HC4067";
1523 this.isReady = true;
1524
1525 this.emit("connect");
1526 this.emit("ready");
1527 }
1528 },
1529 normalize: {
1530 value: function(pin) {
1531 if (typeof pin === "string" && pin[0] === "A") {
1532 return +pin.slice(1);
1533 }
1534 return pin;
1535 }
1536 },
1537 pinMode: {
1538 value: function(pin, mode) {
1539 this.pins[pin].mode = mode;
1540 }
1541 },
1542 analogRead: {
1543 value: function(pin, callback) {
1544 var state = priv.get(this);
1545 var pinIndex = pin;
1546
1547 this.pins[pinIndex].report = 1;
1548
1549 this.on("analog-read-" + pin, callback);
1550
1551 this.io.i2cWrite(this.address, pinIndex, 1);
1552
1553 // Since this operation will read all 4 pins,
1554 // it only needs to be initiated once.
1555 if (!state.reading) {
1556 state.reading = true;
1557
1558 this.io.i2cRead(this.address, 32, function(data) {
1559 var value;
1560 for (var i = 0; i < 16; i++) {
1561 var index = i * 2;
1562
1563 value = (data[index] << 8) + data[index + 1];
1564
1565 this.pins[i].value = value;
1566
1567 if (this.pins[i].report) {
1568 this.emit("analog-read-" + i, value);
1569 }
1570 }
1571 }.bind(this));
1572 }
1573 }
1574 },
1575 },
1576
1577 LIS3DH: {
1578 ADDRESSES: {
1579 value: [0x18]
1580 },
1581 REGISTER: {
1582 value: {
1583 // Page 26
1584 // Table 17. Register address map
1585 //
1586 // NAME: BYTE
1587 OUT_ADC1_L: 0x08,
1588 OUT_X_L: 0x28,
1589 CTRL_REG1: 0x20,
1590 CTRL_REG2: 0x21,
1591 CTRL_REG3: 0x22,
1592 CTRL_REG4: 0x23,
1593 CTRL_REG5: 0x24,
1594
1595 TEMP_CFG_REG: 0x1F,
1596 },
1597 },
1598 initialize: {
1599 value: function(opts) {
1600 var state = priv.get(this);
1601
1602 state.reading = false;
1603
1604 this.address = opts.address || this.ADDRESSES[0];
1605
1606 opts.address = this.address;
1607
1608 this.io.i2cConfig(opts);
1609
1610
1611 // Page 29
1612 // 8.8 CTRL_REG1
1613 // Table 24. CTRL_REG1 register
1614 //
1615 // ODR3 ODR2 ODR1 ODR0 LPen Zen Yen Xen
1616 //
1617 //
1618 // Enable Axis
1619 // 0b00000111
1620 // ZYX
1621 //
1622 var ctrl1 = 0x07; // 0b00000111
1623 //
1624 // Date Rate
1625 // Table 26. Data rate configuration
1626 //
1627 // ODR3 ODR2 ODR1 ODR0 Power mode selection
1628 // 0 0 0 1 = 1 Hz
1629 // 0 0 1 0 = 10 Hz
1630 // 0 0 1 1 = 25 Hz
1631 // 0 1 0 0 = 50 Hz
1632 // 0 1 0 1 = 100 Hz
1633 // 0 1 1 0 = 200 Hz
1634 // 0 1 1 1 = 400 Hz
1635 //
1636 // 0b0111 << 4 = 0b01110000
1637 //
1638 ctrl1 = (ctrl1 & ~(0xF0)) | (0x07 << 4);
1639
1640 // ctrl1 = 0b01110111
1641 // 0b01110000 = 0x70 = 112
1642 this.io.i2cWrite(this.address, this.REGISTER.CTRL_REG1, ctrl1);
1643
1644 // Page 31
1645 // 8.11 CTRL_REG4
1646 //
1647 // Table 32. CTRL_REG4 register
1648 //
1649 // BDU BLE FS1 FS0 HR ST1 ST0 SIM
1650 //
1651 // BDU Block data update. Default value: 0
1652 // 0: Continuous update
1653 // 1: Updated when MSB and LSB read
1654 //
1655 // HR High resolution output mode: Default value: 0
1656 // 0: Disable
1657 // 1: Enable
1658 //
1659 // Setting BDU and HR:
1660 // 0b1---1---
1661 //
1662 // 0b10001000 = 0x88 = 136
1663 //
1664 this.io.i2cWrite(this.address, this.REGISTER.CTRL_REG4, 0x88);
1665 //
1666 // Page 31
1667 // 8.10 CTRL_REG3
1668 //
1669 // I1_DRDY1 -> ON
1670 //
1671 // 0b00010000 = 0x10 = 16
1672 this.io.i2cWrite(this.address, this.REGISTER.CTRL_REG3, 0x10);
1673
1674 Object.assign(this.MODES, this.io.MODES);
1675
1676 for (var i = 0; i < 4; i++) {
1677 if (i === 0) {
1678 this.pins.push({
1679 supportedModes: [],
1680 mode: 0,
1681 value: 0,
1682 report: 0,
1683 analogChannel: 0x7F
1684 });
1685 } else {
1686 this.pins.push({
1687 supportedModes: [ this.MODES.ANALOG ],
1688 mode: 1,
1689 value: 0,
1690 report: 0,
1691 analogChannel: i
1692 });
1693 this.analogPins.push(i);
1694 }
1695 }
1696
1697 this.name = "LIS3DH";
1698 this.isReady = true;
1699
1700 this.emit("connect");
1701 this.emit("ready");
1702 },
1703 },
1704 normalize: {
1705 value: function(pin) {
1706 if (typeof pin === "string" && pin[0] === "A") {
1707 return +pin.slice(1);
1708 }
1709 return pin;
1710 },
1711 },
1712 pinMode: {
1713 value: function(pin, mode) {
1714 this.pins[pin].mode = mode;
1715 },
1716 },
1717 analogRead: {
1718 value: function(pin, callback) {
1719 var state = priv.get(this);
1720 var pinIndex = pin;
1721
1722 this.pins[pinIndex].report = 1;
1723
1724 this.on("analog-read-" + pin, callback);
1725
1726 // Since this operation will read all 3 ADC pins,
1727 // it only needs to be initiated once.
1728 if (!state.reading) {
1729 state.reading = true;
1730
1731 // Page 29
1732 // 8.7 TEMP_CFG_REG (1Fh)
1733 // Table 23. TEMP_CFG_REG description
1734 //
1735 // ADC_PD TEMP_EN 0 0 0 0 0 0
1736 //
1737 // 0b10000000 = 128 = 0x80
1738 //
1739 this.io.i2cWrite(this.address, this.REGISTER.TEMP_CFG_REG, 0x80);
1740
1741 // Page 23, 24, 25
1742 // bit 1: MS bit. When 0, the address remains unchanged in multiple read/write commands.
1743 // When 1, the address is auto incremented in multiple read/write commands.
1744 this.io.i2cRead(this.address, this.REGISTER.OUT_ADC1_L | 0x80, 6, function(data) {
1745 // V range is 900
1746
1747 // First, scale the value to range that these ADCs support, which is
1748 //
1749 // 1.8V - 0.9V
1750 //
1751 // Then, scale that value to the full 10-bit 0-3.3V range
1752 //
1753 this.pins[1].value = Fn.scale(Fn.int16(data[1], data[0]), -32512, 32512, 1023, 0);
1754 this.pins[2].value = Fn.scale(Fn.int16(data[3], data[2]), -32512, 32512, 1023, 0);
1755 this.pins[3].value = Fn.scale(Fn.int16(data[5], data[4]), -32512, 32512, 1023, 0);
1756
1757 for (var i = 1; i < 4; i++) {
1758 if (this.pins[i].report) {
1759 this.emit("analog-read-" + i, this.pins[i].value);
1760 }
1761 }
1762 }.bind(this));
1763 }
1764 },
1765 },
1766 i2cConfig: {
1767 value: function() {
1768 return this.io.i2cConfig.apply(this.io, arguments);
1769 },
1770 },
1771 i2cWrite: {
1772 value: function() {
1773 return this.io.i2cWrite.apply(this.io, arguments);
1774 },
1775 },
1776 i2cWriteReg: {
1777 value: function() {
1778 return this.io.i2cWriteReg.apply(this.io, arguments);
1779 },
1780 },
1781 i2cRead: {
1782 value: function() {
1783 return this.io.i2cRead.apply(this.io, arguments);
1784 },
1785 },
1786 i2cReadOnce: {
1787 value: function() {
1788 return this.io.i2cReadOnce.apply(this.io, arguments);
1789 },
1790 },
1791 },
1792
1793 ADS1115: {
1794 ADDRESSES: {
1795 value: [0x48, 0x49, 0x4A, 0x4B]
1796 },
1797 REGISTER: {
1798 value: {
1799 CONFIG: 0x01,
1800 READ: 0x00,
1801 PIN: [0xC1, 0xD1, 0xE1, 0xF1],
1802 PIN_DATA: 0x83,
1803 }
1804 },
1805 initialize: {
1806 value: function(opts) {
1807 var state = priv.get(this);
1808
1809 state.reading = false;
1810
1811 this.address = opts.address || this.ADDRESSES[0];
1812
1813 opts.address = this.address;
1814 this.io.i2cConfig(opts);
1815
1816 Object.assign(this.MODES, this.io.MODES);
1817
1818 for (var i = 0; i < 4; i++) {
1819 this.pins.push({
1820 supportedModes: [
1821 this.MODES.ANALOG
1822 ],
1823 mode: 1,
1824 value: 0,
1825 report: 0,
1826 analogChannel: i
1827 });
1828 this.analogPins.push(i);
1829 }
1830
1831 this.name = "ADS1115";
1832 this.isReady = true;
1833
1834 this.emit("connect");
1835 this.emit("ready");
1836 }
1837 },
1838 normalize: {
1839 value: function(pin) {
1840 if (typeof pin === "string" && pin[0] === "A") {
1841 return +pin.slice(1);
1842 }
1843 return pin;
1844 }
1845 },
1846 pinMode: {
1847 value: function(pin, mode) {
1848 this.pins[pin].mode = mode;
1849 }
1850 },
1851 analogRead: {
1852 value: function(pin, callback) {
1853 var state = priv.get(this);
1854 this.pins[pin].report = 1;
1855
1856 var ready = false;
1857
1858 this.on("analog-read-" + pin, callback);
1859
1860 // Since this operation will read all 4 pins,
1861 // it only needs to be initiated once.
1862 if (!state.reading) {
1863 state.reading = true;
1864
1865 // CONVERSION DELAY
1866 var delay = function () {
1867 setTimeout(function () {
1868 ready = true;
1869 }, 8);
1870 };
1871
1872 this.io.i2cWrite(this.address, this.REGISTER.CONFIG, [this.REGISTER.PIN[pin], this.REGISTER.PIN_DATA]);
1873 delay();
1874
1875 this.io.i2cRead(this.address, this.REGISTER.READ, 2, function(data) {
1876 if (ready) {
1877 ready = false;
1878
1879 var newPin = pin === this.pins.length - 1 ? 0 : pin + 1;
1880
1881 this.io.i2cWrite(this.address, this.REGISTER.CONFIG, [this.REGISTER.PIN[newPin], this.REGISTER.PIN_DATA]);
1882
1883 var value = (data[0] << 8) + data[1];
1884 this.pins[pin].value = value;
1885
1886 if (this.pins[pin].report) {
1887 this.emit("analog-read-" + pin, value);
1888 }
1889
1890 pin = newPin;
1891
1892 delay();
1893 }
1894 }.bind(this));
1895 }
1896 }
1897 },
1898 }
1899};
1900
1901Controllers["CD74HCT4067"] = Controllers.CD74HC4067;
1902Controllers["74HC4067"] = Controllers.CD74HC4067;
1903
1904Controllers.PCF8574A = Object.assign({}, Controllers.PCF8574, {
1905 ADDRESSES: {
1906 value: [0x38]
1907 }
1908});
1909
1910var methods = Object.keys(Board.prototype);
1911
1912Object.keys(Controllers).forEach(function(name) {
1913 methods.forEach(function(key) {
1914 if (Controllers[name][key] === undefined) {
1915 Controllers[name][key] = {
1916 writable: true,
1917 configurable: true,
1918 value: function() {
1919 throw new Error("Expander:" + name + " does not support " + key);
1920 }
1921 };
1922 }
1923 });
1924});
1925
1926var nonAddressable = [
1927 "74HC595"
1928];
1929
1930function Expander(opts) {
1931 if (!(this instanceof Expander)) {
1932 return new Expander(opts);
1933 }
1934
1935 Base.call(this);
1936
1937 var expander = null;
1938 var addressError = "Expander cannot reuse an active address";
1939 var controller = null;
1940 var state = {};
1941 var controllerValue;
1942
1943 if (typeof opts === "string") {
1944 controllerValue = opts;
1945 }
1946
1947 Board.Component.call(
1948 this, opts = Board.Options(opts), {
1949 normalizePin: false,
1950 requestPin: false
1951 }
1952 );
1953
1954 if (nonAddressable.includes(opts.controller) &&
1955 typeof this.address === "undefined") {
1956 this.address = Fn.uid();
1957 }
1958
1959 expander = active.get(this.address);
1960
1961 if (expander) {
1962 if (this.bus && (expander.bus !== undefined && expander.bus === this.bus)) {
1963 addressError += " on this bus";
1964 }
1965 throw new Error(addressError);
1966 }
1967
1968 if (typeof opts.controller === "undefined" && controllerValue) {
1969 opts.controller = controllerValue;
1970 }
1971
1972 if (opts.controller && typeof opts.controller === "string") {
1973 controller = Controllers[opts.controller.toUpperCase()];
1974 } else {
1975 controller = opts.controller;
1976 }
1977
1978 if (controller == null) {
1979 throw new Error("Expander expects a valid controller");
1980 }
1981
1982 Board.Controller.call(this, controller, opts);
1983
1984 priv.set(this, state);
1985
1986 if (typeof this.initialize === "function") {
1987 this.initialize(opts);
1988 }
1989
1990 active.set(this.address, this);
1991}
1992
1993util.inherits(Expander, Base);
1994
1995
1996Expander.get = function(required) {
1997
1998 if (!required.address || !required.controller) {
1999 throw new Error("Expander.get(...) requires an address and controller");
2000 }
2001
2002 if (required.address !== undefined) {
2003 required.address = Number(required.address);
2004 }
2005
2006 if (Number.isNaN(required.address)) {
2007 throw new Error("Expander.get(...) expects address to be a number");
2008 }
2009
2010 if (typeof required.controller !== "string") {
2011 throw new Error("Expander.get(...) expects controller name to be a string");
2012 }
2013
2014 // If no address was sent them assume the request wants
2015 // to re-use an active Expander, by controller name.
2016 // if (!required.address) {
2017 // return Expander.byController(required.controller);
2018 // }
2019
2020 var expander = active.get(required.address);
2021
2022 if (expander && (expander.name === required.controller.toUpperCase())) {
2023 return expander;
2024 }
2025
2026 return new Expander(required);
2027};
2028
2029Expander.byAddress = function(address) {
2030 return active.get(address);
2031};
2032
2033Expander.byController = function(name) {
2034 var controller = null;
2035
2036 active.forEach(function(value) {
2037 if (value.name === name.toUpperCase()) {
2038 controller = value;
2039 }
2040 });
2041 return controller;
2042};
2043
2044Expander.hasController = function(key) {
2045 return Controllers[key] !== undefined;
2046};
2047
2048/* istanbul ignore else */
2049if (!!process.env.IS_TEST_MODE) {
2050 Expander.Controllers = Controllers;
2051 Expander.purge = function() {
2052 priv.clear();
2053 active.clear();
2054 };
2055}
2056
2057module.exports = Expander;