5 comments on “Figuring out Commodore 64 RS-232

  1. Hi, good to see you’re blogging again, love reading these! I got interested in toying with C64 RS-232 a couple of years ago with the intention of writing VT100 capable terminal and use it with Linux box for IRC and telnetting into C64 BBS’s. I didn’t quite finish it as I got distracted with other projects (this is what usually happens with my hobby projects..), but I got working good enough for my needs.

    I really suggest you read George Hug’s article in Transactor vol 9 issue 3, “Toward 2400”. It has great explanations of deficiencies and bugs of KERNAL RS-232 routines, and gives an example routine capable of 2400bps. I had problems with even 1200bps working reliably, but after adapting the new RS-232 routine listed there, I was able to get it up to 4800bps without issues. I live in PAL-land, so I had to calculate new values based on PAL C64 clockrate (that one used NTSC), and going up to 4800 required just some minor tweaking.

    At 4800bps ASCIIPETSCII translations, handling of VT100 escape codes and scrolling the screen were starting to become issues, due to time CPU needed to handle incoming data. I made a new character set for ASCII, and that helped quite a bit as I was able to drop translating incoming ASCII to PETSCII, saving some precious cycles. The most time consuming bit was scrolling the screen. I did some calculations back then, and if I remember correctly, even 9600bps might have been doable without it.

    • Thanks for that reference to the Transactor article – I was finally able to try that code out and it worked like a charm!

  2. Hi!

    I’m currently playing around with CC65 and hooking up my C64 to my Arduino! Sadly I couldn’t really find any code examples of using the C64 serial port with C, and it seems there is no library for that either (probably due to the simplicity of configuring it)
    If you could point me to the right place to find a code example, that would be awesome! 🙂

    • Well, I used the cbm_k_* functions, which are basically just a thin layer over the C64 KERNAL routines. So to set up the port for 1200 bps I used:

      unsigned char name1200[] = {0x08, 0x00, 0x00};
      /** The RS-232 driver expects to have 256-byte buffers for
      * input and output.
      */
      char rs232_read_buf[512];
      char rs232_write_buf[512];

      /** These memory locations store pointers to the RS-232 read
      * and write buffers. We’ll fill them in with pointers to
      * our read and write buffers before we open the RS-232
      * device. That’ll prevent the KERNAL open routine from
      * allocating buffers from the top of BASIC memory, which
      * would probably really mess us up.
      */
      char** RIBUF = (char**)0x00f7;
      char** ROBUF = (char**)0x00f9;
      unsigned char __fastcall__ (*cbm_k_getin)(void) = 0xffe4;

      And then to open the port:

      // set up rs-232 buffers
      *RIBUF = (char*)(((int)rs232_read_buf & 0xff00) + 256);
      *ROBUF = (char*)(((int)rs232_write_buf & 0xff00) + 256);

      textcolor (COLOR_GRAY3);
      printf (“preopen, ribuf is %p\r\n”, *RIBUF);
      // open rs232 channel
      cbm_k_setlfs (2,2,3);
      cbm_k_setnam (name/*”\x19\x00″*/);
      retval = cbm_k_open ();

      And to read and write from it (here I’m echoing stuff from the keyboard out the RS232, and writing the input from the RS232 onto the screen):

      for (;;)
      {
      // look for a keyboard press
      cbm_k_chkin (0);
      c = cbm_k_getin();
      if (c)
      {
      putchar(c);
      cbm_k_ckout(2);
      cbm_k_bsout(c);
      }

      // look for input on rs232
      cbm_k_chkin (2);
      c = cbm_k_getin ();
      if (c)
      {
      putchar(c);
      }
      }

      Hope that’s helpful, even if it’s way late.

Leave a comment