Calculating Engine Documentation

Introduction

Relay Machine ExteriorThis document describes a relay-based computing engine that is able to compute floating point square roots to eight digits of accuracy. It is inspired by the early relay computers of Konrad Zuse.

In building this machine I aimed to make the computation process as accessible as possible. It therefore runs quite slowly, is noisy, and has a light for every relay switch element so that the viewer really gets a feel for the thinking process that is happening before them. This is in contrast to modern computers where the actual function is very much hidden and happens at extraordinary speed.

The machine contains 480 relays. Each relay consists of a coil and four parallel changeover contacts. These are arranged so that 16 relays are on the board in each module. The machine has 10 rows of 3 modules. The front panel is semi-transparent so that LEDs connected to the coil of each relay are visible to the user.

Numbers are displayed on an eight digit display constructed using Nixie tubes which are neon-filled cold cathode tubes. These were common in the 1960s and give it a retro feel.

Numbers are entered using a phone dial and a button is present to allow a decimal point to be set. The system counts the pulses from the phone dial and shifts in the newly entered digit on the right as is usual for a calculator display. There is also a clear button to reset the display to zero and is also used to abort any operation.

When the desired number has been entered, the user presses a run button and the machine springs to life, calculating the square root. The display clears and the answer is scrolled in from the right as each new digit is determined. Each result takes around 30 seconds or less to produce. There is a speed control which can be used to slow the system down for easier viewing.

Motor and DisplayThe heartbeat of the machine is a clock generator utilizing a motor which rotates a cam, pressing on two switches in turn. This is visible on the front panel. This motor turns in order to step the machine through the internal states of its operation.

This machine took me 6 years to build, alternating between part time and full time work, depending on other demands. I originally thought of building a full calculator, but in the end decided that it was going to use too many relays and be too much work.

Method of Operation

Square RootComputation of square roots involves repeated shifting and subtracting of digits. The machine uses a binary coded decimal format and does its computation effectively in base 10. Each four bits stored in the internal registers can represent the numbers 0 through 9 and codes for a single digit. The bit combinations 1010 through 1111 are not used. This is done because of the relative difficulty of converting to and from base 10 if a fully binary floating point format were used. It also allows the result to be built up one digit at a time which is a natural-seeming behavior.

block_diagramThe block diagram shows the parts of the machine. There are two main registers: An 8 digit register that holds the information that appears on the display – this includes the number entered by the user and also the final answer which is built up one digit at a time.

The display register binary coded decimal digits are decoded to drive the display tubes. A leading zero suppression process which also takes into account the decimal point position ensures that extra zeros do not appear to the left of the number on the display. The decimal point register keeps track of the decimal point position at all times and increments if there is a decimal point set during user input when new numbers are dialed in.

During the process of data entry, the machine is configured so that the dial pulses from the phone dial increment the count register and when the phone dial comes back to rest, a signal shifts the new number from the count register into the display register so all the digits move along one place. This process is also used during the building up of the answer when the data entry dial is disabled.

The main accumulator register is a 17 digit shift register which can load in a variety of ways. It can load data from the answer entry register via a multiply by 5 unit and a single optional digit shift. It can load data from itself so as to carry out a shifting operation where the register contents get shifted two digits to the left. It can also load the output of the subtractor into the most significant 10 digits.

The subtractor gets one input from the shift register most significant digits and one from the answer entry register. This second input undergoes 9s complement so as to implement subtraction as opposed to addition. The number that is subtracted is the concatenation AE.C.5, where AE means the 8 digits from the answer entry register, and C represents the one digit from the count register and 5 is the constant 5.

The subtractor used is actually a binary adder which was designed by Konrad Zuse. However since we use binary coded decimal, the output of each digit for the adder goes into a decimal adjust unit which converts the partial sums back to binary coded decimal and handles the inter-digit carry operation.

The state machine is a sequencer which steps through the various load, shift, increment, and subtract operations. It has 11 states and various branches within this program are taken depending on the ongoing calculation.

While running, the system uses a two phase clock which is derived from two microswitches which follow a motor driven cam on the front panel. The speed of rotation of the motor dictates the speed of operation of the machine and this can be adjusted on the front panel.

The two phases are used because the accumulator store consists of two parallel banks of memory elements. The input latches are loaded first with results from the previous calculation, and then on the next phase of the clock, the output latches are loaded from the input latches. This avoids data racing since these latches are not edge triggered.

The latches that are used in the counters, state machine, and in the answer entry register are all edge triggered D-type flip flops, each implemented with three relays. However for the accumulator, dual transparent latches were used because this is more economical with relays.

The general steps of the operation are as follows:

  1. The user enters a number optionally with a decimal point. The machine keeps track of the decimal point position.
  2. The number is multiplied by five and loaded into the accumulator.
  3. The number is shifted to the left until a required alignment criterion is met so as to create a normalized representation. An exponent register keeps track of the number of shifts required.
  4. The count and answer and entry register are cleared and the correct DP position selected.
  5. The concatenation AE.C.5 is formed from the answer entry register and the count register and is compared to the digits of the most significant part of the accumulator.
  6. If the accumulator is larger then the AE.C.5 number is subtracted from the accumulator and the result loaded back in. Also the count register is incremented.
  7. This operation repeats from step 5 until the comparison fails.
  8. Whenever the next subtraction would take the result negative, the value of the count register is shifted into the result and the accumulator is left shifted by two digits.
  9. If the stopping criteria are not met, then the count register is cleared and this process repeats from step 5.
  10. The machine signals that it has completed the operation.

If you mechanically step through these operations you will find that the square root operation is generated. The algorithm is adapted from W. E. Egbert, “Personal Calculator Algorithms I: Square Roots,” Hewlett-Packard Journal, vol. 28, no. 9, May 1977.

State Machine

state_diagramThe state machine is a four bit register which implements the program operations as described above. As can be seen on the state diagram, there are 11 states. The clock for the state machine comes from one of the microswitches on the rotating cam that generates the operational clock pulses.

State S0 is the reset idle state. Normally the motor is stopped in this state and the control of the AE register is handed over to the user. Pressing the run button starts the motor going and the state machine is enabled to transition from S0 into S1. When the program completes the machine enters S0 again and this cuts off the motor at the correct point in the cycle.

