Tag Archive for オーディオコーデック

WM8510オーディオコーデック / WM8510 Audio Codec: Configuring for 48kHz Sampling Rate

dsPic Starter kit WM8510 facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

こんにちは / Hello,

A couple of posts below i mentioned about Wolfson WM8510 audio codec used in the Microchip’s DCS Starter Kit. In the demo files found on Microchip’s webpage you can find a driver for this codec written in C  but it only has config defined for 8kHz and 16kHz which ofcourse it is very very low for any hi-fi standard. This doesn’t mean the chip can’t do better.

First thing we will need the datasheet of the WM8510 which can be found here. At page 65 you will find [Register Bits by Address] and this is a very helpfull map around the device’s registers.

Now lets look at the files from Microchip. We have WM8510CodecDrv.c and WM8510CodecDrv.h. These two are the ones that interest us. In main.c file we can see the function call that sets up WM8510 for the desired sampling rate:

/* Configure codec for 8K operation */
WM8510SampleRate8KConfig(codecHandle);

WM9510SampleRate8KConfig() function is defined in WM8510CodecDrv.c file. Under this function are a bunch of instructions that will write specific values in WM8510’s registers. For example:

commandValue = 0b000000100;
WM8510IOCtl(codecHandle,WM8510_INPUT_CTRL, (void *) &commandValue);

This will write 000000100 bits in WM8510_INPUT_CTRL register. All register names are defined in WM8510CodecDrv.h and each name has a decimal value attributed. This decimal value coresponds to the Register Address from page 65 in the WM8510 datasheet.

I found a weird thing in the setup for 8kHz sampling rate which i dont understand:

commandValue = 0b001111101;
WM8510IOCtl(codecHandle,WM8510_NOTCH_FILTER4, (void *) &commandValue);
if (result == -1) while(1);

commandValue = 0b100000000;
WM8510IOCtl(codecHandle,WM8510_NOTCH_FILTER4, (void *) &commandValue);
if (result == -1) while(1);

Why write two different values in the same register in consecutive instructions beats me.

So in order to configure WM8510 for 48kHz sampling rate we will need to create one more function and add it to the WM8510CodecDrv.c, basically copy paste from the 16kHz one and then modify it, or just copy paste whats below. Remember to backup your files first and read the disclaimer :).

void WM8510SampleRate48KConfig(WM8510Handle *codecHandle)
{
int commandValue,result;
commandValue = 1; /* Any value can be written to reset the codec */
result = WM8510IOCtl(codecHandle,WM8510_SOFTWARE_RESET, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b001101111;
WM8510IOCtl(codecHandle,WM8510_POWER_MGMT1, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000010101;
WM8510IOCtl(codecHandle,WM8510_POWER_MGMT2, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b010001001;
WM8510IOCtl(codecHandle,WM8510_POWER_MGMT3, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000011000;
WM8510IOCtl(codecHandle,WM8510_AUDIO_INTERFACE, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b100000001;
WM8510IOCtl(codecHandle,WM8510_CLOCKGEN_CTRL, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000000000;
WM8510IOCtl(codecHandle,WM8510_ADDITIONAL_CTRL, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000000100;
WM8510IOCtl(codecHandle,WM8510_GPIO_STUFF, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000001000;
WM8510IOCtl(codecHandle,WM8510_PLL_N, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000001100;
WM8510IOCtl(codecHandle,WM8510_PLL_K1, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b010010011;
WM8510IOCtl(codecHandle,WM8510_PLL_K2, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b011101001;
WM8510IOCtl(codecHandle,WM8510_PLL_K3, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000000100;
WM8510IOCtl(codecHandle,WM8510_INPUT_CTRL, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000000000;
WM8510IOCtl(codecHandle,WM8510_ADC_BOOST_CTRL, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b000000001;
WM8510IOCtl(codecHandle,WM8510_MONO_MIXER_CTRL, (void *) &commandValue);
if (result == -1) while(1);
commandValue = 0b100001000;
WM8510IOCtl(codecHandle,WM8510_ADC_CONTROL , (void *) &commandValue);
if (result == -1) while(1);
}

 

Now in WM8510CodecDrv.h you must add before #endif

void WM8510SampleRate48KConfig(WM8510Handle *codecHandle);

After this the chip is configured to work at 48kHz sampling rate and 16bits word length. To modify it for 24bits you need to modify bits 6:5 to 0b10 from register 4 or WM8510_AUDIO_INTERFACE. For 48kHz sampling rate first you need to modify bits 3:1 to 0b000 (default value actually) in WM8510_ADDITIONAL_CTRL (R7) register, bits 7:2 in WM8510_CLOCKGEN_CTRL (R6) to 0b000000 and bit 4 in WM8510_PLL_N (R36) to 0.

I have run some sine log sweeps to determine frequency response and here are the results:

WM8510 8kHz sampling rate dsPIC Starter KItWM8510 16kHz sampling rate dsPIC Starter KItWM8510 48kHz sampling rate dsPIC Starter KIt

 

Looking through the register map you can see many usefull functions like an input mixer, gain control, level control, output selection, some filtering capabilities. You can modify all these registers in main.c by calling WM8510IOCtl() function. After you added the 48kHz config in the driver .c file you will also need to replace the WM8510SampleRate8KConfig(codecHandle); with WM8510SampleRate48KConfig(codecHandle); in main.c. 

Happy coding and thanks for visiting.

ご覧いただきありがとうございます。