The system now boots and runs code from an 8k EEPROM:
Attachment:
6507 calculator breadboard.jpg [ 90.14 KiB | Viewed 6361 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 [ 7.56 KiB | Viewed 6361 times ]