-
Another Working Digital Computer Lives!
06/15/2021 at 12:26 • 0 commentsI just wanted to welcome Marcelo to the small rather exclusive club of hobbyists that have actually built a Working Digital Computer based on the book. Check out his PaperClip Computer project page!
-
Say Hello To WDC-2
05/07/2020 at 23:10 • 0 commentsOver the past couple of months I had been slowly building a new working digital computer to replace the one now on display at the System Source Computer Museum. Hopefully in the not too distant future people will actually be able to go into the museum and see it there :-(
Well a basically identical reproduction of the original (WDC-1) is now finished! Not to much to say here except that I thought the process of rebuilding would be tedious and boring, but I was surprised at how enjoyable it actually was. Without the anxiety of wondering (despite best laid plans) if everything would work as expected, and the anticipation pushing you (maybe too fast sometimes) to want to see a finished project, I had a very pleasant experience. I think it helps that there is a good variety of tasks that go into making a WDC:
- Printing and post printing (a lot of the smaller parts required brims that had to be removed).
- Assembly. Who doesn't like putting things together.
- Wiring and soldering .
- Organization. I took the time to organize the various STL print files and remove any that were no longer being used.
By working on a module at a time, I was able to cycle through these task and thus not get too tired of doing any one thing for too long.
All in all, making WDC-2 was a nice change of pace.
-
Postscript
03/17/2020 at 14:53 • 2 commentsWith thanks to Bob Roswell curator of the System Source Computer Museum I'm proud to announce that my WDC-1 will be on permanent display at the museum.
WDC-1 is on the middle shelf, to the right of a CT-650, which was a commercial version of the working digital computer built from the same book. The tablet on the far right is looping the video that I made of WDC-1 in action (which in hindsight I should have put a little more effort into - sigh).
In the same picture you can see six other devices that I have made reproductions of, five of which I created myself. I'm in good company there. I'm honored.
-
Winding Down
01/24/2020 at 00:46 • 0 commentsI posted a video of WDC-1 in "action" today calculating a couple of digits of the Fibonacci Sequence.
It's been a lot of fun but, time to move on. I appreciate the all follows, likes, and views. Thank you!
-
Running a Program on WDC-1
01/15/2020 at 22:17 • 0 commentsWith everything together I wanted to do something interesting on my Working Digital Computer Version 1 so I wrote the following program to calculate the first few numbers in the Fibonacci sequence (which we know starts with 0, 1 and that each subsequent element is the sum of the previous two numbers in the sequence (so 0, 1, 1, 2, 3, 5, 8, 13...)).
; Calculate the first few Fibonacci numbers. ; Assumes that the first two numbers 0 and 1 are in the ; INPUT Encoder A and Encoder B addresses. ; 1000 1000 RIN A ; Read the first seed 0110 0000 TRA ; Transfer A to X 1000 0100 RIN B ; Read the second seed 0001 1100 STO C1 ; Save the last number 0100 1101 ADD 4 ; A + X Result in A 1110 0011 RUT 1s ; Result < 10 show in OUTPUT 0001 0010 STO C2 ; Remember result 1000 1100 RIN C1 ; Get last number 0110 0000 TRA ; Transfer A to X 1000 0010 RIN C2 ; Get current result back 1010 0001 SHL 1 ; Is the current result >= 8? 1001 0001 COJ 1 ; Result >= 8 1000 0010 RIN C2 ; Get current result back 0001 1100 STO C1 ; New last number 0101 1101 JMP 4 ; Go back to add 1101 0001 ENJ 1 ; Jump to location 1000 0010 RIN C2 ; Get current result back 0100 0000 ADD ; A + X Result in A 1110 1111 RUT BCD ; Convert binary to BCD put result in OUTPUT 0000 0111 NOP ANS ; Final result
The hardest part was keeping the program length down to 20 instructions, the current limit for my "low density" drum memory. I'll have to get going on the "high density" drum if I want to do more. I've "run" the program a few times and it seems to operate as expected. I guess my current thinking is to make a video of WDC-1 in action.
-
Finishing Touches
01/15/2020 at 19:38 • 0 commentsWith all of the major components complete it's time to put it all together. I attached a 3-wire power cable with a 3.5 mm stereo plugs to each of the peripheral modules.
For the Input and Output panels the extra power wire would allow me to selectively power the Encoder A, Encoder B, 10^1, and 10^0 elements independently should I choose.
After that there was nothing left to do but plug it all together and power it on.
Ready to go.
-
Control Panel Done
01/14/2020 at 20:47 • 0 commentsJust finished wiring and testing the Control Panel. The wiring got a bit hairy but it works well.
I used a 10 lead ribbon cable to connect the Drum Instruction Memory to the panel itself. Two leads were for power and the other 8 were for the op code and address control bits (4 for each). The drum base has lights marked Even and Odd hooked up to the two timing switches. These will alternate between instructions to give a visual indication that you have move to the next instruction correctly. You could also have both on to indicate the first line of the program and both off for the last line (say).
Lots of wire but the two 4 to 16 decoders basically just map the each op code and address to a single indicator light on the panel. There are 31 LEDs in total. I guess you could say this is WDC-1's instruction decoder.
The Control Panel is also where the power comes in and gets distributed to the other components of the machine. I'm using 3.5 mm stereo jacks and plugs so that the various pieces of the machine can be easily disconnected for close examination.
As I was setting up the power I also decided to make another small change from the book. The power "Junction Box" in the book was set up to power the components only when they were being used for part of an instruction. So for the command:
RIN Address A
for instance only the ALU and the Input Panel's Encoder A part of the machine would be enabled. This might provide a little extra clarity when executing instructions, but prevents a demonstrator from just showing what each part of the machine does in the absence of the proper commands. So I have decided to keep all of the modules powered all the time. I have not closed the door on the book's method, I can easily rewire for it, but for now I'm going with always on.
-
2BCD, Or Not 2BCD, That Is the Question
01/09/2020 at 15:23 • 0 commentsWhen I first started looking at the book "How to Build a Working Digital Computer" I noticed with interest that the Input Panel converted decimal numbers to Binary Coded Decimal (BCD) and the Output Panel in turn converted BCD results back to decimal numbers. In between the ALU is pure binary. This was new for me as all of my other projects were pretty much binary only. Cool. The encoders and decoders for these panels were pretty straight forward as they only had to deal with single digit decimal numbers and their BCD equivalents.
What I didn't give a lot of thought to was this, "How does a binary result that is greater than 9 get converted into the two BCD inputs that the Output Panel is expecting?". Well the answer is simple, run a program. Here is the "Readout Program" from the book.
Wait there's more...
So if I'm demonstrating WDC-1 and want to show something basic like adding 8 + 7 I would run a program something like this (assumes the two addends are in Address A and B):
RIN Address A ; Read first addend into A TRA ; Transfer A to X RIN Address B ; Read second addend into A ADD ; Add A and X. Result in A
With the result now in the accumulator at this point I say "Please bear with me as I perform 43 more complex and potentially error prone instructions so I can show you the answer.".
This felt like a gap to me so I started looking into binary to BCD conversion. How hard could it be? Well it turns out that while BIN2BCD conversion is not really that hard, it's not easy to do with a simple circuit. It requires computation, hence the 43 instruction "Readout Program". So I think I understand why the authors relegated their solution to the very back of the book.
I learned that there are a few ways to perform binary to BCD conversion. You can create a circuit to do this. Here is a design I found on Stack Exchange with thanks to jonk that employs the Double Dabble (love the name) algorithm:
This first schematic accepts a binary value and leaves it unchanged if the value is ≤ 4. Otherwise, it adds 3 to the binary input.
The second schematic uses the above circuit (named PLUS3 below), repeatedly:
Like I said, binary to BCD is not an easy get with logic circuits. I can't imagine how this could have been done with "household" items.
Another clever way to do a binary to BCD conversion is to use a binary up/down counter (SN74LS191 say) and a BCD counter (SN74LS192 say). The binary number is in parallel jammed into the up/down counter. Then the counter is clocked to count down to zero. The same clock is used to clock the BCD counter up from zero. When the binary counter reaches zero, the BCD counter will contain the binary number in BCD format.
A third option is to use a microprocessor. Now at this point I had already decided that I really needed (wanted) a BIN2BCD component to get me past the awkward 8 + 7 show the result issue. I was tempted by option number 2, the counters solution, which was more in line with my use of 7400 series ICs in other modules, but I literally had an Arduino Nano sitting on the desk in front of me. So microprocessor it is. Here is my BIN2BCD module:
The first thing you'll notice is that I chose different colors for this component. I wanted to make it clear that this module, with it's definitely not from the 60s microprocessor, was somehow "outside" of the Working Digital Computer book implementation. At a minimum the different color should initiate a discussion as to why.
I wrote a "brute force" but hopefully easy to understand sketch for the Arduino:
#include <avr/pgmspace.h> /** * Debug. Uncomment the following line for debugging. */ // #define DEBUG 1 // Only recalculate if different. int oldDecimal = -1; void setup() { // Initialize serial debugging. #ifdef DEBUG Serial.begin(115000); Serial.println("Setup Binary to BCD."); #endif // Setup A0-A5,11,12 to output the BCD. A0-A3 represent // the tens value and the rest the ones value. pinMode(A0, OUTPUT); pinMode(A1, OUTPUT); pinMode(A2, OUTPUT); pinMode(A3, OUTPUT); pinMode(A4, OUTPUT); pinMode(A5, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); // Clear the BCD display. clearBCD(); // Set D3-D10 to input the Binary were D3 = 1 and // D10 = 128. pinMode(3, INPUT_PULLUP); pinMode(4, INPUT_PULLUP); pinMode(5, INPUT_PULLUP); pinMode(6, INPUT_PULLUP); pinMode(7, INPUT_PULLUP); pinMode(8, INPUT_PULLUP); pinMode(9, INPUT_PULLUP); pinMode(10, INPUT_PULLUP); // Clear the inputs. digitalWrite(3, HIGH); digitalWrite(4, HIGH); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(8, HIGH); digitalWrite(9, HIGH); digitalWrite(10, HIGH); } void loop() { // Calculate the BCD values the delay a second. calculateBCD(); delay(1000); } /** * Nothing fancy here. Convert the binary inputs to a decimal * number. If the number is greater than 99 emit a zero as an * invalid indicator. Otherwise emit the tens and ones as BCD * values. */ void calculateBCD() { // Find the decimal number. int decimal = 0; if (digitalRead(3) == LOW) { decimal += 1; } if (digitalRead(4) == LOW) { decimal += 2; } if (digitalRead(5) == LOW) { decimal += 4; } if (digitalRead(6) == LOW) { decimal += 8; } if (digitalRead(7) == LOW) { decimal += 16; } if (digitalRead(8) == LOW) { decimal += 32; } if (digitalRead(9) == LOW) { decimal += 64; } if (digitalRead(10) == LOW) { decimal += 128; } #ifdef DEBUG Serial.print("Decimal = "); Serial.println(decimal); #endif // Only change if inputs have changed. if (decimal != oldDecimal) { oldDecimal = decimal; // Check for value out of bounds. if (decimal > 99) { decimal = 0; } // Clear the old values. clearBCD(); // Then output the new BCD values. int tens = decimal / 10; int ones = decimal % 10; #ifdef DEBUG Serial.print("Tens = "); Serial.println(tens); Serial.print("Ones = "); Serial.println(ones); #endif if ((tens & 1) > 0) { digitalWrite(A4, HIGH); } if ((tens & 2) > 0) { digitalWrite(A5, HIGH); } if ((tens & 4) > 0) { digitalWrite(11, HIGH); } if ((tens & 8) > 0) { digitalWrite(12, HIGH); } if ((ones & 1) > 0) { digitalWrite(A0, HIGH); } if ((ones & 2) > 0) { digitalWrite(A1, HIGH); } if ((ones & 4) > 0) { digitalWrite(A2, HIGH); } if ((ones & 8) > 0) { digitalWrite(A3, HIGH); } } } /** * Turn off all the BCD lights. */ void clearBCD() { digitalWrite(A0, LOW); digitalWrite(A1, LOW); digitalWrite(A2, LOW); digitalWrite(A3, LOW); digitalWrite(A4, LOW); digitalWrite(A5, LOW); digitalWrite(11, LOW); digitalWrite(12, LOW); }
That's it. I think I now appreciate why the authors did not tackle this as part of their build. For me though, 2BCD is the answer.
-
The Control Panel
01/08/2020 at 17:11 • 0 commentsFrom the Book
The unit "that unifies all of the computer elements" built so far is the Control Panel. It consists of two major parts, a display panel
to tell the operator (you) what program instructions to perform, and a drum memory
device to hold those instructions. The drum memory was by far the most complex of all the components described in the book. It was constructed from a tin can wrapped in paper with holes (much like their decimal to binary encoder), a frame, and many, many paper clips. Here is the construction diagram:
Despite the complexity of the drum memory, the Control Panel implementation in the book is very simple. The Working Digital Computer supports 10 different instructions and the 16 addresses that those instructions can act upon. Here they are:
There is a paperclip "contact" for each individual command and address, plus two contacts for "timing", and another to act as the common ground for all the other contacts. That makes 29 in total. Each command and address contact is connected to an appropriately labeled light on the display panel. The timing contacts drive two lights beside the rotating drum that alternate being on indicating even and odd instruction lines. Like I say pretty simple.
My Implementation
My first thought was that the 29 paperclip contacts seemed pretty extreme. I have a great deal of respect for gort59 for getting this to work in his wonderfully authentic Working Digital Computer build (as seen in the video in the Details section). I understand that he used the small springs from ball point pens which may have helped. Still kudos gort59!
I had also at this point decided to take advantage of my beefed up ALU and add 6 more op codes bringing the total up to 35. Thats a lot of switches leading to a lot of potential points of failure. Given that the total number of commands and addresses were both 16 or less, and that I already had a 4 to 16 decoder designed and working for the Output Panel, I decided to implement a 10 bit encoded instruction instead. This is what I came up with:
Each instruction would have 4 bits for the op code, 4 bits for the address, and I would keep the 2 timing bits as is.
The advantage of having a single bit for each command and address is that an instruction can have more than one "address" bit for each op code. For example the STO command would have an Address C bit to enable the Core Panel (essentially power the panel - this feels more like a control bit to me than an address) and a Core n bit to indicate which word to store the value of the accumulator in. With encoded addresses this is not possible, so some small tweaks to the implementation were required. For the above example I eliminated the Address C address altogether and will enable the Core Panel if any of the Core 1 to Core 5 addresses are used. Here are the other small changes:
- Display ACC removed. Like the Address C bit this would be added to any command that required the accumulator to enable the ALU. Since this is most commands I will simply leave the accumulator "on" all the time.
- JMP changed. The JUP op code used in the book just seemed very wrong to me.
- ENJ command added. The COJ and JMP instructions used the 1-4 addresses as a way to label the target instruction for the jump. They can still be used this way for instructions that do not take an address (like ADD for instance), but for instructions with an address (like STO for instance) an ENJ instruction with the target 1-4 can be added just prior.
- ORA command added. Boolean Or the A and X registers. Store result in A.
- XOR command added. Boolean Exclusive Or the A and X registers. Store result in A.
- AND command added. Boolean And the A and X registers. Store result in A.
- INV command added. Boolean Invert A register. Store result in A.
- NOP command added. No Operation. Do Nothing.
- BCD address added. I'll cover this off in a future log.
With the more compact instruction size I built my drum memory unit:
I guess the design should come as no surprise. It uses the same pegs and switches as the Input Panel and ALU encoders. The right 2 "rings" have alternating pegs to trigger the even/odd instruction lights. One command line is visible, a STO Core 2 instruction.
The one disadvantage of this design is that the peg size doesn't allow for very many instructions lines on this 80 mm diameter cylinder, only 20. The one from the book has 50 program instructions. I have another design in mind for a "high density" drum memory using magnets and reed switches (so predictable).
Finally here is the Control Panel with two 4 to 16 decoders ready to be wired and connected to the instruction memory drum.
The new BCD command has not been added yet either.