VS1010 MEMS microphone capture

Designing hardware and software for systems that use the VS1010 MP3 Audio DSP Microcontroller.
Post Reply
User avatar
Panu
VSDSP Expert
Posts: 2803
Joined: Tue 2010-06-22 13:43

VS1010 MEMS microphone capture

Post by Panu » Tue 2017-08-01 16:00

Dear all,

Here is a small example that configures the MEMS microphone port on the developer board and loops audio from the microphone to the DAC. It uses interrupts to get the MEMS data and decimates the data in an overly simplistic fashion by just taking the average of 8 samples. The idea is that this demonstrates the usage of the MEMS interface hardware; it's not a very good example of signal processing.

Code: Select all

#include <vo_stdio.h>
#include <vs1010b.h>
#include <audiofs.h>
#include <vo_gpio.h>
#include <fifoy.h>
#include <protocol.h>

__y s_int16 memsDataBuffer[128];
__y struct FIFOY memsFifo;

#pragma interrupt y 0x26
void MemsMicInterruptHandler(void) {
	FIFOYPut(&memsFifo,PERIP(FAUDIO_L)); //Get audio from mems data port to FIFO
}

void fini(void) { //Disable the MEMS mic interrupt
	PERIP(INT_ENABLE0_HP) &= ~(1 << 6);
}

ioresult main (char *params) {
	int i;
	static s_int32 sampleRate = 24000;
	ioctl(stdaudioout, IOCTL_AUDIO_SET_ORATE, &sampleRate);
	ioctl(stdaudioout, IOCTL_AUDIO_SET_OCHANNELS, (IOCTL_ARGUMENT)2);

	gotoShell = 0;
	FIFOYInit(&memsFifo,memsDataBuffer,sizeof(memsDataBuffer));
	PERIP(INT_ENABLE0_HP) |= (1 << 6);

	printf("Looping, [Enter] to end..\n");	
	GpioSetAsPeripheral(0x09); //MD1
	GpioSetAsPeripheral(0x0a); //MC1
	
	PERIP(MEMSMIC_CF) = MEMSMIC_CF_SELIO | MEMSMIC_CF_ENA;// | MEMSMIC_CF_LEDGE | MEMSMIC_CF_REDGE;
	PERIP(PERIP_CF) |= (1 << 2); //Enable MC1 clock generation /// \todo vs1010b.h file has error!		
	PERIP(FAUDIO_SEL) = 2; //Route MEMS mic to fast audio read register

	while(!gotoShell) { // Loop until Enter is pressed
		static u_int16 abuf[2];
		if (FIFOYFill(&memsFifo) > 8) { //8 MEMS samples (192k) available, average them to get a crude 24kHz sample.
			s_int16 s = 0;
			for (i=0; i<8; i++) s += FIFOYGet(&memsFifo) / 4;

			abuf[0] = abuf[1] = s;
			stdaudioout->op->Write(stdaudioout, abuf, 0, 4);						
		}
	}
	
	return S_OK;
}
Attachments
arch-LoopMems-2017-08-01-16-59-Average24k.zip
Loops audio from MEMS microphone to output. Source code, VSIDE solution.
(12.8 KiB) Downloaded 170 times
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

User avatar
Panu
VSDSP Expert
Posts: 2803
Joined: Tue 2010-06-22 13:43

Re: VS1010 MEMS microphone capture

Post by Panu » Tue 2017-08-01 17:29

Hi again!

With help from other experts at VLSI, here's a mems microphone loopback code with a proper decimation filter. With this one the sound quality is actually pretty good and it is a good example of signal processing. :D

Code: Select all

	while(!gotoShell) { // Loop until Enter is pressed
		#define BLOCKSIZE 64 // Decimate 64 samples at 192kHz to 16 samples at 48kHz.
		static u_int16 fullRate[BLOCKSIZE];
		if (FIFOYFill(&memsFifo) > BLOCKSIZE) { 
		
			static s_int16 dec4delay[17*2];
			static s_int16 *dec4delayPtr = dec4delay+16;
			static const __mem_y s_int16 dec4coeff[17] = {
				-711,   -224,   153,    885,   1919,   3099,   4199,   4980,   5264, 4980,   4199,   3099,   1919,    885,   153,   -224,   -711
			};
			s_int16 *p = fullRate;
			for (i=0; i<BLOCKSIZE; i++) {
				*p++ = FIFOYGet(&memsFifo);
			}
			
			FirGeneralStrideAsm(fullRate, 1, BLOCKSIZE, dec4coeff, &dec4delayPtr, 17, 1);
			memcpystride(fullRate, sizeof(s_int16), fullRate, 4*sizeof(s_int16), BLOCKSIZE/4); //Re-pack decimate by 4.	
			stdaudioout->op->Write(stdaudioout, fullRate, 0, (BLOCKSIZE/4)*2);
		}
	}
With this code, the DAC runs at 48 kHz and the filter code outputs 16 samples at each iteration in mono mode, so it's pretty efficient too.

-Panu
Attachments
LoopMems.dlx
MEMS mic loopback program for VS1010B. VS1010 VSOS executable.
(1.2 KiB) Downloaded 161 times
arch-LoopMems-2017-08-01-18-24-DecimationFilter.zip
MEMS mic loopback using a FIR decimation filter. Source code, VSIDE solution.
(14.17 KiB) Downloaded 176 times
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

User avatar
Panu
VSDSP Expert
Posts: 2803
Joined: Tue 2010-06-22 13:43

Re: VS1010 MEMS microphone capture

Post by Panu » Thu 2017-08-03 13:34

