Creating the environment and infrastructure for the CBM 8032 AV performance project included a lot of custom hardware development, writing software not only for the computers used but also for helper tools and finding unique solutions for upcoming problems.

Basic System Architecture

Due to the inherent technical limitations, an audiovisual performance setup using a single Commodore CBM 8032 would be too restricted.

We decided to create a network of several computers to achieve more complexity.

One unit serves as the sequencer, which provides the control data for the other computers in a synchronised manner, and is the main unit to play with during a performance, since recalling and modifying patterns is what turns the individual sound and graphic routines in structured pieces.

The computers are connected via a parallel network, which also allows to insert data from a Arduino Teensy during the software development process.

Recalling sound and video routines relies heavily on the usage of interrupts. The sequencing computer distributes the data for the individual receiving machines on the parallel bus, and notifies them about the presence of valid data via an NMI ('non maskable interrupt') sent directly to the CPU of each machine.

A dedicated video computer runs all the graphics routines, and its output to the built-in CRT display is converted into a HDMI signal for possible video projection. The sequencer computer also is capable of transmitting its screen content via HDMI.

Three computers run sound generation routines, and are equipped with a custom digital to analoge converter board. They provide two channels of 8 bit analogue signals. All five computers can also create sounds using the very primitive built in sound generation method.

The sequencer itself is clocked via external hardware, which also generates an NMI sent to the sequencer.

Like all other hardware extensions, every part of the bus hardware in use during a performance, is built using circuits available already in 1980, such as the SN74LSxxx, or CD40xx series.


Video Generation

The CBM 8032's graphic capabilities are very limited: The display is represented inside the computer as a 2000 byte large block of memory; 80 characters per line, 25 lines. Each character is a single byte, using Commodore's PetASCII format.

Writing to the screen equals putting data into the correct memory location which represents the screen. We developed several unique drawing algorithms, each with its own set of rules, and with different response to incoming notes. This allows us to rhythmically sequence the appearance of shapes, the rate of a drawing or a decay, the amount and types of random variations, and so on.

There is no dedicated graphics chip in the 8032 and no 'libraries'. Even the simple task of drawing a line requires to we write a program that reads through data containing memory addresses for the beginning of each row on screen and calculating offsets to store the desired character in the right locations, so that we see a continuous line made up of several pre-defined 8 pixel x 8 pixel characters.

With only 256 characters to choose from, of which half are unique and the other half are their inverses - all of the CBM 8032 AV pieces only use about 64 unique characters - the focus is less on what to draw, but how, at which moment, and where. (Incidentally, if a program accidentally ‘draws’ into the wrong addresses, it might overwrite software and ultimately crashes the computer).

The creative process involves generating sets of rules and then defining how much random behaviour the algorithms provide in order to oscillate between structure and chaos. Aesthetic questions are defined by a minimal selection of forms, with focus on variation in movement, density, and pacing.

Drawing routines have no concept of frames or time sync - they run in a loop until instructed to do something else. This generates intriguing possibilities, like filling the screen with characters changing faster than the CRT display can update, leading to interferences and Moire like patterns.


Video Output

The CBM 8032 only provides a very rudimentary video output, not compatible with any contemporary video format. We discussed several methods of getting the images shown on the computer's green CRT ('cathode ray tube') display out in a way suitable for a large video projection. Filming the display with a camera would not look good enough. Using a software emulator for the video computer would defeat the purpose of the project and would still not look good. Analogue to digital scan converters have their own artefacts which are beyond our control and we did not find a satisfying solution.

We finally decided to throw a lot of contemporary technology on that problem.


We use a high speed embedded CPU from Xmos to monitor the data bus, the address bus, the read/write line, and several other signals to gather the screen data when it is created.

This is greatly simplified by the fact that the CBM 8032 provides all necessary signals directly on its mainboard on two large pin headers for potential expansion boards. The Xmos CPU sends out a frame synchronised stream of data via its serial output, containing the current state of the CRT display data.

The method is not perfectly accurate.

Inside the 8032, its CRT control chip scans dedicated screen memory, line by line in sync with the movement of the electron beam of the display tube. If a program is writing data in rapid succession to screen memory, states can be achieved in which the upper part of a character already has been displayed when new data is written to the same location.