State S1 is the first active state and it transfers the information from the AE register into the AC register via the multiply by 5 unit and single digit shifter. The entire AC register is loaded and the upper digits not coming from the AE register are zeroed. The single digit shift is set up so that it will load a left shifted version of the AE register if the decimal point position is even. This is done because the AC unit is only able to shift two places at a time and for normalization an odd number of digit shifts may be needed. The least significant digit of the AC register can only represent 0 or 5 (using 1 bit) because the AE register is multiplied by 5. Also in state S1, the EXP register is loaded from the DP register. The EXP register is used to store the current exponent of the answer as a power of 10. Both the DP register and the EXP register store 3 bits but their relationship is complex. The EXP register loads a bit inverted version of DP bit 2 and DP bit 1 into EXP bit 1 and EXP bit 0. EXP bit 2 is set to zero.

States S2 through S5 carry out the alignment normalization phase. This process ensures that AC digits AC7, AC8, and AC9 always contain a value between 5 and 495. At each state, these digits of AC are tested and if the values are correct, the machine moves to state S6. Otherwise it repeatedly shifts the AC register two digits to the left and decrements the EXP register. Up to four shift / decrement operations are allowed which is sufficient to cover all the combinations of decimal point positions and non zero numbers in an 8 digit system. The virtual decimal point position of the AC register is between digits 6 and 7. (Digits of the AC register index from AC0, the least significant digit which can only hold the values 0 or 5, and AC16. All these digit stores use binary coded decimal.)

After alignment, S6 is used to clear the AE register and set the decimal point position to zero by clearing the DP register. At this point, if the AC register holds a zero value, the program terminates early by branching to state S10.

In state S7, the DP register is loaded using a decoded version of the EXP register contents in order to set up the initial position of the decimal point, e.g. if the number starts at a fractional value, such as for an answer like 0.001. The operation of the decimal point unit is fairly involved. There is a latch which gets set only if the decimal point is going to shift with left shifts of the AE register. When this is clear, numbers can shift into the AE register without moving the decimal point from the digit zero position. As soon as the latch is set the decimal point starts to move. The system sets this latch at any time that the EXP register goes negative and when this happens, subsequent digits generated in the answer will follow after the decimal point. This can happen at any time in states S7 or S9. Also in state S7 the count (C) register is cleared in preparation for the main loop.

The main calculation loop consists of state S8 and S9. S8 carries out subtractions and S9 shifts digits into the AE register. In state S8 the current contents AE7 through AE0, the C register and the constant 5 are subtracted from the AC register digits AC16 through AC7 respectively as a single sum. The subtraction generates a carry when the result would be positive. If the result is positive, the subtraction result is loaded back into the AC register digits AC16 through AC7, the C register is incremented, and the state continues in S8. If the AE register is zero then this subtracts 05, 15, 25, 35, etc, in sequence from the AC register. Eventually when the C register gets to 9, the result of the subtraction must go negative, so the state will always move to S9. The value in the C register when this happens is the next digit of the answer.

In state S9 the resulting C register value is left shifted into AE and the decimal point position may move. The EXP register is also decremented and if it goes negative, this will set the DP latch for the next cycle. The increment of the DP position only happens when the DP latch is set. In addition AC is left shifted by two digits and the C register is cleared for the next cycle of subtractions. At this point the state machine will go one of three ways: If the subtraction result is negative then it will remain in S9, if positive it will go back to S8 to continue subtractions, and if the termination condition is true it will enter S10 (this takes priority). The run terminates when the AE register is full (either the most significant digit is non-zero, or the decimal point is at position AE7), or if the AC register is zero and the EXP register is negative. This last condition ensures that additional zeroes are generated for results such as 100 where the AC register may be zero before the final answer is reached.

The last state S10 clears anything remaining in the AC register (to reduce power draw) and sets a latch indicating that the end has been reached. This is used to trigger the bell and turn on the completion light on the user interface. The machine then transitions into state S0 in order to stop the motor.

Slide5The primary limitation on the speed of the machine is the ripple carry used during subtraction. Each digit has a fast carry internally, but the requirement to have a decimal adjust unit makes it hard to avoid ripple carries from digit to digit. The state machine transitions must test to see if the carry out of the subtraction is one or zero and this takes time to generate after the load-2 phase of the AC register which occurs mid cycle.

Module Construction

IMG_9826The machine is built using 30 modules each containing 16 relays. All the relays are 12V 4 pole changeover type NF4EB-12V (Aromat). They close at around 9.6V and have a 330ohm coil resistance, with 30VDC 2A contacts. Each relay has an associated LED in series with a 365 ohm resistor. In addition a 1N4148 diode is placed across each LED with the anode to ground. This configuration acts to limit the reverse voltage across the relay coil when it de-energizes. It also prevents large reverse voltages across the LEDs.

The relay life is expected to be larger than one million operations. The circuitry was designed to avoid overloading the contacts on any one relay and also designed to prevent inductive spikes causing switching discharges or significant radio interference.

Square Root Machine InternalsThe printed circuit boards holding the relays are all identical and were designed as a form of prototyping board that distributes power and ground and provides pads onto which wires can be soldered. All the units were therefore hand soldered and most of them are different.

Each module has a dual set of screw terminals and these break out the inputs and outputs from the associated circuit board. The unit is tied together by steel end cheek brackets which were custom manufactured.

The terminal board integrates a decoupling capacitor and four status LEDs. These indicate functionally relevant information based on outputs from the module. Most of them indicate the binary code for numbers stored in the associated registers so it is easy to read the register contents by looking at the back of the machine and this aids in debugging.

Layout of Modules in the Case

Layout of Modules in the Case

Definition of Logic Signals

In this project I use four different types of names for logic signals which make their function clear. Let us suppose that we have a signal called RUN. This can then have one of the following forms:

  • RUN- The signal is active when connected to ground, otherwise it is inactive.
  • RUN_N- The signal is inactive when connected to ground, otherwise it is active.
  • RUN+ The signal is active when connected to the positive supply, otherwise it is inactive.
  • RUN_N+ The signal is inactive when connected to the positive supply, otherwise it is active.

For example RES_N+ is a common signal which resets a counter when it is disconnected from the positive supply. In this project the majority of the signals are active when connected to ground, like the RUN- signal, so typically relay coils will connect to the positive supply and contacts will connect to ground.

