My father plays in a band and he uses multiple MIDI sound modules with an old Akai MPC60 serving as a MIDI controller. The MPC60 is getting quite old and seems to be less reliable after all these years of service, so when I heard my father was looking for a new MIDI controller, I started thinking about building one for him.
Like with most controller circuits, I started out with a PSoC micro controller. I chose the CY8C29466-24PXI) as this controller has room for 8 communication blocks, which I used for 4 MIDI outputs, 2 MIDI inputs and an RS232 UART for communication with a PC (laptop/netbook) through USB-to-Serial cable. With all 8 communication blocks used up, there still are 8 other configurable digital blocks left for other general stuff (Timers, PWM, etc…).
I haven’t made any schematics of the circuit itself, but it’s pretty straight-forward.
A simple google image search returns a lot of useful MIDI-interface circuits. I’ve used a couple of 74HC14 inverters as a buffer for the MIDI outputs and 6n138 opto-couplers for the inputs. All resistors in the midi-interface circuit are 220 Ohms.
The power supply is built around a LM2574HVN-5.0. There are 4 diodes configured as a bridge rectifier followed by a 220uF/35V capacitor at the power input so the controller can accept both DC and AC adapters of a wide voltage range.
The RS232 interface is a standard interface using a MAX232 and a handful of 100nF capacitors.
MIDI Controller API
The controller supports 4 layers, which means that one midi message on any input can be routed to a maximum of 4 channels (on the same or multiple outputs) at the same time
- int midi_setoutput(struct midi *m, int layer, int input, int inchannel, int output) // Set the physical output to which a certain input/midi channel combination for this layer should be routed to
- int midi_setchannel(struct midi *m, int layer, int input, int inchannel, int channel) // Set the output midi channel to which a certain input/midi channel combination for this layer should be routed to
- int midi_setvelocity(struct midi *m, int layer, int input, int inchannel, int velocity) // Set the velocity of this input/midi channel combination for this layer anywhere between 0-200%
- int midi_enabled(struct midi *m, int layer, int input, int inchannel, int enabled) // Enable/disable this input/midi channel combination for this layer
- int midi_getoutput(struct midi *m, int layer, int input, int inchannel) // Get the physical output to which a certain input/midi channel combination for this layer is currently routed to
- int midi_getchannel(struct midi *m, int layer, int input, int inchannel) // Get the output midi channel to which a certain input/midi channel combination for this layer is currently routed to
- int midi_getvelocity(struct midi *m, int layer, int input, int inchannel) // Get the velocity of this input/midi channel combination for this layer
- int midi_isenabled(struct midi *m, int layer, int input, int inchannel) // Check if the input/midi channel combination for this layer is enabled
- int midi_disableall(struct midi *m) // Disable all routes
- int midi_output(struct midi *m, int output, unsigned char *data, int len) // Send raw MIDI data to an output
- int midi_bufferinfo(struct midi *m, unsigned char *data) // Get info about the internal MIDI output buffer usage
- int metronome_start(struct midi *m, unsigned char *pattern, int len, int period) // Start metronome using a onfigurable speed and pattern
- int metronome_stop(struct midi *m) // Stop metronome
- int metronome_clickselect(struct midi *m, int click) // Select a click sample
Here‘s a link to the Picture Gallery.
Attached are the PSoC Designer files and an application (Linux) to test functionality. The final PC-side application hasn’t been built yet.
- PSoC Designer project: midicontroller.rar
- PC-side test application (C): testapp.tgz
The circuit becomes clear when looking at the pin usage after opening the project in PSoC Designer.
For more pictures check out the gallery