Thus during a single frame 'hybrid' characters consisting of two or more partially drawn characters can occur.
Ironically, to reproduce this behaviour exactly would require an even more powerful contemporary CPU, and we decided against it. [A problem similar to the attempt to 100% reproduce the behaviour of early digital synthesisers in software.]

To turn the serial signal into an image again, an Intel Nuc computer running the Rust framework reconstructs the characters including the typical phosphor decay behaviour and provides the HDMI output. This process introduces a 50ms delay; the audio signals have to be compensated for this.

The video computer and the sequencer computer both contain the Xmos board. A switch in the Control Box (see below) allows to project either signal during the performance.

Aspect Ratio

The original Commodore 'Pet2001' and the CBM 40xx models had 1kByte screen memory, and were capable of displaying 25 lines with 40 characters each. That produced a nice character aspect ratio and especially the graphical symbols did benefit a lot from it. After all, they were designed with this geometry in mind.

The CBM 8032 offers twice the screen memory, it displays 80 characters per line. The characters are now drawn much narrower, which does not nearly look as good.


To project the characters in full HD via a contemporary projector we had to rescale them anyway, and decided in favour of a more appealing compromise for the aspect ratio,
which is somehow in the middle between the CBM 40xx and the CBM 80xx models. Basically a 8032 'widescreen'. Each pixel of the original characters is represented as 5px high and 3px wide object, leading to a resolution of 80 x 8 x 3 = 1920 pixel horizontally and 25 x 8 x 5 = 1000 pixel vertically.
Vertical CBM pixels contain 3 green HD pixels, and 2 dark ones, emulating the typical horizontal CRT line drawing effect.

Sound Generation

The CBM 8032 contains now dedicated sound chip.

To provide a simple method for creating notification sounds or similar, a specific feature of one of the bus interface chips (the 6522 VIA) is used. One of its two internal shift register's can be set to a mode in which data is rotating endlessly, driven by the CPU clock, divided by a clock divider unit. The signal of one of the outputs feeds an internal piezo speaker. Three address registers are used to define that behaviour. Manipulating the data in its registers allows to create a range of noises and 1bit waveforms. The results are not very sophisticated.


We decided to add an 8bit digital to analog converter ('DAC') to extend the sonic possibilities. We learned how to decode address data and were capable of building a comparably simple circuit board featuring two DACs, an additional 8bit parallel output port and the necessary analog circuits to condition the signals, including filtering of the piezo / shift register signal.

At an earlier stage of the project, we intended to use one of the DACs to control a modular synthesiser. Thus we decided for linear DACs with DC coupled outputs.

We later gave up on the idea, and added switchable filters on a newer board revision. The filters are controlled by some bits from the digital output. There is still room here for a lot of improvement in later versions.

With the two DACs we now can create sounds that are panned hard left, center or right, and we can create stereo sounds to a certain very limited extend.

The 1MHz 6502 CPU is very limited. Every clock cycle counts, and sound generation routines must be extremely simple. We rely a lot on clever usage of tables, there is no such thing as floating point numbers, or even multiplications. The built in random number generator routine in the ROM of the CBM 8032 needs a few hundred CPU cycles for each call. That's way to slow for creating audio noise. We wrote a simpler version that only needs 75 cycles, allowing us to create noise with a bandwidth of 10kHz.

Amongst the possible sounds we can create are percussive and steady sine waves, bass drum like tones, a simple Karplus-Strong algorithm, lots of variations of noise, hi-hats, claps, and some wavetable type timbres.

Audio Processing

By using multiple computers for sound we can create up to three simultaneous voices, each either using the DACs or the shift register output or, theoretically at least, both.

The video computer and the sequencer computer also have the DACs and the shift register output, but we only use the later ones since in some rare cases. ( The credits at the end of the performance are created from the sequencer computer and come with a bit of sound, and some of the video routines also drive the shift register output. )


All audio signals are summed together in a small mixer, with the option to add additional effects. They are chosen with the concept in mind that a performance must have been possible already in 1980. We are mainly using an early digital effects unit, the AMS RMX 16, for chorus and short reverb tail, and a legendary French dual channel pitch shifter, the Publison's DHM 89 B2, from 1978 to enhance and further process the signals.
The intention is to enhance what is there, not to obscure the origin and rough texture of the source signals.

