Skip to content

UMK4x4 V2.5 User Manual

TheKikGen edited this page Jul 13, 2024 · 39 revisions
      __ __| |           |  /_) |     ___|             |           |
         |   __ \   _ \  ' /  | |  / |      _ \ __ \   |      _` | __ \   __|
         |   | | |  __/  . \  |   <  |   |  __/ |   |  |     (   | |   |\__ \
        _|  _| |_|\___| _|\_\_|_|\_\\____|\___|_|  _| _____|\__,_|_.__/ ____/

USBMIDIKLIK V2.5 User Manual

Revision History

Document Version Firmware Version Date Changes

1.0

2.5.0

May. 10, 2020

Initial Version

1.1

2.5.2

Oct. 21, 2023

Velocity curves pipe

© The KikGen Labs 2018-2023.

The content of this manual serves the purpose of providing non-binding information only and shall not be construed as a commitment of any kind by The KikGen Labs and can be subject to change at any time without notice. Despite making every effort to ensure that the information contained in this manual is accurate, The KikGen Labs shall not be liable for potential errors or inaccuracies.

1. Introduction

miditech midifacebox1

The story of this project starts with a hack of the MIDIPLUS/MIDITECH MidiFace 4x4 USB to MIDI interface. Needing more midi jacks, I bought a second Miditech interface, but I discovered it was not possible to use 2 interfaces on the same computer to get 8x8. This is mainly because of identical product/vendor ID and serial, and, according to the Miditech support, as that usb midi interface is not updateable at all, I was stucked…​. That was motivating me enough to go deep in the detail, and try, at less to change the PID or VID.

You can read about the detailed hack here : The Miditech 4x4 hack and STM32Duino.

The 2.5 is a major release of USBMIDIKLIK4x4 (aka UMK4X4), and is not compatible with previous versions. This manual describes how you can communicate and configure UMK4x4 with the host computer via the USB link.

2. UMK4x4 overview

2.1. Features

16 MIDI USB IN / OUT

16 USB ports available from the host. Support 15 physical JACK IN / 15 JACK OUT in bus mode.

8 virtual ports

8 internal virtual ports available for routing purpose

4 midi clock generators

Support until 4 internal midi clocks / Midi Time code (MTC)

Full remote Configuration

Configuration by SYSEX commands and/or and interactive menu from a serial USB terminal

Large Sysex flow support

Unbuffered SYSEX processed on the fly allowing unlimited messages size

Complex routing rules

Configurables by sysex or from an interactive user menu; allowing MIDI MERGE, SPLIT easily on any ports available. Ability to route any USB IN to any USB OUT/ MIDI OUT.

Midi messages transformation engine

Powerfull "pipeline" feature allowing to modify an incoming midi message within a chain of transformation functions, e.g., transpose notes, split, map channel to another, map CC to another, etc…​.

USB identification customization

USB device ProductStringName, Vendor and Product Ids can be changed easily by the user

STANDALONE Mode

MIDI routing without connecting any host to the USB

Intellithru mode

Possibility to define a second level of routing rules automatically activated when USB is idle or unavailable after a certain delay

Stackable interfaces

Until 5 interfaces can be "stacked" in "bus mode" , to get 6x6, 9x9, 15x15 physical midi ports and 16x16 USB.

STM32F103 full support

STM32F103C8 / STM32F103CB / STM32F103RB / STM32F103RC uC support. Bluepill and Miditech 4x4 board support.

UMK4X4 can be used in two ways : the USB host mode or the standalone mode.

Host USB mode allows the interface to be used with MIDI software when connected to a computer, called a "host.

Standalone mode allows the interface to be used without connection to the host, powered only by the USB port with, for example, a phone charger. In this mode only the DIN midi jacks are used.

An intermediate USB mode, called "Intelligent Midi Thru" (ITHRU), allows to switch to standalone mode if no midi message is received after a certain user-defined delay.

From the version 2.0, the "bus mode" allows to aggregate until 5 boards, each hosting a Bluepill , forming then a one virtual 15x15 ports interface (see bus mode section).

2.2. Hardware support

UMX4X4 can be installed or adapted to a great variety of boards based on the STM32F1 microcontrollers, and especially the STM32F103.

DSC 5474

The STM32F103C8T6 board — also called Blue Pill (picture above) — is the preferred board for UMK4x4 because of its low cost (around 2$) and the 3 IN / 3 OUT midi ports capability. Obviously, the Miditech Midiface 4x4 (4 midi in/out) can be used, as it was the original POC for this project.

I have also designed a board, which can be considered as a "midi shield" for the bluepill, to easily transform that cheap uC board to a powerful 3 IN/OUT MIDI compliant interface.

20190113 221557

The board is USB Powered, so no additional power supply necessary. It works driverless as a class compliant device, with Windows XP SP3, Vista 32 and 64 Bit, Windows 7 / 8 / 10 32 and 64 Bit, and Mac OS X, Linux ALSA, Akai MPC Live/X/Force, IOS, Android.

Some units are currently available at Tindie :

tindie logo@2x

3. MIDI Interface

3.1. MIDI Interface Access

UMK4X4 provides three to four MIDI interfaces (and more in bus mode), each of which has an input and an output port. Only one application at a time can access a port. The midi 1 port is used to set special functions of UMK4x4 by using proprietary SYSEX messages. These messages are ignored on other ports.

3.2. Sysex Commands

The sysex system exclusive ("sysex") commands are vendor-specific MIDI messages used to configure UMK4X4 and retrieve device states.

3.2.1. General Command Format

All sysex messages to and from UMK4X4 have the format given in the table below.

Sysex messages sent to UMK4X4 are called commands, messages sent back to the host are called replies. UMK4X4 sends replies only as reaction to commands, no spontaneous sysex messages are sent. The reply id is most of the time equal to the corresponding command id, although the argument list usually differs.

Commands should not be nested. Before sending the next command the host should wait for the reply, if any is expected, of the previous command. Otherwise, pending replies might be dropped.

SYSEX ARE ONLY INTERPRETED ON CABLE 0 OR MIDI IN JACK 1.

The system exclusive messages format is the following :

Table 1. General Sysex Format
Message Data Description

0xF0

SOX (start of sysex)

0x77

Manufacturer. The KikGen Labs sysex ID. Know that it is a totally unofficial Id.

0x77

Device ID. Probably not needed for USB devices, but this is what most manufacturers do.

0x78

Model ID

ID

Command or reply ID (7 bits unsigned integer)

Arguments

A number of 7 bit values depending on command or reply ID

0xF7

EOX (end of sysex)

Example: [ F0 77 77 78 06 08 F7 ] = command with ID 0x06 and argument 0x08

3.2.2. Command List Overview

This is the list of sysex commands. The details are given in the respective sections.

Table 2. Command List overview
Command ID Sub command

[0x05 Configuration dump as SYSEX commands]

0x06 Global UMK functions

0x00 Hardware reset

0x01 Identity request

0x02 Sysex acknowledgment toggle

0x03 Sysex acknowledgment

0x04 Factory settings

0x05 Clear all midi, Ithru routing rules and pipelines

0x06 Save settings to flash memory

0x08 Reboot in configuration mode

0x09 Reboot in update mode

0x0B USB device settings

0x00 Set USB product string

0x01 Set USB vendor id and product id

0x0C Midi Clock settings

0x00 Enable/disable midi clock

0x01 Set midi clock bpm

0x02 Enable/disable Midi Time Clock

[0x0E Intelligent thru mode settings]

0x00 Reset to default

0x01 Disable

0x02 Set USB idle

0x03 Set jack routing

[0x0F Midi routing settings]

0x00 Reset to default

0x01 Set midi port routing

[0x10 Bus mode settings]

0x00 Enable bus mode

0x01 Set device Id

[0x11 Midi transformation pipelines settings]

Slot operations :
0x00 0x00 copy slot
0x00 0x01 clear slot
0x00 0x02 attach/detach port to slot

Pipe operations :
0x01 0x00 add pipe
0x01 0x01 insert pipe
0x01 0x02 replace pipe
0x01 0x03 clear pipe by index
0x01 0x04 clear pipe by id
0x01 0x05 pipe bypass

3.3. SYSEX messages detail

3.3.1. 0x05 : Configuration dump as SYSEX commands

F0 77 77 78 05 <dump address:nn nn nn nn> F7

-------------------------------------------------------------
| Dump data             | Dump address
-------------------------------------------------------------
| All                   | 7F 00 00 00
| USB device settings   | 0B 00 00 00
| Midi clock settings   | 0C <clock#:0-8> 00 00
| USB Idle              | 0E 02 00 00
| IThru routing         | 0E 03 <Jack In> 00
| In port midi routing  | 0F 01 <in port type:0-2> <in port>
| Bus mode settings     | 10 00 00 00
| In port attached slot | 11 00 <in port type:0-3> <in port>
| Pipes in slot         | 11 01 <slot> <pipe index>
-------------------------------------------------------------
Clock #: 0-8    in port: 0-F
port type : cable = 0 | jack = 1 | virtual:2 | ithru = 3

3.3.2. 0x06 Global UMK functions

06 00 Hardware reset
F0 77 77 78 06 00 F7

06 01 Identity request
F0 77 77 78 06 01 F7

06 02 Sysex acknowledgment toggle (on/off)
F0 77 77 78 06 02 F7

06 03 Sysex acknowledgment (received/never interpreted)
F0 77 77 78 06 03 <ack> F7

06 04 Factory settings
F0 77 77 78 06 04 F7
The device will reboot after the command.

06 05 Clear all (midi, Ithru routing rules and pipelines..)
F0 77 77 78 06 05 F7

06 06 Save settings to flash memory
F0 77 77 78 06 06 F7

06 08 Reboot in configuration mode
F0 77 77 78 06 08 F7

06 09 Reboot in update mode
F0 77 77 78 06 09 F7

3.3.3. 0x0B USB device settings

0B 00 Set USB product string
F0 77 77 78 0B 00 <usb product string not accentuated> F7

0B 01 Set USB vendor ID and product ID
F0 77 77 78 0B 01 <vendor id:nn nn nn nn> <product id:nn nn nn nn> F7

3.3.4. 0x0C Midi Clock settings

0C 00 Enable/disable midi clock
F0 77 77 78 0C 00 <clock #:0-3> <disable:0 enabled:1> F7

0C 01 Set midi clock bpm
F0 77 77 78 0C 01 <clock #:0-3> <bpm: msbn lsbn1 lsbn2> F7
Each 4 bits hex digit nibble must be serialized from the MSB to the LSB.
Bpm value must be x 10, and between 100 (10 bpm) and 3000 (300 bpm)

0C 02 Enable/disable Midi Time Clock
F0 77 77 78 0C 02 <clock #:0-3> <disable MTC:0 enabled MTC:1> F7

If clock # = 7F, then all clocks are updated (MTC must be set individually).
Due to the frequency of change, the clock state or BPM are not stored into
the flash memory after the execution of the sysex command.
However, the global function "Save settings" (06) can be used to save clocks.

3.3.5. 0x0E Intelligent thru

0E 00 Reset to default
F0 77 77 78 0E 00 F7

0E 01 Disable all
F0 77 77 78 0E 01 F7

0E 02 Set USB idle
F0 77 77 78 0E 02 < Number of 15s periods: 00-7F > F7

0E 03 Set jack routing
F0 77 77 78 0E 03 <JackIn port > [<out port type> [<out ports list: nn...nn>] ] F7
Allowed port type : jack=1 | virtual=2   port:0-F  out port type/ports list are optional.
If only jackin is passed, this toggle on/off IThru if output ports exist.
If no out ports list passed, the entire out type will be cleared.

3.3.6. 0x0F Midi routing

Refer also to appendices for more examples.
Any IN port can be routed to any OUT port.
4 Midi clock generator / 8 virtual ports are available within the routing engine.
Below is an overview of the possible paths for a midi message packet, coming from a physical in port to a physical out port :

routingmap

Sysex routing commands :

0F 00 Reset to default
F0 77 77 78 0F 00 F7

0F 01 Set midi port routing
F0 77 77 78 0F 01 <in port type> <in port> <out port type>[out ports list: nn...nn] F7
port type : cable = 0 |jack=1 | virtual=2   port : 0-F out ports list is optional.
If no out ports given, the port routing will be canceled.
A virtual port can't be routed to another virtual port.

3.3.7. 0x10 Bus mode

Regarding bus mode, please refer also to appendices.

10 00 Enable/disable bus mode
F0 77 77 78 10 00 < enable:1 | disable:0 > F7
The device will reboot after the command if bus state changed.

10 01 Set device ID
F0 77 77 78 10 01 < deviceid:04-08 > F7
deviceid must be set to 4 when master.
The device will reboot after the command if id changed.

3.3.8. 0x11 Transformation pipelines

The "pipeline" feature allows you to apply transformation of an incoming midi message through a chain (a "slot) of transformation functions (a "pipe"), e.g., transpose notes, split, map channel to another, map CC to another, etc…​
The first step is to attach a midi in port to slot, so all midi events will pass through the slot and undergo transformations.
The second step consists in defining what will be the transformation sequence, by adding pipes in the selected slot. Until 8 pipes can be easily chained to obtain complex midi transformations without degrading performances.

pipelinemap
Pipe ids table

Pipes are the following :

ID Description

MSGFLTR

Filter midi message depending on particular conditions

NOTECHG

Transpose midi notes by semitones

CHANMAP

Change the source midi channel to another

VELOCHG

Modify note velocity, or filter notes depending on velocity value

CCCHANG

Modify a Control Change (CC) value to another, or filter a specific CC

CLKDIVD

Divide an incoming midi clock message by a specific ratio

LOOPBCK

Route again a midi message to any IN port (loopback)

SLOTCHN

Chain current slot to another existing slot

KBSPLIT

Keyboard split

VLSPLIT

Velocity split

VLCURV1

Set 4 values of the velocity curve

VLCURV2

Set a single linear segment of a velocity curve

VLCURV3

Velocity curve between 6 presets

Pipes can be repeated within the same slot. For example, if you need to split your midi keyboard to 4 different areas, you can add 2 KBSLPIT pipes in the same slot, so notes will be affected to 4 different midi out channels.

Velocity curve pipes

3 pipes are available to adjust the velocity of played midi in notes.

VLCURV1 : Velocity curve 4 values
This pipeline allows you to define 4 values, that will form a 5 segments velocity "curve" affecting midi out :

velocurv1graph

Intervals are defined as follows :

# Midi in velocity range

1

[ 0 , 25 ]

2

] 25 , 50 ]

