back to buchty.net
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 computer?

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

Suggestions, questions, acclamation, or simple curiosity about who that guy is you might want to place here:

rainer@buchty.net

DOC -- what's that?
The DOC, sometimes also called Q-Chip by Mirage veterans, 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 80s. If you take a closer look at both of them, they share some similarities 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 which lead to conceptual improvement. 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 with 0x80 being 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 is controlled via the following registers:

Registers

The DOC contains common registers and oscillator-individual ones.

Common Registers

  • Oscillator Interrupt Register (OIR) ($E0)
  • This register contains the DOC interrupt request pin's status and the number of the interrupt-generating oscillator, if any. When an oscillator reaches the end of a wavetable (and the Enable Interrupt Bit for that oscillator was previously set), the IRQ line and therefore bit 7 of the OIR is set together with the oscillator number in bits 5 to 1.
    Bit Function
    7 IRQ
    This bit is lowered if one of the 32 DOC oscillators generated an interrupt and there's still an unprocessed entry in the OIR stack. Otherwise it remains 1.
    6 reserved
    5-1 Interrupting oscillator number
    0 reserved
    Oscillator Interrupt Register
  • Oscillator Enable Register (OER)($E1)
  • The number of operating oscillators is set by this register. 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 (ADCR)($E2)
  • The ADCR contains the output value of the internal successive-approximation ADC. The input signal fed into the corresponding input can be sampled 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.)

    As can be deduced from the first-generation Mirage models sporting an external ADC, this register gives access to a built-in AD7574 operating 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 determined 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 OF=(SR/2(17+RES))*FR.

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

    The scan rate SR is determined by SR=DOC_clk/(8*(#osc+2)). It hence depends on the machine's master clock and the number of enabled oscillators. On the Ensoniq machines, the master clock is 8MHz. resulting in SR=38.46kHz for the ESQ1/SQ80 and their 24 enabled oscillators and 29.41kHz for the Mirage running SoundProcess OS at 32 enabled oscillators.

    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 last byte read from wave memory. (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 an oscillator's wavetable starting page number. All wavetables must begin on a page boundary, i.e. the first byte of a page. They 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. With 32k pages only bit 7 will be used for address calculation. Therefore, the maximum size of a single wave is limited to 32kB.

    The SQ80 waveforms have individual sizes ranging from 256 bytes up to 16kB. In the ESQ1, the largest wave is 4kB.

  • 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. Analog-like playback can be emulated by not resetting the phase accumulator, so that phases are somewhat randomized.

    One-shot mode

      The wave is only played once from wave start (assuming accumulator reset), stopping at the end of the wave (page-size limit or 0).

    Sync and AM mode

      Here, the (up to) 32 oscillators are paired into 16 groups of two, starting with osc #0. If the bit is set for the even-numbered osc, the following odd-numbered osc will sync to its partner's zero crossings. If the bit is set for the odd-numbered osc, AM takes place: the odd-numbered volume register setting is disregarded, instead the partner's wave-data reading is applied instead. The SQ80 uses three oscillators per voice, hence the OS ensures proper even/odd pairing for Sync and AM.

    Swap mode

      Swap mode can be considered as a special case of the sync mode. Again, it uses and even/odd pair. Once the even osc ends its playback, the odd partner's accumulator is reset and it starts its own waveform playback. This oscillator now can either play in one-shot (and eventually trigger an interrupt) or free-run mode. With this method, it its possible to play a 64kB-sized wave without interrupt driven external control or dividing a waveform into an attack part played once and a looped sustain part without additional CPU overhead.
Bit Function
7-4 Channel Address Bits
Only the low three bits are used for output routing by the SQ80. There, bit 7 is used for extended WaveROM 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 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 selecting one of two 64kB WaveROM banks.
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.
 
Pattern
Highest Accu Bit
Lowest Accu Bit
(depending on Wavetable Size)
000
16
9-2
001
17
10-3
010
18
11-4
011
19
12-5
100
20
13-6
101
21
14-7
110
22
15-8
111
23
16-9

Looking inside your SQ80 you find the multisample zones at ROMLOW offset $1000. Every 16 bytes reflect one user wave as offered to the sound programmer. Such a zone hence comprises 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 WaveROM. Byte 1 denotes the starting wavetable, Byte 2 the respective value for the Wavetable Size Register, the remaining ones are coarse/fine tuning.

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.

5503DOC (Rev D) pinout
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 (as would be expected in a 6800/9 system).
  • /IRQ is not employed on the ESQ1/SQ80, thus more elaborate use of the SWAP mode or arbitrarily-sized looping like on the Mirage is pretty much 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, it will sync the following odd-numbered oscillator.
  • If set for an odd-numbered oscillator, that will lead to being AM'ed by the even-numbered mate..
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.

  • We could do expansion in the analog domain on the DOC's output. For this, the WaveROM is converted into a-law representation. Of this, the DOC only plays back the lower 4 bits, i.e. the steps, (handed in as the upper 4 wave data bits; the lower 4 are an OR over those upper four bits to avoid unwanted 0x00 results). These of course get inverted by the sign bit, so the DOC linearly converts these into a symmetric audio signal of 16 positive and 16 negative steps. This analog output then is scaled by the 3-bit scale factor and an according offset value is added. The latter must of course follow the sign bit to follow signal polarity.

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 any CPU access may only take place 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 writing 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?