PDM_SPM1423.ino 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. Description: Read the microphone data of the PDM Unit and display the audio frequency spectrum.
  3. Note: Remove the M5GO base when using this example, otherwise it will not work properly,PDM Unit connected PORT-A
  4. */
  5. #include <M5Stack.h>
  6. #include <driver/i2s.h>
  7. #include "fft.h"
  8. #define PIN_CLK 22
  9. #define PIN_DATA 21
  10. #define MODE_MIC 0
  11. TFT_eSprite DisFFTbuff = TFT_eSprite(&M5.Lcd);
  12. static QueueHandle_t fftvalueQueue = nullptr;
  13. static QueueHandle_t i2sstateQueue = nullptr;
  14. void header(const char *string, uint16_t color)
  15. {
  16. M5.Lcd.fillScreen(color);
  17. M5.Lcd.setTextSize(1);
  18. M5.Lcd.setTextColor(WHITE, BLACK);
  19. M5.Lcd.fillRect(0, 0, 320, 30, BLACK);
  20. M5.Lcd.setTextDatum(TC_DATUM);
  21. M5.Lcd.drawString(string, 160, 3, 4);
  22. }
  23. typedef struct
  24. {
  25. uint8_t state;
  26. void* audioPtr;
  27. uint32_t audioSize;
  28. }i2sQueueMsg_t;
  29. bool InitI2SSpakerOrMic(int mode)
  30. {
  31. // i2s_driver_uninstall(I2S_NUM_0);
  32. i2s_config_t i2s_config = {
  33. .mode = (i2s_mode_t)(I2S_MODE_MASTER),
  34. .sample_rate = 44100,
  35. .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
  36. .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
  37. .communication_format = I2S_COMM_FORMAT_I2S,
  38. .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
  39. .dma_buf_count = 2,
  40. .dma_buf_len = 128,
  41. };
  42. if (mode == MODE_MIC)
  43. {
  44. i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM);
  45. }
  46. //Serial.println("Init i2s_driver_install");
  47. i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  48. i2s_pin_config_t pin_config;
  49. pin_config.bck_io_num = I2S_PIN_NO_CHANGE;
  50. pin_config.ws_io_num = PIN_CLK;
  51. pin_config.data_out_num = I2S_PIN_NO_CHANGE;
  52. pin_config.data_in_num = PIN_DATA;
  53. //Serial.println("Init i2s_set_pin");
  54. i2s_set_pin(I2S_NUM_0, &pin_config);
  55. //Serial.println("Init i2s_set_clk");
  56. i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
  57. return true;
  58. }
  59. static void i2sMicroFFTtask(void *arg)
  60. {
  61. uint8_t FFTDataBuff[128];
  62. uint8_t FFTValueBuff[24];
  63. uint8_t* microRawData = (uint8_t*)calloc(2048,sizeof(uint8_t));
  64. size_t bytesread;
  65. int16_t* buffptr;
  66. double data = 0;
  67. float adc_data;
  68. uint16_t ydata;
  69. uint32_t subData;
  70. uint8_t state = MODE_MIC;
  71. i2sQueueMsg_t QueueMsg;
  72. while(1)
  73. {
  74. if( xQueueReceive(i2sstateQueue,&QueueMsg,(TickType_t)0) == pdTRUE)
  75. {
  76. //Serial.println("Queue Now");
  77. if( QueueMsg.state == MODE_MIC )
  78. {
  79. InitI2SSpakerOrMic(MODE_MIC);
  80. state = MODE_MIC;
  81. }
  82. }
  83. else if( state == MODE_MIC )
  84. {
  85. fft_config_t *real_fft_plan = fft_init(1024, FFT_REAL, FFT_FORWARD, NULL, NULL);
  86. i2s_read(I2S_NUM_0, (char *)microRawData, 2048, &bytesread, (100 / portTICK_RATE_MS));
  87. buffptr = ( int16_t*)microRawData;
  88. for ( int count_n = 0; count_n < real_fft_plan->size; count_n++)
  89. {
  90. adc_data = (float)map(buffptr[count_n], INT16_MIN, INT16_MAX, -2000, 2000);
  91. real_fft_plan->input[count_n] = adc_data;
  92. }
  93. fft_execute(real_fft_plan);
  94. for ( int count_n = 1; count_n < real_fft_plan->size / 4; count_n++)
  95. {
  96. data = sqrt(real_fft_plan->output[2 * count_n] * real_fft_plan->output[2 * count_n] + real_fft_plan->output[2 * count_n + 1] * real_fft_plan->output[2 * count_n + 1]);
  97. if ((count_n - 1) < 128)
  98. {
  99. data = ( data > 2000 ) ? 2000 : data;
  100. ydata = map(data, 0, 2000, 0, 255);
  101. FFTDataBuff[128 - count_n] = ydata;
  102. }
  103. }
  104. for( int count = 0; count < 24; count++ )
  105. {
  106. subData = 0;
  107. for( int count_i = 0; count_i < 5; count_i++ )
  108. {
  109. subData += FFTDataBuff[count * 5 + count_i ];
  110. }
  111. subData /= 5;
  112. FFTValueBuff[count] = map(subData,0,255,0,8);
  113. }
  114. xQueueSend( fftvalueQueue, (void * )&FFTValueBuff, 0 );
  115. fft_destroy(real_fft_plan);
  116. //Serial.printf("mmp\r\n");
  117. }
  118. else
  119. {
  120. delay(10);
  121. }
  122. }
  123. }
  124. void microPhoneSetup()
  125. {
  126. fftvalueQueue = xQueueCreate(5, 24 * sizeof(uint8_t));
  127. if( fftvalueQueue == 0 )
  128. {
  129. return;
  130. }
  131. i2sstateQueue = xQueueCreate(5, sizeof(i2sQueueMsg_t));
  132. if( i2sstateQueue == 0 )
  133. {
  134. return;
  135. }
  136. InitI2SSpakerOrMic(MODE_MIC);
  137. xTaskCreatePinnedToCore(i2sMicroFFTtask, "microPhoneTask", 4096, NULL, 3, NULL, 0);
  138. DisFFTbuff.createSprite(320,54);
  139. }
  140. void MicroPhoneFFT()
  141. {
  142. uint8_t FFTValueBuff[24];
  143. xQueueReceive( fftvalueQueue, (void * )&FFTValueBuff, portMAX_DELAY );
  144. DisFFTbuff.fillRect(0,0,320,54,DisFFTbuff.color565(0x00,0x00,0x00));
  145. uint32_t colorY = DisFFTbuff.color565(0xff,0x9c,0x00);
  146. uint32_t colorG = DisFFTbuff.color565(0x66,0xff,0x00);
  147. uint32_t colorRect;
  148. for( int x = 0; x < 24; x++ )
  149. {
  150. for( int y = 0; y < 9; y++ )
  151. {
  152. if( y < FFTValueBuff[23-x] )
  153. {
  154. colorRect = colorY;
  155. }
  156. else if( y == FFTValueBuff[23-x] )
  157. {
  158. colorRect = colorG;
  159. }
  160. else
  161. {
  162. continue;
  163. }
  164. DisFFTbuff.fillRect(x*12,54-y*6 - 5,5,5,colorRect);
  165. }
  166. }
  167. DisFFTbuff.pushSprite(20, 120);
  168. }
  169. void setup() {
  170. M5.begin(true, true, true, true);
  171. header("PDM Unit", BLACK);
  172. microPhoneSetup();
  173. }
  174. void loop() {
  175. MicroPhoneFFT();
  176. }