3

] 50 , 76 ]

4

] 76 , 101 ]

5

] 101, 127 ]

VLCURV2 : Linear velocity curve segment
This pipeline allows you to define a single linear segment of the velocity curve with 2 (midi in, midi out) pairs. You can use that to define a fully customized curve, by adding, for example, 6 VLCURV2 pipes in the same slot that will form 7 segments on top of the velocity curve. It can be combined with VLCURV1, or VLCURV3 to fine tune the resulting velocity curve. It is important to note that VLCURV2 applies ONLY on the original midi packet velocity, i.e. before any transformation.
The graph below shows an example combining pipes VLCURV1(40,15,80,90) and VLCURV2(120,120,127,90):

VLCURV Example1

VLCURV3 : velocity curve presets
This pipeline allows you to choose a predefined velocity curve between 6 presets : compressed for hard player, medium velocity, compresser/expander, low velocity 1 & 2, top and bottom ends cut.

VLCURV3 Velocity%20curves%20presets

Preset midi velocity xIn,yOut values :

# 1. Compressed for hard players 2. Medium velocity : compressed dynamics 3. Compresser/Expander : Low values then high 4. Low Velo 1 : Extreme compression; Low values 5. Low Velo 2 : Extreme compression; Low values 6. Compressed : Top and bottom ends cut

