Skip to content
Janne Peräaho edited this page Feb 27, 2026 · 22 revisions

Table of Contents

ReVox

For the Commodore 16, 116, and Plus/4

User Manual

ReVox hardware design and documentaton © 2023 SukkoPera. ReVox is Open Hardware. The hardware design files and technical documentation are available at https://github.com/SukkoPera/ReVox. They may be used, modified, manufactured, and distributed in accordance with the license terms included in the repository.

ReVox User Manual © 2026 Spektro is licensed under Creative Commons Attribution–ShareAlike 4.0 International (CC BY-SA 4.0) license.

Disclaimer

THIS HARDWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. THE DESIGNER SHALL NOT BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS HARDWARE.

1. Introduction

ReVox is an Open Hardware sound card designed to enhance the audio experience on the Commodore 264 Series computers. It plugs into the computer’s memory expansion port and provides an 8-bit Digital-to-Analog Converter (DAC) that ensures crystal-clear digital sample output in demos, games, and multimedia applications.

ReVox is compatible with the Commodore 16, Commodore 116, and Commodore Plus/4 computers.

The device is powered via the memory expansion port, eliminating the need for an external power source, and it supports plug-and-play functionality for easy installation. ReVox is an excellent choice for users seeking to upgrade their audio experience with high-quality, versatile, and user-friendly sound card solutions.

2. System Requirements

  • Commodore 16, 116, or Plus/4 computer
  • 16 kB of RAM
  • Available memory expansion port
  • Amplified speakers, headphones, or recording equipment

3. Hardware Overview

4. Setting Up

  1. Turn off your computer before inserting or removing the ReVox cartridge.
  2. Insert the ReVox cartridge carefully and firmly, with the label side up, into the memory expansion port on the back of your computer.
  3. Turn the computer on. The BASIC start screen should appear. If the screen remains blank, turn the computer off and on again. If the screen is still blank, turn the computer off and remove the ReVox cartridge. Carefully reinsert the cartridge and try again.
Warning: Do not insert or remove ReVox while the computer is powered on.

5. Programming ReVox

ReVox provides a single-channel 8-bit digital-to-analog converter (DAC) intended for straightforward, CPU-driven audio playback. Software must explicitly implement support for ReVox, as no automatic audio handling is provided by the hardware.

Audio samples are played by writing sample data to the ReVox output register with precise timing. ReVox does not include a sample buffer or DMA support; therefore, all sample playback is performed directly by the CPU. As a result, the achievable playback rate depends entirely on the available system resources. In practice, typical playback rates range approximately from 6 kHz to 20 kHz.

Sound quality is influenced not only by the selected playback rate, but also by how accurately writes to the ReVox register are timed. To achieve the best possible audio quality, screen updates and other CPU-interrupting activities should be disabled during playback. Precise timing is typically implemented using a hardware timer.

ReVox features two registers, both of which are connected to the same DAC. The device supports unsigned 8-bit PCM sample data. Values written to the registers must be 8-bit unsigned integers in the range 0–255. The registers are write-only; the DAC state cannot be read back from the hardware.

A sound sample stored in RAM can be played back using the following procedure:

  1. Load a pointer to the sample data in RAM.
  2. Repeatedly write sample bytes to a ReVox register.
  3. Maintain a constant delay between writes to control the playback rate.
  4. Stop playback when the end of the sample is reached.
Below is a listing of the PlaySample subroutine, which demonstrates how to play an audio sample stored in RAM using ReVox.

5.1 Sample Playback Routine

PlaySample is a subroutine that plays an 8 bit unsigned PCM sample with the supplied sample rate. The subroutine accepts two parameters: pointer to sample data and sample rate.

Sample data must be located at the start of memory page, and it can contain only the sample values between 0-254. Value 255 is an end-of-sample mark, that tells to PlaySample where the sample data ends.

Before calling the subroutine, the high byte (Most Significant Byte, MSB) of the sample data address must be supplied in .A (accumulator) and sample rate in .X (X register).

5.1.1 Defines

PlaySample

Label: start of PlaySample
PlaySample.Loop
Label: start of playback loop
PlaySample.Delay
Label: start of time delay
PlaySample.Play
Label: start of play sample
PlaySample.Done
Label: end of PlaySample
REVOX_DAC
ReVox output (DAC)
REVOX_AUD_LSB
Temporary sample data address, low byte (LSB)
REVOX_AUD_MSB
Temporary sample data address, high byte (MSB)
REVOX_AUD_END
Audio control command: end-of-sample
TED_MASK_TIMER_1
Timer 1 mask
TED_TIMER_1_LSB
Timer 1 register, low byte (LSB)
TED_TIMER_1_MSB
Timer 1 register, high byte (MSB)
TED_IRQ_STATUS
Interrupt status register
TED_SCREEN_MODE
Screen mode register
TED_MASK_SCREEN_MODE_BLANK
Mask for blanking the screen
TED_MASK_SCREEN_MODE_UNBLANK
Mask for unblanking the screen

