So why even program a tiny sound generator in assembly?
The inspiration for this was the 1kB contest. Also I wanted to see if I could really do it. This resulted in a lot of thinking about minimal implementations of algorithms and also in my first assembler project. It turned out to be a lot of fun, too!
So how do I know that it is smaller than 1kB?
First of all, otherwise it wouldn't even fit onto the chip. Secondly AVR Studio (which was used to assemble this project) told me, that only about 760 Bytes are taken.
Still don't trust me?
After disassembling the hex file again with
avr-objdump -m avr -D blues_generator.hexthe last instruction was on the address 0x2F6 which is 758 in decimal. It was a 'ret' instruction which is 2 bytes long, so the program is only 760 bytes big and consumed less than 75% of the chip.
Other than the main flash no other memory (e.g. EEPROM) was used.
As already mentioned in the short description, this circuit will produce a 12 Bar blues . The original 12 Bar blues consists of the tonic (T; the first note in the scale of the key), the subdominant (S; the fourth note) and the dominant (D; the fifth note).
12 Bar blues
These three are played as chords according to the following sequence:
T T T T S S T T D D T T
I wanted a little bit more retro sound in my blues generator so used arpeggio for the chords which in my case just means quickly switching between the tonic and dominant of the current note. This was also widely used in 8-bit tunes to overcome the voice limit of sound chips (you will probably not what I mean when you hear it).
These chords are accompanied with a walking bass in the key of the currently played chord. The walking bass uses the first, third, fifth, sixth and seventh note of the scale of the current chord like showed in the following scheme:
1 3 5 6 7 6 5 3
The last part I utilized was a very simple improvisation on top of the chords and the walking bass. Improvisation in jazz and blues is mostly done by using the pentatonic scale (consisting of the first, fourth, sixth, eighth an eleventh note of the key) . This scale is independent of the current chord but it stills is in harmony with all chords.
In this implementation the AVR decides to go up or down one note with a chance of 37.5% each. It repeats the same note with a chance of 12.5% and doesn't play anything if none of the above is chosen. Although being very simple, this algorithm creates satisfy able results.
Aside from the AVR, power connection and reset button the circuit is dividable into three parts: the LED's, the temperature sensor and the sound output.
The LED's are simply used to output the current position of the walking bass (in binary of course). These were added very late to the project because it was easy to implement, the resource were there and it looks way cooler if something is blinking.
The LED D1 shows the most significant bit.
The temperature sensor is a simple voltage divider and is only used to initialize the random number generator with a 'random' number (read through the ADC).
The sound output surely looks like the most complex part of the circuit although only consisting of an audio amplifier chip in it's minimal configuration. The potentiometer can (theoretically) used to control the output volume but as the minimal amplification of the audio chip is 20, most position will amplify the signal to the maximum.
The software is by far the most complex part of the project.
The following parts should provide an overview. For more technical details please take a look at the annotations in the source code.
After the assigning register names and the interrupt table begins the general initialization (SREG, stack pointer, etc.) followed by the ADC initialization. This is kept very simple and it's only purpose is (as mentioned above) to read out the value of the temperature sensor and use this as...Read more »