logo for David Morrin

EMT 250

EMT 250

David Morrin

2024-01-20

EMT 250 home
Programming instructions

Introduction

This is document provides a technical analysis of the EMT 250 digital reverb, primarily focused on the digital computer which seems to have no publicly available manual. Any references to “EMT-1”, “EMT-2”, etc., refer to the schematics that may be obtainable by contacting Barco (the company that bought EMT).

Some information on the computer design can be found by looking for papers published by Dr. Barry Blesser and Ralph Zaorski. The published papers discuss simulating the design on a larger computer.

The computer has a Harvard architecture: instructions are stored in read-only memory (ROM) which cannot be changed while the machine is operating. The ROM contains 512 32-bit instructions. An 8-bit program counter (PC) selects the current immediate instruction (IM), which is stored into the instruction register (IR) on the next clock cycle. The programmer can load the PC with an 8-bit address from the output of the arithmetic logic unit (ALU). Otherwise the PC automatically increments on each clock cycle, rolling over from the maximum address of 255 to 0, counting endlessly. The ROM is banked between the lower and upper 256 address space using the front panel “REV” button. More details are contained in the ROM section.

To store program data, there are three different random-access memories (RAM) available:

The main memory is primarily used to store the digitized audio samples, but can also store any value from the ALU that does not need immediate access (main memory is slow to read and write). All of the programs reserve Register B, address 3 (B3) as a pointer to the main memory for the next input value.

Program ROM

32-bit instructions are stored across 8, 4-bit ROM ICs, with 9 address pins. These ROMs are labeled “1B” to “8B”. There is an additional ROM labeled “XA” which contains the microcode to select ALU functions which is not discussed here. The MSB of the ROM address bus is controlled by the user control panel button “REV”. The other 8 address bits are driven by the program counter, which is made up of a pair of 74163 counter ICs. The program counter is wired to the first 8 bits of the ALU output for programmable execution branches.

From a cold start, the first 8 address bits will be zeros. The 9th bit will be 0 if “REV” is selected, 1 otherwise.

Branching and conditional execution

There are two commands available to cause the program counter to follow the ALU result: jump and jump-if-interrupt. There is a 1-instruction delay between either jump commands and the actual change to the PC. This means the next instruction after either jump is also executed.

Jumps and other actions can be made conditional by using the “skip logic” hardware, which is primarily implemented using a 74S151 multiplexer IC (E20, see “EMT-4”). The instruction can select a skip condition. The options are explained in the “Skip function” section.

Program layout

Bank A: Reverb

The “REV” program begins with an initialization routine (addresses 0-58) where the state of the controls are converted to multiplication factors for the DSP. The factors for overall decay time, low frequency decay time, and high frequency decay time are stored in the multiplier memory. From the initialization routine, it jumps into the main reverb routine (addresses 122-255, 88-255, 88-255, …) If the “SET” button is pressed, this will raise the interrupt flag which will cause the main routine to jump back the initialization routine (address 120 jumps to 0) and update the decay factors.

Switching from “REV” to another program, or vice-versa, toggles the 9th address bit and the execution immediately jumps by 256 instructions. The programming must take this unexpected jumping behavior into account.

Bank B: Delay, Phase, Chorus, Echo, Space

The remaining five programs use the state of the front panel buttons to determine which ROM address to read from. There is a common path for all programs that starts at address 510, wraps to 256 via program counter overflow, checks the state of the program buttons, and jumps to the correct program.

Sample rate and input control

Each program is responsible for telling the AD converter to make a conversion via the “START A/D” command, thus the program sets the sample rate. This means each program needs to be around 166 instructions in total length to maintain an approximate 24 kHz sampling rate when using a 4 MHz instruction clock. Indeed, this is the case in the EMT 250 ROMs. Alternatively, the program could track the number of cycles, triggering the conversion when the count reaches 166, but this would be complex and waste program space and time with the tracking.

To aid in keeping a length of around 166 instructions, there is a subroutine for the processor to do nothing for a set number of cycles, as is commonly found in programming (e.g. delay(int ms) on Arduino, or sleep [seconds] on Linux). This subroutine is used by the Delay, Phase, Echo, and Space routines. Reverb and Chorus are the largest routines and do not require additional delay to achieve the correct sample rate.

The A/D arrives via serial lines to 3 input registers: “A/D #1”, “A/D #2”, and “A/D #3”. The instructions can copy these to a general register, memory, or the multiplier hardware.

Output control

