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

200 行
6.0KB

  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::underflow_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. void AudioInputUSB::begin(void)
  47. {
  48. incoming_count = 0;
  49. incoming_left = NULL;
  50. incoming_right = NULL;
  51. ready_left = NULL;
  52. ready_right = NULL;
  53. underflow_flag = 1;
  54. // update_responsibility = update_setup();
  55. // TODO: update responsibility is tough, partly because the USB
  56. // interrupts aren't sychronous to the audio library block size,
  57. // but also because the PC may stop transmitting data, which
  58. // means we no longer get receive callbacks from usb_dev.
  59. update_responsibility = false;
  60. usb_audio_sync_feedback = 722824;
  61. }
  62. static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
  63. {
  64. // TODO: optimize...
  65. while (len > 0) {
  66. uint32_t n = *src++;
  67. *left++ = n & 0xFFFF;
  68. *right++ = n >> 16;
  69. len--;
  70. }
  71. }
  72. // Called from the USB interrupt when an isochronous packet arrives
  73. // we must completely remove it from the receive buffer before returning
  74. //
  75. void usb_audio_receive_callback(unsigned int len)
  76. {
  77. unsigned int count, avail;
  78. audio_block_t *left, *right;
  79. const uint32_t *data;
  80. len >>= 2; // 1 sample = 4 bytes: 2 left, 2 right
  81. data = (const uint32_t *)usb_audio_receive_buffer;
  82. //serial_print(".");
  83. //serial_phex(usb_audio_receive_buffer[0]);
  84. count = AudioInputUSB::incoming_count;
  85. left = AudioInputUSB::incoming_left;
  86. right = AudioInputUSB::incoming_right;
  87. if (left == NULL) {
  88. left = AudioStream::allocate();
  89. if (left == NULL) return;
  90. AudioInputUSB::incoming_left = left;
  91. }
  92. if (right == NULL) {
  93. right = AudioStream::allocate();
  94. if (right == NULL) return;
  95. AudioInputUSB::incoming_right = right;
  96. }
  97. while (len > 0) {
  98. avail = AUDIO_BLOCK_SAMPLES - count;
  99. if (len < avail) {
  100. //serial_print(".");
  101. copy_to_buffers(data, left->data + count, right->data + count, len);
  102. AudioInputUSB::incoming_count = count + len;
  103. return;
  104. } else {
  105. //serial_print("^");
  106. copy_to_buffers(data, left->data + count, right->data + count, avail);
  107. data += avail;
  108. len -= avail;
  109. if (AudioInputUSB::ready_left) // buffer overrun, PC sending too fast
  110. AudioStream::release(AudioInputUSB::ready_left);
  111. AudioInputUSB::ready_left = left;
  112. if (AudioInputUSB::ready_right)
  113. AudioStream::release(AudioInputUSB::ready_right);
  114. AudioInputUSB::ready_right = right;
  115. if (AudioInputUSB::update_responsibility) AudioStream::update_all();
  116. left = AudioStream::allocate();
  117. if (left == NULL) {
  118. AudioInputUSB::incoming_left = NULL;
  119. AudioInputUSB::incoming_right = NULL;
  120. AudioInputUSB::incoming_count = 0;
  121. return;
  122. }
  123. right = AudioStream::allocate();
  124. if (right == NULL) {
  125. AudioStream::release(left);
  126. AudioInputUSB::incoming_left = NULL;
  127. AudioInputUSB::incoming_right = NULL;
  128. AudioInputUSB::incoming_count = 0;
  129. return;
  130. }
  131. AudioInputUSB::incoming_left = left;
  132. AudioInputUSB::incoming_right = right;
  133. if (AudioInputUSB::underflow_flag) {
  134. AudioInputUSB::underflow_flag = 0;
  135. memset(left->data + count, 0, AUDIO_BLOCK_SAMPLES);
  136. memset(right->data + count, 0, AUDIO_BLOCK_SAMPLES);
  137. count = AUDIO_BLOCK_SAMPLES/2;
  138. serial_print("*");
  139. } else {
  140. count = 0;
  141. }
  142. }
  143. }
  144. AudioInputUSB::incoming_count = count;
  145. }
  146. void AudioInputUSB::update(void)
  147. {
  148. audio_block_t *left, *right;
  149. __disable_irq();
  150. left = ready_left;
  151. ready_left = NULL;
  152. right = ready_right;
  153. ready_right = NULL;
  154. // TODO: use incoming_count for USB isochronous feedback
  155. uint16_t c = incoming_count;
  156. __enable_irq();
  157. //serial_phex(c);
  158. //serial_print(".");
  159. if (!left || !right) {
  160. underflow_flag = 1;
  161. //serial_print("#"); // buffer underrun - PC sending too slow
  162. }
  163. if (left) {
  164. transmit(left, 0);
  165. release(left);
  166. }
  167. if (right) {
  168. transmit(right, 1);
  169. release(right);
  170. }
  171. }
  172. // Called from the USB interrupt when ready to transmit another
  173. // isochronous packet. If we place data into the transmit buffer,
  174. // the return is the number of bytes. Otherwise, return 0 means
  175. // no data to transmit
  176. unsigned int usb_audio_transmit_callback(void)
  177. {
  178. return 0;
  179. }
  180. #endif // F_CPU
  181. #endif // AUDIO_INTERFACE