Saturday, September 7, 2024

Koogo Analog Delay schematic (Donner Yellow Fall)

    I've been experimenting with controlling analog effects pedals, like this chorus. I bought a cheap "Koogo Analog Delay" to try to repeat my success. Turns out that it's not analog at all. It's the same digital PT2399 chip that seems to be in every delay. It does have a leg up by adding a sa571 compander though. Turns out this is the same design as the Donner Yellow Fall pedal; It's just been rebranded.

    I decided to draw a schematic in case there was anything to learn from it. I didn't add any capacitor values since they're not marked, and would have to be desoldered and measured. I did put in a few speculative values though.

    The PT2399 lives on a daughterboard and follows the datasheet design pretty closely. So closely that I just copied and pasted the last schematic I made from a PT2399 board.

PT2399 daughterboard

    
    The main board isn't too interesting either. It uses variations on the compressor and expander from the SA571 datasheet.

    
    An extra lowpass filter has been added before the expander. This is probably to help knock down some of the aliasing noise that would throw off the envelope detector of the SA571.

    A bypass FET has been put in the feedback loop so that you'll still get "tails" when turning off the circuit. This means that the delayed signal won't be immediately cut off; The last repeat will ring out, but no additional repeats will be created.

    The input buffer adds pre-emphasis, boosting the high frequencies. The summing amp is the complement to it, doing de-emphasis duty. These cancel each other out, and have no real effect on the dry signal. The benefit is to the signal-to-noise ratio of the delay line. By de-emphasizing (low passing) the output of the delay line, the high frequency noise can be greatly reduced.

Mainboard schematic


    I think these additions were inspired by actual analog pedals, despite the delay line being digital. You can see the pre/de-emphasis, lowpass filter, compander, and feedback bypass in the Boss DM-3

Boss DM-3


Saturday, August 10, 2024

Adding CV to the Electro Harmonix EH400 Mini Synthesizer

    This is a follow up to our previous look at the EH400 here. Now we're investigating methods of voltage controlling the oscillator.

    As a reminder, this is what we're up against. It's similar to a relaxation oscillator, but it's been modified to charge through a resistance labeled "keyboard".

The original oscillator circuit

Get your VCRs ready

     One approach to adding CV would be to replace the resistor with some kind of voltage-controlled resistor (VCR). These circuits are a bit uncommon though. Another difficulty would be figuring out the relationship between resistance and frequency, then replicating it in the VCR. The saw recharges quite slowly because of R2, and this impacts the relationship.

Update

    I decided to graph the resistance that corresponds to each of the 24 note (1 being the lowest, 24 being the highest). With the help of a curve fitting tool and Wolfram Alpha, I ended up with this formula: resistance(k) = 188.198 - 44.8472 * e^(0.0574576 * note)

Current affairs

    We can do away with the resistance worries by instead forcing a current into the timing capacitor C2. We could then use a much more conventional voltage controlled exponential current source, instead of a VCR. This is a circuit that's very common in synthesizers, and will give us a standard 1 volt per octave response, while also being relatively temperature stable.
    There are some voltage requirements that make the oscillator a little hard to current control though. The cap needs to swing from 2V to 4V. The typical expo source can't do this directly, but we can add a current mirror to help it along.
    Here we've added a standard expo source (actually a current sink). We've also lowered R2 to 1k to help mitigate the slow recharge time.

Expo sink and current mirror design

    This mostly works, but the tuning goes flat on the low end. I'm unsure what to blame this on, maybe the current sink. Regardless, it's back to the drawing board.

Derivation

    Part of the trouble with this oscillator is that it's too different from typical VCOs. How can we bring it more in-line without replacing it entirely? Well, we have to look at it differently. What we've been calling a "modified relaxation oscillator" can also be thought of as a variation on a schmitt trigger.


Schmitt Trigger

    The majority of VCOs have a schmitt trigger in them somewhere, and many of them are related to this schmitt + integrator design:


    By adding an integrator we can turn this into a more normal oscillator, one that lends itself to being voltage controlled. We only have to make minimal changes to the original board to accomplish this. The original timing cap needs to be removed, and the integrator needs to be connected in its place. If we want to replicate the original's sawtooth waveform, we can tap the "pulse" output and use it to reset our integrator. As a bonus, this resets much faster than the original oscillator did, and pretty much cures the slow reset problem. Now we have a fairly conventional oscillator.


