beatz & funkz

Friday, November 4, 2005

USB MIDI Controller

I use Ableton live a lot to jam and to DJ, and using the mouse to
control all the parameters got in the way quite often. You can’t
select a scene and turn a knob at the same time, switching between
views was tiresome. I first thought about building a midibox, but then decided to build my own midi system
using an AVR microcontroller, which I’m more used to. Blueloop helped me a lot
with the schematics, showing me a nice trick to control LEDs using the
same matrix as for the switches (this is not integrated yet,

Alt Tag Added during WordPress Conversion

The midi controller is quite simple. It features 33 switches and 56
potentiometers. The switches and potentiometers are laid out in a
matrix. You can select a horizontal row by pulling down a port to 0 V,
and then reading the switch values on another port, or by going
through the ADCs in the case of the potentiometers. The actual circuit
for the microcontroller is really really simple. There is an
oscillator and a resistor for the MIDI output. The rest of the I/O
pins go to a pinhead which connects the front panel to the circuit

There is a second circuit board in the midi controller that
converts the MIDI output of the first circuit to USB. It was an old
USB programmer board I built 2 years ago that was lying around. I
directly connected the power of the first circuit board to the USB
connector, and connected the MIDI output to the RX pin of the USB
programmer. I had no 12 Mhz oscillator (the one which I normally use),
so I used a 20 Mhz quartz out of an old network card. The board is
really simple too, and consists of a PDIUSBD11 chip by Phillips, which
gets commands over I2C and outputs USB, and an ATMEGA8
microcontroller. Sadly, the PDIUSBD11 is not manufactured any more,
which is kind of sad, as it is the only USB controller I am aware of
that uses I2C, which spared pins on the microcontroller side. I
implemented the USB MIDI
out of the specification, and the controller seems
to work under Linux and Windows (there is a problem with MacOSX, but I
last checked two years ago and haven’t tried/debugged it since
then). I can’t publish the whole code for the usb-midi adapter though,
as most of it (including the USB stack) was written by Till Harbaum.

Alt Tag Added during WordPress Conversion

The matrices are soldered on the front panel, which I made out of a
plexiglas sheet through which I drilled holes for the switches and
pots. I had no real problems with the plexiglas, except that you have
to drill quite slowly through it in order not to split it, and that I
had to remove the melt plastic around the holes using a rasp. Each
switch has a diode at one of its outputs, so that two knobs pressed at
the same time can be distinguished on the controller side. The
potentiometers are connected to VCC one one side, to the select port
on the other side, and the variable output is connected to the ADC
using a diode. When selecting a switch or a pot, the select pin is
set to GND, all the other pins are set to VCC. Because of the diodes,
the pressed switches or the pots which are not selected are always
high, and the diode won’t allow them to influence the signal.

Alt Tag Added during WordPress Conversion

Alt Tag Added during WordPress Conversion

The code on the microcontroller is almost as simple as the circuit
board. A simple ring-buffer interrupt-based UART handling is used to
handle outgoing MIDI data (the midi controller can’t receive MIDI

#define RB_SIZE 16
#define MIDI_BAUD 31250UL    /* 31.25 kbps */

volatile char tx_buf[RB_SIZE];
volatile char tx_wr = 0, tx_rd = 0;
#define TX_INCR(a, b) (((a) + (b)) & (RB_SIZE - 1))
#define UART_TX_OK (UCSRA & _BV(UDRE))
#define TX_FREE (!(TX_INCR(tx_wr, 1) == tx_rd))

  if (tx_rd != tx_wr) {
    UDR = tx_buf[tx_rd];
    tx_rd = TX_INCR(tx_rd, 1);

void uart_putc(char c) {
  if (UART_TX_OK && (tx_wr == tx_rd)) {
    UDR = c;
  } else {
    while (TX_INCR(tx_wr, 1) == tx_rd) ;
    tx_buf[tx_wr] = c;
    tx_wr = TX_INCR(tx_wr, 1);

void uart_init(void) {
  tx_wr = tx_rd = 0;
  /* set baudrate */
  UBRRL = (((F_CPU) / (16 * MIDI_BAUD)) - 1);
  /* enable TX, interrupts */


The static buffer “tx_buf” is used to buffer outgoing serial
data. “tx_wr” and “tx_rd” are used as indices into the ring
buffer. “TX_INCR” handles the indices when a character is added to the
ring buffer. “TX_FREE” checks if there is free space in the ring
buffer. “UART_TX_OK” checks if the serial interface is ready to send
another character. “SIGNAL(SIG_UART_TRANS)” is the interrupt routine
that is called when a character has successfully been sent. It checks
if the ring buffer is empty, and sends the next character if it is
not. “uart_putc” is the API to the UART code, and directly sends the
character if the serial interface is ready and the ring buffer is
empty. If not, it waits until there is space in the ring buffer, and
adds the new character to the ring buffer. “uart_init” handles the
initialization of the serial interface, sets the correctly baudrate,
and enables TX and the TX_TRANS interrupt. Finally, interrupts on the
AVR are enabled.

void io_init(void) {
  /* disable watchdog */
  WDTCR = 0;

  /* DD = 1, output */
  /* PORT = 1 wenn DD = 0, dann pull-up */
  /* portd = output */
  DDRD = 0XFF;
  /* enable ADC */
  DDRA = 0;
  PORTA = 0xFF;
  // ADCSRA = _BV(ADEN);


The routine “io_init” initializes the Atmel, first disabling the
watchdog, then setting PORTD to output (which is not really necessary,
as the status of the port is set by the switch polling routine). The
ADC is enabled by setting the PORTA to input, enabling pullup
resistors, and enabling the ADC in a 10 bit mode, and using AVCC as
reference voltage. Finally the UART is initialized.

/*** MIDI zeugs ***/

#define MIDI_NOTE_ON 0x9
#define MIDI_NOTE_OFF 0x8
#define MIDI_CC 0xB

#define MIDI_STATUS_TYPE(c) (((c) & 0xF0) >> 4)
#define MIDI_STATUS_CHAN(c) ((c) & 0xF)

static inline midi_is_status(char c) {
return (c & 0x80);

void midi_send_note_on(unsigned char channel, unsigned char note, unsigned char velocity) {

The midi controller sends three types of midi messages. When a switch
is pressed, it sends a note on message, when a switch is release, it
sends a note off message, and when a pot is modified it sends a
control channel message. All three messages are three bytes long and
sent directly to the uart using "uart_putc".

#define LED_BUTTON_PORT     D

#define SET_PIN_OUTPUT(port, pin) { DDR ## port |= _BV(pin); }
#define SET_PIN_INPUT(port, pin) { DDR ## port &= ~(_BV(pin)); }
#define SET_PIN_INPUT_PULLUP(port, pin) { SET_PIN_INPUT(port, pin); PORT ## port |= _BV(pin); }
#define SET_PIN_LOW(port, pin) { PORT ## port &= ~(_BV(pin)); }
#define SET_PIN_HIGH(port, pin) { PORT ## port |= _BV(pin); }
#define PIN_VALUE(port, pin) ((PIN ## port & _BV(pin)) ? 1 : 0)

#define NUM_BUTTONS 30

#define BUTTON_STATUS(i) (button_status[(i)] & 0xF)
#define SET_BUTTON_STATUS(i, val) { button_status[(i)] = button_status[(i)] & 0xF0 | (val); }
#define LED_STATUS(i) ((button_status[(i)] >> 4) & 0xF)
#define SET_LED_STATUS(i, val) { button_status[(i)] = button_status[(i)] & 0xF | ((val) 1 (bounce?) -> 2
wenn knopf auf 1 dann nachricht senden (note on), wieder auf 0 (note off)

#define BUTTON_ROWS 5
unsigned char button_status[BUTTON_ROWS * 8];

void init_buttons(void) {
int i, j;
for (i = 0; i

posted by manuel at 1:08 am  


  1. geil 🙂 mehr krach!

    +++ neingeist

    Comment by neingeist — November 4, 2005 @ 3:18 am

  2. Das Ding ist ja echt kühl geworden und tolle Dokumentation!

    Comment by Blueloop — November 4, 2005 @ 8:00 am

  3. hallo

    ich bastel auch gerade an nem midi controller, hab allerdings ziemliche probleme mim uart des ATMEGA 16. Bekomme einfach nix rauß geschrieben.
    das liegt bestimmt an der krummen baudrate der midi spezifikation. hast du den internen oszilator des avr`s genutz zur uart taktung oder nen quarz ?

    Comment by gast — December 14, 2006 @ 9:42 pm

  4. Mit 8 Mhz als Quartz kriegst du saubere 31250 bps hin. Muesste eigentlich kein problem sein. Vielleicht reicht der Pin output nicht fuer den receiver? Hast du einen Transistor eingebaut?

    Comment by manuel — December 14, 2006 @ 11:26 pm

  5. really cool ,any ideas on implementing an lcd?
    how are the revisions and new features coming along?? vey keen to hear your progress.

    Comment by manyworldsproductions — January 7, 2007 @ 6:55 pm

  6. Hallo,
    könnte ich die unterlagen vom AVR-Midi-USB Adapter bekommen?

    Gruß Raphael

    Comment by Raphael — February 6, 2007 @ 7:59 am

  7. Hallo Raphael,

    leider nicht, die oben dokumentierte Version ist eh mit einem Chip gebaut, den es nicht mehr gibt, und der Code ist leider zum Teil nicht meiner. Allerdings habe ich eine neue Version mit dem AT90USB1286, setz dich bitte mit mir in Verbindung

    Comment by netzstaub — February 6, 2007 @ 11:34 am

  8. I need to repeat your device but with different number of buttons and pots. Can you compile a firmware for atmega644? With 8 pots (each one on 1 ADC line) and 8×8 buttons matrix. I’m asking because you said that you will not give a full source. Thank you.

    Comment by MonZon — February 11, 2007 @ 5:54 am

  9. I need to repeat your device but with different number of buttons and pots. Can you compile a firmware for atmega644? With 8 pots (each one on 1 ADC line) and 8×8 buttons matrix. I’m asking because you said that you will not give a full source. Thank you. Mail it here slamlmd (doggy)

    Comment by MonZon — February 11, 2007 @ 5:54 am

  10. Well the code for the MIDI application itself is completely available in the posting on top (yeah that’s all the firmware), so just modify it for your need. What I’m not posting is the USB MIDI code which is obsolete anyway. Cheers, manuel

    Comment by netzstaub — February 11, 2007 @ 1:45 pm

  11. some forums says that it’s not possible to make USB MIDI HID device on atmega because MIDI requres bulky endpoints. I don’t know what does it mean. Can you give me any hints how to do that?

    Comment by MonZon — February 11, 2007 @ 5:54 pm

  12. Hi well done! … Today I finished the firmware for my own device and it passed all usb9 tests and windows knows it as audio device. So far so good … now I have a working USB midi device. I want to connect it to Traktor 3, but i can’t. It is not available inside. It is no prob of tracktor. I just can’t interact with the midipart of the device. I thought the device is mapped by a standard driver of windows so I can connect it to Traktor. What did you do to connect your device under windows to ableton live? … is there a special software required?


    Comment by alibabashack — May 9, 2007 @ 12:37 pm

  13. Hi alibabashack,

    I just used the standard windows driver. Maybe there is something wrong with your usb midi descriptors? It is quite tricky… Maybe if you send me a copy of them I could go over them. Did you define only one midi output? I guess windows needs to have a port with both in and out, else it won’t be recognized correctly.

    Comment by manuel — May 9, 2007 @ 12:46 pm

  14. thank you for quickly answering…
    my descriptors are ok … they passed the usb9 test, but your last idea is right maybe … i just defined a midi IN port because I just want to controll tracktor and need no respond from pc .. I’ll send you a dump of my descriptors and try to define an out endpoint in addition. hope it will work then… thank you very much! 🙂

    Comment by alibabashack — May 9, 2007 @ 2:43 pm

  15. hmmm doesn’t work also with out pipe …

    Comment by alibabashack — May 9, 2007 @ 3:25 pm

  16. Hi I am currently starting my own project similar to yours and was scouring the web for resources. Your controller looks awesome btw! Just one thing, I can’t grasp why you have the output of 2 pots connected to one terminal, i.e. I think the schematic shows there are 16 pots connected to an 8-bit A/D port, have you used a multiplexer and just not shown it or do your rotary pots interact as pairs?

    Comment by haydos — December 14, 2007 @ 3:57 am

  17. ahh i just read over it, and the penny dropped. Would you advise not to use mux’s because of propogation delays?

    Comment by haydos — December 14, 2007 @ 4:22 am

  18. this still blows my mind everytime i bring this page up. hopefully i can get started on my knob-box soon!

    Comment by slvmchn — December 15, 2007 @ 4:49 am

  19. I will soon start my own midi project too. 🙂

    Comment by usb — March 7, 2008 @ 10:57 pm

  20. Vielen Dank für all die sehr nutzvollen Informationen…. Webdesign Agentur Düsseldorf

    Comment by Webdesign Agentur — March 16, 2008 @ 11:55 pm

  21. It is no prob of tracktor. I just can’t interact with the midipart of the device. I thought the device is mapped by a standard driver of windows so I can connect it to Traktor.

    Comment by 普通話課程 — May 19, 2008 @ 11:35 am

  22. We sell cheap rechargeable laptop battery for most every notebook computer on the market. Since 1996, we have worked with leading laptop battery manufacturers around the world to design, specify, and build high quality laptop batteries. All our laptop batteries must pass stringent quality control tests that ensure they will work with your laptop computer.

    Comment by laptop batteries — September 10, 2008 @ 6:37 am

  23. Use the laptops power management system. This application will help optimize power usage.

    Comment by computer battery — October 15, 2008 @ 3:21 am

  24. is specialize in replacement power tools batteries for most brands such as black&decker, dewalt, makita, hitachi, bosch and many more.Our products are new and 12 months warranty!

    Comment by power tool battery — October 15, 2008 @ 3:23 am

  25. If you need a new laptop battery, I suggest you could purchase one from , which would shipping to yu fast and the quality is satisfy satisfied.:)

    Comment by laptop battery battery — October 15, 2008 @ 3:25 am

  26. We supply a large range of rechargeable Laptop Battery packs for your Laptop , All Laptop Battery in our website are made with high quality cells. Shipping with us is 100% secure guaranteed.

    Comment by ACER battery — October 15, 2008 @ 3:26 am

  27. toshiba 19V 4.74A 90w 6.3mm*3.0mm adapter PA3201U-1ACA SEB100P2-15.0 toshiba 19V 6.3A 120w 5.5mm*2.5mm adapter PA3290U-2ACA PA-1121-08

    Comment by baterry — November 15, 2008 @ 6:31 am

  28. acer squ-519 battery,

    Comment by baterry — November 18, 2008 @ 12:22 pm

  29. asus a32-f3 battery, compaq n400 battery,

    Comment by baterry — November 23, 2008 @ 3:13 pm

  30. dell latitude d810 battery,

    Comment by baterry — November 24, 2008 @ 11:35 am

  31. toshiba pa3420u battery, sony vgp-bps2 battery,

    Comment by baterry — November 28, 2008 @ 10:20 am

  32. We here at strive to make you battery purchases easy. Since we understand that finding the right batteries for your needs can be overwhelming and confusing at times we developed a battery finder to help find the right size for the make and model of your equipment. We also offer educational articles and tips to help you conserve your rechargeable batteries and choose the proper battery chargers and some of the common functions of different power supplies. By us providing education you are able to make the right purchasing decisions as well as provide proper care for all of your electronics.

    Comment by laptop battery — December 9, 2008 @ 6:39 am

  33. wholesale jewelry
    handmade jewelry

    Comment by wholesale jewelry — January 8, 2009 @ 9:23 am

  34. Lots of the files from the Megaupload system at the global web are available for downloading at without registration!

    Comment by hilla — January 23, 2009 @ 11:59 pm

  35. Fashion jewelry Pandora jewelry

    Comment by fashion jewelry — February 20, 2009 @ 2:25 pm

  36. thank you

    Comment by beyonce — March 3, 2009 @ 11:58 am

RSS feed for comments on this post.

Leave a comment

Powered by WordPress