DFLIP Sub Unit

 dflipOne of the innovations that made this relay machine possible was the development of an edge triggered D-type flip flop. I think this is possibly a unique circuit invention. The challenge with relays vs digital logic is that it is hard to overcome the intermediate state as a relay switches from the normally closed contacts over to the normally open ones. During this state, nothing is connected, and so it is quite difficult to build anything that is like synchronous logic. However I managed to invent a positive edge triggered D-type flip flop using three relays which forms the basis for a number of the registers and counters in this machine. (An equivalent negative edge triggered design is possible.)

Looking at the schematic one can see that there are two input relays (S and R) and one output (Q) relay. The S input relay is for setting the Q relay and the R input relay for resetting it. Under normal operation the RES_N+ line is connected to the positive supply. If the Q relay is turned on, it will be held on by its own normally closed contact via the diode and resistor to positive. Alternatively it may be turned off. These are the two stable states. The S and R relays act to change the state and these two relays can only turn on when the clock line CK+ is active. The D input of the flip flop comes from the D- and D_N- inputs, and these must always be a complementary pair. When the clock line goes active, one of the D inputs must be grounded for correct operation.

If the D- input is active when CK+ gets activated, the S relay turns on. In doing so, it disconnects the D_N- input from the R relay, and this prevents later changes from influencing the circuit when the clock pulse is active. As soon as the S relay turns on, it holds itself on via a diode and this prevents any loss of the D- input activation from causing this relay to drop out. Simultaneously, the same circuit via another diode acts to connect the Q relay coil to ground which energizes Q via the resistor. Once Q is energized it holds itself on after the clock pulse is over.

The system is symmetric and so the same argument goes for the R relay, which disconnects the D- input when it gets energized. The R relay locks itself on for the duration of the clock pulse and also shorts to ground the positive end of the relay coil which turns it off if the coil had been energized.

The outcome of these operations is that once either the S or R relays have been energized at the CK+ rising edge, no further change to the D- or D_N- inputs can influence the flip flop. This ability to ignore further changes at the input allows one to construct synchronous counters with this circuit. You will find that this block is used in numerous places in the design of the machine and is given its own circuit symbol.

Module CREG

Board number B1.

b1_cregThe C register is the count register that follows the dial pulses during data entry and also gets used by the state machine to store the next digit that is being tested when generating the answer. It is a four bit binary up counter. It is designed to count up to 9 and then reset again to zero, as more clock pulses arrive. The phone dial will generate 10 pulses when a zero value is selected by the user.

The counter uses four of the D-type flip flops described above. The challenge is to create a decade counter using only the available relay contacts. In addition, this counter must generate two special signals called SUB123- and SUB1X2- which are used by the subtractor unit.

First we shall see how a binary counter is implemented, and then we shall see how to make it a decade counter. On the schematic, the least significant bit is stored by the flip flop on the left. Its D- input is connected to its Q_N- output and its D_N- input is connected to its Q- output. This means that the bit will always flip when there is a clock pulse. The second bit of the counter using the flip flop to the right is a little different. The second and third set of contacts (W2 and W3) are called the flip and no-flip contacts respectively. They are set up so that when the wiper W2 of the flip contacts is grounded, then this relay will change state, whereas if the wiper W3 of the no-flip contacts is grounded, then the flip-flop will not change state. This is implemented by the diode arrangement from the NO and NC contacts to the flip-flop inputs D- and D_N-. These diodes correctly set the flip-flip inputs so that the bit flips or does not flip depending on whether W2 or W3 is grounded at the next clock edge.

For the next bit which uses the next flip-flop to the right, the configuration is similar. Its W2 and W3 inputs are also its flip and no-flip connections. However the flip input at W2 is connected to the NO2 terminal of the previous stage. This means the flip is only active if the previous bit is a 1. This is the carry operation between stages in a binary counter. However we also have to generate correctly the complementary no-flip input at W3. This comes from a logical OR using two diodes of the NC contacts from bit 0 and bit 1, meaning that the bit 2 relay will not flip if there is a 0 in any lower order bit. It is always necessary to generate these complementary signals because of the need to have two complementary D inputs to the flip-flop circuit.

The final stage bit 3 also has a similar flip or no-flip logic, with the no-flip input at its W3 coming from a running diode OR of all the previous no flip inputs and the NC contacts of the flip circuits. In effect for the flip input we are ANDing together all the previous bits, and for the no-flip inputs we are making an OR of all the inverted bits.

The decade functionality is implemented by forcing the counter to reset on the clock pulse after a 9 is detected. This EQUAL9- signal is generated at the NO3 contact of the bit 0 flip-flop and results from ANDing together bit 0 and bit 3 of the counter. When the line is driven, it activates the D_N- inputs of bits 1-3 and de-activates their D- inputs by disabling the normal flipping operation using the two diodes and contacts at W2 of bit 0.

In fact the output EQUAL9- is a legacy output and is not used in the machine.

The SUB123- and SUB1X2- outputs are signals that represent the 9s complement of the C register digit. SUB123- ANDs together bits 1, 2, and 3, whereas SUB1X2- EXORs together bit 1 and bit 2. The 9s complement number is made up of Q0_N-, Q1-, SUB1X2-, and SUB123-, representing bit 0, 1, 2, and 3, respectively. This is fed into the subtractor circuit, which is really actually an adder with an additional carry input.

Three relays on the board are used to condition the dial input. The dial generates break signals at DIALPULSE_N- and these are inverted to create DIALPULSE+. The other dial input DIAL- is grounded when the dial is in motion away from its rest position. When the user interface is enabled, this is used to un-reset the C register counter, otherwise it is held reset. However when the dial returns to rest, it is necessary to have a brief interval where the count in the C register is loaded into the AE register. This is done by making a relay monostable that generates a short pulse at the end of the dial return time. This pulse is DIALSHIFTCK- and the C register reset signal is DIALRES_N+.

In addition there is a GOEN- signal which is used to disable the run button when the dial is in motion so that the state of running and the state of dialing are properly separated.

The last relay on the board is a buffer for the AE shift signal. When SHIN- is grounded, a positive going clock activation is generated at SHOUT+ which goes to all the clock inputs of the AE shift register digits.

Module AEREGLSB

Board number B2.

b2_aereglsblayout_aereg_c layout_aereg_b layout_aereg_aBoards B2 through B9 comprise the 8 digit AE shift register. This holds the number that is shown on the display. Each digit has a 4-bit memory made up of four d-type flip-flop circuits. Resetting these sets the display to zero and clocking them moves the digits on by one place and clocks in the contents of the C register as the least significant digit. All the modules are very similar. There are minor differences for the least and most significant digits.

