Teensy 4.1 core updated for C++20
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

213 行
6.4KB

  1. /* Teensyduino Core Library
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2016 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_audio.h"
  31. #include "HardwareSerial.h"
  32. #include <string.h> // for memcpy()
  33. #ifdef AUDIO_INTERFACE // defined by usb_dev.h -> usb_desc.h
  34. #if F_CPU >= 20000000
  35. bool AudioInputUSB::update_responsibility;
  36. audio_block_t * AudioInputUSB::incoming_left;
  37. audio_block_t * AudioInputUSB::incoming_right;
  38. audio_block_t * AudioInputUSB::ready_left;
  39. audio_block_t * AudioInputUSB::ready_right;
  40. uint16_t AudioInputUSB::incoming_count;
  41. uint8_t AudioInputUSB::receive_flag;
  42. #define DMABUFATTR __attribute__ ((section(".dmabuffers"), aligned (4)))
  43. uint16_t usb_audio_receive_buffer[AUDIO_RX_SIZE/2] DMABUFATTR;
  44. uint16_t usb_audio_transmit_buffer[AUDIO_TX_SIZE/2] DMABUFATTR;
  45. uint32_t usb_audio_sync_feedback DMABUFATTR;
  46. static uint32_t feedback_accumulator = 722534 << 8;
  47. void AudioInputUSB::begin(void)
  48. {
  49. incoming_count = 0;
  50. incoming_left = NULL;
  51. incoming_right = NULL;
  52. ready_left = NULL;
  53. ready_right = NULL;
  54. receive_flag = 0;
  55. // update_responsibility = update_setup();
  56. // TODO: update responsibility is tough, partly because the USB
  57. // interrupts aren't sychronous to the audio library block size,
  58. // but also because the PC may stop transmitting data, which
  59. // means we no longer get receive callbacks from usb_dev.
  60. update_responsibility = false;
  61. //usb_audio_sync_feedback = 722824;
  62. //usb_audio_sync_feedback = 723700; // too fast?
  63. usb_audio_sync_feedback = 722534; // too slow
  64. }
  65. static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
  66. {
  67. // TODO: optimize...
  68. while (len > 0) {
  69. uint32_t n = *src++;
  70. *left++ = n & 0xFFFF;
  71. *right++ = n >> 16;
  72. len--;
  73. }
  74. }
  75. // Called from the USB interrupt when an isochronous packet arrives
  76. // we must completely remove it from the receive buffer before returning
  77. //
  78. void usb_audio_receive_callback(unsigned int len)
  79. {
  80. unsigned int count, avail;
  81. audio_block_t *left, *right;
  82. const uint32_t *data;
  83. AudioInputUSB::receive_flag = 1;
  84. len >>= 2; // 1 sample = 4 bytes: 2 left, 2 right
  85. data = (const uint32_t *)usb_audio_receive_buffer;
  86. count = AudioInputUSB::incoming_count;
  87. left = AudioInputUSB::incoming_left;
  88. right = AudioInputUSB::incoming_right;
  89. if (left == NULL) {
  90. left = AudioStream::allocate();
  91. if (left == NULL) return;
  92. AudioInputUSB::incoming_left = left;
  93. }
  94. if (right == NULL) {
  95. right = AudioStream::allocate();
  96. if (right == NULL) return;
  97. AudioInputUSB::incoming_right = right;
  98. }
  99. while (len > 0) {
  100. avail = AUDIO_BLOCK_SAMPLES - count;
  101. if (len < avail) {
  102. copy_to_buffers(data, left->data + count, right->data + count, len);
  103. AudioInputUSB::incoming_count = count + len;
  104. return;
  105. } else if (avail > 0) {
  106. copy_to_buffers(data, left->data + count, right->data + count, avail);
  107. data += avail;
  108. len -= avail;
  109. if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) {
  110. // buffer overrun, PC sending too fast
  111. AudioInputUSB::incoming_count = count + avail;
  112. //if (len > 0) {
  113. //serial_print("!");
  114. //serial_phex(len);
  115. //}
  116. return;
  117. }
  118. send:
  119. AudioInputUSB::ready_left = left;
  120. AudioInputUSB::ready_right = right;
  121. //if (AudioInputUSB::update_responsibility) AudioStream::update_all();
  122. left = AudioStream::allocate();
  123. if (left == NULL) {
  124. AudioInputUSB::incoming_left = NULL;
  125. AudioInputUSB::incoming_right = NULL;
  126. AudioInputUSB::incoming_count = 0;
  127. return;
  128. }
  129. right = AudioStream::allocate();
  130. if (right == NULL) {
  131. AudioStream::release(left);
  132. AudioInputUSB::incoming_left = NULL;
  133. AudioInputUSB::incoming_right = NULL;
  134. AudioInputUSB::incoming_count = 0;
  135. return;
  136. }
  137. AudioInputUSB::incoming_left = left;
  138. AudioInputUSB::incoming_right = right;
  139. count = 0;
  140. } else {
  141. if (AudioInputUSB::ready_left || AudioInputUSB::ready_right) return;
  142. goto send; // recover from buffer overrun
  143. }
  144. }
  145. AudioInputUSB::incoming_count = count;
  146. }
  147. void AudioInputUSB::update(void)
  148. {
  149. audio_block_t *left, *right;
  150. __disable_irq();
  151. left = ready_left;
  152. ready_left = NULL;
  153. right = ready_right;
  154. ready_right = NULL;
  155. uint16_t c = incoming_count;
  156. uint8_t f = receive_flag;
  157. receive_flag = 0;
  158. __enable_irq();
  159. if (f) {
  160. int diff = AUDIO_BLOCK_SAMPLES/2 - (int)c;
  161. feedback_accumulator += diff;
  162. // TODO: min/max sanity check for feedback_accumulator??
  163. usb_audio_sync_feedback = (feedback_accumulator >> 8) + diff * 3;
  164. //if (diff > 0) {
  165. //serial_print(".");
  166. //} else if (diff < 0) {
  167. //serial_print("^");
  168. //}
  169. }
  170. //serial_phex(c);
  171. //serial_print(".");
  172. if (!left || !right) {
  173. //serial_print("#"); // buffer underrun - PC sending too slow
  174. if (f) feedback_accumulator += 10 << 8;
  175. }
  176. if (left) {
  177. transmit(left, 0);
  178. release(left);
  179. }
  180. if (right) {
  181. transmit(right, 1);
  182. release(right);
  183. }
  184. }
  185. // Called from the USB interrupt when ready to transmit another
  186. // isochronous packet. If we place data into the transmit buffer,
  187. // the return is the number of bytes. Otherwise, return 0 means
  188. // no data to transmit
  189. unsigned int usb_audio_transmit_callback(void)
  190. {
  191. return 0;
  192. }
  193. #endif // F_CPU
  194. #endif // AUDIO_INTERFACE