Texas Instruments' engineers said this was impossible - their chip only had 3 storage registers, no subroutine calls, and no storage for constants such as π. The ROM storage in the calculator held only 320 instructions, just enough for basic arithmetic. How could they possibly squeeze any scientific functions into this chip?
Fortunately Clive Sinclair, head of Sinclair Radionics, had a secret weapon - programming whiz and math PhD Nigel Searle. In a few days in Texas, they came up with new algorithms and wrote the code for the world's first single-chip scientific calculator, somehow programming sine, cosine, tangent, arcsine, arccos, arctan, log, and exponentiation into the chip. The engineers at Texas Instruments were amazed.
How did they do it? Up until now it's been a mystery. But through reverse engineering, I've determined the exact algorithms and implemented a simulator that runs the calculator's actual code. The reverse-engineered code along with my detailed comments is in the window below.
| A register | |||||||
|---|---|---|---|---|---|---|---|
| B register | |||||||
| C register | |||||||
| A flags | |||||||
| B flags | |||||||
| Mask / constant |
| Instr | |||||||
|---|---|---|---|---|---|---|---|
| Cond |
E to set the exponent. Operations are entered after the number and there is no equals key. Use the up and down arrows to select scientific functions. A display such as 1.2300 01 indicates 1.23*10^1, i.e. 12.3. A few examples:
To divide 17 by 3, enter
1 7 E 1 + 3 ÷
To take the sin of 0.01 radians, enter
0 0 1 ▲ +
To take antilog of .5 (to compute 10^.5), enter
5 E - 1 ▼ ×
For more usage, see the original manual here.
1.2345 03. Interestingly, only 5 digits are displayed, although 6 digits are stored internally.
The mantissa and exponent each have a sign; positive is represented internally by the digit 0 and negative by the digit 5. This may seem random, but it actually makes sign arithmetic easy. For instance, when multiplying numbers the signs are added: positive times positive has 0+0=0 which indicates positive. Negative times negative has 5+5=0 indicating positive (the carry is dropped). Negative times positive has 5+0=5 indicating negative. This is one of the tricks that helps the Sinclair code fit into the small ROM.
It's slightly confusing that numbers are stored internally different from how they are displayed.
The first digit in the A register is the mantissa sign, followed by the exponent sign. (The signs have to be stored in these locations since the hardware provides special display decoding for these digits which is how a 5 is displayed as a -.) The next two digits of the A register are the exponent, which is followed by the mantissa. This order is opposite from the display but makes some calculations simpler.
Due to the simple loop-based algorithms, the speed of the Sinclair Scientific calculator varies from good to horribly slow depending on the values. For instance, sin .1 takes under a second, but sin 1 takes about 7.5 seconds. Arccos .2 takes about 15 seconds. Log and antilog have the overhead of recomputing the constant 229.15, and take about 1 to 2 seconds. In comparison, the HP-35 was designed with a one second deadline for computations.
Using such slow, inaccurate algorithms would be unthinkable for HP or TI, but in the Sinclair Scientific they got the job done at a good price.
The category Function is code to read the keyboard input and keep track of what function is being performed. RPN greatly simplifies this, since functions are performed immediately. With algebraic notation, the calculator must store the function when it is entered, and then perform it later.
Using scientific notation shrunk the Sinclair Scientific's code in the next two categories: Digit is code to handle entering digits into a number and Display is code to format a number for display. As can be seen from the Texas Instrument code, a calculator with regular floating point numbers needs a lot of code to shift numbers back and forth and adjust the decimal point. In fact, since the Texas Instruments code ends up keeping an exponent internally, the floating point display is strictly overhead. Moving the minus sign to the correct display position is also overhead that the Sinclair Scientific avoids.
Normalize is the code to normalize the result of an operation and is fairly close on both calculators. The add/subtract/multiply/divide code is also similar length on both calculators. The scientific functions in the Sinclair Scientific fit into the remaining space. Trig functions were implemented in about 40 instructions. Arc-trig operations are almost 30 more instructions. Logarithms are about 40 instructions, with anti-log about 20 on top of that.
How much code is used for each function in the TI calculator vs the Sinclair Scientific.
After the operation (as with all operations) the result is normalized. That is, a result such as 0.0023 is shifted to 2.3000 and the exponent is correspondingly decreased by 3. Finally, registers are cleaned up and the result is displayed.
For example, 23 * 34 is computed as 34 + 34 + 34 + 340 + 340 (i.e. 3 * 34 + 2 * 340).
Before multiplying the mantissas, the exponents are simply added. At the end, the result is normalized.
C = C - S / 1000 S = S + C / 1000These operations are quick and are done without division:
S / 1000 is simply S shifted right three digits. (If you've studied graphics, this is basically a rotation matrix. This algorithm was discovered by Marvin Minsky and published in HAKMEM in 1972. I wonder if Sinclair read HAKMEM or rediscovered the algorithm.)
The calculator multiplies the input argument by 1000 (i.e. shifts it left three digits) and performs the rotation that many times; TRIGLOOP is the code that does this.
At the end of the rotations, the sine and cosine are available. To compute the tangent, the sine and cosine are simply divided.
The following diagram illustrates. The starting unit vector (1, 0) is rotated in steps of .001 radian until angle θ is reached. At that point, the coordinates give cos θ and sin θ. (To be precise, the starting vector is (1, 0.0005) to provide rounding.)
Vector rotation is used to compute sine and cosine in the Sinclair Scientific calculator.
Arcsine and arccosine use the same loop, but instead of iterating a fixed number of times, the rotation is performed until the sine or cosine of the vector matches the desired value, and the loop counter gives (after dividing by 1000) the angle θ, which is the desired arcsine or arccosine.
Arctan uses a slight modification. To compute arctan(z), the starting vector is (z, 1). The vector is rotated until vertical (the first coordinate is 0). The angle of rotation gives the arctan.
The following diagram shows how this works for arctan(.7). Rotating the red vector by θ will make the x coordinate 0. tan(θ) is .7 (opposite ÷ adjacent in the red triangle). Thus, rotating the vector until it is vertical and counting to measure θ will generate the arctan.
The main log loop takes an input X and iterates through X*.99^N until the result is less than 1. The resulting loop counter N is approximately -log(X)/log(.99). By adding the remainder, a couple additional digits of accuracy are obtained - see the code comments for details.
One complication of using .99 as the base is the calculations require the constant 229.15 (which approximates -1/log(.99)) in several places. Unfortunately, the calculator can't store multi-digit constants. The solution is the calculator actually recomputes this constant every time it performs a log or antilog.
Putting this all together, the log is computed by using the loop to compute -log(10)/log(.99), which is the magic constant 229.15. The same loop is used on the mantissa of the input to compute -log(input)/log(.99). Dividing the two values yields the log of the input. Finally, the exponent of the input is simply added to the result, since log(10^N) is just N.
Thus, log is computed with a single slow division along with quick shifts, adds, and subtracts.
Thus, antilog is computed with one multiplication, one division, and a lot of quick shifts, adds, and subtracts.
You might wonder how this algorithm can fit into three registers since there's the constant 229.15, the loop counter, the power of .99, and the power divided by 100, all in use at the same time. The trick is the registers are split in two. The chip's instructions support masks, so part of the register can be a counter and part can hold a computation value, for instance.
A high-level flowchart of the code in the Sinclair Scientific calculator.
The TMS0805 chip that powers the Sinclair Scientific calculator.
This chip uses simpler technology than chips such as the 6502. In particular, it doesn't have a layer of polysilicon interconnects like the 6502 processor.
The ROM is programmed by putting a transistor for a zero bit and omitting a transistor for a one bit. Once the layout of the ROM is known, reading the ROM is a simple matter of looking for transistors in the image. Likewise, the operation masks and single-digit constants can be figured out from the photograph. I converted the ROM contents into source code and wrote extensive comments explaining how the code works; the commented source code is displayed in the simulator window.
The Sinclair Scientific chip adds a couple instructions to the instruction set that weren't in the original chip. By looking at the instruction decoding circuit, it wasn't too hard to figure them out. The instructions were nothing special (for example, add A to B and store the result in C), but they probably made the code a few critical instructions shorter.
The image below shows the ALU instruction decode ROM. Each opcode from 31 to 0 has an input line on the top and is connected via transistors (the squares) to control lines that exit on the left. The ALU takes two arguments and by default performs addition. For instance opcode 0 is connected to "Arg1 is A", "Arg2 is B", and "Destination is A". Thus it adds A and B, putting the result in A. Opcode 13 selects C as argument 1, constant as argument 2, performs a subtract, and has no destination. Thus, it compares register C to a constant. Likewise, the other opcodes can easily be figured out from the image.
The instruction decode ROM in the TMS0805 processor that powers the Sinclair Scientific calculator.
The calculator manual specifies fairly restrictive limits on the allowable values for scientific operations, but the calculator doesn't enforce these limits. If you're outside the limits, there's no telling what the calculator might do. For instance, logarithm is only supported for arguments ≥ 1. The calculator almost works for arguments such as 5E-3, except it adds the exponent 3 instead of subtracting it, so the result is totally wrong. If they had room for just a few more instructions they could have made this work.
EdS found that 1.99996 antilog yields the wildly wrong answer of 0, even though it is in the supported antilog range. The problem is in the computation of 229.15*(1-.99996), the second factor is so small the multiplication yields 0 causing antilog to bail out.
The antilog code assumes that if the exponent is greater than 0, it is 1.
Thus antilog of 0.01E2 yields 1.2589 instead of 10. Calling NORMALIZE would have fixed this, but there wasn't space for the call.
Arccos of a very small value (e.g. 0.0005) goes into an almost-infinite loop and takes 1 minute, 48 seconds to complete (as measured on a real calculator), before returning the wrong value 0. The root cause is since the angle is increased in steps of .001, it never exactly reaches the desired cosine value. When the rotation vector crosses vertical, the angle goes from 1.570 radians to 1.571 radians. cos 1.570 is bigger than .0005 so the loop doesn't exit. But at 1.571, everything falls apart: the loop uses unsigned arithmetic, so the sine value wraps to 999.99955 and the sine and cos become meaningless. The only reason the loop ever terminates is the loop counter eventually overflows after 9999 iterations, which inadvertently causes the code to fall into the arctan path and exit with 0.
Scientific calculators usually provide constants such as e and π but there was no space in the ROM for these constants. The Sinclair Scientific used the brilliant solution of printing the constants on the calculator's case - the user could enter the constant manually if needed.
Unfortunately, as calculator prices collapsed, so did Sinclair Radionics' profits, and the company was broken up in 1979 after heavy losses. Clive Sinclair's new company Sinclair Research went on to sell the highly-popular ZX 80 and ZX Spectrum home computers. Clive Sinclair was knighted for his accomplishments in 1983, becoming Sir Clive Sinclair.
If you want a short link to this page, use http://righto.com/sinclair.
This article has a bunch of interesting comments at Hackaday and Hacker News so take a look. Thanks for visiting!