The output of the AE register is multiplied by 5 and goes to the AC register via the shift unit. The other output of the AE register goes to the subtractor units and for this a 9s complement representation is formed, like the one for the C register. As a consequence, the AE units all generate both a 9s complement and a multiplied by 5 representation.

The four bits of the register receive D- and D_N- complementary inputs from either the C register for AEREGLSB or from the previous AE register digit. The outputs are Q- and Q_N-. The relay contacts on each bit are used to create the SUB1X2- and SUB123- signals that make up bit 2 and bit 3 of the subtractor 9s complement representation as described in the C register section. The multiply by 5 operation is done by a single relay on each unit. This has an input AEX5IN- that comes from Q0- of the next digit to the left. It controls whether the output on AEX5-[0..3] ranges from 0 through 4 in the case that the Q0- is inactive, or ranges from 5 through 9 in the case that Q0- is active on the next digit. The Q0- on the least significant digit of the AE register dictates whether the least significant digit of the multiply by 5 output is 0 or 5, and this can either go to digit AC0 of the accumulator, or to digit AC1 depending on the shift unit status. Diodes on the multiply by 5 unit are used for isolating the AE register from the AC register.

The ten decimal combinations of the AE digit bits are decoded to drive the nixie tube cathodes. This just uses a tree of relay contacts together with an additional relay which is controlled by bit 0. In the special case of all bits being zero, indicating a zero on the display, a zero relay is activated. On later units this is used to control ripple blanking for leading zero suppression, and it also generates outputs ZERO- and ZERO_N-, as well as generating a signal ALLZEROOUT- which was designed to indicate that the AE register was equal to zero. However these zero control lines are not actually used because the design was changed. The only place that they are used is for digit 7 of the display, where it is necessary to sense whether the display has become full to stop the machine from generating more digits, or to prevent the user from entering too many non-zero digits.

On the AEREGLSB module, the is also a reset buffer relay which has an input called RES- and generates the RES_N+ signal that is used by the entire AE register.

Module AEREG

Board numbers B3, B4, B5, B6, B7, B8.

b3_b4_b5_b6_b7_b8_aeregThis is the main circuit circuit for most of the digits of the AE register. The functionality is pretty much identical to the description above. The only difference being the addition of the leading zero suppression circuitry. The idea here is that you must suppress the display of any zeros unless there is a non-zero value in any digit to the left, or else the decimal point is set on the current digit or on any to the left. Each digit generates a RNZOUT- signal that indicates that either this current digit is zero or else this digit has a decimal point or else any digit to the left has a RNZOUT- activated. The RNZIN- input conveys this information along with the DP- decimal point activation for the current unit. The current NIXIE0- line is only enabled if either RNZIN- in active or DP- is active. These RNZ lines are daisy chained through the AE register digits. The LSB is always enabled to show a zero.

Module AEREGMSB

Board number B9.

b9_aeregmsbThis module is identical to the AEREG except that it has no RNZIN- input since there are no digits to its left.

It also contains a relay that inverts the UIDIS- line to generate UIDIS_N-, a signal which is used to enable the dial and decimal point button on the user interface at various times.

Module ACREGSUBAE

Board numbers B10, B11, B12, B13, B14, B15, B16.

b10_b11_b12_b13_b14_b15_b16_acregsubaelayout_acregsubaeThis module is used in the most significant 7 digits of the AC accumulator register. It features a 4 bit register consisting of dual transparent latches and a four bit binary subtractor.

The design for the AC register is different than for the AE register. Since the AC register has 17 digits and is solely under control of the state machine, it uses transparent latches instead of edge triggered flip-flops as a storage method. This is done in order to cut down the number of relays and to avoid the need for generating complementary signals for D inputs. The main trade-off is that the system needs a carefully-timed two phase clock. In fact clocking the input to the output of this register requires four sequential steps.

Each digit of the AC register typically can be loaded from up to three sources, but not all digits have them all. The A source is for shifting the AC register left by two digit positions. The A inputs come from the outputs of the digit two places to the right of the current digit. The B source is for loading the result of subtractions and comes from the current digit’s outputs once they have been conditioned by the decimal adjust units. The C input comes from the input shifter unit that takes its input from the multiply by 5 outputs of the AE register and is for initializing the AC register at the start of computation. In addition, if none of the three inputs are selected during a load operation, the AC register digit loads a zero.

The structure of an AC register digit consists of one or more load-1 relays, a set of four input storage relays, a load-2 relay and a set of four output storage relays. The input storage and output storage relays are each controlled by their hold lines which are grounded when the bank of relays is supposed to store information, and are disconnected when they the banks is supposed to clear and be driven by input signals. The clock cycle is controlled therefore by the signals LOAD1-, HOLD1-, LOAD2-, and HOLD2-. Normally both hold lines are activated. However during a load from an external source, firstly the HOLD1- line is disconnected, causing the input relays to drop out, then the LOAD1- line is activated causing the input source bit pattern to be connected to the four input relays. This loads the bit pattern into those relay latches, so that next when the HOLD1- line is activated, and subsequently the LOAD1- line is deactivated, they continue to store the bit pattern. The same cycle is used to transfer this bit pattern into the four output relays by first deactivating the HOLD2- line, then activating the LOAD2- line, transferring the data, then activating the HOLD2- line and deactivating the LOAD2- line. Thus the data first moves from the source to the input relays, and then from the input relays to the output relays. The two phase operation is necessary because a race condition would ensue if there were only one bank of relays and inputs were fed directly from outputs.

The load and hold sequencing is fairly complicated. In order to make this work, auxiliary load relays are present on many of these boards and generate either the LOAD1- / HOLD1- pair or the LOAD2- / HOLD2- pair for up to four boards. These relays are driven from the LD- input and have capacitors on the LOADX- contacts which serve to slightly delay the dropping out of the load relay until the hold line has been activated during the transition from loading to holding.

The sequencing of the numerical computation makes use of a two phase clock, and in the first phase, the LD- input for load-1 relays is activated, and during the second phase the LD- input for load-2 relays is activated.

The load-1 relays on each digit are also gated by the signals LEA+, LEB+ and LEC+ on the positive side. These control the source for the information that will load during the load-1 cycle.

The load-1 and load-2 signals are segregated into two parts, one controlling the most significant digits (MSB) of the AC register: AC-7 through AC-16, and the other controlling AC-0 through AC-6 (LSB). This is done because the computation with subtractions only affects the most significant 10 digits. Therefore the state machine controls for any step of the program, the signals load-1 MSB, load-2 MSB, load-1 LSB, load-2 LSB, LEA+, LEB+ and LEC+.

