Make the first byte of KeyAction items purely denote their type. Make the binary representation of KeyAction items variable-length.

This commit is contained in:
László Monda
2016-03-30 17:19:09 +02:00
parent 4bd1c8b3e9
commit 5b6f62c113
9 changed files with 116 additions and 65 deletions

View File

@@ -1,9 +1,23 @@
enum LongPressAction {
leftCtrl,
leftShift,
leftAlt,
leftSuper,
rightCtrl,
rightShift,
rightAlt,
rightSuper,
mod,
fn,
mouse
}
class DualRoleKeystrokeAction extends KeyAction implements Serializable<DualRoleKeystrokeAction> { class DualRoleKeystrokeAction extends KeyAction implements Serializable<DualRoleKeystrokeAction> {
static keyActionTypeString = 'dualRoleKeystroke'; static keyActionTypeString = 'dualRoleKeystroke';
public scancode; public scancode;
private _longPressAction: KeyActionId; private _longPressAction: LongPressAction;
get longPressAction(): number { get longPressAction(): number {
return this._longPressAction; return this._longPressAction;
@@ -17,32 +31,34 @@ class DualRoleKeystrokeAction extends KeyAction implements Serializable<DualRole
} }
static isDualRoleKeystrokeActionValid(keyActionIdParam): boolean { static isDualRoleKeystrokeActionValid(keyActionIdParam): boolean {
return KeyActionId.DualRoleActionLeftCtrlLongPressAction <= keyActionIdParam && return MouseActionParam[keyActionIdParam] !== undefined;
keyActionIdParam <= KeyActionId.DualRoleActionMouseLongPressAction;
} }
fromJsObject(jsObject: any): DualRoleKeystrokeAction { fromJsObject(jsObject: any): DualRoleKeystrokeAction {
this.longPressAction = jsObject.longPressAction; this.assertKeyActionType(jsObject, DualRoleKeystrokeAction.keyActionTypeString, 'DualRoleKeystrokeAction');
this.scancode = jsObject.scancode; this.scancode = jsObject.scancode;
this.longPressAction = jsObject.longPressAction;
return this; return this;
} }
fromBinary(buffer: UhkBuffer): DualRoleKeystrokeAction { fromBinary(buffer: UhkBuffer): DualRoleKeystrokeAction {
this.longPressAction = buffer.readUInt8(); this.readAndAssertKeyActionId(buffer, KeyActionId.DualRoleKeystrokeAction, 'DualRoleKeystrokeAction');
this.scancode = buffer.readUInt8(); this.scancode = buffer.readUInt8();
this.longPressAction = buffer.readUInt8();
return this; return this;
} }
toJsObject(): any { toJsObject(): any {
return { return {
keyActionType: DualRoleKeystrokeAction.keyActionTypeString, keyActionType: DualRoleKeystrokeAction.keyActionTypeString,
longPressAction: KeyActionId[this.longPressAction], scancode: this.scancode,
scancode: this.scancode longPressAction: KeyActionId[this.longPressAction]
}; };
} }
toBinary(buffer: UhkBuffer) { toBinary(buffer: UhkBuffer) {
buffer.writeUInt8(this.longPressAction); buffer.writeUInt8(KeyActionId.DualRoleKeystrokeAction);
buffer.writeUInt8(this.scancode); buffer.writeUInt8(this.scancode);
buffer.writeUInt8(this.longPressAction);
} }
} }

View File

