Bit banger is built around an ATtiny15 microcontroller, which runs at
1.6 MHz and has 1 kB of flash ROM and a claustrophobic 32 bytes
of RAM. In fact, those 32 bytes are the CPU registers. Only the most basic
AVR instructions are supported; they occupy at least two bytes each, and can
obviously not be compressed since they are executing from ROM, so a maximum of
512 instructions will fit inside the chip (fewer if static data is
needed).
The microcontroller supports interrupts, but they would have been too costly to
use. Instead, the entire demo is cycle counted.
At a clock rate of 1.6 MHz, the visible part of each line of the VGA
signal swooshes by in exactly 36 clock cycles. The entire line, including
horizontal blanking, is 51 clock cycles wide. During this time, both
graphics and sound must be generated.
I quickly arrived at the following overall design: Three registers make up a
24-bit frame buffer, organized as a 3x8 grid. Every 60 raster lines,
these registers are rotated one bit, to prepare for the next row of
the grid. At three different positions along the visible part of the line, the
MSB of the corresponding frame buffer register is interpreted as an instruction
to either keep or invert the current colour; the resulting colour is then
transmitted onto an output pin. At the end of the visible line, black is
selected.
In the gaps between these four positions and the two places where the
horizontal sync signal is flipped, sound must be generated and emitted. The
ATtiny15 luckily has a PWM output that runs on a separate peripheral clock
at a staggering 25.6 MHz, which is high enough for 8-bit audio output.
Writing a sample to the PWM output is a simple one-cycle instruction; the
challenge is to calculate the value of the sample during the remaining clock
cycles.
Here's an excerpt from the source code, so you get an idea of what I was up
against:
The peculiar indentation signifies that there are two things going on: The
graphics output in the left column and the sound generation in the right
column. Pixels are emitted at times t6, t18 and t30. If we should advance to
the next row in the grid, the frame buffer registers are rotated at t35 through
t41; otherwise we branch down to noadvance, delay for 4 clock
cycles, and then jump back. Cycle counting at its finest. In the sound column,
we see two 16-bit oscillators being updated (phase is accumulated in r7:r6 and
r5:r4, frequency is taken from r11:r10 and r9:r8. White noise is generated by
means of a linear feedback shift register in r21:r20. One of the oscillators
has a variable pulse width, which is kept in r3.
Vertical blanking
Outside the visible area, 45 raster lines make up the vertical blanking
space. During these lines, horizontal (and vertical) sync pulses must still be
generated, but since there are no visible pixels we can afford the luxury of
generating the sound in a subroutine, rather than inline. Hence, out of
51 clocks, 25 are spent in the sound subroutine, and the rest can be
used freely to prepare the next frame and to perform music playback. This work
can thus be divided up into at most 45 small code snippets, of no more
than 26 cycles each.
In practice, music playback and frame calculation is intermingled; state
information from the music player is used as parameters for the visual
effects. This saves space and has the added benefit of creating effects that
are synced with the music. The music is based around a single 32-step pattern,
one byte per step, expressing the bass part and the drums. There is also an
arpeggio table with the four chords. The code maintains a current offset into
the pattern, which is in fact the lower bits of a 16-bit frame counter for
overall demo progress. Other bits in this counter turn glitches on and off.
Most of the glitches are implemented in a semi-controlled fashion, by
trashing the registers that will be used during the upcoming frame. In other
words, most of them weren't designed as much as discovered. I tried to ensure
that the timing of the sync signals would remain perfectly correct no matter
how wildly the other parameters would vary. I'm pretty sure I failed somehow,
because an assortment of monitors refuse to display the resulting VGA
signal.
Analogue features
All of the above creates a very primitive digital output: A stable (well...)
VGA signal, 3x8 huge pixels and sound. The microcontroller has five
user-controllable I/O pins. Two of them are needed for horizontal and vertical
sync, and one is the sound output. The remaining two pins express pixel colour;
this allows no more than four colours, one of which must be black.
To improve the situation, the sound PWM doubles as a pixel colour bit as well;
however, the VGA signal must be black outside the visible area, even when the
sound is playing. A transistor is connected as a poor man's NOR-gate, to mask
this signal whenever one of the regular pixel outputs is high. Another
transistor, a capacitor, and a couple of resistors are also employed to
recombine the pixel colour signals into red, green and blue voltages, because I
wished to avoid being stuck with the standard coder colours. The capacitor
introduces a low-pass characteristic, which is responsible for the clearly
visible horizontal gradient effect.
Reception
Bit banger was a success in the compo, which was somewhat unexpected for
such an experimental production. Naturally I was very happy!
Some people claim that I abused the rules for the Oldschool 4k compo, since the
ATtiny15 is a modern chip. The other option was the Wild compo, which is
typically a catch-all category when a production doesn't fit any other compo.
I insist, however, that both the aesthetics of the demo and the technical
limitations faced by the programmer are definitely more oldschool than
newschool in this case.
Posted Monday 13-Jun-2011 10:23
Discuss this page
Disclaimer: I am not responsible for what people (other than myself) write in the forums. Please report any abuse, such as insults, slander, spam and illegal material, and I will take appropriate actions. Don't feed the trolls.
Jag tar inget ansvar för det som skrivs i forumet, förutom mina egna inlägg. Vänligen rapportera alla inlägg som bryter mot reglerna, så ska jag se vad jag kan göra. Som regelbrott räknas till exempel förolämpningar, förtal, spam och olagligt material. Mata inte trålarna.
Anonymous Mon 13-Jun-2011 12:58
Riktigt bra, som alltid! :)
/Henrik
Anonymous Mon 13-Jun-2011 18:00
This almost sounds like a IDM track by Aphex Twin. And damn, only 32 Bytes ram? Awesome!
Anonymous Tue 14-Jun-2011 15:38
I am working on a demo of my own based on the ATtiny2313. I almost stopped when i realized that it only goes to 16 MHz. Until I saw you using the ATtiny15 -- WTF?!!?! Okay.. Now I am inspired! :)
Anonymous Fri 17-Jun-2011 19:30
Any chance you'd post annotated schematics?
Anonymous Fri 17-Jun-2011 21:59
Awesome. If anyone wanted to complain about using a modern chip, I'd say the fact that you are running it at merely 1.6Mhz without any support chips at all should quell any disgruntlement. Very cool.
Anonymous Tue 21-Jun-2011 04:19
Do you think you could upload a recording of this? I think it would make a great ringtone for my cell phone.
Anonymous Wed 22-Jun-2011 16:08
Do you think you could upload a recording of this? I think it would make a great ringtone for my cell phone.
yeah, i also would really appreciate a recording of this tune! it is excellent!
Anonymous Mon 27-Jun-2011 21:55
Release an album of your stuff :)
Anonymous Sun 8-Jan-2012 00:12
Is there an emulator for this? I'd like to play these demos on my pc (including video+audio).
Anonymous Sat 14-Apr-2012 00:04
Do you have a schematic?
benadski Ralph Willekes Thu 26-Apr-2012 22:02
Awesome! I'm so gonna build one myself! For the poster above, the PCB layout is in the package!
benadski Ralph Willekes Thu 14-Jun-2012 14:36
Done, works great! :)
Most people like it, even those who have never heard of the words scene, demo or the combination of those words. Thanks for the layout!
Anonymous Thu 28-Jun-2012 01:03
I think you included a schematic but you forgot to include part values. I would be very much obliged to you if you could include some labeling so I can build this wonderful project.