The LEA+, LEB+ and LEC+ signals are common for the whole of AC, but include diodes (outside the modules) to prevent interference between units via the load lines.

An output ALLZERO_N- is generated from the Q-[0..3] of the digit which is used to generate a signal to indicate that the whole AC register is non-zero. In addition these lines are used during the initial alignment of the number to be analyzed within the AC register.

The subtractor makes use of an additional four relays which interact with the output storage relays. These get their inputs from the 9s complement outputs from the AE register or C register. They implement actually a binary adder with a fast carry. This design was created by Konrad Zuse and I used it pretty much un-modified. It requires a complementary carry in signal CIN- and CIN_N-. It generates a single binary carry out BINCOUT-. To implement subtraction, the carry input is set when there is no borrow from the previous digit.

Because this subtractor is a binary system, and the machine uses binary coded decimal, the output signals BINS-[0..3] can go outside the range 0000 to 1001 of the BCD system. This means that they must be sent to the decimal adjust unit in order to be converted back to binary coded decimal and a corrected BCD carry complementary pair generated for feeding into the next digit.

There is a minor bug in the design here, in that the binary outputs of the subtractor are not valid when the HOLD2- line is disconnected. This means that not much time is available for the subtractor outputs to stabilize at the output of the decimal adjust units after the HOLD2- line eventually gets activated. The end result is that the machine runs a bit slower than I had in mind.

Module ACREGXSUBAE

Board numbers B17, B25.

b17_b25_acregxsubaelayout_acregxsubaeThis module is a slight variation on the ACREGSUBAE module where the load/hold auxiliary relay has been replaced by a load-1 relay that loads from the C input source via the DC-[0..3] lines.

Module ACREGXSUB5

Board number B18.

b18_acregxsub5layout_acregxsub5This module is an AC register digit module like the ACREGSUBAE module except that rather than subtracting a digit that comes from the AE register, it subtracts the constant 5. Because this operation is less complex, it does not need to use an external decimal adjust unit to maintain the binary coded decimal representation. In addition, this register is actually the least significant digit of the ones the use subtraction and so it needs no carry in signal and it directly computes the complementary carry out signal that goes to the next digit’s subtractor.

The input has three sources – the A input comes from the digit which is two to the right of the current one, to implement the left shift operation of the accumulator, the B input comes directly from the output of the subtract 5 logic, and the C input comes from the AE register via the multiply by 5 system and shift unit.

This unit also contains an auxiliary load / hold relay which is used to drive four digit modules.

Computing the subtract 5 result and its associated carries requires an additional three relays along with the four relays of the output digit store.

Module DECIMALADJ

Board numbers B19, B20.

b19_b20_decimaladjlayout_decimaladjEach decimal adjust unit contains four copies of the same decimal adjust circuit. This conditions the three most significant bits plus the carry of the subtractor output to reflect the binary coded decimal representation. It just implements a logical truth table that maps subtractor outputs in the range 0101X through 1001X (10 to 19 binary) into the range 1000X through 1100X (10 to 19 BCD).

The SUB outputs of each decimal adjuster are fed back into the B inputs of the same digit. The carry outputs of each adjuster go to the carry inputs of the next digit. Since this introduces a per-digit ripple carry through one relay, there is a latency for generating the final carry output for the whole register. This is the primary factor that controls how fast the machine can operate because the carry output is used to control program branching and must be valid in time for the next state machine transition.

Module ACREGDAJ

Board number B21.

b21_acregdajlayout_acregdajThis module is used for digit AC-6 of the accumulator. The description is similar to ACREGSUBAE except there is no subtractor, as is the case for digits AC-0 through AC-6. The extra relays are used to implement a copy of the decimal adjust unit, described above, which is used along with digit AC-8 (which is the unit that does the subtraction of the C-register.)

Module ACREGLSB

Board number B22.

b22_acreglsblayout_acreglsbThis module implements both AC-3 and AC-0 for the accumulator. Its AC-3 load inputs can come from the A source (accumulator shifting) or C source (from the AE register via multiply buy 5 and the shift unit).

Its AC-0 load input can only come from the C source. The AC-0 digit only uses a 1 bit store because the only values that it can hold are 0 and 5, due to the AE register being multiplied by 5 before loading into the accumulator. A logic one in this bit represents a 5. Other than it using only one bit, its load and hold control is the same as for the rest of the accumulator.

Module ACREGSHIFTHI

Board number B23.

b23_acregshifthilayout_acregshifthiThis module implements accumulator digit AC-5, but it also implements half of the shift unit that connects the accumulator with the AE register. The sources for this AC digit can be the A source, coming from the digit two places to the right, or the C source which comes from the shifter.

The shifter is a bank of relays which all change over together. These are integrated with digits AC-5 and AC-4 (described below). This shifting operation is based on the least significant bit of the decimal point position at the start of the compute cycle. The reason that this shift is needed is because the AC register can only left shift by 2 digits at a time. This shifter provides a single digit place shift of the source input and allows any possible alignment of the AE register input that may be needed for the initial normalization alignment of the digits in the AC register prior to the main compute cycle. The AE register after the multiply by 5 operation is left shifted using this shifter if the decimal point position is even. This places the data in the correct location of the AC register and allows the exponent register to correctly represent the exponent of the result. Outputs from the shifter go to AC register digits AC-0 through AC-9, but the five relays on this unit only handle half of the connections.

The rest of the digit operation is the same as previously described.

Module ACREGSHIFTLO

Board number B24.

b24_acregshiftlolayout_acregshiftloThis module implements accumulator digit AC-4 and also half of the shifter unit as described above. Its outputs drive the C inputs for digits AC-0 through AC-3.

The AE register source DX5LSB- comes from the Q0- output of the AE-0. It is interpreted as a 5 when it is active. If there is no shift then it passes through to the one bit wide store of AC-0, otherwise it gets converted into a 5 (0101) pattern and is presented to AC-1.

Module ACREG2

Board number B26.

b26_acreg2layout_acreg2Quite a lot of complexity is distributed between boards B26 through B30 because each of them has a part of the control circuitry and state machine function.

The module implements accumulator digit store AC-2 and also implements the program flow control for the state machine sequencer. The accumulator digit circuit is unremarkable and is identical in function to those described above.

