So my MFOS Mini Synth is working and a treat to the “synthetophile” ears. But at the time being it makes just experimental noises … what about connecting a keyboard and playing some lead synth lines?
Nope, the MFOS Synth has an analogue CV input (CV = control voltage) + external trigger. Do you have a CV compatible keyboard at home? (Or at least ever seen one with your own eyes?) – No! – But all my keyboards have a MIDI output … so I would need a …
MIDI to CV converter.
I found a first inspiration here:
This project utilizes an AVR microcontroller which controls a standard 8 bit DAC with an 8 bit parallel interface. The microcontroller receives the MIDI data through its serial interface (UART).
Now I wondered if it was possible to add nice features like pitch bend control, portamento and modulation to this bare bone concept. The answer is yes, with a few tricks and inexpensive components:
For this project I used an ATTiny 2313, it’s cheap and very sufficient for the job. As in the project from analog-synth.de I use a standard 8 bit DAC to generate a CV signal. In addition to that I use three independent PWM channels for the “extra goodies”.
Let’s start with how I generate pitch bend functionality:
That’s pretty straight forward. While no pitch bend control arrives via MIDI, the pitch bend PWM pin generates a rectangle wave with 50% duty cycle. Moving the pitch wheel on the controller keyboard results in changing the duty cycle. After applying a low pass filter (RC filter) to the PWM signal, I get a MIDI controllable offset voltage that I simply add to the CV signal from the DAC (with the help of a summing amplifier). I can adjust the pitch bend range by using a trimmer potentiometer as a voltage divider (not shown in the block sketch). I set the range to be +/- two half notes.
Now how does the modulation control work?
I generate a low frequency triangle wave using a double op-amp. The triangle wave is then “chopped” by an analogue switch (MOS 4051, better not 74xx4051) which is controlled by another PWM output of the microcontroller. The resulting signal is then low pass filtered, this removes the undesired high frequency parts introduced by the modulation. I have effectively amplitude modulated the triangle wave with my PWM signal. Needless to say that the PWM frequency has to be relatively high compared to the triangle frequency. The following picture should make it clear:
Now I have a triangle shaped time dependent voltage that I can modulate in its amplitude between 0% and 100% with the mod wheel on my keyboard. The absolute range is adjustable via another trimmer potentiometer. I set it to something like +/- one half note. This voltage is also added to the CV signal inside the summing amplifier.
Now the most tricky part was implementing the portamento (some people call it “glide”) feature. I thought really long and hard about that. The glide effect can easily be achieved by low pass filtering the CV signal from the DAC, i.e. charging/decharging a capacitor with the CV voltage through a resistor. The time constant (R*C) of the filter determines the glide speed. So to alter the portamento time you could just use a potentiometer as “R”. But as you were able to see in the pictures in the last article there is no more space left for knobs on the front panel. Plus I want to control the portamento time via MIDI because I want to glide between notes only while playing legato, i.e. keep holding down the previously played key. How to change the time constant of a low pass filter digitally?
I made use of an analogue switch again! I employ it between the DAC and the RC filter and drive it with yet another PWM signal from the microcontroller. When the switch is closed the capacitor is charged, when the switch opens, the capacitor keeps its current fill state. If I drive the switch with a PWM signal that has only 50% duty cycle then the capacitor takes twice as long to charge as in the case of a closed switch. If I drive it with 33% duty cycle … three times as long … and so on. In my actual design I used an analogue multiplexer to both apply PWM and select between three different fixed resistors and a direct short (see schematic for details). With the three different resistors I create three different slopes in my portamento time function. This comes close enough to a logarithmic response of the control (lets you cover a higher dynamic range of possible glide times). Here’s a theoretical plot I made with octave:
If you wonder about the “steppy” artefacts on the right side of the curve then contemplate this: You want to control the glide time. You have (linear/proportional) control over the duty cycle of the PWM signal. The discretely valued duty cycle is inversely proportional to the glide time (glide time ~ 1/duty cycle). This means that you have a quite good resolution for short glide times and relatively bad resolution for long glide times (even for 10 bit PWM mode). The three resistor solution helps counteracting that problem because large subsections of the slope can be “recycled” with another multiplier (higher R).
Oh, I almost forgot: The portamento time is controlled with the MIDI CC 5 signal. (MIDI Control Change No.5, assuming you start counting with 0)
Last but not least I added some power supply features:
The whole box (synth and MIDI2CV) are powered by a single 12V DC power supply. The synth needs +9V and -9V and the AVR needs +5V. The positive supply voltages I provide through linear fixed voltage regulators (LM7809, LM7805). For the negative supply rail I use a charge pump IC (LT1054) that is able to invert my incoming +12V. The resulting minus “eleven-dot-sth.” volts are cropped by a negative linear fixed voltage regulator (LM7909) to clean and smooth -9V. I power my synth with a 12V 0.6A DC switching wall power supply that I bought on http://www.pollin.de for two or three Euros.
IMPORTANT: Never connect the metal heatsink part of the 7909 (or any similar negative voltage regulator) to GND. Especially do not connect electrically to the heatsinks of the other regulators (which ARE connected to GND, that is the mean thing). I grilled most of my ICs by accidentally shorting the heatsinks with a screwdriver. That’s why you see shrinking hose around one of the regulators in the pictures 😀
Ah before I forget: Sorry my layout is so terribly crowded. But as you see in the pictures, it had to fit inside the box by all means!
The microcontroller firmware
The microcontroller listens to incoming MIDI packages on it’s UART. Decoding MIDI information on an AVR is no magic and there are some very good instruction documents around. If you are interested in that field, I advise you to read “MIDI and the AVR” .
So what the microcontroller does is pretty straight forward. Decode incoming MIDI, i.e. distinguish between note on, note off, mod wheel change, pitch wheel change and particular control change (for the portamento) events. It then translates the note and control parameters to their relative DAC and PWM settings.
What I think has to be mentioned is the use of a memory stack which is used in the following way:
When a note on event arrives -> store the note number (~tone pitch value) on top of the “note stack”
When a note off event arrives -> search through the stack and remove the corresponding note from the “note stack”
Always “play” the note which is on top of the stack.
This way if you press key #1 and hold it down while you then press and release key #2, the synth will first play pitch #1 then jump to pitch #2 and then, thanks to the memory stack, play pitch #1 again (until the note off-event for key #1 arrives).
I also use the fill state of the note stack to determine when to glide between two notes and when to jump:
If the stack is empty (no currently pressed keys) then jump directly to the note that is subsequently played.
If the stack already holds one or more elements then glide to the note played next.
The same way you get your gate signal almost for free:
If the stack is empty: Gate pin = low.
If the stack is partially filled: Gate pin = high.
What I totally forgot to explain is the reasons for all the potis!
1) RV_TUNE1 poti (MIDI to CV section):
This poti adjusts the scaling of your tonal output range. In other words: How much space( mV of CV voltage) is there between two neighbouring half tones. Connect a voltmeter between CV-Out and GND. Play two notes on the MIDI keyboard that are one octave apart. The output voltage should change by 1V. Then you have a CV signal according to the 1V/octave standard.
2) RV_BIAS1 poti (Mixer Section):
This poti adjusts the offset voltage of the CV signal, i.e. the absolute position of your tonal output range. Keep it in a middle position for the start or adjust to your needs, i.e. the CV input range of the synth oscillators.
3) RV_TRIG_FREQ1 poti (Triangle Generator):
Sets the speed of the Modulation vibrato. (set to ~4Hz or to taste …)
4) RV_MOD_AMP1 poti (Modulation Section):
Sets the depth of the Modulation vibrato. My desired vibrato depth is ~slightly more than one half tone (set by ear).
5) RV_PBEND1 poti (Pitch Bend Section):
Sets the tonal range of the pitch bend control. Standard setting would be +/- two half tones (set by ear).
I advise you to use multiturn trim potentiometers for all variable resistors in this project.
Pictures from the build:
May 15th, 2013:
Please note that I made a mistake in the schematic! The capacitors next to the quartz are actually 22p not 22n! The quartz is 12 MHz, I forgot to tell you that, too.
July 27th, 2014:
Cleaned up the schematic and the KICAD project files, everything should be fine now. By the way, the pin “gate_mode” in the schematic has no meaning at all.
July 21th, 2018:
Please mind the fuse bits!
The fuse bits are three 8 bit registers that define certain basic settings of the ATTiny 2313 (as well as in other AVR micros). In particular the fuse bits determine what clock source the microcontroller should use. You are right, without the correct fuse bits my MIDI2CV converter should not work at all :D. By default the ATTiny 2313 uses its internal (not so precise) RC oscillator, running at 8 MHz. This clock is then divided internally by a factor of 8.
But we want: use external quartz running at 12 MHz, no internal clock division.
We achieve that by setting the following fuse bits:
low fuse: 0xf9
high fuse: 0xdf
extended fuse: 0xff
if you use avrdude to flash your chip then you would use the following arguments
avrdude -c [your programmer] -p attiny2313 -P [address of programmer] -U lfuse:w:0xf9:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
fuse bits are not magic, but I agree they are not very human readable.
but you can help yourself with the following website that translates fuse bits back and forth:
July 23rd, 2018:
MIDI jacks are connected like this:
or view the project’s Github page