6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 2:55 am

All times are UTC




Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Jan 15, 2020 10:01 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
For my entry, I plan to build a scientific calculator. I've done some other projects working up to building a full-fledged graphing calculator with a 6502, so it should be fun to build a much reduced version that fits in only 8KB of memory. Here is the outline of what I plan as the rules require:

Software
Four-level RPN stack similar to old HP calculators like the HP-35. Calculations will be BCD floating point with precision around 10 digits. Four functions, trig, and logs will probably take up a lot of the 8KB, but if there is room (and time) left, simple keystroke programming might be possible.

Memory
Most of the 8KB range will probably be ROM with the RIOT providing some or all of the RAM. Hmm, not sure if there is a way to get the glue logic to use the RIOT as partially zero page and partially hardware stack. If the there is room left in the ROM, it might make sense to add a little more RAM to hold keystrokes for a keystroke programming mode.

Output
A screen of some sort. There are a lot of options, especially since running off a small battery is not possible anyway. HD44780 is an obvious choice but might come up with something more interesting like a VFD display. Most of the displays I've looked into like OLEDs and Nokia 1202s will probably be too small compared to how big the rest of the calculator will have to be.

Input
Keypad with 30-40 3D printed keys. Size and layout will probably mostly be determined by how big the underlying circuit board is. The RIOT has enough pins to multiplex this but might need an additional shift register since it has to drive the LCD too.

That's about it. Open to input and suggestions as the rules encourage :) Good luck!


Last edited by Druzyek on Thu Sep 24, 2020 3:12 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 15, 2020 10:47 pm 
Offline
User avatar

Joined: Fri Dec 12, 2008 10:40 pm
Posts: 1007
Location: Canada
Great start!

_________________
Bill


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 15, 2020 10:53 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
I put some tips in the Hardware forum on how to lay out the RIOT's address space.


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 25, 2020 12:24 am 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
The system now boots and runs code from an 8k EEPROM:
Attachment:
6507 calculator breadboard.jpg
6507 calculator breadboard.jpg [ 90.14 KiB | Viewed 6362 times ]
The screen is a 20x4 HD44780 type LCD I have hooked up for testing. I settled on a 128x64 graphic monochrome LCD with the same dimensions for the final project.

One strange thing is that when I power the system on for the first time on a given day, the LCD shows garbage or nothing, but everything works reliably every time it's turned on after that. It seems to be a power supply problem since it can be reproduced by unplugging the power then shorting all the capacitors. The voltage on the far side of the breadboard is close to the 4.75v minimum for the 6507, although it's a little over 5 at the power jack of the supply. Next, I'll move it to protoboard and see if the problem persists.

The address decoding is done with a ATF16V8C GAL. The datasheet shows it can take up to 130mA, so I also got some CZ and BQL variants to see if I can get away with using less current. The whole setup takes about 240mA at the moment. My current plan is to run everything off of lithium AA batteries since they can sustain high current draw without dropping the voltage as much as alkalines. I also plan to have the option to power it over USB with the help of an MCP2221A. This will enumerate as a USB device and let me draw more current and also act as a USB to serial converter. Hopefully using the timer in the RIOT is fast enough to bit bang serial at a few hundred baud.

I decided to switch from a 4-level scientific calculator to one with a simple Forth-like interface similar to some of the later HP calculators. I added 2k of RAM to support this. Stack items are 9 bytes where the first byte marks the type and the next 8 bytes are data. There are four data types:
  • floats
  • strings
  • simple hex
  • smart hex

Simple hex is a 16-bit unsigned value, so it only uses 2 of the 8 bytes. It supports the four functions and bit shifts. Smart hex is generated by using the ' or tick operator to get the address of a variable or word and only supports addition and subtraction since multiplying a pointer is meaningless. 6 of the 8 bytes are taken up with 2 for the address, 2 for the offset, and 2 for the sum of the base and offset. Storing the base and offset separately is convenient for implementing garbage collection so any word or variable can be removed arbitrarily without having to remove everything that comes after it in the dictionary. When a word is removed, all of the words later in the dictionary are moved down so there is no empty space left where the deleted word was. When they move, any address generated by ' that pointed to the moved words will no longer be valid, so the garbage collector looks for any smart hex items on the stack or embedded in words and updates the base address, then recalculates the sum of the base and offset. That way, if you use ' to get an address and add or subtract a simple hex number to address the bytes after that, the address will still be valid after garbage collection since the number of bytes added or subtracted is stored in the offset and can be added to the new base.

