-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
245 lines (214 loc) · 7.66 KB
/
index.js
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// Copyright 2015 Alain Owen Kuchta See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
var TNode = require('./lib/TNode.js'), // This
util = require('util'),
EventEmitter = require('events').EventEmitter,
Commands,
Trellis; // The module function
/**
* The commands used to communicate with the HT16K33
*/
Commands = {
DEV_ADDR: 0x70,
OSC_ON: 0x21,
DISP_ON: 0x81,
INT_ON_ACT_HI: 0xA3,
READ_BTN: 0x40
};
/**
* This function creates a new Trellis object
*/
Trellis = function Trellis(port, interrupt_enable) {
var trellis = new EventEmitter(), // For public interface, errors, etc
_trellis = {}; // For internal data
//
// Initialization
//
// Setup default options
trellis.setMaxListeners(20);
_trellis.pub = trellis;
_trellis.port = port;
_trellis.dispBuf = new Buffer(17);
_trellis.dispBuf.fill(0);
// The device i2c address
_trellis.i2c = new port.I2C(Commands.DEV_ADDR);
_trellis.interrupts = !!interrupt_enable;
// Device connection
/**
* Build up the matrix of nodes
*/
_trellis.nodes = [
[TNode(0x72, 0x07, _trellis), TNode(0x67, 0x04, _trellis), TNode(0x65, 0x02, _trellis), TNode(0x64, 0x22, _trellis)],
[TNode(0x50, 0x05, _trellis), TNode(0x51, 0x00, _trellis), TNode(0x43, 0x00, _trellis), TNode(0x44, 0x01, _trellis)],
[TNode(0x26, 0x03, _trellis), TNode(0x33, 0x10, _trellis), TNode(0x21, 0x30, _trellis), TNode(0x20, 0x21, _trellis)],
[TNode(0x16, 0x13, _trellis), TNode(0x15, 0x12, _trellis), TNode(0x14, 0x11, _trellis), TNode(0x02, 0x31, _trellis)]
];
/**
* Read the key data and store it in the btn buffer. This is called whenever an interrupt is raised
* NOTE: The key data was be read entirely in order for the inerrupt flag to be reset
*/
_trellis.readKeyData = function(cause) {
_trellis.i2c.transfer(new Buffer([Commands.READ_BTN]), 6, function(err, rx) {
if (err) {
trellis.emit("error", err);
return;
}
_trellis.btnBuf = rx;
trellis.emit('keydata');
trellis.emit(cause);
});
}; // end read key data
_trellis.buttonValueCached = function buttonValueCached(addr) {
var mask;
mask = (1 << (addr & 0x0F)); // Use the lower half othe address as a mask to choose just one bit
return (_trellis.btnBuf[(addr >> 4)] & mask);
};
/**
*
*/
_trellis.buttonValue = function buttonValue(addr, callback) {
var mask;
mask = (1 << (addr & 0x0F)); // Use the lower half othe address as a mask to choose just one bit
// If interrupts are enabled, the key data was already read and stored in btnBuf
if (_trellis.interrupts) {
callback(_trellis.btnBuf[(addr >> 4)] & mask);
// If interrupts are NOT enabled, the key data must be read on demand.
} else {
// Setup a one-time event handler for grabbing the button value
_trellis.pub.once('keydata', function() {
// Get 1 byte from the buffer and mask it, if the result equals the mask, the button is on
if (_trellis.btnBuf[(addr >> 4)] & mask) {
callback(1);
} else {
callback(0);
}
});
// Initate key data read
_trellis.readKeyData();
}
}; // end buttonValue
/**
*
*/
_trellis.outputLed = function outputLed(ledAddr, value) {
var bufferOffset, // which byte in the offset to we need to change?
currentByte; // the current byte which we are working on
bufferOffset = 1 + (ledAddr >> 4); // Use the top 4 bites of the address to index into the buffer
bytes = _trellis.dispBuf.readUInt8(bufferOffset); // Read 1 byte from that location in the buffer
if (value) { // LED should be on
bytes |= (1 << (0x0F & ledAddr)); // Use the bottom 4 bits of the address to choose 1 bit to toggle in the byte
} else { // LED should be off
bytes &= ~(1 << (0x0F & ledAddr)); // Use the buttom 4 bits of the address to choose 1 bite toggle in the byte
}
_trellis.dispBuf.writeUInt8(bytes, bufferOffset); // Write the byte back into the buffer
_trellis.i2c.send(_trellis.dispBuf); // Send the whole buffer, including the display pointer command as the first byte
}; // end outputLed
/**
* Called to setup the actual connection to the HT16K33
*/
trellis.ready = function ready(callback) {
_trellis.i2c.send(new Buffer([Commands.OSC_ON]), function(err1) { // Turn on system oscillator
if (err1) {
trellis.emit('error', err1);
return;
}
_trellis.i2c.send(new Buffer([Commands.DISP_ON]), function(err2) { // Turn on display no blink
if (err2) {
trellis.emit('error', err2);
return;
}
_trellis.i2c.send(new Buffer([Commands.INT_ON_ACT_HI]), function(err3) { // Turn on Interrupts, with the interrupt pin being active high
if (err3) {
trellis.emit('error', err3);
return;
}
if (_trellis.interrupts) {
_trellis.port.digital[0].input();
// Initial read to ensure that interrupt is cleared
trellis.once('keydata', function() {
_trellis.port.digital[0].on('rise', function() {
_trellis.readKeyData('press');
}); // end on rise
_trellis.port.digital[0].on('fall', function() {
_trellis.readKeyData('release');
});
}); // end button once
_trellis.readKeyData();
callback();
} // end if interrupts
}); // end send INT_ON
}); // end send DISP_ON
}); // end send OSC_ON
}; // end ready
/**
* Retrieve the port that the module is using.
*/
trellis.port = function port() {
return _trellis.port;
};
/**
* Grab a specific LED
*/
trellis.led = function led(row, col) {
if (row + col > 6 || row + col < 0 ) {
throw new Error("Index Error: (" + row + "," + col + ") is not a valid index.");
}
return _trellis.nodes[row][ col].led;
};
/**
* Grab a specific Button
*/
trellis.button = function button(row, col) {
if (row + col > 6 || row + col < 0 ) {
throw new Error("Index Error: (" + row + "," + col + ") is not a valid index.");
}
return _trellis.nodes[row][col].button;
};
/**
* Grab a node (button-led pair)
*/
trellis.node = function node(row, col) {
if (row + col > 6 || row + col < 0 ) {
throw new Error("Index Error: (" + row + "," + col + ") is not a valid index.");
}
return _trellis.nodes[row][col];
};
/**
* Set the brightness of the display
* Levels: - 0 (dimmest) to 7 (brightest)
*/
trellis.brightness = function brightness(level) {
level = level | 0;
level = level & 0x0F; // take only the lowest 4 bits
_trellis.i2c.send(new Buffer([0xE0 | level]));
};
/**
* Sets the blinking frequency for the display
* 0 - No Blinking
* 1 - 2 Hz
* 2 - 1 Hz
* 3 - .5 Hz
*/
trellis.blink = function blink(speed) {
speed = speed | 0;
speed = speed & 0x03; // take only the low two bits
speed = speed << 1;
_trellis.i2c.send(new Buffer([Commands.DISP_ON | speed]));
};
trellis.clearDisplay = function clearDisplay() {
_trellis.dispBuf.fill(0);
_trellis.i2c.send(_trellis.dispBuf);
};
trellis.fillDisplay = function fillDisplay() {
_trellis.dispBuf.fill(0xFF);
_trellis.i2c.send(_trellis.dispBuf);
};
return trellis;
};
module.exports = Trellis;