Title: Altair on WiFi Date: December 26, 2018 Tags: altair hardware ======================================== Putting the Altair 8800 on the internet is easy and cheap. Just takes a bit of hardware and some firmware emulating a Hayes modem. You can get on a BBS in minutes. I had heard about serial WiFi modems for retro computers but the device being talked about was no longer being made. I sort of forgot about it for a while and then recently looked again for available options. I found a blog post[0] detailing the assembly of your own from a couple of components and the Zimodem[1] firmware by Bo Zimmerman that was written to interface with a Commodore 64 over it's serial connection. I chose to use the ESP8266-12E module, a "5-wire" RS-232 to TTL adapter, a DB25F to DB9F adapter, an old cell phone charger and a null modem adapter I already had. Note that the "5-wire" adapter only came with 4 jumper wires which, after power and ground, only actually allows for Rx and Tx without any flow control. To hook up flow control, I also bought a variety of jumper wires which can be used for future projects, too, but I still haven't used flow control anyway. So actually, Rx and Tx with the jumper wires it came with is all you need. You could probably find a DB25 to DB9 adapter that is also a null modem adapter. I didn't know I would need one until I was confused for a day by the modem not working on the Altair. Plugged into my laptop, it worked fine so it took me a night's sleep before it clicked that it might need a null modem adapter. The blog author had to modify the Zimodem firmware because the Commodore 64 serial port flips high for low as compared to normal RS-232 lines. His changes mostly just flip those by default. The firmware is fully configurable if you were able to talk to the device in the first place. But, if you couldn't you'd be stuck. The modified version is a year or so out of date now and the blog author is not maintaining it going forward. It builds easily with the Arduino 1.6.x IDE. Version 1.6 is important. It will not build as is with 1.8. I'll describe building the firmware below. When starting this article, I did everything using the build from the blog post so updating is not critical. The ESP8266-12E has a built in USB serial adapter: CP2102 USB to UART Bridge Controller. My OpenBSD laptop could not flash the ESP module over this device but after the firmware was loaded, could talk to the firmware. My Mac, needed a driver[2] installed and was then able to flash the Zimodem firmware. I was then able to connect to the device using OpenBSD and configure my wireless access point. It supports WPA2 with a passphrase and DHCP just fine. I could immediately start making network connections through the modem using my terminal. I set the baud rate to 9600, it defaults to 1200, and disabled any flow control options. Make sure you save your configuration with AT&W so when you plug the modem into your retro computer, you don't have to reconfigure it. The Zimodem README[3] is a must for a command reference. Initially I wrote a long command entry interface based on string echo[4] for the Altair to communicate with the modem and receive data back from it. At the time, I hadn't yet realized I needed a null modem adapter and couldn't figure out why the modem didn't seem to be doing anything. I then wrote a quick test program that simply sends terminal input to the modem and modem output the terminal character by character. That was really all I needed to get started. I works pretty smoothly for poking around the internet with the modem. Here is the simple test program: 000 LXI SP 061 ; Set stack pointer 001 000Q 000 002 100Q 100 003 MVI A 076 ; Reset ACIA 004 003Q 000 005 OUT 323 ; for terminal port 006 020Q 020 007 OUT 323 ; for modem port 010 022Q 022 011 MVI A 376 ; Set to 9600 baud 8N1 012 225Q 225 ; and enable receive interrupts 013 OUT 323 ; for terminal port 014 020Q 020 015 OUT 323 ; for modem port 016 022Q 022 017 EI 373 020 NOP 000 ; Wait loop 021 JMP 303 022 020Q 020 023 000Q 000 ; Modem handler 024 IN 333 ; Get character from modem 025 023Q 023 026 MOV B,A 107 ; Save in B register 027 IN 333 ; Check if terminal is ready 030 020Q 020 ; to send 031 RRC 017 032 RRC 017 033 JNC 322 034 027Q 027 035 000Q 000 036 MOV A,B 170 ; Write character to terminal 037 OUT 323 040 021Q 021 041 RET 311 ; Terminal handler 042 IN 333 ; Get character from terminal 043 021Q 021 044 MOV B,A 107 ; Save in B register 045 IN 333 ; Check if modem is ready 046 022Q 022 ; to send 047 RRC 017 050 RRC 017 051 JNC 322 052 045Q 045 053 000Q 000 054 MOV A,B 170 ; Write character to modem 055 OUT 323 056 023Q 023 057 RET 311 ; Interrupt handler 070 IN 333 ; If modem has data 071 022Q 022 072 RRC 017 073 CC 334 ; goto modem handler 074 024Q 024 075 000Q 000 076 IN 333 ; If terminal has data 077 020Q 020 100 RRC 017 101 CC 334 ; goto terminal handler 102 042Q 042 103 000Q 000 104 EI 373 105 RET 311 I cleaned this up a bit from it's original thrown together code. Short and sweet, it lets you talk back and forth with the modem allowing you to access all the functions of the modem. It's without any fancy output or parsing, no backspace, and it relies on the Zimodem firmware's character echo to show you what you're entering. ## Breaking it down ## # Main program # If you've followed along with the previous echo articles, the main program should look familiar but with the addition of a second serial port. The 2SIO board in an Altair 8800 had 2 serial ports. The Altair clone defaults to the first port with the status register at address 020Q and data register at address 021Q. The second port has the status register at 022Q and data register at 023Q. My terminal is plugged into port 1 and the modem into port 2. We don't need any heap space here as we're not writing anything to memory, just passing it straight through to the ports. We reset both ports and then configure both ports to 9600 baud 8N1 with receive interrupts enabled. My original hack and slash version reset port 1 then configured port 1 then reset port 2 and then configured port 2. I had to keep loading the Accumulator with commands. Reordering to send the same command to both ports then changing commands saves quite a few bytes of code. Then we enable interrupts, which will fire if either port receives a character. And spin in our familiar wait loop. # Interrupt handler # Going in execution order instead of memory order, I'll cover the interrupt handler next. This will also look similar to our other echo programs. Here, since we enabled receive interrupts on both 2SIO ports, we don't know which one triggered the interrupt. The data register's bit 7 will be a 1 if that port has generated an interrupt. But the data register full bit, bit 0, will also be 1 if there is something for us to read. So instead of caring where the interrupt came from, I just check both ports for a character ready and process it. I check the modem's status first and if the data register full bit is 1, call the modem handler to read what's there. Then check the terminal's data register and call the terminal handler if that port has a character ready. You'll see that I've basically in-lined write char from the string echo program to do the writing. # Modem handler # The modem handler is called from the interrupt handler if a character is ready in the modem port data register. It simply reads the character from the modem port then checks the terminal data register until the terminal port is ready to send a character and then writes the character out to the terminal. # Terminal handler # The terminal handler is the same thing as the modem handler with the port addresses switched. It reads a character from the terminal, waits for the modem port to be ready to send, then sends the character to the modem. ## Altair on the internet ## That's enough to get the Altair on the modern internet. They Hayes command-set is supposed to allow you to use old terminal programs. I haven't reached that era of Altair computing yet so I don't know how well that works. If you've ever used netcat or telnet to connect to a web server or other server that usually has a specialty client, that's what using the WiFi modem is like with this simple program. You have to know the protocol and what messages to send to the server to get the right output. And then all you get is the raw output. The Zimodem firmware does have a telnet client built in, however. You can use that to get onto a BBS and you're back in the 80's without any further effort. Use `atdt"SomeTelnetBBSHost:23"` to connect and you can interact directly with the BBS in telnet mode. Check out the list of telnet BBS severs[5]. Be careful with terminal size. If my terminal is too large, it doesn't clear the screen correctly and I get a jumble of output. Might be the server software the BBS I tested with is running, though. Also make sure you have your terminal is set up correctly for color and ANSI, etc. Just like the old days. Altair on a BBS[6] Websites are a bit trickier. They can be very picky about proper usage of carriage return and newline sequences and may require certain headers be present. Since our program only sends exactly what you type to the modem, if you hit enter and send a carriage return, nothing is going to process that and add a newline if it's needed. Everything has to be explicitly entered. Try it with the following commands (<^j> is a control+j to send a newline) `atde"altairclone.com:80" GET / HTTP/1.1<^j> Host: altairclone.com<^j> User-Agent: Altair<^j> <^j>` to get a dump of the altairclone homepage. User-Agent isn't necessary but maybe Mike will notice it in is logs and wonder what's going on. :) Careful doing this with even "simple" web sites like google.com or you'll be waiting a long time while it dumps tons of formatting garbage and scripts to your terminal. If you want to experience just how bloated websites have become, try them at 9600 baud. There is no support for TLS (https, port 443) web sites so that is a bit limiting. Also, some web servers will close the connection if you don't send a request within a certain time and you probably won't be able to type quickly enough. ## Upgrading firmware ## Updating the firmware to the latest version (3.4.1 from Dec 11 2018) is pretty straight forward. I re-applied the change to the defaults for non-C64 systems, plus defaulting to 9600 baud and rebuilt it. I had to do this on a Mac and the instructions should work on Windows and Linux. I am assuming the ESP8266 board as that is the one I have. The code should support the other boards but configuring the Arduino IDE and flashing is up to you to figure out since I can't test anything I don't have. * Start by installing version 1.6.13[7] of the Arduino IDE. * Follow the directions to install[8] the ESP8266 board definitions and libraries. At this time the version is 2.5.0-beta2. * Select the NodeMCU 1.0 (ESP-12E Module) from the Board list under ESP8266Boards. * Set Flash Size to "4M (1M SPIFFS)" and CPU Frequency to "80 MHz". * Check out the Zimodem software[9] from Github. * Apply the changes to the code for the Altair. Diff for Zimodem 3.4.1[10]. * Open the zimodem.ino file from the Arduino IDE which loads the project. * From the Sketch menu, select Export compiled Binary. A binary named zimodem.ino.nodemcu.bin should be created in the same directory as the zimodem.ino file. I followed the original blog instructions for flashing[11] without the Arduino IDE. To flash the ESP module, you have to disconnect the RS-232 to TTL adapter otherwise the USB port is used for serial output, also, and you can't flash the memory through it. Modify the UPDATE_URL to your own location if you want to host your own over-the-air updates. [0] https://subethasoftware.com/2018/02/28/wire-up-your-own-rs-232-wifi-modem-for-under-10-using-esp8266-and-zimodem-firmware/ [1] https://github.com/bozimmerman/Zimodem [2] https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers [3] https://github.com/bozimmerman/Zimodem/blob/master/README [4] https://blog.kagu-tsuchi.com/articles/8080_IO_string_echo.html [5] https://www.telnetbbsguide.com/ [6] gopher://kagu-tsuchi.com:70/I/blog/images/altair_wifi_bbs.png [7] https://www.arduino.cc/en/Main/OldSoftwareReleases#previous [8] https://github.com/esp8266/Arduino#installing-with-boards-manager [9] https://github.com/bozimmerman/Zimodem [10] gopher://kagu-tsuchi.com:70/0/blog/files/zimodem-altair.diff [11] http://subethasoftware.com/2018/02/25/how-to-load-zimodem-firmware-to-an-esp8266-without-arduino-ide/