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.

usb_api.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. #ifndef USBserial_h_
  2. #define USBserial_h_
  3. #include <inttypes.h>
  4. #include "Stream.h"
  5. #define USB_MIDI_SYSEX_MAX 60 // maximum sysex length we can receive
  6. /*
  7. These were originally meant to allow programs written for
  8. Francois Best's MIDI library to be easily used with
  9. Teensy's usbMIDI which implements the same API. However,
  10. the MIDI library definitions have changed, so these names
  11. now conflict. They've never been documented (the PJRC web
  12. page documents usbMIDI.getType() in numbers) so they are
  13. now commented out so usbMIDI and the MIDI library can be
  14. used together without conflict.
  15. #define NoteOff 0
  16. #define NoteOn 1
  17. #define AfterTouchPoly 2
  18. #define ControlChange 3
  19. #define ProgramChange 4
  20. #define AfterTouchChannel 5
  21. #define PitchBend 6
  22. #define SystemExclusive 7
  23. */
  24. class usb_midi_class
  25. {
  26. public:
  27. // Message type names for compatibility with Arduino MIDI library 4.3.1
  28. enum MidiType {
  29. InvalidType = 0x00, // For notifying errors
  30. NoteOff = 0x80, // Note Off
  31. NoteOn = 0x90, // Note On
  32. AfterTouchPoly = 0xA0, // Polyphonic AfterTouch
  33. ControlChange = 0xB0, // Control Change / Channel Mode
  34. ProgramChange = 0xC0, // Program Change
  35. AfterTouchChannel = 0xD0, // Channel (monophonic) AfterTouch
  36. PitchBend = 0xE0, // Pitch Bend
  37. SystemExclusive = 0xF0, // System Exclusive
  38. TimeCodeQuarterFrame = 0xF1, // System Common - MIDI Time Code Quarter Frame
  39. SongPosition = 0xF2, // System Common - Song Position Pointer
  40. SongSelect = 0xF3, // System Common - Song Select
  41. TuneRequest = 0xF6, // System Common - Tune Request
  42. Clock = 0xF8, // System Real Time - Timing Clock
  43. Start = 0xFA, // System Real Time - Start
  44. Continue = 0xFB, // System Real Time - Continue
  45. Stop = 0xFC, // System Real Time - Stop
  46. ActiveSensing = 0xFE, // System Real Time - Active Sensing
  47. SystemReset = 0xFF, // System Real Time - System Reset
  48. };
  49. void begin(void) { }
  50. void end(void) { }
  51. void sendNoteOff(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) {
  52. send(0x80, note, velocity, channel, cable);
  53. }
  54. void sendNoteOn(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) {
  55. send(0x90, note, velocity, channel, cable);
  56. }
  57. void sendPolyPressure(uint8_t note, uint8_t pressure, uint8_t channel, uint8_t cable=0) {
  58. send(0xA0, note, pressure, channel, cable);
  59. }
  60. void sendAfterTouch(uint8_t note, uint8_t pressure, uint8_t channel, uint8_t cable=0) {
  61. send(0xA0, note, pressure, channel, cable);
  62. }
  63. void sendControlChange(uint8_t control, uint8_t value, uint8_t channel, uint8_t cable=0) {
  64. send(0xB0, control, value, channel, cable);
  65. }
  66. void sendProgramChange(uint8_t program, uint8_t channel, uint8_t cable=0) {
  67. send(0xC0, program, 0, channel, cable);
  68. }
  69. void sendAfterTouch(uint8_t pressure, uint8_t channel, uint8_t cable=0) {
  70. send(0xD0, pressure, 0, channel, cable);
  71. }
  72. void sendPitchBend(uint16_t value, uint8_t channel, uint8_t cable=0) {
  73. // MIDI 4.3 takes -8192 to +8191. We take 0 to 16383
  74. send(0xE0, value, value >> 7, channel, cable);
  75. }
  76. void sendSysEx(uint16_t length, const uint8_t *data, bool hasTerm=false, uint8_t cable=0) {
  77. if (cable > 0) return;
  78. if (hasTerm) {
  79. sendSysEx_BufferHasTerm(length, data);
  80. } else {
  81. sendSysEx_AddTermBytes(length, data);
  82. }
  83. }
  84. void sendRealTime(uint8_t type, uint8_t cable=0) __attribute__((always_inline)) __attribute__((always_inline)) {
  85. switch (type) {
  86. case 0xF8: // Clock
  87. case 0xFA: // Start
  88. case 0xFB: // Continue
  89. case 0xFC: // Stop
  90. case 0xFE: // ActiveSensing
  91. case 0xFF: // SystemReset
  92. send(type, 0, 0, 0, cable);
  93. break;
  94. default: // Invalid Real Time marker
  95. break;
  96. }
  97. }
  98. void sendTimeCodeQuarterFrame(uint8_t type, uint8_t value, uint8_t cable=0) __attribute__((always_inline)) __attribute__((always_inline)) {
  99. send(0xF1, ((type & 0x07) << 4) | (value & 0x0F), 0, 0, cable);
  100. }
  101. void sendSongPosition(uint16_t beats, uint8_t cable=0) __attribute__((always_inline)) {
  102. send(0xF2, beats, beats >> 7, 0, cable);
  103. }
  104. void sendSongSelect(uint8_t song, uint8_t cable=0) __attribute__((always_inline)) {
  105. send(0xF3, song, 0, 0, cable);
  106. }
  107. void sendTuneRequest(uint8_t cable=0) __attribute__((always_inline)) {
  108. send(0xF6, 0, 0, 0, cable);
  109. }
  110. void beginRpn(uint16_t number, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  111. sendControlChange(101, number >> 7, channel, cable);
  112. sendControlChange(100, number, channel, cable);
  113. }
  114. void sendRpnValue(uint16_t value, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  115. sendControlChange(6, value >> 7, channel, cable);
  116. sendControlChange(38, value, channel, cable);
  117. }
  118. void sendRpnValue(uint8_t msb, uint8_t lsb, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  119. sendControlChange(6, msb, channel, cable);
  120. sendControlChange(38, lsb, channel, cable);
  121. }
  122. void sendRpnIncrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  123. sendControlChange(96, amount, channel, cable);
  124. }
  125. void sendRpnDecrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  126. sendControlChange(97, amount, channel, cable);
  127. }
  128. void endRpn(uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  129. sendControlChange(101, 0x7F, channel, cable);
  130. sendControlChange(100, 0x7F, channel, cable);
  131. }
  132. void beginNrpn(uint16_t number, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  133. sendControlChange(99, number >> 7, channel, cable);
  134. sendControlChange(98, number, channel, cable);
  135. }
  136. void sendNrpnValue(uint16_t value, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  137. sendControlChange(6, value >> 7, channel, cable);
  138. sendControlChange(38, value, channel, cable);
  139. }
  140. void sendNrpnValue(uint8_t msb, uint8_t lsb, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  141. sendControlChange(6, msb, channel, cable);
  142. sendControlChange(38, lsb, channel, cable);
  143. }
  144. void sendNrpnIncrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  145. sendControlChange(96, amount, channel, cable);
  146. }
  147. void sendNrpnDecrement(uint8_t amount, uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  148. sendControlChange(97, amount, channel, cable);
  149. }
  150. void endNrpn(uint8_t channel, uint8_t cable=0) __attribute__((always_inline)) {
  151. sendControlChange(99, 0x7F, channel, cable);
  152. sendControlChange(98, 0x7F, channel, cable);
  153. }
  154. void send(uint8_t type, uint8_t data1, uint8_t data2, uint8_t channel, uint8_t cable) __attribute__((always_inline)) {
  155. if (cable > 0) return;
  156. if (type < 0xF0) {
  157. if (type < 0x80) return;
  158. send_raw(type >> 4, (type & 0xF0) | ((channel - 1) & 0x0F),
  159. data1 & 0x7F, data2 & 0x7F);
  160. } else if (type >= 0xF8 || type == 0xF6) {
  161. send_raw(0x0F, type, 0, 0);
  162. } else if (type == 0xF1 || type == 0xF3) {
  163. send_raw(0x02, type, data1 & 0x7F, 0);
  164. } else if (type == 0xF2) {
  165. send_raw(0x03, type, data1 & 0x7F, data2 & 0x7F);
  166. }
  167. }
  168. void send_now(void);
  169. uint8_t analog2velocity(uint16_t val, uint8_t range);
  170. bool read(uint8_t channel=0);
  171. inline uint8_t getType(void) {
  172. return msg_type;
  173. }
  174. uint8_t getCable(void) {
  175. return 0;
  176. }
  177. uint8_t getChannel(void) {
  178. return msg_channel;
  179. }
  180. uint8_t getData1(void) {
  181. return msg_data1;
  182. }
  183. uint8_t getData2(void) {
  184. return msg_data2;
  185. }
  186. uint8_t * getSysExArray(void) {
  187. return msg_sysex;
  188. }
  189. void setHandleNoteOff(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
  190. // type: 0x80 NoteOff
  191. handleNoteOff = fptr;
  192. }
  193. void setHandleNoteOn(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
  194. // type: 0x90 NoteOn
  195. handleNoteOn = fptr;
  196. }
  197. void setHandleVelocityChange(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
  198. // type: 0xA0 AfterTouchPoly
  199. handleVelocityChange = fptr;
  200. }
  201. void setHandleAfterTouchPoly(void (*fptr)(uint8_t channel, uint8_t note, uint8_t pressure)) {
  202. // type: 0xA0 AfterTouchPoly
  203. handleVelocityChange = fptr;
  204. }
  205. void setHandleControlChange(void (*fptr)(uint8_t channel, uint8_t control, uint8_t value)) {
  206. // type: 0xB0 ControlChange
  207. handleControlChange = fptr;
  208. }
  209. void setHandleProgramChange(void (*fptr)(uint8_t channel, uint8_t program)) {
  210. // type: 0xC0 ProgramChange
  211. handleProgramChange = fptr;
  212. }
  213. void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {
  214. // type: 0xD0 AfterTouchChannel
  215. handleAfterTouch = fptr;
  216. }
  217. void setHandleAfterTouchChannel(void (*fptr)(uint8_t channel, uint8_t pressure)) {
  218. // type: 0xD0 AfterTouchChannel
  219. handleAfterTouch = fptr;
  220. }
  221. void setHandlePitchChange(void (*fptr)(uint8_t channel, int pitch)) {
  222. // type: 0xE0 PitchBend
  223. handlePitchChange = fptr;
  224. }
  225. void setHandleSysEx(void (*fptr)(const uint8_t *data, uint16_t length, bool complete)) {
  226. // type: 0xF0 SystemExclusive - multiple calls for message bigger than buffer
  227. handleSysExPartial = (void (*)(const uint8_t *, uint16_t, uint8_t))fptr;
  228. }
  229. void setHandleSystemExclusive(void (*fptr)(const uint8_t *data, uint16_t length, bool complete)) {
  230. // type: 0xF0 SystemExclusive - multiple calls for message bigger than buffer
  231. handleSysExPartial = (void (*)(const uint8_t *, uint16_t, uint8_t))fptr;
  232. }
  233. void setHandleSystemExclusive(void (*fptr)(uint8_t *data, unsigned int size)) {
  234. // type: 0xF0 SystemExclusive - single call, message larger than buffer is truncated
  235. handleSysExComplete = fptr;
  236. }
  237. void setHandleTimeCodeQuarterFrame(void (*fptr)(uint8_t data)) {
  238. // type: 0xF1 TimeCodeQuarterFrame
  239. handleTimeCodeQuarterFrame = fptr;
  240. }
  241. void setHandleSongPosition(void (*fptr)(uint16_t beats)) {
  242. // type: 0xF2 SongPosition
  243. handleSongPosition = fptr;
  244. }
  245. void setHandleSongSelect(void (*fptr)(uint8_t songnumber)) {
  246. // type: 0xF3 SongSelect
  247. handleSongSelect = fptr;
  248. }
  249. void setHandleTuneRequest(void (*fptr)(void)) {
  250. // type: 0xF6 TuneRequest
  251. handleTuneRequest = fptr;
  252. }
  253. void setHandleClock(void (*fptr)(void)) {
  254. // type: 0xF8 Clock
  255. handleClock = fptr;
  256. }
  257. void setHandleStart(void (*fptr)(void)) {
  258. // type: 0xFA Start
  259. handleStart = fptr;
  260. }
  261. void setHandleContinue(void (*fptr)(void)) {
  262. // type: 0xFB Continue
  263. handleContinue = fptr;
  264. }
  265. void setHandleStop(void (*fptr)(void)) {
  266. // type: 0xFC Stop
  267. handleStop = fptr;
  268. }
  269. void setHandleActiveSensing(void (*fptr)(void)) {
  270. // type: 0xFE ActiveSensing
  271. handleActiveSensing = fptr;
  272. }
  273. void setHandleSystemReset(void (*fptr)(void)) {
  274. // type: 0xFF SystemReset
  275. handleSystemReset = fptr;
  276. }
  277. void setHandleRealTimeSystem(void (*fptr)(uint8_t realtimebyte)) {
  278. // type: 0xF8-0xFF - if more specific handler not configured
  279. handleRealTimeSystem = fptr;
  280. }
  281. private:
  282. void send_raw(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3);
  283. void sendSysEx_BufferHasTerm(uint16_t length, const uint8_t *data);
  284. void sendSysEx_AddTermBytes(uint16_t length, const uint8_t *data);
  285. void read_sysex_byte(uint8_t b);
  286. uint8_t msg_channel;
  287. uint8_t msg_type;
  288. uint8_t msg_data1;
  289. uint8_t msg_data2;
  290. uint8_t msg_sysex[USB_MIDI_SYSEX_MAX];
  291. uint16_t msg_sysex_len;
  292. void (*handleNoteOff)(uint8_t ch, uint8_t note, uint8_t vel);
  293. void (*handleNoteOn)(uint8_t ch, uint8_t note, uint8_t vel);
  294. void (*handleVelocityChange)(uint8_t ch, uint8_t note, uint8_t vel);
  295. void (*handleControlChange)(uint8_t ch, uint8_t, uint8_t);
  296. void (*handleProgramChange)(uint8_t ch, uint8_t);
  297. void (*handleAfterTouch)(uint8_t ch, uint8_t);
  298. void (*handlePitchChange)(uint8_t ch, int pitch);
  299. void (*handleSysExPartial)(const uint8_t *data, uint16_t length, uint8_t complete);
  300. void (*handleSysExComplete)(uint8_t *data, unsigned int size);
  301. void (*handleTimeCodeQuarterFrame)(uint8_t data);
  302. void (*handleSongPosition)(uint16_t beats);
  303. void (*handleSongSelect)(uint8_t songnumber);
  304. void (*handleTuneRequest)(void);
  305. void (*handleClock)(void);
  306. void (*handleStart)(void);
  307. void (*handleContinue)(void);
  308. void (*handleStop)(void);
  309. void (*handleActiveSensing)(void);
  310. void (*handleSystemReset)(void);
  311. void (*handleRealTimeSystem)(uint8_t rtb);
  312. };
  313. extern usb_midi_class usbMIDI;
  314. class usb_serial_class : public Stream
  315. {
  316. public:
  317. // standard Arduino functions
  318. void begin(long);
  319. void end();
  320. virtual int available();
  321. virtual int read();
  322. virtual int peek();
  323. virtual void flush();
  324. #if ARDUINO >= 100
  325. virtual size_t write(uint8_t);
  326. #else
  327. virtual void write(uint8_t);
  328. #endif
  329. using Print::write;
  330. operator bool();
  331. // Teensy extensions
  332. void send_now(void);
  333. uint32_t baud(void);
  334. uint8_t stopbits(void);
  335. uint8_t paritytype(void);
  336. uint8_t numbits(void);
  337. uint8_t dtr(void);
  338. uint8_t rts(void);
  339. private:
  340. uint8_t readnext(void);
  341. };
  342. extern usb_serial_class Serial;
  343. #endif