Compare commits

...

2 Commits

Author SHA1 Message Date
Sascha Nitsch e4c0c8cbe0 now with MIDI supprt 2022-07-22 12:27:05 +02:00
Sascha Nitsch 3a234b1969 optional low pass filter for analog values 2022-07-22 12:22:16 +02:00
7 changed files with 629 additions and 47 deletions

View File

@ -11,7 +11,6 @@
// library includes
#include <Adafruit_MCP23X17.h>
// own includes
#include "cimdithal.h"
@ -109,6 +108,9 @@ void CimditHAL::readFromHardware(bool interrupt) {
int16_t lastAnalogValue = m_currentAnalogValues[m_analogNum];
// scan analog value
m_currentAnalogValues[m_analogNum] = analogRead(ANALOG_IN);
#ifdef ANALOG_LOW_PASS_FACTOR
m_currentAnalogValues[m_analogNum] = lastAnalogValue - (ANALOG_LOW_PASS_FACTOR * (lastAnalogValue - m_currentAnalogValues[m_analogNum]));
#endif
// set changed bits
if (lastAnalogValue != m_currentAnalogValues[m_analogNum]) {
//if (abs(lastAnalogValue - m_currentAnalogValues[m_analogNum]) > 1) {

View File

@ -12,6 +12,11 @@
#include <Arduino.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_MIDI
#include <MIDIUSB.h>
#endif
#ifndef EXTERNAL_EEPROM
#include <EEPROM.h>
#endif
@ -166,11 +171,14 @@ void CimditProfile::load(uint8_t num) {
for (uint8_t i = 0; i < m_numMappedButtons ; ++i) {
m_mappedButtons[i].m_number = nextUInt8();
m_mappedButtons[i].m_type = (MappingType)(nextUInt8());
m_mappedButtons[i].m_value = nextUInt8();
m_mappedButtons[i].m_value1 = nextUInt8();
if (m_mappedButtons[i].m_type == MIDI_NOTE || m_mappedButtons[i].m_type == MIDI_CTRL || m_mappedButtons[i].m_type == MIDI_PITCH) {
m_mappedButtons[i].m_value2 = nextUInt8();
m_mappedButtons[i].m_value3 = nextUInt8();
}
}
}
// end of mapped buttons
// mapped axis
// number of mapped axis
m_numMappedAxis = nextUInt8();
@ -178,11 +186,13 @@ void CimditProfile::load(uint8_t num) {
for (uint8_t i = 0; i < m_numMappedAxis ; ++i) {
m_mappedAxis[i].m_number = nextUInt8();
m_mappedAxis[i].m_type = (MappingType)(nextUInt8());
m_mappedAxis[i].m_value = nextUInt8();
m_mappedAxis[i].m_value1 = nextUInt8();
if (m_mappedAxis[i].m_type == MIDI_CTRL_AXIS) {
m_mappedAxis[i].m_value2 = nextUInt8();
}
}
}
// end of mapped axis
// mapped rotary
// number of mapped rotary
m_numMappedRotary = nextUInt8();
@ -190,7 +200,7 @@ void CimditProfile::load(uint8_t num) {
for (uint8_t i = 0; i < m_numMappedRotary ; ++i) {
m_mappedRotary[i].m_number = nextUInt8();
m_mappedRotary[i].m_type = (MappingType)(nextUInt8());
m_mappedRotary[i].m_value = nextUInt8();
m_mappedRotary[i].m_value1 = nextUInt8();
}
}
// end of mapped rotary
@ -305,14 +315,14 @@ void CimditProfile::scanOrExecuteMacro(uint8_t macroNum, bool execute) {
for (uint8_t i = 0; i < m_numMappedAxis; ++i) {
if (m_mappedAxis[i].m_number == axis) {
m_mappedAxis[i].m_type = MOUSE_REL_X_AXIS;
m_mappedAxis[i].m_value = value8;
m_mappedAxis[i].m_value1 = value8;
found = true;
}
}
if (!found) {
m_mappedAxis[m_numMappedAxis].m_type = MOUSE_REL_X_AXIS;
m_mappedAxis[m_numMappedAxis].m_number = axis;
m_mappedAxis[m_numMappedAxis++].m_value = value8;
m_mappedAxis[m_numMappedAxis++].m_value1 = value8;
}
}
} else {
@ -337,14 +347,14 @@ void CimditProfile::scanOrExecuteMacro(uint8_t macroNum, bool execute) {
for (uint8_t i = 0; i < m_numMappedAxis; ++i) {
if (m_mappedAxis[i].m_number == axis) {
m_mappedAxis[i].m_type = MOUSE_REL_Y_AXIS;
m_mappedAxis[i].m_value = value8;
m_mappedAxis[i].m_value1 = value8;
found = true;
}
}
if (!found) {
m_mappedAxis[m_numMappedAxis].m_type = MOUSE_REL_Y_AXIS;
m_mappedAxis[m_numMappedAxis].m_number = axis;
m_mappedAxis[m_numMappedAxis++].m_value = value8;
m_mappedAxis[m_numMappedAxis++].m_value1 = value8;
}
}
} else {
@ -359,6 +369,61 @@ void CimditProfile::scanOrExecuteMacro(uint8_t macroNum, bool execute) {
}
}
break;
case MACRO_MIDI_NOTEON:
{
uint8_t channel = nextUInt8();
value8 = nextUInt8();
uint8_t velocity = nextUInt8();
#ifdef HAVE_MIDI
if (execute) {
midiEventPacket_t noteOn = {0x09, (uint8_t)(0x90 | channel), value8, velocity};
MidiUSB.sendMIDI(noteOn);
MidiUSB.flush();
}
#endif
}
break;
case MACRO_MIDI_NOTEOFF:
{
uint8_t channel = nextUInt8();
value8 = nextUInt8();
uint8_t velocity = nextUInt8();
#ifdef HAVE_MIDI
if (execute) {
midiEventPacket_t noteOff = {0x08, (uint8_t)(0x80 | channel), value8, velocity};
MidiUSB.sendMIDI(noteOff);
MidiUSB.flush();
}
#endif
}
break;
case MACRO_MIDI_CTRL:
{
uint8_t channel = nextUInt8();
uint8_t control = nextUInt8();
value8 = nextUInt8();
#ifdef HAVE_MIDI
if (execute) {
midiEventPacket_t event= {0x0B, (uint8_t)(0xB0 | channel), control, value8};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
#endif
}
break;
case MACRO_MIDI_PITCH:
{
uint8_t channel = nextUInt8();
uint16_t value = nextUInt16();
#ifdef HAVE_MIDI
if (execute) {
midiEventPacket_t event = {0x0E, (uint8_t)(0xE0 | channel), (unsigned char)(value&127), (uint8_t)(value>>7)};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
#endif
}
break;
}
} while (token != MACRO_NULL);
}
@ -375,13 +440,13 @@ void CimditProfile::rotaryAction(uint8_t num, int8_t delta) {
// rotary supports mouse rel axis, next/prev profile and macro
switch (m_mappedRotary[i].m_type) {
case MOUSE_REL_X_AXIS:
Mouse.move(m_mappedRotary[i].m_value * delta, 0, 0);
Mouse.move(m_mappedRotary[i].m_value1 * delta, 0, 0);
break;
case MOUSE_REL_Y_AXIS:
Mouse.move(0, m_mappedRotary[i].m_value * delta, 0);
Mouse.move(0, m_mappedRotary[i].m_value1 * delta, 0);
break;
case MOUSE_REL_WHEEL:
Mouse.move(0, 0, m_mappedRotary[i].m_value * delta);
Mouse.move(0, 0, m_mappedRotary[i].m_value1 * delta);
break;
case NEXT_PROFILE:
case PREV_PROFILE:
@ -397,7 +462,7 @@ void CimditProfile::rotaryAction(uint8_t num, int8_t delta) {
showActivate();
break;
case MACRO_PRESS:
scanOrExecuteMacro(m_mappedRotary[i].m_value, true);
scanOrExecuteMacro(m_mappedRotary[i].m_value1, true);
break;
default:
break;
@ -490,7 +555,7 @@ void CimditProfile::axisAction(uint8_t num, uint16_t state) {
if (m_mappedAxis[i].m_number == num) {
switch (m_mappedAxis[i].m_type) {
case JOYSTICK_AXIS:
switch (m_mappedAxis[i].m_value) {
switch (m_mappedAxis[i].m_value1) {
case 1:
Gamepad.xAxis(map(state, 0, 1023, -32768, 32767));
break;
@ -514,9 +579,9 @@ void CimditProfile::axisAction(uint8_t num, uint16_t state) {
case MOUSE_REL_X_AXIS: {
int16_t pos = (int16_t)state - 512;
if (pos > JOYSTICK_DEAD_ZONE_X) {
m_mouseMoveX = map(pos, JOYSTICK_DEAD_ZONE_X, 511, 0, m_mappedAxis[i].m_value);
m_mouseMoveX = map(pos, JOYSTICK_DEAD_ZONE_X, 511, 0, m_mappedAxis[i].m_value1);
} else if (pos < -JOYSTICK_DEAD_ZONE_X) {
m_mouseMoveX = map(pos, -512, -JOYSTICK_DEAD_ZONE_X, -m_mappedAxis[i].m_value, 0);
m_mouseMoveX = map(pos, -512, -JOYSTICK_DEAD_ZONE_X, -m_mappedAxis[i].m_value1, 0);
} else {
m_mouseMoveX = 0;
}
@ -525,16 +590,46 @@ void CimditProfile::axisAction(uint8_t num, uint16_t state) {
case MOUSE_REL_Y_AXIS: {
int16_t pos = (int16_t)state - 512;
if (pos > JOYSTICK_DEAD_ZONE_Y) {
m_mouseMoveY = map(pos, JOYSTICK_DEAD_ZONE_Y, 511, 0, m_mappedAxis[i].m_value);
m_mouseMoveY = map(pos, JOYSTICK_DEAD_ZONE_Y, 511, 0, m_mappedAxis[i].m_value1);
} else if (pos < -JOYSTICK_DEAD_ZONE_Y) {
m_mouseMoveY = map(pos, -512, -JOYSTICK_DEAD_ZONE_Y, -m_mappedAxis[i].m_value, 0);
m_mouseMoveY = map(pos, -512, -JOYSTICK_DEAD_ZONE_Y, -m_mappedAxis[i].m_value1, 0);
} else {
m_mouseMoveY = 0;
}
}
break;
default:
case MIDI_CTRL_AXIS:
#ifdef HAVE_MIDI
{
midiEventPacket_t event = {0x0B, (uint8_t)(0xB0 | m_mappedAxis[i].m_value1), m_mappedAxis[i].m_value2, (uint8_t)(state/8)};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
#endif
break;
case MIDI_PITCH_AXIS:
#ifdef HAVE_MIDI
{
uint16_t val = (1023-state) * 16;
midiEventPacket_t event = {0x0E, (uint8_t)(0xE0 | m_mappedAxis[i].m_value1), (unsigned char)(val&127), (uint8_t)(val>>7)};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
#endif
break;
case MAPPING_NONE:
case JOYSTICK_BUTTON:
case MOUSE_BUTTON:
case MOUSE_REL_WHEEL:
case NEXT_PROFILE:
case PREV_PROFILE:
case SWITCH_PROFILE:
case MACRO_PRESS:
case MACRO_RELEASE:
case KEYBOARD_BUTTON:
case MIDI_NOTE:
case MIDI_CTRL:
case MIDI_PITCH:
break;
}
}
@ -550,27 +645,27 @@ void CimditProfile::buttonAction(uint8_t num, bool state) {
switch (m_mappedButtons[i].m_type) {
case JOYSTICK_BUTTON:
if (state) {
Gamepad.press(m_mappedButtons[i].m_value);
Gamepad.press(m_mappedButtons[i].m_value1);
} else {
Gamepad.release(m_mappedButtons[i].m_value);
Gamepad.release(m_mappedButtons[i].m_value1);
}
Gamepad.write();
break;
case MOUSE_BUTTON:
if (state) {
Mouse.press(m_mappedButtons[i].m_value);
Mouse.press(m_mappedButtons[i].m_value1);
} else {
Mouse.release(m_mappedButtons[i].m_value);
Mouse.release(m_mappedButtons[i].m_value1);
}
break;
case MOUSE_REL_X_AXIS:
Mouse.move(m_mappedButtons[i].m_value, 0, 0);
Mouse.move(m_mappedButtons[i].m_value1, 0, 0);
break;
case MOUSE_REL_Y_AXIS:
Mouse.move(0, m_mappedButtons[i].m_value, 0);
Mouse.move(0, m_mappedButtons[i].m_value1, 0);
break;
case MOUSE_REL_WHEEL:
Mouse.move(0, 0, m_mappedButtons[i].m_value);
Mouse.move(0, 0, m_mappedButtons[i].m_value1);
break;
case NEXT_PROFILE:
case PREV_PROFILE:
@ -592,21 +687,57 @@ void CimditProfile::buttonAction(uint8_t num, bool state) {
break;
case MACRO_PRESS:
if (state)
scanOrExecuteMacro(m_mappedButtons[i].m_value, true);
scanOrExecuteMacro(m_mappedButtons[i].m_value1, true);
break;
case MACRO_RELEASE:
if (!state)
scanOrExecuteMacro(m_mappedButtons[i].m_value, true);
scanOrExecuteMacro(m_mappedButtons[i].m_value1, true);
break;
case KEYBOARD_BUTTON:
if (state) {
Keyboard.press((KeyboardKeycode)m_mappedButtons[i].m_value);
Keyboard.press((KeyboardKeycode)m_mappedButtons[i].m_value1);
} else {
Keyboard.release((KeyboardKeycode)m_mappedButtons[i].m_value);
Keyboard.release((KeyboardKeycode)m_mappedButtons[i].m_value1);
}
break;
case MIDI_NOTE:
#ifdef HAVE_MIDI
if (state) {
// send a midi note on message
midiEventPacket_t noteOn = {0x09, (uint8_t)(0x90 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3};
MidiUSB.sendMIDI(noteOn);
} else {
// send a midi note on message
midiEventPacket_t noteOff = {0x08, (uint8_t)(0x80 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3};
MidiUSB.sendMIDI(noteOff);
}
MidiUSB.flush();
#endif
break;
case MIDI_CTRL:
#ifdef HAVE_MIDI
{
// send a midi note on message
midiEventPacket_t control = {0x0B, (uint8_t)(0xB0 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3};
MidiUSB.sendMIDI(control);
MidiUSB.flush();
}
#endif
break;
case MIDI_PITCH:
#ifdef HAVE_MIDI
{
// send a midi note on message
midiEventPacket_t event = {0x0E, (uint8_t)(0xE0 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
#endif
break;
case MAPPING_NONE:
case JOYSTICK_AXIS:
case MIDI_CTRL_AXIS:
case MIDI_PITCH_AXIS:
break;
}
}
@ -736,7 +867,6 @@ void CimditProfile::writeFlash() {
}
m_displayState = DISPLAY_BLANK; // to enforce a redraw
showActiveProfile();
return false;
}
void CimditProfile::setUserString(uint8_t timeout, const char* input) {
@ -787,7 +917,7 @@ void CimditProfile::userDisplay() {
buf = 0;
uint16_t len = width * height;
if (width != SCREEN_WIDTH || SCREEN_HEIGHT != 32) {
for (uint8_t i = 0; i < width * height; ++i) {
for (uint8_t i = 0; i < len; ++i) {
buf = Serial.read();
if (buf == '\n') buf = Serial.read();
}

View File

@ -94,6 +94,16 @@ class CimditProfile {
MACRO_RELEASE,
/// mapping as keyboard button
KEYBOARD_BUTTON,
/// mapping as MIDI note
MIDI_NOTE,
/// mapping as MIDI command
MIDI_CTRL,
/// mapping as MIDI pitch
MIDI_PITCH,
/// mapping axis as MIDI command
MIDI_CTRL_AXIS,
/// mapping axis as MIDI pitch
MIDI_PITCH_AXIS
};
/// enums for use in macros
@ -134,6 +144,14 @@ class CimditProfile {
MACRO_MOUSE_REL_X_AXIS, // 13
/// move mouse Y according to an analog axis
MACRO_MOUSE_REL_Y_AXIS, // 14
/// MIDI note on
MACRO_MIDI_NOTEON, // 15
/// MIDI note off
MACRO_MIDI_NOTEOFF, // 16
/// MIDI send control message
MACRO_MIDI_CTRL, // 17
/// MIDI send pitch message
MACRO_MIDI_PITCH, // 18
};
private:
@ -212,7 +230,13 @@ class CimditProfile {
MappingType m_type;
/// optional value
int8_t m_value;
uint8_t m_value1;
/// optional value 2
uint8_t m_value2;
/// optional value 2
uint8_t m_value3;
};
/// number of mapped buttons

View File

@ -1,6 +1,9 @@
/// we have a display connected
#define HAVE_DISPLAY
/// we want to create MIDI
#define HAVE_MIDI
/// use a custom keyboard layout
#define HID_CUSTOM_LAYOUT
@ -36,6 +39,9 @@
/// dead zone (noise) around the center of the joystick Y axcs
#define JOYSTICK_DEAD_ZONE_Y 20
/// optional analog filtering higher values mean faster changer, but more noise
#define ANALOG_LOW_PASS_FACTOR 0.95
/// i2c address of the external EEPROM
#define EXTERNAL_EEPROM 0x50

View File

@ -194,10 +194,143 @@
"source": 1,
"type": "NEXT_PROFILE"
}
],
"macros": []
},
{
"name": "MIDI",
"mappedbuttons": [
{
"source": 62,
"type": "SWITCH_PROFILE"
},
{
"source": 61,
"type": "MIDI_NOTE",
"channel": 0,
"note": 48,
"velocity": 64
},
{
"source": 53,
"type": "MIDI_NOTE",
"channel": 0,
"note": 49,
"velocity": 64
},
{
"source": 45,
"type": "MIDI_NOTE",
"channel": 0,
"note": 50,
"velocity": 64
},
{
"source": 37,
"type": "MIDI_NOTE",
"channel": 0,
"note": 51,
"velocity": 64
},
{
"source": 46,
"type": "MIDI_CTRL",
"channel": 0,
"control": 10,
"value": 0
},
{
"source": 38,
"type": "MIDI_CTRL",
"channel": 0,
"control": 10,
"value": 64
},
{
"source": 49,
"type": "MIDI_PITCH",
"channel": 0,
"value": 0
},
{
"source": 41,
"type": "MIDI_PITCH",
"channel": 0,
"value": 8192
},
{
"source": 33,
"type": "MACRO_PRESS",
"macro": 0
}
],
"mappedaxis": [
{
"source": 0,
"type": "MIDI_CTRL_AXIS",
"channel": 0,
"control": 10
},
{
"source": 1,
"type": "MIDI_PITCH_AXIS",
"channel": 0
},
{
"source": 2,
"type": "MIDI_CTRL_AXIS",
"channel": 0,
"control": 1
}
],
"mappedrotary": [
{
"source": 0,
"type": "PREV_PROFILE"
},
{
"source": 1,
"type": "NEXT_PROFILE"
}
],
"macros": [
[
"MACRO_MIDI_NOTEON",
0,
60,
64,
"MACRO_DELAY",
1000,
"MACRO_MIDI_CTRL",
0,
10,
0,
"MACRO_DELAY",
2000,
"MACRO_MIDI_CTRL",
0,
10,
64,
"MACRO_DELAY",
1000,
"MACRO_MIDI_PITCH",
0,
512,
"MACRO_DELAY",
1000,
"MACRO_MIDI_PITCH",
0,
8192,
"MACRO_DELAY",
1000,
"MACRO_MIDI_NOTEOFF",
0,
60,
64
]
]
}
]
</textarea>
]</textarea>
<p><button id="generatestring" class="button">Generate String</button></p>
<p id="error"></p>
<textarea id="string"></textarea>

View File

@ -14,6 +14,10 @@ type EntityJson = {
axis?: number;
value?: number;
macro?: number;
channel?: number;
note?: number;
velocity?: number;
control?: number;
}
type EntityProfileString = {
@ -48,6 +52,11 @@ class ProfileGenerator {
"MACRO_PRESS",
"MACRO_RELEASE",
"KEYBOARD_BUTTON",
"MIDI_NOTE",
"MIDI_CTRL",
"MIDI_PITCH",
"MIDI_CTRL_AXIS",
"MIDI_PITCH_AXIS",
];
private macroEnum: Array<string> = [
"MACRO_NULL",
@ -64,7 +73,11 @@ class ProfileGenerator {
"MACRO_MOUSE_REL_X",
"MACRO_MOUSE_REL_Y",
"MACRO_MOUSE_REL_X_AXIS",
"MACRO_MOUSE_REL_Y_AXIS"
"MACRO_MOUSE_REL_Y_AXIS",
"MACRO_MIDI_NOTEON",
"MACRO_MIDI_NOTEOFF",
"MACRO_MIDI_CTRL",
"MACRO_MIDI_PITCH",
];
private keyLookup = {
@ -424,7 +437,6 @@ class ProfileGenerator {
map(entities: Array<EntityJson>) : EntityProfileString {
var out ="";
var bytes = 0
var count = 0;
for (var i = 0; i < entities.length; ++i) {
var entity = entities[i];
@ -437,8 +449,27 @@ class ProfileGenerator {
} else {
tmp += this.hexString(this.keyLookup[<string>entity.target]);
}
} else if (entity.channel !== undefined && entity.note !== undefined && entity.velocity !== undefined && entity.type === 'MIDI_NOTE') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.note);
tmp += this.hexString(entity.velocity);
} else if (entity.channel !== undefined && entity.control !== undefined && entity.value !== undefined && entity.type === 'MIDI_CTRL') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.control);
tmp += this.hexString(entity.value);
} else if (entity.channel !== undefined && entity.value !== undefined && entity.type === 'MIDI_PITCH') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.value >> 8);
tmp += this.hexString(entity.value & 255);
} else if (entity.channel !== undefined && entity.control !== undefined && entity.type === 'MIDI_CTRL_AXIS') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.control);
} else if (entity.channel !== undefined && entity.type === 'MIDI_PITCH_AXIS') {
tmp += this.hexString(entity.channel);
} else if (entity.axis !== undefined) {
tmp += this.hexString(entity.axis);
} else if (entity.control !== undefined) {
tmp += this.hexString(entity.control);
} else if (entity.value !== undefined) {
tmp += this.hexString(entity.value);
} else if (entity.macro !== undefined) {
@ -447,14 +478,13 @@ class ProfileGenerator {
tmp += "00";
}
out += tmp;
bytes += 3;
++count;
} catch(e) {
// print error
console.log(e);
}
}
return {bytes: bytes, count: count, string: out};
return {bytes: out.length / 2, count: count, string: out};
}
createMacroString(macros: any[][]) : EntityProfileString {
@ -512,6 +542,17 @@ class ProfileGenerator {
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]);
bytes +=3;
}
} else if (token === "MACRO_MIDI_NOTEON" || token === "MACRO_MIDI_NOTEOFF") { // expect three integer values, channel, note and velocity
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]);
bytes += 4;
} else if (token === "MACRO_MIDI_CTRL") { // expect three integer values, channel, control and value
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]);
bytes += 4;
} else if (token === "MACRO_MIDI_PITCH") { // expect two integer values, channel and value (16 bit)
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]);
const value = macro[++j]
out += this.hexString(value >> 8) + this.hexString(value & 255);
bytes += 4;
} else {
if (typeof(token) === "number") {
out += this.hexString(token);
@ -624,6 +665,22 @@ class ProfileGenerator {
entity.value = this.fromHexS(tokens.shift());
} else if (entity.type === 'MACRO_PRESS' || entity.type === 'MACRO_RELEASE') {
entity.macro = this.fromHexU(tokens.shift());
} else if (entity.type === 'MIDI_NOTE') {
entity.channel = this.fromHexU(tokens.shift());
entity.note = this.fromHexU(tokens.shift());
entity.velocity = this.fromHexU(tokens.shift());
} else if (entity.type === 'MIDI_CTRL') {
entity.channel = this.fromHexU(tokens.shift());
entity.control = this.fromHexU(tokens.shift());
entity.value = this.fromHexU(tokens.shift());
} else if (entity.type === 'MIDI_PITCH') {
entity.channel = this.fromHexU(tokens.shift());
entity.value = this.fromHexU(tokens.shift())<<8 + this.fromHexU(tokens.shift());
} else if (entity.type === 'MIDI_CTRL_AXIS') {
entity.channel = this.fromHexU(tokens.shift());
entity.control = this.fromHexU(tokens.shift());
} else if (entity.type === 'MIDI_PITCH_AXIS') {
entity.channel = this.fromHexU(tokens.shift());
} else {
tokens.shift();
}
@ -691,6 +748,21 @@ class ProfileGenerator {
macro.push(this.fromHexS(tokens.shift()));
}
break;
case "MACRO_MIDI_NOTEON":
case "MACRO_MIDI_NOTEOFF":
macro.push(this.fromHexS(tokens.shift())); // channel
macro.push(this.fromHexS(tokens.shift())); // note
macro.push(this.fromHexS(tokens.shift())); // velocity
break;
case "MACRO_MIDI_CTRL":
macro.push(this.fromHexS(tokens.shift())); // channel
macro.push(this.fromHexS(tokens.shift())); // control
macro.push(this.fromHexS(tokens.shift())); // value
break;
case "MACRO_MIDI_PITCH":
macro.push(this.fromHexS(tokens.shift())); // channel
macro.push(this.fromHexU(tokens.shift())<<8 + this.fromHexU(tokens.shift())); // value
break;
}
} while (token !== "MACRO_NULL" && tokens.length > 0);
return macro;

View File

@ -194,10 +194,143 @@ textarea{width:100%}#string{height:5vh}.codeEditor,.lineCounter{font-family:cour
"source": 1,
"type": "NEXT_PROFILE"
}
],
"macros": []
},
{
"name": "MIDI",
"mappedbuttons": [
{
"source": 62,
"type": "SWITCH_PROFILE"
},
{
"source": 61,
"type": "MIDI_NOTE",
"channel": 0,
"note": 48,
"velocity": 64
},
{
"source": 53,
"type": "MIDI_NOTE",
"channel": 0,
"note": 49,
"velocity": 64
},
{
"source": 45,
"type": "MIDI_NOTE",
"channel": 0,
"note": 50,
"velocity": 64
},
{
"source": 37,
"type": "MIDI_NOTE",
"channel": 0,
"note": 51,
"velocity": 64
},
{
"source": 46,
"type": "MIDI_CTRL",
"channel": 0,
"control": 10,
"value": 0
},
{
"source": 38,
"type": "MIDI_CTRL",
"channel": 0,
"control": 10,
"value": 64
},
{
"source": 49,
"type": "MIDI_PITCH",
"channel": 0,
"value": 0
},
{
"source": 41,
"type": "MIDI_PITCH",
"channel": 0,
"value": 8192
},
{
"source": 33,
"type": "MACRO_PRESS",
"macro": 0
}
],
"mappedaxis": [
{
"source": 0,
"type": "MIDI_CTRL_AXIS",
"channel": 0,
"control": 10
},
{
"source": 1,
"type": "MIDI_PITCH_AXIS",
"channel": 0
},
{
"source": 2,
"type": "MIDI_CTRL_AXIS",
"channel": 0,
"control": 1
}
],
"mappedrotary": [
{
"source": 0,
"type": "PREV_PROFILE"
},
{
"source": 1,
"type": "NEXT_PROFILE"
}
],
"macros": [
[
"MACRO_MIDI_NOTEON",
0,
60,
64,
"MACRO_DELAY",
1000,
"MACRO_MIDI_CTRL",
0,
10,
0,
"MACRO_DELAY",
2000,
"MACRO_MIDI_CTRL",
0,
10,
64,
"MACRO_DELAY",
1000,
"MACRO_MIDI_PITCH",
0,
512,
"MACRO_DELAY",
1000,
"MACRO_MIDI_PITCH",
0,
8192,
"MACRO_DELAY",
1000,
"MACRO_MIDI_NOTEOFF",
0,
60,
64
]
]
}
]
</textarea>
]</textarea>
<p><button id="generatestring" class="button">Generate String</button></p>
<p id="error"></p>
<textarea id="string"></textarea>
@ -227,6 +360,11 @@ var ProfileGenerator = (function () {
"MACRO_PRESS",
"MACRO_RELEASE",
"KEYBOARD_BUTTON",
"MIDI_NOTE",
"MIDI_CTRL",
"MIDI_PITCH",
"MIDI_CTRL_AXIS",
"MIDI_PITCH_AXIS",
];
this.macroEnum = [
"MACRO_NULL",
@ -243,7 +381,11 @@ var ProfileGenerator = (function () {
"MACRO_MOUSE_REL_X",
"MACRO_MOUSE_REL_Y",
"MACRO_MOUSE_REL_X_AXIS",
"MACRO_MOUSE_REL_Y_AXIS"
"MACRO_MOUSE_REL_Y_AXIS",
"MACRO_MIDI_NOTEON",
"MACRO_MIDI_NOTEOFF",
"MACRO_MIDI_CTRL",
"MACRO_MIDI_PITCH",
];
this.keyLookup = {
"KEY_RESERVED": 0,
@ -597,7 +739,6 @@ var ProfileGenerator = (function () {
};
ProfileGenerator.prototype.map = function (entities) {
var out = "";
var bytes = 0;
var count = 0;
for (var i = 0; i < entities.length; ++i) {
var entity = entities[i];
@ -612,9 +753,34 @@ var ProfileGenerator = (function () {
tmp += this.hexString(this.keyLookup[entity.target]);
}
}
else if (entity.channel !== undefined && entity.note !== undefined && entity.velocity !== undefined && entity.type === 'MIDI_NOTE') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.note);
tmp += this.hexString(entity.velocity);
}
else if (entity.channel !== undefined && entity.control !== undefined && entity.value !== undefined && entity.type === 'MIDI_CTRL') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.control);
tmp += this.hexString(entity.value);
}
else if (entity.channel !== undefined && entity.value !== undefined && entity.type === 'MIDI_PITCH') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.value >> 8);
tmp += this.hexString(entity.value & 255);
}
else if (entity.channel !== undefined && entity.control !== undefined && entity.type === 'MIDI_CTRL_AXIS') {
tmp += this.hexString(entity.channel);
tmp += this.hexString(entity.control);
}
else if (entity.channel !== undefined && entity.type === 'MIDI_PITCH_AXIS') {
tmp += this.hexString(entity.channel);
}
else if (entity.axis !== undefined) {
tmp += this.hexString(entity.axis);
}
else if (entity.control !== undefined) {
tmp += this.hexString(entity.control);
}
else if (entity.value !== undefined) {
tmp += this.hexString(entity.value);
}
@ -625,14 +791,13 @@ var ProfileGenerator = (function () {
tmp += "00";
}
out += tmp;
bytes += 3;
++count;
}
catch (e) {
console.log(e);
}
}
return { bytes: bytes, count: count, string: out };
return { bytes: out.length / 2, count: count, string: out };
};
ProfileGenerator.prototype.createMacroString = function (macros) {
var bytes = 0;
@ -695,6 +860,20 @@ var ProfileGenerator = (function () {
bytes += 3;
}
}
else if (token === "MACRO_MIDI_NOTEON" || token === "MACRO_MIDI_NOTEOFF") {
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]);
bytes += 4;
}
else if (token === "MACRO_MIDI_CTRL") {
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]);
bytes += 4;
}
else if (token === "MACRO_MIDI_PITCH") {
out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]);
const value = macro[++j];
out += this.hexString(value >> 8) + this.hexString(value & 255);
bytes += 4;
}
else {
if (typeof (token) === "number") {
out += this.hexString(token);
@ -811,6 +990,27 @@ var ProfileGenerator = (function () {
else if (entity.type === 'MACRO_PRESS' || entity.type === 'MACRO_RELEASE') {
entity.macro = this.fromHexU(tokens.shift());
}
else if (entity.type === 'MIDI_NOTE') {
entity.channel = this.fromHexU(tokens.shift());
entity.note = this.fromHexU(tokens.shift());
entity.velocity = this.fromHexU(tokens.shift());
}
else if (entity.type === 'MIDI_CTRL') {
entity.channel = this.fromHexU(tokens.shift());
entity.control = this.fromHexU(tokens.shift());
entity.value = this.fromHexU(tokens.shift());
}
else if (entity.type === 'MIDI_PITCH') {
entity.channel = this.fromHexU(tokens.shift());
entity.value = this.fromHexU(tokens.shift()) << 8 + this.fromHexU(tokens.shift());
}
else if (entity.type === 'MIDI_CTRL_AXIS') {
entity.channel = this.fromHexU(tokens.shift());
entity.control = this.fromHexU(tokens.shift());
}
else if (entity.type === 'MIDI_PITCH_AXIS') {
entity.channel = this.fromHexU(tokens.shift());
}
else {
tokens.shift();
}
@ -878,6 +1078,21 @@ var ProfileGenerator = (function () {
macro.push(this.fromHexS(tokens.shift()));
}
break;
case "MACRO_MIDI_NOTEON":
case "MACRO_MIDI_NOTEOFF":
macro.push(this.fromHexS(tokens.shift()));
macro.push(this.fromHexS(tokens.shift()));
macro.push(this.fromHexS(tokens.shift()));
break;
case "MACRO_MIDI_CTRL":
macro.push(this.fromHexS(tokens.shift()));
macro.push(this.fromHexS(tokens.shift()));
macro.push(this.fromHexS(tokens.shift()));
break;
case "MACRO_MIDI_PITCH":
macro.push(this.fromHexS(tokens.shift()));
macro.push(this.fromHexU(tokens.shift()) << 8 + this.fromHexU(tokens.shift()));
break;
}
} while (token !== "MACRO_NULL" && tokens.length > 0);
return macro;