back to
Section Ensoniq
back to Ensoniq heaven

Digital Oscillator Circuit - Ensoniq 5503DOC
Trying to reach me?
Did you know that the DOC was not only used in the ancient Ensoniq machines but also as the heart of computer sound cards - and that it even was used as the sound processor of the Apple IIGS machine?

The latter is our great luck because Ensoniq themselves don´t give away any information, neither about their machines nor their chips. But fortunately Apple is offering at least the programming information in the Hardware Manual of the Apple IIGS (thanks to Henrik Gudat for providing me copies of the respective pages). 

Sad but true... These days one really calls for spam when publishing an email address on a website. But what the heck.

DOC - what's that?
The DOC is the sound engine of your Mirage, ESQ1, or SQ80 and was designed by Bob Yannes, who also developed the well-known SID6581 which was the sound generator of the famous Commodore 64 home computer back in the 80's. If you look closer at them both chips offer some parallels like
  • Oscillators are digitally generated based on phase accumulators
  • Amplification is done using multiplying D/A converters
  • A/D converter on chip
However, the DOC wasn't designed under such a timing pressure like the SID6581, so this led to certain differences. Let's have a closer look at this chip, which was the heart of all "ancient" Ensoniq machines:

The DOC consists of 32 time-multiplexed digital oscillators based on phase accumulators. The frequency resolution is 16 bit, whereas the sample resolution is 8 bit unsigned, thus 0x80 being the zero level. Each oscillator is followed by a so-called (digital) amplifier, i.e. a multiplying DAC, controlled via 8 bit resulting in 48dB of dynamic range. It's controlled via various registers which are explained in the following table.


The DOC contains common registers aswell as registers being individual for each oscillator which are listed here:

Common Registers

  • Oscillator Interrupt Register ($E0)
  • This register contains the status of the DOC interrupt request pin and the number of the oscillator which has generated the interrupt, if any. When an oscillator reaches the end of a wavetable (and the Enable Interrupt Bit for that oscillator has previously been set), the IRQ line and therefore bit 7 of the Oscillator Interrupt Register are set together with the oscillator number in bits 5 to 1.
    Bit Function
    7 IRQ
    This bit is set to 0 if one of the 32 DOC oscillators generated an interrupt, otherwise it remains 1.
    6 reserved
    5-1 Number of interrupting oscillator
    0 reserved
    Oscillator Interrupt Register

  • Oscillator Enable Register ($E1)

  • Through this register, the number of operating oscillators is controlled. To enable one or more oscillators one must multiply the desired number of oscillators (up to 32) by two and enter that number into this register, therefore any number from 2 to 64 is allowed and will enable the corresponding oscillators in sequential order. Low-numbered oscillators cannot be skipped in order to enable higher-numbered ones. Also, a minimum of one oscillator is always enabled, which is also the reset default.

    In the SQ80 this register is set to $2e so that 24 oscillators are enabled.

  • A/D Conversion Register ($E2)

  • The ADCR contains the output value of the internal successive-approximation ADC. An analogue input signal can be sampled (at which pin I´ll have to figure out) and the result of the conversion is stored in this register right after completing the conversion. Reading this register initiates the conversion process, taking 31 microseconds. If this register is read before a running conversion process has ended, that value will be discarded and a new conversion will begin.

    The SQ80 uses this register for sampling pitch bend, modulation wheel, data input slider, and the foot controller. (In software, the wheels get some more processing though, to make them less steppy.)

    In fact, this register is nothing more than access to a built-in AD7574 running in ROM-mode.