The state machine is set up in such a way that it has a set of outputs S0- through S11- which are the fully decoded state activation lines, so that if the state machine is in state S5 then the S5- line will be active. It also has a set of inputs U0- through U11- which are intended to be driven to indicate what the next state will be. Only one of these lines should be driven at one time. For any time step, it is necessary to determine which of the U lines should be driven given the current state activation and the current conditions of the mathematical operations. Therefore the branching unit takes the S lines and a few other logical inputs and generates the correct U line activations to move to the next state. The state machine diagram is shown in the introduction.

Here the only state transitions that are of concern are the ones where two or more different next states are possible. States where there is no choice to the next transition are hard wired on the exterior of the state machine module.

The relay on the right controls whether states S1, S2, S3, or S4 are going to transition into states S2, S3, S4, S5 or if instead they are going to directly branch to S6. This is used for the shifting normalization process. The branching to S6 occurs if the number that has shifted into the accumulator is correctly positioned in the register. Correct positioning is detected by examining the contents of digit stores AC-7 through AC-9. These digit stores should hold a value in the range 5 through 495. This is detected as AC-9 is non-zero or AC-8 is non-zero or AC-7 is greater than or equal to 5. The left hand relay on the schematic for this module implements the latter part of this OR term.

Branching between states S7, S8, S9, and S10 is implemented by the rest of the circuitry. The SUBPOS- input is used to detect that the subtraction yielded a positive result, based on the carry output of the last subtractor decimal adjust unit. If the subtraction was positive, the system stays in state S8.

The end state transition to S10 is detected when the AC register is zero or else all the digits of the AE register have been filled. Actually, as mentioned in the introduction, bit 2 of the EXP register is used to indicate that it is ok to end the program when AC is zero. This allows additional zeroes to be loaded into the AE register when the result would be something like 100 where the AC register is zero for a while, but EXP is still positive.

The center relay is active when AE is full, and the second from the left is active when AC is zero. The fourth from the left is active when the subtraction is positive. State S6 can transition into state S7 or S10, state S9 can transition into state S8, S9, or S10, and state S8 can transition into state S8, or S9. This module implements those transitions.

Module ACREG1

Board number B27.

b27_acreg1layout_acreg1This module features the digit store for accumulator AC-1. The operation is the same as previously described digit stores. However the only input is the C input from the shift unit because there is no shift input from any prior accumulator digit. This unit loads zero if an accumulator shift takes place.

This module also includes circuitry to generate control signals from the state machine state outputs. Also it contains circuitry to switch between control coming from the user interface, and control coming from the state machine.

The state decoder uses four relays to generate signals that enable the load-1 accumulator source selectors LEA+, LEB+, and LEC+. Also it generates S8+ from S8- and EXPCKEN-. This latter signal is used to enable the clocking of the EXP register which is needed during EXP load and EXP decrement operations that are not associated with AE shifting. The EXP clock is further conditioned by another relay outside this module so that the EXP clock occurs on the B half cycle (which is actually at the beginning of the two phase cycle) so that it does not get affected by state machine settling race conditions.

LEC+ is only active in state S1 when the AE data is loaded into AC. LEB+ is active in state S8 when the subtraction results are loaded back into the accumulator. LEA+ is active for all accumulator shifts for normalization, S2, S3, S4, S5, and during digit generation in S9.

The RUN- input activates a relay on this board to switch over the source of a number of signals that are shared between the state machine and the user interface. These outputs are the UICOM- line which is used to enable the dial and decimal point button, the AESHIFT- line which causes the AE register to shift by one digit and load in the C register value, the CREGCK+ line which is for incrementing the C register contents, and the CREGRES_N+ line which is for resetting the C register back to zero. When the system is not calculating, these are connected to circuitry on the C register board which generates the timing signals from the telephone dial motion. Also in this state, the UIDIS_N- line controls the UICOM- output. This input is disabled when an answer is present on the display after a calculation and the answer light is illuminated. It stops the user from entering digits until they have pressed the cancel button.

When the machine is running, the run relay connects the AE register and C register to signals that are generated from the state machine so that it can control shifting and counting in this system.

Module DPREG

Board number B28.

b28_dpreglayout_dpregThe decimal point store is a three bit edge triggered up counter which counts from 0 to 7, after which it stays at 7. It also has a facility for synchronous parallel load – this load information coming from the EXP register. A group of relays also decodes the three bit code to drive the eight decimal point cathodes of the Nixie tubes.

The counter uses the same d-type flip flop circuit as in other places. It implements a counter using the flip / no-flip method as was described for the C register, using contacts W2 and W3 on the Q relays. Counting can be disabled by the relay on the lower right of the schematic which drives the flip and no-flip lines of bit 0 of the counter. When this relay is pulled in, the counter will stay at the same value irrespective of any clock pulses.

Two relays control the loading of the DP register from the EXP register. When the LOAD- line is inactive, the D inputs of the flip-flops are connected to the counting circuitry. When this line is activated, these inputs are connect to the parallel load data lines. However only bits 0 and 1 are loaded, with bit 2 always being loaded with 0. The DP register is loaded in state S7 prior to the main computation loop. The value that is loaded depends on the normalization stage that happens in states S1 through S5 when the EXP register is decremented on each normalization shift. In fact the DP register is loaded with zero if the EXP register is positive, meaning that the expected answer exponent is greater than or equal to zero. If it is negative, then the DP register loads the inverted two lower bits of the EXP value, causing the initial DP position to be further to the left the more negative the value of the exponent.

The DP register counting operation is disabled when either the count has reached 7 or else the DP latch is not set. This DP latch controls when the decimal point will move left during shifts of the AE register. The DP latch relay is the one on the lower left that gets its input from the DPLATCH- line. Once this relay pulls in, it will stay set until the DP register gets cleared. At the beginning of operations (user pressed clear, or run state S6) the DP latch is cleared. Later it may become set by grounding the DPLATCH- line. This happens during data entry when the user presses the decimal point button. It also may happen during computation when the EXP register goes negative, indicating that a decimal point needs to be shifted in on the next AE shift cycle.

This module also contains the answer latch relay. This latch is set when the state machine generates the SMEND- signal. This causes the ANSWER- line to be active and held that way until the DP register is reset by the user pressing the cancel button. This ANSWER- line lights up the answer light on the front panel to indicate an answer is present. It also drives the UIDIS- line to disable the user interface to prevent entry of digits when the answer is present (until the user presses cancel).

