Monday 30 August 2021

6502 : Xmodem

 My 6502 system is working well but I still find the program upload process irritating.  I am probably being a diva about this as the old school method to remove, program, replace the EEPROM chip was very painful.   My programs are quite small but it takes time to compile them, transfer them to an Arduino sketch then run the sketch to copy the program to EEPROM.  For a 1KB program, which is quite large for my assembler programs but reasonable for C it can take a minute to process.

I have been thinking of trying to implement XMODEM for a while, it seems sensible to use the serial port session which will allow a transfer at 19200 baud, taking a few seconds for program download into RAM (not EEPROM).  6502.org provides a copy of Daryl Rictor's xmodem code so a couple of weeks ago I tried it out.  The code is intended for a 65C02 + ACIA 6551, the same as mine, and it is only a couple of hundred lines long so I thought I have a good chance of success.  I was a little nieve but that is the best way to start a long journey.

It was easy to download the program and tweak it to compile/load successfully.  However, on starting Xmodem nothing happened.  Not knowing the code or the protocol or having a tool to look at serial port traffic meant that debugging and experimentation were unsuccessful.

I found the modem protocol is quite simple so I wrote a C program under Windows WSL to download a test packet meaning that at least I had reasonable input.  I still couldn't get the example code working so I wrote my own version called xm.  After a while this worked fine, I could compile a program, start xm running and run my serial program to send the machine code. I excluded most of the modem error checking, particularly block number and CRC checks as we are transmitting at quite slow speeds down a 15cm cable.  The only downside is that I have to exit Putty to start the serial program downloading as they share the COM port; on completion I have to restart Putty.  This can be accomplished by means of a batch file loop but still it doesn't seem right.

In an effort to streamline this process I considered writing my own terminal emulator, from which I could easily start the transfer program.  Again I chose C under WSL as my development environment.  Configuring and using serial ports with C isn't terribly easy, some low level commands are required to setup the UART; as usual a good tutorial made this easy.  After that READ and WRITE statements can be used to fill/send buffers through the port.  Under Linux and WSL there isn't a function kbhit() to tell you if the user has pressed a key so I had to implement that myself based on Morgan Mcguire.  Although I could easily capture and display information from the 6502 and deal with keyboard input properly I couldn't get the two to work together seamlessly and I didn't complete this attempt.

On a whim I googled to see whether there are any software only (free) packages which can monitor the serial port.  It turns out there are a few, and Serial Port Monitor seemed a good choice.  The free version is old and not Windows 10 friendly so I used a demo of the paid version.  It is a shame it costs $100 so it is't something I would buy for a one-off problem.  The software is clever enough (using admin privilege) to share the serial port with Putty and after a few minutes learning I could see the serial port traffic.

Using Serial Port Monitor I could see that xmodem was sending a good packet to the 6502 but it was being NAKed by the 6502 and repeatedly resent.  My debugging focussed again on the sample code but I still couldn't get it working.  In particular, not all bytes were read in the ACIA port properly.  I tried all sorts of things to make it work, including slowing the transmission to 9600 or 4800, swapping my Arduino Nano controllable clock for the 1Mhz chip,  using RTS / CTS flow control with extra wires on the USBTTL connection, putting delays on the 6502 send characters which were being garbled.

Eventually I decided to write my own 6502 program, jmodem.  With my new understanding of modem and the structure of the sample code it was a simple job to write my own using subroutines I have previously written.  The only new feature is to read characters until no more come.  Xmodem sends a 128 byte buffer with 3 header characters, terminated by two CRC bytes.      It then stops and waits for ACK or NAK.  If any characters are lost there will be less than 133 characters in total.  Once I had this subroutine working with Putty terminal input remaining coding was easy.  The program initially accepted just one block, checked the number of bytes and transferred it to a fixed memory address.  It was then easy to loop round until an EOT byte was received.


Success is sweet.  I can now load programs into RAM quickly when I want to without exiting Putty using a standard technique.  Completed programs or subroutines can still be saved in ROM using the Arduino Mega but we no longer need it for normal development or system usage.





No comments:

Post a Comment