Sinking lower

    With our new oscillator design, the exponential current sink becomes more useful. It doesn't have to make the capacitor swing to any voltage, not directly anyway. The integrator does all the work, while presenting a relatively constant voltage to the current sink.

    Since the integrator is the one charging the cap, it does have to worry about the voltage swing. It must reach both 2V and 4V. If we run it using half of VCC as our AGND, then we'll run into a problem on reset. The reset pulse will only bring it down to 6V/2 = 3V, and not the 2V that we need. This is because the reset pulse "closes" T3 and turns the op-amp into a unity gain buffer. This effectively forces the AGND voltage (from the non-inverting input) to show up at the output.

Unity gain buffer

    We can fix this by lowering our AGND voltage to below 2V. We just need to play with the values in a voltage divider until we come up with something that's a safe margin below 2V. Our 6V supply into 33k + 15k yields 1.875V.

    Here it is all put together. Conveniently, it only requires one quad op-amp to add the expo sink, integrator, and buffers. Falstad link here


The complete CV circuit


    

Saturday, August 3, 2024

Atari XC12 FSK Decoder

     I have a bit of a fascination with tape storage interfaces. They're just an interesting junction between analog and digital. How do you make a computer talk to a cassette? It turns out there are many answers to that question, but here's a quick look at one.

    The Atari "Program Recorder" is a line of cassette storage devices made for their 8-bit range of computers. The last of the line was the XC12 from 1986. It stores data using frequency shift keying that we looked at previously. The two tones required are generated by the computer, but they're decoded by the XC12. How though?

Normalizing

    First the signal is normalized (brought to a consistent volume) by an op-amp with diodes in the feedback path. This is actually a clipping amplifier, as used in distortion pedals.

XC12 Clipper

more reading here

Decoding

    The core of FSK decoding is discerning between the two tones used. In this case we're using 5,327 Hz and 3,995 Hz. Atari took the very analog approach of separating the tones with bandpass filters. The high tone will pass more through the top filter, and less through the bottom filter. The opposite for the low tone. This isn't particularly responsive, nor precise.


    The two filters then feed simple diode-capacitor envelope followers. The idea is to extract the amplitude of each signal, rather than the tones themselves. A good deal of the tone still spills though tough.

XC12 filters

Comparing

    An op-amp setup as a simple comparator is the trick to countering the slop of the filters. We use it to test what filter has a higher amplitude, and the winner dictates the logic level of the output. This means that the output of the filters + envelope followers can get away with being quite messy, so long as the correct one is higher than the other.

    

Cleaning

    Unfortunately, the comparator alone isn't enough to scrub the noise from the filters. They change amplitude rather slowly, meaning they'll sluggishly cross over each other while jittering around. This puts the wrong signal at the higher amplitude, and the comparator will momentarily give the wrong result. A lowpass filter is used to remove these glitches from the comparator's output. Finally a transistor buffers the digital output.



Simulating

    It's always interesting seeing these circuits in action, so I recreated it in falstad. Link here

    For input two oscillators, a clock, and a digital switch are used to generate a signal that toggles between 5,327 Hz and 3,995 Hz. This gets squashed by the clipping circuit and sent to the filters.
    We can see the output of the envelope followers slowly ramping up and down as the frequency changes. We can also see how much of the tones end up in what should be the envelope of each signal.
    Finally we get a square wave out that tracks the original clock used to switched the tones.



Friday, August 2, 2024

PWM Chorus Control

    I'm a fan of synths that have analog choruses built in. The Juno 106 and Poly 800 are two popular examples. Strangely, neither gives you proper rate or depth controls for the chorus. I thought it would be interesting to not just include these controls, but to store them in a synth's patches. This means that the CPU needs a way to interact with the chorus circuit.

    In the modern day, we have a number of options for adding digital control to an analog circuit. A DAC can bridge the gap if the circuit is already voltage controlled. A digipot can do the same if it's resistance controlled. A less common, and more interesting approach, is to pulse width modulate(PWM) a CMOS switch. We already looked at Pearl's use of this in their Drum-X.