5.1.2 How It Works?

Label: PlaySample

PlaySample stores the sample data address’ high byte (MSB) to REVOX_AUD_MSB. The low byte (Least Significant Byte, LSB) of the address is always 0 and it is stored to REVOX_AUD_LSB.

Timer 1 will be used for playing the sample at the desired rate. To initialize the timer, the supplied sample rate is stored to the timer’s LSB byte, TED_TIMER_1_LSB, and timer’s MSB, TED_TIMER_1_MSB, is set to 0.

Label: PlaySample.Loop

The playback loop starts by a delay that will determine the time delay between each sample. The delay will determine the sample playback rate. First the interrupt status register’s (TED_IRQ_STATUS) Timer 1 flag (TED_MASK_TIMER_1) is cleared. Computer will set the flag when Timer 1 interrupt occurs.

Label: PlaySample.Delay

Then we will wait by polling the TED_IRQ_STATUS register until the TED_MASK_TIMER_1 flag is set.

Label: PlaySample.Play

When the flag is set, we will read a sample from the sample data pointed by REVOX_AUD_LSB. If the read sample was an end-of-sample mark (REVOX_AUD_END), we will exit the subroutine (jump to PlaySample. Done). Otherwise the sample will be written to ReVox’s DAC (REVOX_DAC), the 16 bit sample data pointer (REVOX_AUD_LSB-REVOX_AUD_MSB) will be advanced by one, and we will jump at the beginning of the playback loop (PlaySample.Loop).

5.1.3 PlaySample Listing

; ReVox output (DAC)
REVOX_DAC = $fd5e

; Temporary sample data address: $03-$04
REVOX_AUD_LSB = $03
REVOX_AUD_MSB = $04

; Audio control command: end-of-sample
REVOX_AUD_END = $ff

; Masks for blanking and unblanking the screen
TED_MASK_SCREEN_MODE_BLANK = %11101111
TED_MASK_SCREEN_MODE_UNBLANK = %00010000

; Timer 1 mask
TED_MASK_TIMER_1 = %00001000

TED_SCREEN_MODE = $ff00 + 6      ; Screen mode register
TED_TIMER_1_LSB = $ff00 + 0      ; Timer 1 register (LSB)
TED_TIMER_1_MSB = $ff00 + 1      ; Timer 1 register (MSB)
TED_IRQ_STATUS = $ff00 + 9       ; Interrupt status register

;***** PlaySample *************************************************************
;
; NAME
;     PlaySample -- Play 8-bit sound sample
;
; USAGE
;     .A = <pointer to sample data: MSB>
;     .X = <sample rate>
;     jsr PlaySample
;
; AFFECTED REGISTERS
;     .A, .Y
;
; FUNCTION
;     PlaySample plays 8-bit PCM sound samples. The high byte of
;     the sample data address must be loaded to .A and playback rate to .X
;     before calling PlaySample.
;
;     First byte of the sample data must start at the beginning of a memory
;     page. The data can be of any length and contain values $00-$fe. Value
;     $ff marks the end of the sample.
;
;     PlaySample uses Timer 1 for the playback.
;
; INPUTS
;     .A - Pointer to sample data (MSB)
;     .X - Sample rate: 0-255
;
; RESULT
;     .Y - Always 0
;
; EXAMPLE
;     Play a 16 kHz sound sample stored at memory address $2000:
;         ; Disable interrupts and blank the screen
;         sei
;         lda TED_SCREEN_MODE
;         and #TED_MASK_SCREEN_MODE_BLANK
;         sta TED_SCREEN_MODE
;
;         lda #$20        ; Pointer to sample data (MSB)
;         ldx #$37        ; Sample playback rate
;         jsr PlaySample
;
;         ; Unblank the screen and enable interrupts
;         lda TED_SCREEN_MODE
;         ora #TED_SCREEN_MODE_UNBLANK
;         sta TED_SCREEN_MODE
;         cli
;         rts
;
; NOTES
;     * You need to disable interrupts and blank the screen before calling
;       the PlaySample to get the best possible sound quality.
;
; BUGS
;     -
;
;******************************************************************************
PlaySample
    ; .Y must be 0
    ldy #$00

    ; Set sample data address
    sta REVOX_AUD_MSB            ; MSB
    lda #$00                     ; LSB is always 0
    sta REVOX_AUD_LSB            ; |

    ; Set sample rate
    stx TED_TIMER_1_LSB          ; LSB
    lda #$00                     ; MSB is always 0
    sta TED_TIMER_1_MSB          ; |

    PlaySample.Loop
        ; Clear Timer 1 flag
        lda #TED_MASK_TIMER_1
        sta TED_IRQ_STATUS

    PlaySample.Delay
        ; Wait for Timer 1 interrupt
        lda TED_IRQ_STATUS
        and #TED_MASK_TIMER_1
        beq PlaySample.Delay

    PlaySample.Play
        ; Play sample
        lda (REVOX_AUD_LSB), y   ; Get sample
        ; End of sample data?
        cmp #REVOX_AUD_END
        beq PlaySample.Done      ; Yes, exit
        sta REVOX_DAC            ; Write sample to DAC

        ; Update sample index
        inc REVOX_AUD_LSB        ; Low byte
        bne PlaySample.Loop
        inc REVOX_AUD_MSB        ; High byte
        bne PlaySample.Loop

    PlaySample.Done
