The KIM Uno is a portable, software defined dev kit for (retro) microprocessors. But let me introduce the idea of it by going back in time:
Back in late 2018 it came to my mind, that I wanted to build a small portable microprocessor dev kit, just like the famous KIM-1 from MOS Technology, Inc. and designed by Chuck Peddle who was also involved in creating the 6502 CPU.
But building a "bare-bone" dev kit with discrete logic components was no option since it needed a big power supply (since those ancient devices tend to take some serious current) and also the development would be very time intensive. And I want it now!
Therefore, I designed the KIM Uno as a portable device, which fits in one hand and is powered by two CR2032 batteries. It uses the ATMega328p ("Arduino") microcontroller running at 8 MHz to emulate (or simulate) a desired CPU. This architecture also makes sure, that the emulated CPUs are interchangeable to anything which fits inside the microcontroller's flash memory. So it is a multi-purpose device.
By coincidence I later watched a really good talk - called The Ultimate Apollo Guidance Computer Talk (34C3) - on YouTube where "One Instruction Set Computers" or OISCs are mentioned. I did not know about them and found this as the perfect candidate to implement it.
The KIM Uno emulates a CPU with just one instruction: subleq - subtract and branch if less than or equal to zero.
If you follow along with me through this Instructable, you can build your own KIM Uno in no time. And the best part - beside the fact that you can modify it to your taste - is, that it only costs 4,75 € to make (as of end 2018).
One hint: there is a Git repository which contains all the files provided by the different steps of this instructable. In case you want to modify some resources and share them with us all you can make a PR. But you can also download all files at once there. Simply to to https://github.com/maxstrauch/kim-uno. Thanks!
Step 1: Sourcing the PCB
As you can see, I used the opportunity to design a PCB and let it be professionally made. Since manufacturing it externally and shipping it to you will take a lot of time (depending on where you are in the world ;-) ), getting it ordered it is the first step. We can then continue with the other steps while the PCB is made and shipped to you.
I ordered my PCBs in China at PCBWay for just $5. I don't get any benefit for presenting PCBWay as my goto manufacturer for PCBs, it's just that it worked fine for me and might also work fine for you. But you can order them at any other place like JLCPCB, OSH Park or any local PCB company.
But if you are willing to order them at PCBWay you can download the attached ZIP file "kim-uno-rev1_2018-12-12_gerbers.zip" and upload it directly to PCBWay without any change. This is the original file I used to order the PCBs you can see in the images.
If you are ordering them from an other manufacturer you might need to re-export them from the original KiCad sources, because I generated them with the specifications from PCBWay you can find here. For the original KiCad sources, download "kim-uno-kicad-sources.zip" and extract it.
But there is even a second way: if you don't want to order the PCB, you can build your own version using perfboard or even a breadboard.
Anyway: since the PCBs are now on the way, we can focus on the other parts! Come, follow me.
Step 2: Sourcing the Components
Now you need to get the components. For this you'll find an overview image of all components and quantities you need, attached to this step as well as a BOM (bill of materials).
The BOM contains links to eBay. Although those offers might be closed when you read this, you can use it as a starting point. The used components are pretty standard.
In the following I'll explain to you all the needed components:
- 7x 1 kΩ resistors for the seven segment displays. You can reduce the value (e.g. to 470 Ω) to make them shine brighter, but reduce it not too much otherwise the LEDs will die or the battery is drained very quickly. I found that this value works for me
- 1x 10 kΩ as a pull-up resistor for the RESET line of the microcontroller
- 1x 100nF capacitor to smooth out any voltage spikes (which should not happen since we are using batteries, right, but for good measure ...)
- 1x ATMega328P in the DIP-28 package (usually named ATMega328P-PU)
- 1x the main PCB - see the previous step; either ordered or built by yourself
- 2x CR2032 battery holders
- 1x SPDT (single pole, double throw) switch which basically has three contacts and in every of its two states (either on or off) it connects two contacts
- 20x tactile push buttons for the keyboard. To use the backside of the PCB I used SMD tactile push buttons (the standard 6x6x6 mm ones) - they are pretty easy to solder as you will see
- OPTIONAL: 1x 1x6 pin header for connecting the programmer, but this is optional as you will see later
- 1x seven segment display with 4 digits and 1x seven segment display with 2 digits - the board will take only 0.36 inch (9,14 mm) elements with common anode wiring. Both requirements are important in order to get a working unit. But also this type of seven segment display are very common
Attached to this step you can find the file "component-datasheets.zip" which contains more precise information on dimensions and types of the used components. But most of the components are very standard and can be sourced easily for little money.
Now you need to wait until you have all components ready to continue to soldering. During this time you can already jump to the end and read a little bit about using the KIM Uno if you like.
Step 3: Soldering Tool Overview
For soldering and building the KIM Uno you need the tools shown by the images:
- Wire cutter (to cut the end of the component wires)
- Flat pliers
- Pair of tweezers
- (decent) Solder which is not to thick - I use 0.56 mm solder
- A soldering iron - you don't need a high-end soldering iron (because we are also not doing rocket science here) - I use the Ersa FineTip 260 for a long time now and it is really good
- A flux pen: adding flux to the components and pads makes it so much more easier to solder them since the solder then "flows" by its own to the right place*
- Optionally: a sponge (from metalwool) for your soldering iron
To later program the KIM Uno you'll also need:
- a computer with the AVR-GCC toolchain and avrdude to upload the firmware
- an ISP (programmer) - as you can see on the image I'm using my Arduino Uno as an ISP with a special sketch - so no need to buy any fancy hardware
* some guidance by humans needed ;-)
Are you ready? In the next step we are going to start assembling the KIM Uno.
Step 4: Soldering #1: Adding Resistors and Capacitors
You should always work from the smallest (in terms of component height) components first, to the highest components last. Therefore, we start by adding the resistors and bending over the legs at the back so that the resistors are easy to solder and stay in place. Afterwards cut the long wires.
Also, not shown in the images, add the small 100 nF capacitor the same way.
One tip: keep those wire legs in a small container, they sometimes come in handy.
Step 5: Soldering #2: Assembling the Keyboard
The next step is to solder the 20 SMD tactile switches. Since this work is a little bit fiddly, we do it now, when the PCB lays flat on the workbench.
We'll work from top to bottom (or from left to right if the PCB is oriented as shown in the photos) and start with the first row: choose one of the four pads for every switch and wet it with the flux pen.
Then use a pair of tweezers to grab a switch and position it carefully on the four pads. Then solder only the leg of the switch which is on the pad you picked and prepared with flux. For this you should "grab" some solder with your iron before starting. Using this method, complete the whole row of switches, soldering only one leg.
The image with the arrows shows a magnification how the soldering was done exactly.
After you have soldered the entire row (one pin only) you can make little adjustments by heating the pin back up and re-positioning the switch. Make sure, that the switches are aligned as good as possible.
If you are happy with the alignment, you can wet all other pins with the flux pen and then solder them by touching it with the soldering iron and adding a little bit solder by touching it also. You'll see that the solder is sucked directly onto the pad.
After soldering a row or so you will notice that you get the hang of it and it is not that hard but repetitive. So just do the rest and you will end-up with a finished keyboard in no time.
Step 6: Soldering #3: the Seven Segment Display, Switch and Pin Header
Now you can add the switch and pin header (optional) by holding it with your finger and soldering one pin to hold it to the PCB, so that you can solder the other pins and finally touch up the initial holding pin.
Be carful that you do not burn yourself with the hot soldering iron. If you are not comfortable with this, you can use a little bit of tape (e.g. painter's tape) to hold the component. This way you have both hands free to move.
The seven segment displays are soldered the same way (see image): you put it in, hold it with your hand or tape and solder two opposite pins to hold it in place while you can solder the other pins.
But be careful and put the seven segment display in the right direction (with the decimal dots facing to the keyboard). Otherwise you're in trouble ...
Step 7: Soldering #4: Soldering the Microcontroller
Now that you have a lot of practice, you can go ahead and put in the microcontroller with the notch on the top (or first pin) facing towards the switch. Using Flat pliers you can carefully bend the legs of the microcontroller a little bit in, so that they match the holes on the PCB.
Since it is a tight fit, you need some controlled force to put the microcontroller in. The advantage is, that it does not fall out. This means, you can take your time and solder it from the back.
Step 8: Soldering #5: Add the Battery Holders (final Step)
Finally you need to add the battery holders to the back. For this you simply use the flux pen and wet all four pads and then get some solder on your iron. Align the battery holder carefully on both pads. At both ends of the contacts there should be the same amount of the PCB pad visible. Touch the PCB pad and the leg of the battery holder with your iron. The solder will flow under the pad and over it and secure it in place as shown in the image. If you have problems with this, you can add more flux with the pen.
Step 9: Flashing the Emulator
In the attached zip archive "kim-uno-firmware.zip" you can find the source code for the emulator along with an already compiled "main.hex" which you can directly upload to the microcontroller.
Before you can actually use it, you need to set the fuse bits of the microcontroller, so that it uses the internal 8 MHz clock without dividing it in half. You can get the job done with the following command:
avrdude -c stk500v1 -b 9600 -v -v -P /dev/cu.usbmodem1421 -p m328p -U lfuse:w:0xe2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m
If you don't know avrdude: it is a program for uploading programs to a microcontroller. You can learn more about it here. Basically you install it and then it is ready to use. For your setup you might need to change the argument of "-P" to another serial port. Please check on your computer which serial port is used (e.g. inside the Arduino IDE).
After this you can flash the firmware onto the microcontroller with this command:
avrdude -c stk500v1 -b 9600 -v -v -P /dev/cu.usbmodem1421 -p m328p -U flash:w:main.hex
Again: the same thing applies to "-P" as above.
Since I do not own a "professional" ISP (In-System Programmer) I always use my Arduino UNO (see image) and the sketch I attached ("arduino-isp.ino", from Randall Bohn). I know that there is a newer version, but with this version I had zero trouble with over the last five years, so I keep it. It just works. Using the comment in the header of the sketch you get the pinout on the Arduino UNO and using the schematic of the KIM Uno (see attached) you can get the pinout of the 1x6 ISP header on the KIM Uno. The square pin, near to the seven segment display is pin 1 (GND). The following pins are (in the right order): RESET, MOSI, MISO, SCK, VCC. You can connect VCC either to 3V3 or to 5V.
If you did not add the 1x6 pin header you can use breadboard wires and put them into the connection holes and angle them with your finger - just as shown in the picture. This makes enough contact to flash the firmware and set the fuses. But if you like a more permanent setup, you should definitely add the 1x6 pin headers.
I have two devices: a production version without the pin headers and a development version with pin headers which I leave connected and use it over and over again during development. This is much more comfortable.
Step 10: Finished
Now you are finished and can start writing your own subleq programs on paper, assembling it and then entering it into the memory.
The KIM Uno comes with a pre-programmed Fibonacci computation starting at memory location 0x0a. It is set by default to n = 6 so should result in a value of 8. Press "Go" to start computation.
Step 11: PCB Design Analysis
After completing this project I found a couple of points which are noteworthy and should be addressed in a new revision of the board:
- the ATMega328p's silk screen has not the usual notch where the first pin is located. The DIP-28 footprint does not even have a square pad where the first pin is located. This should definitely be improved with a more detailed silkscreen to prevent confusion
- the ISP header has no connection labels on the silk screen. This makes it difficult to recognize how to connect it to the ISP
- the ISP header could be changed into a 2x6 pin header with a standard pin layout to prevent any confusion
Apart from those points I'm pretty happy how it turned out and worked on the first try.
Step 12: How to Program SUBLEQ?
The subleq instruction stands for subtract and branch if less than or equal to zero. In pseudo-code this looks like the following:
subleq A B C <=> mem[B] = mem [B] - mem[A]; if (mem[B] <= 0) goto C;
Since the KIM Uno emulates a 8-bit machine, all arguments A, B and C are 8 bit values and therefore it can address a total main memory of 256 byte. Obviously this can be extended, by making A, B and C multi-byte values. But for now let's keep it simple.
The KIM Uno has also "peripherals": the display and keyboard. It uses a memory mapped architecture to interface those peripherals, although the memory map is very simple:
- 0x00 = the Z register (zero) and should be kept zero.
- 0x01 - 0x06 = six bytes which represent the value of every of the display segments (from right to left). A value <= 0xf (16) can be placed in one of this memory locations and it will appear on the seven segment display. There are some special characters to show which can be displayed setting a value > 0xf - see the source code (main.c) for more details.
- 0x07, 0x08, 0x09 = three bytes where every byte represents two seven segment displays (from right to left). This memory locations allow simply displaying a result without splitting up the result into two nibbles to place it in the single digit memory locations 0x01 - 0x06.
- 0x0a+ = A program starts at 0x0a. Currently the "Go" key executes from 0x0a fixed.
With this information one can now write a program in assembler and enter the instructions into the memory and then execute it. Since there is only one instruction, only the arguments (A, B and C) are entered. So after three memory locations the next instruction arguments begin and so forth.
Attached to this step you can find the file "fibonacci.s" and also an image of the handwritten program which is an example implementation of Fibonacci. But wait: there are three instructions used - specifically ADD, MOV and HLT - which are not subleq. "What is the deal? Didn't you say that there is only one instruction, subleq?" you are asking? It is very easy: with subleq one can mimic those instructions very easily:
MOV a, b - copy data at location a to b can be composed of:
- subleq b, b, 2 (next instruction)
- subleq a, Z, 3 (next instruction)
- subleq Z, b, 4 (next instruction)
- subleq Z, Z, e.g. 5 (next instruction)
Using the subtraction feature of subleq, which does mem[b] - mem[a] and overwrites mem[b] with the result, the value is copied using the zero register. And "subleq Z, Z, ..." simply resets the zero register to 0, regardless of the value of Z.
ADD a, b - adds the values a + b and stores the sum in b can be composed of:
- subleq a, Z, 2 (next instruction)
- subleq Z, b, 3 (next instruction)
- subleq Z, Z, e.g. 4 (next instruction)
This instruction simply calculates mem[b] - (- mem[a]) which is mem[b] + mem[a] by also using the subtraction feature.
HLT - halts the CPU and ends the execution:
By definition the emulator knows that the CPU wants to terminate if it jumps to 0xff (or -1 if singed). So a simple
subleq Z, Z, -1
does the job and indicates to the emulator, that it should end emulation.
Using this three simple instructions, the Fibonacci algorithm can be implemented and works fine. This is, because the OISC can compute everything a "real" computer can compute with only the instruction subleq. But of course, there are many tradeoffs to make - like code length and speed. But nonetheless it is a great way to learn and experiment with low level software programming and computers.
Attached to this step you can also find the zip archive "kim_uno_tools.zip". It contains some basic assembler and simulator for the KIM Uno. They are written in NodeJS - make sure that you have installed it.
If you take a look at "fibonacci/fibonacci.s" you'll find that it is the source code for the discussed fibonacci implementation. To assemble it and make a program out of it, that the KIM Uno can run, you enter the following command (in the root of the extracted "kim_uno_tools.zip" archive):
node assemble.js fibonacci/fibonacci.s
and it will either print an error if you made a mistake or spill out the resulting program. To save it, you can copy the output and save it to a file or simply run this command:
node assemble.js fibonacci/fibonacci.s > yourfile.h
The output is formatted in a way that it can be directly included in the KIM Uno firmware as a C header file, but the simulator can also use it to simulate. Simply enter:
node sim.js yourfile.h
And you will be presented with the simulation result and the output expected from the KIM Uno on the display.
This was a very brief introduction to this tools; I recommend you to play around with them and look how they work. This way you get a deep knowledge and learn the functioning principles behind CPUs, instructions, assemblers and emulators ;-)
Step 13: Outlook
If you read this you probably went through this entire instructable and built your own KIM Uno. This is really nice.
But the journey does not end here - there are an infinite number of options how you could modify the KIM Uno and customize it to your needs and liking.
For example the KIM Uno could be equipped with a "real" retro CPU emulator which might emulate the famous MOS 6502 or Intel 8085, 8086 or 8088. Then it would go the way to my initial vision, before I learned about OISCs.
But there are possible other uses, since the hardware design is pretty generic. The KIM Uno could be used as ...
- ... a remote controller e.g. for CNCs or other devices. Maybe wired or equipped with an IR diode or any other wireless sender
- ... a (hexadecimal) pocket calculator. The firmware can be adapted very easily and the board design does not need to be changed very much. Maybe the silkscreen can be adapted with math operations and the gap between the segments can be removed. Apart from this, it is already ready for this transformation
I hope you had as much fun following and hopefully building the KIM Uno as I had designing and planning it. And if you extend it or modify it - please let me know. Cheers!
Runner Up in the