Started laying groundwork for more mouse hardware

This commit is contained in:
Jeff Parsons 2017-08-24 19:20:39 -07:00 committed by Jeff Parsons
commit b91eaeba48
14 changed files with 2087 additions and 1511 deletions

View file

@ -51,24 +51,26 @@ class Mouse extends Component {
*
* The Mouse component has the following component-specific (parmsMouse) properties:
*
* serial: the ID of the corresponding serial component
* adapter: 1 (primary) or 2 (secondary); 0 if not defined
*
* Since the first version of this component supports ONLY emulation of the original Microsoft
* serial mouse, a valid serial component ID is required. It's possible that future versions
* of this component may support other types of simulated hardware (eg, the Microsoft InPort
* bus mouse adapter), or a virtual driver interface that would eliminate the need for any
* intermediate hardware simulation (at the expense of writing an intermediate software layer or
* virtual driver for each supported operating system). However, those possibilities are extremely
* unlikely in the near term.
* binding: name of a corresponding device component (implies type is "serial")
*
* If the 'serial' property is specified, then communication will be established with the
* SerialPort component, requesting access to the corresponding serial component ID. If the
* SerialPort component is not installed and/or the specified serial component ID is not present,
* a configuration error will be reported.
* scaleMouse: a floating-point number used to scale incoming mouse coordinates; the default is 0.5
*
* TODO: Just out of curiosity, verify that the Microsoft Bus Mouse used ports 0x23D and 0x23F,
* because I saw Windows v1.01 probing those ports immediately prior to probing COM2 (and then COM1)
* for a serial mouse.
* serial: the ID of a corresponding serial component (used in lieu of type="serial" and binding="ID")
*
* type: one of "bus", "inport", or "serial"; the default is "serial" if serial or binding properties are set
*
* The first version of this component supported ONLY emulation of the original Microsoft serial mouse,
* so a valid serial component ID using the 'serial' property was required. Now, using the 'type' property,
* it's possible to enable support for other types of mouse hardware (eg, 'bus' for the original Microsoft
* Bus Mouse interface or 'inport' for the Microsoft InPort Mouse interface). The 'adapter' property is used
* only when the selected type supports different configurations (eg, primary vs. secondary InPort adapters).
*
* If either the original 'serial' property or the new 'binding' property is set, then serial communication
* will be established with the specified SerialPort component, requesting access to the corresponding serial
* component ID. If the SerialPort component is not installed and/or the specified serial component ID is not
* present, a configuration error will be reported.
*
* @this {Mouse}
* @param {Object} parmsMouse
@ -77,18 +79,22 @@ class Mouse extends Component {
{
super("Mouse", parmsMouse, Messages.MOUSE);
this.idAdapter = parmsMouse['serial'];
if (this.idAdapter) this.sAdapterType = "SerialPort";
this.iAdapter = parmsMouse['adapter'] || 0;
this.idDevice = parmsMouse['serial'] || parmsMouse['binding'];
this.sType = parmsMouse['type'] || (this.idDevice? Mouse.TYPE.SERIAL : Mouse.TYPE.BUS);
this.typeDevice = (this.sType == Mouse.TYPE.SERIAL? "SerialPort" : null);
this.componentDevice = null;
this.scale = parmsMouse['scaleMouse'];
this.setActive(false);
this.fCaptured = this.fLocked = false;
this.fActive = this.fCaptured = this.fLocked = false;
/*
* Initially, no video devices, and therefore no screens, are attached. initBus() will update aVideo,
* and powerUp() will update aScreens.
*/
this.aVideo = [];
this.aScreens = [];
this.setReady();
}
/**
@ -113,6 +119,11 @@ class Mouse extends Component {
for (var video = null; (video = cmp.getMachineComponent("Video", video));) {
this.aVideo.push(video);
}
if (this.sType == Mouse.TYPE.BUS) {
bus.addPortInputTable(this, Mouse.aBusInput, Mouse.BUS.DATA.PORT);
bus.addPortOutputTable(this, Mouse.aBusOutput, Mouse.BUS.DATA.PORT);
}
this.setReady();
}
/**
@ -161,35 +172,35 @@ class Mouse extends Component {
} else {
if (!this.restore(data)) return false;
}
if (this.sAdapterType && !this.componentAdapter) {
var componentAdapter = null;
while ((componentAdapter = this.cmp.getMachineComponent(this.sAdapterType, componentAdapter))) {
if (componentAdapter.attachMouse) {
this.componentAdapter = componentAdapter.attachMouse(this.idAdapter, this, this.receiveStatus);
if (this.componentAdapter) {
if (this.typeDevice && !this.componentDevice) {
var componentDevice = null;
while ((componentDevice = this.cmp.getMachineComponent(this.typeDevice, componentDevice))) {
if (componentDevice.attachMouse) {
this.componentDevice = componentDevice.attachMouse(this.idDevice, this, this.receiveStatus);
if (this.componentDevice) {
/*
* It's possible that the SerialPort we've just attached to might want to bring us "up to speed"
* on the adapter's state, which is why I envisioned a subsequent syncMouse() call. And you would
* want to do that as a separate call, not as part of attachMouse(), because componentAdapter
* on the device's state, which is why I envisioned a subsequent syncMouse() call. And you would
* want to do that as a separate call, not as part of attachMouse(), because componentDevice
* isn't set until attachMouse() returns.
*
* However, syncMouse() seems unnecessary, given that SerialPort initializes its MCR to an "inactive"
* state, and even when restoring a previous state, if we've done our job properly, both SerialPort
* and Mouse should be restored in sync, making any explicit attempt at sync'ing unnecessary (or so I hope).
*/
// this.componentAdapter.syncMouse();
// this.componentDevice.syncMouse();
break;
}
}
}
if (this.componentAdapter) {
if (this.componentDevice) {
this.aScreens = []; // ensure the screen array is empty before (re)filling it
for (var i = 0; i < this.aVideo.length; i++) {
var screen = this.aVideo[i].getScreen(this);
if (screen) this.aScreens.push(screen);
}
} else {
Component.warning(this.id + ": " + this.sAdapterType + " " + this.idAdapter + " unavailable");
Component.warning(this.id + ": " + this.typeDevice + " " + this.idDevice + " unavailable");
}
}
if (this.fActive) {
@ -552,7 +563,7 @@ class Mouse extends Component {
if (this.messageEnabled(Messages.SERIAL)) {
this.printMessage((sDiag? (sDiag + ": ") : "") + (yDiag !== undefined? ("mouse (" + xDiag + "," + yDiag + "): ") : "") + "serial packet [" + Str.toHexByte(b1) + "," + Str.toHexByte(b2) + "," + Str.toHexByte(b3) + "]", 0, true);
}
this.componentAdapter.receiveData([b1, b2, b3]);
this.componentDevice.receiveData([b1, b2, b3]);
this.xDelta = this.yDelta = 0;
}
@ -563,7 +574,7 @@ class Mouse extends Component {
*
* During normal serial mouse operation, both RTS and DTR must be "positive".
*
* Setting RTS "negative" for 100ms resets the mouse. Toggling DTR requests an identification byte (ID_SERIAL).
* Setting RTS "negative" for 100ms resets the mouse. Toggling DTR requests an identification byte (SERIAL.ID).
*
* NOTES: The above 3rd-party information notwithstanding, I've observed that Windows v1.01 initially writes 0x01
* to the MCR (DTR on, RTS off), spins in a loop that reads the RBR (probably to avoid a bogus identification byte
@ -606,11 +617,11 @@ class Mouse extends Component {
* its failure to properly terminate-and-stay-resident when its initial INT 0x33 reset returns an error,
* I'm not in the mood to give it the benefit of the doubt.
*
* So, anyway, I solve the terminate-and-stay-resident bug in MOUSE.COM v8.20 by feeding it *two* ID_SERIAL
* So, anyway, I solve the terminate-and-stay-resident bug in MOUSE.COM v8.20 by feeding it *two* SERIAL.ID
* bytes on a reset. This doesn't seem to adversely affect serial mouse emulation for Windows 1.01, so
* I'm calling this good enough for now.
*/
this.componentAdapter.receiveData([Mouse.ID_SERIAL, Mouse.ID_SERIAL]);
this.componentDevice.receiveData([Mouse.SERIAL.ID, Mouse.SERIAL.ID]);
this.printMessage("serial mouse ID sent");
}
this.captureAll();
@ -638,6 +649,118 @@ class Mouse extends Component {
this.pins = pins;
}
/**
* inBusData(port, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23C)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number} simulated port value
*/
inBusData(port, addrFrom)
{
var b = 0;
this.printMessageIO(port, null, addrFrom, "DATA", b);
return b;
}
/**
* inBusTPPI(port, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23D)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number} simulated port value
*/
inBusTPPI(port, addrFrom)
{
var b = 0;
this.printMessageIO(port, null, addrFrom, "TPPI", b);
return b;
}
/**
* inBusCtrl(port, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23E)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number} simulated port value
*/
inBusCtrl(port, addrFrom)
{
var b = 0;
this.printMessageIO(port, null, addrFrom, "CTRL", b);
return b;
}
/**
* inBusCPPI(port, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23F)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number} simulated port value
*/
inBusCPPI(port, addrFrom)
{
var b = 0;
this.printMessageIO(port, null, addrFrom, "CPPI", b);
return b;
}
/**
* outBusData(port, bOut, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23C)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
outBusData(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "DATA");
}
/**
* outBusTPPI(port, bOut, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23D)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
outBusTPPI(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "TPPI");
}
/**
* outBusCtrl(port, bOut, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23E)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
outBusCtrl(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "CTRL");
}
/**
* outBusCPPI(port, bOut, addrFrom)
*
* @this {Mouse}
* @param {number} port (eg, 0x23F)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
outBusCPPI(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "CPPI");
}
/**
* Mouse.init()
*
@ -658,6 +781,121 @@ class Mouse extends Component {
}
}
Mouse.TYPE = {
BUS: "bus",
INPORT: "inport",
SERIAL: "serial"
};
Mouse.BUTTON = {
LEFT: 0,
RIGHT: 2
};
/*
* The Microsoft Bus Mouse supported only one base address: 0x23C.
*
* NOTE: Windows v1.01 probes ports 0x23D and 0x23F immediately prior to probing COM2 (and then COM1)
* for a serial mouse.
*/
Mouse.BUS = {
DATA: { // Mouse Data Register
PORT: 0x23C
},
TPPI: { // 8255 (PPI) Test Register
PORT: 0x23D
},
CTRL: { // Mouse Control Register
PORT: 0x23E
},
CPPI: { // 8255 (PPI) Control Register
PORT: 0x23F
}
};
Mouse.aBusInput = {
0x0: Mouse.prototype.inBusData,
0x1: Mouse.prototype.inBusTPPI,
0x2: Mouse.prototype.inBusCtrl,
0x3: Mouse.prototype.inBusCPPI
};
Mouse.aBusOutput = {
0x0: Mouse.prototype.outBusData,
0x1: Mouse.prototype.outBusTPPI,
0x2: Mouse.prototype.outBusCtrl,
0x3: Mouse.prototype.outBusCPPI
};
/*
* The retail Microsoft InPort card supported two base addresses, 0x23C and 0x238, through the primary and
* secondary jumpers, respectively. However, OEMs may have had InPorts on other base addresses.
*
* Here's a typical InPort Mouse detection sequence:
*
* S = IN(Mouse.INPORT.ID.PORT)
* ...
* VERIFY THAT S EQUALS Mouse.INPORT.ID.CHIP
* T = IN(Mouse.INPORT.ID.PORT)
* ...
* VERIFY ADDITIONAL PAIRS OF READS RETURN MATCHING S AND T VALUES
*
* Here's a typical InPort Mouse interrupt sequence:
*
* OUT(Mouse.INPORT.ADDR.PORT, Mouse.INPORT.ADDR.MODE)
* OUT(Mouse.INPORT.DATA.PORT, IN(Mouse.INPORT.DATA.PORT) | Mouse.INPORT.DATA.MODE.HOLD)
* ...
* OUT(Mouse.INPORT.ADDR.PORT, Mouse.INPORT.ADDR.X)
* X = IN(Mouse.INPORT.DATA.PORT)
* OUT(Mouse.INPORT.ADDR.PORT, Mouse.INPORT.ADDR.Y)
* Y = IN(Mouse.INPORT.DATA.PORT)
* OUT(Mouse.INPORT.ADDR.PORT, Mouse.INPORT.ADDR.STATUS)
* B = IN(Mouse.INPORT.DATA.PORT) & (Mouse.INPORT.DATA.STATUS.B1 | Mouse.INPORT.DATA.STATUS.B2 | Mouse.INPORT.DATA.STATUS.B3)
* ...
* OUT(Mouse.INPORT.ADDR.PORT, Mouse.INPORT.ADDR.MODE)
* OUT(Mouse.INPORT.DATA.PORT, IN(Mouse.INPORT.DATA.PORT) & ~Mouse.INPORT.DATA.MODE.HOLD)
*/
Mouse.INPORT = {
ADDR: {
PORT: 0x23C,
STATUS: 0x00, // InPort Status Register
X: 0x01, // InPort X Movement Register
Y: 0x02, // InPort Y Movement Register
ISTAT: 0x05, // InPort Interface Status Register
ICTRL: 0x06, // InPort Interface Control Register
MODE: 0x07 // InPort Mode Register
},
DATA: {
PORT: 0x23D,
STATUS: { // InPort Status Register (0)
B3: 0x01, // Status button 3
B2: 0x02, // Status button 2
B1: 0x04, // Status button 1
DB3: 0x08, // Delta button 3
DB2: 0x10, // Delta button 2
DB1: 0x20, // Delta button 1
MOVE: 0x40, // Movement
PACKET: 0x80 // Packet complete
},
MODE: { // InPort Mode Register (7)
HOLD: 0x20 // hold the status for reading
}
/*
* The internal register read or written via this port is determined by the value written to ADDR.PORT
*/
},
ID: {
PORT: 0x23E,
CHIP: 0xDE // InPort Chip ID
/*
* Alternate reads return a byte containing InPort revision number in low nibble, version number in high nibble
*/
},
TEST: {
PORT: 0x23F
}
};
/*
* From http://paulbourke.net/dataformats/serialmouse:
*
@ -733,12 +971,8 @@ class Mouse extends Component {
* The high order bit of each byte (D7) is ignored. Bit D6 indicates the start of an event, which allows the software to
* synchronize with the mouse.
*/
Mouse.ID_SERIAL = 0x4D;
Mouse.BUTTON = {
LEFT: 0,
RIGHT: 2
Mouse.SERIAL = {
ID: 0x4D
};
/*

View file

@ -1004,70 +1004,74 @@ SerialPort.sIOBuffer = "buffer";
* 0x0002 56000 2.86%
* 0x0001 128000
*/
SerialPort.DLL = {REG: 0}; // Divisor Latch LSB (only when SerialPort.LCR.DLAB is set)
SerialPort.THR = {REG: 0}; // Transmitter Holding Register (write)
SerialPort.DL_DEFAULT = 0x180; // we select an arbitrary default Divisor Latch equivalent to 300 baud
SerialPort.DLL = {REG: 0}; // Divisor Latch LSB (only when SerialPort.LCR.DLAB is set)
SerialPort.THR = {REG: 0}; // Transmitter Holding Register (write)
SerialPort.DL_DEFAULT = 0x180; // we select an arbitrary default Divisor Latch equivalent to 300 baud
/*
* Receiver Buffer Register (RBR.REG, offset 0; eg, 0x3F8 or 0x2F8) on read, Transmitter Holding Register on write
*/
SerialPort.RBR = {REG: 0}; // (read)
SerialPort.RBR = {REG: 0}; // (read)
/*
* Interrupt Enable Register (IER.REG, offset 1; eg, 0x3F9 or 0x2F9)
*/
SerialPort.IER = {};
SerialPort.IER.REG = 1; // Interrupt Enable Register
SerialPort.IER.RBR_AVAIL = 0x01;
SerialPort.IER.THR_EMPTY = 0x02;
SerialPort.IER.LSR_DELTA = 0x04;
SerialPort.IER.MSR_DELTA = 0x08;
SerialPort.IER.UNUSED = 0xF0; // always zero
SerialPort.IER = {
REG: 1, // Interrupt Enable Register
RBR_AVAIL: 0x01,
THR_EMPTY: 0x02,
LSR_DELTA: 0x04,
MSR_DELTA: 0x08,
UNUSED: 0xF0 // always zero
};
SerialPort.DLM = {REG: 1}; // Divisor Latch MSB (only when SerialPort.LCR.DLAB is set)
SerialPort.DLM = {REG: 1}; // Divisor Latch MSB (only when SerialPort.LCR.DLAB is set)
/*
* Interrupt ID Register (IIR.REG, offset 2; eg, 0x3FA or 0x2FA)
*
* All interrupt conditions cleared by reading the corresponding register (or, in the case of IRR_INT_THR, writing a new value to THR.REG)
*/
SerialPort.IIR = {};
SerialPort.IIR.REG = 2; // Interrupt ID Register (read-only)
SerialPort.IIR.NO_INT = 0x01;
SerialPort.IIR.INT_LSR = 0x06; // Line Status (highest priority: Overrun error, Parity error, Framing error, or Break Interrupt)
SerialPort.IIR.INT_RBR = 0x04; // Receiver Data Available
SerialPort.IIR.INT_THR = 0x02; // Transmitter Holding Register Empty
SerialPort.IIR.INT_MSR = 0x00; // Modem Status Register (lowest priority: Clear To Send, Data Set Ready, Ring Indicator, or Data Carrier Detect)
SerialPort.IIR.INT_BITS = 0x06;
SerialPort.IIR.UNUSED = 0xF8; // always zero (the ROM BIOS relies on these bits "floating to 1" when no SerialPort is present)
SerialPort.IIR = {
REG: 2, // Interrupt ID Register (read-only)
NO_INT: 0x01,
INT_LSR: 0x06, // Line Status (highest priority: Overrun error, Parity error, Framing error, or Break Interrupt)
INT_RBR: 0x04, // Receiver Data Available
INT_THR: 0x02, // Transmitter Holding Register Empty
INT_MSR: 0x00, // Modem Status Register (lowest priority: Clear To Send, Data Set Ready, Ring Indicator, or Data Carrier Detect)
INT_BITS: 0x06,
UNUSED: 0xF8 // always zero (the ROM BIOS relies on these bits "floating to 1" when no SerialPort is present)
};
/*
* Line Control Register (LCR.REG, offset 3; eg, 0x3FB or 0x2FB)
*/
SerialPort.LCR = {};
SerialPort.LCR.REG = 3; // Line Control Register
SerialPort.LCR.DATA_5BITS = 0x00;
SerialPort.LCR.DATA_6BITS = 0x01;
SerialPort.LCR.DATA_7BITS = 0x02;
SerialPort.LCR.DATA_8BITS = 0x03;
SerialPort.LCR.STOP_BITS = 0x04; // clear: 1 stop bit; set: 1.5 stop bits for LCR_DATA_5BITS, 2 stop bits for all other data lengths
SerialPort.LCR.PARITY_BIT = 0x08; // if set, a parity bit is inserted/expected between the last data bit and the first stop bit; no parity bit if clear
SerialPort.LCR.PARITY_EVEN = 0x10; // if set, even parity is selected (ie, the parity bit insures an even number of set bits); if clear, odd parity
SerialPort.LCR.PARITY_STICK = 0x20; // if set, parity bit is transmitted inverted; if clear, parity bit is transmitted normally
SerialPort.LCR.BREAK = 0x40; // if set, serial output (SOUT) signal is forced to logical 0 for the duration
SerialPort.LCR.DLAB = 0x80; // Divisor Latch Access Bit; if set, DLL.REG and DLM.REG can be read or written
SerialPort.LCR = {
REG: 3, // Line Control Register
DATA_5BITS: 0x00,
DATA_6BITS: 0x01,
DATA_7BITS: 0x02,
DATA_8BITS: 0x03,
STOP_BITS: 0x04, // clear: 1 stop bit; set: 1.5 stop bits for LCR_DATA_5BITS, 2 stop bits for all other data lengths
PARITY_BIT: 0x08, // if set, a parity bit is inserted/expected between the last data bit and the first stop bit; no parity bit if clear
PARITY_EVEN: 0x10, // if set, even parity is selected (ie, the parity bit insures an even number of set bits); if clear, odd parity
PARITY_STICK: 0x20, // if set, parity bit is transmitted inverted; if clear, parity bit is transmitted normally
BREAK: 0x40, // if set, serial output (SOUT) signal is forced to logical 0 for the duration
DLAB: 0x80 // Divisor Latch Access Bit; if set, DLL.REG and DLM.REG can be read or written
};
/*
* Modem Control Register (MCR.REG, offset 4; eg, 0x3FC or 0x2FC)
*/
SerialPort.MCR = {};
SerialPort.MCR.REG = 4; // Modem Control Register
SerialPort.MCR.DTR = 0x01; // when set, DTR goes high, indicating ready to establish link (looped back to DSR in loop-back mode)
SerialPort.MCR.RTS = 0x02; // when set, RTS goes high, indicating ready to exchange data (looped back to CTS in loop-back mode)
SerialPort.MCR.OUT1 = 0x04; // when set, OUT1 goes high (looped back to RI in loop-back mode)
SerialPort.MCR.OUT2 = 0x08; // when set, OUT2 goes high (looped back to RLSD in loop-back mode)
SerialPort.MCR.LOOPBACK = 0x10; // when set, enables loop-back mode
SerialPort.MCR.UNUSED = 0xE0; // always zero
SerialPort.MCR = {
REG: 4, // Modem Control Register
DTR: 0x01, // when set, DTR goes high, indicating ready to establish link (looped back to DSR in loop-back mode)
RTS: 0x02, // when set, RTS goes high, indicating ready to exchange data (looped back to CTS in loop-back mode)
OUT1: 0x04, // when set, OUT1 goes high (looped back to RI in loop-back mode)
OUT2: 0x08, // when set, OUT2 goes high (looped back to RLSD in loop-back mode)
LOOPBACK: 0x10, // when set, enables loop-back mode
UNUSED: 0xE0 // always zero
};
/*
* Line Status Register (LSR.REG, offset 5; eg, 0x3FD or 0x2FD)
@ -1076,30 +1080,32 @@ SerialPort.MCR.UNUSED = 0xE0; // always zero
* I have calls it TEMT instead of TSRE, and claims that it is set whenever BOTH the THR and TSR are empty, and clear
* whenever EITHER the THR or TSR contain data.
*/
SerialPort.LSR = {};
SerialPort.LSR.REG = 5; // Line Status Register
SerialPort.LSR.DR = 0x01; // Data Ready (set when new data in RBR.REG; cleared when RBR.REG read)
SerialPort.LSR.OE = 0x02; // Overrun Error (set when new data arrives in RBR.REG before previous data read; cleared when LSR.REG read)
SerialPort.LSR.PE = 0x04; // Parity Error (set when new data has incorrect parity; cleared when LSR.REG read)
SerialPort.LSR.FE = 0x08; // Framing Error (set when new data has invalid stop bit; cleared when LSR.REG read)
SerialPort.LSR.BI = 0x10; // Break Interrupt (set when new data exceeded normal transmission time; cleared LSR.REG when read)
SerialPort.LSR.THRE = 0x20; // Transmitter Holding Register Empty (set when UART ready to accept new data; cleared when THR.REG written)
SerialPort.LSR.TSRE = 0x40; // Transmitter Shift Register Empty (set when the TSR is empty; cleared when the THR is transferred to the TSR)
SerialPort.LSR.UNUSED = 0x80; // always zero
SerialPort.LSR = {
REG: 5, // Line Status Register
DR: 0x01, // Data Ready (set when new data in RBR.REG; cleared when RBR.REG read)
OE: 0x02, // Overrun Error (set when new data arrives in RBR.REG before previous data read; cleared when LSR.REG read)
PE: 0x04, // Parity Error (set when new data has incorrect parity; cleared when LSR.REG read)
FE: 0x08, // Framing Error (set when new data has invalid stop bit; cleared when LSR.REG read)
BI: 0x10, // Break Interrupt (set when new data exceeded normal transmission time; cleared LSR.REG when read)
THRE: 0x20, // Transmitter Holding Register Empty (set when UART ready to accept new data; cleared when THR.REG written)
TSRE: 0x40, // Transmitter Shift Register Empty (set when the TSR is empty; cleared when the THR is transferred to the TSR)
UNUSED: 0x80 // always zero
};
/*
* Modem Status Register (MSR.REG, offset 6; eg, 0x3FE or 0x2FE)
*/
SerialPort.MSR = {};
SerialPort.MSR.REG = 6; // Modem Status Register
SerialPort.MSR.DCTS = 0x01; // when set, CTS (Clear To Send) has changed since last read
SerialPort.MSR.DDSR = 0x02; // when set, DSR (Data Set Ready) has changed since last read
SerialPort.MSR.TERI = 0x04; // when set, TERI (Trailing Edge Ring Indicator) indicates RI has changed from 1 to 0
SerialPort.MSR.DRLSD = 0x08; // when set, RLSD (Received Line Signal Detector) has changed
SerialPort.MSR.CTS = 0x10; // when set, the modem or data set is ready to exchange data (complement of the Clear To Send input signal)
SerialPort.MSR.DSR = 0x20; // when set, the modem or data set is ready to establish link (complement of the Data Set Ready input signal)
SerialPort.MSR.RI = 0x40; // complement of the RI (Ring Indicator) input
SerialPort.MSR.RLSD = 0x80; // complement of the RLSD (Received Line Signal Detect) input
SerialPort.MSR = {
REG: 6, // Modem Status Register
DCTS: 0x01, // when set, CTS (Clear To Send) has changed since last read
DDSR: 0x02, // when set, DSR (Data Set Ready) has changed since last read
TERI: 0x04, // when set, TERI (Trailing Edge Ring Indicator) indicates RI has changed from 1 to 0
DRLSD: 0x08, // when set, RLSD (Received Line Signal Detector) has changed
CTS: 0x10, // when set, the modem or data set is ready to exchange data (complement of the Clear To Send input signal)
DSR: 0x20, // when set, the modem or data set is ready to establish link (complement of the Data Set Ready input signal)
RI: 0x40, // complement of the RI (Ring Indicator) input
RLSD: 0x80 // complement of the RLSD (Received Line Signal Detect) input
};
/*
* Scratch Register (SCR.REG, offset 7; eg, 0x3FF or 0x2FF)

View file

@ -924,9 +924,21 @@
<xsl:template match="mouse[not(@ref)]">
<xsl:param name="machine" select="''"/>
<xsl:variable name="serial">
<xsl:variable name="adapter">
<xsl:choose>
<xsl:when test="@serial"><xsl:value-of select="@serial"/></xsl:when>
<xsl:when test="@adapter"><xsl:value-of select="@adapter"/></xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="binding">
<xsl:choose>
<xsl:when test="@binding"><xsl:value-of select="@binding"/></xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="type">
<xsl:choose>
<xsl:when test="@type"><xsl:value-of select="@type"/></xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
@ -936,10 +948,16 @@
<xsl:otherwise>0.5</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="serial">
<xsl:choose>
<xsl:when test="@serial"><xsl:value-of select="@serial"/></xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="component">
<xsl:with-param name="machine" select="$machine"/>
<xsl:with-param name="class">mouse</xsl:with-param>
<xsl:with-param name="parms">,serial:'<xsl:value-of select="$serial"/>',scaleMouse:<xsl:value-of select="$scaleMouse"/></xsl:with-param>
<xsl:with-param name="parms">,adapter:<xsl:value-of select="$adapter"/>,binding:'<xsl:value-of select="$binding"/>',type:'<xsl:value-of select="$type"/>',scaleMouse:<xsl:value-of select="$scaleMouse"/>,serial:'<xsl:value-of select="$serial"/>'</xsl:with-param>
</xsl:call-template>
</xsl:template>