Each program is responsible for streaming output to the 4 analog outputs, also at the approximate 24 kHz sampling rate. The command “START D/A” is available for resetting the DA system. After resetting the system, the command “LOAD D/A” will move the ALU result to the first analog output. Subsequent calls to “LOAD D/A” will cycle through the remaining outputs automatically. Thus, each program calls “START D/A” once and “LOAD D/A” four times.

Instruction Word

The EMT 250 uses a 32 bit instruction word. This section examines these bits in detail.

Formats

There are 3 mutually exclusive formats to organize the word. Each option makes a different use of the lower significant byte.

Bits in detail

ALU

Functions

“ALU function” drives the XA ROM to set the ’181 functions. Confusingly, the A mux is wired to the ’181 B inputs and the B latch is wired to the A inputs. The following table refers to EMT 250 registers, not ’181 inputs. Each function may have a slightly different behavior if the carry flag is set.

# Logic No Carry Carry
0 \(B\) \(B + 1\)
1 \(B - A - 1\) \(B - A\)
2 \(B + A\) \(B + A + 1\)
3 \(\overline{A}\) (bitwise negation)
4 \(A \oplus B\) (bitwise XOR)
5 \(A\)
6 \(A \cdot B\) (bitwise AND)
7 \(B + B\) \(B + B + 1\)

I/O Function Select

  1. Multiplier memory output register

  2. Front panel controls

  3. “8-rotate” (Latch A: bits 15:8 move to 7:0; bits 7:1 move to 14:8; bit 15 = 0)

  4. “Noise” (linear-feedback shift register for PRNG)

  5. A/D #1 (shortest pre-delay tap)

  6. A/D #2

  7. A/D #3 (longest pre-delay tap)

  8. Product register

IR[11:8] are the “I/O Function Select” bits and they span pages 2, 3, and 4. The bits both select what is available at the output of the I/O mux and I/O side effects. The side effects, controlled by the IC labelled “E16”, are discussed in the following section.

The MSB, IR11, can control the multiplier memory output. Details are in the multiplier memory section.

I/O mux

On “EMT-3”, all 4 bits are used at the I/O mux. Bits 8, 9, 10 primarily select the input for the I/O mux. Bit 11 is used in conjunction with the other bits and \(\overline{\overline{\mathrm{OF}}\ \mathrm{V\ NEG}}\) to drive the mux strobe input (if that input is high, all the outputs are zero). For the strobe to go high, the \(\overline{\overline{\mathrm{OF}}\ \mathrm{V\ NEG}}\) would need to be high, and the entire I/O word needs to be 6. Yet to be determined what this does. \(\overline{\overline{\mathrm{OF}}\ \mathrm{V\ NEG}}\) is an output from the multiplier memory (RAM) on “EMT-2”.

Rotate function

The “8-rotate” function is used for the very practical purpose of swapping around the control register, and also in making pseudo-random numbers.

As a mathematical function, “8-rotate” maps the signed 16-bit domain a quasi-periodic, positive, sawtooth-like output. The period is \(n+256\), however I call it quasi-periodic because while the overall pattern is repeating every 256 steps, the exact values are all offset each cycle by 1. Examining just the start of each cycle, input 0 yields output 0 and each cycle this increases by 1, so input 256 outputs 1, input 512 outputs 2, up through input 32512 outputs 127. This pattern then wraps around to the most negative input, \(-2^{15}\), which outputs 128, reaching a “maximum-minimum” start at -256 outputting 255. The output range is roughly the positive half of the signed 16-bit numbers. This appears to be used in concert with the “Noise” function to generate pseudo-random memory addresses in the reverb algorithm.

E16 mux

On “EMT-4”, the E16 mux determines various side effects. E16 mux can be disabled (all outputs HIGH) by either the I/O word (IR[11:8]) or by the I/O clock (output of the B18 NAND gate).

I/O Clock

I/O clock goes high (and does not disable E16) when

I/O Word

The I/O func select word must be 6 or 8-15 to not disable E16.

E16 effects

  1. LOAD D/A

  2. SKIP and clear IRPT (IRPT signal can override)

  3. WRITE SP (multiplier RAM, OR’d with 7)

  4. JUMP

  5. START D/A

  6. SYNC (unknown function)

  7. START A/D

  8. WRITE SP (multiplier RAM, OR’d with 2)

If either 2 or 7 are selected (WRITE SP), then the AND gate goes low and the multiplier RAM is in write mode.

A CLK DIS.