Entering a variable name returns the value instead of the address, and new values are stored with STO instead of using ! with the address. Avoiding pointers for normal math calculations should let me have an environment where no user mistakes can crash the calculator, although @ and ! are still available to use at your own risk.

The threading is token based to maximize the use of the 2k of RAM. One thing that hopefully saves space in the long run is a flag byte for primitives that marks how many stack items are expected and what type they should be. This lets the dispatcher do error checking and stack adjustment so the words themselves don't waste space doing it.

So far I have about 25 Forth words defined. There is support for reading and writing variables as described above, defining and executing new words, the four functions for hex numbers, and input and output for all 4 types. This takes up about 4.7k of the 8k. I still have to add deleting variables and words with garbage collection, floating point calculations, control structures, string manipulation, and serial input. My plan is to implement all of this in my simulator, which will probably take more than 8k, then try to compress the size after everything is functional. Part of this may be embedding tokenized Forth code in the assembly to save space.

Here's a short program running on my simulator:
Code:
: FOO 0.3e7 ;
: BAR 2e5 FOO ;
: BAZ 10e3 BAR ;
BAZ

: TEST $10 * $4 + ;
$123 ' TEST $5 + $7 - $2 + EXEC

"HELLO!"
Attachment:
6507 calculator screenshot 1.png
6507 calculator screenshot 1.png [ 7.56 KiB | Viewed 6362 times ]


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 25, 2020 6:11 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Excellent! And that's a really clear display you have there.


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 25, 2020 3:25 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
Druzyek wrote:
One strange thing is that when I power the system on for the first time on a given day, the LCD shows garbage or nothing, but everything works reliably every time it's turned on after that. It seems to be a power supply problem since it can be reproduced by unplugging the power then shorting all the capacitors. The voltage on the far side of the breadboard is close to the 4.75v minimum for the 6507, although it's a little over 5 at the power jack of the supply. Next, I'll move it to protoboard and see if the problem persists.
The HD44780 (especially the clones) can be fussy about startup. The datasheet (I'm using this version from SparkFun: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) on page 45 says to wait for more than 15ms after Vcc rises to 4.5V (or more than 40ms after Vcc rises to 2.7V). In my experience, several of the clones actually need longer than this, and do not initialize properly if you try to talk to them too soon (with symptoms similar to yours). I use a 100ms delay before initializing the LCD on my projects and that has worked with every LCD I have used in both 8 and 4-bit modes. A 50ms delay did not work with some cheaper displays that had glop-top ICs on the back (probably HD44780 clones).

I'm super-excited to follow your progress on this project. I have two HP48GX (RPN) calculators (one at work, and one at home) that get a lot of use, and your project looks like it will have a lot of interesting details.


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 25, 2020 9:56 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
SamCoVT wrote:
The HD44780 (especially the clones) can be fussy about startup.
Thanks for the tip! I'm actually using one from New Haven (link) that I've had good luck driving with a microcontroller before. I haven't been able to find any clones that have both the black on gray coloring and more importantly, the slim outline that would fit in a calculator. The display still has problems when I stretch all the delays to 1000ms, which makes me think it's power supply problems with the breadboard, but I could be wrong.

Quote:
I'm super-excited to follow your progress on this project. I have two HP48GX (RPN) calculators (one at work, and one at home) that get a lot of use, and your project looks like it will have a lot of interesting details.
Cool! I had an HP-48GX and eventually got 128k SRAM and 4mb EEPROM cards for it before selling it in 2005 or so. Sometimes I wish I had hung onto it. Now I have an HP-48G on my desk at work that I found on craigslist and talked the seller down to $20 on. I also got an HP-50G last year but haven't warmed up to it 100% yet. I think this project will be a little bit similar even if it has way less functionality.


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 27, 2020 8:17 am 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Coming up on a year since the contest began, so I'd like to give a little update:

The circuit is now on protoboard instead of a breadboard, so it starts reliably every time. The only thing the circuit relies on from the breadboard is the power rails. Surprisingly, even though the voltage takes a long path from the power source through the rails, it doesn't drop any voltage along the way. Running the supply voltage through a breadboard jumper wire drops 0.4v which was the problem I had before moving everything to protoboard. This must be what was keeping the circuit from working half the time.
Attachment:
6507_calculator_protoboard.jpg
6507_calculator_protoboard.jpg [ 89.92 KiB | Viewed 6087 times ]
The LCD is now a 128x64 graphical LCD instead of a 20x4 character LCD. In the picture, you can see the pins running along the top of the LCD since it's technically upside down. This makes the screen writing code a little tricky especially since there isn't room for a screen buffer with just 2k of RAM. Another challenge was getting the 6532 to output data to the LCD. The LCD Enable pin has to be raised to write but then needs to be lowered before the data bus changes since it doesn't latch on clock up like you might expect.
Attachment:
6507_calculator_LCD.jpg
6507_calculator_LCD.jpg [ 75.5 KiB | Viewed 6087 times ]
The LCD is arranged in 8 rows that are 8 pixels tall. This makes it easy to use a 5x8 font (6x8 including white space) instead of the 8x8 font above. Now all 12 digits of precision fit on the screen for floating point numbers. After posting in another thread about free fonts, I made one myself, then made a few different versions. The squarish font with thin lines is my favorite so far.
Attachment:
calculator fonts.png
calculator fonts.png [ 5 KiB | Viewed 6087 times ]
The firmware is coming along slowly but surely. Adding, subtracting and multiplying works for floats. They have 12 digits of precision with proper guard, round, and sticky digits. My reference implementation is an emulated HP-48GX. One plan to verify my calculations was to generate random floats, send them to the HP-48GX for calculation, then check the result against what my firmware computes, but I decided against that since it's not easy to get large amounts of data into and out of the emulator. Instead, I ported my javascript 6502 emulator to node.js so I can run the emulation from the command line. A Python script generates millions of float pairs and outputs them to a file which comes to about 200MB that the emulator takes in as key presses. Running the tests 24/7 for weeks probably won't shorten the life of my SSD, but I set up a RAM drive for this anyway just to be sure. The first test is a round robbin where every number on the list is added, subtracted, and multiplied with every other number on the list. Edge cases like 0 and the largest and smallest possible float values are on the list every time so they get tested with a lot of randomized numbers. The second test starts with two randomized significands and generates number pairs from them where the exponent difference goes from 0 to 16. This is good for testing addition and subtraction since the exponent difference in the pairs in the first test is usually so big you have to skip adding. The Python script also outputs the expected answer to the file so the emulator can check the result and halt if there is a discrepancy. The Decimal library in Python can be configured to use 12 decimal digits, round ties to even on calculations, and round 5 up on input, which is what the HP-48GX does. Testing in node.js is only a little faster than running the test in the browser, but it's easy to keep it minimized 24/7, and I can still use the emulator in the browser to work on the firmware while the tests run. Someday I'll try either porting the emulator to C so I can compile to webassembly and have it run much faster in both the browser and in node.js or I'll just port it to a console C program to make testing faster and leave the browser emulator as it is. Doing this randomized testing has helped me catch several mistakes, although it's not enough by itself to ensure my calculations are reliable since it can only test a very tiny number of possible calculations.

The firmware is now under 6k and hopefully will fit in an 8k ROM. Next will be division and trig and log functions then the rest of the Forth system like loops, IF..THEN, and deleting words with garbage collection. This will probably be more than 8k, so the plan is still to go back and rewrite some of the assembly in Forth once all the pieces are together. My source files are marked with tons of TODO comments in places that can be made smaller, and I made a little script to search all the files and shows all the TODOs:
Attachment:
calculator_todo.png
calculator_todo.png [ 32.39 KiB | Viewed 6087 times ]


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 28, 2020 2:27 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
That's a great looking project.

Druzyek wrote:
Instead, I ported my javascript 6502 emulator to node.js so I can run the emulation from the command line. A Python script generates millions of float pairs and outputs them to a file which comes to about 200MB that the emulator takes in as key presses.... The Python script also outputs the expected answer to the file so the emulator can check the result and halt if there is a discrepancy.... Someday I'll try either porting the emulator to C so I can compile to webassembly and have it run much faster in both the browser and in node.js....

I'm curious: does your 6502 simulator do something special that the existing Python and C simulators don't do? I'd think that for the testing you describe above it would be easier just to have Python drive py65 directly, and avoid having to write code to generate files, more code to read files, and having these huge files kicking around that make you worry about your SSD write lifetime. And if you wanted to go faster, it's not too difficult pick one of the many 6502 simulators written in C and call it directly from Python.

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 28, 2020 3:25 am 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
cjs wrote:
That's a great looking project.
Thanks a lot!

Quote:
I'm curious: does your 6502 simulator do something special that the existing Python and C simulators don't do?
That's a good question. Yes, it runs on my website, so I'll be able to upload the firmware and let you try out the calculator in your browser when I'm done with it. Also, I built it from the beginning to support bank switching which might not be easy to add to someone else's simulator.

Quote:
I'd think that for the testing you describe above it would be easier just to have Python drive py65 directly, and avoid having to write code to generate files, more code to read files, and having these huge files kicking around that make you worry about your SSD write lifetime.
Hmm, I don't see how that would be much better. You need Python code to generate the random numbers whether you use py65 or node.js to test them, and the code to read files was already built into the simulator since it's just processing the file as key presses. Out of curiosity, I just tested and it's not any faster to keep the randomized data in memory in Python than writing it to disk, so there probably wouldn't be a speed advantage to importing py65 and feeding it data directly.

Quote:
And if you wanted to go faster, it's not too difficult pick one of the many 6502 simulators written in C and call it directly from Python.
Possibly, though then I would have to institute bank switching and peripheral mapping in an existing simulator to match what I have now. It would be a lot faster to just port the JavaScript I have to C than it would be to modify someone else's project, but that's because I'm not actually a JavaScript programmer so all of my JavaScript already looks like C :)


Top
 Profile  
Reply with quote  
PostPosted: Sun Jul 18, 2021 8:44 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
You can now try out the firmware in simulation in your browser: 6507 Calculator

That page has a word list, overview, and some other info about the project.

The Forth system is complete except for garbage collection and some checks. The math words are mostly implemented too and include SIN, COS, and TAN. The arc versions of those three, logarithms and exponents still need to be added. The last feature is a simple graphing mode.

The firmware is currently a little over 9kB in simulation, so won't fit on the 8kB ROM. I have been planning on optimizing for space after I get everything working, so I think I should be able to shave off 1-2kB. The CORDIC routines especially take up a lot of space, so I plan to try implementing a register based VM for floating point values to save space. I'll try applying that to all the other math routines as well to shrink things further. I can also use the existing Forth engine to rewrite other parts of the firmware like the interface.

Please let me know if you find any bugs!


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 19, 2021 1:18 pm 
Offline

Joined: Sat Jul 03, 2021 4:25 am
Posts: 49
I'm laid up in bed with a killer migraine today so I will mess around with this and see if I can crash it or break it


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 19, 2021 3:47 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Thanks for publishing, Druzyek! I do like in-browser offerings like this.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 19, 2021 4:34 pm 
Offline
User avatar

Joined: Fri Dec 12, 2008 10:40 pm
Posts: 1007
Location: Canada
Very nice!

_________________
Bill


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 19, 2021 4:35 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Quote:
I'm laid up in bed with a killer migraine today so I will mess around with this and see if I can crash it or break it
That would be highly appreciated! There is a list of bugs on the page that might be useful.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 18 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: