|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
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.
If you expect an answer please send plain text emails.
HTML-formatted mails will be dumped automatically.
|DOC - what's that?
|The DOC is the sound engine of your SQ80 or
ESQ-1 and was designed by Bob Yannes, who developed also 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
But since the DOC wasn't designed under such a timing pressure like the
SID6581 and this led to certain differences. Let's have a closer look at
this chip, which was the heart of all ancient Ensoniq machines:
Oscillators are digitally generated based on phase accumulators
Amplification is done using multiplying D/A converters
A/D converter on chip
The DOC consists of 32 time-multiplexed digital oscillators based on
phase accumulators. The frequency resolution is 16bit whereas the sample
resolution is 8bit unsigned, thus being $80 the zero level. Each oscillator
is followed by a (digital) amplifier (which I assume to be a multiplying
DAC) which is controlled via 8bit resulting in 48dB dynamic range. It's
controlled through various registers which are explained in the following
The DOC contains common registers aswell as registers being individual
for each oscillator which are listed here:
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 then together
with the oscillator number in bits 5 to 1.
Oscillator Interrupt Register
This bit is set to 0 if one of the 32 DOC oscillators generated an
interrupt, otherwise it remains 1.
||Number of interrupting oscillator
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 which will take 31 microseconds. If this register
is read before the end of a started conversion process, the value will
be lost and a new conversion will begin.
The SQ80 uses this register for sampling pitch bend and modulation wheel,
data input slider and the foot switch. However, it looks like the wheels
being sampled more frequent or with a higher priority.
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
Frequency Registers (LSB: $00+n, MSB: $20+n)
The frequency of an oscillator is determine by the 16bit value formed
out of MSB and LSB. It doesn´t reflect the frequency of the
oscillator but the speed at which the wave data is read from memory. 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.
According to the Apple IIGS manual the scan rate SR is 894886kHz/(OSC+2).
Who wants to do some calculations how the values are in the SQ80 just have
a look at address $7000 to $7fff of ROMLOW where the values for all 127
possible semitones with a resolution of 10 cents per semitone are stored.
Volume Registers ($40+n)
The oscillator´s volume is stored here and the current wavetable
data byte is multiplied by this 8bit value to obtain the oscillator´s
final output level.
Data Registers ($60+n)
These are read-only registers and contain the wave's last played byte.
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 referring to the
selected page size, e.g. 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.
In the SQ80 waveforms have individual sizes ranging from 256B up to
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:
An oscillator starts playing back a wave from its beginning and keeps
on repeating it until the halt bit is set or a 0 is encountered in the
Just like free-run mode but the wave is only played once, stopping
at the end of the wave.
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
Since the SQ80 uses three oscillators per voice the (virtual) oscillator
count is reordered to achieve the even/odd pairing.
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.
||Channel Address Bits
Only the low three bits are used for output routing by the SQ80, bit 7
is used for wave ROM addressing.
||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.
The oscillator mode is selected by the following patterns:
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.
This bit is indeed completely unused.
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.
The wavetables may extend up to 32kB in size, but in discrete steps
only. Wavetables must also begin on a page boundary. Unused locations within
a wavetable should begin with a minimum of eight zeroes, otherwise the
oscillator will not halt when encountering these bytes and will interpret
them as data.
||Address Bus Resolution
The wavetable is either played back using every byte or only intermittent
bytes as data. These bits determine whether or not every byte is used during
playback by selecting which accumulator bits are used for address calculation.
For practical 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)
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:
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)
- 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).
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.
|Pinout of 5503DOC (rev D)
|Thanks to Michael Käser I finally got
the complete pinout of the Ensoniq DOC.
Besides the obvious ones we have the follwing special pins:
Ensoniq did not use all of the pins in the way one might expect from the
pin naming, there are a few differences:
CSRB: channel address strobe, shows validity of channel address outputs
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
/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 used as CPU interrupt, thus using SWAP mode is quite
impossible on the SQ80.
|DOC insights, errata, and thoughts for expansion
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:
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 ...
- 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.
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) and oscillator 3 (receiving WPA). 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 ...
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 a 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 ...
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?
- 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, 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.