Individual Registers (0<=n<=31 represents oscillator number)

  • Frequency Registers (LSB: $00+n, MSB: $20+n)

  • The frequency of an oscillator is determine by the 16 bit value formed by MSB and  LSB. It doesn't reflect the oscillator frequency directly, but the increase of the phase accumulator. The relationship between the frequency of the output signal (OF), the wavetable scan rate (SR), and the frequence ratio (FR) set by these registers is

    RES is the wave's resolution set in the Wavetable Size Register.

    The scan rate SR depends on the machine. In the Apple IIGS it's 894886kHz/(OSC+2), on the Ensoniq machines it's 1MHz/(OSC+2). So for the ESQ1/SQ80 with 24 enabled oscillators, we get 38.46kHz, on the Mirage with SoundProcess OS and all 32 oscillators enabled, SR drops to 29.41kHz. Who wants to do some calculations, check out the values are in the SQ80 or ESQ1 ROM (bank 7 of ROMLOW) where the values for all 127 possible semitones are stored with a resolution of 10 cents per semitone.

  • Volume Registers ($40+n)

  • The oscillator's volume is stored here. The current wavetable data byte is scaled by this 8 bit value to obtain the oscillator's final output level. As this is taking place in the analog domain, no waveform resolution is lost with lower volume settings.
  • Data Registers ($60+n)

  • These are read-only registers and contain the wave's last played byte. (I wouldn't be too surprised though, if you can write here as well and just use the DOC as a bit-banged multichannel DAC.)
  • Wavetable Pointer Registers ($80+n)

  • These registers contain the starting page number of an oscillator's wavetable. All wavetables must begin on a page boundary, i.e. the first byte of a page, and cannot wrap around to low memory addresses. The value in these registers is used for final address calculation regarding the selected page size: for a page size of 256 bytes all bits of this register are used, though with 32k pages only bit 7 will be used for address calculation. Therefore, the maximum size of a single wave is limited to 32kB.

    In the SQ80 waveforms have individual sizes ranging from 256B up to 16kB.

  • Oscillator Control Registers ($a0+n)

  • All functions of each oscillators are controlled through this set of registers. Control includes which of eight optional external analogue multiplexer channels an oscillator will be routed to, whether or not and oscillator may generate an interrupt, and the oscillator's operating mode. The following modes are possible:

    Free-run mode

      An oscillator starts playing back a wave from its beginning and keeps repeating it until the halt bit is set (or a 0 is encountered in the wave data, in which case no repeating will take place). This only workes with page-size granularity.
    One-shot mode
      Just like free-run mode but the wave is only played once, stopping at the end of the wave (page-size limit or 0).
    Sync mode
      Sync mode is only possible between pairs of even and odd numbered oscillators, i.e. a lower even-numbered oscillator paired with a higher odd-numbered oscillator. When the even-numbered oscillator starts playing back its wavetable, its odd-numbered mate will be synchronized to it and begins its wavetable simultaneously.
      Since the SQ80 uses three oscillators per voice the (virtual) oscillator count is reordered to achieve the required even/odd pairing.
    Swap mode
      Swap mode uses even/odd pairs of oscillators as explained above. The enabled oscillator runs in one-shot mode, when it reaches the end of its wavetable, it resets its accumulator to zero, sets its halt bit and clears the halt bit of its mate. With this method it its possible to play a 64kB sized wave without interrupt driven external control, but when using such methods it is theoretically possible to play back even longer waves.
Bit Function
7-4 Channel Address Bits
Only the low three bits are used for output routing by the SQ80, bit 7 is used for wave ROM addressing.
3 Interrupt Enable Bit
If set to one, interrupt flag and oscillator number will be set in the Oscillator Interrupt Register, so the DOC will assert the IRQ line on oscillator halt.
2-1 Oscillator Mode
The oscillator mode is selected by the following patterns:
Pattern Mode
00 Free-run
01 One-Shot
10 Sync
11 Swap

0 Halt Oscillator
This is a r/w bit and is set to 1 to halt the oscillator. Certain modes (one-shot, sync, swap) will halt the oscillator and set this bit automatically after completion. If an oscillator either is running or should be forced to run, this bit is cleared.

  • Wavetable Size Registers ($c0+n)

  • These registers control the size of an individual wavetable each oscillator will access. The size of a wavetable can vary from 256byte to 32kByte in 8 discrete steps as shown below.
