sipeed / Maixduino

Arduino port on Maix board ( k210 )
https://maixduino.sipeed.com
Other
216 stars 96 forks source link

Looking I2S Microphone Arduino example #86

Open bmitov opened 4 years ago

bmitov commented 4 years ago

Hello everyone,

I am the developer of Visuino - https://www.visuino.com One of the Visuino users sent me Maixduino to add support for it in Visuino, and now I am working on it. It surely is a very interesting, and exciting board. I have already added pin mapping for the digital pins, and for the boot button, and the serial. Now looking to add the rest. I am however not sure how to use the I2S API to acquire buffers from the Microphone :-( . I want to use non blocking/asynchronous API so I can collect buffers from the microphone while at the same time run other processes. I do this on other boards like ESP32 and Arduino Nano 33 BLE. Can someone please post a small code example using the K210 API to get I2S buffers from the Microphone?

With best regards, Boian Mitov

chegewara commented 4 years ago

https://github.com/chegewara/sipeed-maixduino-test-apps/blob/master/platformIO/MaixPy/mic-array.py

bmitov commented 4 years ago

Thank you @chegewara . I am actually looking for C++ code using the K210 API, and a non blocking (pooling) implementation. It seems from what I see that I need to use i2s_handle_data_dma to setup callback. Still trying to figure out the usage, but at least some progress. So far I have found only one example in Japanese and with google translate slowly working through it. The K210 documentation is quite scarce unfortunately :-( , but won't be the first time fighting barely documented board to add to Visuino... Story of my life... :-D

chegewara commented 4 years ago

Actually there is somewhere "good" documentation for k210 to use with freertos. Sorry but i dont remember where, i printed out it long time ago. Now i have 2 pretty cool maixduino boards in drawer, each with display and mic/LED array.

bmitov commented 4 years ago

@chegewara Maybe time for you to get them out and play with them ;-) . I can get you Beta of Visuino with the Maixduino added for you to play with it :-) . Working on the MicroSD at the moment, and will move to the Microphone and Display/Camera next. Finally the AI stuff :-) Will take some days...

chegewara commented 4 years ago

I am playing with esp32 S2 and USB stuff right now, but i could test and see how maixduino would works with visuino. I am not using it personally, but my cousin is a teacher at elementary school and i recommended her visuino some time ago.

bmitov commented 4 years ago

@chegewara Cool! :-) I have not had chance to work on the S2 yet. They still have to sort the Arduino libraries from what I have heard, so I am waiting for it to be sorted, before I start messing with it, but it surely is on the lis :-) I got the MicorSD to work, and now onto the I2S. I think I have found a codes snipped for the I2S on the Japanese guy's blog. I am trying to write a small test to see if I can get it to work :-)

chegewara commented 4 years ago

One thing, did you check maixduino library in arduino IDE? There is for sure some mic code, because its voice reco.

bmitov commented 4 years ago

@chegewara I did. They have direct connection (channeling) between the Microphone and the AI classifier. I want to get the samples in the code, and there does not seem to be example, but I am writing one now :-). Hope to have a simple test working shortly :-) I will be looking at direct piping later after I get the basic functionality working ;-)

bmitov commented 4 years ago

I have a proof of concept working :-) Here is the code if somebody else needs it. Super crappy, but shows the concept:

include

define FRAME_LEN 512 // CHUNK = 512(Monoral) / 1024(Stereo)

define SAMPLE_RATE 16000

uint32_t rx_buf[ FRAME_LEN * 2 ];

// I2S Event Routine Register i2s_data_t data = (i2s_data_t){ .rx_channel = DMAC_CHANNEL0, .rx_buf = rx_buf, .rx_len = FRAME_LEN * 2, .transfer_mode = I2S_RECEIVE, };

int i2s_on_irq(void *ctx) { Serial.println(".");

plic_interrupt_t irq = (plic_interrupt_t){ .callback = i2s_on_irq, .ctx = nullptr, .priority = 1 };

i2s_handle_data_dma(I2S_DEVICE_0, data, &irq);

return 0; }