@@ -1,27 +1,15 @@
// A KeyAction is composed of 2 bytes in the RAM of the UHK: id byte, and param byte. // A KeyAction is composed of 3 bytes in the RAM and up to 3 bytes in the EEPROM of the UHK.
// Id denotes the subclass of the KeyAction and param is subclass-specific. // The first byte denotes the subclass of the KeyAction and its length in the EEPROM.
enum KeyActionId { enum KeyActionId {
NoneAction = 0, NoneAction = 0,
KeyStrokeActionFirst = TypeChecker.firstValidScancode, // 1 KeystrokeAction = 1,
// Intermediary scancodes = 2 to 230 KeystrokeWithModifiersAction = 2,
KeyStrokeActionLast = TypeChecker.lastValidScancode, // 231 DualRoleKeystrokeAction = 3,
SwitchLayerAction = 232, SwitchLayerAction = 4,
SwitchKeymapAction = 233, SwitchKeymapAction = 5,
MouseAction = 234, MouseAction = 6,
PlayMacroAction = 235, PlayMacroAction = 7
DualRoleActionLeftCtrlLongPressAction = 236,
DualRoleActionLeftShiftLongPressAction = 237,
DualRoleActionLeftAltLongPressAction = 238,
DualRoleActionLeftSuperLongPressAction = 239,
DualRoleActionRightCtrlLongPressAction = 240,
DualRoleActionRightShiftLongPressAction = 241,
DualRoleActionRightAltLongPressAction = 242,
DualRoleActionRightSuperLongPressAction = 243,
DualRoleActionModLongPressAction = 244,
DualRoleActionFnLongPressAction = 245,
DualRoleActionMouseLongPressAction = 246
// Let's leave space for further layers - additional actions should descend from 255
} }
class KeyAction { class KeyAction {
@@ -43,14 +31,28 @@ class KeyAction {
let keyActionFirstByte = buffer.readUInt8(); let keyActionFirstByte = buffer.readUInt8();
buffer.backtrack(); buffer.backtrack();
if (TypeChecker.isScancodeValid(keyActionFirstByte)) { switch (keyActionFirstByte) {
return new KeystrokeAction().fromBinary(buffer); case KeyActionId.KeystrokeAction:
} else if (keyActionFirstByte === KeyActionId.MouseAction) { return new KeystrokeAction().fromBinary(buffer);
return new MouseAction().fromBinary(buffer); case KeyActionId.MouseAction:
} else if (keyActionFirstByte === KeyActionId.NoneAction) { return new MouseAction().fromBinary(buffer);
return new NoneAction().fromBinary(buffer); case KeyActionId.NoneAction:
} else { return new NoneAction().fromBinary(buffer);
throw 'Invalid KeyAction first byte "${keyActionFirstByte}"'; default:
throw 'Invalid KeyAction first byte "${keyActionFirstByte}"';
}
}
assertKeyActionType(jsObject: any, keyActionTypeString: string, classname: string) {
if (jsObject.keyActionType !== keyActionTypeString) {
throw 'Invalid ${classname}.id: ${jsObject.keyActionType}';
}
}
readAndAssertKeyActionId(buffer: UhkBuffer, keyActionIdParam: KeyActionId, classname: string) {
let readKeyActionId = buffer.readUInt8();
if (readKeyActionId !== keyActionIdParam) {
throw 'Invalid ${classname} first byte: ${keyActionId}';
} }
} }
} }

View File

@@ -2,8 +2,6 @@ class KeystrokeAction extends KeyAction implements Serializable<KeystrokeAction>
static keyActionTypeString = 'keystroke'; static keyActionTypeString = 'keystroke';
modifierMask: number;
private _scancode: number; private _scancode: number;
get scancode(): number { get scancode(): number {
@@ -18,14 +16,14 @@ class KeystrokeAction extends KeyAction implements Serializable<KeystrokeAction>
} }
fromJsObject(jsObject: any): KeystrokeAction { fromJsObject(jsObject: any): KeystrokeAction {
this.assertKeyActionType(jsObject, KeystrokeAction.keyActionTypeString, 'KeystrokeAction');
this.scancode = jsObject.scancode; this.scancode = jsObject.scancode;
this.modifierMask = jsObject.modifierMask;
return this; return this;
} }
fromBinary(buffer: UhkBuffer): KeystrokeAction { fromBinary(buffer: UhkBuffer): KeystrokeAction {
this.readAndAssertKeyActionId(buffer, KeyActionId.KeystrokeAction, 'KeystrokeAction');
this.scancode = buffer.readUInt8(); this.scancode = buffer.readUInt8();
this.modifierMask = buffer.readUInt8();
return this; return this;
} }
@@ -33,12 +31,11 @@ class KeystrokeAction extends KeyAction implements Serializable<KeystrokeAction>
return { return {
keyActionType: KeystrokeAction.keyActionTypeString, keyActionType: KeystrokeAction.keyActionTypeString,
scancode: this.scancode, scancode: this.scancode,
modifierMask: this.modifierMask
}; };
} }
toBinary(buffer: UhkBuffer) { toBinary(buffer: UhkBuffer) {
buffer.writeUInt8(KeyActionId.KeystrokeAction);
buffer.writeUInt8(this.scancode); buffer.writeUInt8(this.scancode);
buffer.writeUInt8(this.modifierMask);
} }
} }

