api_sysex.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include "api_sysex.h"
  2. #include "sysex_tools.h"
  3. #include "print.h"
  4. void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length) {
  5. // SEND_STRING("\nTX: ");
  6. // for (uint8_t i = 0; i < length; i++) {
  7. // send_byte(bytes[i]);
  8. // SEND_STRING(" ");
  9. // }
  10. if (length > API_SYSEX_MAX_SIZE) {
  11. xprintf("Sysex msg too big %d %d %d", message_type, data_type, length);
  12. return;
  13. }
  14. // The buffer size required is calculated as the following
  15. // API_SYSEX_MAX_SIZE is the maximum length
  16. // In addition to that we have a two byte message header consisting of the message_type and data_type
  17. // This has to be encoded with an additional overhead of one byte for every starting 7 bytes
  18. // We just add one extra byte in case it's not divisible by 7
  19. // Then we have an unencoded header consisting of 4 bytes
  20. // Plus a one byte terminator
  21. const unsigned message_header = 2;
  22. const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header;
  23. const unsigned encoding_overhead = unencoded_message / 7 + 1;
  24. const unsigned encoded_size = unencoded_message + encoding_overhead;
  25. const unsigned unencoded_header = 4;
  26. const unsigned terminator = 1;
  27. const unsigned buffer_size = encoded_size + unencoded_header + terminator;
  28. uint8_t buffer[encoded_size + unencoded_header + terminator];
  29. // The unencoded header
  30. buffer[0] = 0xF0;
  31. buffer[1] = 0x00;
  32. buffer[2] = 0x00;
  33. buffer[3] = 0x00;
  34. // We copy the message to the end of the array, this way we can do an inplace encoding, using the same
  35. // buffer for both input and output
  36. const unsigned message_size = length + message_header;
  37. uint8_t* unencoded_start = buffer + buffer_size - message_size;
  38. uint8_t* ptr = unencoded_start;
  39. *(ptr++) = message_type;
  40. *(ptr++) = data_type;
  41. memcpy(ptr, bytes, length);
  42. unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size);
  43. unsigned final_size = unencoded_header + encoded_length + terminator;
  44. buffer[final_size - 1] = 0xF7;
  45. midi_send_array(&midi_device, final_size, buffer);
  46. // SEND_STRING("\nTD: ");
  47. // for (uint8_t i = 0; i < encoded_length + 5; i++) {
  48. // send_byte(buffer[i]);
  49. // SEND_STRING(" ");
  50. // }
  51. }