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.

192 lines
5.3KB

  1. #include "Audio.h"
  2. #include "arm_math.h"
  3. DMAMEM static uint32_t i2s_rx_buffer[AUDIO_BLOCK_SAMPLES];
  4. audio_block_t * AudioInputI2S::block_left = NULL;
  5. audio_block_t * AudioInputI2S::block_right = NULL;
  6. uint16_t AudioInputI2S::block_offset = 0;
  7. bool AudioInputI2S::update_responsibility = false;
  8. void AudioInputI2S::begin(void)
  9. {
  10. //block_left_1st = NULL;
  11. //block_right_1st = NULL;
  12. //pinMode(3, OUTPUT);
  13. //digitalWriteFast(3, HIGH);
  14. //delayMicroseconds(500);
  15. //digitalWriteFast(3, LOW);
  16. AudioOutputI2S::config_i2s();
  17. CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0
  18. DMA_CR = 0;
  19. DMA_TCD1_SADDR = &I2S0_RDR0;
  20. DMA_TCD1_SOFF = 0;
  21. DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
  22. DMA_TCD1_NBYTES_MLNO = 2;
  23. DMA_TCD1_SLAST = 0;
  24. DMA_TCD1_DADDR = i2s_rx_buffer;
  25. DMA_TCD1_DOFF = 2;
  26. DMA_TCD1_CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
  27. DMA_TCD1_DLASTSGA = -sizeof(i2s_rx_buffer);
  28. DMA_TCD1_BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
  29. DMA_TCD1_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
  30. DMAMUX0_CHCFG1 = DMAMUX_DISABLE;
  31. DMAMUX0_CHCFG1 = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
  32. update_responsibility = update_setup();
  33. DMA_SERQ = 1;
  34. // TODO: is I2S_RCSR_BCE appropriate if sync'd to transmitter clock?
  35. //I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
  36. I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_FRDE | I2S_RCSR_FR;
  37. NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
  38. }
  39. void dma_ch1_isr(void)
  40. {
  41. uint32_t daddr, offset;
  42. const int16_t *src, *end;
  43. int16_t *dest_left, *dest_right;
  44. audio_block_t *left, *right;
  45. //digitalWriteFast(3, HIGH);
  46. daddr = (uint32_t)DMA_TCD1_DADDR;
  47. DMA_CINT = 1;
  48. if (daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) {
  49. // DMA is receiving to the first half of the buffer
  50. // need to remove data from the second half
  51. src = (int16_t *)&i2s_rx_buffer[AUDIO_BLOCK_SAMPLES/2];
  52. end = (int16_t *)&i2s_rx_buffer[AUDIO_BLOCK_SAMPLES];
  53. if (AudioInputI2S::update_responsibility) AudioStream::update_all();
  54. } else {
  55. // DMA is receiving to the second half of the buffer
  56. // need to remove data from the first half
  57. src = (int16_t *)&i2s_rx_buffer[0];
  58. end = (int16_t *)&i2s_rx_buffer[AUDIO_BLOCK_SAMPLES/2];
  59. }
  60. left = AudioInputI2S::block_left;
  61. right = AudioInputI2S::block_right;
  62. if (left != NULL && right != NULL) {
  63. offset = AudioInputI2S::block_offset;
  64. if (offset <= AUDIO_BLOCK_SAMPLES/2) {
  65. dest_left = &(left->data[offset]);
  66. dest_right = &(right->data[offset]);
  67. AudioInputI2S::block_offset = offset + AUDIO_BLOCK_SAMPLES/2;
  68. do {
  69. //n = *src++;
  70. //*dest_left++ = (int16_t)n;
  71. //*dest_right++ = (int16_t)(n >> 16);
  72. *dest_left++ = *src++;
  73. *dest_right++ = *src++;
  74. } while (src < end);
  75. }
  76. }
  77. //digitalWriteFast(3, LOW);
  78. }
  79. void AudioInputI2S::update(void)
  80. {
  81. audio_block_t *new_left=NULL, *new_right=NULL, *out_left=NULL, *out_right=NULL;
  82. // allocate 2 new blocks, but if one fails, allocate neither
  83. new_left = allocate();
  84. if (new_left != NULL) {
  85. new_right = allocate();
  86. if (new_right == NULL) {
  87. release(new_left);
  88. new_left = NULL;
  89. }
  90. }
  91. __disable_irq();
  92. if (block_offset >= AUDIO_BLOCK_SAMPLES) {
  93. // the DMA filled 2 blocks, so grab them and get the
  94. // 2 new blocks to the DMA, as quickly as possible
  95. out_left = block_left;
  96. block_left = new_left;
  97. out_right = block_right;
  98. block_right = new_right;
  99. block_offset = 0;
  100. __enable_irq();
  101. // then transmit the DMA's former blocks
  102. transmit(out_left, 0);
  103. release(out_left);
  104. transmit(out_right, 1);
  105. release(out_right);
  106. //Serial.print(".");
  107. } else if (new_left != NULL) {
  108. // the DMA didn't fill blocks, but we allocated blocks
  109. if (block_left == NULL) {
  110. // the DMA doesn't have any blocks to fill, so
  111. // give it the ones we just allocated
  112. block_left = new_left;
  113. block_right = new_right;
  114. block_offset = 0;
  115. __enable_irq();
  116. } else {
  117. // the DMA already has blocks, doesn't need these
  118. __enable_irq();
  119. release(new_left);
  120. release(new_right);
  121. }
  122. } else {
  123. // The DMA didn't fill blocks, and we could not allocate
  124. // memory... the system is likely starving for memory!
  125. // Sadly, there's nothing we can do.
  126. __enable_irq();
  127. }
  128. }
  129. /******************************************************************/
  130. void AudioInputI2Sslave::begin(void)
  131. {
  132. //block_left_1st = NULL;
  133. //block_right_1st = NULL;
  134. //pinMode(3, OUTPUT);
  135. //digitalWriteFast(3, HIGH);
  136. //delayMicroseconds(500);
  137. //digitalWriteFast(3, LOW);
  138. AudioOutputI2Sslave::config_i2s();
  139. CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0
  140. DMA_CR = 0;
  141. DMA_TCD1_SADDR = &I2S0_RDR0;
  142. DMA_TCD1_SOFF = 0;
  143. DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
  144. DMA_TCD1_NBYTES_MLNO = 2;
  145. DMA_TCD1_SLAST = 0;
  146. DMA_TCD1_DADDR = i2s_rx_buffer;
  147. DMA_TCD1_DOFF = 2;
  148. DMA_TCD1_CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
  149. DMA_TCD1_DLASTSGA = -sizeof(i2s_rx_buffer);
  150. DMA_TCD1_BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
  151. DMA_TCD1_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
  152. DMAMUX0_CHCFG1 = DMAMUX_DISABLE;
  153. DMAMUX0_CHCFG1 = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
  154. update_responsibility = update_setup();
  155. DMA_SERQ = 1;
  156. // TODO: is I2S_RCSR_BCE appropriate if sync'd to transmitter clock?
  157. //I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
  158. I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_FRDE | I2S_RCSR_FR;
  159. NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
  160. }