Showing posts with label RPN Scientific Calculator. Show all posts
Showing posts with label RPN Scientific Calculator. Show all posts

Sunday, December 27, 2015

Makevention 2015


Makevention went really well! I was able to show everything I have been working on, although I didn't have time to finish everything. I made a poster board explaining some concepts related to calculators like RPN, BCD, and CORDIC on the left side with information about my RPN Scientific Calculator on the right. I also had a print out of how my external RAM preprocessor works. A few of the people who came by my table were programmers and understood the solution.

On the table itself I had different calculators and projects laid out in roughly chronological order. The first was an MK-61 RPN calculator I added to my collection over 10 years ago. Of course I didn't make it but I wanted to show an example of an RPN calculator and what inspired me to first make calculators. When I first got the calculator out to test it, it didn't show anything on the screen and I was afraid it was broken. I took it completely apart and looked for burst capacitors. I also brushed off the battery contacts since they didn't look very clean. When I turned it on, it still didn't show anything but when I pressed a number it showed up! It seems the calculator just doesn't display anything when first turned on, instead of the zero I was expecting. Somehow I had forgotten that in the 10 years its been since I last used it.

The Casio Algebra FX 2.0 was included to show the RPN stack program I wrote for it in 2002 or so. That program was designed to make the calculator function more like the HP-48GX I had at the time which I admired so much. First, I had to buy a calculator to replace the Algebra FX 2.0+ I sold in college. Loading the program onto the calculator took quite a while to figure out! In 2002 I used a serial cable, which I think was an SB-87, to load programs without any trouble. Nowadays I don't have a serial port, so I bought an FA-124 USB cable. It turns out that this cable doesn't work on Windows 7. I also couldn't get it to work correctly under Windows XP running in an emulator. Next I tried a lot of different third-party software and finally got the program to load using FlashCOM 1.4v and an FTDI cable. For the link port I bought a 2.5mm plug that I could easily wire to the FTDI cable. After that, the program I loaded kept crashing and I thought the transfer was corrupt. After more fiddling I got Turbo C up and running in an emulator and compiled the program source myself, which produced a fairly stable program that was good enough for exhibiting, although it did crash a couple times during Makevention. Someday I would like to fix the program up and make it more stable.

The next thing I showed was a launchpad hooked up to a breadboard with a button and blinking LED to show how easy it is to get started with electronics. The next step was my binary LED calculator. I soldered a coin battery holder on to the board. After that I showed the RPN Scientific Calculator and explained that it was not too difficult to move to this stage after I managed to finish the binary LED calculator. The Programmable RPN Scientific Calculator was next. I printed temporary a colored keypad on poster paper which I taped to it, but it did not work very well. Unexpectedly, the calculator showed random keypresses when I put my hand near it. All the keys were in the same column on the keyboard, which makes me thing there is a bad connection in that row of the key matrix.

Next I showed the Improved 6502 Virtual Trainer up and running on my laptop, along with the first 6502 Virtual Trainer. I also showed what I had accomplished with the 6502 graphing calculator. So far, I have most of the hardware for it installed but I am having problems keeping the buffer chips for driving the LCD at the appropriate voltage level. Maybe the pins joining the sections of the calculator together aren't making a good connection. In any case, I showed the calculator taken apart into its sections. I also showed the Logic Tool I have been using to debug the graphing calculator and the EEPROM programmer I built. The last thing I showed was the TI-86 I bought to hook up to an ESP8266. My plan was to relay text from the calculator over WiFi to a computer running Matlab or similar software to allow the calculator to solve more complex equations. I still haven't gotten the ESP8266 voltage levels to work right, but I want to finish this project when I have time.

All in all it was a great day and I really enjoyed showing the public all the things I have been working
on.

Thursday, December 24, 2015

RPN Scientific Calculator on Hackaday