Bit Function
7 reserved
This bit is unused.
6 Extended Addressing
This bit is used for bank selection within a wave ROM. By default it's thought to switch between 64kB wave ROMs - in the SQ80 it depends on the type of (EP)ROMs used for wave storage.
5-3 Wavetable Size
The wavetables may extend up to 32kB in size, but in discrete steps only. Wavetables must also begin on a page boundary. End-markers should feature at least eight zeroes, otherwise the oscillator might not halt when encountering these bytes (due to overstepping, cf. 32kB waves with according shift setting).
Pattern Tablesize hex.
000 256 $0100
001 512 $0200
010 1024 $0400
011 2048 $0800
100 4096 $1000
101 8192 $2000
110 16384 $4000
111 32768 $8000

2-0 Address Bus Resolution
These bits determine which accumulator bits are used for address calculation. For tuning reasons this value has to be set to the same pattern as bits 5-3 thus resulting in A9 being the lowest used accumulator bits (highest depending on the wavetable size). By using a different pattern, octave shifting can be achieved.
Highest Accu Bit
Lowest Accu Bit
(depending on Wavetable Size)

Looking inside your SQ80 you find the multisample zones at address $1000 of ROMLOW, every 16 bytes reflect one wave as offered to the sound programmer. Thus, such a zone is responsible for 8 semitones. From $14b0 onwards you find the raw sample data, 4 bytes being responsible for access of one raw waveform as stored in the rom. Byte 1 is the starting wavetable, Byte 2 the respective value for the Wavetable Size Register.

Differences in DOC revisions

Commonly, the 5503DOC appears in revision D, be it on Mirage, ESQ1/SQ80, or Apple IIGS. However, the first generation of Mirages uses a slightly different DOC.

Firstly, it does not include the ADC. In the first revision, the ADC (an AD7574, btw.) was externally applied, featuring its own address decoder that ensured that the DOC is limited to address offsets 0x00 to 0xe1, with the external ADC responding to offset 0xe2.

Furthermore, the original DOC shows explicitly that it only employs a single, time-shared DAC for volume and waveform output generation:

  • In a first phase, the volume output (pin 13) is sampled (triggered by pin 11), which then is fed back for waveform generation.
  • Consequently, the waveform output (pins 15/16) is also sampled using its own control signal (pin 12).
On rev. D, all this sampling and buffering is moved inside the DOC and only some minor current-to-voltage conversion and feedback takes place externally (cf. pins 11/VVref and 12/VOLFDBK on rev. D)

The differences can be easily spotted when comparing the 1984 and 1985 versions of the Mirage schematics. It should hence also be somewhat easy to convert an "old" Mirage to using a rev. D DOC. If you are daring enough, find the (untested) instructions here.

Pinout of 5503DOC (rev D)
Thanks to Michael Käser I finally got the complete pinout of the Ensoniq DOC.
5503DOC pinout

Besides the obvious ones we have the follwing special pins:
  • CSRB: channel address strobe, shows validity of channel address outputs (CA0-3)
  • CAx: channel address outputs, used for external routing of the output signal to one of 16 possible audio channels
  • VVREF: volume voltage reference input(-5V)
  • VLFDBK: volume feedback
  • VOL-: adjustment of D/A output volume
  • WVREF: Wave Volume Reference
  • Sig+/Sig-: balanced analogue outputs
  • A/D: A/D converter input, signals must be in 0-2.5V range
  • BS: bank select, switch between 64kB banks of wave memory
  • Address and Data bus are used for both, communication with the CPU and accessing waveform memory
Ensoniq did not use all of the pins in the way one might expect from the pin naming, there are a few differences:
  • /RAS is used as /ALE for demultiplexing pins 23 to 30
  • CA3, normally selecting audio channels 8 to 15, is used (together with /CAS) for WaveROM selection.
  • E clock output serves as /CS for the WaveROMs
  • /IRQ is not employed on the ESQ1/SQ80, thus more elaborate use of the SWAP mode or arbitrarily-sized looping is quite impossible there.

DOC insights, errata, and thoughts for expansion

AM bug
You probably heard about the famous AM bug on the SQ80. You may also have heard that this is an OS glitch. No, it isn't. (Repeat after me: No, it is not an OS glitch.)

The best thing is: You don't need to believe me, just point your disassembler of choice at address $ED24 ff. (i.e. offset $6d24 in OSHI) of SQ80 OS1.8 and have a look yourself how waveform addressing is handled. See? Told you so.

