Added LED support to VT100 keyboard

This commit is contained in:
Jeff Parsons 2016-08-02 14:44:31 -07:00 committed by Jeff Parsons
commit 999828da4e
4 changed files with 640 additions and 409 deletions

View file

@ -57,6 +57,20 @@ function Keyboard(parmsKbd)
Component.subclass(Keyboard);
Keyboard.VT100 = {
STATUS: {
PORT: 0x82, // write-only
LED4: 0x01,
LED3: 0x02,
LED2: 0x04,
LED1: 0x08,
LOCKED: 0x10,
ONLINE: 0x20,
START: 0x40,
CLICK: 0x80
}
};
/**
* Alphanumeric and other common (printable) ASCII codes.
*
@ -234,6 +248,8 @@ Keyboard.SOFTCODES = {
'fire': Keyboard.KEYCODE.SPACE
};
Keyboard.MINPRESSTIME = 100; // 100ms
/**
* Alternate keyCode mappings (to support the popular WASD directional mappings)
*
@ -246,44 +262,13 @@ Keyboard.ALTCODES[Keyboard.ASCII.D] = Keyboard.KEYCODE.RIGHT;
Keyboard.ALTCODES[Keyboard.ASCII.L] = Keyboard.KEYCODE.SPACE;
Keyboard.LEDSTATES = {
'l1': 0x01,
'l2': 0x02,
'l3': 0x04,
'l4': 0x08,
'locked': 0x10,
'local': 0x20,
'online': 0x40
};
/**
* getSoftCode(keyCode)
*
* @this {Keyboard}
* @return {string|null}
*/
Keyboard.prototype.getSoftCode = function(keyCode)
{
keyCode = Keyboard.ALTCODES[keyCode] || keyCode;
for (var sSoftCode in Keyboard.SOFTCODES) {
if (Keyboard.SOFTCODES[sSoftCode] === keyCode) {
return sSoftCode;
}
}
return null;
};
/**
* reset()
*
* @this {Keyboard}
*/
Keyboard.prototype.reset = function()
{
/*
* As SOFTCODE keyDown events are encountered, a corresponding property is set to true in
* keysPressed, and as SOFTCODE keyUp events are encountered, the property is set to false.
*/
this.keysPressed = {};
'l4': Keyboard.VT100.STATUS.LED4,
'l3': Keyboard.VT100.STATUS.LED3,
'l2': Keyboard.VT100.STATUS.LED2,
'l1': Keyboard.VT100.STATUS.LED1,
'locked': Keyboard.VT100.STATUS.LOCKED,
'online': Keyboard.VT100.STATUS.ONLINE,
'local': ~Keyboard.VT100.STATUS.ONLINE
};
/**
@ -372,6 +357,138 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
return false;
};
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {Keyboard}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
*/
Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.dbg = dbg; // NOTE: The "dbg" property must be set for the message functions to work
this.chipset = cmp.getMachineComponent("ChipSet");
this.model = this.chipset.model;
switch(this.model) {
case ChipSet.VT100.MODEL:
this.config = Keyboard.VT100;
break;
}
if (this.config) {
bus.addPortInputTable(this, this.config.portsInput);
bus.addPortOutputTable(this, this.config.portsOutput);
}
};
/**
* powerUp(data, fRepower)
*
* @this {Keyboard}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
Keyboard.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) {
if (!data) {
this.reset();
} else {
if (!this.restore(data)) return false;
}
}
return true;
};
/**
* powerDown(fSave, fShutdown)
*
* @this {Keyboard}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
Keyboard.prototype.powerDown = function(fSave, fShutdown)
{
return fSave? this.save() : true;
};
Keyboard.VT100.init = [
[
0
]
];
/**
* reset()
*
* @this {Keyboard}
*/
Keyboard.prototype.reset = function()
{
/*
* As keyDown events are encountered, a corresponding "softcode" property in keysPressed
* is set to the timestamp of the keyDown event. When the corresponding keyUp event occurs,
* we look at the elapsed time: if it is less than MINPRESSTIME, then we move the key
* to keysToRelease and set a timeout handler to release the key later; otherwise, we process
* the keyUp event immediately.
*/
this.keysPressed = {};
this.keysToRelease = {};
if (this.config && !this.restore(this.config.init)) {
this.notice("reset error");
}
};
/**
* save()
*
* This implements save support for the Keyboard component.
*
* @this {Keyboard}
* @return {Object}
*/
Keyboard.prototype.save = function()
{
var state = new State(this);
switch(this.model) {
case ChipSet.SI1978.MODEL:
break;
case ChipSet.VT100.MODEL:
state.set(0, [this.bLEDs]);
break;
}
return state.data();
};
/**
* restore(data)
*
* This implements restore support for the Keyboard component.
*
* @this {Keyboard}
* @param {Object} data
* @return {boolean} true if successful, false if failure
*/
Keyboard.prototype.restore = function(data)
{
var a;
if (data && (a = data[0]) && a.length) {
switch(this.model) {
case ChipSet.SI1978.MODEL:
return true;
case ChipSet.VT100.MODEL:
this.bLEDs = a[0];
this.updateLEDs();
return true;
}
}
return false;
};
/**
* setLED(control, f)
*
@ -388,36 +505,41 @@ Keyboard.prototype.setLED = function(control, f)
};
/**
* updateLEDs(bitState)
* updateLEDs()
*
* @this {Keyboard}
* @param {number} [bitState] is the bit in bitsStateSim that may have changed, if known; undefined if not
*/
Keyboard.prototype.updateLEDs = function(bitState)
Keyboard.prototype.updateLEDs = function()
{
var control;
for (var sBinding in Keyboard.LEDSTATES) {
var id = "led-" + sBinding;
var bitLED = Keyboard.LEDSTATES[sBinding];
if ((!bitState || bitState == bitLED) && (control = this.bindings[id])) {
this.setLED(control, !!bitLED); // !!(this.bKeyboardState & bitLED)
var control = this.bindings[id];
if (control) {
var bitLED = Keyboard.LEDSTATES[sBinding];
var fOn = !!(this.bLEDs & bitLED);
if (bitLED & (bitLED-1)) {
fOn = !(this.bLEDs & ~bitLED);
}
this.setLED(control, fOn);
}
}
};
/**
* initBus(cmp, bus, cpu, dbg)
* getSoftCode(keyCode)
*
* @this {Keyboard}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @return {string|null}
*/
Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
Keyboard.prototype.getSoftCode = function(keyCode)
{
this.dbg = dbg; // NOTE: The "dbg" property must be set for the message functions to work
this.chipset = cmp.getMachineComponent("ChipSet");
keyCode = Keyboard.ALTCODES[keyCode] || keyCode;
for (var sSoftCode in Keyboard.SOFTCODES) {
if (Keyboard.SOFTCODES[sSoftCode] === keyCode) {
return sSoftCode;
}
}
return null;
};
/**
@ -425,7 +547,7 @@ Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
*
* @this {Keyboard}
* @param {Object} event
* @param {boolean} fDown is true for a keyDown event, false for a keyUp event
* @param {boolean} fDown is true for a keyDown event, false for up
* @return {boolean} true to pass the event along, false to consume it
*/
Keyboard.prototype.onKeyDown = function(event, fDown)
@ -454,12 +576,27 @@ Keyboard.prototype.onKeyDown = function(event, fDown)
*
* @this {Keyboard}
* @param {string} sSoftCode
* @param {boolean} fDown is true for a down event, false for an up event
* @param {boolean} fDown is true for a down event, false for up
* @return {boolean} true to pass the event along, false to consume it
*/
Keyboard.prototype.onSoftKeyDown = function(sSoftCode, fDown)
{
this.keysPressed[sSoftCode] = fDown;
if (fDown) {
this.keysPressed[sSoftCode] = Date.now();
delete this.keysToRelease[sSoftCode];
} else {
var msDown = this.keysPressed[sSoftCode];
this.assert(msDown);
if (msDown) {
var msElapsed = Date.now() - msDown;
if (msElapsed < Keyboard.MINPRESSTIME) {
this.keysToRelease[sSoftCode] = msDown;
this.checkSoftKeysToRelease();
return true;
}
}
delete this.keysPressed[sSoftCode];
}
if (this.chipset) {
switch(sSoftCode) {
@ -488,7 +625,60 @@ Keyboard.prototype.onSoftKeyDown = function(sSoftCode, fDown)
break;
}
}
return false;
return true;
};
/**
* checkSoftKeysToRelease()
*
* @this {Keyboard}
*/
Keyboard.prototype.checkSoftKeysToRelease = function()
{
var msDelayMin = -1;
var asSoftCodes = Object.keys(this.keysToRelease);
for (var sSoftCode in asSoftCodes) {
var msDown = this.keysToRelease[sSoftCode];
var msElapsed = Date.now() - msDown;
var msDelay = Keyboard.MINPRESSTIME - msElapsed;
if (msDelay > 0) {
if (msDelayMin < 0 || msDelayMin > msDelay) {
msDelayMin = msDelay;
}
} else {
delete this.keysToRelease[sSoftCode];
this.onSoftKeyDown(sSoftCode, false);
}
}
if (msDelayMin >= 0) {
var kbd = this;
setTimeout(function() { kbd.checkSoftKeysToRelease(); }, msDelayMin);
}
};
/**
* outVT100UARTStatus(port, b, addrFrom)
*
* @this {Keyboard}
* @param {number} port (0x82)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
Keyboard.prototype.outVT100UARTStatus = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "KBDUART.STATUS", null, true);
this.bLEDs = b;
this.updateLEDs();
};
/*
* Port notification tables
*/
Keyboard.VT100.portsInput = {
};
Keyboard.VT100.portsOutput = {
0x82: Keyboard.prototype.outVT100UARTStatus
};
/**