Hacking a RigKontrol 2 as a MODEP controller

#1

I’ve been messing around with MODEP for a while and I eventually decided to make it suitable for live performing.

I needed a good audio card (possibly with HI-Z input) and a MIDI pedalboard to control the effects. I bumped into this old piece of hardware that I got from a friend and I thought BINGO! That’s perfect! But… I didn’t know the MIDI implementation of this pedalboard was such a nightmare! In fact it has NO MIDI IMPLEMENTATION!

After spending a couple of days unsuccesfully trying to get some MIDI signal out of the RigControl, I realized that the footswitches emulates a USB keyboard and the volume controller emulate a USB joystick (Yes you got it right…) Essentially, pressing a footswitch RigKontrol sends a number (1 to 7) like if it was pressed on the keyboard. Operating the foot controller, acts like if you were moving a joystick on the X axis.

So I wrote a little software that grabs these events and sends MIDI messages to MODEP accordingly. I hate Python, but in the end I decided to go for it, because it seemed to be the simplest solution for such a small program.

The good thing is that IT WORKS!

All you have to do is launch the program then you can let the MODEP effects’ controls learn the MIDI message sent by the pedalboard. You can manually run the program via SSH, but I strongly suggest for you to make it auto-run at boot using systemd (as a service).

Here’s the code, in case you’re interested in it:

#!/usr/bin/python

import time
import rtmidi
import evdev

#
## Definizione dei 7 controlli a pulsante
## Stato, N. CC, Valore off, Valore on
#
aFootControls = [
        [False, 20, 0, 127],
        [False, 21, 0, 127],
        [False, 22, 0, 127],
        [False, 23, 0, 127],
        [False, 24, 0, 127],
        [False, 25, 0, 127],
        [False, 26, 0, 127]]

#
## Definizione dei 3 controlli a pedale
## CC, Valore minimo ingresso, Valore massimo in ingresso, valore minimo rimappato, valore massimo rimappato
#
aVariableControls = [
        [27, 190, 1500, 0, 127],
        [28, 190, 1600, 0, 127],
        [29, 190, 1600, 0, 127]]


# Funione di rimappatura del valore letto dal controller ai valori MIDI
def remap(val, from_min, from_max, to_min, to_max):
        nNewVal = (to_max - to_min)*(val - from_min) / (from_max - from_min) + to_min
        if nNewVal < to_min:
                nNewVal = to_min

        if nNewVal > to_max:
                nNewVal = to_max

        return(nNewVal)

#print(evdev.util.list_devices())

device = evdev.InputDevice('/dev/input/event0')

#print(device)

# Apre la porta Midi
midiout = rtmidi.MidiOut()
available_ports = midiout.get_ports()

if available_ports:
    midiout.open_port(0)
else:
    midiout.open_virtual_port("GuidoPort")

with midiout:
    aMessage = [0xB0, 0, 0] # channel 1, middle C, velocity 112
    try:
        for event in device.read_loop():
            # Premuto un bottone sulla pedaliera
            if event.type == evdev.ecodes.EV_KEY:
                keyevent = evdev.categorize(event)
                if int(event.value) <> 1:
                  continue

                # Controlla che il bottone sia nel range dei 7 bottoni della pedaliera
                nButton = int(event.code) - 2

                if nButton < 0 or nButton > 6:
                  continue

                # Assegna al messaggio il numero di CC MIDI associato al bottone
                aMessage[1] = aFootControls[nButton][1]

                # inverte lo stato del bottone
                aFootControls[nButton][0] = not aFootControls[nButton][0]

                # Prepara il valore da inviate
                if aFootControls[nButton][0]:
                   aMessage[2] = aFootControls[nButton][3]
                else:
                   aMessage[2] = aFootControls[nButton][2]

                # Invio del messaggio MIDI
                midiout.send_message(aMessage)

            elif event.type == evdev.ecodes.EV_ABS:
                absevent = evdev.categorize(event)
                if absevent.event.code > len(aVariableControls):
                        continue

                nNewVal = remap(absevent.event.value, aVariableControls[absevent.event.code][1], aVariableControls[absevent.event.code][2],
                                aVariableControls[absevent.event.code][3], aVariableControls[absevent.event.code][4]);

                if absevent.event.code < 0 or absevent.event.code > 2:
                  continue

                # Assegna al messaggio il numero di CC MIDI associato al bottone
                aMessage[1] = aVariableControls[absevent.event.code][0]

                aMessage[2] = nNewVal

                # Invio del messaggio MIDI
                midiout.send_message(aMessage)

    except (EOFError, KeyboardInterrupt):
      print('Fine')

del midiout

This software sends CC #20 to #26 for the footswitches and CC #27 to #t29 for the avriable controller, as specified in the following matrices:

aFootControls = [
        [False, 20, 0, 127],
        [False, 21, 0, 127],
        [False, 22, 0, 127],
        [False, 23, 0, 127],
        [False, 24, 0, 127],
        [False, 25, 0, 127],
        [False, 26, 0, 127]]

aVariableControls = [
        [27, 190, 1500, 0, 127],   # Volume pedal
        [28, 190, 1600, 0, 127],   # pedal input 1
        [29, 190, 1600, 0, 127]]   # pedal input 2

The second matrix specifies the CC #, the minimum read value, the maximum read value, the minimum MIDI value to be sent, the maximum MIDI value to be sent. The mapping of these values is performed by the remap() funcion.

NOTE: I couldn’t test the input pedals 1 & 2, not having any pedal to plug! :slight_smile:

Now, the bad thing is that I could only grab signals out of the RigKontrol, but I could not reverse engineer the way the device accepts signals back into it, so I wasn’t able to turn on the LEDs on the footswitches. In other words you don’t have any visual feedback on the status of a pedal which is pretty annoying. I thought I could add some external LEDs, perhaps driven by the GPIO ports, but I didn’t worked it out yet. I’ll see.

Please feel free to ask questions.

0 Likes