Wednesday, April 17, 2019

Tiny Calculator: Hardware

Tiny Calculator is business card size.
The hardware for this project is finally done! The first step was getting the LCD running. This time I went with a 128x32 LCD from Newhaven, which is a little pricey at $11. A simple HD44780 compatible LCD like I used for my RPN Scientific Calculator project would give me the same 20x4 character resolution for $3-4, but all the ones I have seen are way too big. Another option would be a small OLED screen, which are very cheap but would drain the CR2032 battery a lot faster.

The LCD has 17 pins with 1.5mm spacing, which is smaller than a breadboard or protoboard but still big enough to solder by hand. The majority of the pins are for capacitors, so I soldered a small adapter board to hold them and route the data pins to a breadboard. This was tedious and more difficult than I imagine when I bought the LCD but the hardware worked on the first try. After I got it running, I epoxied the LCD to the board. Next time, I think I will go with something easier to solder like an OLED screen even if it takes more current.


The datasheet for the LCD has some initialization code, which I could not get to work. A search turned up some working C code from another forum that was easy to get running with GCC for the MSP430. Translating the C code to assembly was a little tricky since some of the variables for initializing the SPI module on the MSP430 are not plain constants as you might expect from looking at the C code. It took some searching in the header files to figure out that what appears to be a constant is actually something cleverly defined to load a configuration value from the MSP430. After I got that working, everything else went smooth. Rather than try to design my own 5x7 font, I reused a character set I found on a German forum, which came in handy on another project I have been working on but haven't posted about yet.

The main board of the calculator is pretty simple. It just holds the microcontroller, CR2032 battery, and some pins for programming. All the wires are 30 gauge wire wrap I got from Mouser, which I really like using. The power lines are thicker gauge, but they are there more for color coding than because I need them to be that thick. 30 gauge copper is supposed to be able to carry more than the few mA I am using without dropping a lot of voltage.

The keypad has 35 keys, which is more than the 25 I was planning on originally. The main reason I did this is because it looked strange to have a square keypad. Also, there were two leftover pins since Xin and Xout can be reused as GPIO if there is no crystal.

 Each key takes up one 3x3 block on the protoboard, which is smaller than the 4x3 spacing of the keypad on my Pocket Calculator project. It turns out, it's not too difficult to bend the legs under the button a little to make them fit the tighter spacing. The LCD and the keypad both plug into the main board with headers.

Since the calculator runs on a battery, it's important to keep the calculator in low power mode as much as possible. This turned out to be surprisingly painless in assembly! Setting up interrupts is very straightforward too. The calculator scans the keypad a few dozen times a second and goes back to sleep if there is no work to be done. Each key has a byte of memory allocated to it to implement a counter for debouncing the keys and showing which keys have been read. My very cheap multimeter shows that the calculator uses a lot less current than the datasheet for the MSP430 and LCD suggest. Hopefully I can borrow better equipment and get a more accurate reading to try to better estimate how long the calculator should run before it needs a new battery.

The interface code is already mostly done and will be the topic of the next post on this project. After that, the only step left is adding the key labels.

Sunday, April 7, 2019

New Project: 7400 Logic Calculator

My newest project is a calculator using 7400-series logic chips. There are a lot of really neat computers built using these parts, and I would like to try building a relatively small one that fits into a calculator. My idea is to keep the design as minimal as possible, since even a simple computer of this type could get pretty big quickly. There are a few things I have been thinking of for a long time that should help me save space.

A few years ago, I got interested in building one of these computers using lookup tables on a flash or EEPROM chip to implement a simple ALU and got as far as putting a 4x4 bit look up on table on an EEPROM. Eventually, I gave up the idea since at least one other person had built essentially the same thing that I wanted to build, and I didn't want to totally reinvent the wheel. Recently, I got interested in the idea again when I saw Ben Eater's excellent series on building an 8-bit breadboard computer. It uses an EEPROM for microcode, which is what I had considered for other projects. Another neat project I looked at is the Gigatron, which is a different RISC-type design that I don't think uses microcode. So far, I have been able to get a fairly simple version of what I want to build going in the Atanua simulator:


After I got this going, I already started looking for ways to make the circuit smaller and fit into a calculator sized case. First, I have four registers, which would make programming a lot more convenient, but I would leave out to save space. Also, I have two microcode ROMs, like in Ben Eater's design, although I could survive with just one if I latch out some of the control codes from the program ROM.

Sunday, February 3, 2019

Tiny Calculator: Improved CORDIC