Switches as resistors

    A CMOS switch can act somewhat like a variable resistor when turned on and off very quickly. The more time it's on (relative to off) the lower the effective resistance. That's all PWM is: a change of the on-time relative to the off-time (duty cycle). Two of these variable resistances can be put together and used like a potentiometer. The trick is to increase the resistance of one, while decreasing the other. The idea being that the total resistance should stay roughly the same, and only the ratio of resistances changes.

PWM

    The nice thing about pulse width control is that it's easy for most microcontrollers to generate. Virtually all of them have timers with special facilities to output a variable pulse width signal. At the same time, it's quite easy to generate a PWM signal in an all analog circuit. You can simply compare a CV source to a saw carrier wave. The output will be a pulse wave where the width is proportional to the CV amplitude.

PWM diagram from PCBhaven

Chorus circuit

    I'm working with a clone of the Ibanez CS9 chorus pedal, branded as a KMISE Classic Chorus. The pedal generates a triangle wave that it then uses to modulate the clock of a delay line. The rate control adjusts the frequency of this triangle wave LFO, while the depth adjusts the amplitude. Here's the corresponding portion of a very similar chorus circuit:


LFO with rate and depth potentiometers


Switches as potentiometers

    Notice that both the rate and depth are controlled with potentiometers set up as voltage dividers. This means we need to fake four separate resistances and maintain the ratios we discussed before. We can make this much simpler by using double-throw CMOS switches, like the ones in the CD4053 IC.

    Each throw is provided by its own switch internally, but the two are set up to have opposite states: one is open while the other is closed. So, they will also maintain opposite duty cycles when we PWM the pair. If one is closed 25% of the time, the other will be closed 75%, always "adding up" to 100%. This equates to resistance, meaning they will always maintain the same total resistance between them. This makes it easy to use the two throw switches together as one potentiometer.

Rate control

    Let's apply this to the rate knob. You can think of one throw as giving the maximum rate, and the other giving the minimum rate. You can see a small hitch when the PWM signal is low. This is the time spent at the minimum speed. If we do this very quicky, the hitches become negligible, and the rate averages out based on the ratio of time spent at the two extremes.


 

Depth control

    Now we'll look at the depth knob. If we use the same trick, we don't get the same tiny hitches; We get deep bites taken out of our signal.


slow carrier PWM

    This is exaggerated by the slow PWM carrier frequency used to illustrate the result. In practice we use a much faster carrier, and the results are less dramatic. Bites are still take out, but they're much narrower, and more rapid. More rapid means they're high(er) frequency noise, and we can lowpass them away. Notice that the schematic already has a lowpass filter on the output of the depth knob: R34 & C20. If we probe after this lowpass, we see (in yellow below) a much more normal triangle with a lower amplitude based on the PWM duty cycle. You can think of the low pass as having stolen some of the peaks to fill in the valleys.

fast carrier PWM with filtering

 

Hardware

    The ubiquitous Arduino can give us the two PWM signals. The analogWrite() function can be used to generate 980Hz PWM signals on pins 5 & 6. This is quite slow in the audio world, but still fast enough relative to our slow LFO, and lowpass filter. So, if you use an Arduino as the brain for your synth, it would be able to store and recall your chorus settings. It would only need a humble CD4053 to actually control the chorus. No passives required.

    The 4053 includes three double-pole switches, meaning we have one free after controlling rate and depth. This last one can be used to switch the effect on and off. It could be PWM'd to mix the wet and dry signal, but it would require a very high carrier frequency to allow the full audio spectrum to pass through unaffected. Note that some choruses already include a way to turn the effect on/off via a digital signal. This clone happens to use "true bypass" instead.


 

Other ideas

    Instead of controlling the LFO, we could have replaced it entirely. This might be a good option if your micro is well equipped to generate its own LFO output. This also opens up the possibility of new waveforms.

    Or we could have generated CV and converted it into PWM instead of generating the PWM signal directly. This would make more sense for a micro that can't generate any (additional) PWM outputs, or is already set up to generate a large number of CV signals. Many synths multiplex one DAC to multiple outputs, and it would be easy to tack on two more for the chorus.

Saturday, July 13, 2024

Boss DR-220 Gate Array (MB670120) Interface

    I've wondered for a while how exactly the CPU of the DR-220 controls its gate array. The CPU handles the screen, buttons, and triggers. The MB670120 gate array controls ROM, RAM, and the DAC + multiplexer for playing sounds. Interestingly, the two are separated onto different boards that are joined by a pin header. This makes it very easy to separate them and experiment.

