From vice-emu
Revision as of 21:56, 23 November 2019 by Gpz (talk | contribs) (Signals and Pinout)
Jump to: navigation, search

here i will track some things regarding rs232 emulation, and perhaps fix things while at it. It may also serve as documentation on how all those RS232 things work. Gpz (talk) 19:29, 25 July 2019 (CEST)

  • for all first tests i will use some version of CCGMS, and regular user-port rs232 emulation at 2400 baud.
  • for ACIA tests i will use novaterm or striketerm.
  • if not explicitly testing two instances of VICE, i will use cgterm as the "calling" end


I need more / better testcases. Right now i am using CCGMS, but that will hardly do for more than a few basic checks. what i am looking for is:

  • some (terminal?) program that shows the various modem control lines (dtr/dtd rts/cts CD etc) on screen in realtime
  • a minimal c*base setup that lets me reproduce c*base related bugs
    • detailed description of the supposed problems with c*base
  • other problematic programs/scenarios
  • all of the above pre-configured for a) a standard userport modem at 2400 baud and b) a swithlink at something like 38400 baud

To make this page more complete, more examples of real-world usecases would be nice.


To reproduce what is explained below, a few C64 programs and some host utilities are needed.


  • CCGMS (if you are familiar with another terminal program, that will do just as good)


  • socat (Windows binaries)
  • tcpser (use the FozzTexx fork until the changes are merged back into jim brains repo)
  • recent VICE binaries. You can find Windows nightly builds here. Sometimes we will upload experimental Windows binaries here.
  • cgterm

using a real RS232 port

This works by using the device name of your OS, VICE uses physical RS232 ports.


RsUserEnable = 1
RsUserBaud = 2400
RsUserDev = 1
RsDevice1 = /dev/ttyUSB0
RsDevice1Baud = 2400

status: working out of the box


RsUserEnable = 1
RsUserBaud = 2400
RsUserDev = 1
RsDevice1 = com6
RsDevice1Baud = 2400
  • the windows driver understands various options passed in the so called "mode string" after a colon after the ports name
  • finding out what COM port the usb adapter ended up might be tricky, you can use a tool like "Keyspan Serial Assistant"

status: working after some massaging of the code

rs232 over ip

This works by using the IP and port you are connecting to, VICE will use a TCP socket.

TODO: check if DNS lookup works ([ Domain name support in RS-232 settings})

connect two VICE instances on the same host

$ socat tcp-listen:25232 tcp-listen:25231

config instance #1

RsUserEnable = 1
RsUserBaud = 2400
RsUserDev = 2
RsDevice2 =
RsDevice2Baud = 2400

config instance #2

RsUserEnable = 1
RsUserBaud = 2400
RsUserDev = 2
RsDevice2 =
RsDevice2Baud = 2400


status: works


status: works

connect two VICE instances on different hosts

status: untested

piping to an external program

This is the unix way to talk to external programs.

Piping will be used when the first character of the device "file" name is a "|" (pipe) character.

Note: when the external program is netcat (or "nc") without further options, the result is equivalent to using "rs232 over ip" as described above.


"calling" a telnet BBS

$ tcpser -v 25232 -p 6400 -s 2400 -l 4
RsUserEnable = 1
RsUserBaud = 2400
RsUserDev = 4
RsDevice4 = |nc 25232
RsDevice4Baud = 2400



status: works


status: not implemented

TODO: a windows replacement for arch/shared/coproc.c:fork_coproc() must be implemented (this is non trivial unfortunately) and then hooked up in rs232-win32-dev.c in the same way it is on unix. once done define grep for COPROC_SUPPORT and adjust the respective places (preferably removing it)

some pointers:


  • the code is somewhat prepared
  • we should probably create another thread which monitors the launched external process, closes the pipes when the child dies, and perhaps other things


  • whether the "UP9600" (daniel dallmann) hack is being used seems to depend on the baudrate(?). this should be a seperate option

driver issues

  • handling of DTR and RTS seems to be completely missing. rs232dev_set_status, rs232dev_get_status, rs232dev_set_bps apparently are not called by the layer above
this is partially solved for IP connections

user interface

  • a couple of typical rs232 settings should probably be configurable for at least "real rs232 port at host". (behavior of DTR, RTS...)