In August my RPN Scientific Calculator was featured on Hackaday in Hacklet 70 - Calculator Projects. It was really great to see my project on Hackaday! There was also a small scientific calculator running a 6502 emulator, a KIM-1 replica with a calculator form factor, and a project called CalcHack that adds functionality to TI graphing calculators. CalcHack is an awesome idea and one thing it adds is a 2.4GHz radio. One of my ideas for Makevention was adding an ESP8266 to the inside of a TI-86, but this solution is much better! Hackaday also created a page for calculator projects where I added my RPN Scientific Calculator, Improved RPN Scientific Calculator, and 6502 Graphing Calculator.

Monday, July 6, 2015

2015 Hackaday Prize

Hackaday recently started a competition for projects that feature parts made by Atmel, Freescale, Microchip, or Texas Instruments. 50 prizes are being awarded for each group, so I entered my RPN Scientific Calculator into the TI competition. The winners were announced today and my project was one of the 50. My prize was a Bluefruit LE Sniffer, which I was able to order from the Hackaday store for free. I'm not sure what I will use it for yet since I don't have a smart phone. My project page for the calculator is here.

Sunday, March 1, 2015

RPN Scientific Calculator: Keypad

The last part of my RPN Scientific Calculator is the keypad. Before, I had considered trying to make individual key labels somehow. If I could print them on something like the material credit cards are made out of, I could cut them up and glue them to the keys. In the end, gluing on 42 labels without getting glue inside any of the buttons sounded daunting. Instead, I was able to make one out of stamp rubber on the laser cutter at our hackerspace. It turned out really well and I was able to paint the buttons different colors. At this point, there is nothing left to add, so I consider the project totally finished.

Thursday, November 27, 2014

Progress Report (Sort Of)

So I have not updated my blog in a while. Grad school is keeping me pretty busy. Most of what I do with electronics now is related to the local hackspace I joined. I was able to use some tools there to shorten the bolts for the case of my RPN Scientific Calculator and I also have access to a laser cutter and 3D printer that I eventually want to use to make keys for it. One of the members there and I decided to start on a project together. We have not made enough progress yet to post about but we did finish a schematic of what we plan to do. For this we have both EPROMs and EEPROMs. The EPROMs have a small window and can be erased with UV light, though the lamp we have does not seem to be working. They would also need a higher voltage source to write them and I want to make a voltage multiplier when time allows. If I can get that working, it might also help me with another project that needs -27 volts for LCD contrast.

Another neat thing I have experimented with at the hackerspace is the Spark Core. One of our members was able to get a hold of several of these for us. These tiny little boards let you connect a microcontroller to Wi-Fi pretty painlessly. This would work really well for a project idea I have that I have not started on yet. One thing I don't like is the Arduino-like environment used to program them with but I think I could get used to it since I would probably use my own microcontroller for everything but Wi-Fi. Another idea would be to simply use the CC3000 chip the board uses without the Spark Core board, though that may be too complicated to be worth it. It seems that the newer Spark Photon uses a different chip which could be easier to use by itself, though Spark Photons are not scheduled to ship until March.

One thing I have been working on on my own is a sombrero with LEDs. It was supposed to be part of a Halloween costume, but I did not finish it in time. Each color (red, green, and blue) is soldered as a 4x4 matrix that has its own shift register. It might have been possible to solder all 48 LEDS (16 each of red, green, and blue) as a 6x8 matrix and use one less shift register, but this way lets me keep each LED on three times longer. NeoPixels would have worked well for this project but just one of them costs almost as much as all of the LEDs. The board for controlling everything is finished. Now all the LEDs just need to be sewed to the sombrero and the firmware written to control their flashing. In order to save time I only soldered buttons to the board for controlling the patterns of the LEDs, but I do have some nice potentiometers I bought that I now have time to use instead. Reading their value with an MSP430 worked great on the first try and I displayed it on my one wire debug display.

Tuesday, May 13, 2014

RPN Scientific Calculator: Case