1

[ 0 , 0 ]

[ 0 , 0 ]

[ 0 , 0 ]

[ 0 , 0 ]

[ 0 , 0 ]

[ 0 , 0 ]

2

[ 32 , 16 ]

[ 16 , 48 ]

[ 13 , 29 ]

[ 8 , 8 ]

[ 8 , 8 ]

[ 6 , 24 ]

3

[ 64 , 32 ]

[ 95 , 64 ]

[ 105, 37 ]

[ 32 , 8 ]

[ 48 , 8 ]

[ 56 , 35 ]

4

[ 95 , 64 ]

[ 127, 127 ]

[ 117, 70 ]

[ 64 , 24 ]

[ 68 , 19 ]

[ 95 , 57 ]

5

[ 127, 127 ]

[ 127, 127 ]

[ 84 , 43 ]

[ 92 , 40 ]

[ 119, 86 ]

6

[ 127, 127 ]

[ 111, 79 ]

[ 111, 79 ]

[ 122, 121 ]

7

[ 117, 121 ]

[ 117, 121 ]

[ 127, 127 ]

8

[ 127, 127 ]

[ 127, 127 ]

Sysex transformation commands :

00 Slot operation
-----------------
11 00 00 slot copy
F0 77 77 78 11 00 00 < src slot:01-08 > < dest slot: 01-08 > F7

