LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 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 "../AudioInput.h"
34 
35 #if defined(USB_DEVICE_ROM_DRIVER)
36 
37 #include "usbd_adcuser.h"
38 
40 #define AUDIO_MAX_SAMPLE_FREQ 48000
41 
42 /* control interface number */
43 #define USB_ADC_CIF_NUM 0
44 /* streaming interface number */
45 #define USB_ADC_SIF1_NUM 1
46 /* Volume definitions */
47 #define VOLUME_MIN 0x0000
48 #define VOLUME_MAX 0x003F
49 #define VOLUME_RES 0x0001
50 
51 uint32_t ISO_packet_size = 0;
52 uint32_t ISO_buffer_address;
53 
54 /* Device Transfer Descriptor used in Custom ROM mode */
55 DeviceTransferDescriptor Rom_dTD ATTR_ALIGNED(32);
56 /* external Audio Sample Frequency variable */
58 /* Current Volume */
59 uint32_t curr_vol;
60 
61 extern uint32_t CALLBACK_HAL_GetISOBufferAddress(const uint32_t EPNum, uint32_t* last_packet_size);
62 void Audio_Reset_Data_Buffer(void);
63 void Audio_Init (uint32_t samplefreq);
64 /* inline functions */
65 static INLINE DeviceQueueHead* Usbd_GetEpQH(USB_CORE_CTRL_T* pCtrl, uint8_t ep)
66 {
67  DeviceQueueHead* ep_QH = (DeviceQueueHead*)(*((uint32_t*)pCtrl->hw_data));
68  uint32_t ep_idx = (ep & 0x0F) << 1;
69 
70  if(ep & 0x80)
71  ep_idx++;
72 
73  return &ep_QH[ep_idx];
74 }
75 
77 static INLINE uint32_t Usbd_GetTransferSize(USB_CORE_CTRL_T* pCtrl, uint8_t ep)
78 {
79  DeviceQueueHead* ep_QH = Usbd_GetEpQH(pCtrl, ep);
80  return (ep_QH->TransferCount - ep_QH->overlay.TotalBytes);
81 }
82 
83 void Audio_Reset_Data_Buffer(void)
84 {
85 }
86 
87 void Audio_Init (uint32_t samplefreq)
88 {
89 }
90 
91 void UsbdDcdDataTransfer(uint8_t EPNum, uint8_t *pData, uint32_t length)
92 {
93  uint8_t PhyEP = (EPNum<<1) | (EPNum>>7); /* Rotate left without carry */
94  DeviceQueueHead* ep_QH = Usbd_GetEpQH((USB_CORE_CTRL_T*) UsbHandle, EPNum);
95  DeviceTransferDescriptor* pDTD = (DeviceTransferDescriptor*) &Rom_dTD;
96 
97  while ( LPC_USB0->ENDPTSTAT & _BIT( EP_Physical2BitPosition(PhyEP) ) ) /* Endpoint is already primed */
98  {
99  }
100 
101  /* Zero out the device transfer descriptors */
102  memset((void*)pDTD, 0, sizeof(DeviceTransferDescriptor));
103 
104  if(((ENDPTCTRL_REG(PhyEP/2)>>2)&EP_TYPE_MASK)==EP_TYPE_ISOCHRONOUS) // iso out endpoint
105  {
106  uint32_t mult = (USB_DATA_BUFFER_TEM_LENGTH + 1024) / 1024;
107  pDTD->NextTD = LINK_TERMINATE ;
108  ep_QH->Mult = mult;
109  }
110  else if(((ENDPTCTRL_REG(PhyEP/2)>>18)&EP_TYPE_MASK)==EP_TYPE_ISOCHRONOUS)// iso in endpoint
111  {
112 
113  }
114  pDTD->TotalBytes = length;
115  pDTD->IntOnComplete = 1;
116  pDTD->Active = 1;
117  pDTD->MultiplierOverride = 1;
118 
119  pDTD->BufferPage[0] = (uint32_t) pData;
120  pDTD->BufferPage[1] = ((uint32_t) pData + 0x1000) & 0xfffff000;
121  pDTD->BufferPage[2] = ((uint32_t) pData + 0x2000) & 0xfffff000;
122  pDTD->BufferPage[3] = ((uint32_t) pData + 0x3000) & 0xfffff000;
123  pDTD->BufferPage[4] = ((uint32_t) pData + 0x4000) & 0xfffff000;
124 
125  ep_QH->Mult = 1;
126  ep_QH->MaxPacketSize = 512;
127  ep_QH->overlay.NextTD = (uint32_t) pDTD;
128  ep_QH->TransferCount = length;
129 
130  /* prime the endpoint for transmit */
131  LPC_USB0->ENDPTPRIME |= _BIT( EP_Physical2BitPosition(PhyEP) ) ;
132 }
133 
134 
136 void UsbdAdc_Init(void)
137 {
138  uint32_t ep_indx;
139  USBD_API->hw->ForceFullSpeed(UsbHandle,1);
140 
141  /* register ep0 handler */
142  USBD_API->core->RegisterClassHandler(UsbHandle, UsbdAdc_ep0_hdlr, NULL);
143 
144  /* register ISO OUT endpoint interrupt handler */
145  ep_indx = ((AUDIO_STREAM_EPNUM & 0x0F) << 1);
146  USBD_API->core->RegisterEpHandler (UsbHandle, ep_indx, UsbdAdc_ISO_OUT_Hdlr, NULL);
147 
148 }
149 
150 
155 ErrorCode_t ADC_IF_GetRequest (USB_CORE_CTRL_T* pCtrl)
156 {
157 
158  /*
159  Interface = SetupPacket.wIndex.WB.L;
160  EntityID = SetupPacket.wIndex.WB.H;
161  Request = SetupPacket.bRequest;
162  Value = SetupPacket.wValue.W;
163  ...
164  */
166 
167  if (pCtrl->SetupPacket.wIndex.W == 0x0200) {
168  /* Feature Unit: Interface = 0, ID = 2 */
169  if (pCtrl->SetupPacket.wValue.WB.L == 0) {
170  /* Master Channel */
171  switch (pCtrl->SetupPacket.wValue.WB.H) {
172  case AUDIO_MUTE_CONTROL:
173  if (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_GET_CUR) {
174  /*TODO: Get MUTE */
175  //pCtrl->EP0Buf[0] = (ADC_PLAY_MUTE)?1:0;
176  ret = LPC_OK;
177  }
178  break;
180  switch (pCtrl->SetupPacket.bRequest) {
182  *((ATTR_PACKED uint16_t *)pCtrl->EP0Buf) = curr_vol;
183  ret = LPC_OK;
184  break;
186  *((ATTR_PACKED uint16_t *)pCtrl->EP0Buf) = VOLUME_MIN;
187  ret = LPC_OK;
188  break;
190  *((ATTR_PACKED uint16_t *)pCtrl->EP0Buf) = VOLUME_MAX;
191  ret = LPC_OK;
192  break;
194  *((ATTR_PACKED uint16_t *)pCtrl->EP0Buf) = VOLUME_RES;
195  ret = LPC_OK;
196  break;
197  }
198  break;
199  }
200  }
201  }
202 
203  return (ret); /* Not Supported */
204 }
205 
206 
211 ErrorCode_t ADC_IF_SetRequest (USB_CORE_CTRL_T* pCtrl)
212 {
213 
214 /*
215  Interface = SetupPacket.wIndex.WB.L;
216  EntityID = SetupPacket.wIndex.WB.H;
217  Request = SetupPacket.bRequest;
218  Value = SetupPacket.wValue.W;
219  ...
220 */
222  if (pCtrl->SetupPacket.wIndex.W == 0x0200) {
223  /* Feature Unit: Interface = 0, ID = 2 */
224  if ((pCtrl->SetupPacket.wValue.WB.L == 0) &&
225  (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_SET_CUR)) {
226  /* Master Channel */
227  switch (pCtrl->SetupPacket.wValue.WB.H) {
228  case AUDIO_MUTE_CONTROL:
229  if (pCtrl->EP0Buf[0])
230  { /*TODO: set MUTE here */
231  }else
232  { /*TODO: disable MUTE here */
233  }
234  ret = (LPC_OK);
235  break;
237  /*TODO: Set volume here */
238  curr_vol = *((ATTR_PACKED uint16_t *)pCtrl->EP0Buf);
239  ret = (LPC_OK);
240  break;
241  }
242  }
243  }
244 
245  return ret; /* Not Supported */
246 }
247 
248 
253 ErrorCode_t ADC_EP_GetRequest (USB_CORE_CTRL_T* pCtrl)
254 {
255  /*
256  EndPoint = SetupPacket.wIndex.WB.L;
257  Request = SetupPacket.bRequest;
258  Value = SetupPacket.wValue.W;
259  ...
260  */
262 
263  switch(pCtrl->SetupPacket.wIndex.W) {
264  case AUDIO_STREAM_EPNUM:
265  /* Feature Unit: Interface = 0, ID = 2 */
266  if (pCtrl->SetupPacket.wValue.WB.L == 0) {
267  /* Master Channel */
268  if ((pCtrl->SetupPacket.wValue.WB.H == AUDIO_CONTROL_SAMPLING_FREQ) &&
269  (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_GET_CUR) ) {
270  pCtrl->EP0Buf[0] = (uint8_t)(CurrentAudioSampleFrequency & 0xFF);
271  pCtrl->EP0Buf[1] = (uint8_t)((CurrentAudioSampleFrequency >> 8) & 0xFF);
272  pCtrl->EP0Buf[2] = (uint8_t)((CurrentAudioSampleFrequency >> 16) & 0xFF);
273  ret = (LPC_OK);
274  }
275  }
276  break;
277  default:
278  break;
279  }
280  return ret; /* Not Supported */
281 }
282 
283 
288 ErrorCode_t ADC_EP_SetRequest (USB_CORE_CTRL_T* pCtrl)
289 {
290 
291  /*
292  EndPoint = SetupPacket.wIndex.WB.L;
293  Request = SetupPacket.bRequest;
294  Value = SetupPacket.wValue.W;
295  ...
296  */
297  uint32_t rate;
299 
300  switch(pCtrl->SetupPacket.wIndex.W) {
301  case AUDIO_STREAM_EPNUM:
302  /* Feature Unit: Interface = 0, ID = 2 */
303  if (pCtrl->SetupPacket.wValue.WB.L == 0) {
304  /* Master Channel */
305  if (pCtrl->SetupPacket.wValue.WB.H == AUDIO_CONTROL_SAMPLING_FREQ) {
306  rate = pCtrl->EP0Buf[0] | (pCtrl->EP0Buf[1] << 8) | (pCtrl->EP0Buf[2] << 16);
307  if (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_SET_CUR) {
310  {
312  ret = LPC_OK;
313  }
314  }
315  }
316  }
317  break;
318  default:
319  break;
320  }
321  return (ret); /* Not Supported */
322 }
323 
328 {
329  USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
330  uint16_t wIndex = pCtrl->SetupPacket.wIndex.W;
331  uint16_t wValue = pCtrl->SetupPacket.wValue.W;
332 
333  /* write code to enable/disable audo playback when interface
334  ALT setting is changed */
335  if (wIndex == USB_ADC_SIF1_NUM) {
336  if((wValue == 0x0001)){
338  }else
339  {
341  }
342 
343  }
344 
345  return LPC_OK;
346 }
348 ErrorCode_t USB_Configure_Event (USBD_HANDLE_T hUsb)
349 {
350  return LPC_OK;
351 }
355 ErrorCode_t UsbdAdc_ep0_hdlr(USBD_HANDLE_T hUsb, void* data, uint32_t event)
356 {
357  USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
359 
360  if (pCtrl->SetupPacket.bmRequestType.BM.Type == REQUEST_CLASS) {
361  switch (event) {
362  case USB_EVT_SETUP:
363  if ((pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_INTERFACE) &&
364  ((pCtrl->SetupPacket.wIndex.WB.L == USB_ADC_CIF_NUM) || /* IF number correct? */
365  (pCtrl->SetupPacket.wIndex.WB.L == USB_ADC_SIF1_NUM)) ) {
366  switch (pCtrl->SetupPacket.bRequest) {
371 
372  ret = ADC_IF_GetRequest(pCtrl);
373  if (ret == LPC_OK) {
374  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* point to data to be sent */
375  USBD_API->core->DataInStage(pCtrl); /* send requested data */
376  }
377  break;
379  // case AUDIO_REQUEST_SET_MIN:
380  // case AUDIO_REQUEST_SET_MAX:
381  // case AUDIO_REQUEST_SET_RES:
382  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* data to be received */
383 
384  ret = LPC_OK;
385  break;
386  }
387  } else if (pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_ENDPOINT) {
388  switch (pCtrl->SetupPacket.bRequest) {
393  ret = ADC_EP_GetRequest(pCtrl);
394  if (ret == LPC_OK) {
395  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* point to data to be sent */
396  USBD_API->core->DataInStage(pCtrl); /* send requested data */
397  }
398  break;
400  // case AUDIO_REQUEST_SET_MIN:
401  // case AUDIO_REQUEST_SET_MAX:
402  // case AUDIO_REQUEST_SET_RES:
403  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* data to be received */
404  ret = LPC_OK;
405  break;
406  }
407  }
408  break;
409  case USB_EVT_OUT:
410  if ((pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_INTERFACE) &&
411  ((pCtrl->SetupPacket.wIndex.WB.L == USB_ADC_CIF_NUM) || /* IF number correct? */
412  (pCtrl->SetupPacket.wIndex.WB.L == USB_ADC_SIF1_NUM)) ) {
413  switch (pCtrl->SetupPacket.bRequest) {
415  // case AUDIO_REQUEST_SET_MIN:
416  // case AUDIO_REQUEST_SET_MAX:
417  // case AUDIO_REQUEST_SET_RES:
418  ret = ADC_IF_SetRequest(pCtrl);
419  if (ret == LPC_OK) {
420  USBD_API->core->StatusInStage(pCtrl); /* send Acknowledge */
421  }
422  break;
423  }
424  } else if (pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_ENDPOINT) {
425  switch (pCtrl->SetupPacket.bRequest) {
427  // case AUDIO_REQUEST_SET_MIN:
428  // case AUDIO_REQUEST_SET_MAX:
429  // case AUDIO_REQUEST_SET_RES:
430  ret = ADC_EP_SetRequest(pCtrl);
431  if (ret == LPC_OK) {
432  USBD_API->core->StatusInStage(pCtrl); /* send Acknowledge */
433  }
434  break;
435  }
436  }
437  break;
438 
439  default:
440  break;
441  }
442  }
443  return ret;
444 }
445 
449 void UsbdAdc_start_xfr(void)
450 {
451  ISO_packet_size = 0;
452 
453  /* reset audio buffer */
455  ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(AUDIO_STREAM_EPNUM, &ISO_packet_size);
456  UsbdDcdDataTransfer(AUDIO_STREAM_EPNUM, (uint8_t*)ISO_buffer_address, 512);
457 }
458 
462 void UsbdAdc_stop_xfr(void)
463 {
464  ISO_packet_size = 0;
465  /* reset audio buffer */
467  USBD_API->hw->ResetEP(UsbHandle, AUDIO_STREAM_EPNUM);
468 }
469 
470 
474 ErrorCode_t UsbdAdc_ISO_OUT_Hdlr (USBD_HANDLE_T hUsb, void* data, uint32_t event)
475 {
476  if (event == USB_EVT_OUT)
477  {
478  ISO_packet_size = Usbd_GetTransferSize((USB_CORE_CTRL_T*) hUsb, AUDIO_STREAM_EPNUM);
479  if(ISO_packet_size !=0)
480  ISO_packet_size = ISO_packet_size;
481  /* Send DMA request */
482  ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(AUDIO_STREAM_EPNUM, &ISO_packet_size);
483  UsbdDcdDataTransfer(AUDIO_STREAM_EPNUM, (uint8_t*)ISO_buffer_address, 512);
484  }
485 
486  return LPC_OK;
487 }
488 
489 #endif