After a few months of work, the case for my calculator is finally finished. Back in January I made a post with a picture of the clad I soldered together for the case. My plan at the time was to stuff all of the internals of the calculator into the case over the course of a few days but it ended up taking much longer.


The first hurdle was figuring out how to attach the front and back plates to the case. In the end I settled on epoxy. The first one I tried was still oily after 24 hours and did not hold very well but a much cheaper one held extremely well and I used it to glue four bolts to either side of the case body. Oddly enough the epoxy turned the clad green pretty quickly. From there I made holes with a box cutter in the front and back pieces for the bolts. Cutting out the hole for the keypad and LCD in the front piece of clad with a box cutter and wire cutters was a real chore and I don't plan on working with clad ever again without something like a dremel. For spacers between the clad and components I used rubber erasers.


These are cheap and easy to work with. My only fear is that they may dry out and crack someday. At first I tried gluing one of the plastic battery holders to an eraser with epoxy but surprisingly the bond was very weak. Super glue worked very well, though, and I glued in more erasers to hold the LCD, PCB, and keypad in place. All of that added a noticeable amount of weight to everything. The front and back pieces also have erasers glued to them to help hold everything together.


There was not enough room to comfortably route the wires from the LCD and keypad to the PCB so I desoldered them and used Cat5 cable instead. The wires inside are much smaller and easier to work with. It is also possible to leave the individual wires inside the Cat5 cable to make routing neater and I did this for some of the keypad wires. After assembling everything it worked fairly well except the keypad buttons were hooked up upside down. This was easy to fix in software and I loaded the new version using the programming pins soldered to the PCB without having to take the PCB out of the case. There was another bug that caused the calculator to freeze after pressing escape. For some reason the program was going into sleep mode when I pressed escape. I must have added this during debugging but it does not make sense at this point.


The next step will be to add some sort of labels for the keys and then paint it if I decide to.

Friday, January 31, 2014

RPN Scientific Calculator: Hardware

In the last two months I have made a lot of progress with my calculator. The software is now finished. As well as cleaning up a few bugs I also added a battery meter to the settings page. There was enough memory on the external RAM for two separate stacks with 200 levels each. All of the code is now on a GitHub page: https://github.com/druzyek/RPN_Calculator.

For the hardware I soldered everything on to perfboard. It didn't power up the first time I plugged it in but after fixing one power connection everything started up and worked fine. Here is a picture:


For the power supply I am using 4xAA batteries with an LM1117 adjustable regulator. My local shop didn't have the resistors I needed to get 3.6v from the regulator so it is running closer to 3.5v. On the left side you can see female headers for the keyboard outputs to be plugged into and on the lower left a repurposed DIP socket for the LCD and keyboard inputs to be plugged into. The red, white, and blue wires were the smallest single strand gauge one store had and worked fairly well. When I ran out of that I switched to an even smaller gauge (the brown wires) I got form another store and it was even more convenient. It works so much better than breadboard wire and I definitely plan to use it again. If you look closely you will see two pins for power so that the whole board can be powered from the LaunchPad if needed. Each MSP430 also has its own set of programming pins so that they can be programmed in circuit. One strange thing I noticed on this project is that solder will sometimes spill through the holes and onto the other side of the board. This may be because the smaller gauge wire lets the solder through more easily. One problem I had while testing the connections were two adjacent socket pins that seemed to be bridged, even after desoldering everything around them. After removing the socket itself, I saw that a drop of solder had flowed to the other side of the board and shorted the two legs in the space between the board and the socket.

Here is everything connected and running:


 Here is a circuit schematic of the whole system:


For the case I soldered together some clad which I was able to get really cheaply. It feels pretty solid. It needs a coat of paint and I need to adjust the holes in the faceplate for the keyboard and screen. Here is what it looks like so far:


As was my goal, I submitted the project to the Project of the Month Competition at 43oh.com. Thankfully it was extended an extra month so I had some time to finish most of what I wanted to finish. Voting starts tomorrow!

Friday, November 29, 2013