It indeed is a bug in the DOC that for whatever reason overwrites the modulated oscillator's bank-select signal with the modulator's, leading to accessing the wrong sample ROM.

Long story short: keep your hands off bank select if you want to use AM ...

You can have either AM or Sync, right?
Following the data sheet, both should be possible even though it is controlled by the same bit:

  • If set for an even-numbered oscillator, that will lead to AM of the following odd-numbered oscillator.
  • If set for an odd-numbered oscillator, it will sync to the previous even-numbered oscillator.
Admittedly, the datasheet description of AM/Sync is puzzling (to put it nicely), but following the ESQ1/SQ80 voice handling the above description seems to hold true as 1) only a combined sync/AM bit is generated and 2) this bit is only applied to one oscillator the position of which is either odd or even depending on the sync bit. It's a pity that Ensoniq did not include this possibility in their synths, as it would've allowed poor-man's resonance sweep by applying AM and sync together. Ok, we would've needed a saw-down wave for that instead of a saw-up one, but still ...

DOC memory expansion
Already with the SQ80, Ensoniq decided that the DOC's native 128kB (well, more like 4*32k as 32k is an oscillator's maximum waveform size) addressing capabilities were not enough. As only 8 audio channels were required, they just reassigned one channel-address bit for waveform addressing. While in theory this approach could be extended, you'll obviously sacrifice audio channels for waveform memory size which is not exactly what you want in a hybrid synth.

Luckily, there are other methods, too, which however weren't explored by Ensoniq: they require some more effort as you now need to sync to the internal workings of the DOC. It is then left to your choices whether you want to attach an extra memory (that'll e.g. hold 32*8 or 32*16 waveform addresses) or go with a more baseline, yet electrically more complicated approach.

  • Each full cycle, the DOC will perform two refresh cycles and an arbitrary number of oscillator cycles as defined in the oscillator-enable register. Bus-wise, refresh cycle and oscillator cycle are identical, so the analog voice demultiplexer needs to be kept from distributing spurious audio data. This is controlled by the channel strobe signal: During ordinary oscillator cycles, this strobe appears during E=1; during refresh cycles it doesn't.

    That way, we have an easy way of synchronisation: E=1 && CSTRB=1 identifies refresh cycles and hence the start of sound generation. We now use this as a reset signal for some counter of choice that is clocked with E=0 in order to output the currently serviced oscillator number.

  • For the RAM-based solution, a 5-bit counter is required. During E=0, these 5 bits are used for addressing, during E=1, the CPU-provided address bits are used in order to allow writing to these locations (and hence setting the extended page address).

    The RAM-based solution is wasteful on the RAM itself, as essentially only 32 memory locations are used. It has the benefit of making full DOC use, though, i.e. 32 oscillators or 16 pairs. Back in the days, this would've been an easy hack featuring common 74189 or the more obscure 78218/318. These days, you'll hardly even get small SRAMs like 6116 or 6264 anymore. You'd hence do this in a small FPGA nowadays (which could easily hold an extended DOC design, but I digress ...). This solution could also be used with an ESQ1/SQ80 without having to rewrite the entire system software.

  • We can do w/o a full-blown RAM also, but this requires a twist as we now pair four oscillators: oscillator 0 and 1 will not participate in sound generation, but just provide their wave page address (easily available on A15:8 with 256-byte waves). These will get stored in an 8-bit latch each to be output with the cycles of oscillator 2 (receiving WPA[0]) and oscillator 3 (receiving WPA[1]). Correspondingly, only a 2-bit counter is required in order to generate the according enable signals.

    This solution is wasteful on the DOC, as only 50% of the oscillators are available for sound generation, so you'll end up with a 16-osc configuration but the grunge (aka playback rate) of a 32-osc one. This solution could be nicely fit into a small CPLD (even small by 1990s standards) or a handfull of standard TTL chips. And you could even use the lower 8 address bits to access a saw-down wave and use that one for the above-mentioned poor man's (digital) resonance ...

