diff options
| -rw-r--r-- | quantum/api/api_sysex.c | 60 | ||||
| -rw-r--r-- | quantum/config_common.h | 2 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 32 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.h | 4 |
4 files changed, 71 insertions, 27 deletions
diff --git a/quantum/api/api_sysex.c b/quantum/api/api_sysex.c index a4a554e76..868f854b9 100644 --- a/quantum/api/api_sysex.c +++ b/quantum/api/api_sysex.c | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | #include "api_sysex.h" | 1 | #include "api_sysex.h" |
| 2 | #include "sysex_tools.h" | ||
| 3 | #include "print.h" | ||
| 2 | 4 | ||
| 3 | void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length) { | 5 | void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length) { |
| 4 | // SEND_STRING("\nTX: "); | 6 | // SEND_STRING("\nTX: "); |
| @@ -6,24 +8,50 @@ void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, | |||
| 6 | // send_byte(bytes[i]); | 8 | // send_byte(bytes[i]); |
| 7 | // SEND_STRING(" "); | 9 | // SEND_STRING(" "); |
| 8 | // } | 10 | // } |
| 9 | uint8_t * precode = malloc(sizeof(uint8_t) * (length + 2)); | 11 | if (length > API_SYSEX_MAX_SIZE) { |
| 10 | precode[0] = message_type; | 12 | xprintf("Sysex msg too big %d %d %d", message_type, data_type, length); |
| 11 | precode[1] = data_type; | 13 | return; |
| 12 | memcpy(precode + 2, bytes, length); | 14 | } |
| 13 | uint8_t * encoded = malloc(sizeof(uint8_t) * (sysex_encoded_length(length + 2))); | 15 | |
| 14 | uint16_t encoded_length = sysex_encode(encoded, precode, length + 2); | 16 | |
| 15 | uint8_t * array = malloc(sizeof(uint8_t) * (encoded_length + 5)); | 17 | // The buffer size required is calculated as the following |
| 16 | array[0] = 0xF0; | 18 | // API_SYSEX_MAX_SIZE is the maximum length |
| 17 | array[1] = 0x00; | 19 | // In addition to that we have a two byte message header consisting of the message_type and data_type |
| 18 | array[2] = 0x00; | 20 | // This has to be encoded with an additional overhead of one byte for every starting 7 bytes |
| 19 | array[3] = 0x00; | 21 | // We just add one extra byte in case it's not divisible by 7 |
| 20 | array[encoded_length + 4] = 0xF7; | 22 | // Then we have an unencoded header consisting of 4 bytes |
| 21 | memcpy(array + 4, encoded, encoded_length); | 23 | // Plus a one byte terminator |
| 22 | midi_send_array(&midi_device, encoded_length + 5, array); | 24 | const unsigned message_header = 2; |
| 25 | const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header; | ||
| 26 | const unsigned encoding_overhead = unencoded_message / 7 + 1; | ||
| 27 | const unsigned encoded_size = unencoded_message + encoding_overhead; | ||
| 28 | const unsigned unencoded_header = 4; | ||
| 29 | const unsigned terminator = 1; | ||
| 30 | const unsigned buffer_size = encoded_size + unencoded_header + terminator; | ||
| 31 | uint8_t buffer[encoded_size + unencoded_header + terminator]; | ||
| 32 | // The unencoded header | ||
| 33 | buffer[0] = 0xF0; | ||
| 34 | buffer[1] = 0x00; | ||
| 35 | buffer[2] = 0x00; | ||
| 36 | buffer[3] = 0x00; | ||
| 37 | |||
| 38 | // We copy the message to the end of the array, this way we can do an inplace encoding, using the same | ||
| 39 | // buffer for both input and output | ||
| 40 | const unsigned message_size = length + message_header; | ||
| 41 | uint8_t* unencoded_start = buffer + buffer_size - message_size; | ||
| 42 | uint8_t* ptr = unencoded_start; | ||
| 43 | *(ptr++) = message_type; | ||
| 44 | *(ptr++) = data_type; | ||
| 45 | memcpy(ptr, bytes, length); | ||
| 46 | |||
| 47 | unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size); | ||
| 48 | unsigned final_size = unencoded_header + encoded_length + terminator; | ||
| 49 | buffer[final_size - 1] = 0xF7; | ||
| 50 | midi_send_array(&midi_device, final_size, buffer); | ||
| 23 | 51 | ||
| 24 | // SEND_STRING("\nTD: "); | 52 | // SEND_STRING("\nTD: "); |
| 25 | // for (uint8_t i = 0; i < encoded_length + 5; i++) { | 53 | // for (uint8_t i = 0; i < encoded_length + 5; i++) { |
| 26 | // send_byte(array[i]); | 54 | // send_byte(buffer[i]); |
| 27 | // SEND_STRING(" "); | 55 | // SEND_STRING(" "); |
| 28 | // } | 56 | // } |
| 29 | } \ No newline at end of file | 57 | } |
diff --git a/quantum/config_common.h b/quantum/config_common.h index 17c11faeb..4bdb2065d 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h | |||
| @@ -80,4 +80,6 @@ | |||
| 80 | # endif | 80 | # endif |
| 81 | #endif | 81 | #endif |
| 82 | 82 | ||
| 83 | #define API_SYSEX_MAX_SIZE 32 | ||
| 84 | |||
| 83 | #endif | 85 | #endif |
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 097189770..6dd5959dc 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c | |||
| @@ -1252,28 +1252,40 @@ void cc_callback(MidiDevice * device, | |||
| 1252 | // midi_send_cc(device, (chan + 1) % 16, num, val); | 1252 | // midi_send_cc(device, (chan + 1) % 16, num, val); |
| 1253 | } | 1253 | } |
| 1254 | 1254 | ||
| 1255 | #ifdef API_SYSEX_ENABLE | ||
| 1255 | uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0}; | 1256 | uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0}; |
| 1257 | #endif | ||
| 1256 | 1258 | ||
| 1257 | void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) { | 1259 | void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) { |
| 1258 | #ifdef API_SYSEX_ENABLE | 1260 | #ifdef API_SYSEX_ENABLE |
| 1259 | // SEND_STRING("\n"); | 1261 | // SEND_STRING("\n"); |
| 1260 | // send_word(start); | 1262 | // send_word(start); |
| 1261 | // SEND_STRING(": "); | 1263 | // SEND_STRING(": "); |
| 1264 | // Don't store the header | ||
| 1265 | int16_t pos = start - 4; | ||
| 1262 | for (uint8_t place = 0; place < length; place++) { | 1266 | for (uint8_t place = 0; place < length; place++) { |
| 1263 | // send_byte(*data); | 1267 | // send_byte(*data); |
| 1264 | midi_buffer[start + place] = *data; | 1268 | if (pos >= 0) { |
| 1265 | if (*data == 0xF7) { | 1269 | if (*data == 0xF7) { |
| 1266 | // SEND_STRING("\nRD: "); | 1270 | // SEND_STRING("\nRD: "); |
| 1267 | // for (uint8_t i = 0; i < start + place + 1; i++){ | 1271 | // for (uint8_t i = 0; i < start + place + 1; i++){ |
| 1268 | // send_byte(midi_buffer[i]); | 1272 | // send_byte(midi_buffer[i]); |
| 1269 | // SEND_STRING(" "); | 1273 | // SEND_STRING(" "); |
| 1270 | // } | 1274 | // } |
| 1271 | uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4))); | 1275 | const unsigned decoded_length = sysex_decoded_length(pos); |
| 1272 | uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4); | 1276 | uint8_t decoded[API_SYSEX_MAX_SIZE]; |
| 1273 | process_api(decode_length, decoded); | 1277 | sysex_decode(decoded, midi_buffer, pos); |
| 1278 | process_api(decoded_length, decoded); | ||
| 1279 | return; | ||
| 1280 | } | ||
| 1281 | else if (pos >= MIDI_SYSEX_BUFFER) { | ||
| 1282 | return; | ||
| 1283 | } | ||
| 1284 | midi_buffer[pos] = *data; | ||
| 1274 | } | 1285 | } |
| 1275 | // SEND_STRING(" "); | 1286 | // SEND_STRING(" "); |
| 1276 | data++; | 1287 | data++; |
| 1288 | pos++; | ||
| 1277 | } | 1289 | } |
| 1278 | #endif | 1290 | #endif |
| 1279 | } | 1291 | } |
diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h index b11854101..a049fd43c 100644 --- a/tmk_core/protocol/lufa/lufa.h +++ b/tmk_core/protocol/lufa/lufa.h | |||
| @@ -70,7 +70,6 @@ typedef struct { | |||
| 70 | #ifdef MIDI_ENABLE | 70 | #ifdef MIDI_ENABLE |
| 71 | void MIDI_Task(void); | 71 | void MIDI_Task(void); |
| 72 | MidiDevice midi_device; | 72 | MidiDevice midi_device; |
| 73 | #define MIDI_SYSEX_BUFFER 32 | ||
| 74 | #endif | 73 | #endif |
| 75 | 74 | ||
| 76 | #ifdef API_ENABLE | 75 | #ifdef API_ENABLE |
| @@ -79,6 +78,9 @@ typedef struct { | |||
| 79 | 78 | ||
| 80 | #ifdef API_SYSEX_ENABLE | 79 | #ifdef API_SYSEX_ENABLE |
| 81 | #include "api_sysex.h" | 80 | #include "api_sysex.h" |
| 81 | // Allocate space for encoding overhead. | ||
| 82 | //The header and terminator are not stored to save a few bytes of precious ram | ||
| 83 | #define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0)) | ||
| 82 | #endif | 84 | #endif |
| 83 | 85 | ||
| 84 | // #if LUFA_VERSION_INTEGER < 0x120730 | 86 | // #if LUFA_VERSION_INTEGER < 0x120730 |
