The Game Plan
So my plan is to make a full size case that will be as authentic looking as possible, with beautiful walnut sides for sure. I will 3D print the blue panels instead of using sheet metal so the build will be accessible to more people should they decide to make one.
For the keyboard I have been in touch with Dave from osiweb.org who has designed a complete replacement keyboard for the Sol-20 using modern Cherry key switches. From the Unified Retro Keyboard Project:
The keyboard is not a replica of the original. It doesn't use the same capacitive circuit or keys. But it does have exactly the same layout with the same functionality, including the 3 LEDs (UPPER CASE, SHIFT LOCK, LOCAL) and 3 outputs (RESET, BREAK, LOCAL). It uses cherry MX or Futaba MD-4PCs keys. Neither has quite the same feel as the capacitive keys, but the Futaba keys approach the travel of the keytronic switches, and do have a nice feel.
I'm getting the keyboard as a kit and looking forward to putting it together.
On the inside I'm going to emulate the Sol-20 hardware on a Raspberry Pi 4. To that end I have a working (very basic at this point) Python based emulator I'm going to post to GitHub shortly.
I haven't decided what to do for a monitor yet. Certainly a CRT of some sort would be ideal, but I may have to go with a LCD.
Is Emulation the Sincerest Form of Flattery?
While I was researching the project and planning the build I was working a Sol-20 emulator. I thought about using Jim Battle's Solace emulator, but it is Windows based and ultimately I hope to run my Sol-20 reproduction on a Raspberry Pi 4.
Since the Sol-20 was based on the Intel 8080 microprocessor I thought that would be the logical place to start. Fortunately for me, Space Invaders and some of the other early arcade machines also used the 8080. Because there is a very active gaming community helping to preserve these retro classics, there are a number of great 8080 emulators to be found on GitHub. I ended up cloning py8080 because it's Python based and I'm more comfortable right now with Python than I am with C++.
So with a working virtual 8080 processor it was a pretty easy task to allocate some memory for it (64K because why not), load a monitor program (Solos since it was the default shipped), set the instruction pointer to the start of the program (0xC000), and run the emulator. Success! Technically I had a Sol-20 running in emulation, but it was pretty boring since I had no way to interact with it. Time to create some virtual devices.
The Display
The system memory used by the Sol-20 is as follows:
C000-C7FF - System ROM. Sol-20 "Personality Modules" like Solos are mapped here. C800-CBFF - System RAM. Reserved by the system. CC00-CFFF - Display RAM. Shared memory between the CPU and VDM-1 video circuit.
Although most systems shipped with only 8K or 16K of memory (or less) in those days, I have to wonder why they didn't map these addresses up into the F000-FFFF space to allow a contiguous 60K memory space for user programs. At any rate the important thing to note for display purposes is the CC00-CFFF shared video RAM. This 1K space was used to store 16 lines of text each of which is 64 characters long. Any text written to this memory would automatically be displayed on the screen.
Using PyGame I created my virtual screen. I could have written the characters from the shared video memory directly to the screen but the Sol-20 used a lot of unique character glyphs.
So based on the original 6574 character ROM I created a set of character tiles that I could easily "blit" to the screen. I wrote a function to iterate over the 64 x 16 array of characters in the shared video memory and write them out to the screen and added this function to the main loop of my emulator. When I did that I was rewarded with this. I know the aspect ratio is off here. I'll deal with that later.
Wow. Still super boring but I see a > prompt so progress. I realized that the display was being updated every time through the main loop so I added a check in the 8080 emulator to set a dirty flag whenever the shared video memory was written to and now only update the screen when the dirty flag is set. Good enough for now.
The Keyboard
The 8080 can communicate with peripherals through shared memory locations like the Sol-20 display does, or through I/O ports. I/O ports are accessed via the 8080 op codes IN and OUT. There are 256 possible ports numbered 0x00-0xFF. When an IN instruction is executed the 16-bit address bus is set with the port number of the request in both the upper and lower bytes of the address, the IORQ (Input/Output Request) line is held high, and a data byte is retrieved from the 8-bit data bus. Similarly, for an OUT instruction, the 16-bit address bus is set with the response port number in both the upper and lower bytes of the address, the IORQ line is held high, and a data byte is written to the 8-bit data bus. You can think of this block of ports as a separate "memory space" for the 8080.
For the exception of the memory mapped display, all communication between the Sol-20 and peripherals is accomplished via I/O ports. I have added code that "handles" the IN and OUT op codes and emulates device interaction. Let's look at the keyboard implementation as an example.
I created a small keyboard buffer to store key presses that are mapped from my "modern" keyboard to keys that the Sol-20 is expecting. 95% of the key codes are the same but some are different and the Sol-20 has a few extra keys like LOCAL and CLEAR. When I get Dave's keyboard working this mapping will no longer be required.
When the Sol-20 monitor program is waiting for a key to be pressed, it will make repeated IN requests to port 0xFA to fetch the General Status Port. If there is a key in my local buffer I return the 8-bit status result with the Keyboard Data Ready bit (0x01) "set" otherwise that bit will be "cleared". When it "sees" that there is a key ready, the monitor program will make a subsequent IN request on port 0xFC to fetch the key which I then returned from the head of my buffer.
More Screen Stuff
With the virtual keyboard running I can now enter commands to Solos.
A little more interesting. But something is missing. There is no cursor. It turns out that the Sol-20 marks the cursor position on the screen by setting the high bit of the character the cursor is on. The video hardware on the original machine uses this bit indicator to inverse the character at that position (black character on white background) and optionally blinking that character. I added a cursor by doubling the size of my character table with the characters 0-127 as normal white on black background characters and the corresponding characters in the 128-255 range as inverted black on white background characters. This gets me the block cursor that I want. I'm leaving the blinking part as an exercise for future me.
One more thing I noticed was that the display did not scroll as expected with long command results, but instead wrapped from the bottom to the top of the screen.
Sol-20 had a solution for this too. A "start display line" value is continuously output from port 0xFE via the OUT op code. The VDM-1 hardware would use this value to implement scrolling behavior by emitting the lines from the shared video memory beginning with the start display line and ending with the last line to the top of the screen first, then it emits the lines from the start of the shared video memory and ending with the start display line to the bottom of the screen. My display implementation does the same. For the above example the start display line value would be 4.
Virtual Cassette Tapes
With just keyboard and display you can view and enter values into memory but not much else. I guess you could hand assemble a program, enter it into memory, then execute it were you so inclined. But to be truly useful and interesting you need the ability to load and save programs. The Sol-20 and Solos had built in support for two cassette tape drives. I have mentioned Jim Battle's excellent Solace Virtual Tape Drive and it's faithful reproduction of the cassette tape experience. My goal here is not nearly as lofty. At least initially I just want to support the Solos commands for loading (GET), saving (SAVE) and listing (CATALOG) "files" from "tape".
A Sol-20 file on tape has the following format.
Lead-in: At least 30 null (0x00) characters followed by a 1 (0x01). Header: 16 byte header followed by a Cyclic Redundancy Check (CRC) byte. * 6 bytes - file name. Actual name maximum is 5 bytes. Named padded out to 6 bytes with 0s. * 1 byte - file type. * 2 bytes - data length excluding CRCs. * 2 bytes - starting memory location to load data. * 2 bytes - execution address in not the same as the starting address. * 3 bytes - padded with 0s. * 1 byte - CRC byte. Data: The file contents with length defined by the header. After every 256 bytes there is a CRC byte that is not included in the header length.
When the emulator starts up it looks for a couple of special files TAPE1.svt and TAPE2.svt and uses them to load into memory virtual tape images for cassette 1 and 2 using the format defined above. These .svt files use a subset of Jim Battle's Solace Virtual Tape Format 1 to define the tape's content. The commands implemented are:
H NNNNN TT LLLL SSSS XXXX Create a header with name NNNNN, type TT, date length LLLL, start address SSSS, and execution address XXXX. All parameters except name are assumed to be in hex notation. D AABBCCDDEEFF... Specifies a sequence of data bytes, as hex digits. There can be up to 32 bytes on one line. F [file name] Load the file from [file name]. There are two types of files supported. .HEX files are assumed to be binary images of a properly formatted tape file and are loaded "as is". .ENT files are text files whose first line is an ENTER command with the starting address and subsequent lines have the format AAAA: HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH where AAAA: is a memory address followed by 16 hex encoded bytes to load at that address.
All other SVT commands are ignored for now.
OK so I have virtual tape images now, how does Solos access them? As with all devices through ports of course. When Solos wants to read from or write to a tape the first thing that it does is attempt to turn the tape drive on by performing an OUT byte to port 0xFA with the TT1 bit (0x80) set for tape 1 or the TT2 bit (0x40) set for tape 2. Sol-20 had a hardware connection to the cassette players AUX jack to accomplish this. My emulator uses this signal to prepare for tape activity. Since I don't know if the operation will be a read (LOAD) or write (SAVE) I prepare for both. For reading I set the tape head to 0 to start reading from the beginning of the tape, and switching to virtual tape 1 or 2 depending on what TTx bit was set. For writing I prepare a empty buffer to accept tape writes from Solos. A tape on flag is also set at this point.
Once the tape is started, Solos will perform an IN on port 0xFA to see the tape ready status. For reading if the tape head is less than the length of the current virtual tape the status byte will be returned with the TDR (Tape Data Ready - 0x80) bit set. Solos will then issue INs on port 0xFB to retrieve consecutive bytes from the current virtual tape. For writing a TTBE (Tape Transmitter Buffer Empty - 0x40) bit will be set. Solos will issue OUTs to port 0xFB with the bytes to save which get appended to my output buffer.
Finally when the LOAD or SAVE operation is complete Solos will turn off the drive by sending an OUT to port 0xFA with a null byte clearing the TDR and TTBE bits. For reads there is nothing more to do here, but for writes (SAVEs) at this point if tape on is set, the output buffer is written to a file with the tape filename used in the SAVE command and .HEX extension. At the same time a "F filename.HEX" entry is added to the appropriate TAPEn.svt file (if it's not there already) then the virtual tape is reloaded to pick up the changes.
So with the default TAPE1.svt that looks this:
SVT1: Solace Virtual Tape Format 1 F aster.ent F atc.ent F chess.ent F minefield.ent F msbasic.ent F raiders.ent F reversi.ent F trap.ent
You can now issue the CATALOG command.
Then GET the CHESS game.
And EXECUTE it with an >EX 0000 command.
Finally something interesting.
Getting the Ratio Right
When I was working on the virtual display I skipped a couple of improvements in the interest of finishing some of the other stuff like keyboard and virtual cassette tapes. The first was the aspect ratio which was more like 16:9 than the period 4:3. This has been adjusted by altering the character ROM images, basically by doubling every scan line.
I have also added an optional virtual blinking cursor, the original's display hardware took care of this. The original Sol-20 also had a bank of 8 dip switches that controlled display options like SOLID and BLINK cursor. I'll be adding a similar set of switches to my reproduction, but for now the BLINKING_CURSOR option is a Boolean in my Python code.
I think there is a fair amount of functionality in the emulator already. Serial and parallel port support is not there yet. I have posted the code to GitHub. You should check out the Solos User's Manual to see what commands are possible.
Body Building
My local makerspace was in the process of rewiring the woodworking shop which includes the CNC that I want to use to mill the walnut side panels. In the mean time I had been taking the pre-requisite online courses in order to qualify on that particular piece of equipment.
Even though I couldn't make the walnut side panels right away I decided to get going on the Sol-20 case. In addition to creating the reproduction keyboard, Dave has also produced DXF files for the side panels.
As you can see there are two distinct parts. There is the outside panel that will be milled from walnut, and an inside panel onto which the blue console pieces will rest. There are a lot of cutouts on the inside panel that were used to attach internal components from the original design like the 5-slot S-100 bus cage and power supply. In my much simpler reproduction these will not be used.
With the side panels pretty much a known quantity, there were still many unanswered questions. For instance how wide are the blue console pieces? I know the size of the keyboard cutout from Dave's KiCad files, but how is it positioned relative to the edges of the case?
Well redjr16 to the rescue. Rick, who actually owns a Sol-20 (I'm totally jealous), was kind enough to take the time to answer these questions, take pictures, and more. Thanks Rick!
With these measurements I was confident that I could produce a Sol-20 body that was pretty close to the original's. I loaded the DXF files into Fusion 360 and produced STL files for each of the side pieces. Then I brought these STL files into TinkerCAD so I could noodle around with the design. Here is what I ended up with.
I used the laser cutter at my makerspace to cut four of the inside panels (blue) and two of the outside panels (red) from 3 mm hardboard. The outside pieces will be used as templates when producing the final walnut panels, but in the mean time I can use them as stand-ins while I work on the case panels. The cross pieces (yellow) are 1" x 3" pine cut to 434 mm lengths and are attached to the inside pieces with #8 x 1 1/4" flat head wood screws (in which the heads should end up being flush with the panel). Outside pieces are for the moment bolted to the inside with M3 x 12mm bolts and nuts using existing holes.
Using the inside panel DXF outlines as a guide, and with additional pictures from Rick, I modelled the keyboard panel seen in the rightmost photo above. I lucked out because the width of the panels (446 mm) will just fit on my printer if split in two. The pieces are then glued together and reinforced with cross beams.
The panel is 3 mm thick which seems to be sufficient to prevent sagging in the middle. It shouldn't be too hard now to finish the rest of the console pieces.
The Sol-20 Keyboard
The keyboard in the Sol-20 was a capacitive keyboard made by Keytronic. These keyboards had a great feel, but unfortunately, the foam pad present in each key deteriorated over time and virtually all keyboards of this type failed. To be fair it has been 45 years since the Sol-20 was introduced.
If you are lucky enough to find a vintage Sol-20 for sale (and can afford to buy it) you will probably be faced with this keyboard issue. Fortunately all is not lost. One option is repair. Geoff Harrison has figured out a way to make his own foam pads, and has a nice write-up on how he did it. Please see Geoff's web page on how to repair a Sol-20 Keyboard. Also Texelec has a 105 key replacement pad set at a reasonable price.
The second option is to replace the keyboard. I have already mentioned Dave from osiweb.org who has designed a complete replacement keyboard for the Sol-20 using modern Cherry key switches. While not an exact replica, Dave has gone to great lengths to reproduce the look of the original keyboard, including having a set of custom Sol-20 specific keycaps manufactured. Dave's keyboard will drop right into an original Sol-20. So cool.
Fortunately Dave's keyboard is also perfect for someone trying to make a Sol-20 reproduction. Dave offered to ship me an assembled keyboard, but I didn't want to deprive myself the fun of soldering one up myself.
You can see above the keyboard PCB and aligner for Futaba MD-4PCS switches. The bag to the right is a set of "standard" keycaps. The keycaps below the PCBs are Sol-20 specific keycaps that Dave had manufactured, and the smaller PCB to the right of that is the PCB for a very flexible encoder with the following capabilities (from Dave's GitHub repository):
- Supports up to 3 "special" host outputs, such as RESET, SCREEN_CLEAR, BREAK, etc.
- Supports up to 3 keyboard LEDs
- Can decode arbitrary keyboards up 16 rows by 8 columns.
- Apple 1, Apple 2, and SOL-20 compatible outputs. Other configurations can be supported by making a custom cable.
- Up to 8 configuration settings via an up-to-8 position DIP switch
- Parallel or serial output
The Keyboard Encoder
The construction of Dave's encoder was pretty straight forward. I followed Dave's assembly notes on GitHub. Here is what the end result looks like.
Nothing to see here. What was a little trickier was flashing the ATmega328P with the encoder firmware. Dave uses Atmel Studio 7 to build the firmware and a high end Atmel-ICE programmer burn the chips. A little out of my price range.
Fortunately you can use practically any Arduino as an AVR programmer. There is a lot of sometimes confusing information online on how do do this. I'll just tell you about what worked for me.
I started by opening the Arduino IDE and loading the sketch ArduinoISP.
I had a Arduino UNO attached on COM12 so I compiled and uploaded ArduinoISP with the following settings.
Then I switched the Programmer: setting in the IDE to Arduino as ISP.
Using jumpers I wired the Arduino UNO to the encoder board's ISP Header with the following connections.
Arduino | ISP Header |
---|---|
Pin 10 | Pin 5 (RESET) |
Pin 11 | Pin 4 (MOSI) |
Pin 12 | Pin 1 (MISO) |
Pin 13 | Pin 3 (SCK) |
+5V | +5V |
GND | GND |
Here is my setup.
The Arduino IDE uses a command line program called avrdude under the covers to flash AVR devices. Getting the command line parameters to this program correct can be tricky. Fortunately there is a GUI called avrdudess which can be found here that I downloaded.
I didn't have an environment setup to build Dave's encoder firmware, but he was kind enough to send me the latest build's HEX file. At this point I was all set to flash the ATmega328P on the board. I fired up avrdudess.
I altered the following inputs:
- Entered the Fuse settings that Dave provided: Low 0xD2, High 0xD9, Ext. 0xFF.
- Changed the MCU to the target device ATmega328P.
- Set the Flash input field to Dave's firmware HEX file.
- Changed Port to the com port the UNO was attached to: COM12.
Then I pressed the Program! button. You can see that the writing and verification all checked out so the keyboard encoder is ready to go.
Logo
One of the things that makes the Sol-20 so memorable is the logo bar of yellow/orange lettering that runs the full width of the body. Stunning. Needless to say I wanted to do a good job of reproducing the logo.
Again I have to thank redjr16 who sent me a great picture of the logo from his machine.
With his picture, and knowing the dimensions of the logo (width 446 mm), I brought the image into Fusion 360 as a Canvas and calibrated it within fusion to it's actual size. Using Fusion drawing tools (mostly splines) I "traced" the letters and icon and ended up with a sketch of the logo.
My plan at this point was to save the sketch as a DXF file, bring it into Inkscape, add the colors, and print the logo onto cardstock which is what was done on the original Sol-20. I even had a piece of acrylic cut to size to go in front of it to protect it, again like the original.
I have had some success in previous projects "drawing" text by extruding the letters and printing them in a different color by pausing the print at the appropriate layer and switching the filament. So I decided to give this a try. To my delight this worked better than expected.
The small amount of relief afforded by the extrude characters makes them really pop. So as not to waste, I am using the acrylic piece as a backing for the printed logo which is only about 1 mm thick.
Here is a sneak peek at the logo bar in place. I had at this point only just started printing the top panel.
You might be asking "Hey Mike what's with the two different blues?". I tried the lighter blue on the top panel and I like it better, so I will eventually be reprinting the keyboard panel to match.
More Skinning
I finished the cover for the back part of the Sol-20. I had to print it in four parts which I glued together and braced.
If I get another 3D printer it will have a 500 mm x 500 mm print bed for sure. Or maybe I can just get Ivan Miranda to print these large parts for me ;-)
At any rate the panel fit perfectly on my Sol-20 frame.
Seeing more of the light blue convinces me that it's my preferred color choice.
Keyboard Construction
When the Fubata MD-4PCS key switches finally arrived it was time to get the keyboard put together. The first step was to add the 85 IN4148 diodes. To save some time I printed a diode lead bender from Thingiverse.
I was super careful to double and triple check the orientation of each diode since trying to replace one after all the switches are installed would be very hard.
You can also see that I have installed the screw-in stabilizers for the space bar and Shift keys plus the three limiting resistors for the Local, Upper Case, and Shift Lock key LEDs. On the back a 2x20 pin female connector was added to mate with the encoder.
On the aligner PCB there are four extenders to be used with the Spacebar and Shift Stabilizers.
Snip these off and as the text instructs you have to file down one end so that it is 1.5 mm thick so they will fit into the keycaps.
This is how they will be installed when you first start adding switches attaching the aligner and keyboard PCBS.
Make sure that they pass through the openings in the aligner as pictured above.
I followed Dave's advice adding the switches.
- Snap a few Futaba keys into the aligner, perhaps 3 or 4 evenly spaced per main keyboard row, and one at each corner of the keypad. Then fit the aligner with keys to the keyboard PCB. At this point you should have the extenders connected and ready to go as pictured above.
- Solder in one lead of each switch. Then, go through all the switches and reflow each solder joint while applying tight clamping pressure (with your fingers) to push the aligner and PCB together so each switch is flush. This makes a torsion-box structure for the keyboard.
- Now solder the second lead of each switch.
- Now snap in a few more keys, spaced evenly between the already installed switches, and repeat the same procedure as above.
- Now install the rest of the switches, snapping in enough switches to fill one of the gaps between keys, then soldering all the leads at once.
Here is what I have so far. The wires you can see on the left had side of the keyboard are for the Local, Upper Case, and Shift Lock key LEDs since I found that the leads on the LEDs that I had were too short.
Using one of the keycaps I cut the wires so that when the LED was attached it would extend up into the keycap without touching the top when the key was depressed. Looks like this.
Finally I attached the encoder via the 40 pin connector. There were holes on the encoder and keyboard PCBs but I found they did not line up correctly and would have been hard to reach at any rate. So I printed a brace to secure the front part of the encoder board.
That's pretty much it for the keyboard. I'll attach the keycaps once I have verified that everything is working as expected.
Mounting the Keyboard
I wired the keyboard up to the Raspberry Pi 4 I will be using to run the Sol-20 emulator. I did enough testing to ensure that all of the keys are working as expected. At first some of the keys were not responding, but with Dave's help I discovered I had missed installing a couple of jumpers and also I found a solder bridge that shouldn't have been there. When I was satisfied all was well I installed all of the keycaps.
Using the finished keyboard I was able to refine the measurements for the keyboard cutouts in the front panel. I reprinted the panel with the changes in the "new" light blue filament and reinforced it as I had the first one.
I added some 1/2" x 1/2" wooded supports for the keyboard on the side frame positioned about 2mm below the top edge that the front panel will be resting on.
Using the printed front panel as a guide, I positioned the keyboard and locked it in place with four #6 x 5/8 inch wood screws.
Wiring the Keyboard
The keyboard encoder is expecting 5V while the Raspberry Pi 4 operates at 3.3V. So to overcome this I purchase a Voltage-Level Shifter Module from Amazon. I also printed a "caddy" to hold the Pi 4 in place and added a small 30 mm x 30 mm x 10 mm blower fan for good measure to keep things cool. The fan I used is from Amazon: GDSTIME 3cm 30mm x 10mm 5V DC Brushless Small Blower Cooling Fan, with Dual Ball Bearings. The fan and the keyboard will be run off of the Pi's power supply. The Pi is secured in place to the caddy with two sided tape.
I then mounted this unit onto the back support of the Sol-20 frame again using two sided tape. The USB and HDMI ports are facing to the rear of the unit.
So we are ready to wire the keyboard to the Pi. Here is what the Sol-20 header pinout looks like.
And the Raspberry Pi level shifter hat.
So here is how I wired the keyboard. Note that for the exception of +5V and GND lines which are wired to the 3.3V side or the level shifter, all of the other connections are wired to the 5V side.
Keyboard Encoder | Raspberry Pi | Description |
---|---|---|
5V | 5V | Power |
GND | GND | |
D0 | GPIO6 | Key 0 bit (low) |
D1 | GPIO13 | Key 1 bit |
D2 | GPIO19 | Key 2 bit |
D3 | GPIO26 | Key 3 bit |
D4 | GPIO21 | Key 4 bit |
D5 | GPIO20 | Key 5 bit |
D6 | GPIO16 | Key 6 bit |
D7 | GPIO12 | Key 7 bit (high) |
STROBE | GPIO5 | Key ready on falling edge. |
OUT1 | GPIO23 | LOCAL button. Toggle. HI when LED on. |
OUT2 | GPIO22 | BREAK button pressed when rising edge. |
OUT3 | GPIO24 | RESET button pressed when falling edge. |
Here is what the wiring looks like.
I had a small issue with the BREAK which Dave quickly helped to resolve, but otherwise everything is working great. The keyboard is now integrated with the emulator. Getting close. Very exciting.
The InSide Story
The walnut sides of the Sol-20 are beautiful and help to set it apart from all of the other computers of the era. I really wanted to do them justice in my reproduction. I also saw the fabrication of the sides as an opportunity to advance my woodworking skills.
A couple of years ago I was thinking about building my own CNC router. At that time the The Mostly Printed CNC (MPCNC) was a popular choice. At the same time a friend told me about the Kwartzlab makerspace so I took a tour on one of their Tuesday Open Nights. I saw their massive Mach3 driven CNC router with a 4x4 foot cutting bed, plus their 100 watt laser cutter, complete woodworking, metal fabrication, craft, and electronics shops and decided to join on the spot. The cost of the parts for a MPCNC would pay for a years worth of access to Kwartzlab. I was attracted by the cool tools, but what I didn't consider at the time was all of the great people that I would get to know there.
Despite the fact that I have had access to the CNC at the "lab" for almost three years now, I have never actually used it. Finally now I had a great reason to remedy that. I had to take some online courses and one-on-one training but eventually I made my first CNC artifact.
The first image of course is a Sol-20 side piece that I cut from a scrap piece of plywood I had lying around. I wasn't about to risk my expensive slab of walnut on my first attempt! But it went well so I took the plunge (second photo).
And thankfully that went OK too. But I was not quite done. The CNC just cut out the side shapes. I wanted to get the nice rounded edges as well. I learned that this was accomplished by using a round over routing bit (pretty clear at this point that I'm not a woodworking guy right). With a little more expert coaching from some lab mates I got this done as well learning how to use a handheld router.
Finally to finish off the pieces I applied some Minwax Walnut Gel Stain. This couldn't have been easier. The stain is applied evenly to the wood with a brush or rag and after only 3 minutes the excess is removed by wiping it off following the grain of the wood with a rag. See photo three above.
Then I installed the walnut sides onto my Sol-20 reproduction.
So happy with the result.
A View Into the Soul of the Sol-20
From the beginning of my work on the Sol-20 reproduction I wondered what kind of display I would use with it. Of course a small CRT based TV or monitor would be ideal. To that end I put out feelers with my maker mates and even had someone at a local electronics recycling depot keeping an eye out for me. But after a couple of months and no success I realized I needed a Plan B.
I started thinking "What if Processor Technology had sourced and branded a monitor for the original Sol-20?". What would that look like? Well it might have looked something like this.
This design takes its cues from the Sol-20 with the wooden sides and color scheme. It has a retro CRT look while using a period correct 4:3 aspect ratio LCD panel. I my humble and somewhat biased opinion it looks great sitting on top of the Sol-20 reproduction.
The build for this was pretty straight forward. I started by laying out the side panels in Fusion 360.
I used the DXF file to laser cut from 1/4 inch plywood two of the smaller side pieces with both sets of holes and two of the larger side pieces with only the one set of holes closest to the center. Using four 1/2 inch wooden dowels cut to 188 mm and with pre-drilled starter holes in the ends I assembled the inside frame (smaller panels) with No. 6 x 1 inch wood screws.
The larger panels I sanded down and stained with the same Minwax Walnut gel that I used on the Sol-20 sides.
The funky grain patterns were a bit of a surprise but I'm kind of liking it. I could have used walnut here but balked a bit at the additional cost. Then I attached the outer panels to the inner frame with M3 x 14 mm bolts.
For the display I repurposed the screen frame that I used in my 2:3 Scale VT100 Reproduction.
I had to tweak the design a bit and I added the logo but overall it saved me a lot of time to repurpose the design. I used the same display as the VT100's a PIM372 (Digi-Key part number 1778-1225-ND), an 8 inch 1024x768 XGA display.
The display panel just snaps into the frame. Be sure to get the orientation right with the display connector at the top of the screen frame. I printed a "caddy" for the driver board and after I connected the ribbon cable attached the board and caddy to the back of the display panel with two sided tape.
Next I designed and printed the "skin" used to wrap the monitor.
I attached the two pieces with glue and a brace for support.
Then I wrapped the monitor frame with the skin. If you loosen the bolts holding the larger side panels in place the skin should slide in easily. Then tighten the bolts again to hold the printed panels in place.
Finally insert the screen frame and display into the monitor.
I connected the display to the Raspberry Pi with an HDMI cable. I was also able to power the display panel via a micro USB cable from one of the Pi's USB ports.
It was fun to imagine an alternate timeline where Processor Technology sold a branded monitor with their Sol-20s.
Interfaces
Here is a photo of the back of an original Sol-20.
You can see that the whole left side is taken up with power supply components: power button, fan, fuse, and power cord connection. Since my reproduction does not require any of these I chose to focus on and highlight the interface section in the lower right part of the rear panel.
So I designed and printed my own "interface" panel and dug through my parts box for the components to populate it.
I then attached the interfaces panel to the rear panel with glue and braces.
Then I added the connection hardware. Here is what the back of my reproduction look like.
Understand at this point these ports are mostly for show. I already have a "virtual" cassette so I'm unlikely to implement a physical one. I do plan to get the serial interface working, but since I have nothing with a parallel interface to connect to, I probably won't wire that one up. While I don't plan to support real Sol-20 personality modules, I do have an idea that I might simulate a personality module with perhaps RFID tags to have the Sol-20 reproduction load different software modules on system startup. Right now the personality module slot is just a simple hole.
Soft Switches
The Sol-20 had 4 banks of DIP switches on the motherboard to control various aspects of the machine's operation. Here's a photo of three of them.
I didn't see an advantage to using physical switches for my emulated hardware so I created a configuration file instead.
# SOL-20 SWITCH FUNCTION DEFINITIONS # # This configuration file replaces the four physical setup switch banks on the Sol-20. # # Display Control # S1-1 = 0 # 0-Run 1-Restart to Zero. (N/A for emulator.) S1-2 = 0 # Not used. S1-3 = 0 # 0-Show control characters. 1-Blank control characters (ASCII values < 32). S1-4 = 0 # 0-Colored characters on black background. 1-Black characters on colored background. S1-5 = 0 # 0-Solid or NO cursor. 1-Blinking cursor. (NOTE: Requires apscheduler - "pip install APScheduler") S1-6 = 1 # 0-Blinking or NO cursor. 1-Solid cursor. S1-7 = 0 # 0-White screen. 1-Green screen. 2-Amber screen. (Emulator extension.) S1-8 = 0 # 0-6574 character ROM. 1-6575 character ROM. (Emulator extension.) # # NOTE: No cursor if S1-5 and S1-6 are off at the same time. # # # Sense Switch # S2-1 = 1 # Sense switches in LSB to MSB order. Read by the system with an IN 0xFF instruction. S2-2 = 1 # Not used by many applications. S2-3 = 1 S2-4 = 1 S2-5 = 1 S2-6 = 1 S2-7 = 1 S2-8 = 1 # # # Serial I/O Baud Rate Switch # S3-1 = 0 # 1-75 Baud. S3-2 = 0 # 1-110 Baud. S3-3 = 0 # 1-150 Baud. S3-4 = 0 # 1-300 Baud. S3-5 = 0 # 1-600 Baud. S3-6 = 0 # 1-1200 Baud. S3-7 = 0 # 1-2400 Baud. 2-4800 Baud. (Emulator extension.) S3-8 = 0 # 1-9600 Baud. # # Do not turn on more than one switch at a time. # # # Serial I/O Control Switch. # S4-1 = 0 # 0-Parity even if S4-5 set to 1. 1-Parity odd. S4-2 = 0 # Data word length. | 0 | 1 | 0 | 1 S4-3 = 0 # | 0-8 Bits.| 0-7 Bits. | 1-6 Bits. | 1-5 Bits. S4-4 = 1 # 0-2 stop bits(1.5 if 5 bit words). 1-1 stop bit. S4-5 = 0 # 0-No parity. 1-Parity. S4-6 = 0 # 0-Full duplex. 1-Half duplex. (N/A in Emulator) #
This file switches.cfg is loaded when the emulator starts up, so if you make any changes to the file you will have to restart the emulator to pick them up. I have posted this file and the updated code that implements these changes to github.
Wiring Up a Serial Port
I felt that it was important that my Sol-20 reproduction work with a real HW Serial port. It is the Sol Terminal Computer after all. I thought that adding an RS-232 Serial hat like I did for my VT100 reproduction would complicate things since I was already using a Voltage-Level Shifter Module hat for the keyboard. So I purchased a USB to Serial Converter from Amazon.
I found that the version of Raspberry PI OS that I was using recognized this device without having lo load any drivers. I did have to figure out what the device name was. I did this by listing all of the USB devices.
pi@raspberrypi:~ $ ls /dev/*USB* /dev/ttyUSB0 pi@raspberrypi:~ $
Then it was a pretty simple process to integrate /dev/ttyUSB0 into my emulator using the Python serial library.
pip install pyserial
I won't go into too many details here, but on a Sol-20 the serial port works just like keyboard. When the Sol-20 monitor program is waiting for a character from the serial port, it will make repeated IN requests to port 0xF8 to fetch the Serial Status Port. If there is a character in the port's input buffer I return the 8-bit status result with the Serial Data Ready (SDR) bit (0x40) "set" otherwise that bit will be "cleared". When it "sees" that there is a character ready, the monitor program will make a subsequent IN request on port 0xF9 to fetch the character which I then returned from the serial port's buffer. Similarly if the monitor wants to send a character to the serial port, it checks port 0xF8 with an IN to see if the Serial Transmit Buffer is Empty (STBE) bit (0x80) is "set" and if so an OUT to port 0xF9 is issued with the character to send which I write to the serial ports output buffer.
I wired the TX, RX, and GND from the USB Serial Converter to the DB9 connector.
Wrapping Up
One of the finishing touches I wanted on this project is to make the Raspberry Pi boot directly into the Sol-20 emulator on startup.
I created an autostart folder on my Pi and switched to that folder.
mkdir /home/pi/.config/autostart cd /home/pi/.config/autostart
Into the autostart folder just created I added the following two files.
runSol-20
cd /home/pi/Sol-20 /usr/bin/python3 main.py
Sol-20.desktop
[Desktop Entry] Type=Application Name=Sol-20 Exec=/home/pi/.config/autostart/runSol-20
In addition the runSol-20 file must be made executable with the following command:
sudo chmod 777 runSol-20
Now if you reboot the system, you should briefly see the desktop appear, and shortly after Sol-20 emulator will load.
Final Thoughts
Well it's been about 45 years since that poor college student version of me saw his first Sol-20 at that small computer store on Queen Street in Toronto. It was something that I never forgot. For me the wait is over. I now have a working Sol-20 and have been having a ball running all of the cool programs that were written for it those many years ago.
I have to thank Dave from osiweb.org who designed the complete replacement keyboard for the Sol-20 using modern Cherry key switches. He was a great help throughout the project. Without this great piece of kit to build on I may not have even attempted this project.
This was the first project I can remember where I didn't have to scour the far corners of the internet for information about the Sol-20. Jim Battle has done an amazing job of gathering a huge treasure trove of Sol-20 materials into one site, Sol20.org. A one stop shop for the would be Sol-20 replicator, or anyone with an interest in this wonderful retro computer. Thanks Jim for all your hard work.
Rick Downs (redjr16), who actually owns a Sol-20 (I'm totally jealous), was kind enough to take the time to answer my many questions, take pictures, and more. Thanks Rick!
When he saw my project Nyles sent me a huge pile of original manuals that he had been keeping.
Once the hardware and emulator were done, these have been invaluable resources for helping me figure out how to run the software that's out there. Thank you Nyles.
It's been a lot fun learning about this wonderful machine. I'll leave you with a side-by-side of my Sol-20 reproduction and the original.
Needless to say I'm extremely happy with the result.