RPN Scientific Calculator: Update

As I mentioned in the last post about this project, I added a second MSP430 because the firmware was getting too large. In the end hardware UART turned out to be a good choice for communication between them. It works very fast and is reliable. The first MSP430 is responsible for reading the keyboard, controlling the LCD, handling the interface, and performing checks such as division by zero before passing on the addresses of the values  to be calculated to the second MSP430. The firmware for the first chip comes to a little over 13KB. The second MSP430 does all the actual calculating since it is connected to the SRAM. Its firmware is about 10KB.

The software part of this project is almost finished. One thing I added was a settings page. The accuracy of calculations can be set anywhere between 6 and 32 decimal places. There are also options to use scientific notation and switch between degrees and radians for trig functions. The only things left to add are a battery meter and support for two stacks. A second stack is not really necessary but as it is now, only one half of the 128KB SRAM is usable since the 17th address pin is not hooked up. I plan to add a button so that the second half of memory can be used as a separate stack.

Although I planned on adding programming features at the beginning, I may not have time. The 43oh forum is having a project of the month competition I would like to enter this project in and I will need to hurry to finish putting together the hardware and making a case for it. If there is time left at the end of the month I may add a simple key stroke programming mode. It is a little disappointing that I did not get to this but on the other hand, it is convenient to have a firm end to this project. It would be easy to keep adding features but even now I feel like I have stretched the project beyond what the hardware can reasonably handle. I have plans for other calculators that will be programmable but they will use a more powerful chip than the MSP430G2553 and they won't use SRAM controlled by shift registers.

One change I made to the hardware was to use a different LCD. The new LCD is also 20x4 but it was much cheaper. The old LCD was quite expensive and I would like to keep using it rather than commit it to this project. The new LCD is 10cm wide instead of 8cm like the old one so I decided to turn the keypad long ways to save room. Here is the layout I plan to use:



Sunday, September 8, 2013

RPN Scientific Calculator: Second MSP430

The next step for the calculator is the interface. The code for handling input ended up being fairly long but now entering numbers works as well as the basic math functions. A lot of flash space was taken up by the mathematical checks that must be done with trig functions to convert them to useable forms and ensure that they are within a valid range.
 
At this point the firmware took up about 14KB, which is close to the 16KB I have to work with. There probably isn't enough space left to add all of the functions and accompanying checks so I decided to add another MSP430. This will give me more more space but also make things more difficult since I will have to coordinate communication between the two. Moving to another chip with more Flash would be an option but I have plenty of MSP430s on hand and I don't want to move chips now that I have everything working well together.

Since I only have one LaunchPad I had to program the second MSP430 on a breadboard. This is pretty easy to do. The LaunchPad has jumpers on the RST and TEST lines where the programming signals can be diverted and used elsewhere. In this case they go to the breadboard, and a dip switch is used to select whether the programming signals go back to the LaunchPad or to the breadboarded chip.

With two chips I have a lot of left over pins. This let me eliminate the read and write shift registers used with the SRAM. The data port is now connected to one whole port of the second MSP430 instead and should work a little faster. The next step was to establish communication between the two chips. Using one pin for data and another as a clock signal, I was able to do some simple data transfers. Unfortunately this caused an error, usually after several thousand successful transfers. It's not clear whether the error was caused by hardware problems like breadboard crosstalk or if there was a timing error of some kind in my code. My plan now is to use hardware UART between the chips instead. Hopefully this will be more reliable.

There are now also enough pins to drive the LCD directly instead of using a shift register. When I tried doing this before with a 16x2 LCD it worked well but at some point in the project it began to randomly stop working. In retrospect I think it may have started after adding some of the other components to the project. In any case, sending signals to the 20x4 LCD from the LaunchPad does not work at all. This problem will have to wait until I can replace my broken multimeter and test all the voltages involved.

Saturday, August 17, 2013

RPN Scientific Calculator: Tweaks