The pitch shifter allows to freeze the signal and this is often used to create steady atmospherical backgrounds. For non-artistic practical reasons, our audio processing also includes tools for the necessary audio/video sync delay and room acoustics compensation.

For historical accuracy it would have been appropriate to use a Lexicon 224 for longer, lush reverbs. For practical reasons that function is provided by a later Lexicon PCM 80 instead which is smaller and fits in our rack on the desk.

During a performance, the settings of the units and the mix are dynamically altered as needed for each piece.

Sequencing

The sequencer written for this project follows a classic pattern based approach. It provides five tracks, one to control the video computer, three for the audio units and one generating an 'accent' signal for audio processing, see the 'Control Box' chapter below.

The sequencer is driven by a clock signal in 32nd note intervals, provided by an external clock generator. Each pattern consists of up to 32 steps, advancing by 32nd ,16th, 8th, 4th... etc. note intervals. When switching from one pattern to another, that process is quantised to one bar. The sequencer also has an offset parameter, and there is an option to play back steps not in sequential order but randomised.


The data for each step is represented as a two digit hexadecimal number, allowing for a theoretical maximum of 256 possible 'notes' per track. Some notes have specific functions, like representing no note at all (FF), or silence (FE), or jump to pattern zero (FD), which effectively turns the currently recalled pattern into a one shot.

Settings for all currently running patterns can be stored in a scene. This allows to recall parts of musical pieces in a timed manner and makes it possible to create fluent rhythmical transitions between those parts.

The right side of the computer screen on the sequencer unit represents an overview of the currently running patterns for all tracks, including the memory locations containing the data in these patterns.

To avoid the significant effort of developing a complete user interface for the sequencer, and not just a display as in the current version, editing pattern data happens inside the hex monitor provided by the CBM 8032 operating system, shown on the left side. It literally means writing directly into RAM addresses.

That might perhaps be changed in a later version of the sequencer code.
The performance is organised in ten pieces, each with dedicated memory locations in the sequencer. Each piece can consist of up to 8 scenes, and each track can have up to 5 different patterns. The limiting factor here is the available amount of RAM in the sequencer computer.

It is possible to mute tracks, and to stop the sequencer and restart all patterns in sync. For this purpose the numerical keys on the computer keyboard are utilised. There is also a function to reset pattern positions every x bars, which is important when creating patterns with uneven lengths. Pattern data also can be copied from one location to another, either in the same or any other track.


Control Box

Several needed function blocks for the whole system are combined in the 'Control Box', a little piece of hardware sitting left of the sequencer computer on the desk. It is using a mix of existing Eurorack synthesis modules and own hardware.

Its functionality is split in three parts: Video output switching, sequencer clock generation and audio accent handling.


The video switching module consists of a simple switch, and a serial to USB converter. It allows to define which signal is shown on the projection screen: Either the sequencer or the video computer output. We show the sequencer briefly during the performance.
A big tempo control knob and a Run/Stop switch is controlling a VCO and a clock divider module. This provides the trigger signal for the sequencer, 32nd note pulses at a tempo from ca. 60bpm to ca. 300bpm.
An accent signal from the sequencer computer is providing a gate voltage for an Attack-Release envelope module, which is controlling a VCA module. The VCA input comes from a send of the mixing desk. This allows to add an accent of variable strength to each audio track. Since the accent is routed to a mixer input channel it can further be processed and filtered.

Assembler Tools

At the beginning, I wrote assembler by hand on paper. Then I started using an online assembler program and wrote a first version of the Max based file transfer program. Once we became a team working on the project, we decided things need to operate on a different level, and we adapted a freeware assembler for the Sublime editor to work with the 6502. That turned the project into a serious software development adventure.

Data Storage and Transfer

Each CBM 8032 computer is equipped with an internal SD card based floppy emulator, a PetSD+ unit. Whilst this is helpful for storing final data and utility routines, it is not suitable for fast data transfer during development.

Assembler routines and tables containing data are created externally, either via Max or other tools, and we use a Max patch in combination with a Arduino Teensy to send data to the CBM computers via their User Port.

On the receiving side, a short assembler routine is receiving the data. This turned out to be a relatively fast and very reliable method and it allows to quickly update selected memory locations on the running system.

What started as a simple Max patch to transfer programs matured into a Swiss knife.


