Sunday, December 31, 2023
IRC Forth Chatbot
Sunday, January 29, 2023
6507 Graphing Calculator: Forth Virtual Machine
As my last post explains, my goal for 2023 is to finish enough projects to give a presentation at HHC 2023. One of the biggest jobs will be finishing the 6507 Graphing Calculator I've been working on the past few years. The latest stage of the project was rewriting part of the firmware in Forth to save space, which turned out to be a failure.
When I last worked on this project, the firmware had reached 9.3K which well exceeds the calculator's 8K EEPROM. This wasn't so concerning since it seemed plausible at the time to implement a tiny Forth core and shrink the firmware by rewriting parts of it in Forth. Also, some parts of the existing firmware, which is all written in assembly, could be improved to save space. With this plan in mind, I started implementing a preprocessor in Python that scans all of the project's assembly files for Forth code and converts it into bytes to embed in the assembly source code. The Forth core uses token threading so each Forth word in the source produces just one byte rather than two as in direct and indirect threading or three with subroutine threading. The Forth system is initiated with a BRK instruction which jumps to the software interrupt handler and begins interpreting the bytes following the BRK. This saves two bytes for every invocation of the Forth system over using JMP or JSR. One of the tokens in the Forth system is assigned the same number as the BRK op code and increments a counter when executed. A corresponding token at the end of each function decrements the counter and switches from Forth back to assembly when the counter reaches zero. With this setup, the program can jump from assembly or Forth to a function written in Forth and continue executing seamlessly.
Tuesday, January 4, 2022
7400 Logic Calculator: Project End
What to keep
Control signals in instructions
Like most other TTL computers, this one used an EEPROM to store the microcode controlling the state of the components in the system. Since the instruction byte is just an arbitrarily assigned index into a lookup table, I also encoded information in the instruction itself. This let me save room in the design and is part of how everything fit into one microcode EEPROM instead of two.
Work on both sides of the clock
An inverted copy of the clock signal latches values where necessary so that state changes in the circuit when the clock signal goes up and is latched when it goes down. This is simpler than trying to coordinate machine cycles like a Z80 or 8051.
Separate RAM and program memory
As tempting as it is to build a Von Neumann architecture where addresses can refer to RAM or ROM, it's simpler to keep the two types of memory apart.
What to change
Move from 8-bit to 4-bit architecture
This is the biggest change since it affects a lot of the other aspects of the design. It will hopefully require fewer chips and simplify some things. In the old design, for example, there were four 74HC670s that form two sets of four registers for a total of eight 8-bit registers. In the new design, one 8-bit latch should be enough to hold two 4-bit registers. This is also a good register size since the BCD numbers a calculator uses are divided into 4 bits for each decimal place.
Simplify design
The old design was up to over 30 chips without being finished. Space on the two protoboards I planned to put the chips on was starting to get really tight. The new design should be simpler since it only uses 4-bit registers and also because I have some new ideas for reducing the chip count like using pull ups to eliminate a lot of buffers. For example, to load immediate values into one half of the 8-bit latch that holds the two 4-bit registers, the immediate value can be encoded in the instruction and fed to the data bus with pull ups. Z-stating everything that can drive the data bus and loading the latch will load the immediate. The other 4-bit half can drive the other four bits of the data bus so the load retains the value in the other half of the latch. Another idea is to use pullups to the RAM address bus driven by the bits of the instruction to refer to eight or 16 bytes of RAM that can be used like registers.
Arithmetic Logic Unit (ALU)
My plan to use a DIP8 EEPROM as an ALU was something novel about the old design but at the same time also what held me back from finishing it. The EEPROM I found had 4MB of storage, so it could hold 64 tables 8x8 in size. Adding a carry bit, this would mean 32 ALU operations which is definitely enough to implement what I was planning with the calculator. Carry could also serve to refer to different instructions in cases where it isn't used, such as multiply and divide, so the practical number of instructions would be much more than 32. The problem with this setup is getting the 22 bits of information needed for every ALU operation into the EEPROM efficiently along with the eight bits or more needed to put the device into read mode. One idea was to run a second clock eight or 16 times faster than the main clock and use that to clock data into the EEPROM, but I could never figure out how to get the two systems to cooperate while running at different speeds. Also, this setup would require extra latches and shift registers which would probably negate any space savings from using the EEPROM in DIP8. The new design will use a 32KB EEPROM. With eight bits for the two 4-bit registers and one bit for the carry bit, there will be room for 64 ALU operations.
There are a few aspects of this that I haven't figured out yet. One is how to handle the carry bit. The 8-bit latch holding the two 4-bit registers will drive the ALU and also receive it's output, so in the case of addition, one half will contain the sum and the other half will contain the carry. From there, there needs to be some way to record the carry bit since it will be overwritten when a new value is loaded into the register. The easy way is to add a latch to capture the carry, though I hope I can devise something that doesn't add to the chip count like having that latch do something else useful with the other seven bits.
Another interesting advantage of using an 8-bit latch to hold both registers that feed the ALU is that the latch can load an 8-bit address value from ROM or RAM and increment it with the ALU without having to do it in two 4-bit halves. The problem with this is that the ALU output is only 8-bits so there is no room to record the carry output which would be needed to increment a 16-bit pointer. One solution is to keep the 8-bit value in the latch and test if it's zero to know if it overflowed. Another idea is to have a separate bit fed to the ALU so that operations can have a second 8-bit output when needed as in this case with the carry bit. The advantage of this is that 4-bit operations could also have a carry output without trashing one of the two 4-bit registers to hold the carry.
Microcode changes
The old design embedded microcode directly into the program ROM in order to reduce the number of microcode ROMs from two down to one. This made some instructions balloon to many bytes. In retrospect, I don't think even a simple scientific calculator would have fit into the 8KB EEPROM I was using since the encoding was so inefficient. The next design will use a more traditional setup without microcode steps in the program. I'm still trying to think of ways to get away with only one EEPROM for microcode. One idea is to store two 8-bit values on the EEPROM for each microcode step and add a second latch to output the second byte every instruction cycle.
Program Counter (PC)
The program counter is another area that proved to be more difficult than I imagined. For one, connecting three 4-bit counters is a huge amount of wiring and only allows for an 8KB program ROM. Unfortunately, as I mentioned in a previous post, there are no readily available 8-bit counters that can be loaded with an arbitrary value. One simplification is to use two 4-bit counters and an 8-bit latch to allow a full 64KB address space. This would require the last instruction in every 256 byte page of program space to change the 8-bit latch to the next page. The assembler could insert those instructions in the background without the programmer needing to worry about them.
Voltage
The old design used a mixture of 3.3v and 5v since the EEPROMs all need 5v while the DIP8 EEPROM for the ALU needed 3.3v. The next time around, I plan to keep everything the same voltage if possible. Hopefully, this will eliminate the HCT parts I was using for managing level translations.
Simulation
Building this type of TTL computer in a simulator is one of the most fun parts of these projects. The last time, I used Atanua to simulate part of it. Unfortunately, I found a major bug in one of the counter chips that would be used for the program counter. The author of Atanua responded to my email reporting the bug but was not helpful in fixing it since he no longer maintains Atanua. There are also useful chips like the 74HC670 that aren't simulated in Atanua, so I think I would try making my own TTL simulator next time. This would be quite a lot of work which is part of my hesitation to jump back into this project.
Miscellaneous ideas
There are a few other interesting things that might be useful for this project that I haven't found a place for yet. The 74HC670 that I was using for registers before is an amazing chip that I don't have plans for in the new design. Implementing some type of bank switching for the RAM or ROM using this might help reduce a chip or two, though there would have to be a way to set it without adding extra chips.
Another interesting observation is that a latch holding eight bits of an address plus four more bits encoded in an instruction would let me specify 12 bits which is enough to address 4KB of RAM. Since 16 bytes can hold a BCD floating point number, memory could be split up into 256 chunks 16 bytes in size. This could shrink the SRAM addressing mechanism to just one 8-bit latch. The problem is that encoding the lower four bits in the instructions means there is no flexibility to loop through the 16 bytes programmatically, so a different mechanism would be needed for when that's necessary.
Monday, January 3, 2022
TI-86 Battery Discharger
In 2015, I got an ESP8266 with the hopes of using it to connect a graphing calculator to the internet. The plan was to swap the four 1.5v AAA batteries in a TI-86 for two 3.6v 10440 batteries and use the space freed up in the battery compartment to house the ESP8266. The TI-86 would have acted as a terminal to more powerful mathematical software like Mathematica or Matlab running on my computer. My last post mentioning this project was about Makevention 2015 and explained that there were power supply problems running the ESP8266 on a breadboard. Since then, this project has been on the back burner.
While I haven't done anything with the ESP8266 since then, I did put batteries in the TI-86 this past year so it would be ready to use if I ever wanted it. When I turned it on, the screen was solid black. This happens sometimes with new batteries when the contrast is set too high after being increased over and over as the last set of batteries decreases in voltage. This time, adjusting the contrast down didn't show any noticeable change. After a few minutes of letting the calculator run, the contrast decreased gradually until the text on the screen was visible. This was really puzzling behavior.
Searching the internet didn't turn up much for calculators that malfunction with a dark screen. While trying to troubleshoot the problem myself, I checked the voltage of the batteries with my multimeter. In all of my calculators, I have Lithium AAAs since they don't leak and damage the calculator the way alkalines can. The voltage of the AAAs in the TI-86 was around 1.8v, far above the 1.5v nominal voltage of a AAA and the 1.6v of new alkaline AAAs I've measured. After letting the calculator run a while until the text on the screen became visible, I measured the battery voltage again and it was over 1.6v. It seems the voltage drops as the calculator runs which eventually lowers the contrast, so I decided to build a circuit to discharge the batteries down to the optimal point for the contrast.
The discharger I built uses an MSP430 to switch an NPN transistor that bleeds the batteries for one second at a time through eight parallel 1/4W resistors. After each one second discharge, the MSP430 takes an ADC voltage reading from a resistor divider that lowers the battery voltage down to the range the MSP430 can safely measure. The MSP430 then displays the ADC voltage read, the calculated voltage of the batteries, and run time on a very small OLED. Part of the justification (and fun) for this project was learning how to drive the OLED since I'd like to use one for a calculator screen someday. The whole discharge process repeats until the battery voltage hits 1.55v. In my case, it took 42 seconds to hit the target voltage.
After the batteries discharged to 1.55v, I put them in the TI-86 and the contrast was perfect! This was very satisfying. However, the next morning when I woke up and turned the calculator on, the contrast was back to solid black since the battery voltage had floated back up to over 1.7v overnight. Apparently, this is a normal part of battery chemistry. For the discharger to work, I would need to figure out how far down below 1.55v to discharge the batteries so that they wouldn't rise over 1.6v overnight. Rather than spending multiple days testing battery discharge and recovery cycles, I soldered a piece of protoboard to replace one of the four batteries and lower the average total voltage:
Thursday, June 25, 2015
Summer Hackathon: Update
EEPROM Computer
Basing a computer architecture on precomputed lookup tables seemed like a an interesting idea when I started working on an assembler program for a 4-bit EEPROM-based computer. On IRC I explained what I was intending and the creator of the CADET computer showed me what he had accomplished. It is more or less the same thing I wanted to build, so I decided to stop work on this project for the time being. After discussing the idea with a friend at our hackerspace, I decided that it would only be worth continuing this project if I expanded it to a 16 or 32-bit architecture.
Brainfuck Microcontroller
ESP8266
A guy at our hackerspace was having trouble getting his ESP8266 going, so I set mine up to figure
out how to do it. Luckily for me, mine worked fairly well on the first try. The 03 variant I bought last year looked especially good since it is a little smaller than the others I looked at, and has several GPIOs, which I will need for one of the projects I have planned. One inconvenient thing is the 2mm pitch of the pins, which is slightly smaller than the 2.54mm, or 0.1'', pitch of a breadboard, but I soldered a small adapter. The firmware behavior is a little different than what some of the tutorials say to expect, but I was able to get a list of wireless networks at my house and connect to the WiFi at our hackerspace.
Wireless Breadboard
This project was especially exciting to me because it can be used to debug several of the other projects. To begin with I cut one of my 8x12cm protoboards in half and soldered single-row female headers to them, so a breadboard with male headers soldered on could be plugged into it. Unfortunately, I miscalculated the width of the breadboard and soldered the female headers on too wide apart. My local shop has been out of headers lately, so I tried to desolder the headers and broke a row of them in half in the process. So far I would consider this project a failure.
ATF1508 CPLD
This is an essential part of the 6502-based calculator I am hoping to build soon. Unfortunately, it has been my main source of headaches over the past few weeks. First of all, I tried to program the chip with an MSP430 generating JTAG signals from an svf file but this failed. After some searching, I found out that the JTAG standard is not really "standard" at all, and chips from different manufacturers handle the standard differently. Next, I tried generating a pcf file from the svf file, because it contains the actual states of every pin on every clock cycle. Although this worked and I could program the chip, the programming steps were ridiculously complicated. After using Atmel's WinCUPL program (which itself is rather unpleasant to use) to generate a JEDEC file, I convert it to an svf file with the Atmel ISP program. The problem with this is that the program offers a couple of nonsense error messages and just crashes if the FTDI cable I use to communicate with the MSP430 is still plugged in when I start the program or click the button to generate the svf file. Next, I have to switch to a virtual machine to generate the pcf file, since Atmel's SVF2PCF utility is 16-bit only.
When my troubles with this chip started, I ordered a Byteblaster JTAG programmer, as the Atmel datasheets list this as a possibility for programming the chip. When it arrived, I quickly found out that the USB Byteblaster I had ordered has nothing at all to do with the Byteblaster cable that Atmel ISP can use. The open source driver I tried for the programmer caused my Windows 7 computer to crash with the blue sreen. Next, I ordered a USB to parallel converter cable, since the schematic for the Byteblaster is just a 74HC244 chip connected to the parallel port. So far I have not tried programming with this chip and may go back to programming with the pcf files generated by Atmel's 16-bit SVF2PCF utility.
Improved 6502 Virtual Trainer
In my post about GCC for the STM32F429 I explained how difficult it had been to get a GCC toolchain running. While I did get the toolchain to work in the end, I was unable to make any of the USB-to-serial examples work. This is very attractive for this project because I could use the chip as a Virtual Com Port and wouldn't need an FT232 chip or USB-to-serial cable. Many examples used the STM32CubeMx program from ST to generate the base code. None of the generated projects, however, can be opened with Eclipse, This is especially disappointing considering that the page for the utility lists GCC as a supported toolchain (although it is not actually in the list of toolchains in the project generator!) and provides an Eclipse plugin form of the utility. As I stated before, developing for STM32 with free tools has been a real pain! I tried the OpenSTM32 IDE, which is based on Eclipse and the libopencm3 library. This was able to compile a USB project generated by STM32CubeMx, but not without a good bit of fiddling with the files generated.
Makevention
Our hackerspace is sponsoring a convention for makers in August and I would like to show some of my calculator projects there, so for the next two months I plan to focus mostly on the Improved 6502 Trainer and ATF1508 CPLD. These will both be necessary for the next calculator I want to build.
Thursday, July 3, 2014
Quiz Buzzer
The plan was that each of ten students would have a button connected to a buzzer by a few meters of wire and the first to press the button after a question was asked would cause a sound and light to go off. The connectors are RCA style and the buttons are from an automotive store.
These lead to an A42 enclosure I was able to sample from Serpac. The enclosure felt really sturdy but the plastic was surprisingly easy to cut and work with with just a knife. I will definitely use them again when I need an enclosure. The circuit itself was fairly simple with just an MSP430 microcontroller, buzzer, two 595 shift registers, and two 165 shift registers. I did not get around to adding the LEDs, although the firmware does use the shift registers to turn on the correct light when someone buzzes in.
To control things I made a separate detachable board with a 16x2 LCD. It will be easier to transport if the cable is detachable and it will also let me add a longer cable if the judges doing the scoring need to sit farther away from the enclosure. Other than the LCD, the board has a 555 to generate negative voltage for the LCD contrast and another 595 shift register to run the LCD. It also has buttons to change the time given to answer and to reset the counter.
For the cable I used Cat-5 again and this may be part of the reason it does not work correctly. For the connector I wanted to make something that would only plug in one way so that people other than me could use it without fear of plugging it in backwards and shorting something. Each side has a pin that can only be connected one way.
A project like this would take me a week at least but I tried to finish in two days because my friends needed it. The night before I stayed up soldering until 7am and when I finally switched it on, the LCD came on as expected and the buzzer sounded when I pressed one of the contestants buttons, but it made a high pitched screeching noise when it was finished buzzing. When I turned it off and tried again the LCD wouldn't display anything and only worked some of the time when I tried it again, so we weren't able to use it in the competition after all.
Why did it fail? In retrospect, I have had problems with this particular LCD in the past. When I was working on my calculator project I noticed that the LCD would often not work when being driven directly by a microcontroller but worked fine when being driven from a shift register like in this project. I'm not sure why it worked before and not now but the fact that it was flaky before might be a clue to my problem. Also, maybe my assumption that it will always work at voltages less than 5v is not correct or maybe supplying negative voltage to the display somehow has consequences. On the other hand, I observed the same faulty behavior with the contrast left unconnected. Another source of problems could be the Cat-5 Ethernet cable I am using for wiring. Each pair is twisted together and running a separate signal through each side of the pair instead of grounding one side might be leading to signal corruption. Finally, the loud screeching of the piezo buzzer is something I will have to figure out as well. Hopefully, when I understand more about this it will help me straighten things out with my clock project also.
Going from nothing to a nearly complete project in only two days was a lot of work, but in the end there was not enough time to troubleshoot problems. When I move into my new apartment next month I will have time to figure everything out and then I can send the working system back to Kyrgyzstan for my friends to use.

