Teensy 4.1 core updated for C++20
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

451 行
12KB

  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. #include "usb_dev.h"
  31. #include "usb_audio.h"
  32. #include "HardwareSerial.h"
  33. #include <string.h> // for memcpy()
  34. #ifdef AUDIO_INTERFACE // defined by usb_dev.h -> usb_desc.h
  35. #if F_CPU >= 20000000
  36. // Uncomment this to work around a limitation in Macintosh adaptive rates
  37. // This is not a perfect solution. Details here:
  38. // https://forum.pjrc.com/threads/34855-Distorted-audio-when-using-USB-input-on-Teensy-3-1
  39. //#define MACOSX_ADAPTIVE_LIMIT
  40. bool AudioInputUSB::update_responsibility;
  41. audio_block_t * AudioInputUSB::incoming_left;
  42. audio_block_t * AudioInputUSB::incoming_right;
  43. audio_block_t * AudioInputUSB::ready_left;
  44. audio_block_t * AudioInputUSB::ready_right;
  45. uint16_t AudioInputUSB::incoming_count;
  46. uint8_t AudioInputUSB::receive_flag;
  47. struct usb_audio_features_struct AudioInputUSB::features = {0,0,FEATURE_MAX_VOLUME/2};
  48. #define DMABUFATTR __attribute__ ((section(".dmabuffers"), aligned (4)))
  49. uint16_t usb_audio_receive_buffer[AUDIO_RX_SIZE/2] DMABUFATTR;
  50. uint32_t usb_audio_sync_feedback DMABUFATTR;
  51. uint8_t usb_audio_receive_setting=0;
  52. static uint32_t feedback_accumulator = 185042824;
  53. void AudioInputUSB::begin(void)
  54. {
  55. incoming_count = 0;
  56. incoming_left = NULL;
  57. incoming_right = NULL;
  58. ready_left = NULL;
  59. ready_right = NULL;
  60. receive_flag = 0;
  61. // update_responsibility = update_setup();
  62. // TODO: update responsibility is tough, partly because the USB
  63. // interrupts aren't sychronous to the audio library block size,
  64. // but also because the PC may stop transmitting data, which
  65. // means we no longer get receive callbacks from usb_dev.
  66. update_responsibility = false;
  67. usb_audio_sync_feedback = feedback_accumulator >> 8;
  68. }
  69. static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
  70. {
  71. uint32_t *target = (uint32_t*) src + len;
  72. while ((src < target) && (((uintptr_t) left & 0x02) != 0)) {
  73. uint32_t n = *src++;
  74. *left++ = n & 0xFFFF;
  75. *right++ = n >> 16;
  76. }
  77. while ((src < target - 2)) {
  78. uint32_t n1 = *src++;
  79. uint32_t n = *src++;
  80. *(uint32_t *)left = (n1 & 0xFFFF) | ((n & 0xFFFF) << 16);
  81. left+=2;
  82. *(uint32_t *)right = (n1 >> 16) | ((n & 0xFFFF0000)) ;
  83. right+=2;
  84. }
  85. while ((src < target)) {
  86. uint32_t n = *src++;
  87. *left++ = n & 0xFFFF;
  88. *right++ = n >> 16;
  89. }
  90. }
  91. // Called from the USB interrupt when an isochronous packet arrives
  92. // we must completely remove it from the receive buffer before returning
  93. //
  94. void usb_audio_receive_callback(unsigned int len)
  95. {
  96. unsigned int count, avail;
  97. audio_block_t *left, *right;
  98. const uint32_t *data;
  99. AudioInputUSB::receive_flag = 1;
  100. len >>= 2; // 1 sample = 4 bytes: 2 left, 2 right
  101. data = (const uint32_t *)usb_audio_receive_buffer;
  102. count = AudioInputUSB::incoming_count;
  103. left = AudioInputUSB::incoming_left;
  104. right = AudioInputUSB::incoming_right;
  105. if (left == NULL) {
  106. left = AudioStream::allocate();
  107. if (left == NULL) return;
  108. AudioInputUSB::incoming_left = left;
  109. }
  110. if (right == NULL) {
  111. right = AudioStream::allocate();
  112. if (right == NULL) return;
  113. AudioInputUSB::incoming_right = right;
  114. }
  115. while (len > 0) {
  116. avail = AUDIO_BLOCK_SAMPLES - count;
  117. if (len < avail) {
  118. copy_to_buffers(data, left->data + count, right->data + count, len);
  119. AudioInputUSB::incoming_count = count + len;
  120. return;
  121. } else if (avail > 0) {
  122. copy_to_buffers(data, left->data + count, right->data + count, avail);
  123. data += avail;
  124. len -= avail;
  125. if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) {
  126. // buffer overrun, PC sending too fast
  127. AudioInputUSB::incoming_count = count + avail;
  128. //if (len > 0) {
  129. //serial_print("!");
  130. //serial_phex(len);
  131. //}
  132. return;
  133. }
  134. send:
  135. AudioInputUSB::ready_left = left;
  136. AudioInputUSB::ready_right = right;
  137. //if (AudioInputUSB::update_responsibility) AudioStream::update_all();
  138. left = AudioStream::allocate();
  139. if (left == NULL) {
  140. AudioInputUSB::incoming_left = NULL;
  141. AudioInputUSB::incoming_right = NULL;
  142. AudioInputUSB::incoming_count = 0;
  143. return;
  144. }
  145. right = AudioStream::allocate();
  146. if (right == NULL) {
  147. AudioStream::release(left);
  148. AudioInputUSB::incoming_left = NULL;
  149. AudioInputUSB::incoming_right = NULL;
  150. AudioInputUSB::incoming_count = 0;
  151. return;
  152. }
  153. AudioInputUSB::incoming_left = left;
  154. AudioInputUSB::incoming_right = right;
  155. count = 0;
  156. } else {
  157. if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) return;
  158. goto send; // recover from buffer overrun
  159. }
  160. }
  161. AudioInputUSB::incoming_count = count;
  162. }
  163. void AudioInputUSB::update(void)
  164. {
  165. audio_block_t *left, *right;
  166. __disable_irq();
  167. left = ready_left;
  168. ready_left = NULL;
  169. right = ready_right;
  170. ready_right = NULL;
  171. uint16_t c = incoming_count;
  172. uint8_t f = receive_flag;
  173. receive_flag = 0;
  174. __enable_irq();
  175. if (f) {
  176. int diff = AUDIO_BLOCK_SAMPLES/2 - (int)c;
  177. feedback_accumulator += diff / 3;
  178. uint32_t feedback = (feedback_accumulator >> 8) + diff * 100;
  179. #ifdef MACOSX_ADAPTIVE_LIMIT
  180. if (feedback > 722698) feedback = 722698;
  181. #endif
  182. usb_audio_sync_feedback = feedback;
  183. //if (diff > 0) {
  184. //serial_print(".");
  185. //} else if (diff < 0) {
  186. //serial_print("^");
  187. //}
  188. }
  189. //serial_phex(c);
  190. //serial_print(".");
  191. if (!left || !right) {
  192. //serial_print("#"); // buffer underrun - PC sending too slow
  193. //if (f) feedback_accumulator += 10 << 8;
  194. }
  195. if (left) {
  196. transmit(left, 0);
  197. release(left);
  198. }
  199. if (right) {
  200. transmit(right, 1);
  201. release(right);
  202. }
  203. }
  204. bool AudioOutputUSB::update_responsibility;
  205. audio_block_t * AudioOutputUSB::left_1st;
  206. audio_block_t * AudioOutputUSB::left_2nd;
  207. audio_block_t * AudioOutputUSB::right_1st;
  208. audio_block_t * AudioOutputUSB::right_2nd;
  209. uint16_t AudioOutputUSB::offset_1st;
  210. uint16_t usb_audio_transmit_buffer[AUDIO_TX_SIZE/2] DMABUFATTR;
  211. uint8_t usb_audio_transmit_setting=0;
  212. void AudioOutputUSB::begin(void)
  213. {
  214. update_responsibility = false;
  215. left_1st = NULL;
  216. right_1st = NULL;
  217. }
  218. static void copy_from_buffers(uint32_t *dst, int16_t *left, int16_t *right, unsigned int len)
  219. {
  220. // TODO: optimize...
  221. while (len > 0) {
  222. *dst++ = (*right++ << 16) | (*left++ & 0xFFFF);
  223. len--;
  224. }
  225. }
  226. void AudioOutputUSB::update(void)
  227. {
  228. audio_block_t *left, *right;
  229. // TODO: we shouldn't be writing to these......
  230. //left = receiveReadOnly(0); // input 0 = left channel
  231. //right = receiveReadOnly(1); // input 1 = right channel
  232. left = receiveWritable(0); // input 0 = left channel
  233. right = receiveWritable(1); // input 1 = right channel
  234. if (usb_audio_transmit_setting == 0) {
  235. if (left) release(left);
  236. if (right) release(right);
  237. if (left_1st) { release(left_1st); left_1st = NULL; }
  238. if (left_2nd) { release(left_2nd); left_2nd = NULL; }
  239. if (right_1st) { release(right_1st); right_1st = NULL; }
  240. if (right_2nd) { release(right_2nd); right_2nd = NULL; }
  241. offset_1st = 0;
  242. return;
  243. }
  244. if (left == NULL) {
  245. left = allocate();
  246. if (left == NULL) {
  247. if (right) release(right);
  248. return;
  249. }
  250. memset(left->data, 0, sizeof(left->data));
  251. }
  252. if (right == NULL) {
  253. right = allocate();
  254. if (right == NULL) {
  255. release(left);
  256. return;
  257. }
  258. memset(right->data, 0, sizeof(right->data));
  259. }
  260. __disable_irq();
  261. if (left_1st == NULL) {
  262. left_1st = left;
  263. right_1st = right;
  264. offset_1st = 0;
  265. } else if (left_2nd == NULL) {
  266. left_2nd = left;
  267. right_2nd = right;
  268. } else {
  269. // buffer overrun - PC is consuming too slowly
  270. audio_block_t *discard1 = left_1st;
  271. left_1st = left_2nd;
  272. left_2nd = left;
  273. audio_block_t *discard2 = right_1st;
  274. right_1st = right_2nd;
  275. right_2nd = right;
  276. offset_1st = 0; // TODO: discard part of this data?
  277. //serial_print("*");
  278. release(discard1);
  279. release(discard2);
  280. }
  281. __enable_irq();
  282. }
  283. // Called from the USB interrupt when ready to transmit another
  284. // isochronous packet. If we place data into the transmit buffer,
  285. // the return is the number of bytes. Otherwise, return 0 means
  286. // no data to transmit
  287. unsigned int usb_audio_transmit_callback(void)
  288. {
  289. static uint32_t count=5;
  290. uint32_t avail, num, target, offset, len=0;
  291. audio_block_t *left, *right;
  292. if (++count < 9) { // TODO: dynamic adjust to match USB rate
  293. target = 44;
  294. } else {
  295. count = 0;
  296. target = 45;
  297. }
  298. while (len < target) {
  299. num = target - len;
  300. left = AudioOutputUSB::left_1st;
  301. if (left == NULL) {
  302. // buffer underrun - PC is consuming too quickly
  303. memset(usb_audio_transmit_buffer + len, 0, num * 4);
  304. //serial_print("%");
  305. break;
  306. }
  307. right = AudioOutputUSB::right_1st;
  308. offset = AudioOutputUSB::offset_1st;
  309. avail = AUDIO_BLOCK_SAMPLES - offset;
  310. if (num > avail) num = avail;
  311. copy_from_buffers((uint32_t *)usb_audio_transmit_buffer + len,
  312. left->data + offset, right->data + offset, num);
  313. len += num;
  314. offset += num;
  315. if (offset >= AUDIO_BLOCK_SAMPLES) {
  316. AudioStream::release(left);
  317. AudioStream::release(right);
  318. AudioOutputUSB::left_1st = AudioOutputUSB::left_2nd;
  319. AudioOutputUSB::left_2nd = NULL;
  320. AudioOutputUSB::right_1st = AudioOutputUSB::right_2nd;
  321. AudioOutputUSB::right_2nd = NULL;
  322. AudioOutputUSB::offset_1st = 0;
  323. } else {
  324. AudioOutputUSB::offset_1st = offset;
  325. }
  326. }
  327. return target * 4;
  328. }
  329. struct setup_struct {
  330. union {
  331. struct {
  332. uint8_t bmRequestType;
  333. uint8_t bRequest;
  334. union {
  335. struct {
  336. uint8_t bChannel; // 0=main, 1=left, 2=right
  337. uint8_t bCS; // Control Selector
  338. };
  339. uint16_t wValue;
  340. };
  341. union {
  342. struct {
  343. uint8_t bIfEp; // type of entity
  344. uint8_t bEntityId; // UnitID, TerminalID, etc.
  345. };
  346. uint16_t wIndex;
  347. };
  348. uint16_t wLength;
  349. };
  350. };
  351. };
  352. int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen)
  353. {
  354. struct setup_struct setup = *((struct setup_struct *)stp);
  355. if (setup.bmRequestType==0xA1) { // should check bRequest, bChannel, and UnitID
  356. if (setup.bCS==0x01) { // mute
  357. data[0] = AudioInputUSB::features.mute; // 1=mute, 0=unmute
  358. *datalen = 1;
  359. return 1;
  360. }
  361. else if (setup.bCS==0x02) { // volume
  362. if (setup.bRequest==0x81) { // GET_CURR
  363. data[0] = AudioInputUSB::features.volume & 0xFF;
  364. data[1] = (AudioInputUSB::features.volume>>8) & 0xFF;
  365. }
  366. else if (setup.bRequest==0x82) { // GET_MIN
  367. //serial_print("vol get_min\n");
  368. data[0] = 0; // min level is 0
  369. data[1] = 0;
  370. }
  371. else if (setup.bRequest==0x83) { // GET_MAX
  372. data[0] = FEATURE_MAX_VOLUME & 0xFF; // max level, for range of 0 to MAX
  373. data[1] = (FEATURE_MAX_VOLUME>>8) & 0x0F;
  374. }
  375. else if (setup.bRequest==0x84) { // GET_RES
  376. data[0] = 1; // increment vol by by 1
  377. data[1] = 0;
  378. }
  379. else { // pass over SET_MEM, etc.
  380. return 0;
  381. }
  382. *datalen = 2;
  383. return 1;
  384. }
  385. }
  386. return 0;
  387. }
  388. int usb_audio_set_feature(void *stp, uint8_t *buf)
  389. {
  390. struct setup_struct setup = *((struct setup_struct *)stp);
  391. if (setup.bmRequestType==0x21) { // should check bRequest, bChannel and UnitID
  392. if (setup.bCS==0x01) { // mute
  393. if (setup.bRequest==0x01) { // SET_CUR
  394. AudioInputUSB::features.mute = buf[0]; // 1=mute,0=unmute
  395. AudioInputUSB::features.change = 1;
  396. return 1;
  397. }
  398. }
  399. else if (setup.bCS==0x02) { // volume
  400. if (setup.bRequest==0x01) { // SET_CUR
  401. AudioInputUSB::features.volume = buf[0] + (buf[1]<<8);
  402. AudioInputUSB::features.change = 1;
  403. return 1;
  404. }
  405. }
  406. }
  407. return 0;
  408. }
  409. #endif // F_CPU
  410. #endif // AUDIO_INTERFACE