Also on “EMT-4”, the lower bits (10:8) appear to control the “A CLK DIS.” via AND gate A15. This line is wired to the A register, but the input is from the “START A/D (9)” line; this it is ambiguous whether “A” stands for register A or analog, and unclear what “DIS.” is short for. “A Register Clock Disable” is my current guess.

Skip function

“Skip” controls if a register write or I/O function (via E16) should occur. “Skip” can prevent a PC jump, but does not cause a PC jump. To convert C code like

if (b0 - a0 >= 0)
  a0 = inputValue;

to EMT 250 machine code, the programmer would set the ALU to subtract b0 from a0 and set the skip bits to “skip-on-negative” in the instruction before the a0 assignment instruction.

IR[15:13] controls the E20 mux which selects various possible flags (see below) to drive the “SKIP” and “\(\overline{\mathrm{SKIP\ CLK}}\)” lines.

The E20 mux takes in what would be the Current Program Status Register (CPSR) in a modern architecture and outputs 1 selection based on the current instruction. If the selection is a logical low, then a skip occurs.

The E20 mux can be disabled by IR31 (A mux select) by making the \(\overline{\mathrm{EN}}\) input high. E20 also disables itself via the D18 flip flop at its own output. This would seem to prohibit chaining multiple skip instructions at the hardware level.

If we are skipping, then output W is low, and “SKIP” will be low on the next 4 MHz clock cycle so the skip acts on the next instruction.

The E17 mux controlled by the destination bits will be disabled when “SKIP” is low (skipping).

The registers cannot be written to if we are skipping. Register A has an additional restraint with the “A CLK DIS.” that will prevent writing if high.

Notation note: the symbol \(\lor\) is used to represent a logical OR condition.

  1. No skip (input connected to GND)

  2. Negative (checks ALU 15)

  3. Carry (checks the carry out from ALU)

  4. Positive (checks \(\overline{\mathrm{ALU}\ 15}\))

  5. \(\overline{\mathrm{OF}}\) (checks quite a bit of logic! TBD)

  6. \(\overline{\mathrm{OF}}\ \lor\) Negative

  7. \(\overline{\mathrm{OF}}\ \lor\) Positive

  8. Always (input connected to +5 V)

Notes on the \(\overline{\mathrm{OF}}\):

Uses A MUX 15, LAT B 15, ROM OF (ALU ROM, “XA”), and ALU 15.

A/D

Analog audio is converted to a 15 bit word: 12-bit value with three leading scale bits (pg. 17 of the 1980 user’s manual). 2 of the scale bits correspond to the switchable gain setting used while converting. The 3rd scale bit, plus the 16th bit, are sign bits. A/D conversion begins at the analog circuit (page 36 of service manual PDF). Page “EMT-9” shows the computer’s interface to the analog circuit. There are some minor naming differences for the same signals between the computer and analog schematics; use the pin numbers on the analog board referenced against the J1 table on “EMT-1” if there is any confusion. There is some back and forth between the analog board and the computer (see below), and eventually a digital word is sent serially to the computer (“A/D SER DATA”). The computer adds the scaling used for that conversion to produce “A/D SCALED DATA”, which is sent to the +t\(_d\) delay line on “EMT-7”. 3 different paths can be taken with the same serial stream resulting in output registers A/D #1-3. The CPU can access the registers via the I/O mux.

For the EMT 250 programmer, the only interface is the “START A/D” instruction and reading the A/D registers from the I/O mux.

A/D hardware

A successive approximation IC (Am2504) and 12-bit DAC IC (BB DAC80) make up the core of the analog to digital converter (user’s manual page 24).

The user manual’s converter offset adjustment procedure indicates that a digital word of 2048 indicates a zero voltage input and numbers higher indicate a higher voltage and lower numbers indicate a lower voltage.

Supporting circuitry causes a trigger if the input voltage to the converter is outside of \(\pm\)2.5 V. The trigger causes a previous amplifier stage to reduce the gain. There are 4 possible gain setting for the previous stage and the final gain setting is encoded into the two most significant bits (after the sign bit) of the stored digital word. The D/A section has similar programmable gain amplifiers that perform the inverse gain reduction for each sample.

START A/D

If E16 is active (see relevant section), then a low output 6 indicates the “START A/D” instruction was given. This low output will set flip flops C7\(_B\) (triggers “CONV CLK” and “CONV CMD”) and C3\(_A\) (triggers “\(\overline{\mathrm{T}}\)/H”) (threshold).