Since my last post I have made a lot of changes to the CORDIC routines I was working on. As you can see in the chart above, the new version fits in less than the 4.1k of the last version even after adding in logarithms. The change came after I found an article about how the HP-35 did CORDIC calculations. Unlike the other descriptions of the method I have used, this version uses an atan table of powers of 10 instead of powers of 2. This lets you shift the arguments by whole decimal places, which is much faster with BCD numbers than powers of 2 . Before, I had wondered if this would be more efficient, but I don't understand the math behind it well enough to modify the routine myself. My implementation of the method the HP-35 uses only takes 90k cycles, compared to the 1.18 million of the last version. The X and Y that the calculation produces, however, cannot be scaled to produce sine and cosine directly. The scale factor depends on the number of rotations, which is easy to precalculate when the angle is halved every iteration, but not possible to know in advance when you use powers of 10 since each iteration requires up to 9 calculations with each affecting the scale factor. As a result, the ratio of X and Y provides the tangent and the HP-35 used identities involving multiplication, division, and square root to generate sine and cosine from tangent. In addition to the 90k cycles for the CORDIC calculation, I would need at least another 140k cycles for these identities. This is 5 times faster than how I was doing it before, although I'm afraid the accuracy would suffer from the added calculations.

The next thing I tried was posting on the HP museum forum, where Thomas Klemm showed me how to do CORDIC calculations in base 10 without resorting to identities. This was a huge help and a much better way to do things than anything I have tried before. The newest routine I have calculates tangent in only 186k cycles and provides sine and cosine without additional calculations! Like in Thomas' version, I tried to make this CORDIC routine more generic so that I can reuse it for inverse trig functions too. Logarithms and powers of e turned out to be much simpler than trig functions using the method described on the same page about the HP-35.

There are still a lot of things to learn about MSP430 assembly. One thing that tripped me up was thinking that RRA automatically shifts a 0 in from the left when rotating when it actually reproduces the leftmost bit instead. Another surprise was that shifting packed BCD by two decimal places is just as fast loading a word from memory, swapping and combining bytes, then writing the result back to memory as it is to just copy bytes directly. I thought the byte copies would be faster, but I was actually able to shave one cycle off by loading and writing words. I rewrote this short section of code five different times trying to save a cycle or two and eventually realized that this is not a useful way to spend my time. This improvement is too tiny to ever be noticeable, and I want to finish this project soon. There are a few other small improvements I have not spent time on since they would provide only a negligible speed up.

The next step is to start working on hardware and the interface code.

Sunday, December 30, 2018

Tiny Calculator: Sine, Cosine, and Tangent

For the trig functions, I started building the same angle table that I used for the CORDIC routines in my RPN Scientific Calculator. Comparing my table to an example calculation I found of how CORDIC works, I noticed that the values are all pi times bigger than the ones in the example. Could I have made the same mistake in my RPN Scientific Calculator? When I get back home from the holidays, I should check to make sure that this does not throw off some of the calculations. Another thing I found out from the same page was that the K value to multiply by after the CORDIC calculation is calculated for a particular number of iterations. In my RPN Scientific Calculator, I included a K value for the maximum number of iterations and truncated it when less precision was used. On second thought, I should have done some testing to make sure truncating the K value to the precision of the argument always yields the best results for a particular level of precision. At the moment I don't plan to redo anything on my older calculators unless something is majorly wrong. It is good, though, to recognize this type of mistake, so I can look out for it in future projects that use CORDIC.

To generate the angle table I used the bc command line calculator. It has a very simple programming language that can run from a script. Interestingly, bc does not seem to do any type of rounding, so the tables I have are unrounded. Maybe I will experiment with a rounded table to see how much of an effect it has. For some of the other tables (including a couple I ended up not needing) I used Python, which has been really helpful. The table itself contains angles descending in size, so I only sto

The first step to implementing the trig functions was replicating the CORDIC calculations in a spreadsheet. This works for about 30 iterations until the numbers become too small for the spreadsheet to handle. Rather than doing bit shift operations like I would on the microcontroller, I multiplied by inverse powers of two, which accomplishes the same goal. When I had that working, I tried generating those multipliers on the MSP430 and multiplying, rather than bit shifts. I thought this might be fairly fast since the multiplier could be left in binary, which makes it quicker to use with the Russian Peasant algorithm, and the amount of zeroes in the multiplier would mean relatively few multiplies altogether. Consider this shortened table of successive inverse powers of two:

Friday, December 14, 2018

Tiny Calculator: Four Functions

The last few weeks I have gone down a little bit of a rabbit hole writing BCD math routines for my Tiny Calculator project. The goal has been to compare different calculation strategies to find which ones are fast but still small enough to fit in the 16k of flash the MSP430 I am using has. Like the addition routines I wrote about in my last post, all of these routines were a lot smaller than I expected. There were also some other surprises about what worked best.

Subtraction
To start with, I based this routine on the setup code for the addition routine, which saves some space. Originally my plan was to make everything modular so that I could substitute pieces of code in depending on what size and speed trade off I wanted, which is why I have separate body and ending options in the table for my addition routine. However, to save space and build one routine off the parts of another, it makes more sense to decide which version to use at the beginning. The only big difference between the two subtraction routines I tried was rolling and unrolling the main loop, with the unrolled version being about 75% faster. It's also about 25% larger but that is only around 50 bytes.