rts

5.1.4 How to Use PlaySample?

To play a sample with the best possible sound quality, you need to disable interrupts and blank the screen before calling PlaySample.

The following program will play a 16 kHz sound sample that is stored at memory address $2000 using the PlaySample subroutine.

; Disable interrupts and blank the screen
sei
lda TED_SCREEN_MODE
and #TED_MASK_SCREEN_MODE_BLANK
sta TED_SCREEN_MODE

lda #$20            ; Pointer to sample data (MSB)
ldx #$37            ; Sample playback rate
jsr PlaySample

; Unblank the screen and enable interrupts
lda TED_SCREEN_MODE
ora #TED_SCREEN_MODE_UNBLANK
sta TED_SCREEN_MODE
cli
rts

See Appendix B. Sample Rate for sample rates other than 16 kHz.

6. Limitations

  • Monophonic sound, one audio channel
  • No audio buffering
  • No DMA support

7. Safety and Handling

  • Always power off before connecting or disconnecting the device
  • Avoid excessive force when inserting into the memory expansion port
  • Keep the device away from moisture and static electricity

8. Technical Summary

Feature Specification
Audio Resolution 8-bit PCM
Sample Rate Typically 6 kHz to 20 kHz
Channels Mono
Mixing Mixed with TED audio
Interface Memory Expansion Port
Outputs Computer Audio/Video connector
3.5 mm mono female on ReVox
Power Supplied by memory expansion port

9. Troubleshooting

Problem: No sound

Possible Cause 1: Improper connections of the audio accessories. Verify that the Audio/Video cable is properly connected to a monitor that has built-in speakers or to an external mixer/amplifier.
Possible Cause 2: The running demo, game, or multimedia application is not properly configured to use ReVox as its audio output device.
Possible Cause 3: Demo, game, or multimedia application does not support ReVox. Ensure that the demo, game, or multimedia application supports ReVox output.
Problem: Low sound output
Possible Cause 1: ReVox’s amplifier is set too low. Start sound playback and turn ReVox’s Gain potentiometer until you hear the sound.
Problem: Distorted audio
Possible Cause 1: ReVox’s amplifier is set too loud. Start sound playback and turn ReVox’s Gain potentiometer down until you hear a clean sound.
Possible Cause 2: Poor cables or connections can lead to signal loss and distortion. Check the cabling.
Possible Cause 3: Faulty playback routine. Optimize your playback routine’s timing. If necessary, reduce sample rate.

Appendices

Appendix A. ReVox Memory Map

Label Hex Addr. Decimal Loc. Description
REVOX_DAC FD5E 64862 ReVox output, write-only
REVOX_ALT_DAC FE9E 65182 ReVox output, write-only

Appendix B. Sample Rate

Timer Low (Hex) Timer High (Hex) Rate (Hz) Common Sample Rate (Hz)
BB 01 2001.64 2 000
DE 00 3994.25 4 000
94 00 5991.38 6 000
6F 00 7988.5 8 000
50 00 11 084.05 11 025
37 00 16 122.25 16 000
2C 00 20 152.81 20 000
28 00 22 168.09 22 050
14 00 44 336.18 44 100

You can use the following formula to find the 16-bit Timer register values for rates other than in the table:

TIMER REGISTER VALUE = 886723.5 / RATE
To get the Timer values for NTSC systems, use the following formula:
TIMER REGISTER VALUE = 894886.25 / RATE

Appendix C. Glossary

DAC

A DAC (Digital-to-Analog Converter) is an electronic circuit that converts digital audio into an analog sound signal.

DMA

DMA (Direct Memory Access) is a hardware feature that allows peripheral devices to transfer data directly to and from system memory without continuous involvement of the CPU, thereby improving performance and reducing processor workload.

PCM

A PCM (Pulse-Code Modulation) is a method to digitally represent analog audio signals by sampling their amplitude at regular intervals and encoding the values as digital numbers. A PCM sample file can be converted back to analog audio with a DAC.