11 00 01 clear slot
F0 77 77 78 11 00 01 < slot: 01-08 | All slot:7F > F7

11 00 02 Attach/detach port to slot
F0 77 77 78 11 00 02 < in port type> < in port: 0-F> <slot: 00-08> F7
port type : cable = 0 | jack = 1 | virtual:2 | ithru = 3
When slot = 0, the port is considered as detached from any slot.

01 Pipe operation
-----------------
11 01 00 add pipe
F0 77 77 78 11 01 00 <slot:1-8> <pipe id: nn> <prm: nn nn nn nn > F7

11 01 01 insert pipe at
F0 77 77 78 11 01 01 <slot:1-8> <pipe idx:nn> <pipe id:nn> <prm:nn nn nn nn > F7

11 01 02 replace pipe
F0 77 77 78 11 01 02 <slot:1-8> <pipe idx:nn> <pipe id:nn> <prm:nn nn nn nn > F7

11 01 03 clear pipe index
F0 77 77 78 11 01 03 <slot:1-8> <pipe idx:nn> F7

11 01 04 clear first pipe id
F0 77 77 78 11 01 04 <slot:1-8> <pipe id:nn> F7

11 01 05 pipe bypass index
F0 77 77 78 11 01 05 <slot:1-8> <pipe index:nn> <no bypass:0 | bypass:1> F7

-----------------------------------------------------------------------------------------------
| PipeID  |        par1        |        par2        |        par3        |         par4       |
|---------+--------------------+--------------------+--------------------+--------------------|
| MSGFLTR |   Bits mask        |   include:0        | bits mask.         |     00 (unused)    |
|   00    |   filter:0         |   exclude:1        |  ch voice:0001 (1) |                    |
|         |                    |   select:2         |  Sys.cmn :0010 (2) |                    |
|         |                    |                    |  realtime:0100 (4) |                    |
|         |                    |                    |  sysex   :1000 (8) |                    |
|         |                    |                    |                    |                    |
|         |   MidiStatus       |   include:0        |  midi status id1** OR  midi status id2  |
|         |  dble filter:1     |   exclude:1        |                    |  if par4 unused:0  |
|         |                    |   select:2         |  (see Midi status ids table for values) |
|         |                    |                    |                    |                    |
|         |  midi channel      |   include:0        |  from channel 0-F  |  to channel 0-F    |
|         |  filter:2          |   exclude:1        |                    |                    |
|         |                    |   select:2         |                    |                    |
|         +--------------------+--------------------+--------------------+--------------------|
|         | include : keep only matching midi messages                                        |
|         | exclude : drop matching midi messages                                             |
|         | select  : Apply next transformation pipes in the slot only to matching messages   |
|---------+--------------------+--------------------+--------------------+--------------------|
| NOTECHG |    transpose+:0    |   semitone:00-7F   |     00 (unused)    |     00 (unused)    |
|   01    |    transpose-:1    |   semitone:00-7F   |     00 (unused)    |     00 (unused)    |
|---------+--------------------+--------------------+--------------------+--------------------|
| CHANMAP |    channel map:0   | srce ch:0-F|any:7F |      dst ch:0-F    |     00 (unused)    |
|   02    | ch map to port:1   |   source ch:0-F    |   midi port:0-F    |     00 (unused)    |
|         | ch rotat.offset:2  |   ch offset:0-F    |     00 (unused)    |     00 (unused)    |
|---------+--------------------+--------------------+--------------------+--------------------|
| VELOCHG |     include:0      | from vl value:0-7F | to vl value:0-7F   |     00 (unused)    |
|   03    |     exclude:1      | from vl value:0-7F | to vl value:0-7F   |     00 (unused)    |
|         |       fixed:2      |     value:0-7F     |     00 (unused)    |     00 (unused)    |
|         |         add:3      |     value:0-7F     |     00 (unused)    |     00 (unused)    |
|         |         sub:4      |     value:0-7F     |     00 (unused)    |     00 (unused)    |
|         |        half:5      |     00 (unused)    |     00 (unused)    |     00 (unused)    |
|---------+--------------------+--------------------+--------------------+--------------------|
| CCCHANG |         map:0      |    src cc :0-7F    |    dest cc:00-7F   |     00 (unused)    |
|   04    |     include:1      | from cc value:0-7F |  to cc value:0-7F  |     00 (unused)    |
|         |     exclude:2      | from cc value:0-7F |  to cc value:0-7F  |     00 (unused)    |
|         |      invert:3      |    src cc :0-7F    |     00 (unused)    |     00 (unused)    |
|---------+--------------------+--------------------+--------------------+--------------------|
| CLKDIVD |     ratio:2-10     |     00 (unused)    |     00 (unused)    |     00 (unused)    |
|   05    |                    |                    |                    |                    |
|---------+--------------------+--------------------+--------------------+--------------------|
| LOOPBCK |   dest port type.  |  inclusive filter  |      port:0-F      |     00 (unused)    |
|   06    |      cbl out:0     |     bits mask      |                    |                    |
|         |        jk in:1     |   (see MSGFLTR)    |                    |                    |
|         |      virt.in:2     |                    |                    |                    |
|         |       no chg:3     |                    |                    |                    |
|---------+--------------------+--------------------+--------------------+--------------------|
| SLOTCHN |     slot:1-8       |     00 (unused)    |     00 (unused)    |     00 (unused)    |
|   07    |                    |                    |                    |                    |
|---------+--------------------+--------------------+--------------------+--------------------|
| KBSPLIT |  split note: 0-7F  |     midi ch:0-F    |     no change:0    |     00 (unused)    |
|   08    |                    |                    |    transpose+:1    |   semitone:00-7F   |
|         |                    |                    |    transpose-:2    |   semitone:00-7F   |
|---------+--------------------+--------------------+--------------------+--------------------|
| VLSPLIT | split veloc.: 0-7F |     midi ch:0-F    |       nochg:0      |     00 (unused)    |
|   09    |                    |                    |       fixed:1      |     value:0-7F     |
|         |                    |                    |         add:2      |     value:0-7F     |
|         |                    |                    |         sub:3      |     value:0-7F     |
|---------+--------------------+--------------------+--------------------+--------------------|
| VLCURV1 | value 1 : 0-7F     | value 2 : 0-7F     | value 3 :  0-7F    |  value 4 : 0-7F    |
|   0A    |                    |                    |                    |                    |
|---------+--------------------+--------------------+--------------------+--------------------|
| VLCURV2 |  in 1 : 0-7F       | out 1 : 0-7F       | in 2 :  in 1-7F    | out 2 : 0-7F       |
|   0B    |                    |                    |                    |                    |
|---------+--------------------+--------------------+--------------------+--------------------|
| VLCURV3 | Hard player   : 1  |     00 (unused)    |     00 (unused)    |     00 (unused)    |
|   0C    | Medium velo.  : 2  |                    |                    |                    |
|         | Comp.Expander : 3  |                    |                    |                    |
|         | Low velo. 1   : 4  |                    |                    |                    |
|         | Low velo. 2   : 5  |                    |                    |                    |
|         | Ends cut      : 6  |                    |                    |                    |
-----------------------------------------------------------------------------------------------