The UIDIS- signal is inverted on the AEREGMSB module to create the enable signal for the ground side of the dial and decimal point button. UIDIS- also gets input from the DP7- line and from the AE7ZERO- line that comes from AE-7. These signals are diode ORed with the ANSWER- signal and act to prevent data entry when there is an answer present, or the display has been filled with digits.

The decimal point unit is normally clocked when the AE shift happens via a diode to the clock line from the AE shift clock. However it is also clocked when a DP load happens via a second diode. On state S7, the LOAD- input is activated. The closing of the DP load relay on the DP register unit activates the DPCKEN+ output. This goes to B29 to be conditioned on the B phase of the cycle and this SM_DPCK+ signal gets fed back to be ORed with the AE shift signal before driving the decimal point CK+ input in order to load the data.

Module EXPREG

Board number B29.

b29_expreglayout_expregLike the DP register, the EXP register is a 3 bit counter which is based on edge triggered flip-flop sub units. In this case it is a down counter which will stop at the value 100, corresponding to -4. It is used during the normalization stage to work out what the decimal point position will be in the final answer. It is decremented on every AC register shift. The EXP register is to AC what the DP register is to AE. However there is no need for it to faithfully track the correct exponent once the DP latch has been set for the answer and this allows a 3 bit counter to be used because exponents less than -4 are not needed. As soon as the EXP register becomes negative during digit calculations, the DP latch becomes set and from that point on, the DP register takes over as the method of tracking the decimal point position. The main utility of the EXP register is during normalization when it is first loaded from the DP register and then decremented anything from zero to four times as the AC register shifts the source number into the correct internal position. The DP register cannot do this because it controls the display, cannot go negative, and is initialized with the source DP position, which in any case needs to be divided by two to get the correct answer exponent.

The EXP register uses the same flip and no-flip counting method that has been described before, but this time it is a down counter and so the logic is slightly different. In an up counter, a bit will flip if all the preceding bits are 1, but in a down counter the bit will flip if all the preceding bits are 0. The state of -4 (100) is detected by ORing the correct bits to detect the condition of not equal to -4, which drives a relay which enables counting when energized.

The LOAD- input turns on the two load relays which enable parallel synchronous loading from the DP register outputs. The EXP register is initialized using the values of bits 1 and 2 of the DP register, and DP bit 0 is used to control the shift unit. Bit 2 of the EXP register is initialized to zero. This connection scheme divides the DP register value by 2 which is the correct mode of operation when computing a square root. The value that is loaded is actually the inverted bits from the DP register so that if DP equals 000, the EXP register loads 011.

The output from the EXP register is conditioned to provide the parallel load input for the DP register for the DP load operation in state S7. The DP register loads 000 if the EXP register is positive, and 0XX otherwise where XX are the inverted values of bits 1 and 0 of the EXP register.

The rest of the circuitry on the EXPREG module is concerned with generating timing pulses during the computation operation.

There are two clock phases, the B phase clock and the A phase clock. Actually in the B phase clock comes first in the cycle (named for historical reasons). Both these clocks are generated from the two microswitches that are pressed by a cam on a motor on the front panel. When the motor is running, these two switches are pressed in alternation with a dead time between them. This provides the two phase clock.

The state machine is clocked on the B pulse, represented by the signal B_G+ (B has a gap.) The A pulse, represented by signal A_G- is also generated and has no temporal overlap with the B_G+ signal. This allows operations that are enabled by the state machine outputs and gated by the A_G- signal to reliably get activated without worrying that the state machine bits may cause race conditions as they transition. However, because the AC register requires a two phase clock, it was necessary to also use the B_G+ signal to control some functions. To allow the state machine to settle before using the state decoded output lines such as S1-, it was necessary to make a slightly delayed version of B_G+. This delayed signal is created by the circuit on the lower right of the EXPREG schematic and involves a capacitor circuit which delays the B relay by around 35ms, which is enough to avoid race conditions with the state machine changes.

The two relays on the lower left handle signals that are gated on the A phase, and the two on the lower right handle signals gated on the B phase.

The B phase signals include the load-1 drivers for the MSB and LSB parts of the AC register. They also include the AERES- signal to reset the AE register and the SM_AESHIFT- signal to shift the AE register. Also included are SM_DPCK+ and SM_EXPCK+ which clock the DP and EXP register respectively. The enabling source for the load-1 and AE control signals comes from a diode OR of the various states where these signals should be active. Separate EXPCKEN+ (from the ACREG1 module) and DPCKEN+ (from the DPREG module) signals enable the EXP and DP clocks

The A phase relays generate the load-2 MSB and LSB pulses for the AC load and shift operations and are also decoded using diode ORing from the state lines. These relays also generate the C register reset (SM_CREGRES-) and increment (SM_CREGINC+) signals. The SM_END- signal is also generated on the A phase using state decoding.

The A phase relays also generate the DPLATCH- signal which is enabled by the EXP register bit 2. This sets the latch at the middle of each compute cycle if the EXP register is ever negative and allows the decimal point to move on later AE shift operations.

Module STATE

Board number B30.

b30_statelayout_stateThe state machine sequences the computation through a preset program of operations. The diagram for the state machine can be found at the start of this document. It makes use of four d-type flip-flop units. Valid states consist of bit patterns 0000 thought 1011, corresponding to states S0 thought S11. S11 is used only for testing purposes. S1 is the non-running idle state and S10 is the last state of the machine at the end of the calculation. Bit patterns 1100 through 1111 would only appear if there was a malfunction. They are permanently set to transition into state S0 to avoid spurious operation. This is detected at NO3 of the second relay from the left (bit 2).

In order to make it easy to re-wire the state machine, the inputs to the flip-flops are generated via a diode matrix that drives the correct D inputs for a given state input. For example if U1- is driven, this drives the D- input of the state machine bit 0 and the D_N- inputs for the rest of the bits, resulting in a transition to state S1 after the clock. The outputs of the state machines are fully decoded to generate the state lines S0- through S11-.

The state machine clock input comes from the B_G+ microswitch on the motor unit. The state machine is held in reset (state S0) while the motor is not running and the user is entering data. The transition between user entry mode and running mode is controlled by the run relay which is the center one of the bottom three of the schematic. It generates the RUN- output which switches the control lines using the run slave relay on ACREG1.