void setup() { Serial.begin(115200);

i2s_init(I2S_DEVICE_0, I2S_RECEIVER, 0x3); Serial.println("I2S init OK");

i2s_rx_channel_config(I2S_DEVICE_0, I2S_CHANNEL_0, RESOLUTION_16_BIT, SCLK_CYCLES_32, TRIGGER_LEVEL_4, LEFT_JUSTIFYING_MODE);

uint32_t sample_rate_act; //uint32_t i2s_set_sample_rate(i2s_device_number_t device_num, uint32_t sample_rate); sample_rate_act = i2s_set_sample_rate(I2S_DEVICE_0, SAMPLE_RATE); Serial.printf("sample_rate_act=%d\r\n",sample_rate_act);

plic_interrupt_t irq = (plic_interrupt_t){ .callback = i2s_on_irq, .ctx = nullptr, .priority = 1 };

i2s_handle_data_dma(I2S_DEVICE_0, data, &irq);
}

void loop() { // put your main code here, to run repeatedly: }

chegewara commented 4 years ago

https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_standalone_programming_guide_20190311144158_en.pdf

https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_freertos_programming_guide_20190311143226_en.pdf

chegewara commented 4 years ago

https://github.com/kendryte/kendryte-standalone-demo/blob/develop/i2s_dma/main.c

bmitov commented 4 years ago

@chegewara Thank you! :-) I have seen the PDFs before. Thank you for the github link. I am still testing here since the kendryte_standalone_programming_guide_20190311144158_en.pdf does not document a lot of the important information like how the data is storred in the buffers as example :-( . I am still experimenting to figure out the details.

kevintsq commented 3 years ago

Hi~ Your dialog is interesting. Recently I came up with a question. I'd like to ask how to use the mic array and the on-board mic simultaneously? Since it seems impossible for me to get audio data from the mic array directly via MaixPy API, I tried to get audio data from the on-board mic while using the mic array to get sound direction. But it doesn't work. I guess there may be some I2S interface conflict between the on-board mic and the mic array. But it is said that the CPU supports 8 mics and 3 I2S devices, and the mic array contains 7 mics serving as 1 device. Could anyone helps me out? Thanks a lot~

alirezainallo commented 1 year ago

Hi~ Your dialog is interesting. Recently I came up with a question. I'd like to ask how to use the mic array and the on-board mic simultaneously? Since it seems impossible for me to get audio data from the mic array directly via MaixPy API, I tried to get audio data from the on-board mic while using the mic array to get sound direction. But it doesn't work. I guess there may be some I2S interface conflict between the on-board mic and the mic array. But it is said that the CPU supports 8 mics and 3 I2S devices, and the mic array contains 7 mics serving as 1 device. Could anyone helps me out? Thanks a lot~

Hi @kevintsq, You have connect pin 20 (FUNC_I2S0_IN_D0) to MIC_D3 pin on the mic array. and central mic on mic array is Right mic and on board mic (maxiduino) is Left mic.

alirezainallo commented 1 year ago

@chegewara Thank you! :-) I have seen the PDFs before. Thank you for the github link. I am still testing here since the kendryte_standalone_programming_guide_20190311144158_en.pdf does not document a lot of the important information like how the data is storred in the buffers as example :-( . I am still experimenting to figure out the details.

Hi @chegewara, if you call like i2s_receive_data_dma(I2S_DEVICE, &g_rx_dma_buf[0], I2S_BUF_LEN, DMA_CHANNEL); (uint32_t g_rx_dma_buf[I2S_BUF_LEN]), in the i2s_dma_irq() you have i2s data in g_rx_dma_buf that Right mic is even index and Left mic data is odd index. you can use this code: for(uint32_t i = 0; i < (I2S_BUF_LEN/2); i++){ int16_t r_tmp = (int16_t)(g_rx_dma_buf[2 i] & 0xffff) I2S_SAMPLES_FACTOR; int16_t l_tmp = (int16_t)(g_rx_dma_buf[2 i + 1] & 0xffff) I2S_SAMPLES_FACTOR; }

that factor I2S_SAMPLES_FACTOR is for amplitude and I set it 10.