| 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
usbd_adcuser.c
Go to the documentation of this file.
1 /*
2 * @brief Audio device class ROM based application's specific functions supporting audio class layer
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #define __INCLUDE_FROM_USB_DRIVER
33 #include "../../USBMode.h"
34
35 #if defined(USB_CAN_BE_DEVICE)
36
37 #if defined(USB_DEVICE_ROM_DRIVER) && !(defined(__LPC11U2X_3X__)||defined(__LPC13UXX__))
38 #include "../../../Class/AudioClass.h"
39 #include "usbd_adcuser.h"
40
42 #define AUDIO_MAX_SAMPLE_FREQ 48000
43
44 /* Volume definitions */
45 #define VOLUME_MIN 0x0000
46 #define VOLUME_MAX 0x003F
47 #define VOLUME_RES 0x0001
48
49 uint32_t ISO_packet_size = 0;
50
51 /* Device Transfer Descriptor used in Custom ROM mode */
52 DeviceTransferDescriptor Rom_dTD ATTR_ALIGNED(32);
53 /* external Audio Sample Frequency variable */
54 extern uint32_t CurrentAudioSampleFrequency;
55 /* Current Volume */
56 uint32_t curr_vol;
57 static uint8_t ISOEndpointNumber;
58 static uint8_t StreamInterfaceNumber;
59 static uint8_t ControlInterfaceNumber;
60 static uint8_t USBPort;
61
62 extern uint32_t sample_buffer_size;
63
64 extern uint32_t CALLBACK_HAL_GetISOBufferAddress(const uint32_t EPNum, uint32_t* last_packet_size);
65 extern void Audio_Reset_Data_Buffer(void);
66 extern void Audio_Init (uint32_t samplefreq);
67
68 /* inline functions */
69 static INLINE DeviceQueueHead* Usbd_GetEpQH(USB_CORE_CTRL_T* pCtrl, uint8_t ep)
70 {
71 DeviceQueueHead* ep_QH = (DeviceQueueHead*)(*((uint32_t*)pCtrl->hw_data));
72 uint32_t ep_idx = (ep & 0x0F) << 1;
73
74 if(ep & 0x80)
75 ep_idx++;
76
77 return &ep_QH[ep_idx];
78 }
79
81 static INLINE uint32_t Usbd_GetTransferSize(USB_CORE_CTRL_T *pCtrl, uint8_t ep)
82 {
83 DeviceQueueHead *ep_QH = Usbd_GetEpQH(pCtrl, ep);
84 return ep_QH->TransferCount - ep_QH->overlay.TotalBytes;
85 }
86
87 static void UsbdDcdDataTransfer(uint8_t EPNum, uint8_t *pData, uint32_t length)
88 {
89 uint8_t PhyEP = (EPNum<<1) | (EPNum>>7); /* Rotate left without carry */
90 DeviceQueueHead* ep_QH = Usbd_GetEpQH((USB_CORE_CTRL_T*) UsbHandle, EPNum);
91 DeviceTransferDescriptor* pDTD = (DeviceTransferDescriptor*) &Rom_dTD;
92 IP_USBHS_001_T * USB_Reg;
93 USB_Reg = USB_REG(USBPort);
94
95 while ( USB_Reg->ENDPTSTAT & _BIT( EP_Physical2BitPosition(PhyEP) ) ) /* Endpoint is already primed */
96 {
97 }
98
99 /* Zero out the device transfer descriptors */
100 memset((void*)pDTD, 0, sizeof(DeviceTransferDescriptor));
101
102 if(((ENDPTCTRL_REG(USBPort, PhyEP/2)>>2)&EP_TYPE_MASK)==EP_TYPE_ISOCHRONOUS) // iso out endpoint
103 {
104 uint32_t mult = (USB_DATA_BUFFER_TEM_LENGTH + 1024) / 1024;
105 pDTD->NextTD = LINK_TERMINATE ;
106 ep_QH->Mult = mult;
107 }
108 else if(((ENDPTCTRL_REG(USBPort, PhyEP/2)>>18)&EP_TYPE_MASK)==EP_TYPE_ISOCHRONOUS)// iso in endpoint
109 {
110 uint32_t mult = (USB_DATA_BUFFER_TEM_LENGTH + 1024) / 1024;
111 pDTD->NextTD = LINK_TERMINATE;
112 ep_QH->Mult = mult;
113 }
114 else { // other endpoint types
115 pDTD->NextTD = LINK_TERMINATE; /* The next DTD pointer is INVALID */
116 }
117
118 pDTD->TotalBytes = length;
119 pDTD->IntOnComplete = 1;
120 pDTD->Active = 1;
121 pDTD->MultiplierOverride = 1;
122
123 pDTD->BufferPage[0] = (uint32_t) pData;
124 pDTD->BufferPage[1] = ((uint32_t) pData + 0x1000) & 0xfffff000;
125 pDTD->BufferPage[2] = ((uint32_t) pData + 0x2000) & 0xfffff000;
126 pDTD->BufferPage[3] = ((uint32_t) pData + 0x3000) & 0xfffff000;
127 pDTD->BufferPage[4] = ((uint32_t) pData + 0x4000) & 0xfffff000;
128
129 ep_QH->Mult = 1;
130 ep_QH->MaxPacketSize = 512;
131 ep_QH->overlay.NextTD = (uint32_t) pDTD;
132 ep_QH->TransferCount = length;
133
134 /* prime the endpoint for transmit */
135 USB_Reg->ENDPTPRIME |= _BIT( EP_Physical2BitPosition(PhyEP) ) ;
136 }
137
139 void UsbdAdc_Init(USB_ClassInfo_Audio_Device_t* AudioInterface)
140 {
141 uint32_t ep_indx;
142 USBD_API->hw->ForceFullSpeed(UsbHandle,1);
143
144 /* register ep0 handler */
145 USBD_API->core->RegisterClassHandler(UsbHandle, UsbdAdc_ep0_hdlr, NULL);
146
147 StreamInterfaceNumber = AudioInterface->Config.StreamingInterfaceNumber;
148 ControlInterfaceNumber = AudioInterface->Config.ControlInterfaceNumber;
149 USBPort = AudioInterface->Config.PortNumber;
150 /* register ISO OUT endpoint interrupt handler */
151 if(AudioInterface->Config.DataOUTEndpointNumber)
152 {
153 ISOEndpointNumber = AudioInterface->Config.DataOUTEndpointNumber;
154 ep_indx = ((ISOEndpointNumber & 0x0F) << 1);
155 USBD_API->core->RegisterEpHandler (UsbHandle, ep_indx, UsbdAdc_ISO_Hdlr, NULL);
156 }
157 else if(AudioInterface->Config.DataINEndpointNumber)
158 {
159 ISOEndpointNumber = AudioInterface->Config.DataINEndpointNumber;
160 ep_indx = ((ISOEndpointNumber & 0x0F) << 1) + 1;
161 USBD_API->core->RegisterEpHandler (UsbHandle, ep_indx, UsbdAdc_ISO_Hdlr, NULL);
162 }
163
164 }
165
170 ErrorCode_t ADC_IF_GetRequest (USB_CORE_CTRL_T* pCtrl)
171 {
172
173 /*
174 Interface = SetupPacket.wIndex.WB.L;
175 EntityID = SetupPacket.wIndex.WB.H;
176 Request = SetupPacket.bRequest;
177 Value = SetupPacket.wValue.W;
178 ...
179 */
180 ErrorCode_t ret = ERR_USBD_INVALID_REQ;
181
182 if (pCtrl->SetupPacket.wIndex.W == 0x0200) {
183 /* Feature Unit: Interface = 0, ID = 2 */
184 if (pCtrl->SetupPacket.wValue.WB.L == 0) {
185 /* Master Channel */
186 switch (pCtrl->SetupPacket.wValue.WB.H) {
187 case AUDIO_MUTE_CONTROL:
188 if (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_GET_CUR) {
189 /*TODO: Get MUTE */
190 //pCtrl->EP0Buf[0] = (ADC_PLAY_MUTE)?1:0;
191 ret = LPC_OK;
192 }
193 break;
194 case AUDIO_VOLUME_CONTROL:
195 switch (pCtrl->SetupPacket.bRequest) {
196 case AUDIO_REQUEST_GET_CUR:
197 *((uint16_t *)pCtrl->EP0Buf) = curr_vol;
198 ret = LPC_OK;
199 break;
200 case AUDIO_REQUEST_GET_MIN:
201 *((uint16_t *)pCtrl->EP0Buf) = VOLUME_MIN;
202 ret = LPC_OK;
203 break;
204 case AUDIO_REQUEST_GET_MAX:
205 *((uint16_t *)pCtrl->EP0Buf) = VOLUME_MAX;
206 ret = LPC_OK;
207 break;
208 case AUDIO_REQUEST_GET_RES:
209 *((uint16_t *)pCtrl->EP0Buf) = VOLUME_RES;
210 ret = LPC_OK;
211 break;
212 }
213 break;
214 }
215 }
216 }
217
218 return (ret); /* Not Supported */
219 }
220
221
226 ErrorCode_t ADC_IF_SetRequest (USB_CORE_CTRL_T* pCtrl)
227 {
228
229 /*
230 Interface = SetupPacket.wIndex.WB.L;
231 EntityID = SetupPacket.wIndex.WB.H;
232 Request = SetupPacket.bRequest;
233 Value = SetupPacket.wValue.W;
234 ...
235 */
236 ErrorCode_t ret = ERR_USBD_INVALID_REQ;
237 if (pCtrl->SetupPacket.wIndex.W == 0x0200) {
238 /* Feature Unit: Interface = 0, ID = 2 */
239 if ((pCtrl->SetupPacket.wValue.WB.L == 0) &&
240 (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_SET_CUR)) {
241 /* Master Channel */
242 switch (pCtrl->SetupPacket.wValue.WB.H) {
243 case AUDIO_MUTE_CONTROL:
244 if (pCtrl->EP0Buf[0])
245 { /*TODO: set MUTE here */
246 }else
247 { /*TODO: disable MUTE here */
248 }
249 ret = (LPC_OK);
250 break;
251 case AUDIO_VOLUME_CONTROL:
252 /*TODO: Set volume here */
253 curr_vol = *((uint16_t *)pCtrl->EP0Buf);
254 ret = (LPC_OK);
255 break;
256 }
257 }
258 }
259
260 return ret; /* Not Supported */
261 }
262
263
268 ErrorCode_t ADC_EP_GetRequest (USB_CORE_CTRL_T* pCtrl)
269 {
270 /*
271 EndPoint = SetupPacket.wIndex.WB.L;
272 Request = SetupPacket.bRequest;
273 Value = SetupPacket.wValue.W;
274 ...
275 */
276 ErrorCode_t ret = ERR_USBD_INVALID_REQ;
277
278 if((pCtrl->SetupPacket.wIndex.W & 0x7F) == ISOEndpointNumber) {
279 /* Feature Unit: Interface = 0, ID = 2 */
280 if (pCtrl->SetupPacket.wValue.WB.L == 0) {
281 /* Master Channel */
282 if ((pCtrl->SetupPacket.wValue.WB.H == AUDIO_CONTROL_SAMPLING_FREQ) &&
283 (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_GET_CUR) ) {
284 pCtrl->EP0Buf[0] = (uint8_t)(CurrentAudioSampleFrequency & 0xFF);
285 pCtrl->EP0Buf[1] = (uint8_t)((CurrentAudioSampleFrequency >> 8) & 0xFF);
286 pCtrl->EP0Buf[2] = (uint8_t)((CurrentAudioSampleFrequency >> 16) & 0xFF);
287 ret = (LPC_OK);
288 }
289 }
290 }
291 return ret; /* Not Supported */
292 }
293
294
299 ErrorCode_t ADC_EP_SetRequest (USB_CORE_CTRL_T* pCtrl)
300 {
301
302 /*
303 EndPoint = SetupPacket.wIndex.WB.L;
304 Request = SetupPacket.bRequest;
305 Value = SetupPacket.wValue.W;
306 ...
307 */
308 uint32_t rate;
309 ErrorCode_t ret = ERR_USBD_INVALID_REQ;
310
311 if((pCtrl->SetupPacket.wIndex.W & 0x7F) == ISOEndpointNumber) {
312 /* Feature Unit: Interface = 0, ID = 2 */
313 if (pCtrl->SetupPacket.wValue.WB.L == 0) {
314 /* Master Channel */
315 if (pCtrl->SetupPacket.wValue.WB.H == AUDIO_CONTROL_SAMPLING_FREQ) {
316 rate = pCtrl->EP0Buf[0] | (pCtrl->EP0Buf[1] << 8) | (pCtrl->EP0Buf[2] << 16);
317 if (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_SET_CUR) {
318 CurrentAudioSampleFrequency = rate;
319 if(CurrentAudioSampleFrequency <= AUDIO_MAX_SAMPLE_FREQ)
320 {
321 Audio_Init(CurrentAudioSampleFrequency);
322 ret = LPC_OK;
323 }
324 }
325 }
326 }
327 }
328 return (ret); /* Not Supported */
329 }
330
334 ErrorCode_t USB_Interface_Event (USBD_HANDLE_T hUsb)
335 {
336 USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
337 uint16_t wIndex = pCtrl->SetupPacket.wIndex.W;
338 uint16_t wValue = pCtrl->SetupPacket.wValue.W;
339
340 /* write code to enable/disable audo playback when interface
341 ALT setting is changed */
342 if (wIndex == StreamInterfaceNumber) {
343 if((wValue == 0x0001)){
344 UsbdAdc_start_xfr();
345 }else
346 {
347 UsbdAdc_stop_xfr();
348 }
349
350 }
351
352 return LPC_OK;
353 }
355 ErrorCode_t USB_Configure_Event (USBD_HANDLE_T hUsb)
356 {
357 return LPC_OK;
358 }
359
360 #if defined(__ICCARM__)
361 /* Temp fix for IAR */
362 uint32_t TransferDelayidx=0;
363 volatile uint8_t Event_store[128];
364 #endif
365
369 ErrorCode_t UsbdAdc_ep0_hdlr(USBD_HANDLE_T hUsb, void* data, uint32_t event)
370 {
371 USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
372 ErrorCode_t ret = ERR_USBD_UNHANDLED;
373
374 #if defined(__ICCARM__)
375 /* Temp fix for IAR */
376 Event_store[TransferDelayidx] = event;
377 #endif
378
379 if (pCtrl->SetupPacket.bmRequestType.BM.Type == REQUEST_CLASS) {
380 switch (event) {
381 case USB_EVT_SETUP:
382 if ((pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_INTERFACE) &&
383 ((pCtrl->SetupPacket.wIndex.WB.L == ControlInterfaceNumber) || /* IF number correct? */
384 (pCtrl->SetupPacket.wIndex.WB.L == StreamInterfaceNumber)) ) {
385 switch (pCtrl->SetupPacket.bRequest) {
386 case AUDIO_REQUEST_GET_CUR:
387 case AUDIO_REQUEST_GET_MIN:
388 case AUDIO_REQUEST_GET_MAX:
389 case AUDIO_REQUEST_GET_RES:
390
391 ret = ADC_IF_GetRequest(pCtrl);
392 if (ret == LPC_OK) {
393 pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* point to data to be sent */
394 USBD_API->core->DataInStage(pCtrl); /* send requested data */
395 }
396 break;
397 case AUDIO_REQUEST_SET_CUR:
398 // case AUDIO_REQUEST_SET_MIN:
399 // case AUDIO_REQUEST_SET_MAX:
400 // case AUDIO_REQUEST_SET_RES:
401 pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* data to be received */
402
403 ret = LPC_OK;
404 break;
405 }
406 }
407 else if (pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_ENDPOINT) {
408 switch (pCtrl->SetupPacket.bRequest) {
409 case AUDIO_REQUEST_GET_CUR:
410 case AUDIO_REQUEST_GET_MIN:
411 case AUDIO_REQUEST_GET_MAX:
412 case AUDIO_REQUEST_GET_RES:
413 ret = ADC_EP_GetRequest(pCtrl);
414 if (ret == LPC_OK) {
415 pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* point to data to be sent */
416 USBD_API->core->DataInStage(pCtrl); /* send requested data */
417 }
418 break;
419 case AUDIO_REQUEST_SET_CUR:
420 // case AUDIO_REQUEST_SET_MIN:
421 // case AUDIO_REQUEST_SET_MAX:
422 // case AUDIO_REQUEST_SET_RES:
423 pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* data to be received */
424 ret = LPC_OK;
425 break;
426 }
427 }
428 break;
429 case USB_EVT_OUT:
430 if ((pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_INTERFACE) &&
431 ((pCtrl->SetupPacket.wIndex.WB.L == ControlInterfaceNumber) || /* IF number correct? */
432 (pCtrl->SetupPacket.wIndex.WB.L == StreamInterfaceNumber)) ) {
433 switch (pCtrl->SetupPacket.bRequest) {
434 case AUDIO_REQUEST_SET_CUR:
435 // case AUDIO_REQUEST_SET_MIN:
436 // case AUDIO_REQUEST_SET_MAX:
437 // case AUDIO_REQUEST_SET_RES:
438 ret = ADC_IF_SetRequest(pCtrl);
439 if (ret == LPC_OK) {
440 USBD_API->core->StatusInStage(pCtrl); /* send Acknowledge */
441 }
442 break;
443 }
444 } else if (pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_ENDPOINT) {
445 switch (pCtrl->SetupPacket.bRequest) {
446 case AUDIO_REQUEST_SET_CUR:
447 // case AUDIO_REQUEST_SET_MIN:
448 // case AUDIO_REQUEST_SET_MAX:
449 // case AUDIO_REQUEST_SET_RES:
450 ret = ADC_EP_SetRequest(pCtrl);
451 if (ret == LPC_OK) {
452 USBD_API->core->StatusInStage(pCtrl); /* send Acknowledge */
453 }
454 break;
455 }
456 }
457 break;
458
459 default:
460 break;
461 }
462 }
463 return ret;
464 }
465
469 void UsbdAdc_start_xfr(void)
470 {
471 ISO_packet_size = 0;
472 uint32_t ISO_buffer_address;
473 /* reset audio buffer */
474 Audio_Reset_Data_Buffer();
475 ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(USB_ENDPOINT_IN(ISOEndpointNumber), &ISO_packet_size);
476 if(ISO_buffer_address != 0)
477 UsbdDcdDataTransfer(USB_ENDPOINT_IN(ISOEndpointNumber), (uint8_t*)ISO_buffer_address, ISO_packet_size);
478
479 ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(ISOEndpointNumber, &ISO_packet_size);
480 if(ISO_buffer_address != 0)
481 UsbdDcdDataTransfer(ISOEndpointNumber, (uint8_t*)ISO_buffer_address, 512);
482 }
483
487 void UsbdAdc_stop_xfr(void)
488 {
489 ISO_packet_size = 0;
490 /* reset audio buffer */
491 Audio_Reset_Data_Buffer();
492 USBD_API->hw->ResetEP(UsbHandle, ISOEndpointNumber);
493 USBD_API->hw->ResetEP(UsbHandle, USB_ENDPOINT_IN(ISOEndpointNumber));
494 }
495
496
500 ErrorCode_t UsbdAdc_ISO_Hdlr (USBD_HANDLE_T hUsb, void* data, uint32_t event)
501 {
502 uint32_t ISO_buffer_address;
503
504 if (event == USB_EVT_OUT) {
505 ISO_packet_size = Usbd_GetTransferSize((USB_CORE_CTRL_T *) hUsb, ISOEndpointNumber);
506 if (ISO_packet_size != 0) {
507 ISO_packet_size = ISO_packet_size;
508 }
509 /* Send DMA request */
510 ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(ISOEndpointNumber, &ISO_packet_size);
511 UsbdDcdDataTransfer(ISOEndpointNumber, (uint8_t *) ISO_buffer_address, 512);
512 }
513
514 if (event == USB_EVT_IN)
515 {
516 /* Send DMA request */
517 ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(USB_ENDPOINT_IN(ISOEndpointNumber), &ISO_packet_size);
518 UsbdDcdDataTransfer(USB_ENDPOINT_IN(ISOEndpointNumber), (uint8_t*)ISO_buffer_address, ISO_packet_size);
519 }
520
521 return LPC_OK;
522 }
523
524 #endif
525 #endif