Multiplication
In addition to the straightforward method of repeated additions, I tried the quarter squares and Russian peasant algorithms I learned about doing 6502 BCD multiplication. It was a surprise that using quarter squares was over 10% slower on the MSP430 than the Russian peasant algorithm, whereas it was over 4 times faster on the 6502! Part of the difference may be the speed up I get on the MSP430 by converting each digit of one argument to binary (so it can be halved) only once and saving it, rather than converting it every time like on the 6502. Another major difference is how much slower accessing tables on the MSP430 is compared to register operations. It's interesting how the timing of the architecture can decide which algorithm works the fastest. It's also great that the Russian peasant algorithm doesn't need any tables and is therefore much smaller.

Sunday, November 4, 2018

New project: Tiny Calculator

My Pocket Calculator project has been on the back burner for a few months while I finish my master's thesis. In the mean time, I got interested in doing a much simpler project to make a very small calculator that will hopefully be about 2.5 inches long. This is the size of a 5x5 keypad and the small 128x32 LCD I want to use. Like my first first calculator, it will use a through hole MSP430. The first calculator needed two MSP430s to contain all the firmware, but I think I can fit everything on one chip for this project. It should also be possible to do what I want with the 512 bytes of internal RAM the chip has, so I won't need any external SRAM, and with 25 keys, I also won't need external shift registers. Other than the microcontroller and some capacitors, the only other thing on the board will be a CR2032 battery. The MSP430 needs 2.7v to run at 16MHz, so I plan to run at 8MHz in order to use the battery down to 2.4v. It might be possible to monitor the battery and run at 16MHz as long as the voltage is high enough, but I don't think I will need the extra speed like I did on the last calculator.

One of the main things that got me interested in this project was finding out that the MSP430 has a decimal add instruction that works on packed BCD words. This is really convenient and should be many times faster than doing BCD manually in C like I did for my first calculator. One possibility would be mixing C and assembly to take advantage of features like this, but I am going to try to do the whole thing in assembly to make it as small and fast as possible. Another speed up should come from switching to a 16 byte floating point format. This will let me calculate logarithms and trig functions to the same precision as my first calculator but fit everything in the 512 bytes of internal RAM. Eliminating the bottleneck of transferring data over SPI one bit at a time will probably be the main speed up. For multiplication, I want to try some of the algorithms I tested for the 6502, and for division, I will try out some based on Netwon's Method. For logarithms and trig functions, I'll probably use CORDIC routines again, but I want to see if Taylor polynomials will be much smaller, even if they are slower. With 25 keys, I can fit in just about everything from my first calculator. It should be able to do a little more than an HP-35. The main drawback compared to my first calculator will be less precision with large numbers and less stack space, although neither should be a problem, since there won't be a programmable mode. Also, I plan to keep track of exponents by the byte, rather than the nibble like a did on the first calculator. This will mean losing precision by a factor of 10 in some cases, but it will make aligning numbers during calculation much simpler.

Sunday, June 24, 2018

Calculator Processors

Most of the microcontrollers and processors I have looked into using have been for my calculator projects. That's one of the main reasons I did my microcontroller comparison a few years ago. Recently, I have gotten interested in other chips I could use for calculator projects, in addition to the 6502, 6800 family, and 8051 chips I was interested in before.

The main two criteria I have are an external memory bus and through-hole package. Right away, this eliminates most modern microcontrollers, since almost all of them with an external memory bus are SMD only. In theory, I could use a chip without an external bus if it had a few hundred KB of RAM for data and a few hundred more KB of RAM or flash for program space, but I haven't found that in a through-hole package. Another point is that I would like the ability to load programs from an SD card, which is impractical if I need to have the chip reflash itself every time I load a program. Through-hole parts are more convenient to solder, and I would like to do a few more projects with them before I try to start making surface mount boards.

Modern microcontrollers
  • AVR - None of the ATmega series has an external bus. Some of the ATxmega series do, but they don't come in through-hole packages.
  • PIC - For a through-hole part, the PIC32 series is very impressive at 50mhz with 64KB RAM and 256KB of flash, but even this is not enough for what I am planning. The chip requires a separate programmer, and the compiler offers limited optimizations unless you pay, which is absurd in 2018 compared to its competition. It does have something called PMP, which offers a sort of data bus, but it can only address 12 bits, since the DIP part only has 28 pins. 
  • MSP430 - This chip worked well for my RPN Scientific Calculator, but it also lacks an external bus.
  • Propeller - This is an interesting chip but like the others, it lacks an external bus and does not have enough flash or RAM. The one interesting possibility is doing several calculations in parallel, although I don't know how I would use that for a calculator.
  • Zilog - They have some nice chips, including some processors with external buses, but I would like to use something different than what the TI-83 and similar models use.
  • LPC1114 - I really like this chip, and I am using it in my Pocket Calculator, but it also lacks an external bus, and it seems that it is no longer manufactured.