dirkwhoffmann / virtualc64

VirtualC64 is a cycle-accurate C64 emulator for macOS
https://dirkwhoffmann.github.io/virtualc64
Other
342 stars 33 forks source link

serial port communication via the userport #801

Closed mithrendal closed 20 hours ago

mithrendal commented 2 weeks ago

We've had serial port communication in vc64web, the web version of virtualC64, for a while now.

To make it easier to update to newer core versions and merge the code, I thought it would be a good idea to bring the serial port communication feature from vc64web over to virtualC64.

So, I've put in PR #800 for this.

dirkwhoffmann commented 2 weeks ago

I'm currently reimplementing the merged code to make it fit into the existing component architecture. I am also adapting the Commander interface from vAmiga which allows the emulated computer (the C64 in this case) to control RetroShell. An early prototype is already working.

Step 1: Activate the commander:

Bildschirmfoto 2024-07-03 um 19 36 04

Step 2: Type a RetroShell command in a terminal program. The command will execute inside RetroShell:

Bildschirmfoto 2024-07-03 um 19 36 24
dirkwhoffmann commented 2 weeks ago

This book has some decent information about RS232 communication on the C64:

Bildschirmfoto 2024-07-04 um 10 55 25

Besides explaining how the user port pins map to the RS232 signals...

Bildschirmfoto 2024-07-04 um 10 55 08

... it also explains how data can be received and sent via BASIC. This could be used for testing, if more complex protocols should be supported (different packet sizes, parity bits etc.):

Bildschirmfoto 2024-07-04 um 10 59 18
dirkwhoffmann commented 2 weeks ago

New RS232 code is in place.

@mithrendal: From RetroShell, you can use it like this:

Bildschirmfoto 2024-07-04 um 13 21 10

The following functions are provided by the public API:

/** RS232 Public API
 */
struct RS232API : API {

    class RS232 *rs232 = nullptr;

    /** @brief  Returns the component's current state.
     */
    // const RS232Info &getInfo() const;
    // const RS232Info &getCachedInfo() const;

    /** @brief  Feeds textual data into the RS232 adapter
     *  This function emulates the transmission of incoming data from an
     *  external device.
     */
    void operator<<(char c);
    void operator<<(const string &s);

    /** @brief  Read a printable byte from the incoming logbuffer.
     *  Calling this function empties the logbuffer. When the logbuffer is
     *  empty and a new data packet is received, a MSG_RS232_IN message is
     *  sent to the GUI.
     */
    std::u16string readIncoming();

    /** @brief  Read the logbuffer that records outgoing data.
     *  Calling this function empties the logbuffer. When the logbuffer is
     *  empty and a new data packet is sent, a MSG_RS232_OUT message is
     *  sent to the GUI.
     */
    std::u16string readOutgoing();

    /** @brief  Read a printable byte from the incoming logbuffer.
     */
    int readIncomingPrintableByte();

    /** @brief  Read a printable byte from the outgoing logbuffer.
     */
    int readOutgoingPrintableByte();
};
dirkwhoffmann commented 2 weeks ago

Seems to work...

Let's open a 300 Baud connection with 8 bit packets, no parity (this is the only supported format yet)...

Bildschirmfoto 2024-07-04 um 13 54 38

The output appears in RetroShell...

Bildschirmfoto 2024-07-04 um 13 55 07

Note: To see the output in RetroShell, RETROSHELL has to be selected as RS232 device.

mithrendal commented 2 weeks ago

@dirkwhoffmann brilliant. I merged your latest code back into vc64web which replaces my RS232 hack with your new RS232 code. It works perfectly ! 😍