--------------------------------
|    Midi status ids table     |
|------------------------------|
| noteOffStatus         | 0X08 |
| noteOnStatus          | 0X09 |
| polyKeyPressureStatus | 0X0A |
| controlChangeStatus   | 0X0B |
| programChangeStatus   | 0X0C |
| channelPressureStatus | 0X0D |
| pitchBendStatus       | 0X0E |
| midiTimeCodeStatus    | 0X11 |
| songPosPointerStatus  | 0X12 |
| songSelectStatus      | 0X13 |
| tuneRequestStatus     | 0X16 |
| timingClockStatus     | 0X18 |
| startStatus           | 0X1A |
| continueStatus        | 0X1B |
| stopStatus            | 0X1C |
| activeSensingStatus   | 0X1E |
| systemResetStatus     | 0X1F |
--------------------------------

4. Appendices

4.1. Typical UMK4x4 setup

UMK4x4 is connected to the host computer via USB 2.0. The USB interface provides three MIDI ports or a serial USB interface, which are used to control various aspects of UMK4X4.

4.2. Firmware upgrade (from 2.5 version)

To be done.

  • Upgrading with the KG-HID bootloader firmware

  • Upgrading without bootloader

4.3. Routing example. A "TriThru" à la Midisolutions

Midisolutions midi interfaces have acquired a solid reputation in the professional field. They have my full respect for the high level of quality they deliver. However, these interfaces are relatively expensive, and need a true 5V voltage on the DIN midi line due to "auto-powering", that most recent equipment are not able to provide.

mvqth

By using the USBMidiKlik4x4 routing engine, it is possible to simulate a "Quadra Thru" behaviour, a well known model, which has one IN and 4 OUT. As the Bluepill has only 3 IN/OUT ports, we’ll get more a "TriThru" 1 IN , 3 OUT than a quadra in that configuration example.

20190113 221557

4.3.1. Step by Step guide

  1. Connect the board to the USB plug of your computer

  2. Open your preferred midi software (e.g. MidiOx), and open the midi out port #1

  3. Switch the board in configuration mode by sending the sysex "F0 77 77 78 06 08 F7" The board will disconnect and connect again in serial mode. You should see the led blinking very quickly.

  4. Open a Terminal emulation (e.g. Teraterm or Screen), and open the USB serial port (check devices manager) corresponding to the USBMidiKlik board at 115200 bauds. The following menu should appear after striking ENTER :

USBMIDIKLIK 4x4 - BLUEPILL STMF103C8x - V2.0
(c) TheKikGen Labs
https://github.com/TheKikGen/USBMidiKliK4x4

