Lauchpad-X gateway for FL-Studio

Currently, the last Launchpad-X is not yet supported by FL-Studio 20.

I have developed a small Java application able to make it compatible with FL-Studio by converting Lauchpad-MK2 messages to Lauchpad-X format.

Tested only under Win10, but should work on other Windows versions, or MacOS.

You need to install a Virtual MIDI loopback software such as

Then, setup three Virtual MIDI ports as below:

  • “FL_to_LPX” port will transport MIDI commands from FL-Studio to the Lauchpad-X
  • “LPX_to_FL” port will transport MIDI message from Lauchpad-X to FL-Studio (pads status)
  • “LPX_to_FL (Native)” will do the same, but for native MIDI mode of the Launchpad-X (Note mode or Custom mode)

[Launchpad-X] <=== [Java] <=== FL_to_LPX <=== [FL-Studio]
[Launchpad-X] ===> [Java] ===> LPX_to_FL ===> [FL-Studio]
[Launchpad-X] ===> [Java] ===> LPX_to_FL (Native) ===> [FL-Studio]

Connect your Launchpad-X.

Then you need to install and run the Java application:

Configure it as below:

If you have used the exact recommended names for loopMidi configuration, the Java application should select automatically the right ports. Otherwise, you will need to do it by hand by using the drop down menus, and click “Apply”.

Before launching FL-Studio, you can now click on “Connect” button. As a result, all pads should now become dark. If not, that means you have a configuration problem.

Then, launch FL-Studio. You have to make the connection to the loopMidi virtual ports and declare a “Launchpad MK2” device as below:

  • Input section
    • LPX_to_FL / Novation Launchpad MK2 / port 20
    • LPX_to_FL (Native) / generic controller / port 3 (or any value different from 20)
  • Output section
    • FL_to_LPX / Novation Launchpad MK2 / port 20
    • LPX_to_FL / MIDI hardware port / port 19 (or any value different from 20 and 3)
    • LPX_to_FL (Native) / MIDI hardware port / port 18 (or any value different from 20 and 3)


  • port 20 can be set to any other value, the only constraints is to have the same value both for input and output.
  • port 18 and 19 will not be used by FL-Studio, but they should be declared so that FL-Studio does not automatically configure them for port 20 or 3 and disturb the system.

When everything is configured, you can load a performance mode song.
You should see pads getting several colors according to the Playlist.
Also, you should see the same colors on the Java application:

You can now play with your Launchpad-X. The behavior will be the same as for MK2. See description here:

The “Native” radio button can be used to make the Lauchpad-X going back to power-on status, and send MIDI messages in “Note mode” or “Custom mode”. MIDI messages will be received by FL-Studio on port 3 for our configuration example. When you are in native mode, you can no longer use the performance mode.


Intelys C3000 vise clamps

Time to machine some aluminum clamps for a nice vise.
To be used on the palet of my Intelys C3000.
First time I am using 3D printing to check the part before wasting material and time with CNC milling: very useful, let me fix some design flaws before machining!

Toolpath calculation with BobCAD-CAM
3D printed prototype, compared to 4 aluminum parts machined on a CNC-6040
Clamp installation
Vise alignment

Adding velocity estimation in hal_pru_generic encoder

I needed this feature for my lathe control panel project. The goal is to drive the jog steps size by the rotation speed of the jog wheels.

The algorithm has been validated from 5 Hz to 100 kHz.
Maximum measurement error is 1%. See curves below.

The patch is available here:


HAL configuration

loadusr -w ../

loadrt threads name1=servo-thread period1=1000000
loadrt hal_pru_generic prucode=$(HAL_RTMOD_DIR)/xenomai/pru_generic.bin pru=0 num_encoders=1 num_pwmgens=1 pru_period=2500 halname=hpg
addf hpg.update servo-thread
addf hpg.capture-position servo-thread

setp hpg.encoder.00.chan.00.A-pin 7 #925 ENCxI
setp hpg.encoder.00.chan.00.counter-mode 2 #Up Counter (counts rising edges on A, always counts up, B ignored)

setp 921 #PWM1
setp hpg.pwmgen.00.out.00.enable 1
setp hpg.pwmgen.00.pwm_period 1000000
setp hpg.pwmgen.00.out.00.value 0.5

loadusr -w sleep 1
loadusr -w python


import subprocess
import time
import os

def readpin(p):
 r = subprocess.check_output('halcmd -s show pin ' + p + '|head -1',shell=True) 
 lst = r.split()
 return lst[3]

def setpin(p, v):
 subprocess.check_output('halcmd -s setp %s %d' % (p, v), shell=True)

freq = 5.0
prev_freq = 0.0
maxerror = 0
f = open('result.csv', 'w')
line = 'in(Hz), out(Hz), err(%), latency(ms)'
print line
f.write(line + '\n')

while freq < 100e3:
 period = int(1e9/freq/2500) * 2500 # because pru_period=2500
 real_freq = 1e9/period
 if (real_freq <> prev_freq):
 prev_freq = real_freq
 setpin('hpg.pwmgen.00.pwm_period', period)
 measured_freq = float(readpin('hpg.encoder.00.chan.00.velocity'))
 latency = float(readpin('hpg.encoder.00.chan.00.latency')) * 1e-6
 error = abs(real_freq / measured_freq - 1.0)
 maxerror = max(maxerror, error)
 line = "%8.1f, %8.1f, %4.2f, %3.0f" % (real_freq, measured_freq, error*100.0, latency)
 print line
 f.write(line + '\n')
 freq = 1.1*freq

print "Max error %.1f%s" % (maxerror*100.0, '%')