Recently I was able to get some new components and took the chance to make a few tweaks to the calculator. First of all, I hooked up a new 20x4 character LCD to replace the 16x2 version I was using before. It is gray with black letters and I like how it looks. With this I will be able to make the bottom row of the screen a menu like the kind some of the later HP calculators use. The LCD itself came with male headers so it can be plugged into a breadboard, but there was no convenient place to put it so I decided to run wires from the headers to the breadboard instead. The LCD worked fine at first but quickly became corrupted after I wound the wires into a loop to make them neater. This was causing crosstalk and the problem disappeared when I separated the wires.

I also added a CMOS 555 timer to generate the negative voltage for the LCD. This frees up a microcontroller pin that I am now using to independently drive the input shift register of the RAM. Now I can read the external RAM and the keyboard at the same time without worrying about coordinating interrupts. In order to save energy I decided to use the smallest capacitor and the largest value resistors I could for the timer. Unfortunately, none of the resistor values I had on hand would give me the 30 Hz or so the microcontroller was generating. 48 Hz was the closest I could get using a 0.1 uF capacitor and 100k ohm resistors for R1 and R2. Adding a 470 ohm resistor to the output of the 555 gave a good contrast and should also keep the contrast constant if I try to run everything from a battery later.

The last thing I did was to expand the CORDIC tables to 32 bits wide instead of 16. Using a 16 bit wide table gives around 14 decimal places of accuracy which is sufficient for calculating logarithms. A problem arises, however, when that logarithm is used to calculate things like exponents because those 14 places of accuracy also include the whole part of the answer. A simple calculation like 8^9 only offers 5 decimal places of accuracy after the decimal since the whole part is 9 digits long. The new version takes about 6 seconds to calculate "atan(tan(37))" This is very slow so I will let the user set the precision in settings.

Monday, July 29, 2013

RPN Scientific Calculator: More CORDIC Routines

After finishing the CORDIC routine for logarithms I started on the CORDIC routine for trig functions. For this I needed a different look up table and a different function, but it didn't take up much room in the flash. The table for pre-computed logarithms is stored compactly in flash and the same routine that unpacks it into the external memory is also used to unpack the trig table. With this I can calculate sine, cosine, tangent, and arctangent. It should also be possible to calculate arcsine as well but I haven't tried yet.

To test these new function I tried calculating atan(tan(37)). When using 16 decimal places for the calculations this gives the answer 36.9999999999999781, which is pretty accurate. Unfortunately, this took over two seconds, which is just too slow. The logarithm and powers of e functions were at least twice as fast. In order to speed things up I tried to eliminate as many reads and writes to the external memory as I could. One thing I didn't notice when I wrote the original functions is that the loop condition for a for loop is recalculated each iteration. When the condition depends on a variable in external memory, the variable is fetched on every iteration, which is wasteful if the variable hasn't changed. After changing the code to use local copies of external variables whenever possible, I was able to cut down external memory access by almost 25%.

25% wasn't quite enough so I looked at the code I was using to right shift. This allows me to divide numbers by 2 quickly but takes some extra coding since shifting in BCD is a little more complicated than a normal binary shift. Because of the extra work involved in keeping everything straight during BCD shifting, I was doing shifts one bit at a time. This means a 58 bit shift, for example, would simply do 58 shifts of 1 bit each. As you can imagine this is not efficient and was a big part of the slow down in the code. My solution was to use as many 4-bit shifts as needed, then a few 1 bit shifts at the end to finish it off.

Shifting by 4 bits in BCD is fairly easy. As you probably know, shifting by 4 bits is the same as dividing by 16, and dividing by a number (16 in this case) is the same as summing the results of dividing each decimal place by that number. Since there are only 10 possibilities (0-9) for each decimal place, I stored the results of dividing each possibility by 16 in a look up table and used that to sum the results. Here is an example:

789 ÷ 16 = 700/16 =   4375
                  80/16 =     5000
             +     9/16 =      5625
                               49.3125