[0] View global settings         [a] Show active devices
[1] View midi routing            [d] SYSEX settings dump
[2] Usb VID PID
[3] Usb product string
[4] Cable OUT routing            [e] Reload settings
[5] Jack IN routing              [f] Factory settings
[6] IntelliThru routing          [r] Factory routing
[7] IntelliThru timeout          [s] Save settings
[8] Toggle bus mode              [z] Debug on Serial3
[9] Set device Id                [x] Exit
=>
  1. Reset the board to the factory settings by choosing the "f" option, and confirm 2 times with "y"

=>f

Restore factory settings (yn) ? y
All settings will be erased. Sure (yn) ? y
Factory settings restored.

=>
  1. We’ll configure the MIDI JACK IN1 to route all events to MIDI OUT JACK 1,2,3, by choosing the option "5", and entering the port number "01"

=>5

-- Set Jack IN routing --
Enter Jack IN # (01-03 / 00 to exit) :01
  1. Set filter to all message type by answering "y" 4 times, to Channel Voice, System Common, RealTime, System Exclusive

Set filter Midi messages for MIDI in jack #01 :
Channel Voice    (yn) ? y
System Common    (yn) ? y
Realtime         (yn) ? y
System Exclusive (yn) ? y
  1. Ignore cable routing by entering "x" and route midi IN1 events to jack midi outs 1,2,3 by answering "y" 3 times, then you should be back to the main menu.

Route Jack IN#01 to Cable IN#01  (x to exit) (ynx) ? x

Route Jack IN#01 to Jack OUT#01  (x to exit) (ynx) ? y
Route Jack IN#01 to Jack OUT#02  (x to exit) (ynx) ? y
Route Jack IN#01 to Jack OUT#03  (x to exit) (ynx) ? y
  1. Check the routing table with the option "1". In the "MIDI IN JACK ROUTING" section, you should see that the Jack 1 is mapped with Jack OUT 1, 2, 3

MIDI IN JACK ROUTING  (3 port(s) found)

|Jk| Msg Filter   | Cable IN 1111111 | Jack OUT 1111111 |
|  | Ch Sc Rt Sx  | 1234567890123456 | 1234567890123456 |
|1 |  X  X  X  X  | ................ | XXX              |
|2 |  X  X  X  X  | .X.............. | ...              |
|3 |  X  X  X  X  | ..X............. | ...              |
  1. Save the configuration with the "s" option. The global settings are displayed. confirm with "y"

GLOBAL SETTINGS

Firmware version    : 2.0
Magic number        : MDK20
Build               : 2.200303.1153
Sysex header        : F0 77 77 78
Next BootMode       : 2
Debug Mode          : DISABLED
Hardware type       : BLUEPILL STMF103C8x
EEPROM param. size  : 264
I2C Bus mode        : DISABLED
I2C Device ID       : 4 (master)
MIDI USB ports      : 16
MIDI serial ports   : 3
USB VID - PID       : 2912 - 1970
USB Product string  : USB MIDIKliK 4x4

Save settings (yn) ? y
  1. Reboot the board with the "x" option.

Done ! You just configured a "TriThru" !! Connect a midi keyboard to the midi in jack 1, and synths or sound modules to midi out jack 1,2,3…​and have fun ! If you want to use the board in a pure midi standalone mode, with a power supply instead of connecting the USB plug to a USB HOST, you can use the option "[6] IntelliThru routing" to configure routing in the same way as shown below. Don’t forget to save with "s" option before exiting with "x".

-- Set Jack IN IntelliThru  routing --
Enter Jack IN # (01-03 / 00 to exit) :01

Jack #01 : enable thru mode routing (yn) ? y
Keep existing Midi routing & filtering (yn) ? n

Set filter Midi messages for MIDI in jack #01 :
Channel Voice    (yn) ? y
System Common    (yn) ? y
Realtime         (yn) ? y
System Exclusive (yn) ? y

Route Jack IN#01 to Jack OUT#01  (x to exit) (ynx) ? y
Route Jack IN#01 to Jack OUT#02  (x to exit) (ynx) ? y
Route Jack IN#01 to Jack OUT#03  (x to exit) (ynx) ? y

or directly from your preferred midi software, with a SYSEX command :

F0 77 77 78 0E 03 00 0F 00 01 02 F7

4.4. Velocity curves example : reproduce the Midisolutions Velocity Converter #39 curve

We’ll base this example on the Velocity Converter device from Midisolutions. This product proposes 40 velocity curves you can apply to any midi channel. Here is how to customize UMK4x4 to be able to reproduce the curve #39.

The first step will consist in mapping the curve to linear segments. As shown on the following figure, the closest curve is composed of 6 line segments :

VLCURV3 exampleVC Midisolutions
  1. (0,0)-(25,20) → Hexadecimal values are 00 00 19 14

  2. (25,20)-(48,42) → Hexadecimal values are 19 14 30 2A

  3. (48,42)-(72,68) → Hexadecimal values are 30 2A 48 44

  4. (72,68)-(94,106) → Hexadecimal values are 48 44 5E 6A

  5. (94,106)-(104,127) → Hexadecimal values are 5E 6A 68 7F

  6. (104,127)-(127,127) → Hexadecimal values are 68 7F 7F 7F

We’ll use the VLCURV2 pipe to configure theses segments. VLCURV2 accepts 4 parameters, beeing a pair of (inX,outY) forming a line segment. As we need 6 segments, we’ll add VLCURV2 6 times in a slot. Remember that VLCURV2 will process the original packet velocity, not the transformed one. The "add pipe" Sysex operation, has the following syntax :