View File

@@ -0,0 +1,48 @@
class KeystrokeWithModifiersAction extends KeyAction implements Serializable<KeystrokeWithModifiersAction> {
static keyActionTypeString = 'keystrokeWithModifiers';
modifierMask: number;
private _scancode: number;
get scancode(): number {
return this._scancode;
}
set scancode(value) {
if (!TypeChecker.isScancodeValid(value)) {
throw 'Invalid KeystrokeWithModifiersAction.scancode: ${scancode}';
}
this._scancode = value;
}
fromJsObject(jsObject: any): KeystrokeWithModifiersAction {
this.assertKeyActionType(
jsObject, KeystrokeWithModifiersAction.keyActionTypeString, 'KeystrokeWithModifiersAction');
this.scancode = jsObject.scancode;
this.modifierMask = jsObject.modifierMask;
return this;
}
fromBinary(buffer: UhkBuffer): KeystrokeWithModifiersAction {
this.readAndAssertKeyActionId(buffer, KeyActionId.KeystrokeWithModifiersAction, 'KeystrokeWithModifiersAction');
this.scancode = buffer.readUInt8();
this.modifierMask = buffer.readUInt8();
return this;
}
toJsObject(): any {
return {
keyActionType: KeystrokeWithModifiersAction.keyActionTypeString,
scancode: this.scancode,
modifierMask: this.modifierMask
};
}
toBinary(buffer: UhkBuffer) {
buffer.writeUInt8(KeyActionId.KeystrokeWithModifiersAction);
buffer.writeUInt8(this.scancode);
buffer.writeUInt8(this.modifierMask);
}
}

View File

