From 0ce375ef4f16ccdfa05623f4382084fecbe4162d Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Mon, 1 Mar 2021 19:38:19 +0100 Subject: [PATCH] feat: Refactor & improve (Author: michaelhatPIengineering) --- src/products.ts | 109 ++++++++++++++++++++++++++++++++---------------- src/xkeys.ts | 87 ++++++++++++++++++++++---------------- 2 files changed, 125 insertions(+), 71 deletions(-) diff --git a/src/products.ts b/src/products.ts index c4b8f17..f013cf6 100644 --- a/src/products.ts +++ b/src/products.ts @@ -37,74 +37,92 @@ export interface ProductTbar extends ProductBase { export type Product = ProductBase | ProductJog | ProductShuttle | ProductTbar export const PRODUCTS: {[name: string]: Product} = { + + // Note: The byte numbers are byte index (starts with 0) and will be offset from documentation by -2 + // these byte index are used to access the exact byte in the data report. + XK24: { identifier: 'XK-24', - productId: [1029,1028,1027,1249], + productId: [1029,1027], columns: 4, rows: 6, hasPS: true, banks: 2, bankSize: 32 }, - XK4: { // This has not been tested + XK4: { identifier: 'XK-4', - productId: [1127,1128,1129,1253, 1049], + productId: [1127,1129], columns: 4, rows: 1, - hasPS: false, // unknown + hasPS: true, // slide switch on end banks: 1, // only has blue light bankSize: 32 // unknown }, - XK8: { // This has not been tested + XK8: { identifier: 'XK-8', - productId: [1130,1131,1132,1252], - columns: 8, - rows: 1, - hasPS: false, // unknown + productId: [1130,1132], + columns: 4, + rows: 2, // row1 = 0,1,2,3 row2=4,5,6,7 + hasPS: true, // slide switch on end banks: 1, // only has blue light bankSize: 32 // unknown }, - XK12JOG: { // This has not been tested + XK12JOG: { identifier: 'XK-12 Jog', productId: [1062,1064], columns: 4, rows: 3, hasPS: true, hasJog: true, - jogByte: 8, - hasShuttle: true, - shuttleByte: 9, + jogByte: 6, + hasShuttle: true, + shuttleByte: 7, banks: 2, bankSize: 32 }, - XK12JOYSTICK: { // This has not been tested + XK12JOYSTICK: { identifier: 'XK-12 Joystick', productId: [1065,1067], columns: 4, rows: 3, hasPS: true, hasJoystick: true, + // joyXbyte: 7 + // joyYbyte: 8 + // joyZbyte: 9 // twist of stick + banks: 2, bankSize: 32 }, - XK16: { // This has not been tested + XK16: { identifier: 'XK-16', - productId: [1269,1270,1050,1051,1251], - columns: 4, - rows: 4, // not really rows, but the data comes like that (it is physically one row) - hasPS: false, // unknown + productId: [1049,1051,1213,1216], + columns: 4, // 4 buttton data bytes + rows: 4, // not really rows, but the data comes like that (it is physically one row) row1= 0,1,2,3 row2=4,5,6,7 row3= 8,9,10,11 row4=12,13,14,15 + hasPS: true, // slide switch on end banks: 1, // only has blue light - bankSize: 32 // unknown + bankSize: 0, // only one set LEDs under keys + //btnLocation: ['r1c1','r1c5','r1c9','r1c13','r1c2','r1c6','r1c10','r1c14','r1c3','r1c7','r1c11','r1c15','r1c4','r1c8','r1c12','r1c16'] }, - XR32: { // This has not been tested + XKR32: { // discontinued product, XKE 40 is viable replacement identifier: 'XR-32', - productId: [1279,1280,1281,1282], - columns: 16, - rows: 2, + productId: [1279,1282], + columns: 4, // 4 buttton data bytes + rows: 8, hasPS: false, // unknown bankSize: 128 }, - XK60: { // This has not been tested + XKE40: { + identifier: 'XKE-40', + productId: [1358,1359,1360,1361], + columns: 5, // 5 buttton data bytes + rows: 8, // row1=0,8,16,24,32 row2=1,9,17,25,33 row3=2,10,18,26,34 row4=3,11,19,27,35 row5=4,12,20,28,36 row6=5,13,21,29,37 row7=6,14,22,30,38 row8=7,15,23,31,39 + hasPS: true, // behind small hole on left side. + bankSize: 40 // off set to control second led bank. + }, + + XK60: { identifier: 'XK-60', productId: [1239,1240,1121,1122,1123,1254], columns: 10, @@ -115,7 +133,7 @@ export const PRODUCTS: {[name: string]: Product} = { }, XK80: { identifier: 'XK-80', - productId: [1237,1238,1089,1090,1091,1250], + productId: [1237,1238,1089,1090,1091,1250], columns: 10, rows: 8, hasPS: true, @@ -124,18 +142,18 @@ export const PRODUCTS: {[name: string]: Product} = { }, XKE124TBAR: { identifier: 'XKE-124 T-bar', - productId: [1275,1276,1277,1278], + productId: [1275,1278], columns: 16, rows: 8, hasPS: false, hasTbar: true, - tbarByte: 30, - tbarByteRaw: 31, + tbarByte: 28, // should only use cal t-bar on byte index 28 + tbarByteRaw: 29, banks: 2, bankSize: 128, - disableKeys: [108,109,110,111] + disableKeys: [108,109,110,111] }, - XKE128: { // This has not been tested + XKE128: { identifier: 'XKE-128', productId: [1227,1228,1229,1230], columns: 16, @@ -144,18 +162,37 @@ export const PRODUCTS: {[name: string]: Product} = { banks: 2, bankSize: 128 }, - XK68JOGSHUTTLE: { // This has not been tested + XK68JOGSHUTTLE: { identifier: 'XK-68 Jog-Shuttle', - productId: [1114, 1116], + productId: [1114, 1116], + columns: 10, + rows: 8, + hasPS: true, + hasJog: true, + jogByte: 16, + hasShuttle: true, + shuttleByte: 17, + banks: 2, + bankSize: 80, + disableKeys: [29,30,31, 37,38,39, 45,46,47, 53,54,55] + + }, + XK64JOGTBAR: { + identifier: 'XKE-64 Jog T-bar', + productId: [1325, 1326,1327,1328,1329,1330,1331], columns: 10, rows: 8, hasPS: true, hasJog: true, jogByte: 18, - hasShuttle: true, - shuttleByte: 19, + hasShuttle: true, + shuttleByte: 19, + hasTbar: true, + tbarByte: 17, // should only use cal t-bar on byte index 17 + tbarByteRaw: 15, banks: 2, bankSize: 80, - disableKeys: [29,30,31, 37,38,39, 45,46,47, 53,54,55] + disableKeys: [5,6,7,13,14,15,21,22,23,29,30,31,72,73,74,75] // These bits are messy, better to ignore them + } } diff --git a/src/xkeys.ts b/src/xkeys.ts index 35314c8..b9c9dba 100644 --- a/src/xkeys.ts +++ b/src/xkeys.ts @@ -125,20 +125,39 @@ export class XKeys extends EventEmitter { ) } - this.device.on('data', data => { + this.device.on('data', (data: Buffer) => { - // Note: first column is on word 2 + if (!deviceInfo) return const buttonStates: ButtonStates = {} const buttonStates2: ButtonStates2 = { PS: false } const analogStates: AnalogStates = {} + // UID, unit id, is used to uniquely identify a ceratin panel, from factory it's set to 0. It can be set by a user to be able to find a reconnected panel. + var UID = data.readUInt8(0) // the unit ID is the first byte, index 0, used to tell between 2 identical X-keys, UID is set by user + // @ts-ignore + var PID = deviceInfo.productId // from USB hardware ID + var productName = this.deviceType.identifier // name from products file + + // var keyCol = 1 // use a 1 based system for Rows and Columns + // var keyRow = 1 + + var dd = data.readUInt8(1) + // The genData bit is set when the message is a reply to the Generate Data message + var genData = dd & (1 << 1) ? true : false + if (genData ) { + this.emit('unitID', UID, PID, productName) + } + + + // Note: first button data (column) is on byte index 2 + for (let x: number = 0; x < this.deviceType.columns; x++) { for (let y: number = 0; y < this.deviceType.rows; y++) { - const keyIndex: number = x * 8 + y + var keyIndex = x * this.deviceType.rows + y - const d = data.readUInt32LE(2 + x) + var d = data.readUInt8(2 + x) const bit = d & (1 << y) ? true : false @@ -146,40 +165,39 @@ export class XKeys extends EventEmitter { } } if (this.deviceType.hasPS) { - // program switch-button is on word 1 - const d = data.readUInt32LE(1) + // program switch-button is on byte index 1 + var d = data.readUInt8(1) const bit = d & (1 << 0) ? true : false buttonStates2.PS = bit } - if (this.deviceType.hasJog) { + if (this.deviceType.hasJog && this.deviceType.jogByte !== undefined ) { - const d = data[(this.deviceType.jogByte || 0) - 2] // Jog + var d = data[(this.deviceType.jogByte ) ] // Jog analogStates.jog = (d < 128 ? d : d - 256) } - if (this.deviceType.hasShuttle) { - const d = data[(this.deviceType.shuttleByte || 0) - 2] // Shuttle + if (this.deviceType.hasShuttle && this.deviceType.shuttleByte !== undefined) { + var d = data[(this.deviceType.shuttleByte ) ] // Shuttle analogStates.shuttle = (d < 128 ? d : d - 256) } if (this.deviceType.hasJoystick) { - let d = data.readUInt32LE(7) // Joystick X - analogStates.joystick_x = (d < 128 ? d : d - 256) - - d = data.readUInt32LE(8) // Joystick Y - analogStates.joystick_y = (d < 128 ? d : d - 256) - - d = data.readUInt32LE(9) // Joystick Z (twist of joystick) - analogStates.joystick_z = (d < 128 ? d : d - 256) + var d = data.readUInt8(6); // Joystick X + analogStates.joystick_x = (d < 128 ? d : d - 256); + d = data.readUInt8(7); // Joystick Y + analogStates.joystick_y = (d < 128 ? -d : -(d - 256)); + d = data.readUInt8(8); // Joystick Z (twist of joystick) + analogStates.joystick_z = (d); // joystick z is a continuous value that rolls over to 0 after 255 } - if (this.deviceType.hasTbar) { - let d = data[(this.deviceType.tbarByte || 0) - 2] // T-bar (calibrated) + if (this.deviceType.hasTbar && this.deviceType.tbarByte !== undefined) { + var d = data.readUInt8(this.deviceType.tbarByte ) // T-bar (calibrated) analogStates.tbar = d - d = data.readUInt16BE((this.deviceType.tbarByteRaw || 0) - 2) // T-bar (uncalibrated) - analogStates.tbar_raw = d + // Note: The uncalibrated shouldn't be used at all, it's only used by manufacturer + // d = data.readUInt16BE((this.deviceType.tbarByteRaw || 0) - 2) // T-bar (uncalibrated) + // analogStates.tbar_raw = d } - // Disabled/nonexisting keys: + // Disabled/nonexisting keys: // important as some keys in the jog & shuttle devices are used to shuttle events. if (this.deviceType.disableKeys) { this.deviceType.disableKeys.forEach((keyIndex) => { buttonStates[keyIndex] = false @@ -190,11 +208,11 @@ export class XKeys extends EventEmitter { // compare with previous button states: if ((this._buttonStates[buttonStateKey] || false) !== buttonStates[buttonStateKey]) { if (buttonStates[buttonStateKey]) { // key is pressed - this.emit('down', buttonStateKey) - this.emit('downKey', buttonStateKey) + this.emit('down', buttonStateKey, UID, PID, productName); + this.emit('downKey', buttonStateKey, UID, PID, productName); } else { - this.emit('up', buttonStateKey) - this.emit('upKey', buttonStateKey) + this.emit('up', buttonStateKey,UID, PID, productName); + this.emit('upKey', buttonStateKey, UID, PID, productName); } } } @@ -202,11 +220,11 @@ export class XKeys extends EventEmitter { // compare with previous button states: if ((this._buttonStates2[buttonStates2Key] || false) !== buttonStates2[buttonStates2Key]) { if (buttonStates2[buttonStates2Key]) { // key is pressed - this.emit('down', buttonStates2Key) - this.emit('downAlt', buttonStates2Key) + this.emit('down', buttonStates2Key, UID, PID, productName); + this.emit('downAlt', buttonStates2Key, UID, PID, productName); } else { - this.emit('up', buttonStates2Key) - this.emit('upAlt', buttonStates2Key) + this.emit('up', buttonStates2Key, UID, PID, productName); + this.emit('upAlt', buttonStates2Key, UID, PID, productName); } } } @@ -220,10 +238,9 @@ export class XKeys extends EventEmitter { analogStateKey === 'shuttle' ) { this.emit(analogStateKey , analogStates[analogStateKey]) - } else if ( - analogStateKey === 'tbar_raw' - ) { - this.emit('tbar', analogStates.tbar, analogStates.tbar_raw) + } else if (analogStateKey === 'tbar') { + this.emit('tbar', analogStates.tbar) + } else if ( analogStateKey === 'joystick_x' || analogStateKey === 'joystick_y' ||