andrewm@0
|
1 /*
|
andrewm@0
|
2 TouchKeys: multi-touch musical keyboard control software
|
andrewm@0
|
3 Copyright (c) 2013 Andrew McPherson
|
andrewm@0
|
4
|
andrewm@0
|
5 This program is free software: you can redistribute it and/or modify
|
andrewm@0
|
6 it under the terms of the GNU General Public License as published by
|
andrewm@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
andrewm@0
|
8 (at your option) any later version.
|
andrewm@0
|
9
|
andrewm@0
|
10 This program is distributed in the hope that it will be useful,
|
andrewm@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
andrewm@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
andrewm@0
|
13 GNU General Public License for more details.
|
andrewm@0
|
14
|
andrewm@0
|
15 You should have received a copy of the GNU General Public License
|
andrewm@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
andrewm@0
|
17
|
andrewm@0
|
18 =====================================================================
|
andrewm@0
|
19
|
andrewm@0
|
20 TouchkeyDevice.h: handles communication with the TouchKeys hardware
|
andrewm@0
|
21 */
|
andrewm@0
|
22
|
andrewm@0
|
23 #ifndef TOUCHKEY_DEVICE_H
|
andrewm@0
|
24 #define TOUCHKEY_DEVICE_H
|
andrewm@0
|
25
|
andrewm@0
|
26 #include <iostream>
|
andrewm@0
|
27 #include <fstream>
|
andrewm@0
|
28 #include <cstdio>
|
andrewm@0
|
29 #include <cmath>
|
andrewm@0
|
30 #include <map>
|
andrewm@0
|
31 #include <set>
|
andrewm@0
|
32 #include <deque>
|
andrewm@0
|
33 #include <errno.h>
|
andrewm@0
|
34 #include <fcntl.h>
|
andrewm@0
|
35 #include <limits>
|
andrewm@0
|
36 #include <list>
|
andrewm@20
|
37 #ifndef _MSC_VER
|
andrewm@20
|
38 #include <termios.h>
|
andrewm@20
|
39 #endif
|
andrewm@0
|
40 #include <boost/bind.hpp>
|
andrewm@0
|
41 #include <boost/function.hpp>
|
andrewm@0
|
42 #include "../JuceLibraryCode/JuceHeader.h"
|
andrewm@0
|
43 #include "PianoKeyboard.h"
|
andrewm@0
|
44 #include "Osc.h"
|
andrewm@0
|
45 #include "../Utility/TimestampSynchronizer.h"
|
andrewm@0
|
46 #include "PianoKeyCalibrator.h"
|
andrewm@0
|
47 #include "../Display/RawSensorDisplay.h"
|
andrewm@0
|
48
|
andrewm@0
|
49 using namespace std;
|
andrewm@0
|
50
|
andrewm@0
|
51 #define TOUCHKEY_MAX_FRAME_LENGTH 256 // Maximum data length in a single frame
|
andrewm@0
|
52 #define ESCAPE_CHARACTER 0xFE // Indicates control sequence
|
andrewm@0
|
53
|
andrewm@0
|
54 //#define TRANSMISSION_LENGTH_WHITE 9
|
andrewm@0
|
55 //#define TRANSMISSION_LENGTH_BLACK 8
|
andrewm@0
|
56 //#define TRANSMISSION_LENGTH_TOTAL (8*TRANSMISSION_LENGTH_WHITE + 5*TRANSMISSION_LENGTH_BLACK)
|
andrewm@0
|
57
|
andrewm@0
|
58 const int kTransmissionLengthWhiteOldHardware = 9;
|
andrewm@0
|
59 const int kTransmissionLengthBlackOldHardware = 8;
|
andrewm@0
|
60 const int kTransmissionLengthWhiteNewHardware = 9;
|
andrewm@0
|
61 const int kTransmissionLengthBlackNewHardware = 9;
|
andrewm@0
|
62 const int kTransmissionLengthTotalOldHardware = (8 * kTransmissionLengthWhiteOldHardware + 5 * kTransmissionLengthBlackOldHardware);
|
andrewm@0
|
63 const int kTransmissionLengthTotalNewHardware = (8 * kTransmissionLengthWhiteNewHardware + 5 * kTransmissionLengthBlackNewHardware);
|
andrewm@0
|
64
|
andrewm@0
|
65 // Maximum integer values for different types of sliders
|
andrewm@0
|
66
|
andrewm@0
|
67 //#define WHITE_MAX_VALUE 1280.0 // White keys, vertical (64 * 20)
|
andrewm@0
|
68 //#define WHITE_MAX_H_VALUE 255.0 // Whtie keys, horizontal
|
andrewm@0
|
69 //#define BLACK_MAX_VALUE 1024.0 // Black keys, vertical (64 * 16)
|
andrewm@0
|
70 //#define SIZE_MAX_VALUE 255.0 // Max touch size for either key type
|
andrewm@0
|
71
|
andrewm@0
|
72 const float kWhiteMaxYValueOldHardware = 1280.0; // White keys, vertical (64 * 20)
|
andrewm@0
|
73 const float kWhiteMaxXValueOldHardware = 255.0; // White keys, horizontal (1 byte)
|
andrewm@0
|
74 const float kBlackMaxYValueOldHardware = 1024.0; // Black keys, vertical (64 * 16)
|
andrewm@0
|
75 const float kWhiteMaxYValueNewHardware = 2432.0; // White keys, vertical (128 * 19)
|
andrewm@0
|
76 const float kWhiteMaxXValueNewHardware = 256.0; // White keys, horizontal (1 byte + 1 bit)
|
andrewm@0
|
77 const float kBlackMaxYValueNewHardware = 1536.0; // Black keys, vertical (128 * 12)
|
andrewm@0
|
78 const float kBlackMaxXValueNewHardware = 256.0; // Black keys, horizontal (1 byte + 1 bit)
|
andrewm@0
|
79
|
andrewm@0
|
80 const float kSizeMaxValue = 255.0;
|
andrewm@0
|
81
|
andrewm@0
|
82 enum {
|
andrewm@0
|
83 kControlCharacterFrameBegin = 0x00,
|
andrewm@0
|
84 kControlCharacterAck = 0x01,
|
andrewm@0
|
85 kControlCharacterNak = 0x02,
|
andrewm@0
|
86 kControlCharacterFrameError = 0xFD,
|
andrewm@0
|
87 kControlCharacterFrameEnd = 0xFF
|
andrewm@0
|
88 };
|
andrewm@0
|
89
|
andrewm@0
|
90 // Frame types for data sent over USB. The first byte following a frame start control sequence gives the type.
|
andrewm@0
|
91
|
andrewm@0
|
92 enum {
|
andrewm@0
|
93 kFrameTypeStatus = 0, // Status info: connected keys, current operating modes
|
andrewm@0
|
94 kFrameTypeCentroid = 16, // Centroid data (default mode of operation)
|
andrewm@0
|
95 kFrameTypeI2CResponse = 17, // Response from a specific I2C command
|
andrewm@0
|
96 kFrameTypeRawKeyData = 18, // Raw data from the selected key
|
andrewm@0
|
97 kFrameTypeAnalog = 19, // Analog data from Z-axis optical sensors
|
andrewm@0
|
98
|
andrewm@0
|
99 kFrameTypeErrorMessage = 127, // Error message from controller
|
andrewm@0
|
100 // These types are for incoming (computer -> us) data
|
andrewm@0
|
101 kFrameTypeStartScanning = 128, // Start auto-scan
|
andrewm@0
|
102 kFrameTypeStopScanning = 129, // Stop auto-scan
|
andrewm@0
|
103 kFrameTypeSendI2CCommand = 130, // Send a specific I2C command
|
andrewm@0
|
104 kFrameTypeResetDevices = 131, // Physically reset the system
|
andrewm@0
|
105 kFrameTypeScanRate = 132, // Set the scan rate (in milliseconds)
|
andrewm@0
|
106 kFrameTypeNoiseThreshold = 133,
|
andrewm@0
|
107 kFrameTypeSensitivity = 134,
|
andrewm@0
|
108 kFrameTypeSizeScaler = 135,
|
andrewm@0
|
109 kFrameTypeMinimumSize = 136,
|
andrewm@0
|
110 kFrameTypeSetEnabledKeys = 137,
|
andrewm@0
|
111 kFrameTypeMonitorRawFromKey = 138,
|
andrewm@0
|
112 kFrameTypeUpdateBaselines = 139, // Reinitialize baseline values
|
andrewm@0
|
113 kFrameTypeRescanKeyboard = 140, // Rescan what keys are connected
|
andrewm@53
|
114 kFrameTypeEncapsulatedMIDI = 167, // MIDI messages to pass to MIDI standalone firmware
|
andrewm@0
|
115 kFrameTypeRGBLEDSetColors = 168, // Set RGBLEDs of given index to specific values
|
andrewm@0
|
116 kFrameTypeRGBLEDAllOff = 169, // All LEDs off
|
andrewm@0
|
117 kFrameTypeEnterISPMode = 192,
|
andrewm@0
|
118 kFrameTypeEnterSelfProgramMode = 193
|
andrewm@0
|
119 };
|
andrewm@0
|
120
|
andrewm@0
|
121 enum {
|
andrewm@0
|
122 kKeyColorWhite = 0,
|
andrewm@0
|
123 kKeyColorBlack
|
andrewm@0
|
124 };
|
andrewm@0
|
125
|
andrewm@0
|
126 enum {
|
andrewm@0
|
127 kStatusFlagRunning = 0x01,
|
andrewm@0
|
128 kStatusFlagRawMode = 0x02,
|
andrewm@0
|
129 kStatusFlagHasI2C = 0x04,
|
andrewm@0
|
130 kStatusFlagHasAnalog = 0x08,
|
andrewm@0
|
131 kStatusFlagHasRGBLED = 0x10,
|
andrewm@0
|
132 kStatusFlagComError = 0x80
|
andrewm@0
|
133 };
|
andrewm@0
|
134
|
andrewm@0
|
135
|
andrewm@0
|
136 const int kKeyColor[13] = { kKeyColorWhite, kKeyColorBlack, kKeyColorWhite,
|
andrewm@0
|
137 kKeyColorBlack, kKeyColorWhite, kKeyColorWhite, kKeyColorBlack,
|
andrewm@0
|
138 kKeyColorWhite, kKeyColorBlack, kKeyColorWhite, kKeyColorBlack,
|
andrewm@0
|
139 kKeyColorWhite, kKeyColorWhite };
|
andrewm@0
|
140
|
andrewm@0
|
141 const int kWhiteKeyIndices[13] = { 0, -1, 1, -1, 2, 3, -1, 4, -1, 5, -1, 6, 7};
|
andrewm@0
|
142
|
andrewm@0
|
143 const unsigned char kCommandStatus[] = { ESCAPE_CHARACTER, kControlCharacterFrameBegin, kFrameTypeStatus,
|
andrewm@0
|
144 ESCAPE_CHARACTER, kControlCharacterFrameEnd };
|
andrewm@0
|
145 const unsigned char kCommandStartScanning[] = { ESCAPE_CHARACTER, kControlCharacterFrameBegin, kFrameTypeStartScanning,
|
andrewm@0
|
146 ESCAPE_CHARACTER, kControlCharacterFrameEnd };
|
andrewm@0
|
147 const unsigned char kCommandStopScanning[] = { ESCAPE_CHARACTER, kControlCharacterFrameBegin, kFrameTypeStopScanning,
|
andrewm@0
|
148 ESCAPE_CHARACTER, kControlCharacterFrameEnd };
|
andrewm@0
|
149
|
andrewm@0
|
150 #define octaveNoteToIndex(octave, note) (100*octave + note) // Generate indices for containers
|
andrewm@0
|
151 #define indexToOctave(index) (int)(index / 100)
|
andrewm@0
|
152 #define indexToNote(index) (index % 100)
|
andrewm@0
|
153
|
andrewm@0
|
154 const float kTouchkeyAnalogValueMax = 4095.0; // Maximum value any analog sample can take
|
andrewm@0
|
155
|
andrewm@0
|
156 // This class implements device access to the touchkey hardware.
|
andrewm@0
|
157
|
andrewm@0
|
158 class TouchkeyDevice /*: public OscHandler*/
|
andrewm@0
|
159 {
|
andrewm@0
|
160 // ***** Class to implement the Juce thread *****
|
andrewm@0
|
161 private:
|
andrewm@0
|
162 class DeviceThread : public Thread {
|
andrewm@0
|
163 public:
|
andrewm@0
|
164 DeviceThread(boost::function<void (DeviceThread*)> action, String name = "DeviceThread")
|
andrewm@0
|
165 : Thread(name), actionFunction_(action) {}
|
andrewm@0
|
166
|
andrewm@0
|
167 ~DeviceThread() {}
|
andrewm@0
|
168
|
andrewm@0
|
169 void run() {
|
andrewm@0
|
170 actionFunction_(this);
|
andrewm@0
|
171 }
|
andrewm@0
|
172
|
andrewm@0
|
173 private:
|
andrewm@0
|
174 boost::function<void (DeviceThread*)> actionFunction_;
|
andrewm@0
|
175 };
|
andrewm@0
|
176
|
andrewm@0
|
177 public:
|
andrewm@0
|
178 class ControllerStatus {
|
andrewm@0
|
179 public:
|
andrewm@0
|
180 ControllerStatus() : connectedKeys(0) {}
|
andrewm@0
|
181 ~ControllerStatus() {
|
andrewm@0
|
182 if(connectedKeys != 0)
|
andrewm@0
|
183 free(connectedKeys);
|
andrewm@0
|
184 }
|
andrewm@0
|
185
|
andrewm@0
|
186 int hardwareVersion; // Hardware version
|
andrewm@0
|
187 int softwareVersionMajor; // Controller firmware major version
|
andrewm@0
|
188 int softwareVersionMinor; // Controller firmware minor version
|
andrewm@0
|
189 bool running; // Is the system currently gathering centroid data?
|
andrewm@0
|
190 bool hasTouchSensors; // Whether the device has I2C touch sensors
|
andrewm@0
|
191 bool hasAnalogSensors; // Whether the device has analog optical position sensors
|
andrewm@0
|
192 bool hasRGBLEDs; // Whether the device has RGB LEDs for display
|
andrewm@0
|
193 int octaves; // Number of octaves connected [two octaves per board]
|
andrewm@0
|
194 int lowestHardwareNote; // Note number (0-12) of lowest connector or sensor on lowest board
|
andrewm@0
|
195 unsigned int *connectedKeys;// Which keys are connected to each octave
|
andrewm@0
|
196 };
|
andrewm@0
|
197
|
andrewm@0
|
198 class MultiKeySweep {
|
andrewm@0
|
199 public:
|
andrewm@0
|
200
|
andrewm@0
|
201 int sweepId;
|
andrewm@0
|
202 int sweepOctave;
|
andrewm@0
|
203 float sweepNote;
|
andrewm@0
|
204 int keyCount;
|
andrewm@0
|
205 int keyOctave[2];
|
andrewm@0
|
206 int keyNote[2];
|
andrewm@0
|
207 int keyTouchId[2];
|
andrewm@0
|
208 float keyPosition[2];
|
andrewm@0
|
209 };
|
andrewm@0
|
210
|
andrewm@0
|
211 // Structure to hold changes to RGB LEDs on relevant hardware
|
andrewm@0
|
212 class RGBLEDUpdate {
|
andrewm@0
|
213 public:
|
andrewm@0
|
214 bool allLedsOff; // Set to true if all LEDs should turn off on indicated board
|
andrewm@0
|
215 int midiNote; // MIDI note number to change
|
andrewm@0
|
216 int red; // RGB color
|
andrewm@0
|
217 int green;
|
andrewm@0
|
218 int blue;
|
andrewm@0
|
219 };
|
andrewm@0
|
220
|
andrewm@0
|
221 public:
|
andrewm@0
|
222 // ***** Constructor *****
|
andrewm@0
|
223 TouchkeyDevice(PianoKeyboard& keyboard);
|
andrewm@0
|
224
|
andrewm@0
|
225 // ***** Destructor *****
|
andrewm@0
|
226 ~TouchkeyDevice();
|
andrewm@0
|
227
|
andrewm@0
|
228 // ***** Device Management *****
|
andrewm@0
|
229 // Open a new device. Returns true on success
|
andrewm@0
|
230 bool openDevice(const char * inputDevicePath);
|
andrewm@0
|
231 void closeDevice();
|
andrewm@0
|
232
|
andrewm@0
|
233 // Start or stop the processing. startAutoGathering() returns
|
andrewm@0
|
234 // true on success.
|
andrewm@0
|
235 bool startAutoGathering();
|
andrewm@28
|
236 void stopAutoGathering(bool writeStopCommandToDevice = true);
|
andrewm@0
|
237
|
andrewm@0
|
238 // Status query methods
|
andrewm@23
|
239 bool isOpen();
|
andrewm@0
|
240 bool isAutoGathering() { return autoGathering_; }
|
andrewm@0
|
241 int numberOfOctaves() { return numOctaves_; }
|
andrewm@0
|
242
|
andrewm@0
|
243 // Ping the device, to see if it is ready to respond
|
andrewm@0
|
244 bool checkIfDevicePresent(int millisecondsToWait);
|
andrewm@0
|
245
|
andrewm@0
|
246 // Start collecting raw data from a given key
|
andrewm@0
|
247 bool startRawDataCollection(int octave, int key, int mode, int scaler);
|
andrewm@17
|
248 void rawDataChangeKeyAndMode(int octave, int key, int mode, int scaler);
|
andrewm@0
|
249
|
andrewm@0
|
250 // ***** RGB LED updates *****
|
andrewm@0
|
251 void rgbledSetColor(const int midiNote, const float red, const float green, const float blue);
|
andrewm@0
|
252 void rgbledSetColorHSV(const int midiNote, const float hue, const float saturation, const float value);
|
andrewm@0
|
253 void rgbledAllOff();
|
andrewm@0
|
254
|
andrewm@0
|
255 // ***** Device Parameters *****
|
andrewm@0
|
256
|
andrewm@0
|
257 // Set the scan interval in milliseconds
|
andrewm@0
|
258 bool setScanInterval(int intervalMilliseconds);
|
andrewm@0
|
259
|
andrewm@0
|
260 // Key parameters. Setting octave or key to -1 means all octaves or all keys, respectively.
|
andrewm@0
|
261 bool setKeySensitivity(int octave, int key, int value);
|
andrewm@0
|
262 bool setKeyCentroidScaler(int octave, int key, int value);
|
andrewm@0
|
263 bool setKeyMinimumCentroidSize(int octave, int key, int value);
|
andrewm@0
|
264 bool setKeyNoiseThreshold(int octave, int key, int value);
|
andrewm@19
|
265 bool setKeyUpdateBaseline(int octave, int key);
|
andrewm@0
|
266
|
andrewm@0
|
267 // Jump to device internal bootloader
|
andrewm@0
|
268 void jumpToBootloader();
|
andrewm@0
|
269
|
andrewm@0
|
270 // ***** Calibration Methods *****
|
andrewm@0
|
271
|
andrewm@0
|
272 // Return whether or not the controller has been calibrated, and whether it's currently calibrating
|
andrewm@0
|
273 bool isCalibrated() { return isCalibrated_; }
|
andrewm@0
|
274 bool calibrationInProgress() { return calibrationInProgress_; }
|
andrewm@0
|
275
|
andrewm@0
|
276 // Start: begin calibrating; finish: end and save results; abort: end and discard results
|
andrewm@0
|
277 void calibrationStart(std::vector<int>* keysToCalibrate);
|
andrewm@0
|
278 void calibrationFinish();
|
andrewm@0
|
279 void calibrationAbort();
|
andrewm@0
|
280 void calibrationClear();
|
andrewm@0
|
281
|
andrewm@0
|
282 bool calibrationSaveToFile(std::string const& filename);
|
andrewm@0
|
283 bool calibrationLoadFromFile(std::string const& filename);
|
andrewm@0
|
284
|
andrewm@0
|
285 // ***** Data Logging *****
|
andrewm@0
|
286 void createLogFiles(string keyTouchLogFilename, string analogLogFilename, string path);
|
andrewm@0
|
287 void closeLogFile();
|
andrewm@0
|
288 void startLogging();
|
andrewm@0
|
289 void stopLogging();
|
andrewm@0
|
290
|
andrewm@0
|
291 // ***** Debugging and Utility *****
|
andrewm@0
|
292
|
andrewm@0
|
293 // Set logging level
|
andrewm@0
|
294 void setVerboseLevel(int v) { verbose_ = v; }
|
andrewm@0
|
295 void setTransmitRawData(bool raw) { sendRawOscMessages_ = raw; }
|
andrewm@0
|
296 bool transmitRawDataEnabled() { return sendRawOscMessages_; }
|
andrewm@0
|
297
|
andrewm@0
|
298 // Conversion between touchkey # and MIDI note
|
andrewm@0
|
299 int lowestMidiNote() { return lowestMidiNote_; }
|
andrewm@48
|
300 int highestMidiNote() { return lowestMidiNote_ + 12*numOctaves_ + lowestNotePerOctave_; }
|
andrewm@0
|
301 int lowestKeyPresentMidiNote() { return lowestKeyPresentMidiNote_; } // What is the lowest key actually connected?
|
andrewm@0
|
302 void setLowestMidiNote(int note);
|
andrewm@48
|
303 int octaveKeyToMidi(int octave, int key);
|
andrewm@0
|
304
|
andrewm@0
|
305 // Sensor data display
|
andrewm@0
|
306 void setSensorDisplay(RawSensorDisplay *display) { sensorDisplay_ = display; }
|
andrewm@0
|
307
|
andrewm@0
|
308 // ***** Run Loop Functions *****
|
andrewm@0
|
309 void ledUpdateLoop(DeviceThread *thread);
|
andrewm@0
|
310 void runLoop(DeviceThread *thread);
|
andrewm@0
|
311 void rawDataRunLoop(DeviceThread *thread);
|
andrewm@0
|
312
|
andrewm@0
|
313 // for debugging
|
andrewm@0
|
314 void testStopLeds() { ledShouldStop_ = true; }
|
andrewm@0
|
315
|
andrewm@0
|
316 private:
|
andrewm@0
|
317 // Read and parse new data from the device, splitting out by frame type
|
andrewm@0
|
318 void processFrame(unsigned char * const frame, int length);
|
andrewm@0
|
319
|
andrewm@0
|
320 // Specific data type parsing
|
andrewm@0
|
321 void processCentroidFrame(unsigned char * const buffer, const int bufferLength);
|
andrewm@0
|
322 int processKeyCentroid(int frame,int octave, int key, timestamp_type timestamp, unsigned char * buffer, int maxLength);
|
andrewm@0
|
323 void processAnalogFrame(unsigned char * const buffer, const int bufferLength);
|
andrewm@0
|
324 void processRawDataFrame(unsigned char * const buffer, const int bufferLength);
|
andrewm@0
|
325 bool processStatusFrame(unsigned char * buffer, int maxLength, ControllerStatus *status);
|
andrewm@0
|
326 void processI2CResponseFrame(unsigned char * const buffer, const int bufferLength);
|
andrewm@0
|
327 void processErrorMessageFrame(unsigned char * const buffer, const int bufferLength);
|
andrewm@0
|
328
|
andrewm@0
|
329 // Helper methods for centroid processing
|
andrewm@0
|
330 //pair<float, list<int> > matchClosestPoints(float* oldPoints, float *newPoints, float count,
|
andrewm@0
|
331 // int oldIndex, set<int>& availableNewPoints, float currentTotalDistance);
|
andrewm@0
|
332 void processTwoFingerGestures(int octave, int key, KeyTouchFrame& previousPosition, KeyTouchFrame& newPosition);
|
andrewm@0
|
333 void processThreeFingerGestures(int octave, int key, KeyTouchFrame& previousPosition, KeyTouchFrame& newPosition);
|
andrewm@0
|
334
|
andrewm@0
|
335 // Utility method for parsing multi-key gestures
|
andrewm@0
|
336 pair<int, int> whiteKeyAbove(int octave, int note);
|
andrewm@0
|
337
|
andrewm@17
|
338 // Write the commands to prepare a given key for raw data collection
|
andrewm@17
|
339 void rawDataPrepareCollection(int octave, int key, int mode, int scaler);
|
andrewm@17
|
340
|
andrewm@0
|
341 // After writing a command, check whether it was acknolwedged by the controller
|
andrewm@0
|
342 bool checkForAck(int timeoutMilliseconds);
|
andrewm@0
|
343
|
andrewm@0
|
344 // Utility method for debugging
|
andrewm@0
|
345 void hexDump(ostream& str, unsigned char * buffer, int length);
|
andrewm@17
|
346
|
andrewm@0
|
347 // Internal calibration methods
|
andrewm@0
|
348 void calibrationInit(int numberOfCalibrators);
|
andrewm@0
|
349 void calibrationDeinit();
|
andrewm@0
|
350
|
andrewm@0
|
351 // Set RGB LED color (for piano scanner boards)
|
andrewm@0
|
352 bool internalRGBLEDSetColor(const int device, const int led, const int red, const int green, const int blue);
|
andrewm@0
|
353 bool internalRGBLEDAllOff(); // RGB LEDs off
|
andrewm@0
|
354 int internalRGBLEDMIDIToBoardNumber(const int midiNote); // Get board number for MIDI note
|
andrewm@0
|
355 int internalRGBLEDMIDIToLEDNumber(const int midiNote); // Get LED number for MIDI note
|
andrewm@22
|
356
|
andrewm@22
|
357 // Device low-level access methods
|
andrewm@22
|
358 long deviceRead(char *buffer, unsigned int count);
|
andrewm@22
|
359 int deviceWrite(char *buffer, unsigned int count);
|
andrewm@22
|
360 void deviceFlush(bool bothDirections);
|
andrewm@22
|
361 void deviceDrainOutput();
|
andrewm@0
|
362
|
andrewm@0
|
363 private:
|
andrewm@0
|
364 PianoKeyboard& keyboard_; // Main keyboard controller
|
andrewm@0
|
365
|
andrewm@23
|
366 #ifdef _MSC_VER
|
andrewm@23
|
367 HANDLE serialHandle_; // Serial port handle
|
andrewm@23
|
368 #else
|
andrewm@0
|
369 int device_; // File descriptor
|
andrewm@23
|
370 #endif
|
andrewm@0
|
371 DeviceThread ioThread_; // Thread that handles the communication from the device
|
andrewm@0
|
372 DeviceThread rawDataThread_;// Thread that handles raw data collection
|
andrewm@0
|
373 //CriticalSection ioMutex_; // Mutex synchronizing access between internal and external threads
|
andrewm@0
|
374 bool autoGathering_; // Whether auto-scanning is enabled
|
andrewm@0
|
375 volatile bool shouldStop_; // Communication variable between threads
|
andrewm@0
|
376 bool sendRawOscMessages_; // Whether we should transmit the raw frame data by OSC
|
andrewm@0
|
377 int verbose_; // Logging level
|
andrewm@0
|
378 int numOctaves_; // Number of connected octaves (determined from device)
|
andrewm@0
|
379 int lowestMidiNote_; // MIDI note number for the lowest C on the lowest octave
|
andrewm@0
|
380 int lowestKeyPresentMidiNote_; // MIDI note number for the lowest key actually attached
|
andrewm@0
|
381 int updatedLowestMidiNote_; // Lowest MIDI note if changed; held separately for thread sync
|
andrewm@48
|
382 int lowestNotePerOctave_; // Note which starts each octave, for non C-to-C keyboards
|
andrewm@0
|
383 set<int> keysPresent_; // Which keys (octave and note) are present on this device?
|
andrewm@0
|
384 int deviceSoftwareVersion_; // Which version of the device we're talking to
|
andrewm@0
|
385 int deviceHardwareVersion_; // Which version of the device hardware is running
|
andrewm@0
|
386 int expectedLengthWhite_; // How long the white key data blocks are
|
andrewm@0
|
387 int expectedLengthBlack_; // How long the black key data blocks are
|
andrewm@0
|
388 float whiteMaxX_, whiteMaxY_; // Maximum sensor values for white keys
|
andrewm@0
|
389 float blackMaxX_, blackMaxY_; // Maximum sensor values for black keys
|
andrewm@0
|
390
|
andrewm@0
|
391 // Frame counter for analog data, to detect dropped frames
|
andrewm@0
|
392 unsigned int analogLastFrame_[4]; // Max 4 boards
|
andrewm@0
|
393
|
andrewm@0
|
394 // Synchronization between frame time and system timestamp, allowing interaction
|
andrewm@0
|
395 // with other simultaneous streams using different clocks. Also save the last timestamp
|
andrewm@0
|
396 // we've processed to other functions can access it.
|
andrewm@0
|
397 TimestampSynchronizer timestampSynchronizer_;
|
andrewm@0
|
398 timestamp_type lastTimestamp_;
|
andrewm@0
|
399
|
andrewm@0
|
400 // For raw data collection, this information keeps track of which key we're reading
|
andrewm@17
|
401 bool rawDataShouldChangeMode_;
|
andrewm@0
|
402 int rawDataCurrentOctave_, rawDataCurrentKey_;
|
andrewm@17
|
403 int rawDataCurrentMode_, rawDataCurrentScaler_;
|
andrewm@0
|
404
|
andrewm@0
|
405 // ***** RGB LED management *****
|
andrewm@0
|
406 bool deviceHasRGBLEDs_; // Whether the device has RGB LEDs
|
andrewm@0
|
407 DeviceThread ledThread_; // Thread that handles LED updates (communication to the device)
|
andrewm@0
|
408 volatile bool ledShouldStop_; // testing
|
andrewm@0
|
409 deque<RGBLEDUpdate> ledUpdateQueue_; // Queue that holds new LED messages to be sent to device
|
andrewm@0
|
410
|
andrewm@0
|
411 // ***** Calibration *****
|
andrewm@0
|
412 bool isCalibrated_;
|
andrewm@0
|
413 bool calibrationInProgress_;
|
andrewm@0
|
414
|
andrewm@0
|
415 PianoKeyCalibrator** keyCalibrators_; // Calibration information for each key
|
andrewm@0
|
416 int keyCalibratorsLength_; // How many calibrators
|
andrewm@0
|
417
|
andrewm@0
|
418 // ***** Logging *****
|
andrewm@0
|
419 ofstream keyTouchLog_;
|
andrewm@0
|
420 ofstream analogLog_;
|
andrewm@0
|
421 bool logFileCreated_;
|
andrewm@0
|
422 bool loggingActive_;
|
andrewm@0
|
423
|
andrewm@0
|
424 // ***** Sensor Data Display (for debugging) *****
|
andrewm@0
|
425 RawSensorDisplay *sensorDisplay_;
|
andrewm@0
|
426 };
|
andrewm@0
|
427
|
andrewm@0
|
428 #endif /* TOUCHKEY_DEVICE_H */ |