Tuesday, January 6, 2015

Brainfuck Microcontroller

For a year or two I have been thinking about making a brainfuck computer out of 7400 series logic. Homebrew computers made out of logic chips are fairly common so my idea was to implement it as a microcontroller, with an input and output port instead of a screen or keyboard. This way I could drive LEDs, displays, shift registers, or anything else a microcontroller can. Before I made any progress on my idea, I stumbled on a neat project that is similar, The BrainFuck Machine. It uses a UART chip for input and output. Running an HD44780 or LED matrix with my project using brainfuck code should be an extra challenge.

Not long ago another member at the hackerspace I go to was talking about 7400 series logic projects and spontaneously asked me if I had ever thought about making a brainfuck computer. We had come up with the same idea independently and decided to work together. He already had quite a lot of chips including RAM and UV-erasable EPROMs to work with. His UV lamp didn't work any more so I got a replacement bulb for just a few dollars from Bulb Town. That didn't work either so I had a look inside the lamp. The ballast appeared to be sealed with some kind of gasket to the body and there doesn't seem to be any way to get inside it without breaking that. A few other chips were plain old EEPROMs that work at 5v. With some shift registers and a transistor for level shifting, it was pretty easy to program and read them with an MSP430 on a breadboard. When I finish transferring that to perfboard, I will make a post on it.

My partner and I drew up a schematic that looked reasonable and he started on a wire-wrapped board for everything. Personally, I prefer to solder boards but it will be a good chance to see how wire-wrapping works. He also knows how to make printed circuit boards with the materials at the hackerspace. Over the winter break I haven't been at home with any hardware, so I started working on a simulated version of the project with the program Atanua. It is a 7400 chip simulator that was recently released for free. A year or so ago I was really interested in using it but gave up after all of the annoying pop-ups asking to pay. In principle I would not mind paying $5-10 for something like that if it had more features that in other programs are standard:
Click to enlarge
  • Cut, copy, and paste
  • Selection tool
  • Properties window for objects
  • Rotate for objects
  • Connection points for wires
  • Buttons with no letters
  • More 7400 chips
  • SRAM chips
  • Detailed screenshots
Despite the above annoyances, the simulation turned out alright in the end. To make things a little easier, I only implemented an 8 bit address space. The only RAM chip that can be simulated is a 74LS89, so the data stack is only 4 bits wide and 16 elements deep. At first I connected all the control signals for the chips to buttons so they could be manually operated. After I got that working, I started using EEPROM data to control the signals. The first version pushed the address of every [ onto a stack and jumped back to that at the corresponding ] if the current data wasn't 0. This only used a few chips and worked well but test code failed. It took me a while to realize that a loop like this that always executes at least once is equivalent to a do...while loop, not the plain while loop it is supposed to work like. The next version used a jump instruction that stores the jump address as the byte after the instruction. Getting the signal sequence right so that the jump address is not treated as an op code but is loaded into a buffer then transferred to the address buffer on the right cycle according to the data stack value was pretty tricky. Sometimes backwards jumps loaded half a cycle early, so I inserted a NOP after every forward jump. This wastes space and cycles but is acceptable for this small conceptual test. The jump sequencer could also take less cycles and some of the glue logic could be reduced, which I plan to do when we start on the full version.

In addition to the eight standard commands, it also supports # which many implementations use as a debug command to halt execution. The clock is run through a counter and XORed to produce two alternating clock signals. New EEPROM data appears on even cycles and is latched in as control signals on odd cycles so that the EEPROM output has time to settle before being latched. This probably doesn't matter in the simulation but seems like a necessary step on real hardware. Otherwise, I'm not sure how data appears on the bus and is latched in the same cycle. The control signals themselves use all 8 of the bits for convenience's sake, although they could be condensed. The data readout uses 74LS47 BCD converter chips connected to every three bits which gives an octal display.

To test the setup I wrote this short program which clears the first 6 bytes of the stack then sets the first four to 1, 2, 4, and 8 using multiplication. Then it outputs each byte in turn to the output buffer for a Larson scanner effect. The program comes to 249 bytes when run through the very simple assembler program I wrote, which is just shy of the 256 bytes available with an 8 bit address space.

[-]>
[-]>
[-]>
[-]>
[-]>
[-]
<<<<<
+
[
   [
      >++
      >+
      <<-
   ]
   >>
   [<<+>>-]
   <
]
<
[
   .<.<.<
   .>.>.>
]

Zero first six bytes





Return pointer to 0

Start counter at 1


Add two for every one of counter

Make a copy of counter
Subtract one from counter
Loop until counter==0
Point to copy of counter
Copy counter back to its place
New counter is next address
Loop until counter overflows to 0
Set pointer to last value

Output 8, 4, 2

Output 1, 2, 4
Loop forever

No comments:

Post a Comment