Browse Source

Add modem status functionality to UART class (#980)

Nathan Byrd 2 months ago
parent
commit
8064e19dac
2 changed files with 111 additions and 1 deletions
  1. 40 0
      src/browser/starter.js
  2. 71 1
      src/uart.js

+ 40 - 0
src/browser/starter.js

@@ -1121,6 +1121,46 @@ V86.prototype.serial_send_bytes = function(serial, data)
     }
 };
 
+/**
+ * Set the modem status of a serial port.
+ */
+V86.prototype.serial_set_modem_status = function(serial, status)
+{
+    this.bus.send("serial" + serial + "-modem-status-input", status);
+};
+
+/**
+ * Set the carrier detect status of a serial port.
+ */
+V86.prototype.serial_set_carrier_detect = function(serial, status)
+{
+    this.bus.send("serial" + serial + "-carrier-detect-input", status);
+};
+
+/**
+ * Set the ring indicator status of a serial port.
+ */
+V86.prototype.serial_set_ring_indicator = function(serial, status)
+{
+    this.bus.send("serial" + serial + "-ring-indicator-input", status);
+};
+
+/**
+ * Set the data set ready status of a serial port.
+ */
+V86.prototype.serial_set_data_set_ready = function(serial, status)
+{
+    this.bus.send("serial" + serial + "-data-set-ready-input", status);
+};
+
+/**
+ * Set the clear to send status of a serial port.
+ */
+V86.prototype.serial_set_clear_to_send = function(serial, status)
+{
+    this.bus.send("serial" + serial + "-clear-to-send-input", status);
+};
+
 /**
  * Mount another filesystem to the current filesystem.
  * @param {string} path Path for the mount point

+ 71 - 1
src/uart.js

@@ -26,6 +26,17 @@ var DLAB = 0x80;
 /** @const */ var UART_LSR_TX_EMPTY        = 0x20; // TX (THR) buffer is empty
 /** @const */ var UART_LSR_TRANSMITTER_EMPTY = 0x40; // TX empty and line is idle
 
+// Modem status register
+/** @const */ var UART_MSR_DCD = 0x7; // Data Carrier Detect
+/** @const */ var UART_MSR_RI = 0x6; // Ring Indicator
+/** @const */ var UART_MSR_DSR = 0x5; // Data Set Ready
+/** @const */ var UART_MSR_CTS = 0x4; // Clear To Send
+// Delta bits
+/** @const */ var UART_MSR_DDCD = 0x3; // Delta DCD
+/** @const */ var UART_MSR_TERI = 0x2; // Trailing Edge RI
+/** @const */ var UART_MSR_DDSR = 0x1; // Delta DSR
+/** @const */ var UART_MSR_DCTS = 0x0; // Delta CTS
+
 
 /**
  * @constructor
@@ -98,6 +109,45 @@ function UART(cpu, port, bus)
         this.data_received(data);
     }, this);
 
+    this.bus.register("serial" + this.com + "-modem-status-input", function(data)
+    {
+        this.set_modem_status(data);
+    }, this);
+
+    // Set individual modem status bits
+
+    this.bus.register("serial" + this.com + "-carrier-detect-input", function(data)
+    {
+        const status = data ?
+            this.modem_status | (1 << UART_MSR_DCD) | (1 << UART_MSR_DDCD) :
+            this.modem_status & ~(1 << UART_MSR_DCD) & ~(1 << UART_MSR_DDCD);
+        this.set_modem_status(status);
+    }, this);
+
+    this.bus.register("serial" + this.com + "-ring-indicator-input", function(data)
+    {
+        const status = data ?
+            this.modem_status | (1 << UART_MSR_RI) | (1 << UART_MSR_TERI) :
+            this.modem_status & ~(1 << UART_MSR_RI) & ~(1 << UART_MSR_TERI);
+        this.set_modem_status(status);
+    }, this);
+
+    this.bus.register("serial" + this.com + "-data-set-ready-input", function(data)
+    {
+        const status = data ?
+            this.modem_status | (1 << UART_MSR_DSR) | (1 << UART_MSR_DDSR) :
+            this.modem_status & ~(1 << UART_MSR_DSR) & ~(1 << UART_MSR_DDSR);
+        this.set_modem_status(status);
+    }, this);
+
+    this.bus.register("serial" + this.com + "-clear-to-send-input", function(data)
+    {
+        const status = data ?
+            this.modem_status | (1 << UART_MSR_CTS) | (1 << UART_MSR_DCTS) :
+            this.modem_status & ~(1 << UART_MSR_CTS) & ~(1 << UART_MSR_DCTS);
+        this.set_modem_status(status);
+    }, this);
+
     var io = cpu.io;
 
     io.register_write(port, this, function(out_byte)
@@ -227,11 +277,14 @@ function UART(cpu, port, bus)
     io.register_read(port | 6, this, function()
     {
         dbg_log("read modem status: " + h(this.modem_status), LOG_SERIAL);
+        // Clear delta bits
+        this.modem_status &= 0xF0;
         return this.modem_status;
     });
     io.register_write(port | 6, this, function(out_byte)
     {
-        dbg_log("Unkown register write (base+6)", LOG_SERIAL);
+        dbg_log("write modem status: " + h(out_byte), LOG_SERIAL);
+        this.set_modem_status(out_byte);
     });
 
     io.register_read(port | 7, this, function()
@@ -357,3 +410,20 @@ UART.prototype.write_data = function(out_byte)
         }
     }
 };
+
+UART.prototype.set_modem_status = function(status)
+{
+    dbg_log("modem status: " + h(status), LOG_SERIAL);
+    const prev_delta_bits = this.modem_status & 0x0F;
+    // compare the bits that have changed and shift them into the delta bits
+    let delta = (this.modem_status ^ status) >> 4;
+    // The delta should stay set if they were previously set
+    delta |= prev_delta_bits;
+
+    // update the current modem status
+    this.modem_status = status;
+    // update the delta bits based on the changes and previous
+    // values, but also leave the delta bits set if they were
+    // passed in as part of the status
+    this.modem_status |= delta;
+};