@@ -35,15 +35,13 @@ class MouseAction extends KeyAction implements Serializable<MouseAction> {
} }
fromJsObject(jsObject: any): MouseAction { fromJsObject(jsObject: any): MouseAction {
this.assertKeyActionType(jsObject, MouseAction.keyActionTypeString, 'MouseAction');
this.mouseAction = jsObject.mouseAction; this.mouseAction = jsObject.mouseAction;
return this; return this;
} }
fromBinary(buffer: UhkBuffer): MouseAction { fromBinary(buffer: UhkBuffer): MouseAction {
let keyActionId = buffer.readUInt8(); this.readAndAssertKeyActionId(buffer, KeyActionId.MouseAction, 'MouseAction');
if (keyActionId !== KeyActionId.MouseAction) {
throw 'Invalid MouseAction.id: ${keyActionId}';
}
this.mouseAction = buffer.readUInt8(); this.mouseAction = buffer.readUInt8();
if (!MouseAction.isMouseActionValid(this.mouseAction)) { if (!MouseAction.isMouseActionValid(this.mouseAction)) {

View File

@@ -4,17 +4,12 @@ class NoneAction extends KeyAction implements Serializable<NoneAction> {
static noneActionParam = 0; static noneActionParam = 0;
fromJsObject(jsObject: any): NoneAction { fromJsObject(jsObject: any): NoneAction {
if (jsObject.keyActionType !== NoneAction.keyActionTypeString) { this.assertKeyActionType(jsObject, NoneAction.keyActionTypeString, 'NoneAction');
throw 'Invalid NoneAction.keyActionType: "${jsObject.keyActionType}"';
}
return this; return this;
} }
fromBinary(buffer: UhkBuffer): NoneAction { fromBinary(buffer: UhkBuffer): NoneAction {
let keyActionId = buffer.readUInt8(); this.readAndAssertKeyActionId(buffer, KeyActionId.NoneAction, 'NoneAction');
if (keyActionId !== KeyActionId.NoneAction) {
throw 'Invalid NoneAction.id: ${keyActionId}';
}
let keyActionParam = buffer.readUInt8(); let keyActionParam = buffer.readUInt8();
if (keyActionParam !== NoneAction.noneActionParam) { if (keyActionParam !== NoneAction.noneActionParam) {
@@ -32,6 +27,5 @@ class NoneAction extends KeyAction implements Serializable<NoneAction> {
toBinary(buffer: UhkBuffer) { toBinary(buffer: UhkBuffer) {
buffer.writeUInt8(KeyActionId.NoneAction); buffer.writeUInt8(KeyActionId.NoneAction);
buffer.writeUInt8(NoneAction.noneActionParam);
} }
} }

View File

@@ -16,20 +16,13 @@ class PlayMacroAction extends KeyAction implements Serializable<PlayMacroAction>
} }
fromJsObject(jsObject: any): PlayMacroAction { fromJsObject(jsObject: any): PlayMacroAction {
if (jsObject.keyActionType !== PlayMacroAction.keyActionTypeString) { this.assertKeyActionType(jsObject, PlayMacroAction.keyActionTypeString, 'PlayMacroAction');
throw 'Invalid PlayMacroAction.keyActionType: "${jsObject.keyActionType}"';
}
this.macroId = jsObject.macroId; this.macroId = jsObject.macroId;
return this; return this;
} }
fromBinary(buffer: UhkBuffer): PlayMacroAction { fromBinary(buffer: UhkBuffer): PlayMacroAction {
let keyActionId = buffer.readUInt8(); this.readAndAssertKeyActionId(buffer, KeyActionId.PlayMacroAction, 'PlayMacroAction');
if (keyActionId !== KeyActionId.PlayMacroAction) {
throw 'Invalid PlayMacroAction.keyActionId: ${keyActionId}';
}
this.macroId = buffer.readUInt8(); this.macroId = buffer.readUInt8();
return this; return this;
} }

View File

@@ -16,11 +16,13 @@ class SwitchKeymapAction extends KeyAction implements Serializable<SwitchKeymapA
} }
fromJsObject(jsObject: any): SwitchKeymapAction { fromJsObject(jsObject: any): SwitchKeymapAction {
this.assertKeyActionType(jsObject, SwitchKeymapAction.keyActionTypeString, 'SwitchKeymapAction');
this.keymapId = jsObject.keymapId; this.keymapId = jsObject.keymapId;
return this; return this;
} }
fromBinary(buffer: UhkBuffer): SwitchKeymapAction { fromBinary(buffer: UhkBuffer): SwitchKeymapAction {
this.readAndAssertKeyActionId(buffer, KeyActionId.SwitchKeymapAction, 'SwitchKeymapAction');
this.keymapId = buffer.readUInt8(); this.keymapId = buffer.readUInt8();
return this; return this;
} }

View File

@@ -1,5 +1,6 @@
/// <reference path="KeyAction.ts" /> /// <reference path="KeyAction.ts" />
/// <reference path="KeystrokeAction.ts" /> /// <reference path="KeystrokeAction.ts" />
/// <reference path="KeystrokeWithModifiersAction.ts" />
/// <reference path="DualRoleKeystrokeAction.ts" /> /// <reference path="DualRoleKeystrokeAction.ts" />
/// <reference path="MouseAction.ts" /> /// <reference path="MouseAction.ts" />
/// <reference path="PlayMacroAction.ts" /> /// <reference path="PlayMacroAction.ts" />