Friday, May 31, 2013

RPN Scientific Calculator: External RAM

The last part of the hardware needed to complete the calculator is external RAM. Even if it does not have any programming capabilities, it will still need more RAM for the stack than the 512 bytes an MSP430G2553 has. Microchip makes 128K SRAM chips that are small and accessible over SPI that would work well for this project. However, I had this parallel SRAM chip from Alliance left over with nothing in mind for it and I decided to use it instead. It needs 8 pins for data so I am using one 74HC595 for output and one 74HC165 for input. The 17 address pins are driven by two more 74HC595s. This only gives 16 outputs so the 17th address pin is tied directly to a microcontroller pin. This will allow me to have two banks of memory, although I don't have any use for that at the moment. Putting this together took a lot of wiring but it wasn't too difficult.

Accessing large amounts of memory like this over serial can be a speed bottleneck, so I decided to use the USCI module of the MSP430 to do hardware SPI and speed up transfers. After learning how it works I saw that it is really easy to set up and convenient to use. As with the shift registers that read the button matrix, I decided to share the clock but to use different latches. The USCI has separate data in and data out pins so those aren't shared. This is handy for reading the 165 shift register because after it is latched you can just push a dummy value out then read the USCI receive buffer. There is a flag to control whether the USCI stores data in MSB (Most Signicant Bit) or LSB format but it can't be set separately for the input and output buffers. This means data goes out with the right orientation but comes in backwards. To remedy this I hooked up the data inputs of the 165 in reverse order to the data bus of the SRAM.

To test the speed of this setup I made a test program to write a pattern to every byte of the RAM then read it back and make sure the values are as expected. This worked fine at 1MHz but the LCD glitched when I tried running at 16MHz. After I fixed that I was able to finish the whole test in about two seconds. That is pretty good throughput for a calculator!

Now that the RAM is working, the hardware part is finished. It is good that I don't have anything else to add since all of the microcontroller pins are taken up. In fact the input shift registers for the SRAM and keypad share the same latch since it is unlikely that they will ever be used at the same time. If I need anything else I will have to use the two remaining bits in the keypad shift register (the keypad only has 6 rows and the LCD only needs 5 bits) or add another shift register. Now I can focus on the programming and worry about hardware again when it is time to make a circuit board. Here is what the hardware looks like now:

Thursday, May 30, 2013

RPN Scientific Calculator: Keypad

The next step of the hardware for my calculator is a keypad. I finished this several weeks ago but I haven't posted anything about it because I didn't have any pictures until now.

As you can see, the construction is pretty simple. My local shop had a new kind of perfboard that I wanted to try. It seems to be a little stronger than the kind I used before but still not really stiff like some of the high quality ones I have seen. It took some time to solder this together but it worked well in the end. Only one button connection had to be resoldered.

The circuit is a standard button matrix. A signal is sent through each of the green lines in turn and if any of the buttons are held down the signal will travel out of one of the yellow output lines and be recorded. Each button has a diode to ensure that the signal can only go one way. As you can see from the back side of the board, the columns are connected by solder and the rows by yellow jumpers. After I had soldered most of the columns, I realized that the two legs on each side of this kind of button are connected internally and don't have to be soldered together. The next time I make a button matrix I will leave them unsoldered so I will have room to make the rows out of solder as well. Avoiding jumper wires like I used here will make soldering simpler.

To read the matrix I am using a 74HC165 and a 74HC595 shift register. Output shift registers can easily be chained together but I also found out that an output and input shift register can be chained together as well sharing the same data, clock, and latch lines. Here I decided to use separate latches since the 165 is reading the output of the 595 but they do share data and clock lines which uses less microcontroller pins

Most of the time the shift registers will go unused since scanning the matrix only takes a fraction of a second. To save even more pins I decided to drive the LCD using the 595 shift register as well. This works out as long as communicating with the LCD and reading buttons never overlaps. I will have to take this into consideration if I decide to use an interrupt to read buttons. This also fixed a strange and unsolved issue that would occasionally cause the LCD not to receive commands when it was being driven directly by microcontroller pins.

Saturday, May 18, 2013

RPN Scientific Calculator: Multiplication

The next step of the software for my calculator is multiplication. In Binary Coded Decimal (BCD) this is fairly straightforward. Every decimal place of the first number has to be multiplied by every decimal place of the second number. The tricky part is keeping the results lined up and then putting the decimal point in the right place at the end. Here is an example running on the MSP430:

One advantage of BCD is that it avoids the rounding errors that occur in floating point calculations. This quickly becomes apparent when you start multiplying decimal numbers. Even in this example using fairly small numbers there is a rounding error:
Floating Point:
835.2533 x 907.042 = 757609.823739

Binary Coded Decimal
835.2533 x 907.042 = 757609.8237386
For most uses floating point offers enough precision but a scientific calculator should be as accurate as possible, so BCD is a better choice.

While working on this I was able to find a bug in my code for addition and fix it. I also added a function to shift numbers one decimal place so they will be aligned properly for multiplication. This routine is sometimes necessary since each byte holds two decimal numbers. Routines like this take up space in Flash, which is limited to 16K on value-line MSP430s. One way to avoid having to shift numbers is to let each byte represent one number instead of two. Although this would use twice as much RAM, it would simplify programming and use less space in Flash. This is what I will do if I run out of room for the firmware. Right now I plan to use 128K parallel SRAM chips from Alliance, so running out of RAM wouldn't be a problem. (Of course 8k of SRAM would have been enough but I don't have any of those with me.) Another option would be to write all or part of the BCD routines in assembly. This would help a lot since the MSP430 has an op-code to add BCD numbers. It also handles carries natively which is more efficient than storing it in a variable and checking it explicitly like my code does now. Currently, the program is only 3.3K including the part that handles the LCD. How much I can fit in the remaining Flash will determine what changes I make.