Skip to content

Dial-up Modem device#1523

Open
chschnell wants to merge 2 commits intocopy:masterfrom
chschnell:modem
Open

Dial-up Modem device#1523
chschnell wants to merge 2 commits intocopy:masterfrom
chschnell:modem

Conversation

@chschnell
Copy link
Copy Markdown
Contributor

Addresses #1512.

Add a serial Modem device, see the included documentation for a user guide.

With a few exceptions, this device follows ITU Recommendation V.250 in regards to the AT command interpreter, AT command syntax and the chosen subset of AT commands.

The UART class had to be extended to emit bus messages for changes of its DTR and RTS hardware signals.

There is a slight ugliness in the Modem constructor: It needs to use the bus to send configuration messages to the UART device, but the bus/UART isn't ready at that point in time, so this is delayed until bus event "emulator-ready" is received. It works reliably, but is there a better pattern for this, perhaps move the Modem construction down in the v86 boot sequence to a later point in time, after the CPU has initialized? Or add and call a method Modem.initialize() that is called after CPU initialization?

The only open issue left is what to store in v86 state snapshots for this device, I thinks this needs to be talked over. For now I've left out Modem.get_state() and set_state() entirely.

Added bus messages "serial<N>-data-terminal-ready-output" and "serial<N>-request-to-send-output" for RS-232 hardware output signals DTR and RTS, respectively.
- added new files "modem.js" and its documentation "modem.md"
- added new debug log type LOG_MODEM
- integrated Modem device into V86 options and web interface
Comment thread src/browser/main.js
const modem_uart = parseInt($("modem").value, 10) || -1;
if(modem_uart >= 0 && modem_uart < 4)
{
settings.modem = {uart: modem_uart};
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be configurable by a query parameter (like the other ones above).

Comment thread src/browser/main.js
}
if(settings.mtu !== DEFAULT_MTU) new_query_args.set("mtu", settings.mtu.toString());

const modem_uart = parseInt($("modem").value, 10) || -1;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If UART0 is selected the || -1 will turn it into -1.

(not sure if this intentional; we could remove UART0 from the selection box as it would collide with the serial console anyway; at least until there is a better mechanism to handle collisions, both in the UI and in the API)

Comment thread src/browser/modem.js
}
else if(dial_address.length)
{
const m = dial_address.match(/(\d{3})(\d{3})(\d{3})(\d{3})(\d{0,5})$/);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regular expression should have a ^

Comment thread src/browser/modem.js
this.socket.addEventListener("message", (event) => {
if(this.in_data_mode && (!this.use_rtscts_flowctrl || this.rts_state))
{
const view = new DataView(event.data);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this only uses getUint8 should switch to Uint8Array

Comment thread src/browser/modem.js
Comment on lines +110 to +114
/** @const @type {TextDecoder} */
this.decoder = new TextDecoder();

/** @const @type {TextEncoder} */
this.encoder = new TextEncoder();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these don't store any state and we're module-scoped, I'd move them to the top of this file.

Comment thread docs/modem.md
* [TELIT] [AT Commands Reference Guide](https://docs.rs-online.com/c5f6/0900766b81541066.pdf)
* [websocketd](http://websocketd.com/), also [websockify](https://linux.die.net/man/1/websockify)
* [WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
* [WebRTC API](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API)
Copy link
Copy Markdown
Contributor

@SuperMaxusa SuperMaxusa Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is WebRTC mentioned/used anywhere?

@copy
Copy link
Copy Markdown
Owner

copy commented Apr 20, 2026

Thanks! This looks very cool and I'd like to merged it.

I've given a basic review, but due to unfamiliarity with modems I can't review it detail. That's fine, it makes you the official maintainer of the modem code :-)

There is a slight ugliness in the Modem constructor: It needs to use the bus to send configuration messages to the UART device, but the bus/UART isn't ready at that point in time, so this is delayed until bus event "emulator-ready" is received. It works reliably, but is there a better pattern for this, perhaps move the Modem construction down in the v86 boot sequence to a later point in time, after the CPU has initialized? Or add and call a method Modem.initialize() that is called after CPU initialization?

I agree, in the future I would like to remove internal-only bus events and use direct method calls (e.g. modem receives an uart object or vice-versa). Adding an initialise function sounds fine to me. Or move the modem to cpu.js and pass the uart object to it (that also makes the state handling easier).

I tested some basic commands and connecting to a websocket server. Is there a way to test internet connectivity with user-mode-style networking (e.g. slirp, passt or our own code)?

Comment thread docs/modem.md
@@ -0,0 +1,272 @@
# v86 Modem device
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this file to README.md?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants