NEW: Control-device manager + controller device "drivers"

Hi @jofemodo
I’ve now understood the basic principles and the little I’ve done is working. It’s still the beginning with (AKAI MPD26), mainly because I started without a plan, I just wanted to see what was possible for a possible future projects (e.g. LKM2 keyboard replacement contoller with interaction with Zynthian and Footswitch controller running Opendeck).

Working is, if there is interest to others…

  • 6x Encoders set in NRPN (INC/DEC) as 4xZYNPOT & 2xARROW_[left, right, up, down]
  	#  NRPN Section for the Encoders
		elif ccnum == 99:  # Get NRPN Poti Value
			self.poti = ccval
		elif ccnum == 96 and ccval == 1:  # Get NRPN INC Value
			if self.poti == 3:	 # CTRL-1
				self.state_manager.send_cuia("ZYNPOT", params=[0, 1])
			elif self.poti == 1:  # CTRL-2
				self.state_manager.send_cuia("ZYNPOT", params=[1, 1])
			elif self.poti == 4:  # CTRL-3
				self.state_manager.send_cuia("ZYNPOT", params=[2, 1])
			elif self.poti == 2:  # CTRL-3
				self.state_manager.send_cuia("ZYNPOT", params=[3, 1])
			elif self.poti == 5:  # Customer LEFT/RIGHT
				self.state_manager.send_cuia("ARROW_RIGHT")
			elif self.poti == 6:  # Customer UP/DOWN
				self.state_manager.send_cuia("ARROW_DOWN")

		elif ccnum == 97 and ccval == 1:  # Get NRPN DEC Value
			if self.poti == 3:
				self.state_manager.send_cuia("ZYNPOT", params=[0, -1])
			elif self.poti == 1:  # CTRL-2
				self.state_manager.send_cuia("ZYNPOT", params=[1, -1])
			elif self.poti == 4:  # CTRL-3
				self.state_manager.send_cuia("ZYNPOT", params=[2, -1])
			elif self.poti == 2:  # CTRL-4
				self.state_manager.send_cuia("ZYNPOT", params=[3, -1])
			elif self.poti == 5:  # Customer UP/DOWN
				self.state_manager.send_cuia("ARROW_LEFT")
			elif self.poti == 6:  # Customer UP/DOWN
				self.state_manager.send_cuia("ARROW_UP")
  • PADS [4,8,12,16] in BankA as ZYNSWITCH 0-4 “P” for NoteOn and “R” for NoteOff

      # PADS
      elif evtype == 0x9:  # Capture NoteOn
      	ccnum = ev[1] & 0x7F
      	if ccnum in self.pads_ccnum:
      		if self.pads_ccnum.index(ccnum) == 0:
      			self.state_manager.send_cuia("ARROW_LEFT")
      		elif self.pads_ccnum.index(ccnum) == 1:
      			self.state_manager.send_cuia("ARROW_DOWN")
      		elif self.pads_ccnum.index(ccnum) == 2:
      			self.state_manager.send_cuia("ARROW_RIGHT")
      		elif self.pads_ccnum.index(ccnum) == 5:
      			self.state_manager.send_cuia("ARROW_UP")
      		elif self.pads_ccnum.index(ccnum) == 3:
      			self.state_manager.send_cuia("ZYNSWITCH", params=["0", "P"])
      		elif self.pads_ccnum.index(ccnum) == 7:
      			self.state_manager.send_cuia("ZYNSWITCH", params=["1", "P"])
      		elif self.pads_ccnum.index(ccnum) == 11:
      			self.state_manager.send_cuia("ZYNSWITCH", params=["2", "P"])
      		elif self.pads_ccnum.index(ccnum) == 15:
      			self.state_manager.send_cuia("ZYNSWITCH", params=["3", "P"])
    
      elif evtype == 0x8:  # Capture NoteOff
      	ccnum = ev[1] & 0x7F
      	if self.pads_ccnum.index(ccnum) == 3:
      		self.state_manager.send_cuia("ZYNSWITCH", params=["0", "R"])
      	elif self.pads_ccnum.index(ccnum) == 7:
      		self.state_manager.send_cuia("ZYNSWITCH", params=["1", "R"])
      	elif self.pads_ccnum.index(ccnum) == 11:
      		self.state_manager.send_cuia("ZYNSWITCH", params=["2", "R"])
      	elif self.pads_ccnum.index(ccnum) == 15:
      		self.state_manager.send_cuia("ZYNSWITCH", params=["3", "R"])
    

TODO…

  • Initialise the device with SysEx Settings so that no manual intervention needs to be done on the device, :thinking: I think this is possible.
  • Decide on a plan or use cases, ideas from others are welcome.

EXTRA INFO…

  • AKAI MPD26 has two configurable MIDI Ins (defined as in the Menu A & B and 1 & 2 in Zynthian) so it is possible to separate which MIDI Commands go to the device driver and which to a MIDI chain.
5 Likes

Hi Chrism,

I am very interested in how you exactly made it work; the encoders I mean.
Could you post the whole code? :slight_smile: And how you made it work in Zynthian?
Could you also send wwhat data the USB controller sends?
As in:
MSB Address Message - B? 63 ??
LSB Address Message - B? 62 ??
MSB Data Byte Message - B? 06 ??
LSB Data Byte Message - B? 26 ??

That all would be great :smiley:
I am asking a lot I know…

Cheers and thanks!
Maarten

1 Like

Hi @maartmaart
Thanks for your interest and I’m happy to share where it helps :wink:
I am adding extra information here, to also help others but your answers are in here as well.
Q: Are you also working on the MPD26 or do you have other plans?

Link to AKAI Documentation:
MPD26 Pad MIDI Controller with Assignable Sliders | Akai Pro e.g. MPD26 - Reference Manual

Download:
zynthian_ctrldev_akai_mpd26.py (6.0 KB)
zynthian_akai_mpd26.syx (609 Bytes)
init.py|attachment (580 Bytes)

Credit to @jofemodo :pray: I used zynthian_ctrldev_korg_nanokontrol2.py as my template.

Howto upload the sysex file from the Zynthian shell (This removes the need to manually edit the encoders on the MPD26), WARNING !! this overwrites Preset 30 !!

systemctl stop zynthian
systemctl stop a2jmidid
systemctl stop jack2

Get the physical midi device id for “Akai MPD26 Port 1” with

amidi -l

send(upload) sysex file with e.g physical device id hw:0,0,0

amidi -p hw:0,0,0 -s zynthian_akai_mpd26_Preset30.syx

Power OFF and then ON the MPD26 as a refresh, in case the preset 30 name “Zynthian” doesn’t show up.

Installing the MPD26 Device Driver
Path to Control Device Python files are under

cd /zynthian/zynthian-ui/zyngine/ctrldev

__init__.py needs a line added to it, see example file from download

“zynthian_ctrldev_akai_mpd26”,

Copy zynthian_ctrldev_akai_mpd26.py to the directory
Start zynthian service again, (jack2 and a2jmidid are then automatically started)

systemctl start zynthian

Then it should work!

Extra info for @maartmaart

AKAI seems to divert from the NTPN Norm, it doesn’t send neither CC 6 (parameter value MSB) or CC 38 (parameter value LSB).

MPD26 editing details

  • “Edit” for encoder K6
  • INC/DEC [PRESS ENTER]
  • 1A NRPN006 127

1A = Midi Port (A & B represents controller 1 & 2 in Zynthian)
NRPN006 = MSB, I set to 006 to represent encoder K6
127 LSB parameter value default =127, I’m ignoring it in the code

Here’s my debugging Messages…

Increment encoder K6
[176, 99, 6] < 6 MSB NRPN value
[176, 98, 127] < 127 LSB parameter value
[176, 96, 1] < defines INC
[176, 99, 127]
[176, 98, 127]

Decrement encoder K6
[176, 99, 6]
[176, 98, 127]
[176, 97, 1] < defines DEC
[176, 99, 127]
[176, 98, 127]

4 Likes

Hi Chris!

Thanks soooooo much for your time and effort. I will dive into it tonight and will let you know whether I succeed in using my encoders on the WORLDE ORCAD PAD48 as Zynthian encoders…

For now, ancious to start creating a solution using your info!!

Cheers,
Maarten

1 Like

Hi maartmaart

I hope you’re successful :grinning:

A good tip mentioned quite often in this forum is to run zynthian with debug logs in the shell.

e.g.

systemctl stop zynthian

and then start them “by hand”:

/zynthian/zynthian-ui/zynthian.sh

That way you can add e.g. below, to your code to what the controller is sending

logging.debug(f"MY Debug: => {ev.hex(’ ')}")

2 Likes

Or just use webconf to monitor the log.

Note that debug and info messages are not issued when run normally as described. Only error & warning. To get all log output you need to run in debug mode. This to can be done from webconf.

1 Like

Hi Chris,

My controller is a WORLDE Orca PAD48 and I just found out today that the NRPN implementation of this chinese company confuses me… I am not able to generate a message that generates somkind of difference between increment and decrement.
The only possibility that I can think of is in the python code to compare the new output with the old… (any control message could then be used) to generate up / down.
It is clear to me that I need to think more about it…
At this moment I am dizzy… the controller gave sometimes very unpredictable output… I suppose cheap bought is expensive bought… hahah… a dutch saying:goedkoop is vaak duurkoop
Perhaps I will use a rp2040 in between to transform the messages…

I can control the GUI with cuia via midi from the PAD48. But I really would like to use the PAD48 encoders to perform the same control as the Zynthian 4 encoders… but then via usb… I will find a way :smiley:

Cheers and thanks for your fantastic support!
Maarten

Hi @maartmaart ,

I’ve just been looking at the manual, have you tried setting the encoder to mode:switch and mode option: toggle, is it e.g sending note on for turning clockwise and note off for anticlockwise ?
Quote „cheap bought is expensive bought“
Yea but unfortunately it doesn’t always work the other way round, expensive bought unfortunately doesn’t always guarantee hassle free usage. With open source designs “what you see is what you get“ Well done zynthian!

3 Likes

Unfortunately the encoders can only be programmed as CC or NRPN/RPN… and the last two are imo implemented wrong… no way to see which direction… this ’ [176, 96 , 1] < defines INC’ does not occur…
Also comparisson is not possible since no messages are transmitted after the end of data… (0 or 127).
Thanks. I really appreciate your feedback :grinning:
But… this is the end for using this PAD48 controller to act as Zynthian encoders.

Cheers,
Maarten

I had a Worlde pad thing for a few days. It was pretty bad. I returned it. Build quality and quality control are low and the UI is not as configurable as you would like, e.g. I don’t think you can set the button colours with CC like you can on most other manufacturers’ pads.

The user manual for your device shows the rotary encoders can be set to absolute mode like you describe or relative mode. You probably want the latter.

The encoders can unfortunately only be set CC absolute or NRPN or RPN… and the last two are nok implemented… so… :triumph: :weary: :drooling_face:

I just wanted to bang the drum on this (so to speak) as I have a launchpad pro mk1 running Oram stable and it’s not picking up the driver so it’s not working with zynseq like @Wapata. There’s no little keyboard next to it in the screenshot. I checked to make sure it’s not using the master midi channel

I saw this thread also: Ctrl out for Launchpad Pro (MK 1?) in Oram not working properly - #7 by freeman

@freeman Did you get yours working in the end and build a driver? It’d be great to make use of the extra buttons on the launchpad pro specifically

I have another general question about the plug&play driver mode: if the driver is active, does this mean the device is no longer in active or multitimbral mode? Or can they both work at the same time, I’m not sure I understand that part fully

Yes, I got it working. I have this super early pre-alpha version going that can play clips, control the zynthian and use the step sequencing in zynseq. It still has some rather glaring bugs and it is not working as smooth as i would like, but if you are interested I can upload an early version at the end of the week since I’m on the road at present and don’t have the zynthian at hand.

I should probably backup my work in some cloud solution and make a proper ticket in the system for it, but I’ve had a lot on my plate lately…

@LFO, just let me know if you want it, I can make an effort this weekend. :grin:

1 Like

Hey @freeman yes for sure, I’d like to try it out when you get back into it

Hi there :slight_smile:
Any clue of why the driver is broken in the end ?

Hi @Wapata - I have no clue what you mean.

1 Like

Woops sorry, still talking about Launchpad X not making light in Session mode.
Well. Since the last update, it look like it doesn’t go in Session mode anymore

Send the logs, please.

:flushed:
I don’t know how to do that
I guess it’s not
journalctl -u zynthian-webconf
Into the terminal that you want.

Oh gosh… It worked sop well during the last years that I don’t know how to ask help in a good way ! :cold_sweat:

Try this:

journalctl -u zynthian -f -n 100

And then try to load/unload the driver.

Regards,