XMODEM in 2022
mattkeeter.com
mattkeeter.com
* JMODEM: https://github.com/cpeterso/jmodem
* SEAlink (System Enhancement Associates): https://github.com/cpeterso/sealink
* WXMODEM (Windows XMODEM): https://github.com/cpeterso/wxmodem
* ZMax: https://github.com/cpeterso/zmax
I also remember "Leech Modem", a file transfer protocol that was compatible with XMODEM and YMODEM but designed to bypass a BBS's download quotas. The protocol would NAK the last packet and then abort the file transfer. The user had successfully downloaded the file, but the BBS would mistakenly not count the aborted file transfer against the user's download quota.
I still think in terms of "SYN/ACK SYN/ACK" pairs when analyzing technology.
As a teenager I wrote a few implementations of X/Ymodem and Punter for the C64 in machine code back in the day. I was too poor at that age to afford an assembler.
I also wrote a native X/Ymodem utility for the IBM AS/400. I had to write the CRC calculations in MI (AS/400 machine interface language) in order to get enough performance to make it work well.
I was needing a reliable protocol to move binary data out of an Arduino into my PC and researching XMODEM I found so many things wrong with it, particularly no sane way to specify the file length and a checksum scheme that is totally inadequate. The buffer size also is a bit big for a machine with tiny RAM.
I wound up rolling my own version of
https://en.wikipedia.org/wiki/High-Level_Data_Link_Control
with much smaller packets and a carefully chosen CRC which is adequate for the task. Retrospectively I was shocked that we accepted XMODEM back in the day.
Once you've used the latter letters you never fallback. You'd never leave z to use y or leave y to use x.
At the time you wanted simple and small code.
I have modern (produced in the last couple of years) network switches at work which only support XMODEM (assuming you have to do it over serial, they also support TFTP or transfer from a USB storage device, but in the one occasion we had to use it the OS had trashed itself comprehensively enough that serial was our only option).
When I found out the Arduino had no wires for FC, I practically had a histamine reaction. That killed the Arduino for me, which was too bad because I had ideas about creating something information radiators for developers and ended up with a box of parts I never touched again. And Raspberry Pi had the same issue, and although having Ethernet made that less of a problem, it didn't fix the problem I was trying to solve (how do I run a device in an organization that doesn't allow BYOD on their networks?)
I have another USB-to-serial controller I got to program my handheld ham radio that does support that, you can wire that to your Arduino and it just works...
But really it is a bad bit of cost cutting because the AVR8 is capable of very fast and reliable communications and you shouldn't need to have to add another dongle to get access to it.
And all the next generation arduino clones with built-in USB stack are just wonderful for serial data! I went over 3Mpbs on atmega32u4 device, and it came with USB flow control, so speed goes up as USB bandwidth is freed up, and connection pauses if data is not consumed, fully automatically.
I think a more charitable description would be Minimum Viable Product. It was far less complex than KERMIT, and got the job done.
As soon as better options became available, we all jumped.
Still, sometimes you've got a spiffy new Toshiba laptop with 3 1/2" disk drives, MS-DOS, and nothing else. This in a house full of 8" and 5 1/4" floppies. What to do? Use debug and Copy con to pull over just enough of Xmodem from another machine, to then pull over Qmodem, then Laplink, and it's off to the races we go.
I was amazed to watch it happen.
>I was needing a reliable protocol to move binary data out of an Arduino into my PC
Each solution is designed to deal with the types of noise present in the signals. XMODEM may be bad for you, excellent for the phone lines it was used for. Your method may be terrible for phone line noise. XMODEM was designed to be fast and low cost to implement for the majority case. Your solution looks like it would be neither of those things.
I've made zillions of binary embedded to outside protocols. If you really want robustness, implement a nicer forward error correction protocol.
In any case having a solid understanding of the noise types you see is important to getting best performance. Examples are burst noise (likely bad or loose wiring), average noise (bad shielding), dropped bits (too low power), etc. Each can be combatted by making sure the hardware and connections are decent up to some cost point, then fight the rest with error detection and correction.
As to getting stuff from an arduino to a PC, I've gotten max speed with zero error checking to work on most every occasion, no error correction or detection, testing over many gigabytes to a terabyte, with straight serial protocols. Why is your case so noisy? Is there some physical problem or constraint on the path? I found such transfers to be so robust I no longer even worry about packets or retries for such hardware.
The system I am working on is meant to extract graphical data from a persistence of vision display that's hard to test under real conditions because it is supposed to be strapped onto a moving vehicle.
If the probability is 1% that a test isn't giving the right results because a bit got flipped on the serial line that is too much. So I want to know the data is clean and not guess about it.
I routinely transfer data on original arduinos at 38400, 57600 or faster. The error rate is pretty low, way smaller than 1%.
The majority of cheap cables use a super low-cost chip that ruins data at higher baud rates.
If you get a quality cable with a known good chip in it, then you can transmit at crazy speeds.
My TRS-80 is supposed to max out at 300 baud. But I can go to 600 baud with a crap cable, or 57,600 with a good cable.
The knock-off often use ch340 chip (which is super annoying as it has no serial number of any sort), but even that chip can be pretty fast if placed on the well designed PCB - I regularly upload 1MB firmware files to esp8266 at 230400 using that chip.
That sounds like you have really bad hardware somewhere. You should be able to get vastly more throughput.
>So I want to know the data is clean and not guess about it.
You will never know. You can only bound undetected error probabilities. No checksum, no CRC, no error correction can prove no data loss or bit flips in transmission. This is why understanding channel error types is important to design a protocol that maximizes likelihood of no undetected errors.
I've built many similar sounding systems (even many POV items, I am co-owner of hypnocube.com, and we used to do all sorts of POV experiments, using both COTS hardware and lots of custom boards too). I've found that with even average physical connection we could routinely push 100Mbps into a PC with zero errors over UARTs for literally terabytes of data (I'd create test programs on each end, sender would blast known data patterns and receiver would check them, I'd let them run for days on a test device, looking for errors). This is how I learned a lot about getting good connections - vastly nicer than fighting with flaky hardware connections.
I never needed flow control. Ever.
Have you measured the error rate? Have you looked through forums to see why your Arduino setup is so terribly slow? It sounds like there is a significant other problem than your serial protocol.
If you can use something like a Selae logic probe attached close to your cpu pin out you can also get some good data. I've used these to track down many physical bus errors.
Unfortunately it was not. Thus, YMODEM and ZMODEM replaced it. ZMODEM is more complex, more reliable. YMODEM is same as XMODEM, but bigger buffer if I recall correctly.
XMODEM is “simple” implementation, but maybe not “fast” or even “low cost” implementation due to time needed to debug its issues :(
XMODEM was terrible over phone lines.
> I found such transfers to be so robust I no longer even worry about packets or retries for such hardware.
People say that about not having backed up their data in the last 20 years, then a lightning storm came and destroyed their data. A storm could do that with data over a cable as well. This shouldn't even be a conversation in 2022.
use zssh instead of ssh, then sz on the remote end to send files (and rz to receive)
years ago a load of GUI clients used to have a right click menu to send/receive files that used zmodem (sadly putty wasn't one of them)
This was in 1996. In a fit of amazing fortuitousness, a fellow in Japan, almost exactly at the same time, developed a program called Modemu. It is still out there and has not been maintained since. What Modemu does is creaete a pseudo-tty device in your system that you can use in a program like Minicom. This pseudo-TTY device accepts AT commands to "dial" remote hosts and connect to them.
So at the time I was able to install my Sixpack commands (sps, spr) into Minicom, and then telnet out using Modemu: ATD<host-namne>, then transfer files to the remote hosts.
I would install the receive program by uuencoding it, and then just doing piece by piece copy and paste into the remote session to recover the binary.
TIL:
XMODEM used 128-bytes payloads with a three-byte header and one-byte checksum for a total of 132 bytes per packet. In the era of 300 bps modems, a packet took about four seconds to send, and typical latencies were on the order of 1⁄10 of a second, so the performance overhead was not significant. As speeds increase the problem becomes more problematic; at 2400 bps a packet takes about 1⁄2 to send, so about 1⁄5 of the available bandwidth is wasted waiting for ACKs. At 9600 bps a packet requires only 0.13 seconds to send, so about 1⁄2 of the bandwidth is wasted.
ZMODEM addressed these problems by removing the need for ACKs at all, allowing the sender to send data continually as long as the receiver detected no errors. Only NAKs had to be sent, if and only if there was a problem. Since ZMODEM was often used on links with built-in error correction, like X.25, the receiver would often not send a single message back to the sender. As a result, the system would send the entire file in a continual stream, and ZMODEM referred to itself as a "streaming protocol".At some point I found a BBS with big files I wanted that only supported ymodem, and after several days of trying and hitting the hour timeout, I gave up.
They would recognize the protocol, immediately forge ACKs, deal with error correction and retries, and swallow the other side's ACKs when they eventually came.
Truth to be told, by the time this feature was available, many had moved to YMODEM, ZMODEM, BiModem (Bidirectional transfers whoohoo!) and HS/Link (Bidirectional as well, and even chat with the SysOp while transferring data!).
But those spoofing modems were very valuable for environments where the protocol was hardwired and you couldn't update.
also, kermit.
who remembers rip graphics?
of course it was made irrelevant by the fledgling world wide web.
it was only packet switched commercial services and shell based internet at the libraries/university.
Seeing LORD the first time with RIP graphics made me rethink everything I thought I knew about BBS games.
Nice guy as I recall.
Ironically, Xmodem wouldn't have worked well over CIS's network, since to talk to the X25 nodes you had to have software flow control enabled in your modem connection. Small transfers might work, but when you hit the Xmodem block number that coincides with ^Q, that block would repeatedly NAK until the transfer failed.
They probably had some kind of escaping to overcome that???
It's easy to just blame the FTDI driver, but FTDI is used all over the place in the arduino community on MacOS, so I would have have assumed it was working.
In my first job out of high school, I worked as an IT person in law firm that used Procomm Plus (for connecting to some databases over dial-up, like the land title registry). I used its scripting language to automate logins. I remember Procomm Plus being decent.
Now his only Mustangs are his cars.
* https://en.wikipedia.org/wiki/HS/Link
Bidirectional transfers were so handy and a time saver if you were transferring mail files (QWK, SOUP, BlueWave) and your replies. If anyone has some of those old files available, readers are still available:
I spent more time writing the XMODEM receiver than I spent using software I sent over it. It’s never the destination, always the journey.
Weird factoid for the day: Country music star Shooter Jennings runs one! https://old.reddit.com/user/ShooterJennings/submitted/
Maybe some more recent ones too, I haven't kept up at all.
YMODEM-G was fast because it didn't do any error detection of its own, so it didn't have the overhead of checksums and such. The usage scenario was that the connection would already have error detection and recovery by virtue of the modem and the connection... protocol? I forget what we called them.
Yeah protocols. First ones to see widespread use (at least subjectively) were MNP4 and MNP5 for, respectively, Error correction (with a 25% speed increase as a bonus, since it was synchronous and would not therefore waste code space with start and stop bits) and Data Compression (a terrible one which would actually incur an overhead if data was already compressed).
They got later replaced by v.42 and v.42bis, with the same respective purposes (but v.42bis was smarter than MNP5 and could switch to transparent mode when sending incompressible data).
CARRIER 14400
COMPRESSION: V.42 bis
PROTOCOL: LAPM
CONNECT 57600/ARQ
[ 0.362434] 00:01: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550ASo even if they could offer these ports and Linux reports them, they might not be usable without special work.
But from the host OS it looks like a regular 16550A.
Example: I have native, documented DB9/25 on my latest machine, an asus prime x570-pro https://www.asus.com/us/Motherboards-Components/Motherboards... which if you download the manual and search for "COM" you will see that it uses the semi standardized 10 pin motherboard header into which a card edge DB9/DB25 can be plugged into.
They are overwhelmingly used by hw/firmware/bringup engineers, so, while your right they are frequently undocumented or unpopulated, like JTAG ports its more unusual not to find them. And, yah on a lot of machines they are just whatever logic level the chip supports for IO 1.8V/etc so its common to just wire the headers to FTDI/etc usb converters rather than level shifters.
https://www.dell.com/en-us/work/shop/desktops-all-in-one-pcs...