Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
test-and-measurement:analog-discovery-pro-3x50:midi [2022/09/08 20:34] – changed forum.digilentinc.com to forum.digilent.com Jeffrey | test-and-measurement:analog-discovery-pro-3x50:midi [2023/10/18 19:22] (current) – Alyssa Holzer | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Building a MIDI Controller with Analog Discovery Pro (ADP3450/ | ||
+ | ~~TechArticle~~ | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | <WRAP group> | ||
+ | A Musical Instrument Digital Interface (MIDI) controller is a key element in electronic music production. Such devices, both hardware and software, can be quite expensive, but with a bit of work, the Analog Discovery Pro can be set up as a highly customizable MIDI controller, with wireless connection capability. This guide presents, how to configure a Test & Measurement device and a computer to be able to send and receive MIDI commands over Ethernet or Wi-Fi. | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== Prerequisites ===== | ||
+ | <WRAP group> | ||
+ | == Hardware == | ||
+ | * [[test-and-measurement: | ||
+ | * [[[[programmable-logic: | ||
+ | * hardware user interface elements (buttons, switches, sliders, etc.) | ||
+ | * passive electronic components | ||
+ | |||
+ | == Software == | ||
+ | <WRAP group>< | ||
+ | * On PC: | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | </ | ||
+ | * On Analog Discovery Pro: | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * WaveForms SDK - preinstalled | ||
+ | * [[https:// | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== What is MIDI? What is RTP-MIDI? What is a DAW? ===== | ||
+ | <WRAP group> | ||
+ | Musical Instrument Digital Interface (MIDI) is a technical standard which is used in electronic music production. MIDI controllers are not instruments, | ||
+ | |||
+ | Connecting a MIDI controller to a DAW usually requires specific connectors. Most laptops do not have such a MIDI connector, nor has the Analog Discovery Pro. While building such connectors is possible, it is simpler to send the MIDI commands over Ethernet or Wi-Fi, using a protocol called Real-time Transfer Protocol - MIDI (RTP-MIDI). RTP-MIDI uses the RTP network protocol to send the commands in real-time to a receiver. | ||
+ | |||
+ | After the MIDI commands are received, they should be " | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== Signal Transmission and Reception ===== | ||
+ | ==== Setting Up the DAW ==== | ||
+ | <WRAP group>< | ||
+ | To connect to a DAW without a physical MIDI connector, a network MIDI driver is needed. Such a driver is included in the [[https:// | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group>< | ||
+ | Let the rtpMIDI run in the background and open the DAW. Open the DAW's settings, then find the MIDI settings, or MIDI devices and select the previously created rtpMIDI session as an input device. | ||
+ | |||
+ | Add a new track (or more) to the project and select the desired instrument or effect to control. | ||
+ | |||
+ | Before playing the selected instrument, the MIDI controller must be set up. | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ==== Setting Up the Analog Discovery Pro as a MIDI Controller ==== | ||
+ | <WRAP group> | ||
+ | To successfully run this example, the latest Linux version should be installed on the device. To update the ADP3450/ | ||
+ | |||
+ | Now connect the device the internet. If internet is already enabled for Linux mode, just connect the Ethernet cable and skip this step. Else, follow this guide: [[test-and-measurement: | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | To command the ADP3450/ | ||
+ | |||
+ | Tera Term will be used in this guide, but the steps are similar for each of the mentioned program. | ||
+ | |||
+ | <WRAP group>< | ||
+ | Open the terminal emulator and establish a new Secure Shell (SSH) connection to the Analog Discovery Pro's address: digilent@ADPro. Leave every other setting as default. When required, enter the user name and the password: | ||
+ | |||
+ | |<50% 25% 25%>| | ||
+ | ^ user name: | digilent | | ||
+ | ^ password: | digilent | | ||
+ | |||
+ | The terminal should be connected now. | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | Install the necessary packages by entering the following command into the terminal: | ||
+ | |||
+ | < | ||
+ | |||
+ | When required, enter the sudo password: | ||
+ | |||
+ | |<50% 25% 25%>| | ||
+ | ^ sudo password: | digilent | | ||
+ | </ | ||
+ | |||
+ | <WRAP group>< | ||
+ | Select the location with the " | ||
+ | |||
+ | < | ||
+ | |||
+ | Open the cloned directory: | ||
+ | |||
+ | < | ||
+ | cd raveloxmidi</ | ||
+ | |||
+ | Install RaveloxMIDI with: | ||
+ | |||
+ | < | ||
+ | ./configure | ||
+ | make | ||
+ | sudo make install</ | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== Designing and Building the User Interface ===== | ||
+ | ==== Control Signals ==== | ||
+ | <WRAP group> | ||
+ | The hardware user interface of the MIDI controller consists of several control elements, like buttons, switches, sliders, drum pads, etc. As these elements need certain conditioning circuits and because the ADP3450 has only 16 digital IO pins, 4 analog input and 2 analog output channels, so the large number of control signals must be multiplexed to the reduced number of inputs, an efficient " | ||
+ | |||
+ | The control signals can be divided in three main categories: digital signals (coming from buttons, switches and rotary encoders), slowly changing analog signals (coming from potentiometers/ | ||
+ | |||
+ | Digital signals can be directly connected in the driver circuit. They must be debounced (the mechanical noise created by the " | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | Slowly changing analog signals can't be directly measured by the digital inputs of the ADP. While the analog inputs (oscilloscope channels) can measure them directly, they should be used to record fast changing analog signals, so another solution should be found. One method to transform the analog signals to digital ones is by using comparators: | ||
+ | </ | ||
+ | |||
+ | --> Click for Model and Simulation # | ||
+ | <WRAP group> | ||
+ | < | ||
+ | </ | ||
+ | <-- | ||
+ | |||
+ | <WRAP group> | ||
+ | Fast changing analog signals can be measured by the oscilloscope channels. As there will be more signal sources, then channels, these signals have to be multiplexed as well. In the case of the drum pads, the generated pulses are all positive, so the easiest way of multiplexing them is for every channel to add the output of a drum pad to the inverted output of another drum pad. This way the number of input signals will be double the number of input channels and no digital signals are required to control the " | ||
+ | </ | ||
+ | |||
+ | --> Click for Model and Simulation # | ||
+ | <WRAP group> | ||
+ | < | ||
+ | </ | ||
+ | <-- | ||
+ | ---- | ||
+ | |||
+ | ==== User Interface Design ==== | ||
+ | <WRAP group>< | ||
+ | While a MIDI controller can be controlled with a mouse and/or a keyboard, usually a more convenient hardware is used. Such hardware can be quite expensive to buy, but can be easily designed and built on a custom PCB. An advantage of the DIY controller is, that the control elements can be tailored to the needs of the user. | ||
+ | |||
+ | Design the user interface circuit to contain the desired control and indicator elements. Keep in mind the offered possibilities and limitations of the ADP3450, and the signal conditioning methods discussed above. | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | For a detailed presentation of the user interface circuitry used in this guide, check the drop-down below. Any other custom user interface can be used as well. | ||
+ | |||
+ | --> The User Interface Circuit # | ||
+ | <WRAP group> | ||
+ | <WRAP group> | ||
+ | === Parts of the User Interface === | ||
+ | The user interface consists of five main parts: | ||
+ | * The most important control elements are the play/pause button, the record button, the volume slider and the channel selector button. To display the selected channel, this circuit part also contains a [[pmod: | ||
+ | * To further shave the sound of the controller, the second part contains three filters (low, middle and high). The analog-to-PWM converter for the volume slider and the filters is present in this block as well. Incremental rotary encoders are used to set the modulation, the attack, or the release time of the sounds. | ||
+ | * In the third block, six potentiometers (with analog-to-PWM converters) are used to control the effects set in the DAW. | ||
+ | * While traditional keypads have more buttons, this controller only has 12: for the notes C, C#, D, D#, E, F, F#, G, G#, A, A# and B. Two additional buttons can increment and decrement the octave. The index of the chosen octave is displayed on a seven segment display. The RGB LEDs used to implement visual effects are connected to a connector for an open-drain MOSFET driver module ([[pmod: | ||
+ | * The actual drum pads are mechanical parts, each one a disk containing a piezo, but the driver is implemented on the PCB. The outputs of the piezos are clamped and " | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | === Connecting the User Interface === | ||
+ | Connect the output signals of the user interface to the FPGA board, but keep track of the connections, | ||
+ | |||
+ | The BNC oscilloscope connectors are connected directly to the drum pad outputs (multiplexed) and the waveform generator channels are used to generate the reference signal for the PWM generator and the -5V DC voltage reference. The USB ports on the ADP are used to power and program the FPGA, connect the Wi-Fi dongle and supply power to the displays and LEDs through a USB connector. | ||
+ | |||
+ | The Pmod connectors are used on the Arty-S7 to connect the user interface control elements, while the Chipkit analog headers are used to connect the displays and the LEDs. The ADP3450 digital pins are connected to the outer digital Chipkit header. | ||
+ | </ | ||
+ | </ | ||
+ | <-- | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ==== Driver Design ==== | ||
+ | <WRAP group>< | ||
+ | As most of the control signals are digital (including the converted " | ||
+ | |||
+ | If the chosen FPGA board isn't available in Multisim PLD design, follow the instructions in the [[learn: | ||
+ | |||
+ | Start a new PLD design in Multisim, select the desired board and create the necessary conditioning circuits for the input signals. Some digital I/O pins of the ADP3450 can be used as outputs to control the multiplexers connected to the input pins, this way much more input signals can be connected, then the number of input pins. | ||
+ | |||
+ | When ready, click //Transfer -> Export to PLD... -> Generate and save programming file// to use Vivado and compile the bit file from the design. | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | For a detailed presentation of the driver circuitry used in this guide, check the drop-down below. Any other custom driver can also be designed on the FPGA board. | ||
+ | |||
+ | --> The Driver Circuit # | ||
+ | <WRAP group> | ||
+ | === Hierarchical Blocks === | ||
+ | <WRAP group>< | ||
+ | Before creating the driver, design and test certain circuits which will be used multiple times in the driver, to make the final design easier to create and to understand. Some blocks to create: | ||
+ | * clock divider - several D flip-flops are used to reduce the clock frequency to the desired value. If the clock rate must be further reduced, multiple clock divider blocks can be cascaded. | ||
+ | * debouncer - when a button is pressed, some mechanical noise appears in the signal (the bouncing of the two metal plates on each other), so if the action is taken on the edge of the signal, the circuit will be triggered multiple times. A debouncer " | ||
+ | * latch - so buttons can be used as switches (on press turns the signal high, the next one turns it low). | ||
+ | * 1:2 demultiplexer - Multisim contains only larger circuits (1:8). | ||
+ | * up-down counter to N (0< | ||
+ | * pulse counter - as the Python script will use polling to measure every signal, it might miss certain events of the rotary encoders, so they should be re-encoded as numbers. This is why a pulse counter is designed, which is an up-down counter clocked by the two waves of the rotary encoder in quadrature. The block turns the incremental rotary encoders into 4-bit absolute encoders. | ||
+ | * 7 segment display decoder - while 4-bit binary numbers might be easy to understand for machines, on a user interface (created for humans) numbers should appear in decimal representation. This is why a decoder must be used for the dual 7 segment displays, which displays a number between 1 and 16 (received in binary) in decimal representation. | ||
+ | * display selector - while most FPGA boards have many pins, there are some cases, when " | ||
+ | </ | ||
+ | {{ : | ||
+ | {{ : | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | === Driver === | ||
+ | <WRAP group>< | ||
+ | After all the blocks were designed and tested, the actual driver can be built. | ||
+ | |||
+ | As almost all conditioning circuits need clock signals, the derived clocks (with the desired frequency) must be obtained from the FPGA clock. Use clock dividers to reduce the frequency. | ||
+ | |||
+ | The RGB LED control signals are just passed through the FPGA, they are entirely generated by the ADP. The PWM signals coming from the potentiometer conditioning circuits are again buffered, then sent to the multiplexers. | ||
+ | |||
+ | The play/pause and record buttons are debounced and latched to act like switches. The piano keys are debounced and sent to the multiplexers. | ||
+ | |||
+ | The button selecting the MIDI channel is debounced, then connected to an up counter. The output of the counter is connected to the multiplexers. Octaves are set by two buttons: one buttons shifts the octave up, the other one down. The N counter block is used to set the upper limit of counting to 10 (the block will count from 0 to 10 - 11 positions). | ||
+ | |||
+ | The pulse counter block is used to turn the incremental encoder used as modulation wheel into an absolute encoder. The same is done for the timing wheel, but the latched timing button decides, if the output is used for the attack time, or for the release time (the distinction is made from software). | ||
+ | |||
+ | The previously created hierarchical blocks are used to display the channel number and the octave index on the 7 segment displays. | ||
+ | |||
+ | Finally, the conditioned output signals are multiplexed (4:1) to the digital I/O pins of the ADP. To generate the multiplexer addresses, two digital pins of the ADP are used, the address being generated from software. | ||
+ | </ | ||
+ | {{ : | ||
+ | {{ : | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | === Connecting the Driver === | ||
+ | In Multisim, define the connections between the FPGA board and the ADP. | ||
+ | </ | ||
+ | </ | ||
+ | <-- | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== Designing the Software ===== | ||
+ | ==== Hardware Abstraction Layer ==== | ||
+ | <WRAP group> | ||
+ | To make the program simpler and easier to understand, a sort of Hardware Abstraction Layer (HAL) is needed: a set of functions, which communicate with the hardware, and make the usage of the hardware easier. In this case the WaveForms SDK is used to control the ADP3450, but to further simplify the final script, the module created in the [[test-and-measurement: | ||
+ | </ | ||
+ | ---- | ||
+ | ==== Configuring the FPGA ==== | ||
+ | <WRAP group> | ||
+ | To configure the FPGA board connected to the ADP3450, with the bit file created with Multisim, the [[https:// | ||
+ | |||
+ | Create a module in which the Adept Utilities tool is used with the subprocess command. | ||
+ | < | ||
+ | and | ||
+ | < | ||
+ | |||
+ | **Note: **// | ||
+ | |||
+ | <WRAP center round tip 80%> | ||
+ | In the script, check for the responses of the commands to determine if the operation was successful, or not. One can try the commands first in a terminal to check possible responses. | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ==== MIDI ==== | ||
+ | <WRAP group> | ||
+ | Start raveloxmidi in the background as a subprocess, to be able to communicate using RTPMIDI. Use the following command: | ||
+ | < | ||
+ | Don't forget to change the path of the configuration file, to a file, which contains the bind address: " | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | While the background process is running, data sockets containing MIDI data can be sent. An extensive list of possible MIDI messages is available on the page [[https:// | ||
+ | |||
+ | See the drop-downs below for the most important MIDI messages. | ||
+ | |||
+ | --> MIDI Message Types ^# | ||
+ | <WRAP group> | ||
+ | |<100% 10% 10% 50% 10% 10% 10%>| | ||
+ | ^ Message Type ^ Code ^ Meaning | ||
+ | | NOTE_OFF | ||
+ | | NOTE_ON | ||
+ | | POLY_KEY_PRES | 0xA0 | Polyphonic Key Pressure (Aftertouch) | ||
+ | | CTRL_CHG | ||
+ | | PRG_CHG | ||
+ | | CH_PRS_AFTT | ||
+ | | PITCH_BND | ||
+ | | SYS_EX_START | ||
+ | </ | ||
+ | <-- | ||
+ | |||
+ | <WRAP group>< | ||
+ | --> MIDI Notes ^# | ||
+ | <WRAP group> | ||
+ | |<100% 50% 50%>| | ||
+ | ^ Note ^ Value ^ ^ | ||
+ | | C | 0 | | ||
+ | | C# | 1 | | ||
+ | | D | 2 | | ||
+ | | D# | 3 | | ||
+ | | E | 4 | | ||
+ | | F | 5 | | ||
+ | | F# | 6 | | ||
+ | | G | 7 | | ||
+ | | G# | 8 | | ||
+ | | A | 9 | | ||
+ | | A# | 10 | | ||
+ | | B | 11 | | ||
+ | </ | ||
+ | <-- | ||
+ | </ | ||
+ | --> MIDI Octaves ^# | ||
+ | <WRAP group> | ||
+ | |<100% 20% 10% 70%>| | ||
+ | ^ Notation | ||
+ | | DBL_CONTRA_O | 0 | Starts with $C_{-1}$. | | ||
+ | | SUB_CONTRA_O | 12 | Starts with $C_{0}$. | | ||
+ | | CONTRA_O | ||
+ | | GREAT_O | ||
+ | | SMALL_O | ||
+ | | LINE1_O | ||
+ | | LINE2_O | ||
+ | | LINE3_O | ||
+ | | LINE4_O | ||
+ | | LINE5_O | ||
+ | | LINE6_O | ||
+ | </ | ||
+ | <-- | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | Finally, kill every process with the name " | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ==== MIDI Controller Script ==== | ||
+ | <WRAP group> | ||
+ | In the wrapper script, define the connections between the devices and other parameters like the frequency and amplitude/ | ||
+ | |||
+ | Start the WaveForms instruments needed in the controller: start the power supplies, generate the necessary analog and digital signals, set static DIO pins to the desired state and initialize the oscilloscope and the logic analyzer. (Don't forget to close these instruments and disconnect from the ADP at the end of the script! Also stop raveloxmidi when the script is terminated.) | ||
+ | |||
+ | The rest of the code should run in an infinite loop, broken only by pressing Ctrl+C. In each iteration set the address pins of the multiplexers in the driver to 0, 1, 2, or 3 (implement a 2 bit counter here), then read the current state of the multiplexer outputs. Decode these outputs according to the current address and compare the results to the previous ones. If there is no change in the state of a user interface element, no new command should be sent, but if there is a change, send the respective MIDI command with raveloxmidi. | ||
+ | |||
+ | One might also want to set some visual effects using the RGB LEDs. Colors can be easily modified according to the received data. | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== Testing ===== | ||
+ | <WRAP group>< | ||
+ | Copy the project containing the Python scripts onto the ADP3450, with the help of a FAT32 formatted USB flash drive, or using [[https:// | ||
+ | |||
+ | Navigate into the project directory, then run the script by typing | ||
+ | |||
+ | < | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group>< | ||
+ | Open the rtpMIDI program, then connect to the directory called " | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | <WRAP group>< | ||
+ | The MIDI controller should now be fully functional, capable of " | ||
+ | </ | ||
+ | {{ : | ||
+ | </ | ||
+ | ---- | ||
+ | |||
+ | ===== Next Steps ===== | ||
+ | <WRAP group> | ||
+ | For more information on WaveForms SDK, see its [[software: | ||
+ | |||
+ | For technical support, please visit the [[https:// | ||
+ | </ | ||