The values 4375, 5000, 5625, etc are stored in the look up table. The sum of these results are stored in local RAM since 6 bytes is enough to keep track of the summing long enough to deal with any carries before finally writing the last byte to the external RAM. Doing it like this I only need to read and write every decimal place once per 4-bit shift. This cuts down the number of external memory accesses down to almost one third of what it was at the beginning and allowed me to calculate atan(tan(37)) in a little over a second. All of this fits in 8.1K of Flash meaning I just broke the halfway mark of what the MSP430G2553 chip I am using can hold. If there is any space left over at the end, I would like to implement a similar 8-bit shift routine as well to speed things up even more.

Wednesday, July 10, 2013

RPN Scientific Calculator: Division and Logarithms

After rewriting the multiplication function I started on the division routine. There are several ways to do this. I used the subtract and shift method. It takes up a little more than 150 lines of code which makes it about twice as big as the multiplication routine. Unlike with the other operations, with division a maximum number of decimal places has to be specified. It seems unlikely that I would ever need more than 16 places, which makes me think a fixed place format might have worked too. This is still possible if I need to shrink the program size.

The next step is to implement logarithms and powers of e. This will be useful on its own but will also let me calculate powers and roots. One way I found to calculate logarithms is with a Taylor series like this: 

ln[(1+x)/(1-x)]=2(x+x3/3+x5/5+x7/7+....)

This seems ideal since it only requires one loop and several multiply and divide operations which shouldn't take up much room in Flash. Even with the the MSP430 running at 16MHz, it rook over 3 seconds to calculate ln(7). In an effort to speed things up I examined the code for multiplying and dividing but didn't find much to improve. One thing I did change was the addition routine. I was adding a 0 to the beginning of every result so that there would be room for a 1 if I needed to carry. However, in most cases the 0 wasn't needed and when doing repeated additions during multiplication, the 0s accumulated at the beginning of the result wasting memory. Removing these 0s wasted time so I changed the addition code to only add the 0 when necessary. This still didn't make it much faster, though.

Next, I ran the code on my PC and noticed that it needed to access the external memory over 2 million times to calculate the logarithm to 16 decimal places. Clearly this was the bottleneck. The next idea I tried was the CORDIC method which is ideal for small microcontrollers like the MSP430. This uses a precomputed table and only needs adds and bit shifts, two things that microcontrollers can do much more efficiently than multiplying and dividing. Using this method I can calculate e^x and ln(x) for a wide range of values in less than one second because it only needs about 50,000 accesses to the external memory.

After I finished the ln function but before I started on the e^x function, I noticed that the program was already 6.5k. This is a little concerning since 16k is the max size for the program and there are still many more features to add. One thing that can reduce size is the static keyword. Making all my functions static shrunk the program size down to only 3.7k. After adding some more entries to the CORDIC table, improving the ln function, and adding the e^x function, the program size was back up to almost 6.5k again. This seems very strange since the program is now almost 1,000 lines and the ln functions only takes 50 lines. In fact commenting out the ln function reduces the program down to only 4.4k. Why this one small function should suddenly add more than 2k to my code is not clear but I hope to figure it out soon.

Wednesday, June 12, 2013

RPN Scientific Calculator: Software Update

Work continues on my calculator. Each byte of a BCD number now holds only one digit instead of two. This eliminates the functions that were needed to align and pad numbers when every byte held two numbers. It also makes calculations a little simpler and reduces the amount of space the functions take up in the Flash.

