v86 / src /browser /serial.js
peterpeter8585's picture
Upload 553 files
8df6da4 verified
import { dbg_assert, dbg_log } from "../log.js";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* @constructor
*
* @param {BusConnector} bus
*/
export function SerialAdapter(element, bus)
{
var serial = this;
this.enabled = true;
this.bus = bus;
this.text = "";
this.text_new_line = false;
this.last_update = 0;
this.bus.register("serial0-output-byte", function(byte)
{
var chr = String.fromCharCode(byte);
this.show_char(chr);
}, this);
this.destroy = function()
{
element.removeEventListener("keypress", keypress_handler, false);
element.removeEventListener("keydown", keydown_handler, false);
element.removeEventListener("paste", paste_handler, false);
window.removeEventListener("mousedown", window_click_handler, false);
};
this.init = function()
{
this.destroy();
element.style.display = "block";
element.addEventListener("keypress", keypress_handler, false);
element.addEventListener("keydown", keydown_handler, false);
element.addEventListener("paste", paste_handler, false);
window.addEventListener("mousedown", window_click_handler, false);
};
this.init();
this.show_char = function(chr)
{
if(chr === "\x08")
{
this.text = this.text.slice(0, -1);
this.update();
}
else if(chr === "\r")
{
// do nothing
}
else
{
this.text += chr;
if(chr === "\n")
{
this.text_new_line = true;
}
this.update();
}
};
this.update = function()
{
var now = Date.now();
var delta = now - this.last_update;
if(delta < 16)
{
if(this.update_timer === undefined)
{
this.update_timer = setTimeout(() => {
this.update_timer = undefined;
var now = Date.now();
dbg_assert(now - this.last_update >= 15);
this.last_update = now;
this.render();
}, 16 - delta);
}
}
else
{
if(this.update_timer !== undefined)
{
clearTimeout(this.update_timer);
this.update_timer = undefined;
}
this.last_update = now;
this.render();
}
};
this.render = function()
{
element.value = this.text;
if(this.text_new_line)
{
this.text_new_line = false;
element.scrollTop = 1e9;
}
};
/**
* @param {number} chr_code
*/
this.send_char = function(chr_code)
{
if(serial.bus)
{
serial.bus.send("serial0-input", chr_code);
}
};
function may_handle(e)
{
if(!serial.enabled)
{
return false;
}
// Something here?
return true;
}
function keypress_handler(e)
{
if(!serial.bus)
{
return;
}
if(!may_handle(e))
{
return;
}
var chr = e.which;
serial.send_char(chr);
e.preventDefault();
}
function keydown_handler(e)
{
var chr = e.which;
if(chr === 8)
{
// supress backspace
serial.send_char(127);
e.preventDefault();
}
else if(chr === 9)
{
// tab
serial.send_char(9);
e.preventDefault();
}
}
function paste_handler(e)
{
if(!may_handle(e))
{
return;
}
var data = e.clipboardData.getData("text/plain");
for(var i = 0; i < data.length; i++)
{
serial.send_char(data.charCodeAt(i));
}
e.preventDefault();
}
function window_click_handler(e)
{
if(e.target !== element)
{
element.blur();
}
}
}
/**
* @constructor
*
* @param {BusConnector} bus
*/
function SerialRecordingAdapter(bus)
{
var serial = this;
this.text = "";
bus.register("serial0-output-byte", function(byte)
{
var chr = String.fromCharCode(byte);
this.text += chr;
}, this);
}
/**
* @constructor
* @param {BusConnector} bus
*/
export function SerialAdapterXtermJS(element, bus)
{
this.element = element;
if(!window["Terminal"])
{
return;
}
var term = this.term = new window["Terminal"]({
"logLevel": "off",
"convertEol": "true",
});
term.write("This is the serial console. Whatever you type or paste here will be sent to COM1");
const on_data_disposable = term["onData"](function(data) {
for(let i = 0; i < data.length; i++)
{
bus.send("serial0-input", data.charCodeAt(i));
}
});
bus.register("serial0-output-byte", function(byte)
{
term.write(Uint8Array.of(byte));
}, this);
this.destroy = function() {
on_data_disposable["dispose"]();
term["dispose"]();
};
}
SerialAdapterXtermJS.prototype.show = function()
{
this.term && this.term.open(this.element);
};