F0 77 77 78 11 01 00 <slot:1-8> <pipe id: nn> <prm: nn nn nn nn > F7"

As we want to apply transformation only on the midi channel 1, the MSGFLTR (pipe #0x00) will be added first to the slot 1 to "select" midi packets matching the channel filter parameters. Then we’ll add 6 VLCURV2 (pipe #0x0B) segments. Sysex commands :
NB : all values are hexadecimal

Filter select channel 1 :
F0 77 77 78 11 01 00 01 00 02 02 00 00 F7
Create the curve :
F0 77 77 78 11 01 00 01 0B 00 00 19 14 F7
F0 77 77 78 11 01 00 01 0B 19 14 30 2A F7
F0 77 77 78 11 01 00 01 0B 30 2A 48 44 F7
F0 77 77 78 11 01 00 01 0B 48 44 5E 6A F7
F0 77 77 78 11 01 00 01 0B 5E 6A 68 7F F7
F0 77 77 78 11 01 00 01 0B 68 7F 7F 7F F7

Attach the slot 1 to USB port #1 : this is done with the "Attach/detach port to slot" operation, having the syntax :

F0 77 77 78 11 00 02 < in port type> < in port: 0-F> <slot: 00-08> F7
port type : cable = 0 | jack = 1 | virtual:2 | ithru = 3

Our port is USB, so type is "cable" (0), midi port is 1 (cable 0), our transformation slot is 1. Send the adhoc sysex command :

F0 77 77 78 11 00 02 00 00 01 F7

Done ! From now, all midi events coming from USB cable 0 will pass across the slot 1, and our velocity customized curve will be applied only to notes coming from midi channel 1. You can check the slot 1 with the "p" command when in configuration mode :

PIPELINE SLOT 1 :
| Idx | Pipe id    ( p1, p2, p3, p4 ) | Bypass |
|   0 | 00 MSGFLTR ( 02, 02, 00, 00 ) |
|   1 | 0B VLCURV2 ( 00, 00, 19, 14 ) |        |
|   2 | 0B VLCURV2 ( 19, 14, 30, 2A ) |        |
|   3 | 0B VLCURV2 ( 30, 2A, 48, 44 ) |        |
|   4 | 0B VLCURV2 ( 48, 44, 5E, 6A ) |        |
|   5 | 0B VLCURV2 ( 5E, 6A, 68, 7F ) |        |
|   6 | 0B VLCURV2 ( 68, 7F, 7F, 7F ) |        |

| Attached port            |          1111111 |
|                          | 1234567890123456 |
| Cable out                | X............... |
| Jack in                  | ...              |
| Jack in Ithru            | ...              |
| Virtual in               | ........         |

4.5. Bus mode

USBMIDIKLIK I2C BUS MODE

From the V2.5 of the UMK4x4 firmware, it is possible to stack until 5 boards, each hosting a Bluepill , to aggregate them to a one virtual 15x15 ports interface. From the computer, it is seen as a true 16x16 i/o ports, able to address 15x15 midi i/o jacks. It is possible to route any of the inputs ports to any of the outputs ports, and the configuration menu allows an easy and rapid setup.

20191215 173355

The first UMK4x4 prototype with 5 bluepill boards in bus mode I use everyday

4.5.1. Characteristics of the bus mode

  • The master is the only one connected to USB.

  • All slave boards are connected to the I2C bus, no USB and manage serial midi only (jacks in / out )

  • Master has a fixed address on the bus (no 4)

  • Slaves Ids start from 5 to 8

  • The master collects all midi messages from the slaves in a fast loop

  • Slaves apply routing rules, being synchronized from the master routing rules at the boot time to avoid stressing the master. This allows to pass a "pre-routed" messages to the master.

  • Slaves are aware of the USB state, and can switch in a pure midi jack serial routing (cf Intelligent thru)

  • All routing engine capabilities are preserved in the bus version (merge, split, filter,…​)

  • The board can work is a "busless" mode as a usual usb midi 3x3 interface

When a midi message is addressed to a serial port not being the master’s local ones (Serial 1,2,3), the message is routed to the right board via I2C. For example if a software on a computer want to send to MIDI OUT 4, that will be translated into "send to midi out 1 of the device #2".

The logic is almost the same for MIDI IN. For example, if a midi keyboard sends notes to MIDI IN 5, the messages will pass thru the slave routing engine to determine the target. If the target is not a slave local serial, the pre-routed message will be sent to the master for dispatch to another slave connected on the BUS.

The master routine engine indicates to what port the message must be sent. When the master starts, it will broadcast its own routing configuration to all slaves, to ensure a coherent routing when it is delegated to a slave.

4.5.2. Setting midi routing and activate the bus mode

You must connect at less 2 boards together. 5 max including the master. The bus configuration is not available from SYSEX messages. You must so use the configuration menu with a terminal emulation on the ad-hoc serial port.

In the configuration menu, you must set a device ID, 4 being the master one.

USBMIDIKLIK 4x4 - MIDITECH4x4 STM32F103RC - V2.0
(c) TheKikGen Labs
https://github.com/TheKikGen/USBMidiKliK4x4

[0] View global settings         [a] Show active devices
[1] View midi routing            [d] SYSEX settings dump
[2] Usb VID PID
[3] Usb product string
[4] Cable OUT routing            [e] Reload settings
[5] Jack IN routing              [f] Factory settings
[6] IntelliThru routing          [r] Factory routing
[7] IntelliThru timeout          [s] Save settings
[8] Toggle bus mode              [z] Debug on Serial3
[9] Set device Id                [x] Exit
=>

Select option 9 to set the device ID. The example below set the current device as a master.

Device ID ( 04:Master, Slaves 05-07) :04

Then activate the bus mode with the option 8 to allow routing for all the 16 ports.

Enable bus mode (yn) ? y
Bus mode enabled.

Show the current routing map with the option 1. You will see that the routing now allows you to address 15 or 16 jacks and 16 cables .

USB MIDI CABLE OUT ROUTING (16 port(s) found)

|Cb| Msg Filter   | Cable IN 1111111 | Jack OUT 1111111 |
|  | Ch Sc Rt Sx  | 1234567890123456 | 1234567890123456 |
|1 |  X  X  X  X  | ................ | X............... |
|2 |  X  X  X  X  | ................ | .X.............. |
|3 |  X  X  X  X  | ................ | ..X............. |
|4 |  X  X  X  X  | ................ | ...X............ |
|5 |  X  X  X  X  | ................ | ....X........... |
|6 |  X  X  X  X  | ................ | .....X.......... |
|7 |  X  X  X  X  | ................ | ......X......... |
|8 |  X  X  X  X  | ................ | .......X........ |
|9 |  X  X  X  X  | ................ | ........X....... |
|10|  X  X  X  X  | ................ | .........X...... |
|11|  X  X  X  X  | ................ | ..........X..... |
|12|  X  X  X  X  | ................ | ...........X.... |
|13|  X  X  X  X  | ................ | ............X... |
|14|  X  X  X  X  | ................ | .............X.. |
|15|  X  X  X  X  | ................ | ..............X. |
|16|  X  X  X  X  | ................ | ...............X |

MIDI IN JACK ROUTING  (16 port(s) found)

|Jk| Msg Filter   | Cable IN 1111111 | Jack OUT 1111111 |
|  | Ch Sc Rt Sx  | 1234567890123456 | 1234567890123456 |
|1 |  X  X  X  X  | X............... | ................ |
|2 |  X  X  X  X  | .X.............. | ................ |
|3 |  X  X  X  X  | ..X............. | ................ |
|4 |  X  X  X  X  | ...X............ | ................ |
|5 |  X  X  X  X  | ....X........... | ................ |
|6 |  X  X  X  X  | .....X.......... | ................ |
|7 |  X  X  X  X  | ......X......... | ................ |
|8 |  X  X  X  X  | .......X........ | ................ |
|9 |  X  X  X  X  | ........X....... | ................ |
|10|  X  X  X  X  | .........X...... | ................ |
|11|  X  X  X  X  | ..........X..... | ................ |
|12|  X  X  X  X  | ...........X.... | ................ |
|13|  X  X  X  X  | ............X... | ................ |
|14|  X  X  X  X  | .............X.. | ................ |
|15|  X  X  X  X  | ..............X. | ................ |
|16|  X  X  X  X  | ...............X | ................ |

MIDI IN JACK INTELLITHRU ROUTING  (16 port(s) found)

|Jk| Msg Filter   | Cable IN 1111111 | Jack OUT 1111111 |
|  | Ch Sc Rt Sx  | 1234567890123456 | 1234567890123456 |
|1 |  X  X  X  X  |      (N/A)       | XXXX............ |

IntelliThru mode is active.
USB sleeping detection time :30s

You can then define routing rules for USB cables, Jack or Intellithru mode as usual.

=>4
-- Set USB Cable OUT routing --
Enter Cable OUT # (01-16 / 00 to exit) :01

Set filter Midi messages for cable out #01 :
Channel Voice    (yn) ? y
System Common    (yn) ? y
Realtime         (yn) ? y
System Exclusive (yn) ? y

Route Cable OUT#01 to Cable IN#01  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#02  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#03  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#04  (x to exit) (ynx) ? y
Route Cable OUT#01 to Cable IN#05  (x to exit) (ynx) ? y
Route Cable OUT#01 to Cable IN#06  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#07  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#08  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#09  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#10  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#11  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#12  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#13  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#14  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#15  (x to exit) (ynx) ? n
Route Cable OUT#01 to Cable IN#16  (x to exit) (ynx) ? n

Route Cable OUT#01 to Jack OUT#01  (x to exit) (ynx) ? n
Route Cable OUT#01 to Jack OUT#02  (x to exit) (ynx) ? y
Route Cable OUT#01 to Jack OUT#03  (x to exit) (ynx) ? y
Route Cable OUT#01 to Jack OUT#04  (x to exit) (ynx) ? y
Route Cable OUT#01 to Jack OUT#05  (x to exit) (ynx) ? x

Save settings with the "s" option and reboot with the "x" option.

Configure slaves Ids from 5 to 8 and activate the bus mode in the same way. You don’t need to change the routing rules, as the master rules will be copied to all slaves at the boot time.

4.5.3. How to connect a board without a bus connector

Old versions of the UMK4x4 board don’t have the specific connector (or 2 x 3,5MM jack). It is however still possible to enable the bus mode with a simple modification of the hardware.

The Bus mode is operated via I2C bus. I2C pins are : * PB7 for SDA1 * PB6 for SCL1

busmode

You must pull up the SCA1 and SCL1 lines with 2x10K resistors connected to +5V. So the schematic for 3 boards is:

busconnect

For more boards, it is the same logic. Simply connect SCL1/SDA1 of each board to SCL1/SDA1 bus lines. You do not need more pullup resistors.