The motor control and transition between stopped and running states is fairly complex. The run relay (second from the left bottom) controls the motor. When it is energized the motor starts to run. When it is off, the motor terminals are shorted together to ensure a fast stop (otherwise the motor can take too long to stop and the system keeps on going.) The GO- input starts the system running when the user presses the start button. However this operation is only enabled when the dial is in the neutral position to prevent the user running the program in the middle of a dial return. This is facilitated by some contacts on a relay on the CREG unit via its GOEN- line and this is connected in series with the button and the GO- input.

In the motor stopped state, the B_NG+ (B no gap) input is active because the motor always stops with the cam gap on the A side, i.e. A_G- is active and A_NG- is inactive. This means that if the user presses the start button, the GO- line is activated and the right hand of the three relays gets energized. Once that happens, it holds itself on and so it doesn’t matter when the user releases the start button. When this relay turns on it drives the run relay to turn on which starts the motor running. Eventually as the motor rotates, the B_NG+ line gets deactivated and so the start relay gets cancelled, but by that time, the A_NG- line will have been activated because the motor cam is no longer in the A side gap, and so the run relay will be temporarily held on. If the motor continued to run, it would eventually stop when the A_NG- line went off, but by that time, the B_G- signal will have clocked the state machine into state S1. A non-zero state is detected by the four diodes that provide an OR input to the first set of contacts on the run relay. These ensure that this relay remains latched on until the end of the program when state S0 is once again entered. This orderly turn off of the system competes when the motor runs around once again to the A gap side and A_NG- is deactivated, stopping the motor at that phase.

When the run relay is active, it holds a set of contacts in which drives the state machine RES_N- line (and the EXPREG reset line), ensuring that the state machine can function. These contacts get their input from the left bottom relay on the schematic, which is the cancel relay. If the user presses the cancel button it is able to stop the program from running by immediately forcing the state machine into state S0, after which it will turn off the run relay when the motor gets round to the A side. A CLEAROUT- signal is also generated to reset the AE register via a diode OR with the AERES- line from the EXPREG.

Power Supplies

There are two power supplies for the machine. The main supply provides 13.5V DC at 22A and is a switched mode power supply unit. The power supply output is split into five different circuits which are each fused at 5A. Each circuit supplies six modules. Typically the machine takes around 5A during the idle state, and up to 15A while calculating, mostly current pulses during the AC register and AE register shift when the AE DFLIP input relays are energized.

The high voltage supply for the Nixie tube anodes is a 170V boost converter designed to produce more than 20mA.

Control Panel

The display makes use of eight Russian IN14 Nixie tubes. These have ten numbers plus a decimal point and operate at around 170V DC with a maximum current of 2.5mA. There is an anode resistor for each display tube.

The clock unit consists of a motor with a brass cam attached and this operates two microswitches in alternation to produce a two phase clock cycle. The motor is a 6V gear motor and should not be connected directly to the 13.5V supply! The motor is controlled by a PWM speed controller. This circuit consists of a 555 timer IC connected to a MOSFET. The front panel speed adjustment potentiometer controls the mark space ratio of the 555 output waveform and therefore the time that the motor is on. The control range is limited using resistors so that the motor cannot run too fast. If the motor runs too fast then the machine will start to produce incorrect results.

The rest of the control panel consists of the power switch, decimal point button, clear button, run button and the phone dial for entering the numbers.

Module Interconnects

internal_units_namesTBD

Issues and Refinements

The main issue I found was that the machine ran slower than intended because of the hold lines interfering with the subtractor functions and making the ripple carry take a lot longer to settle. I added a unit to help with this. This two-relay unit acts as a monostable and shortens the pulse to the LOAD2MSB- line. The effect is that the load from the input to the output relays in the AC register MSB is much faster and this gives more time for the subtractor to settle. It brings the speed almost to the design speed of around 2 cycles per second.

Another issue was that after the machine had been running for some time it started malfunctioning. This turned out to be a set of bad relay contacts on the auxiliary load relay on B14 and so I had to move over some load / hold lines so that they ran from different contacts. This was just done using the screw terminals because of the difficulty of replacing relays.

15 thoughts on “Calculating Engine Documentation

  1. Very interesting design! A design concern is that both sides of the relay are being switched which, at least in relay telephony, is never done. This method can lead to “sneak” circuit paths. When looking, for example, in a #5 crossbar switch schematic, you will find all relays have one connection to -48V. Something you may want to consider.

  2. I agree that it makes things more complex to switch both sides of the relay. I tried to keep most of them single ended. However given the limited number of relays available for the design it sometimes was necessary to do this. Liberal use of diodes was made to help ensure that sneak circuits were not a problem.

  3. How did you get the relays that you used and how did you mount them together? I am doing something similar as a personal project. Thanks

  4. Hello Simon,
    I have been viewing and studying your design for about a year in the hopes of building a relay based simple calculator. Your insights have been very helpful and appreciated. I have modified the D-Flip/Flop circuit to enhance a counting design. I would like to send it to you for critiquing if you have time. If compensation is required, a bartering method is preferred. Thankyou for your time.
    Best Regards
    Fred Cathers.

  5. Why did you implement BCD subtraction as a “nines’ complement” followed by a BCD addition? I would have instead used a hexadecimal subtraction and then “cleaned up” the result by subtracting 6 from each digit that “went under” (i.e. generated a borrow).
    I believe that BCD addition is slightly more complex than BCD subtraction. This is because BCD addition carries are harder to detect than hexadecimal addition carries, but BCD subtraction borrows occur exactly where and when a hexadecimal subtraction borrow would occur.

    • There’s a very very efficient binary adder that was invented by Konrad Zuse. 9s complement is not too complex. I did paper designs for many approaches and this seemed simplest, but your observations are certainly noted.

      • What I meant was, as soon as you do the binary subtraction, you already know exactly where the BCD borrows are: they are in the exact same places as binary borrows! Therefore, the decimal adjust can be done without “rippling through” the BCD digits: they can be adjusted in parallel!

  6. Beautiful multiple comcepts, I love the clock motor plus micro switches, I built mine with caps and 10 turn pots to trim the the signals, what ever werks right!!

    Only by understanding the simplest form of a computers working parts, and the way that they come together can we appreciate how to invert the next genteration of thinking machines. I am so proud of your work, I congratulate
    you summa cum laude. Babbage would understand this as a bridge from one form to another. May the spirit of von Neumann et al watch over you.

    Respectfully,

    Bill

Leave a Reply

Your email address will not be published. Required fields are marked *

HTML tags are not allowed.

5,052 Spambots Blocked by Simple Comments