{"id":398,"date":"2016-02-15T09:19:24","date_gmt":"2016-02-15T08:19:24","guid":{"rendered":"http:\/\/elektronik.alexander-roehl.de\/?p=398"},"modified":"2016-05-04T23:06:59","modified_gmt":"2016-05-04T22:06:59","slug":"able-midi-pult","status":"publish","type":"post","link":"http:\/\/elektronik.alexander-roehl.de\/?p=398","title":{"rendered":"Able-Midi Pult"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_top.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-494 size-medium\" src=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_top-300x123.jpg\" alt=\"pcb_top\" width=\"300\" height=\"123\" srcset=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_top-300x123.jpg 300w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_top-1024x421.jpg 1024w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_top-150x62.jpg 150w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_top.jpg 1169w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a> <a href=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_bottom.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-495 size-medium\" src=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_bottom-300x123.jpg\" alt=\"pcb_bottom\" width=\"300\" height=\"123\" srcset=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_bottom-300x123.jpg 300w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_bottom-1024x421.jpg 1024w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_bottom-150x62.jpg 150w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/pcb_bottom.jpg 1169w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nThis is a MIDI project to control the Ableton Music Studio.<\/p>\n<p>A Midi-Controller that look like the controllers in Ableton.<\/p>\n<h2>1. Schematic<\/h2>\n<p><a href=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2.png\"><img loading=\"lazy\" class=\"alignnone wp-image-499 size-medium\" src=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2-300x212.png\" alt=\"Schematic_all\" width=\"300\" height=\"212\" srcset=\"http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2-300x212.png 300w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2-1024x724.png 1024w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2-283x200.png 283w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2-150x106.png 150w, http:\/\/elektronik.alexander-roehl.de\/wp-content\/uploads\/2016\/02\/Schematic_all2.png 1754w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>2. Partlist<\/h2>\n<table style=\"border-collapse: collapse; table-layout: fixed; width: 444px; height: 703px;\" border=\"0\" width=\"369\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"80\">Anzahl<\/td>\n<td width=\"150\">Name<\/td>\n<td width=\"180\">Wert<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">4<\/td>\n<td>C1,C2,C3,C4<\/td>\n<td>22pF<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">2<\/td>\n<td>C5,C6<\/td>\n<td>47\u00b5F<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">4<\/td>\n<td>D1,D2,D3,D4<\/td>\n<td>SM4001<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>D5<\/td>\n<td style=\"mso-ignore: colspan;\" colspan=\"2\">LED_ROT_3MM<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>D6<\/td>\n<td style=\"mso-ignore: colspan;\" colspan=\"2\">LED_GRUEN_3MM<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">2<\/td>\n<td>IC1,IC2<\/td>\n<td style=\"mso-ignore: colspan;\" colspan=\"2\">ATMEGA168(DIL28S)<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>IC3<\/td>\n<td style=\"mso-ignore: colspan;\" colspan=\"2\">TS 2937 CP50<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>K1<\/td>\n<td>A-USBS-B<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>K3<\/td>\n<td style=\"mso-ignore: colspan;\" colspan=\"2\">Einl\u00f6t-DC-Buchse_2.5<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>K4<\/td>\n<td style=\"mso-ignore: colspan;\" colspan=\"2\">WANNENSTECKER-10-LI<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">3<\/td>\n<td>Potti4,Potti5,Potti6<\/td>\n<td>10K<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">2<\/td>\n<td>Q1,Q2<\/td>\n<td>12MHz<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">2<\/td>\n<td>R1,R2<\/td>\n<td>74 Ohm<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>R3<\/td>\n<td>1,5K<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">2<\/td>\n<td>R4,R5<\/td>\n<td>1K<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">3<\/td>\n<td>R11,R12,R13<\/td>\n<td>56K<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">1<\/td>\n<td>R14<\/td>\n<td>10K<\/td>\n<\/tr>\n<tr style=\"height: 12.75pt;\">\n<td style=\"height: 12.75pt;\" height=\"17\">3<\/td>\n<td>S4,S5,S6<\/td>\n<td>JTP-1230B<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<h2>3. Arduino code for IC2<\/h2>\n<pre class=\"height-set:true top-margin:20 lang:c# decode:true\" title=\"Arduino Sketch\">byte MidiChanel = 0xB0;\r\nbyte ControllerChannel = 0x00;  \/\/ 0x21; \/\/ 30 l\u00e4tze frei   \/\/0x14;\r\n\r\n\/\/#define DEBUG\r\n\r\n#define PIN_LINE_SEND 12\r\n#define PIN_LINE_RECEIVE 13\r\n#define LINE_NR_SEND 3\r\nint LINE_NR_RECEIVE;\r\nint ID_COUNTER = 0;\r\n\r\n#define PIN_POTTI_1 A0\r\n#define PIN_POTTI_2 A1\r\n#define PIN_POTTI_3 A2\r\n#define PIN_SLIDER A3\r\n#define BUTTON_1 5\r\n#define BUTTON_2 6\r\n#define BUTTON_3 7\r\n#define BUTTON_THRESHOLD 300\r\n\r\nint potiWert_1,\r\n    potiWert_2,\r\n    potiWert_3,\r\n    sliderWert;\r\nbyte MIDI_Wert_1,\r\n     MIDI_Wert_2,\r\n     MIDI_Wert_3,\r\n     MIDI_Wert_4;\r\nbyte MIDI_Wert_1_alt,\r\n     MIDI_Wert_2_alt,\r\n     MIDI_Wert_3_alt,\r\n     MIDI_Wert_4_alt;\r\nint button_pressed_1,\r\n    button_pressed_2,\r\n    button_pressed_3;\r\nint button_state_1,\r\n    button_state_2,\r\n    button_state_3;\r\n\r\nvoid setup() {\r\n#ifdef DEBUG\r\n  Serial.begin(9600);\r\n#else\r\n  Serial.begin(31250);\r\n#endif\r\n\r\n\r\n  pinMode(PIN_LINE_SEND, 1);\r\n  \/\/  pinMode(PIN_LINE_RECEIVE, 0);\r\n\r\n  pinMode(PIN_POTTI_1, 0);\r\n  pinMode(PIN_POTTI_2, 0);\r\n  pinMode(PIN_POTTI_3, 0);\r\n  pinMode(PIN_SLIDER, 0);\r\n  pinMode(BUTTON_1, 0);\r\n  pinMode(BUTTON_2, 0);\r\n  pinMode(BUTTON_3, 0);\r\n\r\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n  \/\/ Set the start Hardware-ID\r\n  for (int a = 0; a &lt; 10; a++) {\r\n    digitalWrite(PIN_LINE_SEND, 1);\r\n    delay(5);\r\n    digitalWrite(PIN_LINE_SEND, 1);\r\n    delay(5);\r\n  }\r\n}\r\n\r\nvoid loop() {\r\n\r\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n  \/\/ Buttons\r\n  button_pressed_1 = digitalRead(BUTTON_1);\r\n  button_pressed_2 = digitalRead(BUTTON_2);\r\n  button_pressed_3 = digitalRead(BUTTON_3);\r\n  \r\n  if (button_pressed_1) {\r\n    delay(BUTTON_THRESHOLD);\r\n    button_state_1 = ~button_state_1;\r\n    midiSend(MidiChanel, ControllerChannel + 5, 127); \/\/-map(button_state_1, 0, 1, 0, 127));\r\n    midiSend(MidiChanel, ControllerChannel + 5, 0);\r\n  }\r\n  if (button_pressed_2) {\r\n    delay(BUTTON_THRESHOLD);\r\n    button_state_2 = ~button_state_2;\r\n    midiSend(MidiChanel, ControllerChannel + 6, 127); \/\/-map(button_state_1, 0, 1, 0, 127));\r\n    midiSend(MidiChanel, ControllerChannel + 6, 0);\r\n  }\r\n  if (button_pressed_3) {\r\n    delay(BUTTON_THRESHOLD);\r\n    button_state_3 = ~button_state_3;\r\n    midiSend(MidiChanel, ControllerChannel + 7, 127); \/\/-map(button_state_1, 0, 1, 0, 127));\r\n    midiSend(MidiChanel, ControllerChannel + 7, 0);\r\n  }\r\n\r\n\r\n\r\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n  \/\/ Potti 1\r\n  potiWert_1 = analogRead(PIN_POTTI_1);\r\n  MIDI_Wert_1 = map(potiWert_1, 0, 1023, 127, 0);\r\n\r\n\r\n  \/\/if (MIDI_Wert_1 != MIDI_Wert_1_alt) {\r\n  if (!(MIDI_Wert_1 - 2 &lt; MIDI_Wert_1_alt) || !(MIDI_Wert_1 + 2 &gt; MIDI_Wert_1_alt) ) {\r\n    midiSend(MidiChanel, ControllerChannel + 1, MIDI_Wert_1);\r\n    MIDI_Wert_1_alt = MIDI_Wert_1;\r\n  }\r\n\r\n\r\n\r\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n  \/\/ Potti 2\r\n  potiWert_2 = analogRead(PIN_POTTI_2);\r\n  MIDI_Wert_2 = map(potiWert_2, 0, 1023, 127, 0);\r\n\r\n  \/\/Serial.println(MIDI_Wert);\r\n  \/\/if (MIDI_Wert_2 != MIDI_Wert_2_alt) {\r\n  if (!(MIDI_Wert_2 - 2 &lt; MIDI_Wert_2_alt) || !(MIDI_Wert_2 + 2 &gt; MIDI_Wert_2_alt) ) {\r\n    midiSend(MidiChanel, ControllerChannel + 2, MIDI_Wert_2);\r\n    MIDI_Wert_2_alt = MIDI_Wert_2;\r\n  }\r\n\r\n\r\n\r\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n  \/\/ Potti 3\r\n  potiWert_3 = analogRead(PIN_POTTI_3);\r\n  MIDI_Wert_3 = map(potiWert_3, 0, 1023, 127, 0);\r\n\r\n  \/\/Serial.println(MIDI_Wert);\r\n  \/\/if (MIDI_Wert_2 != MIDI_Wert_2_alt) {\r\n  if (!(MIDI_Wert_3 - 2 &lt; MIDI_Wert_3_alt) || !(MIDI_Wert_3 + 2 &gt; MIDI_Wert_3_alt) ) {\r\n    midiSend(MidiChanel, ControllerChannel + 3, MIDI_Wert_3);\r\n    MIDI_Wert_3_alt = MIDI_Wert_3;\r\n  }\r\n\r\n\r\n\r\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n  \/\/ Slider\r\n  sliderWert = analogRead(PIN_SLIDER);\r\n  MIDI_Wert_4 = map(sliderWert, 0, 1023, 127, 0);\r\n\r\n  \/\/Serial.println(MIDI_Wert);\r\n  \/\/if (MIDI_Wert_4 != MIDI_Wert_4_alt) {\r\n  if (!(MIDI_Wert_4 - 2 &lt; MIDI_Wert_4_alt) || !(MIDI_Wert_4 + 2 &gt; MIDI_Wert_4_alt) ) {\r\n    midiSend(MidiChanel, ControllerChannel + 4, MIDI_Wert_4);\r\n    MIDI_Wert_4_alt = MIDI_Wert_4;\r\n  }\r\n}\r\n\r\n\r\n\r\nvoid midiSend(byte chanel, byte controller, byte Value) {\r\n#ifdef DEBUG\r\n  \/\/delay(500);\r\n  Serial.print(chanel);\r\n  Serial.print(\" - \");\r\n  Serial.print(controller);\r\n  Serial.print(\" - \");\r\n  Serial.println(Value);\r\n#else\r\n  Serial.write(chanel);\r\n  \/\/delay(10);\r\n  Serial.write(controller);\r\n  \/\/delay(10);\r\n  Serial.write(Value);\r\n#endif\r\n\r\n}\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>4. AVR Code for IC2 &#8211; MIDI&lt;-&gt;USB Controler<\/h2>\n<pre class=\"height-set:true lang:default decode:true \" title=\"&quot;MIDI\" -=\"\"> USB Code\" &gt;\/* Name: main.c\r\n * MIDI CONVERTER\r\n *\r\n * MOCO: Midi Output Converter\r\n * MICO: Midi Input Converter\r\n *\r\n * (C) 2010 by morecat_lab\r\n *\/\r\n\r\n\r\n\/\/#define ARDUINO 1\r\n\r\n#include &lt;string.h&gt;\r\n#include &lt;avr\/io.h&gt;\r\n#include &lt;avr\/interrupt.h&gt;\r\n#include &lt;avr\/pgmspace.h&gt;\r\n#include &lt;avr\/wdt.h&gt;\r\n\r\n\r\n#include \"usbdrv\/usbdrv.h\"\r\n#include \"usbdrv\/oddebug.h\"\r\n\r\nextern void parseUSBMidiMessage(uchar *, uchar);\r\nextern uchar parseSerialMidiMessage(uchar);\r\n\r\n#define setPortBit0(port, bit) *(port) &amp;= ~_BV(bit);\r\n#define setPortBit1(port, bit) *(port) |= _BV(bit);\r\n#define flipPortBit(port, bit) (*(port) ^= _BV(bit))\r\n#define setPortBit(port, bit, val) { \\\r\n    if ((val) == 0) { setPortBit0((port), (bit)); } else\t\\\r\n      { setPortBit1((port), (bit)); }\t\t\t\t\\\r\n}\r\n\r\n\r\n\r\n\/* debugging LED *\/\r\n#ifdef ARDUINO\r\n#define LED_OFF  { PORTB &amp;= ~0x20; }\r\n#define LED_ON   { PORTB |=  0x20; }\r\n#define FLIP_LED { PORTB ^=  0x20; }\r\n#else\r\n#define LED_OFF  { PORTB &amp;= ~0x01; }\r\n#define LED_ON   { PORTB |=  0x01; }\r\n#define FLIP_LED { PORTB ^=  0x01; }\r\n#endif\r\n\r\n#define RECEIVER\r\n#define TRANSMITTER\r\n\r\n\/*\r\n PORT ASSIGN\r\n PD0: RxD (Serial MIDI)\r\n PD1: TxD (Serial MIDI)\r\n PD2: USB D+\r\n PD3: USB D-\r\n\r\n PD5: LED Monitor\r\n\r\n *\/\r\n\r\n#define HW_CDC_BULK_OUT_SIZE     8\r\n#define HW_CDC_BULK_IN_SIZE      8\r\n\r\n#define\tTRUE\t\t\t1\r\n#define\tFALSE\t\t\t0\r\n\r\nenum {\r\n    SEND_ENCAPSULATED_COMMAND = 0,\r\n    GET_ENCAPSULATED_RESPONSE,\r\n    SET_COMM_FEATURE,\r\n    GET_COMM_FEATURE,\r\n    CLEAR_COMM_FEATURE,\r\n    SET_LINE_CODING = 0x20,\r\n    GET_LINE_CODING,\r\n    SET_CONTROL_LINE_STATE,\r\n    SEND_BREAK\r\n};\r\n\r\n\/\/ This deviceDescrMIDI[] is based on \r\n\/\/ http:\/\/www.usb.org\/developers\/devclass_docs\/midi10.pdf\r\n\/\/ Appendix B. Example: Simple MIDI Adapter (Informative)\r\n\r\n\/\/ B.1 Device Descriptor\r\nstatic PROGMEM const char deviceDescrMIDI[] = {\t\/* USB device descriptor *\/\r\n  18,\t\t\t\/* sizeof(usbDescriptorDevice): length of descriptor in bytes *\/\r\n  USBDESCR_DEVICE,\t\/* descriptor type *\/\r\n  0x10, 0x01,\t\t\/* USB version supported *\/\r\n  0,\t\t\t\/* device class: defined at interface level *\/\r\n  0,\t\t\t\/* subclass *\/\r\n  0,\t\t\t\/* protocol *\/\r\n  8,\t\t\t\/* max packet size *\/\r\n  USB_CFG_VENDOR_ID,\t\/* 2 bytes *\/\r\n  USB_CFG_DEVICE_ID,\t\/* 2 bytes *\/\r\n  USB_CFG_DEVICE_VERSION,\t\/* 2 bytes *\/\r\n  1,\t\t\t\/* manufacturer string index *\/\r\n  2,\t\t\t\/* product string index *\/\r\n  0,\t\t\t\/* serial number string index *\/\r\n  1,\t\t\t\/* number of configurations *\/\r\n};\r\n\r\n\/\/ B.2 Configuration Descriptor\r\nstatic PROGMEM const char configDescrMIDI[] = { \/* USB configuration descriptor *\/\r\n  9,\t   \/* sizeof(usbDescrConfig): length of descriptor in bytes *\/\r\n  USBDESCR_CONFIG,\t\t\/* descriptor type *\/\r\n  101, 0,\t\t\t\/* total length of data returned (including inlined descriptors) *\/\r\n  2,\t\t      \/* number of interfaces in this configuration *\/\r\n  1,\t\t\t\t\/* index of this configuration *\/\r\n  0,\t\t\t\t\/* configuration name string index *\/\r\n#if USB_CFG_IS_SELF_POWERED\r\n    (1 &lt;&lt; 7) | USBATTR_SELFPOWER,       \/* attributes *\/\r\n#else\r\n    (1 &lt;&lt; 7),                           \/* attributes *\/\r\n#endif\r\n  USB_CFG_MAX_BUS_POWER \/ 2,\t\/* max USB current in 2mA units *\/\r\n\r\n\/\/ B.3 AudioControl Interface Descriptors\r\n\/\/ The AudioControl interface describes the device structure (audio function topology) \r\n\/\/ and is used to manipulate the Audio Controls. This device has no audio function \r\n\/\/ incorporated. However, the AudioControl interface is mandatory and therefore both \r\n\/\/ the standard AC interface descriptor and the classspecific AC interface descriptor \r\n\/\/ must be present. The class-specific AC interface descriptor only contains the header \r\n\/\/ descriptor.\r\n\r\n\/\/ B.3.1 Standard AC Interface Descriptor\r\n\/\/ The AudioControl interface has no dedicated endpoints associated with it. It uses the \r\n\/\/ default pipe (endpoint 0) for all communication purposes. Class-specific AudioControl \r\n\/\/ Requests are sent using the default pipe. There is no Status Interrupt endpoint provided.\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* sizeof(usbDescrInterface): length of descriptor in bytes *\/\r\n  USBDESCR_INTERFACE,\t\/* descriptor type *\/\r\n  0,\t\t\t\/* index of this interface *\/\r\n  0,\t\t\t\/* alternate setting for this interface *\/\r\n  0,\t\t\t\/* endpoints excl 0: number of endpoint descriptors to follow *\/\r\n  1,\t\t\t\/* *\/\r\n  1,\t\t\t\/* *\/\r\n  0,\t\t\t\/* *\/\r\n  0,\t\t\t\/* string index for interface *\/\r\n\r\n\/\/ B.3.2 Class-specific AC Interface Descriptor\r\n\/\/ The Class-specific AC interface descriptor is always headed by a Header descriptor \r\n\/\/ that contains general information about the AudioControl interface. It contains all \r\n\/\/ the pointers needed to describe the Audio Interface Collection, associated with the \r\n\/\/ described audio function. Only the Header descriptor is present in this device \r\n\/\/ because it does not contain any audio functionality as such.\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* sizeof(usbDescrCDC_HeaderFn): length of descriptor in bytes *\/\r\n  36,\t\t\t\/* descriptor type *\/\r\n  1,\t\t\t\/* header functional descriptor *\/\r\n  0x0, 0x01,\t\t\/* bcdADC *\/\r\n  9, 0,\t\t\t\/* wTotalLength *\/\r\n  1,\t\t\t\/* *\/\r\n  1,\t\t\t\/* *\/\r\n\r\n\/\/ B.4 MIDIStreaming Interface Descriptors\r\n\r\n\/\/ B.4.1 Standard MS Interface Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* length of descriptor in bytes *\/\r\n  USBDESCR_INTERFACE,\t\/* descriptor type *\/\r\n  1,\t\t\t\/* index of this interface *\/\r\n  0,\t\t\t\/* alternate setting for this interface *\/\r\n  2,\t\t\t\/* endpoints excl 0: number of endpoint descriptors to follow *\/\r\n  1,\t\t\t\/* AUDIO *\/\r\n  3,\t\t\t\/* MS *\/\r\n  0,\t\t\t\/* unused *\/\r\n  0,\t\t\t\/* string index for interface *\/\r\n\r\n\/\/ B.4.2 Class-specific MS Interface Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  7,\t\t\t\/* length of descriptor in bytes *\/\r\n  36,\t\t\t\/* descriptor type *\/\r\n  1,\t\t\t\/* header functional descriptor *\/\r\n  0x0, 0x01,\t\t\/* bcdADC *\/\r\n  65, 0,\t\t\t\/* wTotalLength *\/\r\n\r\n\/\/ B.4.3 MIDI IN Jack Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  6,\t\t\t\/* bLength *\/\r\n  36,\t\t\t\/* descriptor type *\/\r\n  2,\t\t\t\/* MIDI_IN_JACK desc subtype *\/\r\n  1,\t\t\t\/* EMBEDDED bJackType *\/\r\n  1,\t\t\t\/* bJackID *\/\r\n  0,\t\t\t\/* iJack *\/\r\n\r\n  \/* descriptor follows inline: *\/\r\n  6,\t\t\t\/* bLength *\/\r\n  36,\t\t\t\/* descriptor type *\/\r\n  2,\t\t\t\/* MIDI_IN_JACK desc subtype *\/\r\n  2,\t\t\t\/* EXTERNAL bJackType *\/\r\n  2,\t\t\t\/* bJackID *\/\r\n  0,\t\t\t\/* iJack *\/\r\n\r\n\/\/B.4.4 MIDI OUT Jack Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* length of descriptor in bytes *\/\r\n  36,\t\t\t\/* descriptor type *\/\r\n  3,\t\t\t\/* MIDI_OUT_JACK descriptor *\/\r\n  1,\t\t\t\/* EMBEDDED bJackType *\/\r\n  3,\t\t\t\/* bJackID *\/\r\n  1,\t\t\t\/* No of input pins *\/\r\n  2,\t\t\t\/* BaSourceID *\/\r\n  1,\t\t\t\/* BaSourcePin *\/\r\n  0,\t\t\t\/* iJack *\/\r\n\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* bLength of descriptor in bytes *\/\r\n  36,\t\t\t\/* bDescriptorType *\/\r\n  3,\t\t\t\/* MIDI_OUT_JACK bDescriptorSubtype *\/\r\n  2,\t\t\t\/* EXTERNAL bJackType *\/\r\n  4,\t\t\t\/* bJackID *\/\r\n  1,\t\t\t\/* bNrInputPins *\/\r\n  1,\t\t\t\/* baSourceID (0) *\/\r\n  1,\t\t\t\/* baSourcePin (0) *\/\r\n  0,\t\t\t\/* iJack *\/\r\n\r\n\r\n\/\/ B.5 Bulk OUT Endpoint Descriptors\r\n\r\n\/\/B.5.1 Standard Bulk OUT Endpoint Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* bLenght *\/\r\n  USBDESCR_ENDPOINT,\t\/* bDescriptorType = endpoint *\/\r\n  0x1,\t\t\t\/* bEndpointAddress OUT endpoint number 1 *\/\r\n  3,\t\t\t\/* bmAttributes: 2:Bulk, 3:Interrupt endpoint *\/\r\n  8, 0,\t\t\t\/* wMaxPacketSize *\/\r\n  10,\t\t\t\/* bIntervall in ms *\/\r\n  0,\t\t\t\/* bRefresh *\/\r\n  0,\t\t\t\/* bSyncAddress *\/\r\n\r\n\/\/ B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  5,\t\t\t\/* bLength of descriptor in bytes *\/\r\n  37,\t\t\t\/* bDescriptorType *\/\r\n  1,\t\t\t\/* bDescriptorSubtype *\/\r\n  1,\t\t\t\/* bNumEmbMIDIJack  *\/\r\n  1,\t\t\t\/* baAssocJackID (0) *\/\r\n\r\n\r\n\/\/B.6 Bulk IN Endpoint Descriptors\r\n\r\n\/\/B.6.1 Standard Bulk IN Endpoint Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  9,\t\t\t\/* bLenght *\/\r\n  USBDESCR_ENDPOINT,\t\/* bDescriptorType = endpoint *\/\r\n  0x81,\t\t\t\/* bEndpointAddress IN endpoint number 1 *\/\r\n  3,\t\t\t\/* bmAttributes: 2: Bulk, 3: Interrupt endpoint *\/\r\n  8, 0,\t\t\t\/* wMaxPacketSize *\/\r\n  10,\t\t\t\/* bIntervall in ms *\/\r\n  0,\t\t\t\/* bRefresh *\/\r\n  0,\t\t\t\/* bSyncAddress *\/\r\n\r\n\/\/ B.6.2 Class-specific MS Bulk IN Endpoint Descriptor\r\n  \/* descriptor follows inline: *\/\r\n  5,\t\t\t\/* bLength of descriptor in bytes *\/\r\n  37,\t\t\t\/* bDescriptorType *\/\r\n  1,\t\t\t\/* bDescriptorSubtype *\/\r\n  1,\t\t\t\/* bNumEmbMIDIJack (0) *\/\r\n  3,\t\t\t\/* baAssocJackID (0) *\/\r\n};\r\n\r\n\r\nuchar usbFunctionDescriptor(usbRequest_t * rq) {\r\n  if (rq-&gt;wValue.bytes[1] == USBDESCR_DEVICE) {\r\n    usbMsgPtr = (uchar *) deviceDescrMIDI;\r\n    return sizeof(deviceDescrMIDI);\r\n  } else {\t\t\/* must be config descriptor *\/\r\n    usbMsgPtr = (uchar *) configDescrMIDI;\r\n    return sizeof(configDescrMIDI);\r\n  }\r\n}\r\n\r\n\/* ------------------------------------------------------------------------- *\/\r\n\/* ----------------------------- USB interface ----------------------------- *\/\r\n\/* ------------------------------------------------------------------------- *\/\r\n\r\nstatic uchar    sendEmptyFrame;\r\n\/\/ static uchar    modeBuffer[7];\r\n\r\nuchar usbFunctionSetup(uchar data[8]) {\r\n  usbRequest_t    *rq = (void *)data;\r\n\r\n  if((rq-&gt;bmRequestType &amp; USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    \/* class request type *\/\r\n    \r\n    \/*  Prepare bulk-in endpoint to respond to early termination   *\/\r\n    if ((rq-&gt;bmRequestType &amp; USBRQ_DIR_MASK) ==\r\n\tUSBRQ_DIR_HOST_TO_DEVICE)\r\n      sendEmptyFrame = 1;\r\n  }\r\n  return 0xff;\r\n}\r\n\r\n\/*---------------------------------------------------------------------------*\/\r\n\/* usbFunctionRead                                                           *\/\r\n\/*---------------------------------------------------------------------------*\/\r\n\r\nuchar usbFunctionRead( uchar *data, uchar len ) {\r\n\tdata[0] = 0;\r\n\tdata[1] = 0;\r\n\tdata[2] = 0;\r\n\tdata[3] = 0;\r\n\tdata[4] = 0;\r\n\tdata[5] = 0;\r\n\tdata[6] = 0;\r\n    return 7;\r\n}\r\n\r\n\/*---------------------------------------------------------------------------*\/\r\n\/* usbFunctionWrite                                                          *\/\r\n\/*---------------------------------------------------------------------------*\/\r\n\r\nuchar usbFunctionWrite(uchar * data, uchar len) {\r\n  \/\/ setPortBit1(&amp;PORTD, 5);\t\t\/\/ DEBUG LED\r\n  \/* parseMidiMessage(data, len); *\/\r\n  return 1;\r\n}\r\n\/*---------------------------------------------------------------------------*\/\r\n\/* usbFunctionWriteOut                                                       *\/\r\n\/*                                                                           *\/\r\n\/* this Function is called if a MIDI Out message (from PC) arrives.          *\/\r\n\/*                                                                           *\/\r\n\/*---------------------------------------------------------------------------*\/\r\n\r\n#ifdef RECEIVER\r\n#define    RX_SIZE        (HW_CDC_BULK_IN_SIZE)\r\nstatic uchar utxrdy = FALSE;\t\/* USB Packet ready in utx_buf *\/\r\nstatic uchar rx_buf[RX_SIZE];\t\/* tempory buffer *\/\r\nstatic uchar utx_buf[RX_SIZE];\t\/* BULK_IN buffer *\/\r\n#endif\r\n\r\n#ifdef TRANSMITTER\r\n#define    TX_SIZE        (HW_CDC_BULK_OUT_SIZE&lt;&lt;2)\r\n#define    TX_MASK        (TX_SIZE-1)\r\nstatic uchar uwptr = 0, irptr = 0;\r\nstatic uchar tx_buf[TX_SIZE];\r\n#endif\r\n\r\nvoid usbFunctionWriteOut(uchar *data, uchar len ) {\r\n#ifdef TRANSMITTER\r\n  parseUSBMidiMessage(data, len);\r\n#endif\r\n}\r\n\r\n#ifdef TRANSMITTER\r\nvoid parseUSBMidiMessage(uchar *data, uchar len) {\r\n  uchar cin = (*data) &amp; 0x0f;\t\/* CABLE NO????? *\/\r\n  uchar i;\r\n\r\n#ifdef DEBUG\r\n  if (cin == 8) {\r\n    LED_OFF;\r\n  } else if (cin == 9) {\r\n    if (((*(data+3)) &amp; 0x7f) == 0) {\r\n      LED_OFF;\r\n    } else {\r\n      LED_ON;\r\n    }\r\n  }\r\n#else\r\n  FLIP_LED;\r\n#endif\r\n\r\n  if (cin &gt; 1) {\t\t\/* ignore cin == 0 and cin == 1 *\/\r\n    for (i = 1 ; i &lt; 4 ; i++) {\r\n      tx_buf[uwptr++] = *(data + i);\r\n      uwptr &amp;= TX_MASK;\r\n      if (i == 1) {\r\n\tif ((cin == 5) || \/* single byte system common *\/\r\n\t    (cin == 15))  \/* single byte *\/\r\n\t  break;\r\n      }\r\n      if (i == 2) {\r\n\tif ((cin == 2) ||  \/* two-byte system common *\/\r\n\t    (cin == 6) ||  \/* system ex end with 2 bytes *\/\r\n\t    (cin == 12) || \/* program change *\/\r\n\t    (cin == 13))   \/* channel pressure *\/\r\n\t  break;\r\n      }\r\n    }\r\n  }\r\n\r\n  if (len &gt; 4) {\r\n    parseUSBMidiMessage(data+4, len-4);\r\n  }\r\n}\r\n#endif\r\n\r\n#ifdef RECEIVER\r\n\r\nuchar parseSerialMidiMessage(uchar RxByte) {\r\n  static uchar PC = 0;\r\n  static uchar SysEx = FALSE;\r\n  static uchar stateTransTable[] = {\r\n    0, \t\t\t\t\/* 0 dummy *\/\r\n    0,\t\t\t\t\/* 1 dummy *\/\r\n    3,\t\t\t\t\/* 2-&gt;3 NOTE OFF (3) *\/\r\n    2 | 0x80,\t\t\t\/* 3-&gt;2 *\/\r\n    5,\t\t\t\t\/* 4-&gt;5 NOTE ON (3) *\/\r\n    4 | 0x80,\t\t\t\/* 5-&gt;4 *\/\r\n    7,\t\t\t\t\/* 6-&gt;7 Polyphonic key pressure (3) *\/\r\n    6 | 0x80,\t\t\t\/* 7-&gt;6 *\/\r\n    9,\t\t\t\t\/* 8-&gt;9 Control Change (3) *\/\r\n    8 | 0x80,\t\t\t\/* 8-&gt;9 *\/\r\n    10 | 0x80,\t\t\t\/* 10-&gt;10 program change (2) *\/\r\n    0,\t\t\t\t\/* dummy *\/\r\n    12 | 0x80,\t\t\t\/* 12-&gt;12 Channel Pressure (2) *\/\r\n    0,\t\t\t\t\/* 13 dummy *\/\r\n    15,\t\t\t\t\/* 14-&gt;15 Pitch Bend (3) *\/\r\n    14 | 0x80\t\t\t\/* 15-&gt;14 *\/\r\n  };\r\n\r\n  FLIP_LED;\t\/\/ DEBUG LED\r\n  if(SysEx){  \/* MIDI System Message *\/\r\n    if(RxByte == 0xf7){\t\t\/* MIDI_EndSysEx *\/\r\n      SysEx = FALSE;\r\n    }\r\n    return FALSE;\r\n  }\r\n  if (RxByte &gt;= 0xF8){\t\t\/* Single Byte Message *\/\r\n    utx_buf[0] = 0x0f;\r\n    utx_buf[1] = RxByte;\r\n    utx_buf[2] = 0;\r\n    utx_buf[3] = 0;\r\n    return TRUE;\r\n  }\r\n\r\n  if(RxByte &gt; 0x7F){\t\t\/* Channel message *\/\r\n    if(RxByte == 0xf0){\t\t\/* MIDI_StartSysEx *\/\r\n      SysEx = TRUE;\r\n      return FALSE;\r\n    }\r\n    PC = 0;\r\n  }\r\n\r\n  if (PC == 0) {\r\n    PC = (((RxByte &gt;&gt; 4) &amp; 0x07) + 1) * 2;\r\n    \/\/ conversion\r\n    \/\/ 0x80 -&gt; 2, 0x90 -&gt; 4, 0xa0 -&gt; 6, 0xb0 -&gt; 8, 0xc0 -&gt; 10, 0xd0 -&gt; 12, 0xe0 -&gt; 14\r\n    rx_buf[0] = RxByte &gt;&gt; 4;\r\n    rx_buf[1] = RxByte;\r\n    rx_buf[3] = 0;\r\n  } else {\r\n    uchar tt = stateTransTable[PC];\r\n    rx_buf[(PC &amp; 1) + 2] = RxByte;\r\n    PC = tt &amp; 0x0f;\r\n    if ((tt &amp; 0x80) != 0) {\r\n      memcpy(utx_buf, rx_buf, 4);\r\n      return TRUE;\r\n    }\r\n  }\r\n  return FALSE;\r\n}\r\n\r\n#endif\r\n\r\n#ifdef ARDUINO\r\n#define PORTD_DDR (0x00)\r\n#else\r\n#define PORTD_DDR (0b00100010)\r\n#endif\r\n\r\nstatic void hardwareInit(void) {\r\n  uchar i, j;\r\n\r\n  \/* activate pull-ups except on USB lines *\/\r\n  USB_CFG_IOPORT =\r\n    (uchar) ~ ((1 &lt;&lt; USB_CFG_DMINUS_BIT) |\r\n\t       (1 &lt;&lt; USB_CFG_DPLUS_BIT) | PORTD_DDR) ;\r\n  \/* all pins input except USB (-&gt; USB reset) *\/\r\n#ifdef USB_CFG_PULLUP_IOPORT\r\n  \/* use usbDeviceConnect()\/usbDeviceDisconnect() if available *\/\r\n  USBDDR = 0 | PORTD_DDR;\t\/* we do RESET by deactivating pullup *\/\r\n  usbDeviceDisconnect();\r\n#else\r\n  USBDDR = (1 &lt;&lt; USB_CFG_DMINUS_BIT) | (1 &lt;&lt; USB_CFG_DPLUS_BIT) | PORTD_DDR ;\r\n  \/* for output (LED, TxD) *\/\r\n#endif\r\n\r\n  j = 0;\r\n  while (--j) {\t\t\/* USB Reset by device only required on Watchdog Reset *\/\r\n    i = 0;\r\n    while (--i);\t\/* delay &gt;10ms for USB reset *\/\r\n  }\r\n#ifdef USB_CFG_PULLUP_IOPORT\r\n  usbDeviceConnect();\r\n#else\r\n  USBDDR = 0 | PORTD_DDR;\t\t\/*  remove USB reset condition *\/\r\n#endif\r\n\r\n  \/* set baud rate *\/\r\n  UBRR0\t= 31;\t\t\t\/* 312500Hz at 16MHz clock *\/\r\n  \/*  *\/\r\n  UCSR0B\t= (1&lt;&lt;RXEN0) | (1&lt;&lt;TXEN0);\r\n\r\n  \/* DEBUGGING LED *\/\r\n\r\n#ifdef ARDUINO\r\n  DDRB = 0x20;\r\n#else\r\n  DDRB = 0x01;\r\n#endif\r\n  PORTB = 0;\r\n}\r\n\r\nint main(void) {\r\n  \/* I activate the WDT *\/\r\n  wdt_enable(WDTO_1S);\r\n  odDebugInit();\r\n  hardwareInit();\r\n  usbInit();\r\n  \r\n  sendEmptyFrame = 0;\r\n\r\n  sei();\r\n  PORTB = 1;\r\n  \/\/LED_ON;\r\n  for(;;){\r\n    wdt_reset();\r\n    usbPoll();\r\n#ifdef TRANSMITTER\r\n    \/*    send to Serial MIDI line    *\/\r\n    if( (UCSR0A &amp; (1&lt;&lt;UDRE0)) &amp;&amp; uwptr!=irptr ) {\r\n      UDR0 = tx_buf[irptr++];\r\n      irptr &amp;= TX_MASK;\r\n    }\r\n#if USB_CFG_HAVE_FLOWCONTROL == 1\r\n    if( usbAllRequestsAreDisabled() &amp;&amp;\r\n\t((uwptr-irptr)&amp;TX_MASK)&lt;(TX_SIZE-HW_CDC_BULK_OUT_SIZE) ) {\r\n      usbEnableAllRequests();\r\n    }\r\n#endif\r\n#endif\r\n\r\n#ifdef RECEIVER\r\n    \/*    receive from Serial MIDI line    *\/\r\n    if( UCSR0A &amp; (1&lt;&lt;RXC0)) {\r\n      utxrdy |= parseSerialMidiMessage(UDR0);\r\n    }\r\n    \/* send packets to USB MIDI  *\/\r\n    if( usbInterruptIsReady() &amp;&amp; utxrdy ) {\r\n      usbSetInterrupt(utx_buf, 4);\r\n      utxrdy = FALSE;\r\n    }\r\n#endif\r\n  }\r\n}\r\n\r\n\/* EOF *\/<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; &nbsp; This is a MIDI project to control the Ableton Music Studio. A Midi-Controller that look \u2026<\/p>\n<p class=\"continue-reading-button\"> <a class=\"continue-reading-link\" href=\"http:\/\/elektronik.alexander-roehl.de\/?p=398\">Continue reading<i class=\"crycon-right-dir\"><\/i><\/a><\/p>\n","protected":false},"author":1,"featured_media":494,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[32],"tags":[43,42,41,44],"_links":{"self":[{"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/posts\/398"}],"collection":[{"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=398"}],"version-history":[{"count":26,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/posts\/398\/revisions"}],"predecessor-version":[{"id":522,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/posts\/398\/revisions\/522"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=\/wp\/v2\/media\/494"}],"wp:attachment":[{"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=398"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/elektronik.alexander-roehl.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}