As explained in the program ROM section, the programmer is responsible for calling the “START A/D” command as often as needed for the target sample rate, which is about once every 166 instructions at 4 MHz for a 24 kHz rate.

Analog board interface

Analog board to computer signals

Computer to analog board signals

+t\(_d\) delay line

The 2-bit value of the +t\(_d\) control is directly wired to C1 (“EMT-7”), which selects taps from a long series of serial shift registers (Signetics 2533).

“SSR DATA” connects the scaled (sign and S1/S2 encoded) A/D result from (9) to the delay line (7). “SSR CLK” is from “SHIFT CLK” (9).

D1 is a Signetics 2518 hex 32-bit static shift register. Sections 1-4 are used.

There should be a rapid sequence of 1s and 0s flowing through all the shift registers that can be roughly observed with a simple oscilloscope probe. If any output is stuck, that IC is probably dead. These are rare ICs but perhaps some SMD components on a DIP-8 sized PCB could be designed to cheaply replace them.

A/D Registers

Six 74LS164 8-bit shift registers are used to store and access the output from the A/D. The registers are paired into three 16-bit registers named “A/D #1”, “A/D #2”, and “A/D #3”. All three appear at the I/O mux.

REV and SPC are the only two programs to use all 3 A/D registers. CHOR, PHAS, and DEL only read from A/D #1. ECHO only reads from A/D #3.

D/A

Page “EMT-8” shows the computer’s D/A circuit. There is a typo on X23: what appears to be “4 10” should actually be “10 8” (pin 10, output 8).

To do: we need a timing diagram. The output of the ALU has a 12-bit audio sample plus 2-bits for the gain controls, and perhaps something else in the remaining 2-bits (could be stop or parity; there is a xor with a ‘stop’ label…). The ’195 shift registers are arranged to shift the lower bits up and the upper bits out.

At some point in the timing, the parallel outputs of the ’195 shift registers are sent “out” via the appropriate channel gate. Documenting the state of the shift registers when the gate command signal occurs should clear up which bits are audio.

START D/A

“START D/A” resets the counters V22, V23, and X20. It also goes to NAND gates P22. Counter V22 is effectively a divide-by-8 for the 4 MHz clock (500 kHz).

Counter V23, and its decoder, X23, control which output channels are active. The AND gates on N21 are control signals to select which output (I, II, III, or IV) is active.

Output I is active on count 3.

Output II is active on count 5.

Output III is active on count 7.

Output IV is active on count 8.

Counter V23 also controls the read address for the D/A registers (L22, H22, H21, and H20 - all ’670 registers). The read address A and B inputs are wired directly to the counter’s B and C outputs, respectively, which means the register being read is counting up once every two 500 kHz clock cycles (250 kHz).

LOAD D/A

“LOAD D/A” increments the write address for the registers and controls the write enable pin. X20 forms a simple 0 to 4 counter. The “LOAD D/A” signal is coming from the I/O Function Select mux on page 4. The signal is active low (it is normally high when idle). The first “LOAD” signal after “START” should write the current ALU output into D/A register 0, and the rising edge of “LOAD” resuming it’s normal high state will advance the register address to 1. The next “LOAD” writes the current ALU output into D/A register 0, and the address increments. This continues two more times so register addresses 0-4 all have data.

Presumably the instructions trigger “LOAD D/A” fairly quickly compared to the reading of the D/A registers. The reading is limited to changing at 250 kHz, but the writing is limited to the speed of toggling the “LOAD D/A” line, which probably requires two 4 MHz cycles to set and reset the I/O Func Select mux. Further inspection of the I/O Func Select mux (E16, page 4) is required. It may have some logic that allows for quickly toggling “LOAD D/A”; TBD.

“LOAD D/A” is attached to I/O Function Select 0 (only active when IR11 is high, so the whole I/O Func word is \(1000_{2}\) or \(8_{16}\))

Main memory

The main memory has a 13-bit address that can be set by transferring the ALU result to the memory address register (MAR). 13-bits allows for storage of 8,192 16-bit words. After writing to the MAR, the memory output register (MOR) is updated after 3 instruction cycles and can be read from.

After setting the MAR, a new value can be stored by writing to the memory buffer register (MBR). The RAM requires 450 nanoseconds for its write cycle, which is 2 instruction periods. When the RAM write instruction is given, dedicated hardware holds the RAM write line low for 8 cycles of the 20 MHz clock. Thus, two memory writes cannot appear adjacent when programming the ROMs.