It now contains a generator for various waveforms needed for audio routines,
a comprehensive hexadecimal-decimal-binary converter, a sequencer with real time input
for fast testing of new sound generation routines, and a text-to-PetASCII tool.

Interrupts and Timing

When we started the project we were very naive. We coded some 'proof of concept' sound and video routines in assembler, and that gave us the confidence to move on. We later had to learn that things are way more complex. A lot of it has to do with the handling of time. The CBM 8032 is a very basic single CPU system. Its CPU can do one thing at any time, step by step. Already early in computer history it became clear that this method has its limits, especially when a computer program needs to react to any sort of external input, like getting key presses: The CPU has to scan the keyboard in regular intervals, and if the main program is long and complex that would imply it has to jump again and again into a keyboard scanning routine from multiple points in the software.

If the program has to react to multiple inputs that need to be observed, this method becomes impractical or it would even be impossible. The solution is the concept of the 'interrupt' which is an external signal to the CPU that can at arrive any time and basically tells it to stop what ever it is doing, and execute the code of an 'interrupt handler routine' before jumping back to where it was before. Using interrupts is the key to any realtime system such as ours.

The 6502 CPU inside our computers offers two types of interrupts, a 'regular' IRQ, which is triggered by multiple sources including the keyboard and floppy ports, and which can be disabled in software, and the NMI, which has highest priority, cannot be disabled, and is normally not in use in the CBM 8032.

The sequencer engine receives its clock pulses as NMI, and the interrupt routine does all the calculations necessary to send the current step data to the four other computers. Once this is done, it updates the graphical display to reflect the current state.

The exact timing of this routine depends on the number of CPU cycles necessary to execute the code. This might depend on several states; resetting several values at the end of a bar takes a bit longer, or resuming after stop. However, the derivations in timing are in the range of a few microseconds, ten to hundred times better than what MIDI via a 5 pin DIN cable offers.

On the sequencer computer, the software interrupt (IRQ) is not disabled, because it is important to scan the keyboard and serve the hex monitor routine. Since the NMI has priority this does not affect timing.

On the receiving side, things are much more complex. To create a sine wave using the DACs, the program has to scan through the sine wave lookup table in a complete regular fashion. The software interrupt which happens every 20ms and is triggered from the CRT controller has to be disabled. That implies we have to build our own key scanning routine if we want to e.g. react to an "esc" command to exit the software. The more interesting and complex part is how to handle arriving NMIs.

When an NMI arrives, it indicates that the User Port has valid 'note' data, defining which sound routine to play next. The interrupt handler cannot simply abort the current playing routine, but rather sets a memory address to point to the beginning of the desired new sound routine.

Each sound routine jumps in regular intervals to another routine which uses that address to simply jump back to the sound routine. This process takes almost no time ( < 10 CPU cycles / 10 microseconds ) and can be done very often without causing problems.

When receiving an NMI, this jump address gets modified, and the next time the currently running routine arrives there, it exits to the initialisation part of the new sound routine. This initialisation routine itself also sets the jump address to the correct value for the now running routine.
The less often we call the jump routine, the more jitter we introduce, and the less accurate the timing would be. Practically, we do this at least every 100 cycles in each sound routine, giving us a timing accuracy of 0.1 milliseconds.

As a result, the sequencer timing of our 1980s system is exceeding MIDI timing by a magnitude, and we are closer to 'sample accurate' timing of DAWs in 2019.

The audio computers draw a large number on the CRT display when a new note arrives. This is done in the interrupt handler and takes 1.5 milliseconds. Since this is true for every arriving note, it does not create any jitter, it just delays all audio by exactly that amount.

Running any audio routine that involves playing back sounds via the DACs requires a constant stream of data to them, and there is no time for doing also any visual code. However, when a percussive note has finished, we jump into a 'idle' loop, which scrolls two lines horizontally on the screen, providing some additional visual cue.

The concept of 'note' is also applied to the video computer, but the code operates differently. On the sound machines, a new sound will always terminate the currently playing one — the system is monophonic. That's why we use three computers for sound. Running video routines often are just modified when a new note arrives, deleting or altering parts of the image or changing visual movements. This is much more complex to sequence: the order of arriving notes define what happens to the image. 'Clear screen, draw square, rotate' obviously does not do the same as 'draw square, clear screen, rotate’.