Teensy 4.1 core updated for C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 11 година
пре 11 година
пре 10 година
пре 11 година
пре 10 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 7 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 11 година
пре 7 година
пре 7 година
пре 11 година
пре 7 година
пре 7 година
пре 7 година
пре 11 година
пре 11 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* Teensyduino Core Library
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2017 PJRC.COM, LLC.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * 1. The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * 2. If the Software is incorporated into a build system that allows
  17. * selection among a list of target devices, then similar target
  18. * devices manufactured by PJRC.COM must be included in the list of
  19. * target devices and selectable in the same manner.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  25. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  26. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  27. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28. * SOFTWARE.
  29. */
  30. #ifndef USBmidi_h_
  31. #define USBmidi_h_
  32. #include "usb_desc.h"
  33. #if defined(MIDI_INTERFACE)
  34. #include <inttypes.h>
  35. // maximum sysex length we can receive
  36. #if defined(__MKL26Z64__) || defined(__MK20DX128__)
  37. #define USB_MIDI_SYSEX_MAX 60
  38. #else
  39. #define USB_MIDI_SYSEX_MAX 290
  40. #endif
  41. // C language implementation
  42. #ifdef __cplusplus
  43. extern "C" {
  44. #endif
  45. void usb_midi_write_packed(uint32_t n);
  46. void usb_midi_send_sysex_buffer_has_term(const uint8_t *data, uint32_t length, uint8_t cable);
  47. void usb_midi_send_sysex_add_term_bytes(const uint8_t *data, uint32_t length, uint8_t cable);
  48. void usb_midi_flush_output(void);
  49. int usb_midi_read(uint32_t channel);
  50. uint32_t usb_midi_available(void);
  51. uint32_t usb_midi_read_message(void);
  52. extern uint8_t usb_midi_msg_cable;
  53. extern uint8_t usb_midi_msg_channel;
  54. extern uint8_t usb_midi_msg_type;
  55. extern uint8_t usb_midi_msg_data1;
  56. extern uint8_t usb_midi_msg_data2;
  57. extern uint8_t usb_midi_msg_sysex[USB_MIDI_SYSEX_MAX];
  58. extern uint16_t usb_midi_msg_sysex_len;
  59. extern void (*usb_midi_handleNoteOff)(uint8_t ch, uint8_t note, uint8_t vel);
  60. extern void (*usb_midi_handleNoteOn)(uint8_t ch, uint8_t note, uint8_t vel);
  61. extern void (*usb_midi_handleVelocityChange)(uint8_t ch, uint8_t note, uint8_t vel);
  62. extern void (*usb_midi_handleControlChange)(uint8_t ch, uint8_t control, uint8_t value);
  63. extern void (*usb_midi_handleProgramChange)(uint8_t ch, uint8_t program);
  64. extern void (*usb_midi_handleAfterTouch)(uint8_t ch, uint8_t pressure);
  65. extern void (*usb_midi_handlePitchChange)(uint8_t ch, int pitch);
  66. extern void (*usb_midi_handleSysExPartial)(const uint8_t *data, uint16_t length, uint8_t complete);
  67. extern void (*usb_midi_handleSysExComplete)(uint8_t *data, unsigned int size);
  68. extern void (*usb_midi_handleTimeCodeQuarterFrame)(uint8_t data);
  69. extern void (*usb_midi_handleSongPosition)(uint16_t beats);
  70. extern void (*usb_midi_handleSongSelect)(uint8_t songnumber);
  71. extern void (*usb_midi_handleTuneRequest)(void);
  72. extern void (*usb_midi_handleClock)(void);
  73. extern void (*usb_midi_handleStart)(void);
  74. extern void (*usb_midi_handleContinue)(void);
  75. extern void (*usb_midi_handleStop)(void);
  76. extern void (*usb_midi_handleActiveSensing)(void);
  77. extern void (*usb_midi_handleSystemReset)(void);
  78. extern void (*usb_midi_handleRealTimeSystem)(uint8_t rtb);
  79. #ifdef __cplusplus
  80. }
  81. #endif
  82. // To test receiving on Linux, run "aseqdump -l" to list sequencer devices.
  83. //
  84. // Port Client name Port name
  85. // 0:0 System Timer
  86. // 0:1 System Announce
  87. // 14:0 Midi Through Midi Through Port-0
  88. // 24:0 Teensy MIDI Teensy MIDI MIDI 1
  89. // 28:0 AKM320 AKM320 MIDI 1
  90. //
  91. // Then run "aseqdump -p 24:0" to view the MIDI messages.
  92. //
  93. // Waiting for data. Press Ctrl+C to end.
  94. // Source Event Ch Data
  95. // 24:0 Note on 0, note 61, velocity 99
  96. // 24:0 Note off 0, note 61, velocity 0
  97. // 24:0 Note on 0, note 62, velocity 99
  98. // 24:0 Note off 0, note 62, velocity 0
  99. // 24:0 Note on 0, note 64, velocity 99
  100. // 24:0 Note off 0, note 64, velocity 0
  101. //
  102. // Quick-dirty way to transmit MIDI sysex:
  103. // echo -n -e '\xF0abcd\xF7' > /dev/midi2
  104. // C++ interface
  105. #ifdef __cplusplus
  106. class usb_midi_class
  107. {
  108. public:
  109. // Message type names for compatibility with Arduino MIDI library 4.3.1
  110. enum MidiType {
  111. InvalidType = 0x00, // For notifying errors
  112. NoteOff = 0x80, // Note Off
  113. NoteOn = 0x90, // Note On
  114. AfterTouchPoly = 0xA0, // Polyphonic AfterTouch
  115. ControlChange = 0xB0, // Control Change / Channel Mode
  116. ProgramChange = 0xC0, // Program Change
  117. AfterTouchChannel = 0xD0, // Channel (monophonic) AfterTouch
  118. PitchBend = 0xE0, // Pitch Bend
  119. SystemExclusive = 0xF0, // System Exclusive
  120. TimeCodeQuarterFrame = 0xF1, // System Common - MIDI Time Code Quarter Frame
  121. SongPosition = 0xF2, // System Common - Song Position Pointer
  122. SongSelect = 0xF3, // System Common - Song Select
  123. TuneRequest = 0xF6, // System Common - Tune Request
  124. Clock = 0xF8, // System Real Time - Timing Clock
  125. Start = 0xFA, // System Real Time - Start
  126. Continue = 0xFB, // System Real Time - Continue
  127. Stop = 0xFC, // System Real Time - Stop
  128. ActiveSensing = 0xFE, // System Real Time - Active Sensing
  129. SystemReset = 0xFF, // System Real Time - System Reset
  130. };
  131. void begin(void) { }
  132. void end(void) { }
  133. void sendNoteOff(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  134. send(0x80, note, velocity, channel, cable);
  135. }
  136. void sendNoteOn(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  137. send(0x90, note, velocity, channel, cable);
  138. }
  139. void sendPolyPressure(uint8_t note, uint8_t pressure, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  140. send(0xA0, note, pressure, channel, cable);
  141. }
  142. void sendAfterTouchPoly(uint8_t note, uint8_t pressure, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  143. send(0xA0, note, pressure, channel, cable);
  144. }
  145. void sendControlChange(uint8_t control, uint8_t value, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  146. send(0xB0, control, value, channel, cable);
  147. }
  148. void sendProgramChange(uint8_t program, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  149. send(0xC0, program, 0, channel, cable);
  150. }
  151. void sendAfterTouch(uint8_t pressure, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  152. send(0xD0, pressure, 0, channel, cable);
  153. }
  154. void sendPitchBend(int value, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  155. if (value < -8192) {
  156. value = -8192;
  157. } else if (value > 8191) {
  158. value = 8191;
  159. }
  160. value += 8192;
  161. send(0xE0, value, value >> 7, channel, cable);
  162. }
  163. void sendSysEx(uint32_t length, const uint8_t *data, bool hasTerm=false, uint8_t cable=0) __attribute__((always_inline)) {
  164. if (cable >= MIDI_NUM_CABLES) return;
  165. if (hasTerm) {
  166. usb_midi_send_sysex_buffer_has_term(data, length, cable);
  167. } else {
  168. usb_midi_send_sysex_add_term_bytes(data, length, cable);
  169. }
  170. }
  171. void sendRealTime(uint8_t type, uint8_t cable=0) __attribute__((always_inline)) __attribute__((always_inline)) {
  172. switch (type) {
  173. case 0xF8: // Clock
  174. case 0xFA: // Start
  175. case 0xFB: // Continue
  176. case 0xFC: // Stop
  177. case 0xFE: // ActiveSensing
  178. case 0xFF: // SystemReset
  179. send(type, 0, 0, 0, cable);
  180. break;
  181. default: // Invalid Real Time marker
  182. break;
  183. }
  184. }
  185. void sendTimeCodeQuarterFrame(uint8_t type, uint8_t value, uint8_t cable=0) __attribute__((always_inline)) __attribute__((always_inline)) {
  186. send(0xF1, ((type & 0x07) << 4) | (value & 0x0F), 0, 0, cable);
  187. }
  188. void sendSongPosition(uint16_t beats, uint8_t cable=0) __attribute__((always_inline)) {
  189. send(0xF2, beats, beats >> 7, 0, cable);
  190. }
  191. void sendSongSelect(uint8_t song, uint8_t cable=0) __attribute__((always_inline)) {
  192. send(0xF3, song, 0, 0, cable);
  193. }
  194. void sendTuneRequest(uint8_t cable=0) __attribute__((always_inline)) {
  195. send(0xF6, 0, 0, 0, cable);
  196. }
  197. void beginRpn(uint16_t number, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  198. sendControlChange(101, number >> 7, channel, cable);
  199. sendControlChange(100, number, channel, cable);
  200. }
  201. void sendRpnValue(uint16_t value, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  202. sendControlChange(6, value >> 7, channel, cable);
  203. sendControlChange(38, value, channel, cable);
  204. }
  205. void sendRpnIncrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  206. sendControlChange(96, amount, channel, cable);
  207. }
  208. void sendRpnDecrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  209. sendControlChange(97, amount, channel, cable);
  210. }
  211. void endRpn(uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  212. sendControlChange(101, 0x7F, channel, cable);
  213. sendControlChange(100, 0x7F, channel, cable);
  214. }
  215. void beginNrpn(uint16_t number, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  216. sendControlChange(99, number >> 7, channel, cable);
  217. sendControlChange(98, number, channel, cable);
  218. }
  219. void sendNrpnValue(uint16_t value, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  220. sendControlChange(6, value >> 7, channel, cable);
  221. sendControlChange(38, value, channel, cable);
  222. }
  223. void sendNrpnIncrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  224. sendControlChange(96, amount, channel, cable);
  225. }
  226. void sendNrpnDecrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  227. sendControlChange(97, amount, channel, cable);
  228. }
  229. void endNrpn(uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  230. sendControlChange(99, 0x7F, channel, cable);
  231. sendControlChange(98, 0x7F, channel, cable);
  232. }
  233. void send(uint8_t type, uint8_t data1, uint8_t data2, uint8_t channel, uint8_t cable) __attribute__((always_inline)) {
  234. if (cable >= MIDI_NUM_CABLES) return;
  235. if (type < 0xF0) {
  236. if (type < 0x80) return;
  237. type &= 0xF0;
  238. usb_midi_write_packed((type << 8) | (type >> 4) | ((cable & 0x0F) << 4)
  239. | (((channel - 1) & 0x0F) << 8) | ((data1 & 0x7F) << 16)
  240. | ((data2 & 0x7F) << 24));
  241. } else if (type >= 0xF8 || type == 0xF6) {
  242. usb_midi_write_packed((type << 8) | 0x0F | ((cable & 0x0F) << 4));
  243. } else if (type == 0xF1 || type == 0xF3) {
  244. usb_midi_write_packed((type << 8) | 0x02 | ((cable & 0x0F) << 4)
  245. | ((data1 & 0x7F) << 16));
  246. } else if (type == 0xF2) {
  247. usb_midi_write_packed((type << 8) | 0x03 | ((cable & 0x0F) << 4)
  248. | ((data1 & 0x7F) << 16) | ((data2 & 0x7F) << 24));
  249. }
  250. }
  251. void send_now(void) __attribute__((always_inline)) {
  252. usb_midi_flush_output();
  253. }
  254. uint8_t analog2velocity(uint16_t val, uint8_t range);
  255. bool read(uint8_t channel=0) __attribute__((always_inline)) {
  256. return usb_midi_read(channel);
  257. }
  258. uint8_t getType(void) __attribute__((always_inline)) {
  259. return usb_midi_msg_type;
  260. }
  261. uint8_t getCable(void) __attribute__((always_inline)) {
  262. return usb_midi_msg_cable;
  263. }
  264. uint8_t getChannel(void) __attribute__((always_inline)) {
  265. return usb_midi_msg_channel;
  266. }
  267. uint8_t getData1(void) __attribute__((always_inline)) {
  268. return usb_midi_msg_data1;
  269. }
  270. uint8_t getData2(void) __attribute__((always_inline)) {
  271. return usb_midi_msg_data2;
  272. }
  273. uint8_t * getSysExArray(void) __attribute__((always_inline)) {
  274. return usb_midi_msg_sysex;
  275. }
  276. uint16_t getSysExArrayLength(void) __attribute__((always_inline)) {
  277. return usb_midi_msg_data2 << 8 | usb_midi_msg_data1;
  278. }
  279. void setHandleNoteOff(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
  280. // type: 0x80 NoteOff
  281. usb_midi_handleNoteOff = fptr;
  282. }
  283. void setHandleNoteOn(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
  284. // type: 0x90 NoteOn
  285. usb_midi_handleNoteOn = fptr;
  286. }
  287. void setHandleVelocityChange(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
  288. // type: 0xA0 AfterTouchPoly
  289. usb_midi_handleVelocityChange = fptr;
  290. }
  291. void setHandleAfterTouchPoly(void (*fptr)(uint8_t channel, uint8_t note, uint8_t pressure)) {
  292. // type: 0xA0 AfterTouchPoly
  293. usb_midi_handleVelocityChange = fptr;
  294. }
  295. void setHandleControlChange(void (*fptr)(uint8_t channel, uint8_t control, uint8_t value)) {
  296. // type: 0xB0 ControlChange
  297. usb_midi_handleControlChange = fptr;
  298. }
  299. void setHandleProgramChange(void (*fptr)(uint8_t channel, uint8_t program)) {
  300. // type: 0xC0 ProgramChange
  301. usb_midi_handleProgramChange = fptr;
  302. }
  303. void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {
  304. // type: 0xD0 AfterTouchChannel
  305. usb_midi_handleAfterTouch = fptr;
  306. }
  307. void setHandleAfterTouchChannel(void (*fptr)(uint8_t channel, uint8_t pressure)) {
  308. // type: 0xD0 AfterTouchChannel
  309. usb_midi_handleAfterTouch = fptr;
  310. }
  311. void setHandlePitchChange(void (*fptr)(uint8_t channel, int pitch)) {
  312. // type: 0xE0 PitchBend
  313. usb_midi_handlePitchChange = fptr;
  314. }
  315. void setHandleSysEx(void (*fptr)(const uint8_t *data, uint16_t length, bool complete)) {
  316. // type: 0xF0 SystemExclusive - multiple calls for message bigger than buffer
  317. usb_midi_handleSysExPartial = (void (*)(const uint8_t *, uint16_t, uint8_t))fptr;
  318. }
  319. void setHandleSystemExclusive(void (*fptr)(const uint8_t *data, uint16_t length, bool complete)) {
  320. // type: 0xF0 SystemExclusive - multiple calls for message bigger than buffer
  321. usb_midi_handleSysExPartial = (void (*)(const uint8_t *, uint16_t, uint8_t))fptr;
  322. }
  323. void setHandleSystemExclusive(void (*fptr)(uint8_t *data, unsigned int size)) {
  324. // type: 0xF0 SystemExclusive - single call, message larger than buffer is truncated
  325. usb_midi_handleSysExComplete = fptr;
  326. }
  327. void setHandleTimeCodeQuarterFrame(void (*fptr)(uint8_t data)) {
  328. // type: 0xF1 TimeCodeQuarterFrame
  329. usb_midi_handleTimeCodeQuarterFrame = fptr;
  330. }
  331. void setHandleSongPosition(void (*fptr)(uint16_t beats)) {
  332. // type: 0xF2 SongPosition
  333. usb_midi_handleSongPosition = fptr;
  334. }
  335. void setHandleSongSelect(void (*fptr)(uint8_t songnumber)) {
  336. // type: 0xF3 SongSelect
  337. usb_midi_handleSongSelect = fptr;
  338. }
  339. void setHandleTuneRequest(void (*fptr)(void)) {
  340. // type: 0xF6 TuneRequest
  341. usb_midi_handleTuneRequest = fptr;
  342. }
  343. void setHandleClock(void (*fptr)(void)) {
  344. // type: 0xF8 Clock
  345. usb_midi_handleClock = fptr;
  346. }
  347. void setHandleStart(void (*fptr)(void)) {
  348. // type: 0xFA Start
  349. usb_midi_handleStart = fptr;
  350. }
  351. void setHandleContinue(void (*fptr)(void)) {
  352. // type: 0xFB Continue
  353. usb_midi_handleContinue = fptr;
  354. }
  355. void setHandleStop(void (*fptr)(void)) {
  356. // type: 0xFC Stop
  357. usb_midi_handleStop = fptr;
  358. }
  359. void setHandleActiveSensing(void (*fptr)(void)) {
  360. // type: 0xFE ActiveSensing
  361. usb_midi_handleActiveSensing = fptr;
  362. }
  363. void setHandleSystemReset(void (*fptr)(void)) {
  364. // type: 0xFF SystemReset
  365. usb_midi_handleSystemReset = fptr;
  366. }
  367. void setHandleRealTimeSystem(void (*fptr)(uint8_t realtimebyte)) {
  368. // type: 0xF8-0xFF - if more specific handler not configured
  369. usb_midi_handleRealTimeSystem = fptr;
  370. };
  371. };
  372. extern usb_midi_class usbMIDI;
  373. #endif // __cplusplus
  374. #endif // MIDI_INTERFACE
  375. #endif // USBmidi_h_