ip232 protocol support

This is the protocol introduced by some modified WinVICE 1.19 to talk to tcpser.

tcpser->vice ip232.c:ip232_write

0xff nn ->
 nn = 0      DCD = false     
 nn = 1      DCD = true
 nn = 255    literal 0xff
other   ->   unchanged

vice->tcpser ip232.c:ip232_read

0xff nn ->
 nn = 0      DTR = false      note: the original patch sends 0 on rs232 reset
 nn = 1      DTR = true       note: the original patch sends 1 on rs232 connection established
 nn = 255    literal 0xff
other   ->   unchanged

TODO: (optionally!) support this protocol

NOTE: this is partially implemented now

  • userport handles DCD

TODO: fix userport DTR, fix ACIA, more testing


tcpser seems to be buggy too:

  • when sending 0xff, x the respective codes appear in the output. this should not happen, they should directly translate into DTR status. when using an IP connection DTR=0 should disconnect.
    • even worse, that sequence is also echoed, which causes it to be interpreted by the ip232 "user"
  • somehow using the common "+++",delay,"ATH" doesnt disconnect the "modem" when using ip232

Signals and Pinout

Circuit Direction DB-25 pin DB-9 pin
Name Typical purpose Abbreviation DTE (Computer) DCE (Modem)
Data Terminal Ready DTE is ready to receive, initiate, or continue a call. DTR out in 20 4
Data Carrier Detect DCE is receiving a carrier from a remote DCE. DCD in out 8 1
Data Set Ready DCE is ready to receive and send data. DSR in out 6 6
Ring Indicator DCE has detected an incoming ring signal on the telephone line. RI in out 22 9
Request To Send DTE requests the DCE prepare to transmit data. RTS out in 4 7
Ready To Receive DTE is ready to receive data from DCE. If in use, RTS is assumed to be always asserted. RTR out in 4 n/a
Clear To Send DCE is ready to accept data from the DTE. CTS in out 5 8
Transmitted Data Carries data from DTE to DCE. TxD out in 2 3
Received Data Carries data from DCE to DTE. RxD in out 3 2
Common Ground Zero voltage reference for all of the above. GND common 7 5
Protective Ground Connected to chassis ground. PG common 1 shield


driver stack

rsuser.c                   -> rs232drv.c              -> rs232.c              -> shared/rs232dev.c
rsuser_read_ctrl (WIP)        rs232drv_set_status (ok)   rs232_set_status (ok)   rs232dev_set_status (TODO)
rsuser_write_ctrl (WIP)       rs232drv_get_status (ok)   rs232_get_status (ok)   rs232dev_get_status (TODO)
aciacore.c                                                                       rs232net.c
acia_get_status (ok)                                                             rs232net_set_status (WIP)
acia_set_handshake_lines (ok)                                                    rs232net_get_status (WIP)


relevant commits (some that only change comments or defaults are omitted):

  • r36762 move rs232dev to shared
  • r36842 prepare ip232 protocol support, currently disabled
  • r35811 baudrate resources are no more archdep
  • r36810 cleanup, comments, use defaults for serial port that should always work, bring back the baudrate resources
  • r36859 added resources and commandline options to enable/disable IP232 protocol per rs232device
  • r36987 move rs232 related header files into the rs232drv directory
  • r36988 first step to properly emulate dtr/dcd, dcd proved working with userport rs232 (tested with c*base). dtr still needs to be checked. acia not yet working. some temporary logging left enabled.
  • r36989 according to the datasheet DCD is bit5 and DSR is bit6, not the other way around


run tcpser to work with a bbs in vice: note that the baudrate is important, else the bbs sees "connect 38400" which will confuse it

tcpser -l 7 -tsSiImM -v 25232 -s 2400 -L log.txt

run c*base with 2400 baud userport:

x64sc -default -warp -drive8type 1581 -rsuser -rsuserdev 2 -rsuserbaud 2400 -rsdev3ip232 TestBBS.d81

run c*base with 38400 baud swiftlink:

x64sc -default -warp -drive8type 1581 -acia1 -acia1mode 1 -myaciadev 0 -rsdev1 -rsdev1ip232 -rsdev1baud 38400 TestBBS.d81