True AM
On the DOC, AM is an all-or-nothing setting. Wouldn't it be nice to have it scalable?

  • Well, for this we just don't use the DOC's AM bit. The modulating oscillator reads its sample value, scales it with its volume setting, and outputs the value -- together with an "illegal" audio channel address that is not used for routing but declares "use this for AM". The output signal is fed into an S&H stage that will drive a two-quadrant or even four-quadrant multiplier, with the other input coming from the modulated oscillator. This wastes one audio channel and hence might collide with a waveform expansion hack, but otherwise comes without real drawbacks. (We could even use the BS bit for this as it is buggy anyway.)

  • We could also go for an all-digital approach by scaling the modulating oscillator's data reading together with an additional scaling value (more external parameter memory, yay!), sample this into an intermediate register to then be added to an inversely scaled modulated oscillator's data readout. As timing is tight and EPROMs are slow, this however might not work. Alternatively, the wave ROM would need to be increased 256-fold with the scaling factor applied as another bunch of wave addresses, which is also not really practical.

Can we do something about dynamics?
This is a harder one. Unlike the E-II that used 8-bit mu-law sample encoding (expanded to a 12-bit value range via a specialized D/A converter), the DOC uses 8-bit unsigned linear. Where both machines only know 256 different sample values, the DOC sounds much flatter in comparison. So what can we do here?

  • We could opt for an external D/A converter. Instead of feeding the waveform readout from sample memory to the DOC, we could feed it directly into one of those ancient expanding DACs. If we feed the DOC the value 0xff instead, its own output value would directly respond to the DCA setting which we then could use for VCA control (or DAC reference value generation). However, arbitrary sample size (i.e. not page-sized but 0x00-stopped) will be slightly tricky as here either 0xff (in case of a valid value) or 0x00 (in case of sample end) need to be forwarded to the DOC. Never the less doable, although those mu-law DACs are pretty much unavailable these days. Could be applied to the ESQ1/SQ80 w/o software change and make it shine, though. Hmmm ...

  • As the DOC's internal D/A conversion is a multiplying DAC approach where volume scales sample (or vice versa), this could be used to apply sample expansion. For this, we would use an oscillator pair: both oscillators play the same waveform at exactly the same settings. With AM activated (and the first oscillator muted), we will now play back the square of the sampled value and, resultingly, a sample range from 1/256 to 256 in exponential scaling. However, while this indeed gives 16-bit dynamics, we have pretty much no control over it as here we'd just play the squared wave. And, of course, we need to keep those two oscillators in sync.

    Instead, we go for a single-osc approach: the oscillator's read-out is processed according to mu-law rules where only the lower four bits are fed to the DOC and get converted. The topmost four bits are turned into an 8-bit exponential number that serves two purposes: 1) generating an analog scaling factor that is applied to the DOC's output and 2) generating an offset voltage that is added to the scaled output.

    Timing is a little bit more relaxed on this one, but scaling/adding should be set up with the channel strobe to avoid audible effects.

That sounds like some hacking. Is there no other way?
Of course we could go the Amiga way and mimic Delitracker's 14-bit play routine, i.e. skipping the DOC's DMA ability completely, essentially just using it as a 32/16-channel multiplying DAC. That way, the CPU could access all sample memory it wants and preprocess the data in any form needed, to then feed it to the DOC.

But of course, there's more than one catch ...

  • The DOC processing window: unfortunately, the DOC will insist on performing memory accesses, so CPU access may only take once per E=1 cycle. The external fast CPU will hence have to synchronize its writes to these cycles. (This is a general problem of all non-6502/680x CPUs that don't know about E/Q bus timing.)

  • The DOC datasheet states that the wave data register is only CPU-readable, not writeable. (While I don't believe that, I haven't checked so otherwise, though, so let's assume the datasheet tells the truth.) Hence, sample writes must even be synchronized to the DOC's internal state so that a) the volume setting is applied before the next sample is read (but after the current sample is played) and b) sample needs to take place exactly at the designated oscillator's time-slot.
This calls for quite a fast CPU that can do a lot of sample-memory access and sample-data preprocessing during the time waiting for the DOC access slot becoming ready. Which means that you already wrote an improved DOC emulation in software that only is lacking the D/A converters. So why not just using DACs that don't make you jump through hoops?