| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
AudioOutput.c
Go to the documentation of this file.
1 /*
2 * @brief Make your board becomes a USB speaker
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * Copyright(C) Dean Camera, 2011, 2012
7 * All rights reserved.
8 *
9 * @par
10 * Software that is described herein is for illustrative purposes only
11 * which provides customers with programming information regarding the
12 * LPC products. This software is supplied "AS IS" without any warranties of
13 * any kind, and NXP Semiconductors and its licensor disclaim any and
14 * all warranties, express or implied, including all implied warranties of
15 * merchantability, fitness for a particular purpose and non-infringement of
16 * intellectual property rights. NXP Semiconductors assumes no responsibility
17 * or liability for the use of the software, conveys no license or rights under any
18 * patent, copyright, mask work right, or any other intellectual property rights in
19 * or to any products. NXP Semiconductors reserves the right to make changes
20 * in the software without notification. NXP Semiconductors also makes no
21 * representation or warranty that such application will be suitable for the
22 * specified use without further testing or modification.
23 *
24 * @par
25 * Permission to use, copy, modify, and distribute this software and its
26 * documentation is hereby granted, under NXP Semiconductors' and its
27 * licensor's relevant copyrights in the software, without fee, provided that it
28 * is used in conjunction with NXP Semiconductors microcontrollers. This
29 * copyright, permission, and disclaimer notice must appear in all copies of
30 * this code.
31 */
32
33 #include "AudioOutput.h"
34 #if defined(USB_DEVICE_ROM_DRIVER)
35 //#include "usbd_adcuser.h"
36 #endif
37
41 USB_ClassInfo_Audio_Device_t Speaker_Audio_Interface = {
42 .Config = {
43 .StreamingInterfaceNumber = 1,
44
45 .DataOUTEndpointNumber = AUDIO_STREAM_EPNUM,
46 .DataOUTEndpointSize = AUDIO_STREAM_EPSIZE,
47 .PortNumber = 0,
48 },
49 };
50
52 #define AUDIO_MAX_SAMPLE_FREQ 48000
53
54 #define AUDIO_SPEEP_UP_TRIGGER (audio_buffer_size*5/8)
55
56 #define AUDIO_NORMAL_SPEED_TRIGGER (audio_buffer_size*3/8)
57
58 uint32_t CurrentAudioSampleFrequency = AUDIO_MAX_SAMPLE_FREQ;
59
64 #define AUDIO_MAX_PC 10
65 PRAGMA_ALIGN_4
66 uint8_t audio_buffer[2048*2] ATTR_ALIGNED(4);
67 uint32_t audio_buffer_size = 0;
68 uint32_t audio_buffer_rd_index = 0;
69 uint32_t audio_buffer_wr_index = 0;
70 uint32_t audio_buffer_count = 0;
71
72 typedef struct {
73 uint8_t BITRATE;
74 struct {
75 uint8_t X,Y;
76 } RATEUP;
77 struct {
78 uint8_t X,Y;
79 } RATEDOWN;
80 } I2S_RATE_CONFIG;
81
82 static uint32_t I2S_SpeedConfig_index;
83 #if defined(__LPC18XX__ )
84
86 I2S_RATE_CONFIG I2S_SpeedConfig[] =
87 {
88 /* BITRATE RATE_Up(x,y) RATE_Down(x,y) */
89 /* 8000 */
90 {0x3F, {0x2D, 0xF7}, {0x02, 0x0B}},
91 /* 11025 */
92 {0x3F, {0x40, 0xFF}, {0x01, 0x04}},
93 /* 16000 unsupport */
94 {0, {0, 0}, {0, 0}},
95 /* 22050 */
96 {0x3F, {0x80, 0xFF}, {0x01, 0x02}},
97 /* 32000 unsupport */
98 {0, {0, 0}, {0, 0}},
99 /* 44100 */
100 {0x3E, {0xF4, 0xF7}, {0x51, 0x52}},
101 /* 48000 */
102 {0x39, {0x62, 0x63}, {0xC3, 0xC5}}
103
104 };
105 #elif defined(__LPC43XX__ )
106
108 I2S_RATE_CONFIG I2S_SpeedConfig[] =
109 {
110 /* BITRATE RATE_Up(x,y) RATE_Down(x,y) */
111 /* 8000 */
112 {0x3F, {0x20, 0xC1}, {0x16, 0x89}},
113 /* 11025 */
114 {0x3F, {0x1D, 0x83}, {0x38, 0xFD}},
115 /* 16000 unsupport */
116 {0, {0, 0}, {0, 0}},
117 /* 22050 */
118 {0x3F, {0x3A, 0x83}, {0x55, 0xC0}},
119 /* 32000 unsupport */
120 {0, {0, 0}, {0, 0}},
121 /* 44100 */
122 {0x3F, {0x74, 0x83}, {0xC9, 0xE3}},
123 /* 48000 */
124 {0x3F, {0xD5, 0xDD}, {0x85, 0x8A}}
125
126 };
127 #endif
128 Status I2S_RateFind(LPC_I2S_T *I2Sx, Chip_I2S_Audio_Format_T *audio_format, I2S_RATE_CONFIG *I2S_Config)
129 {
130 uint32_t pClk;
131 uint32_t x, y;
132 uint64_t divider;
133 uint16_t dif;
134 uint16_t x_divide = 0, y_divide_down = 0, y_divide_up = 0;
135 uint32_t N;
136 uint32_t err, ErrorOptimal_down = 0xFFFF, ErrorOptimal_up = 0xFFFF;
137
138 pClk = (uint64_t)Chip_Clock_GetRate(CLK_APB1_I2S);
139
140 /* find N that make x/y <= 1 -> divider <= 2^16 */
141 for (N = 64; N > 0; N--) {
142 /* divider is a fixed point number with 16 fractional bits */
143 divider = (((uint64_t)(audio_format->SampleRate) * 2 * (audio_format->WordWidth) * 2) << 16) * N / pClk;
144 if (divider < (1 << 16)) {
145 break;
146 }
147 }
148 if (N == 0) {
149 return ERROR;
150 }
151 //divider *= N;
152 for (y = 255; y > 0; y--) {
153 x = y * divider;
154 if (x & (0xFF000000)) {
155 continue;
156 }
157 dif = x & 0xFFFF;
158 if (dif > 0x8000) {
159 /* mark this case to plus 1 to x value */
160 err = (0x10000 - dif);
161 /* in this case x = 255 + 1 */
162 if((x & 0x00FF0000) == 0x00FF0000) continue;
163 if (err < ErrorOptimal_up ) {
164 ErrorOptimal_up = err;
165 y_divide_up = y;
166 }
167 }
168 else {
169 err = dif;
170 if (err < ErrorOptimal_down) {
171 ErrorOptimal_down = err;
172 y_divide_down = y;
173 }
174 }
175 }
176 I2S_Config->BITRATE = N - 1;
177 x_divide = ((uint64_t)y_divide_up * (audio_format->SampleRate) * 2 * (audio_format->WordWidth) * N * 2) / pClk;
178 x_divide += 1;
179 if (x_divide >= 256) {
180 x_divide = 0xFF;
181 }
182 if (x_divide == 0) {
183 x_divide = 1;
184 }
185 I2S_Config->RATEUP.X = x_divide;
186 I2S_Config->RATEUP.Y = y_divide_up;
187
188 x_divide = ((uint64_t)y_divide_down * (audio_format->SampleRate) * 2 * (audio_format->WordWidth) * N * 2) / pClk;
189 if (x_divide >= 256) {
190 x_divide = 0xFF;
191 }
192 if (x_divide == 0) {
193 x_divide = 1;
194 }
195 I2S_Config->RATEDOWN.X = x_divide;
196 I2S_Config->RATEDOWN.Y = y_divide_down;
197 return SUCCESS;
198 }
199
200 void Audio_Reset_Data_Buffer(void)
201 {
202 audio_buffer_count = 0;
203 audio_buffer_wr_index = 0;
204 audio_buffer_rd_index = 0;
205 }
206
207 uint32_t Audio_Get_ISO_Buffer_Address(uint32_t last_packet_size)
208 {
209 audio_buffer_wr_index += last_packet_size;
210 audio_buffer_count += last_packet_size;
211 if (audio_buffer_count > audio_buffer_size) {
212 Audio_Reset_Data_Buffer();
213 }
214 if (audio_buffer_wr_index >= audio_buffer_size) {
215 memcpy(audio_buffer, &audio_buffer[audio_buffer_size], audio_buffer_wr_index - audio_buffer_size);
216 audio_buffer_wr_index -= audio_buffer_size;
217 }
218 return (uint32_t) &audio_buffer[audio_buffer_wr_index];
219 }
220
221 void Audio_Init(uint32_t samplefreq)
222 {
223 Chip_I2S_Audio_Format_T audio_Confg;
224 audio_Confg.SampleRate = samplefreq;
225 audio_Confg.ChannelNumber = 2; // 1 is mono, 2 is stereo
226 audio_Confg.WordWidth = 16; // 8, 16 or 32 bits
227 Board_Audio_Init(LPC_I2S0, UDA1380_LINE_IN);
228 Chip_I2S_Init(LPC_I2S0);
229 Chip_I2S_Config(LPC_I2S0, I2S_TX_MODE, &audio_Confg);
230 Chip_I2S_Stop(LPC_I2S0, I2S_TX_MODE);
231 Chip_I2S_DisableMute(LPC_I2S0);
232 Chip_I2S_Start(LPC_I2S0, I2S_TX_MODE);
233 Chip_I2S_Int_Cmd(LPC_I2S0, I2S_TX_MODE, ENABLE, 4);
234 NVIC_EnableIRQ(I2S0_IRQn);
235
236 Audio_Reset_Data_Buffer();
237 switch (samplefreq) {
238 case 11025:
239 I2S_SpeedConfig_index = 1;
240 audio_buffer_size = 1764;
241 break;
242 case 22050:
243 I2S_SpeedConfig_index = 3;
244 audio_buffer_size = 1764;
245 break;
246 case 44100:
247 I2S_SpeedConfig_index = 5;
248 audio_buffer_size = 1764;
249 break;
250
251 case 8000:
252 I2S_SpeedConfig_index = 0;
253 audio_buffer_size = samplefreq * 4 * AUDIO_MAX_PC / 1000;
254 break;
255 case 16000:
256 I2S_SpeedConfig_index = 2;
257 audio_buffer_size = samplefreq * 4 * AUDIO_MAX_PC / 1000;
258 break;
259 case 32000:
260 I2S_SpeedConfig_index = 4;
261 audio_buffer_size = samplefreq * 4 * AUDIO_MAX_PC / 1000;
262 break;
263 case 48000:
264 I2S_SpeedConfig_index = 6;
265 default:
266 audio_buffer_size = samplefreq * 4 * AUDIO_MAX_PC / 1000;
267 break;
268 }
269 IP_I2S_SetBitRate(LPC_I2S0, I2S_TX_MODE, I2S_SpeedConfig[I2S_SpeedConfig_index].BITRATE);
270 IP_I2S_SetXYDivider(LPC_I2S0, I2S_TX_MODE,
271 I2S_SpeedConfig[I2S_SpeedConfig_index].RATEDOWN.X,
272 I2S_SpeedConfig[I2S_SpeedConfig_index].RATEDOWN.Y);
273 audio_buffer_size*=2;
274 }
275
276 void Audio_DeInit(void)
277 {
278 Chip_I2S_DeInit(LPC_I2S0);
279 Chip_I2S_Int_Cmd(LPC_I2S0, I2S_TX_MODE, DISABLE, 4);
280 NVIC_DisableIRQ(I2S0_IRQn);
281 }
282
283 void I2S0_IRQHandler(void)
284 {
285 uint32_t txlevel, i;
286 static bool double_speed = false;
287 static uint32_t sample = 0;
288 txlevel = Chip_I2S_GetLevel(LPC_I2S0, I2S_TX_MODE);
289 if (txlevel <= 4) {
290 for (i = 0; i < 8 - txlevel; i++) {
291 if (audio_buffer_count >= 4) { /*has enough data */
292 audio_buffer_count -= 4;
293 sample = *(uint32_t *) (audio_buffer + audio_buffer_rd_index);
294 audio_buffer_rd_index += 4;
295 if (audio_buffer_rd_index >= audio_buffer_size) {
296 audio_buffer_rd_index -= audio_buffer_size;
297 }
298 }
299 Chip_I2S_Send(LPC_I2S0, sample);
300 }
301 /*Skip some samples if buffer run writting too fast. */
302 if(audio_buffer_size != 0)
303 {
304 if(audio_buffer_count >= AUDIO_SPEEP_UP_TRIGGER){
305 if(!double_speed) {
306 IP_I2S_SetXYDivider(LPC_I2S0, I2S_TX_MODE,
307 I2S_SpeedConfig[I2S_SpeedConfig_index].RATEUP.X,
308 I2S_SpeedConfig[I2S_SpeedConfig_index].RATEUP.Y);
309 double_speed = true;
310 }
311 }else if(audio_buffer_count < AUDIO_NORMAL_SPEED_TRIGGER){
312 if(double_speed){
313 IP_I2S_SetXYDivider(LPC_I2S0, I2S_TX_MODE,
314 I2S_SpeedConfig[I2S_SpeedConfig_index].RATEDOWN.X,
315 I2S_SpeedConfig[I2S_SpeedConfig_index].RATEDOWN.Y);
316 double_speed = false;
317 }
318 }
319 }
320 }
321 }
322
325 uint32_t CALLBACK_HAL_GetISOBufferAddress(const uint32_t EPNum, uint32_t *last_packet_size) {
326
327 /* Check if this is audio stream endpoint */
328 if (EPNum == AUDIO_STREAM_EPNUM) {
329 return Audio_Get_ISO_Buffer_Address(*last_packet_size);
330 }
331 else {return 0; }
332 }
333
337 int main(void)
338 {
339 Chip_I2S_Audio_Format_T audio_Confg;
340
341 SetupHardware();
342
343 audio_Confg.ChannelNumber = 2; //stereo
344 audio_Confg.WordWidth = 16; //16 bits
345 /* Build I2S config table */
346 audio_Confg.SampleRate = 8000;
347 I2S_RateFind(LPC_I2S0, &audio_Confg, &I2S_SpeedConfig[0]);
348 audio_Confg.SampleRate = 11025;
349 I2S_RateFind(LPC_I2S0, &audio_Confg, &I2S_SpeedConfig[1]);
350 audio_Confg.SampleRate = 22050;
351 I2S_RateFind(LPC_I2S0, &audio_Confg, &I2S_SpeedConfig[3]);
352 /* Although the founded rate is very accuracy,
353 the XTAL doesn't always match its frequency.
354 Increase the sample rate a little bit will really meet the USB speed. */
355 #if defined(__LPC43XX__ )
356 audio_Confg.SampleRate = 44101; /* a bit higher for 204Mhz device */
357 #else
358 audio_Confg.SampleRate = 44100;
359 #endif
360 I2S_RateFind(LPC_I2S0, &audio_Confg, &I2S_SpeedConfig[5]);
361 #if defined(__LPC43XX__ )
362 audio_Confg.SampleRate = 48001; /* a bit higher for 204Mhz device */
363 #else
364 audio_Confg.SampleRate = 48000;
365 #endif
366 I2S_RateFind(LPC_I2S0, &audio_Confg, &I2S_SpeedConfig[6]);
367
368 #if defined(USB_DEVICE_ROM_DRIVER)
369 UsbdAdc_Init(&Speaker_Audio_Interface);
370 #endif
371
372 for (;; ) {
373 #if !defined(USB_DEVICE_ROM_DRIVER)
374 Audio_Device_USBTask(&Speaker_Audio_Interface);
375 USB_USBTask(Speaker_Audio_Interface.Config.PortNumber,USB_MODE_Device);
376 #endif
377 }
378 }
379
381 void SetupHardware(void)
382 {
383 Board_Init();
384 USB_Init(Speaker_Audio_Interface.Config.PortNumber, USB_MODE_Device);
385 }
386
387 #if !defined(USB_DEVICE_ROM_DRIVER)
388
389 void EVENT_USB_Device_Connect(void)
390 {}
391
393 void EVENT_USB_Device_Disconnect(void)
394 {}
395
397 void EVENT_USB_Device_ConfigurationChanged(void)
398 {
399 bool ConfigSuccess = true;
400
401 ConfigSuccess &= Audio_Device_ConfigureEndpoints(&Speaker_Audio_Interface);
402
403 // LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
404 }
405
407 void EVENT_USB_Device_ControlRequest(void)
408 {
409 Audio_Device_ProcessControlRequest(&Speaker_Audio_Interface);
410 }
411
412 void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t *const AudioInterfaceInfo)
413 {
414 /* reset audio buffer */
415 Audio_Reset_Data_Buffer();
416 }
417
421 bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t *const AudioInterfaceInfo,
422 const uint8_t EndpointProperty,
423 const uint8_t EndpointAddress,
424 const uint8_t EndpointControl,
425 uint16_t *const DataLength,
426 uint8_t *Data)
427 {
428 /* Check the requested endpoint to see if a supported endpoint is being manipulated */
429 if (EndpointAddress == (ENDPOINT_DIR_OUT | Speaker_Audio_Interface.Config.DataOUTEndpointNumber)) {
430 /* Check the requested control to see if a supported control is being manipulated */
431 if (EndpointControl == AUDIO_EPCONTROL_SamplingFreq) {
432 switch (EndpointProperty) {
433 case AUDIO_REQ_SetCurrent:
434 /* Check if we are just testing for a valid property, or actually adjusting it */
435 if (DataLength != NULL) {
436 /* Set the new sampling frequency to the value given by the host */
437 CurrentAudioSampleFrequency =
438 (((uint32_t) Data[2] << 16) | ((uint32_t) Data[1] << 8) | (uint32_t) Data[0]);
439 if (CurrentAudioSampleFrequency > AUDIO_MAX_SAMPLE_FREQ) {
440 return false;
441 }
442 Audio_DeInit();
443 Audio_Init(CurrentAudioSampleFrequency);
444 }
445
446 return true;
447
448 case AUDIO_REQ_GetCurrent:
449 /* Check if we are just testing for a valid property, or actually reading it */
450 if (DataLength != NULL) {
451 *DataLength = 3;
452
453 Data[2] = (CurrentAudioSampleFrequency >> 16);
454 Data[1] = (CurrentAudioSampleFrequency >> 8);
455 Data[0] = (CurrentAudioSampleFrequency & 0xFF);
456 }
457
458 return true;
459 }
460 }
461 }
462
463 return false;
464 }
465
466 #else
467
468 #endif