Another improvement is that arrays can be stored in the external SRAM and accessed similarly to how internal memory is accessed. To read or write anything to the external memory a function has to be used. That means a simple equation like this:
X+=Y*Z-Q;
would become this if those variables were stored externally:
 RAM_Write(X,RAM_Read(X)+(RAM_Read(Y)*RAM_Read(Z)-RAM_Read(Q));
This is difficult to decipher and inconvenient to use when writing code. My solution was to make a small program that preprocesses the source code and replaces any variables that should be stored externally with their corresponding read and write commands. These variables are marked off with #pragma directives. #pragma is a note to the compiler to do something special that may be specific to that compiler. If the compiler doesn't recognize the directive, it is ignored. Here is an example of what the preprocessor would do.

This is unprocessed code:
void puts(unsigned char *msg)
{
     #pragma MM_VAR msg
     for (int i=0;msg[i];i++) putchar(msg[i]);
}

int
main()
   
     #pragma MM_OFFSET 200
     #pragma MM_DECLARE

     unsigned char text1[30];
     unsigned char text2[30];
     #pragma MM_END

     text1[0]='A';
     text1[1]=0;
     puts(text1);
}
 This is preprocessed code:
void puts(unsigned char *msg)
{
     #pragma MM_VAR msg
     for (int i=0;
RAM_Read(msg+i);i++) putchar(RAM_Read(msg+i));

}

int
main()
   
     #pragma MM_OFFSET 200
     #pragma MM_DECLARE

     unsigned char *text1=(unsigned char*)200;
     unsigned char *text2=(unsigned char*)230;

     #pragma MM_END

     RAM_Write(text1+0,'A');
     RAM_Write(text1+1,0);

     puts(text1);

}
Arrays are converted to pointers that store offsets to the external memory. This way none of the function prototypes have to be changed. The code should work the same way whether the variables are stored in internal or external RAM. External memory can be turned off if needed to make tracking down bugs easier. One disadvantage to this is that function arguments must be either internally or externally stored but a function can't accept both types for one argument. For things that need both I will need a wrapper function. The preprocessor doesn't support all of the C standard since I only spent about a day on it. Adding support for all of the possible ways there are to access a variable would take a lot more work and I wouldn't be likely to use that functionality anyway. Things like variable names that span multiple lines or variable assignments inside of other statements aren't supported but I didn't end up using any of those features in my code.

The new code for adding and subtracting BCD numbers fits in about 2K, including LCD driving code. Using the preprocessor to store all the values externally adds another 500 bytes. The code for multiplication is also much smaller than the last version.

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.

Monday, April 8, 2013

New Project: RPN Scientific Calculator

My interest in electronics started because I would like to build calculators like the ones I used to collect. Now I plan to build a scientific RPN calculator. A three inch graphical LCD would work well for this but most cell phone screens I can easily find are a little bit too small. For the time being I will continue using the 16x2 LCD I found.

For this project I intend to use an MSP430. The challenge of this will be that the MSP430G2553s I have only have 512 bytes of RAM. To begin with I decided to start on the programming since this will probably be much more work than the hardware. Although I want this calculator to use RPN, it would also be good if it could evaluate algebraically as well like the HP-49G. It will hopefully also be useful to have a small parser that works on a microcontroller for some other projects I want to do. Here is the parser running on my LaunchPad and evaluating the equation 13*(4+25*13)/((67-33)*2^3):


 
At first I wanted to use recursion because this can really simplify parsing but that's not really an option since it would use a lot of stack space. Instead, it evaluates any expressions it can and stores the result in memory then writes a pointer to that memory in the place where the expression was. Doing it like this instead of tokenizing the whole string before evaluating saves memory. The results of operations are stored starting at the end of the string that holds the expression so that as the expression is evaluated and becomes smaller, memory is freed which can be used to store more results. So far this parser fits in about 2k of Flash.

The second part I worked on is a Binary Coded Decimal format. This will be more accurate than floating point since it will be able to store any number that will fit in available memory. Each byte of data contains two numbers from 0 to 9. Now numbers are limited to 512 digits in length but this can easily be increased, although it probably wouldn't be useful on such a small screen. I have code for adding and subtracting, so multiplication and division should be easy to implement using these. I was able to fit this into less than 2k of  Flash so with the parser I should still have about 12k of flash for other functions. Here is an example using numbers small enough to fit on the screen: