pull/32/head
Holger Wirtz 5 years ago
parent 1533e6ba12
commit 0058a83f3c
  1. 6
      MicroDexed.ino
  2. 16
      config.h
  3. 51
      dexed_sysex.cpp
  4. 2
      dexed_sysex.h
  5. 137
      doc/sysex-format_dexed-setup.txt

@ -1328,8 +1328,6 @@ void initial_values_from_eeprom(bool init)
void check_configuration(void) void check_configuration(void)
{ {
configuration.instances = constrain(configuration.instances, INSTANCES_MIN, INSTANCES_MAX); configuration.instances = constrain(configuration.instances, INSTANCES_MIN, INSTANCES_MAX);
configuration.instance_mode = constrain(configuration.instance_mode, INSTANCE_MODE_MIN, INSTANCE_MODE_MAX);
configuration.instance_splitpoint = constrain(configuration.instance_splitpoint, INSTANCE_SPLITPOINT_MAX, INSTANCE_SPLITPOINT_MAX);
configuration.vol = constrain(configuration.vol, VOLUME_MIN, VOLUME_MAX); configuration.vol = constrain(configuration.vol, VOLUME_MIN, VOLUME_MAX);
configuration.mono = constrain(configuration.mono, MONO_MIN, MONO_MAX); configuration.mono = constrain(configuration.mono, MONO_MIN, MONO_MAX);
configuration.reverb_roomsize = constrain(configuration.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX); configuration.reverb_roomsize = constrain(configuration.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX);
@ -1347,6 +1345,8 @@ void check_configuration(void)
configuration.dexed[instance_id].midi_channel = constrain(configuration.dexed[instance_id].midi_channel, MIDI_CHANNEL_MIN, MIDI_CHANNEL_MAX); configuration.dexed[instance_id].midi_channel = constrain(configuration.dexed[instance_id].midi_channel, MIDI_CHANNEL_MIN, MIDI_CHANNEL_MAX);
configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1); configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1);
configuration.dexed[instance_id].voice = constrain(configuration.dexed[instance_id].voice, 0, MAX_VOICES - 1); configuration.dexed[instance_id].voice = constrain(configuration.dexed[instance_id].voice, 0, MAX_VOICES - 1);
configuration.dexed[instance_id].lowest_note = constrain(configuration.dexed[instance_id].lowest_note, INSTANCE_LOWEST_NOTE_MIN, INSTANCE_LOWEST_NOTE_MAX);
configuration.dexed[instance_id].highest_note = constrain(configuration.dexed[instance_id].highest_note, INSTANCE_HIGHEST_NOTE_MIN, INSTANCE_HIGHEST_NOTE_MAX);
configuration.dexed[instance_id].reverb_send = constrain(configuration.dexed[instance_id].reverb_send, REVERB_SEND_MIN, REVERB_SEND_MAX); configuration.dexed[instance_id].reverb_send = constrain(configuration.dexed[instance_id].reverb_send, REVERB_SEND_MIN, REVERB_SEND_MAX);
configuration.dexed[instance_id].chorus_send = constrain(configuration.dexed[instance_id].chorus_send, CHORUS_SEND_MIN, CHORUS_SEND_MAX); configuration.dexed[instance_id].chorus_send = constrain(configuration.dexed[instance_id].chorus_send, CHORUS_SEND_MIN, CHORUS_SEND_MAX);
configuration.dexed[instance_id].delay_send = constrain(configuration.dexed[instance_id].delay_send, DELAY_SEND_MIN, DELAY_SEND_MAX); configuration.dexed[instance_id].delay_send = constrain(configuration.dexed[instance_id].delay_send, DELAY_SEND_MIN, DELAY_SEND_MAX);
@ -1389,8 +1389,6 @@ void init_configuration(void)
configuration.checksum = 0xffff; configuration.checksum = 0xffff;
configuration.instances = INSTANCES_DEFAULT; configuration.instances = INSTANCES_DEFAULT;
configuration.instance_mode = INSTANCE_MODE_DEFAULT;
configuration.instance_splitpoint = INSTANCE_SPLITPOINT_DEFAULT;
configuration.vol = VOLUME_DEFAULT; configuration.vol = VOLUME_DEFAULT;
configuration.mono = MONO_DEFAULT; configuration.mono = MONO_DEFAULT;
configuration.reverb_roomsize = REVERB_ROOMSIZE_DEFAULT; configuration.reverb_roomsize = REVERB_ROOMSIZE_DEFAULT;

@ -290,6 +290,14 @@ enum { DEXED, CHORUS, DELAY, REVERB};
#define MIDI_CHANNEL_MAX 16 #define MIDI_CHANNEL_MAX 16
#define MIDI_CHANNEL_DEFAULT MIDI_CHANNEL_OMNI #define MIDI_CHANNEL_DEFAULT MIDI_CHANNEL_OMNI
#define INSTANCE_LOWEST_NOTE_MIN 21
#define INSTANCE_LOWEST_NOTE_MAX 108
#define INSTANCE_LOWEST_NOTE_DEFAULT 21
#define INSTANCE_HIGHEST_NOTE_MIN 21
#define INSTANCE_HIGHEST_NOTE_MAX 108
#define INSTANCE_HIGHEST_NOTE_DEFAULT 108
#define REVERB_ROOMSIZE_MIN 0 #define REVERB_ROOMSIZE_MIN 0
#define REVERB_ROOMSIZE_MAX 100 #define REVERB_ROOMSIZE_MAX 100
#define REVERB_ROOMSIZE_DEFAULT 0 #define REVERB_ROOMSIZE_DEFAULT 0
@ -438,15 +446,13 @@ enum { DEXED, CHORUS, DELAY, REVERB};
#define INSTANCE_MODE_MAX 1 #define INSTANCE_MODE_MAX 1
#define INSTANCE_MODE_DEFAULT 0 #define INSTANCE_MODE_DEFAULT 0
#define INSTANCE_SPLITPOINT_MIN MIDI_AIS0
#define INSTANCE_SPLITPOINT_MAX MIDI_B7
#define INSTANCE_SPLITPOINT_DEFAULT MIDI_C3
// //
typedef struct { typedef struct {
uint8_t midi_channel; uint8_t midi_channel;
uint8_t bank; uint8_t bank;
uint8_t voice; uint8_t voice;
uint8_t lowest_note;
uint8_t highest_note;
uint8_t reverb_send; uint8_t reverb_send;
uint8_t chorus_send; uint8_t chorus_send;
uint8_t delay_send; uint8_t delay_send;
@ -479,8 +485,6 @@ typedef struct {
typedef struct { typedef struct {
uint32_t checksum; uint32_t checksum;
uint8_t instances; uint8_t instances;
uint8_t instance_mode;
uint8_t instance_splitpoint;
uint8_t vol; uint8_t vol;
uint8_t mono; uint8_t mono;
uint8_t reverb_roomsize; uint8_t reverb_roomsize;

@ -408,6 +408,7 @@ bool get_sysex_setup(File sysex, config_t configuration)
#endif #endif
return (false); return (false);
} }
sysex.seek(3); sysex.seek(3);
uint8_t dexed_sysex_setup_type = sysex.read(); uint8_t dexed_sysex_setup_type = sysex.read();
if (dexed_sysex_setup_type >= 0x42 && dexed_sysex_setup_type < 0x45) // check for sysex type (0x75=MicroDexed setup for one to four instances) if (dexed_sysex_setup_type >= 0x42 && dexed_sysex_setup_type < 0x45) // check for sysex type (0x75=MicroDexed setup for one to four instances)
@ -417,6 +418,10 @@ bool get_sysex_setup(File sysex, config_t configuration)
#endif #endif
return (false); return (false);
} }
sysex.seek(4);
uint8_t sysex_config_size = sysex.read();
sysex.seek(sysex.size() - 1); // Bulk checksum sysex.seek(sysex.size() - 1); // Bulk checksum
bulk_checksum = sysex.read(); bulk_checksum = sysex.read();
@ -424,11 +429,6 @@ bool get_sysex_setup(File sysex, config_t configuration)
for (n = 0; n < sysex.size() - 2; n++) for (n = 0; n < sysex.size() - 2; n++)
{ {
uint8_t d = sysex.read(); uint8_t d = sysex.read();
#ifdef DEBUG
Serial.print(n + 6, DEC);
Serial.print(F("="));
Serial.println(d);
#endif
bulk_checksum_calc -= d; bulk_checksum_calc -= d;
} }
bulk_checksum_calc &= 0x7f; bulk_checksum_calc &= 0x7f;
@ -452,6 +452,21 @@ bool get_sysex_setup(File sysex, config_t configuration)
return (false); return (false);
} }
// Now everything is ok and we can read the data
sysex.seek(6); // start of bulk data
uint8_t* conf = (uint8_t*)&configuration + 4;
for (n = 0; n < sysex_config_size; n++)
{
uint8_t d = sysex.read();
#ifdef DEBUG
Serial.print(n + 6, DEC);
Serial.print(F("="));
Serial.println(d);
#endif
*(conf + n) = d;
}
configuration.checksum = crc32((uint8_t*)&configuration + 4, sizeof(configuration) - 4);
return (true); return (true);
} }
@ -504,3 +519,29 @@ bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id)
return (false); return (false);
} }
bool save_sysex_setup(uint8_t b, uint8_t v, config_t configuration)
{
const char* sysex_filename = "config.syx";
if (sd_card_available)
{
File sysex;
char sysex_file_name[20];
create_sysex_filename(b, sysex_file_name, v);
sysex = SD.create(sysex_file_name);
if (!sysex)
{
#ifdef DEBUG
Serial.print(F("E : Cannot create "));
Serial.print(sysex_file_name);
Serial.println(F("on SD."));
#endif
return (false);
}
}
return (false);
}

