-
Notifications
You must be signed in to change notification settings - Fork 9
/
SYSEX.txt
216 lines (182 loc) · 7.02 KB
/
SYSEX.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
This file describes the basic protocol for configuring the LUMI block.
It was reversed engineered by using Midi Monitor on a mac and monitoring the sysex commands sent to LUMI by ROLI dashboard.
Sysex commands are sequences of hexadecimal bytes sent to midi device.
They begin with 0xF0 and end in 0xF7. They can only represent 7-bit numbers (one bit is always fixed).
For brievty, the 0x prefix of hexadecimal numbers is skipped in the rest of this document.
Sysex LUMI commands look like:
F0 <manufacturer> 77 <device-id> <command> <checksum> F7
<manufacturer>: 00 21 10 (ROLI)
<device-id>: 37 (for LUMI, 00 for all blocks?)
<command>: a sequence of 56 bits (8 7-bit values), described thereafter
The checksum is computed for the 8 bytes of the command with the following algorithm:
checksum(bytes, size):
c = size
for b in bytes:
c = (c * 3 + b) & 0xff
return c & 0x7f
command: get product serial
# see https://github.com/WeAreROLI/JUCE/blob/724ae27c71ef809b836df06713cf9e50bc14162b/modules/juce_blocks_basics/topology/internal/juce_BlockSerialReader.cpp
F0 00 21 10 78 3F
=> returns sequence of 224 bytes starting in F0 00 21 10 77 <78>...
command: list blocks? reset?
F0 00 21 10 77 00 01 01 00 5D
=> returns sequence of 48 bytes, then 15 bytes starting in F0 00 21 10 77 <77> <00>...
In the following, we assume a prefix (sysex byte, ROLI manufacturer, LUMI device) and a suffix (checksum, sysex end byte):
F0 00 21 10 77 37 <command-bytes> ?? F7
command: battery level?
01 03 00
=> returns sequences of 48 then 15 bytes starting in F0 00 21 10 77 <77> <00>...
command: read configuration? only works right after (list blocks)
10 02
=> returns sequence of 162 then 128 bytes starting in F0 00 21 10 77 <77> <00>...
command: change color 1 (global key color)
10 20 [color] 03
command: change color 2
10 30 [color] 03 (root key color)
# examples of color changes
10 20 64 3F 00 00 7E 03 // blue
10 20 04 40 7F 00 7E 03 // green
10 20 04 00 00 7F 7F 03 // red
10 20 04 40 7F 7F 7F 03 // yellow
10 20 64 3F 00 7F 7F 03 // magenta
10 20 64 7F 7F 00 7E 03 // cyan
# bit encoding of colors:
# 00100 _ 8 bits of blue _ 8 bits of green _ 8 bits of red _ 111111
blue 1100100 0111111 0000000 0000000 1111110
green 0000100 1000000 1111111 0000000 1111110
red 0000100 0000000 0000000 1111111 1111111
yellow 0000100 1000000 1111111 1111111 1111111
magenta 1100100 0111111 0000000 1111111 1111111
cyan 1100100 1111111 1111111 0000000 1111110
# for rgb value, generate 5 values:
v1 = ((b & 0x3) << 5) | 0x4,
v2 = ((b >> 2) & 0x3f) | (g & 1),
v3 = g >> 1,
v4 = r & 0x7f,
v5 = (r >> 7) | 0x7e,
# note: 03 is probably the last two bits of an 8-bit value (brightness?)
# note: 00100 is probably an identifier for the changed color
command: set brightness
10 40 04 00 00 00 00 00 // 0%
10 40 24 06 00 00 00 00 // 25%
10 40 44 0C 00 00 00 00 // 50%
10 40 64 12 00 00 00 00 // 75%
10 40 04 19 00 00 00 00 // 100%
command: set channel
10 00 20 00 00 00 00 00 // 1
10 00 40 00 00 00 00 00 // 2
10 00 60 00 00 00 00 00 // 3
10 00 00 01 00 00 00 00 // 4
10 00 20 01 00 00 00 00 // 5
10 00 40 01 00 00 00 00 // 6
10 00 60 01 00 00 00 00 // 7
10 00 00 02 00 00 00 00 // 8
10 00 20 02 00 00 00 00 // 9
10 00 40 02 00 00 00 00 // 10
10 00 60 02 00 00 00 00 // 11
command: set octave
10 40 00 7F 7F 7F 7F 03 // -4
10 40 20 7F 7F 7F 7F 03 // -3
10 40 40 7F 7F 7F 7F 03 // -2
10 40 60 7F 7F 7F 7F 03 // -1
10 40 00 00 00 00 00 00 // 0
10 40 20 00 00 00 00 00 // 1
10 40 40 00 00 00 00 00 // 2
10 40 60 01 00 00 00 00 // 3
10 40 00 01 00 00 00 00 // 4
10 40 20 01 00 00 00 00 // 5
command: transpose
10 50 60 7F 7F 7F 7F 03 // -1
10 50 00 00 00 00 00 00 // 0
10 50 20 00 00 00 00 00 // 1
10 50 40 00 00 00 00 00 // 2
10 50 60 00 00 00 00 00 // 3
10 50 00 01 00 00 00 00 // 4
10 50 20 01 00 00 00 00 // 5
10 50 40 01 00 00 00 00 // 6
10 50 60 01 00 00 00 00 // 7
10 50 00 02 00 00 00 00 // 8
10 50 20 02 00 00 00 00 // 9
10 50 40 02 00 00 00 00 // 10
10 50 60 02 00 00 00 00 // 11
command: set strike sensitivity
10 20 01 06 00 00 00 00 // low
10 20 41 1B 00 00 00 00 // high
10 20 01 00 00 00 00 00 // min
10 20 61 1F 00 00 00 00 // max
command: set sensitivity
10 50 01 19 00 00 00 00 // high
10 50 01 05 00 00 00 00 // low
10 50 01 00 00 00 00 00 // min
10 50 61 1F 00 00 00 00 // max
# fixed velocity
10 70 21 00 00 00 00 00 // on
10 70 01 00 00 00 00 00 // off
command: set fixed velocity value
10 00 62 1E 00 00 00 00 // 123
10 00 62 1F 00 00 00 00 // 127
command: set color mode
10 40 02 00 00 00 00 00 // rainbow
10 40 22 00 00 00 00 00 // single color scale
10 40 42 00 00 00 00 00 // piano
10 40 62 00 00 00 00 00 // night
command: set scale
10 60 02 00 00 00 00 00 // major
10 60 22 00 00 00 00 00 // minor
10 60 42 00 00 00 00 00 // harmonic minor
10 60 42 04 00 00 00 00 // chromatic
10 60 62 00 00 00 00 00 // pentatonic neutral
10 60 02 01 00 00 00 00 // pentatonic major
10 60 22 01 00 00 00 00 // pentatonic minor
10 60 42 01 00 00 00 00 // blues
10 60 62 01 00 00 00 00 // dorian
10 60 02 02 00 00 00 00 // phrygian
10 60 22 02 00 00 00 00 // lydian
10 60 42 02 00 00 00 00 // mixolydian
10 60 62 02 00 00 00 00 // locrian
10 60 02 03 00 00 00 00 // whole tone
10 60 22 02 00 00 00 00 // arabic (a)
10 60 42 03 00 00 00 00 // arabic (b)
10 60 62 03 00 00 00 00 // japanese
10 60 02 04 00 00 00 00 // ryukyu
10 60 22 04 00 00 00 00 // 8-tone spanish
10 60 42 04 00 00 00 00 // chromatic
command: set key
10 30 03 00 00 00 00 00 // C
10 30 23 00 00 00 00 00 // C#
10 30 43 00 00 00 00 00 // D
10 30 63 00 00 00 00 00 // D#
10 30 23 01 00 00 00 00 // F
10 30 63 02 00 00 00 00 // B
command: set pressure tracking mode
10 00 04 00 00 00 00 00 // poly aftertouch
10 00 24 00 00 00 00 00 // channel pressure
More documentation on BLOCKS messages:
# https://github.com/WeAreROLI/JUCE/blob/bcaa8cbdde40e47654e1a558659fe5ede5ffc7d8/modules/juce_blocks_basics/protocol/juce_BlocksProtocolDefinitions.h
# first byte is message type:
deviceCommandMessage = 0x01,
sharedDataChange = 0x02,
programEventMessage = 0x03,
firmwareUpdatePacket = 0x04,
configMessage = 0x10,
factoryReset = 0x11,
blockReset = 0x12,
setName = 0x20
# for deviceCommandMessage:
beginAPIMode = 0x00,
requestTopologyMessage = 0x01,
endAPIMode = 0x02,
ping = 0x03,
debugMode = 0x04,
saveProgramAsDefault = 0x05
# for configMessage:
setConfig = 0x00,
requestConfig = 0x01, // Request a config update
requestFactorySync = 0x02, // Requests all active factory config data
requestUserSync = 0x03, // Requests all active user config data
updateConfig = 0x04, // Set value, min and max
updateUserConfig = 0x05, // As above but contains user config metadata
setConfigState = 0x06, // Set config activation state and whether it is saved in flash
factorySyncEnd = 0x07,
clusterConfigSync = 0x08,
factorySyncReset = 0x09