I got the blinking (actually breathing) support added to the IS31FL3733 library during the PyCon.US sprints, so now you can have a nice hardware blinking cursor. Back from the conference, and I started working on the next prototype.
Since I want it to have sound (simple 8-bit "pew pew" sounds, as the name implies), I looked around a bit for some kind of dedicated sound-generating chips. Turns out they are all pretty old, coming from old game consoles and computers, and not actually that easy to program. So I decided to put an 8-bit microcontroller on the board for generating the sounds. And of course, once I have the microcontroller there, I can drop the keyboard chip, as that microcontroller can also handle the keys.
So here's my list of requirements for that chip:
- at least 6 GPIO pins with internal pull-ups for the buttons,
- hardware I²C slave peripheral,
- at least 8-bit timer for sound generation with a decent speed,
- internal oscillator,
- small enough to fit on this board,
- easy to program,
- already in my drawer,
The minimum number of GPIOs is thus 10 (6 for keys, 2 for I²C, 2 for the speaker), so that rules out the ATtiny85 and friends. Looking through what I had on hand, I finally narrowed down my choices to two chips: STM8S003f2 and ATmega8. The first one is very cheap, the second one I already know quite well. I decided to start with the STM8, because it's always a nice bonus to learn something along the way.
So I re-created my dev environment and flashed the blinking LED sketch on a STM8 development board. So far so good. Then, just for kicks, I tried the UART example for it, but it didn't work correctly -- the speed was all wrong. Oh well, it's not like I'm going to need that. I even found a nice example of an I²C slave for this chip online.
Then I realized that I need to make sure it actually fits on the board with all the required components. But to determine the required components, I need to actually use a bare chip, not this dev board. So I found a universal breakout board, and soldered one of the chips on it. Then I tried the blink example on it. Hmm, strange, it programmed fine, but the pin only goes up and down a fraction of a volt -- something is fishy. I checked all my connections multiple times, tried the same code on the dev board, used shorter wires for the required capacitor, etc. -- but nothing. It almost looks like that time when I forgot to switch a pin to output on an AVR and was just toggling a pull-up. Several hours and a couple of datasheets and application notes later I decided to throw the towel. I used up all my motivation for the day.
Next day I started work on the ATmega. I already had a bare ATmega8 chip nicely soldered to a PCB -- one of #D1 Mini Tote old prototypes, so I used that. Just added a piezo on PB1 and an ISP header for easier programming. I also used the I²C slave code that I had from that robot -- it's nice for timing-critical stuff like sound, because it doesn't use interrupts. A few lines of C added and I can read the pins from the D port through I²C -- the key handling is done. (Perhaps I will add some de-bouncing there later on). Yay.
Encouraged with this small success, I proceeded to playing with sound. The plan is to be able to send a bunch of parameters, similar to what you can play with at http://www.bfxr.net/, and then have the chip play that, possible mixing multiple channels if the sounds overlap. But I started with a simple PCM sound playback, basing the code on http://avrpcm.blogspot.ch/2010/11/playing-8-bit-pcm-using-any-avr.html. That worked pretty well, especially after a few simplifications and some tuning. And it started to sound really good once I replaced the piezo with a tiny speaker I got for that.
In fact, it worked so well, that for I moment I considered just having a set of few fixed sounds, hard-coded as PCM data in the chip's flash, and triggered with I²C. But after a few calculations and experiments with lower baud rates I realized that...
Read more »