Sunday, January 18, 2015

Space Sombrero

For Halloween I decided to put some LEDs controlled by an MSP430 on a sombrero. Unfortunately, I did not finish in time to take it to the Halloween party at our hackerspace but I did finish working on it the last week.

The LEDs are soldered in three 4x4 matrixes, one matrix for each color. My plan was to combine red, green, and blue into one point diffused with ping pong balls. In the end I skipped the diffusers. The LEDs are bright enough on their own. They are taken from a string of Christmas tree lights so the total of 48 LEDs cost about a dollar. Something like NeoPixels (WS2812) would have been better for this project but would have been much more expensive.

Each color is run by its own 74HC595 shift register, so only one LED per color can be on at a time. This reduces apparent brightness when several LEDs are driven by PWM but is still brighter than using only one matrix for all the LEDs. With a 1k resistor they are very bright, which I noticed when experimenting with them before. Everything is controlled by a small PCB. Each matrix is connected to a Cat5 ethernet cable which has four twisted pairs, exactly enough to multiplex 16 LEDs. The two knobs control speed and color of the patterns and a button switches between patterns. Altogether the hardware is really simple, though there were some headaches soldering the board. The legs of the potentiometers are very weak so I soldered header pins to the back of them for stability. They are really sturdy now but Vcc was shorting through the body of the potentiometers. Once I fixed that, there still showed only about 4k resistance between ground and Vcc. A tiny fleck of solder on the metal body of the power switch was also causing a short. After fixing that there was still a 33k resistance between ground and Vcc. Desocketing and unsoldering narrowed it down to the L4931 voltage regulator. Several other L4931s I measured had the same resistance. After putting everything back together, it worked fine.

The potentiometers and knobs for them came from my local electronics store. They are logarithmic, although linear would work much better for communicating speed to the microcontroller. Converting the curve mathematically seemed pretty tricky, so I used a look up table of a few measured values instead. After soldering the potentiometers onto the board, I realized that the seven values I measured were not enough, so I plotted them on a graph and extrapolated more points. The values I came up with work pretty well, though when changing colors the distances between points don't feel exactly even. The next time I use potentiometers like this I will try to do a lot more exact measuring before soldering them so the points will be more even.

Here is a short video of a few patterns I programmed in. You can see how the speed and color knobs work. There is a lot of room left in the flash for more patterns but this is enough to consider the project finished.

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