Pinout

    The service manual tells us the connections on the header, but it lists the pins in no particular order. Here they are laid out in the order they appear on the board. The signals of interest are underlined, while the others are in grey.

CPU Dir

Feature

Pin

Pin

Feature

CPU Dir

Out

OE

30

1

WR

Out

Out

CS

29

2

GND


Out

ALEL

28

3

ALEH

Out


GND

27

4

Trig-In

In



26

5





25

6



IO

B7

24

7

B6

IO

IO

B5

23

8

B4

IO

IO

B3

22

9

B2

IO

IO

B1

21

10

B0

IO

In

CLK1

20

11




GND

19

12

GND



+5V

18

13

+5V


In

CLK0

17

14

Trig-Out

Out

In

RST

16

15

CLK2

In


General Communication

    The manual also explains the mechanics of communication, but not the significance of it. The gate array determines what sounds to play based on the contents of RAM, and the CPU accesses RAM/ROM through the gate array.
    The CPU can't directly tell the gate array to do anything besides access memory for it. This means there's no instruction to "play a sound right now". Instead, it simply tells the gate array to store a specific value in a specific range of memory. A split second later, the gate array reads back the value, and plays the corresponding sound.

Timing

    The timing is provided by the manual. We're also told what signals are involved. I've redrawn the diagram here. 

MB670120 Gate Array Timing Diagram


    We have a parallel bus, but no dedicated address lines. Instead the bus is multiplexed, similar to some CPUs like the 8085. We specify a 16 bit address, one byte at a time. First the high byte is put on the bus, then the ALEH signal is brought low. This latches our values into an internal address buffer. The same is done for the low byte of that address and ALEL. The data is then put on the bus, and finally we strobe the write line. This stores a value into RAM.
    Curiously, the CPU can't read from RAM; Only the gate array can. This helps show that the RAM access is really just a way to communicate with the gate array.

Addresses

    The last bit of info that the manual gives us is the range of addresses (0-5), though it doesn't exactly say what they do. It turns out these 6 addresses correspond to 6 outputs(channels) of the multiplexer. Different samples(instruments) are hardcoded to these channels. Since we have 11 instruments, some have to strategically share channels.

Instrument

Address

BD

0000

SN

0001

LT

0002

MT

0002

HT

0002

RIM

0003

HCP

0003

OH

0004

CH

0004

RCY

0005

CCY

0005


Data

    So, what values do we put in the addresses to play sounds? The manual has no more answers.
By connecting a logic analyzer to our header, we can see the values sent to the gate array. With a little experimentation, it becomes obvious what the different values correspond to.
    A single byte per address specifies the volume, pause/play status, and instrument for the channel. That's really all we really need.


Bit Values

Effect

Bit #

7

6

5

4

3

2

1

0


Name

?

Vol2

Vol1

Vol0

Play

Inst2

Inst1

Inst0



X

X

X

X

0

X

X

X

Not Playing


X

0

0

0

1

X

X

X

Min Volume


X

1

1

1

1

X

X

X

Max Volume


X

X

X

X

1

0

0

1

Play Inst #1


X

X

X

X

1

0

1

0

Play Inst #2


X

X

X

X

1

1

0

0

Play Inst #3

  • The most significant bit appears to have no impact
  • The next 3 MSBs set the volume (The range is greater than what the CPU actually uses)
  • The next bit says if the channels should be playing or not
  • The last 3 bits specify the instrument
    There's a maximum of three instruments per channel, but 3 bits give us 8 instrument values. Unfortunately, the unused combinations don't yield any interesting results. You'll simply get one of the normal sounds for the channel, not a combination or a hidden sound.

Wrapping up

    Now that we have the pinout, protocol, memory map, and packet structure, we can play some drums! The bus is parallel, the speed is relatively slow, and the timing is forgiving, so most old CPUs should have no problem talking to the gate array. Newer microcontrollers should have it easy too, besides coming up with a dozen outputs. Since we're using the bus in only one direction, we can use a shift register to get extra outputs.
    Now we can interface anything an arduino can be connected to. This opens up the machine immensely, given that it started with only a trigger in/out. MIDI would be an easy choice, but the sky is the limit.