Here's another improvement of the MEMS microphone loopback code. This one processes samples aperiodically, which gives better sound in some situations.
Attachments
arch-LoopMemV-2017-08-03-14-30-Aperiodic.zip
Souce code, VSIDE Solution
(16.15 KiB) Downloaded 144 times
LoopMemV.dlx
VS1010 VSOS Executable
(1.3 KiB) Downloaded 141 times
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

krdarrah
User
Posts: 4
Joined: Tue 2021-01-19 19:39

Re: VS1010 MEMS microphone capture

Post by krdarrah » Fri 2021-02-26 17:54

How to configure on LQFP-48?

I have this, but not sure?

Code: Select all

	GpioSetAsPeripheral(0x01); //MD0
	GpioSetAsPeripheral(0x1E); //MC0
	PERIP(PERIP_CF) |= (1 << 3); //Enable PERIP_CF_I2S48PIN
	PERIP(MEMSMIC_CF) = MEMSMIC_CF_ENA;//| MEMSMIC_CF_REDGE;
	PERIP(PERIP_CF) |= (1 << 1); //Enable MC0 clock generation
	PERIP(PERIP_CF) |= (1 << 3); //Enable PERIP_CF_I2S48PIN
	PERIP(FAUDIO_SEL) = 2; //Route MEMS mic to fast audio read register

Hannu
Senior User
Posts: 146
Joined: Mon 2016-05-30 11:54

Re: VS1010 MEMS microphone capture

Post by Hannu » Mon 2021-03-01 8:53

I don't have LQFP card on hand right now to test but I think you have the I2S overriding the GPIO0_1 and GPIO1_14 function.

I would try something like:

Code: Select all

	GpioSetAsPeripheral(0x01); //MD0
	GpioSetAsPeripheral(0x1E); //MC0
	PERIP(MEMSMIC_CF) = MEMSMIC_CF_ENA;//| MEMSMIC_CF_REDGE;/* MEMSMIC_SELIO should stay 0 */
	PERIP(PERIP_CF) |= (1 << 1); //Enable MC0 clock generation
	PERIP(FAUDIO_SEL) = 2; //Route MEMS mic to fast audio read register
krdarrah wrote:
Fri 2021-02-26 17:54
How to configure on LQFP-48?

I have this, but not sure?

Code: Select all

	GpioSetAsPeripheral(0x01); //MD0
	GpioSetAsPeripheral(0x1E); //MC0
	PERIP(PERIP_CF) |= (1 << 3); //Enable PERIP_CF_I2S48PIN
	PERIP(MEMSMIC_CF) = MEMSMIC_CF_ENA;//| MEMSMIC_CF_REDGE;
	PERIP(PERIP_CF) |= (1 << 1); //Enable MC0 clock generation
	PERIP(PERIP_CF) |= (1 << 3); //Enable PERIP_CF_I2S48PIN
	PERIP(FAUDIO_SEL) = 2; //Route MEMS mic to fast audio read register

User avatar
Panu
VSDSP Expert
Posts: 2803
Joined: Tue 2010-06-22 13:43

Re: VS1010 MEMS microphone capture

Post by Panu » Wed 2021-03-03 18:35

krdarrah wrote:
Fri 2021-02-26 17:54
How to configure on LQFP-48?
Hi!

We've been looking into this. As it turns out, the peripherals need to be used a little bit differently for it to work. Hold on, we're cleaning up and optimizing the source code and making it work as similarly as possible to the old code.

-Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

User avatar
Panu
VSDSP Expert
Posts: 2803
Joined: Tue 2010-06-22 13:43

Re: VS1010 MEMS microphone capture

Post by Panu » Thu 2021-03-04 19:05

Dear VS1010 LQFP package users,

Here's a version of the digital mems microphone capture that works with the LQFP-48 package. It's been tested on the VS1010D LQFP Simple Board. The inner workings of the mic capture have been completely rewritten, but the usage is very simple:

Code: Select all

	InitMemsFilter(sampleRate); //12000 or 24000 
	
	while (lastReceivedCharUart0 != 27) { //Loopback from mems to dac
		s_int16 *s = Get16MicrophoneSamples();
		if (s) {
			stdaudioout->op->Write(stdaudioout, s, 0, 16 * 2); //16*2 bytes
		}
	}
This code loops back audio from the microphone to the main (dac) audio path. InitMemsFilter() sets up the microphone and Get16MicrophoneSamples() gets sound data. If there's not sufficient data in the buffer, the function returns NULL so it's safe to call from realtime systems.

This code can get data in two sample rates; either 24 kHz or 12 kHz. If you need some other sample rates, please let us know!

If you give the parameter 12, the demo uses 12 kHz sample rate, otherwise it uses 24 kHz sample rate.
VS1010>memslqfp
Mems loopback (lqfp), sample rate 24000. [Esc] to end

VS1010>memslqfp 12
Mems loopback (lqfp), sample rate 12000. [Esc] to end

VS1010>
vs1010_lqfp_board.jpg
vs1010_lqfp_board.jpg (111.01 KiB) Viewed 21 times
To work in the LQFP package with all VS1010 versions, the code needs to use the I2S hardware to pump the bits from the microphone and then does high quality software decimation for the best sound quality. Please contact VLSI for details and how this might affect your system.

Sincerely,
Panu
Attachments
memslqfp.dlx
MEMS microphone capture demo program for VS1010D in LQFP package. VS1010/VSOS DLX executable.
(7.83 KiB) Downloaded 2 times
arch-memslqfp-2021-03-04-18-53-RC1.zip
Source code, VSIDE Solution
(37.9 KiB) Downloaded 3 times
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo, VLSI Solution Oy

Post Reply