@ -44,6 +44,7 @@ extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
extern uint8_t ui_state; extern uint8_t ui_state;
extern uint8_t ui_main_state; extern uint8_t ui_main_state;
extern config_t configuration; extern config_t configuration;
extern uint32_t crc32(byte * calc_start, uint16_t calc_bytes);
void create_sysex_filename(uint8_t b, char* sysex_file_name); void create_sysex_filename(uint8_t b, char* sysex_file_name);
void strip_extension(char* s, char *target); void strip_extension(char* s, char *target);
@ -55,5 +56,6 @@ bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data);
void create_sysex_setup_filename(uint8_t b, uint8_t v, char* sysex_setup_file_name); void create_sysex_setup_filename(uint8_t b, uint8_t v, char* sysex_setup_file_name);
bool get_sysex_setup(File sysex, uint8_t voice_number, uint8_t* data); bool get_sysex_setup(File sysex, uint8_t voice_number, uint8_t* data);
bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id); bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id);
bool save_sysex_setup(uint8_t b, uint8_t v, config_t configuration);
#endif #endif

@ -7,42 +7,42 @@ SYSEX Message Controller-Set
11110000 F0 Status byte - start sysex 11110000 F0 Status byte - start sysex
0iiiiiii 67 ID # (i=103; unofficial SYSEX-ID for MicroDexed) 0iiiiiii 67 ID # (i=103; unofficial SYSEX-ID for MicroDexed)
0sssnnnn 00 Sub-status (s=0) & channel number (n=0; ch 1) 0sssnnnn 00 Sub-status (s=0) & channel number (n=0; ch 1)
0fffffff 00 format number (f=66..69; 1..4 MicroDexed setup(s)) 0fffffff ** format number (f=66..69; 1..4 MicroDexed setup(s))
0bbbbbbb 01 byte count MS byte 0bbbbbbb ** byte count MS byte
0bbbbbbb 1B byte count LS byte (b=44; 1 instance 0bbbbbbb ** byte count LS byte (b=44; 1 instance
b=73; 2 instances b=75; 2 instances
b=102; 3 instances b=106; 3 instances
b=131; 4 instances) b=137; 4 instances)
0ddddddd ** data byte 1 setup config 0ddddddd ** data byte 1 setup config
| | | | | |
0ddddddd ** data byte 19 0ddddddd ** data byte 13
0ddddddd ** data byte 20 instance config 0 0ddddddd ** data byte 14 instance config 0
| | | | | |
0ddddddd ** data byte 43 0ddddddd ** data byte 44
/-Optional--------------------------------------------\ /-Optional--------------------------------------------\
0ddddddd ** data byte 44 instance config 1 0ddddddd ** data byte 45 instance config 1
| | | | | |
0ddddddd ** data byte 72 0ddddddd ** data byte 74
\-----------------------------------------------------/ \-----------------------------------------------------/
/-Optional--------------------------------------------\ /-Optional--------------------------------------------\
0ddddddd ** data byte 73 instance config 2 0ddddddd ** data byte 75 instance config 2
| | | | | |
0ddddddd ** data byte 101 0ddddddd ** data byte 105
\-----------------------------------------------------/ \-----------------------------------------------------/
/-Optional--------------------------------------------\ /-Optional--------------------------------------------\
0ddddddd ** data byte 102 instance config 3 0ddddddd ** data byte 106 instance config 3
| | | | | |
0ddddddd ** data byte 131 0ddddddd ** data byte 137
\-----------------------------------------------------/ \-----------------------------------------------------/
0eeeeeee ** checksum (masked 2's comp. of sum of ** bytes) 0eeeeeee ** checksum (masked 2's comp. of sum of ** bytes)
11110111 F7 Status - end sysex 11110111 F7 Status - end sysex
@ -50,77 +50,48 @@ SYSEX Message Controller-Set
Data Structure: MicroDexed Setup Dump Data Structure: MicroDexed Setup Dump
------------------------------------- -------------------------------------
Parameter
Number Parameter Value Range Number Parameter Value Range
--------- --------- ----------- --------- --------- -----------
0 GLOBAL STERO/MONO 0-3 (0=stereo, 1=mono, 2=mono-r, 3=mono-l) 0 GLOBAL STERO/MONO 0-3 (0=stereo, 1=mono, 2=mono-r, 3=mono-l)
1 GLOBAL REVERB-ROOMSIZE 0-100 1 GLOBAL REVERB-ROOMSIZE 0-100
2 GLOBAL REVERB-DAMPING 0-100 2 GLOBAL REVERB-DAMPING 0-100
3 GLOBAL CHORUS-FREQUENCY 0-100 (multiplied by 1/10 Hz) 3 GLOBAL REVERB-LEVEL 0-100
4 GLOBAL CHORUS-WAVEFORM 0-1 (0=triangle, 1=sine) 4 GLOBAL CHORUS-FREQUENCY 0-100 (multiplied by 1/10 Hz)
5 GLOBAL CHORUS-DEPTH 0-100 5 GLOBAL CHORUS-WAVEFORM 0-1 (0=triangle, 1=sine)
6 GLOBAL DELAY-TIME 0-60 (multiplied by 10ms) 6 GLOBAL CHORUS-DEPTH 0-100
7 GLOBAL DELAY-FEEDBACK 0-100 7 GLOBAL CHORUS-LEVEL 0-100
8 DEXED 1 MONO/POLY MODE CHANGE 0-1 O=POLY 8 GLOBAL DELAY-TIME 0-50 (multiplied by 10ms)
9 DEXED 1 PITCH BEND RANGE 0-12 9 GLOBAL DELAY-FEEDBACK 0-100
10 DEXED 1 " " STEP 0-12 10 GLOBAL DELAY-LEVEL 0-100
11 DEXED 1 PORTAMENTO MODE 0-1 0=RETAIN 1=FOLLOW
12 DEXED 1 " GLISS 0-1
13 DEXED 1 " TIME 0-99
14 DEXED 1 MOD WHEEL RANGE 0-99
15 DEXED 1 " " ASSIGN 0-7 b0: pitch, b1:amp, b2: EG bias
16 DEXED 1 FOOT CONTROL RANGE 0-99
17 DEXED 1 " " ASSIGN 0-7 "
18 DEXED 1 BREATH CONT RANGE 0-99
19 DEXED 1 " " ASSIGN 0-7 "
20 DEXED 1 AFTERTOUCH RANGE 0-99
21 DEXED 1 " ASSIGN 0-7 "
22 DEXED 1 OP1_ENABLE 0-1
23 DEXED 1 OP2_ENABLE 0-1
24 DEXED 1 OP3_ENABLE 0-1
25 DEXED 1 OP4_ENABLE 0-1
26 DEXED 1 OP5_ENABLE 0-1
27 DEXED 1 OP6_ENABLE 0-1
28 DEXED 1 MAX_NOTES 0-32
29 DEXED 1 LOUDNESS 0-100
30 DEXED 1 PANORAMA 0-40 (20 is middle)
31 DEXED 1 REVERB-LEVEL 0-100
32 DEXED 1 CHORUS-LEVEL 0-100
33 DEXED 1 DELAY-LEVEL 0-100
34 DEXED 1 FILTER-CUTOFF 0-100
35 DEXED 1 FILTER-RESONANCE 0-100
26 DEXED 1 MIDI-CHANNEL 0-16 (0=OMNI)
37 DEXED 1 POLYPHONY 0-32 (depends on CPU and FX)
38 DEXED 1 ENGINE 0-2 (1=Modern, 2=Mark1, 2=OPL)
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
39 DEXED 2 MONO/POLY MODE CHANGE 0-1 O=POLY 11 DEXED 1 MIDI-CHANNEL 0-16 (0=OMNI)
40 DEXED 2 PITCH BEND RANGE 0-12 12 DEXED 1 BANK 0-99
41 DEXED 2 " " STEP 0-12 13 DEXED 1 VOICE 0-31
42 DEXED 2 PORTAMENTO MODE 0-1 0=RETAIN 1=FOLLOW 14 DEXED 1 LOWEST NOTE 21-108
43 DEXED 2 " GLISS 0-1 15 DEXED 1 HIGHEST NOTE 21-108
44 DEXED 2 " TIME 0-99 16 DEXED 1 REVERB SEND 0-100
45 DEXED 2 MOD WHEEL RANGE 0-99 17 DEXED 1 CHORUS SEND 0-100
46 DEXED 2 " " ASSIGN 0-7 b0: pitch, b1:amp, b2: EG bias 18 DEXED 1 DELAY SEND 0-100
47 DEXED 2 FOOT CONTROL RANGE 0-99 19 DEXED 2 FILTER-CUTOFF 0-100
48 DEXED 2 " " ASSIGN 0-7 " 20 DEXED 2 FILTER-RESONANCE 0-100
49 DEXED 2 BREATH CONT RANGE 0-99 21 DEXED 2 TRANSPOSE 0-48
40 DEXED 2 " " ASSIGN 0-7 " 22 DEXED 2 TUNE 0-100
51 DEXED 2 AFTERTOUCH RANGE 0-99 23 DEXED 2 SOUND INTENSITY 0-100
52 DEXED 2 " ASSIGN 0-7 " 24 DEXED 2 PANORAMA 0-40 (20 is middle)
53 DEXED 2 OP1_ENABLE 0-1 25 DEXED 1 POLYPHONY 0-32 (depends on CPU and FX)
54 DEXED 2 OP2_ENABLE 0-1 26 DEXED 1 ENGINE 0-2 (1=Modern, 2=Mark1, 2=OPL)
55 DEXED 2 OP3_ENABLE 0-1 27 DEXED 1 MONO/POLY MODE CHANGE 0-1 O=POLY
56 DEXED 2 OP4_ENABLE 0-1 28 DEXED 1 PITCH BEND RANGE 0-12
57 DEXED 2 OP5_ENABLE 0-1 29 DEXED 1 " " STEP 0-12
58 DEXED 2 OP6_ENABLE 0-1 30 DEXED 1 MOD WHEEL RANGE 0-99
59 DEXED 2 MAX_NOTES 0-32 31 DEXED 1 " " ASSIGN 0-7 b0: pitch, b1:amp, b2: EG bias
60 DEXED 2 LOUDNESS 0-100 32 DEXED 1 FOOT CONTROL RANGE 0-99
61 DEXED 2 PANORAMA 0-40 (20 is middle) 33 DEXED 1 " " ASSIGN 0-7 "
62 DEXED 2 REVERB-LEVEL 0-100 34 DEXED 1 BREATH CONT RANGE 0-99
63 DEXED 2 CHORUS-LEVEL 0-100 35 DEXED 1 " " ASSIGN 0-7 "
64 DEXED 2 DELAY-LEVEL 0-100 36 DEXED 1 AFTERTOUCH RANGE 0-99
65 DEXED 2 FILTER-CUTOFF 0-100 37 DEXED 1 " ASSIGN 0-7 "
66 DEXED 2 FILTER-RESONANCE 0-100 38 DEXED 1 PORTAMENTO MODE 0-1 0=RETAIN 1=FOLLOW
67 DEXED 2 MIDI-CHANNEL 0-16 (0=OMNI) 39 DEXED 1 " GLISS 0-1
68 DEXED 2 POLYPHONY 0-32 (depends on CPU and FX) 40 DEXED 1 " TIME 0-99
69 DEXED 2 ENGINE 0-2 (1=Modern, 2=Mark1, 2=OPL) 41 DEXED 1 OP_ENABLE 0-31

Loading…
Cancel
Save