The idea for this project came about during a week of freezing winter arctic event here in Austin, Texas, with a failed power grid as well as government, while keeping close to a gas fireplace, the only source of heat and light, for a couple of days. With a weak internet over a phone data line, I could only do some preliminary searches and mainly work out various details on a writing pad, growing a feeling that the project may be personally exciting and practically doable.
I will try to post my progress over the coming weeks.
How do calculators work?
You press a few buttons, a function, and you get your result back. But what is the technology and the algorithms at work behind its computation? For sure we can read about that, but to fully internalize all the tradeoffs and corner cases, we need to embark on designing one. To create one from scratch, and by that, I mean it - not using emulators and pre-existing ROMs, or even a powerful microcontroller, will provide us with that innate knowledge. We should start with a blank drawing pad onto which we would sketch our design from the very first gate and build on top of it.
Let's dive in.
We will have to make certain implementation decisions, many of which are exclusive, each one with its own tradeoff.
Internal number representation
The number format internally used for computation:
- BCD (binary-coded decimal), where each nibble stores one decimal digit of mantissa and exponent
- More cumbersome operations on individual digits.
- Floating point representation
- Needs conversion to and from decimal values.
- Suffers from conversion errors.
The drawbacks of BCD are more complex routines and slightly lower compactness; the advantage is the perfect representation of decimal magnitudes, as opposed to pure binary, that cannot represent exactly some of them; also that there are very refined algorithms for both normal arithmetic and transcendental functions.
Digits of precision
How many digits of precision do we want to carry? Here we need to be very careful not to show more digits than we can compute exactly (with the exception of the last, rounding, digit). A calculator that displays incorrect values is much worse than one that displays only a few, but correct, digits.
- BCD may need internally wider registers to compute trailing, rounding digit, so it uses more digits for computation that it shows in the result (ex. HP41:10 digits, 13 internally; HP71: 12 digits, 15 internally)
- Binary (floating point) may be off when rounding certain values that can't be represented exactly in a decimal system. This notation may follow a standard like IEEE 754 or implement it’s own partitioning of mantissa and exponent values
A major decision to be made is whether to use one of many rounding modes or simply truncate the result. Each rounding mode has its share of advantages and drawbacks, or it’s suitable for a particular use (financial, scientific, etc.)
- RPN (Reverse Polish Notation)
- Does not have parenthesis, uses stack, computes intermediate values immediately.
- Does not have "=" key but have "push to stack" key (often called "ENTER")
- Quicker, less keystrokes.
- Algebraic (or infix notation)
- Uses parenthesis and knows about operator precedence.
- In practice, requires more cognitive effort.
- Have "(", ")" and "=" keys
Programmable vs. fixed function
- Programmable calculators have larger non-volatile storage where they store user input sequence (a program) and provide additional functions for execution control (value testing, looping,...)
- More sophisticated machines are more akin to full-blown computers and have a high-level language interpreter (like BASIC)
Gates vs Microcode
How much is done in hardware (in gates) vs. in microcode (ROM)? Here, by gates, I mean strictly specialized digital logic dedicated to computing arithmetic functions.
- Everything is done in gates (no ROM) (early, or very simple, calculators).
- Very minimal basic operations in gates; most functions is in code (ex. using HP's Saturn CPU).
- Most is done in gates, only the most complex functions in code.
- Everything is done in code, minimal necessary functionality in gates (ex. some Z80-based calculators).
What algorithms are used to compute higher-level functions?
- Taylor series
- Chebyshev polynomials
- Other series and algorithms
Keypad, or keyboard, is the primary interface to the user.
Arguably the best keypads are those made by HP for their line of calculators. They use double molded plastic and a proprietary spring system.
On the other end of the keyboard technology are super-cheap membrane keypads, such are those used in budget home computers by Sinclair and many $1 calculators from China.
A small step up is the membrane sheets pushed by extruded rubber/molded keyboard overlays. They provide more tactile feedback. They are very common since they are inexpensive and provide a good balance of price vs how they feel. Your TV remote controls, thermostats, and most of the appliances around would have those.
Occasionally, a frequently used button, after being pressed harder and harder, would stop working. That happened to our thermostat: two buttons setting up the temperature up and down stopped responding to our increasingly frustrating attempts to set the temperature. The remedy was to open the box and scratch the back of a rubber contact, a small graphite pad called “the contact pill”, with a soft black drawing pencil. Since the pencil leaves graphite marks, those contacts are now fully conducive and will continue working.
Since we cannot make plastic molds easily (perhaps they could be 3d printed, but I don’t have a 3d printer), the membrane-style keypad looks to be the most promising alternative for our calculator. We need to have lettering on the actual keys (numbers “0” through “9” and major functions like “+” and “-“), and also text for secondary functions accessed by some kind of a shift key, and those are normally expected to be shown next to the primary functions (above or below). We could print those on a regular piece of paper (printing using a laser color printer for nicely colored labels if we want to get fancy), and then laminate that sheet. The lamination would add extra stiffness to the paper.
There are two kinds of actuators we could use underneath.
The first one could be traditional PCB-mounted push buttons. Since those have a certain thickness, we would make another PCB sheet, acting as a spacer, with round holes where the buttons are, providing that clearance. If the clearance is not sufficient, we could raise that board up with some spacers.
As you press a spot on a laminated sheet, it would press a switch; the intermediate board would keep it all flat and level.
Another option would be to use small, tactile dome switches. Their use is rather uncommon among hobbyists. Those switches are made of tiny pieces of domed conductive material (sometimes gold plated) which bend as you press to make contact in the middle. They make a quite satisfying tactile “click”. The domes should not be soldered to the board since that would stiffen their elasticity and would make them prone to failure, so they are either physically held by some template or they are glued on top (frequently they are sold with an adhesive sheet).
Surprisingly, although these cost only a fraction of a cent to manufacture, US electronics shops like Mouser sell them for 50 cents each! If you shop from Alibaba (China), you can get a bag of 500 for $10. If you are making a large order, you should not pay more than 0.4 cents per button! I am sure there are quality differences, but we are not building a nuclear reactor control panel, either. It’s ok if they are not perfect.
A variation of those dome switches has a hole in the middle, where you can PCB mount an LED behind it and, for example, have it lit as you press a switch, or show a latched state.
Although I’ve never used those dome switches before, I just ordered a bag from China and am planning to give it a try with this project. I hope they will work as visualized.
There is another kind of “switches”, or better, a lack of them. With the advent of microcontrollers and their special purpose IO blocks, many now offer touch detection which does not need anything else besides access to an open trace. The controller registers even the slightest capacitive touch of a finger. Since we are not using one of those MCUs, we won’t pursue that idea here.
Modes of Operation
When we are already making our own calculator, being engineers, we should plan to support several different number bases. Besides decimal, we should also have hex and binary, and we may as well throw in octal. We could, of course, architect it to support any arbitrary base, but I don’t see any practical use for something like that.
We want to follow conventions and call these modes DEC (decimal), HEX, OCT, and BIN.
Any number currently on the screen can be converted amongst these bases. Non-whole decimal numbers will be truncated to integers.
Consequently, we need a few additional keys: besides the standard “0”…”9” we also need “A”, “B”, “C”, “D”, “E”, and “F”. We also need to assign 4 mode functions to keys.
We should also add a couple of bitwise operations to go with these modes. At the very least, basic AND, OR, XOR, NOR, and SHIFT (left or right) operations come to mind.
The heart of our calculator will be a small micro-sequencer implemented in FPGA. We will try to implement IO as discrete blocks to make our life easier.
For example, keypad scanning could be a separate and independent module that takes care of debouncing and simply queues key codes to an internal FIFO.
Similarly, the LCD driver could also be a separate module that initializes the display and implements some simple protocol to control writing the characters.
The exact details should be more obvious once we start writing a concrete architectural document.
In this first article, I tried to provide an overview of various options we can select from, trying not to decide anything in particular. Other major things are still being left out (like the power source) because we are still wrapping our heads around the complete project. As I was writing, some things did start to crystalize in terms of dependency (“if you decide to implement it this way, then you can’t do that”) and feasibility. Still, anything is on the table.
- HP Saturn processor: HP Saturn - Wikipedia
- Multi-cycle sequencer: Appendix D Mapping Control to Hardware (tufts.edu)
- The Spectrum ROM Disassembly (Uses Chebyshev polynomials for trig functions):www.primrosebank.net/computers/zxspectrum/docs/CompleteSpectrumROMDisassemblyThe.pdf
- How HP calculates CORDIC: www.jacques-laporte.org/TheSecretOfTheAlgorithms.htm
- How CORDIC works: Cordic for Dummies (jacques-laporte.org)
- HP35 on Arduino (with source): www.jacques-laporte.org/TheSecretOfTheAlgorithms.htm
- Calculator forensic: Calculator Forensics (rskey.org)
This set of articles explains how HP calculators calculate various functions:
6 thoughts on “A Calculator”
An interesting project.
I have been looking at the history of electronic (desktop) calculators that begins in about 1960.
The first transistorised calculators appeared in about 1964, and for a simple 4 function 12 digit machine used about 500 transistors and 1000 to 1500 diodes. AND and OR gates were based on diode logic, and transistors were only used if signal inversion (NAND, NOR) was needed.
Early calculators (pre 1967) used either magnetic core memory or magnetostrictive delay line memory. By the late 1960s these were replaced by specially designed solid state shift registers that could hold 12 to 16 4-bit BCD digits.
Arithmetic was done in a bit-serial manner, which massively reduced the hardware compared to 4-bit parallel arithmetic.
Bit serial had been used in the early computers up to the late 1950s. It was slow but used far fewer expensive transistors.
However performing BCD arithmetic as opposed to binary arithmetic led to it's own hardware complications.
The Japanese developed their own range of MSI circuits "JMOS" specifically designed for the calculator market.
By 1971, Mostek, Texas Instruments, Rockwell, Commodore and Intel were developing single LSI chip calculators - and that's where designs became proprietary, and good detailed information scarce.
You might like these sites: http://madrona.ca/e/eec/ics/JMOS.html
I am currently working on a bit serial ALU using TTL inspired by some of the late 1960s calculator logic.
You might also like the Ken Schiriff article about reverse engineering a 1974 Sinclair Scientific calculator - which used every trick in the book to make a 4 function calculator chip generate log and trig functions.
Less is more.......
Ken, thank you for sharing the abridged history - it's fascinating!
I follow Ken's work and will be posting links to it in the upcoming articles.
Would also love to read about your bit serial ALU, a technology I've not considered.
I think you choice of looking at the early HP series of calculators is a good one.
Whilst they were proprietary silicon - enough has been written about them to get a good understanding of the logic and algorithms involved.
The early HP machines were bit serial, but later models with more logic for processing became 4-bit or "nibble serial". This is a good choice because 4-bits is a sweet spot for hardware implementation - a lot of TTL devices are 4 bits wide.
Whilst I have done a bit of verilog on Lattice ICE 40 FPGAs - I still enjoy the challenge of "old skool" TTL. My bit-serial ALU is just 10 TTL packages. With bit-serial you trade off hardware complexity against time for execution. This becomes particularly noticeable when you are dealing with 16 bit or 32 bit word sizes. The hardware doesn't get any more complicated - it just takes longer to compute.
Thanks for the link to the Sinclair Spectrum ROM Disassembly. I got a ZX81 as a kit, aged 16, in the early 1980s and this led to a career in electronic hardware. I have always had a "soft spot" for Z80 code. I now have an RC2014 from a kit that can be used as a target to try out the Spectrum math algorithms.
Looking at the Spectrum ROM (page 210 onwards) I think Sinclair's coding team has created a virtual machine to make the job of calculating the trig and other functions easier. It looks like that from all the define byte DEFB instructions that he has some sort of interpreter running, and each DEFB is a high level instruction.
Clive Sinclair was a key player in the UK calculator industry in the early 1970s. It is not unsurprising that his ZX range of computer's ROMS were influenced by his technical knowledge of calculating trig and exponential functions from first principles.
The Z80 is nothing special, any simple cpu from that mid-70s era could be used to simulate calculator math functions. Afterall the Intel 4004 was originally intended as a programmable calculator chip for the Japanese company Busicom.
I would consider designing a generic cpu - either bit serial or nibble serial, and use the HP (or Sinclair) approach to calculating the trig and math functions.
I like the challenge of minimalism - can you create a useful cpu in 1000 gates, or a usable interpreted language in 1000 bytes of code? This is why I am always drawn back to the simple machines of the mid to late 1960s for inspiration.
BTW - I was in Austin TX. on Halloween 2003. It was 79F in Austin at lunchtime, I then took a plane that evening up to Denver where it was about 14F and the flights were delayed because of de-icing. I had no idea how quickly the cold could strike.
Stay Warm - Ken
Regarding keypads and displays - TI used a standard tactile dome keypad in the late 70s across a wide range of it's calculator products. It was arranged as a 5 x 8 matrix. To keep the cost down a lot of their range shared parts, cases and accessories.
By the mid-1980s, the keypad was being offered as surplus component for about $1 each. I bought 10 of them for a project, and until about 6 months ago, I still had them. I will have to check my parts bin.
I have in my past, laid out custom keypads using tactile domes, and it is fairly simple for a few keys, but a 5 x 8 matrix is going to be tough and costly. They really need a printed membrane panel over them.
Most hobby keypads today resort to low cost Chinese tactile "click" switches on a low cost double sided pcb. }
The RC2014 keyboard is an example of this. Scanning was traditionally done with a mix of address lines to energise a row, and a single input port to read back the key position.
There are modules from China that use a serial keyscanner and LED driver chip - the TM1638.
One of the common ones is "LED&KEY" and another more expanded one is a 16 key, 8 digit 7-segment module called the QYF-TM1638 - available from many sources for very few dollars.
The TM1638 uses a serial communications protocol similar to SPI. SPI can be implemented in TTL with a couple of shift registers and a sprinkling of magic pixie dust (ingenuity).
7-segment displays will give the retro-calculator feel of the early 1970s - and are dirt cheap from China. I often advise the use of standard modules for hobbyist projects as more people will be enthused to follow your work.
At the end of the day this is the 21st century, and if you need to throw in an ATmega328 or ATtiny - just to decode BCD digit streams and convert to something that will display on a TM1638 module - then those are just tools to get the job done. Nobody will admonish you for not strictly adhering to pre-1975 manufactured ICs.
After all - if your cpu is going to be implemented in an FPGA, you have kind of blotted your retro copybook.........
Final suggestion - have a good look at shift registers - the wunderkind of digital logic.
All perfectly sound comments and good links, thanks!
Another interesting pdf link describing some of the internal operation of the HP "Nut" processor - with some verilog examples
And this describes the Nut instruction set
It is starting to become apparent that the cpu on the HP 35 ( a predecessor of Nut) was an unusual and very specialised processor, tailored to the requirements of performing scientific calculations as quickly as possible (typically under 500mS). This had to be done with extreme limitations to the amount of ROM available. The HP 35 had just 768 10-bit ROM addresses, contained in three 256 x 10 bit chips.
HP devised their own serial bus. ROM addresses were sent in serial format of just 8 bits. This addressed a "page" of ROM - which happened to be one ROM chip. If you had to go to the next page, you just enabled the next ROM chip with a separate chip select signal. This kept the addressing short (and faster) and was easy to implement in hardware.
The HP engineers envisioned that other peripheral devices would ultimately be connected to the cpu, such as printer, card reader etc. These would use the same serial bus which would keep the wiring to a minimum. SPI is a modern cousin of the early HP serial bus.
Whilst the HP 35 processor was specialised and ROM constrained, it could fairly readily be emulated by a more general purpose cpu (Z80, 6502 etc) running code from a much larger ROM. I see from your links that there is already an Arduino emulation of the HP 35. This seems a good starting point as a means to familiarise oneself with the workings of the HP 35, without butchering a 50 year old vintage calculator. An ATmega or similar clocking at 20MHz is already clocking 100 times faster than the 200KHz calculator, allowing plenty of scope for creating an HP 35 virtual machine running at speeds similar to the original HP 35.
In the meantime the techniques used in the HP 35 cpu are similar to my aspirations to build a bit-serial cpu in real TTL.
The HP patents relating to the early calculators are fascinating - you can find a list of them here
The best one describing the early HP proprietary cpu, instruction set etc is