All the programs use Register B, address 3 (B3) as a pointer to keep track of where the next input values should be stored.

The main memory is large but slow and is therefore used to store audio samples and create delay lines. However, it can store arbitrary data as well and the programs make use of the main memory by dynamically partitioning it in relation to the B3 main memory pointer. For instance, sample data can be thought of as being stored “behind” the pointer, while intermediate calculations can be stored “ahead” of the pointer.

RAM details

The original RAM board has 8 rows of 16 1024x1 bit RAM ICs. Each RAM IC had 10 pins for the address connected to the “MAR” latch. 3 additional ALU bits control a 3-to-8 decoder IC to select a row of RAM.

The second RAM board has 2 groups of 16 4096x1 bit RAM ICs. Since the 3-to-8 decoding from the main board no longer made sense, the new RAM board has extra logic to encode the 8 “CE” lines back into 3 address bits. It does not simply reverse the logic of the decoder, but maps it in the following way: “MEM ADDR CE”(0:7) maps to 74148 inputs 4, 5, 3, 2, 7, 6, 1, 0.

This mapping results in the desired behavior of creating two groups of memory, “A” and “B”.

In the programs, the memory location pointer will just auto-increment and wrap around as an unsigned 16 bit integer. Since the memory circuit ignores the most significant bits, this does not cause any issue.

Troubleshooting

The 1980 manual mentions a rhythmic 3 Hz sound indicates bad memory. Running the machine with no RAM chips, and installing 1 bit pair (group A/B) at a time can help track this down. Running the machine with the higher bits removed results in non-rhythmic, random noise. Inserting each bit pair in sequence from LSB to MSB, you will eventually add in an IC that introduces the rhythmic noise, and then you can just swap a good RAM with A or B to determine if one or both are defective.

Multiplier memory

RAM details

The multiplier memory is shown in the overview page as 16 bit words in 16 addresses. It also includes 2 extra bits that save the \(\overline{\mathrm{OF}}\ \lor\) Negative and \(\overline{\mathrm{OF}}\ \lor\) Positive status results. See page “EMT-2” for the schematic. The saved “overflow or negative” result is part of the logic to strobe the I/O mux (“EMT-3”). The saved “overflow or positive” result works with IR11 to control the MPLR MEM (also “EMT-2”).

The address for the multiplier RAM is set by IM 3:0, which means the RAM addresses are hardcoded in the ROMs. The RAM data input is connected to the ALU output.

In addition to remembering the status of an operation, the multiplier memory has no delay, so it is appropriate for storing intermediate results and magic constants used for the DSP.

The “WRITE SP” line enables the multiplier RAM write when low. The E16 decoder will enable this line when the I/O function select nibble is 0x2, 0x7, 0xA, or 0xF. In addition to the lower bits selecting the outputs to drive the gate controlling “WRITE SP”, bits 11 and 8 prevent E16’s G1 input from disabling the chip. However, the E16 G2 input can disable a “WRITE SP”. “WRITE SP” requires that the destination bits are set to “I/O” (destination 1).

Multiplication

Logisim of the “LD MPLR” signal.

A dedicated multiplier circuit allows multiplication to happen in parallel with the ALU. The multiplicand is always the ALU result and the multiplier can be sourced from the multiplier memory or a literal value from ROM. “EMT-5” shows the multiplier circuit. There is a 3 instruction cycle delay before the result is available at the product register. A new multiplication operation can be loaded while awaiting a previous result; this feature is used extensively in the reverb program.

The 20 MHz system clock drives the clock input of shift register E9. This part of the schematic is illegible and had to be traced out with the machine. The parallel “A” input to shift register E9 comes from the “LD MPLR” (4) signal, which corresponds to the destination setting “IO” (destination = 1). Figure 1 shows the “LD MPLR” timing simulated in Logisim. The “LD MPLR” line is usually high and just pulses low. The pattern shown in Logisim (see figure 1) is also observed on the machine: pulses low on the “LD MPLR” line are followed by 3 pulses that clock the “PPREG” flip-flops.

The AM25S05 4-bit by 2-bit multiplication ICs perform the function \(S = XY + K\). The \(X\) input comes from the ALU output bus. The \(Y\) input is select by IR12 (the “mulnd sel.” bit) which can be either IR[7:0] or the multiplier memory \(\overline{15}\) and [14:8] (high byte, with the MSB inverted). \(K\) comes from the PPREG (partial product register) which is the result \(S\) latched. PPREG is made available at the debugging headers.