Teensy 4.1 core updated for C++20
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

usb_audio.cpp 5.7KB

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