1 | var Options = require("./board.options");
|
2 |
|
3 | var MODES = {
|
4 | INPUT: 0x00,
|
5 | OUTPUT: 0x01,
|
6 | ANALOG: 0x02,
|
7 | PWM: 0x03,
|
8 | SERVO: 0x04
|
9 | };
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | var pinsToType = {
|
17 | 20: "UNO",
|
18 | 25: "LEONARDO",
|
19 | 70: "MEGA"
|
20 | };
|
21 |
|
22 | function Pins(board) {
|
23 | if (!(this instanceof Pins)) {
|
24 | return new Pins(board);
|
25 | }
|
26 |
|
27 | var io = board.io;
|
28 | var pins = io.pins.slice();
|
29 | var length = pins.length;
|
30 | var type = pinsToType[length] || "OTHER";
|
31 |
|
32 | board.type = type;
|
33 |
|
34 |
|
35 | for (var i = 0; i < length; i++) {
|
36 | this[i] = pins[i];
|
37 | }
|
38 |
|
39 | Object.defineProperties(this, {
|
40 | type: {
|
41 | value: type
|
42 | },
|
43 | length: {
|
44 | value: length
|
45 | }
|
46 | });
|
47 |
|
48 |
|
49 |
|
50 | [
|
51 | "isInput",
|
52 | "isOutput",
|
53 | "isAnalog",
|
54 | "isPwm",
|
55 | "isServo",
|
56 | ].forEach(function(isType) {
|
57 | if (io[isType]) {
|
58 | this[isType] = io[isType];
|
59 | }
|
60 | }, this);
|
61 | }
|
62 |
|
63 | Object.keys(MODES).forEach(function(mode) {
|
64 | Object.defineProperty(Pins, mode, {
|
65 | value: MODES[mode]
|
66 | });
|
67 | });
|
68 |
|
69 | function isFirmata(board) {
|
70 | return board.io.name === "Firmata" || board.io.name === "Mock";
|
71 | }
|
72 |
|
73 | function hasPins(opts) {
|
74 | return typeof opts.pin !== "undefined" ||
|
75 | (typeof opts.pins !== "undefined" && opts.pins.length);
|
76 | }
|
77 |
|
78 | Pins.isFirmata = isFirmata;
|
79 |
|
80 | Pins.Error = function(opts) {
|
81 | throw new Error(
|
82 | "Pin Error: " + opts.pin +
|
83 | " is not a valid " + opts.type +
|
84 | " pin (" + opts.via + ")"
|
85 | );
|
86 | };
|
87 |
|
88 | var normalizers = new Map();
|
89 |
|
90 | Pins.normalize = function(opts, board) {
|
91 | var type = board.pins.type;
|
92 | var isArduino = isFirmata(board);
|
93 | var normalizer = normalizers.get(board);
|
94 | var isNormalizing;
|
95 |
|
96 | if (typeof opts === "string" ||
|
97 | typeof opts === "number" ||
|
98 | Array.isArray(opts)) {
|
99 |
|
100 | opts = new Options(opts);
|
101 | }
|
102 |
|
103 | if (!normalizer) {
|
104 | isNormalizing = board.io && typeof board.io.normalize === "function";
|
105 |
|
106 | normalizer = function(pin) {
|
107 | return isArduino ?
|
108 | Pins.fromAnalog(Pins.translate(pin, type)) :
|
109 | (isNormalizing ? board.io.normalize(pin) : pin);
|
110 | };
|
111 |
|
112 | normalizers.set(board, normalizer);
|
113 | }
|
114 |
|
115 |
|
116 |
|
117 | if (hasPins(opts)) {
|
118 |
|
119 |
|
120 |
|
121 | if (opts.pins) {
|
122 | opts.pins = opts.pins.map(normalizer);
|
123 | } else {
|
124 | opts.pin = normalizer(opts.pin);
|
125 | }
|
126 | }
|
127 |
|
128 | return opts;
|
129 | };
|
130 |
|
131 | Pins.normalize.clear = function() {
|
132 | normalizers.clear();
|
133 | };
|
134 |
|
135 |
|
136 | Pins.translations = {
|
137 | UNO: {
|
138 | dtoa: {
|
139 | 14: "A0",
|
140 | 15: "A1",
|
141 | 16: "A2",
|
142 | 17: "A3",
|
143 | 18: "A4",
|
144 | 19: "A5"
|
145 | },
|
146 |
|
147 |
|
148 | tinker: {
|
149 | I0: "A0",
|
150 | I1: "A1",
|
151 | I2: "A2",
|
152 | I3: "A3",
|
153 | I4: "A4",
|
154 | I5: "A5",
|
155 |
|
156 | O0: 11,
|
157 | O1: 10,
|
158 | O2: 9,
|
159 | O3: 6,
|
160 | O4: 5,
|
161 | O5: 3,
|
162 |
|
163 | D13: 13,
|
164 | D12: 12,
|
165 | D8: 8,
|
166 | D7: 7,
|
167 | D4: 4,
|
168 | D2: 2
|
169 | }
|
170 | },
|
171 | MEGA: {
|
172 | dtoa: {
|
173 | 54: "A0",
|
174 | 55: "A1",
|
175 | 56: "A2",
|
176 | 57: "A3",
|
177 | 58: "A4",
|
178 | 59: "A5",
|
179 | 60: "A6",
|
180 | 61: "A7",
|
181 | 62: "A8",
|
182 | 63: "A9"
|
183 | },
|
184 |
|
185 |
|
186 | tinker: {
|
187 | I0: "A0",
|
188 | I1: "A1",
|
189 | I2: "A2",
|
190 | I3: "A3",
|
191 | I4: "A4",
|
192 | I5: "A5",
|
193 | I6: "A6",
|
194 | I7: "A7",
|
195 | I8: "A8",
|
196 | I9: "A9",
|
197 |
|
198 | O0: 11,
|
199 | O1: 10,
|
200 | O2: 9,
|
201 | O3: 6,
|
202 | O4: 5,
|
203 | O5: 3,
|
204 |
|
205 | D13: 13,
|
206 | D12: 12,
|
207 | D8: 8,
|
208 | D7: 7,
|
209 | D4: 4,
|
210 | D2: 2
|
211 | }
|
212 | }
|
213 | };
|
214 |
|
215 | Pins.translations.LEONARDO = Pins.translations.UNO;
|
216 |
|
217 | Pins.translate = function(pin, type) {
|
218 | var translations = Pins.translations[type.toUpperCase()];
|
219 |
|
220 | if (!translations) {
|
221 | return pin;
|
222 | }
|
223 |
|
224 | return Object.keys(translations).reduce(function(pin, map) {
|
225 | return translations[map][pin] || pin;
|
226 | }, pin);
|
227 | };
|
228 |
|
229 | Pins.fromAnalog = function(pin) {
|
230 | if (typeof pin === "string" && pin[0] === "A") {
|
231 | return parseInt(pin.slice(1), 10);
|
232 | }
|
233 | return pin;
|
234 | };
|
235 |
|
236 | Pins.identity = function(pins, needle) {
|
237 | return [].findIndex.call(pins, function(pin) {
|
238 | return pin.name === needle || pin.id === needle || pin.port === needle;
|
239 | });
|
240 | };
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 | Object.keys(MODES).forEach(function(key) {
|
253 | var name = key[0] + key.slice(1).toLowerCase();
|
254 |
|
255 | Pins.prototype["is" + name] = function(pin) {
|
256 | var attrs = this[pin] || this[Pins.identity(this, pin)];
|
257 |
|
258 | if (attrs && attrs.supportedModes.includes(MODES[key])) {
|
259 | return true;
|
260 | }
|
261 | return false;
|
262 | };
|
263 | });
|
264 |
|
265 | Pins.prototype.isDigital = function(pin) {
|
266 | var attrs = this[pin] || this[Pins.identity(this, pin)];
|
267 |
|
268 | if (attrs && attrs.supportedModes.length) {
|
269 | return true;
|
270 | }
|
271 | return false;
|
272 | };
|
273 |
|
274 | module.exports = Pins;
|