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 "../AudioOutput.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 
57 /* external Audio Sample Frequency variable */
59 /* Current Volume */
60 uint32_t curr_vol;
61 
62 extern uint32_t CALLBACK_HAL_GetISOBufferAddress(const uint32_t EPNum, uint32_t *last_packet_size);
63 
64 extern void Audio_Reset_Data_Buffer(void);
65 
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 
78  return &ep_QH[ep_idx];
79 }
80 
82 static INLINE uint32_t Usbd_GetTransferSize(USB_CORE_CTRL_T *pCtrl, uint8_t ep)
83 {
84  DeviceQueueHead *ep_QH = Usbd_GetEpQH(pCtrl, ep);
85  return ep_QH->TransferCount - ep_QH->overlay.TotalBytes;
86 }
87 
88 void UsbdDcdDataTransfer(uint8_t EPNum, uint8_t *pData, uint32_t length)
89 {
90  uint8_t PhyEP = (EPNum << 1) | (EPNum >> 7);/* Rotate left without carry */
91  DeviceQueueHead *ep_QH = Usbd_GetEpQH((USB_CORE_CTRL_T *) UsbHandle, EPNum);
92  DeviceTransferDescriptor *pDTD = (DeviceTransferDescriptor *) &Rom_dTD;
93 
94  while ( LPC_USB0->ENDPTSTAT & _BIT(EP_Physical2BitPosition(PhyEP) ) ) { /* Endpoint is already primed */
95  }
96 
97  /* Zero out the device transfer descriptors */
98  memset((void *) pDTD, 0, sizeof(DeviceTransferDescriptor));
99 
100  if (((ENDPTCTRL_REG(PhyEP / 2) >> 2) & EP_TYPE_MASK) == EP_TYPE_ISOCHRONOUS) { // iso out endpoint
101  uint32_t mult = (USB_DATA_BUFFER_TEM_LENGTH + 1024) / 1024;
102  pDTD->NextTD = LINK_TERMINATE;
103  ep_QH->Mult = mult;
104  }
105  else if (((ENDPTCTRL_REG(PhyEP / 2) >> 18) & EP_TYPE_MASK) == EP_TYPE_ISOCHRONOUS) {// iso in endpoint
106 
107  }
108  pDTD->TotalBytes = length;
109  pDTD->IntOnComplete = 1;
110  pDTD->Active = 1;
111  pDTD->MultiplierOverride = 1;
112 
113  pDTD->BufferPage[0] = (uint32_t) pData;
114  pDTD->BufferPage[1] = ((uint32_t) pData + 0x1000) & 0xfffff000;
115  pDTD->BufferPage[2] = ((uint32_t) pData + 0x2000) & 0xfffff000;
116  pDTD->BufferPage[3] = ((uint32_t) pData + 0x3000) & 0xfffff000;
117  pDTD->BufferPage[4] = ((uint32_t) pData + 0x4000) & 0xfffff000;
118 
119  ep_QH->Mult = 1;
120  ep_QH->MaxPacketSize = 512;
121  ep_QH->overlay.NextTD = (uint32_t) pDTD;
122  ep_QH->TransferCount = length;
123 
124  /* prime the endpoint for transmit */
125  LPC_USB0->ENDPTPRIME |= _BIT(EP_Physical2BitPosition(PhyEP) );
126 }
127 
129 void UsbdAdc_Init(void)
130 {
131  uint32_t ep_indx;
132  USBD_API->hw->ForceFullSpeed(UsbHandle, 1);
133 
134  /* register ep0 handler */
135  USBD_API->core->RegisterClassHandler(UsbHandle, UsbdAdc_ep0_hdlr, NULL);
136 
137  /* register ISO OUT endpoint interrupt handler */
138  ep_indx = ((AUDIO_STREAM_EPNUM & 0x0F) << 1);
139  USBD_API->core->RegisterEpHandler(UsbHandle, ep_indx, UsbdAdc_ISO_OUT_Hdlr, NULL);
140 
141 }
142 
147 ErrorCode_t ADC_IF_GetRequest(USB_CORE_CTRL_T *pCtrl)
148 {
149 
150  /*
151  Interface = SetupPacket.wIndex.WB.L;
152  EntityID = SetupPacket.wIndex.WB.H;
153  Request = SetupPacket.bRequest;
154  Value = SetupPacket.wValue.W;
155  ...
156  */
158 
159  if (pCtrl->SetupPacket.wIndex.W == 0x0200) {
160  /* Feature Unit: Interface = 0, ID = 2 */
161  if (pCtrl->SetupPacket.wValue.WB.L == 0) {
162  /* Master Channel */
163  switch (pCtrl->SetupPacket.wValue.WB.H) {
164  case AUDIO_MUTE_CONTROL:
165  if (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_GET_CUR) {
166  /*TODO: Get MUTE */
167  // pCtrl->EP0Buf[0] = (ADC_PLAY_MUTE)?1:0;
168  ret = LPC_OK;
169  }
170  break;
171 
173  switch (pCtrl->SetupPacket.bRequest) {
175  *((ATTR_PACKED uint16_t *) pCtrl->EP0Buf) = curr_vol;
176  ret = LPC_OK;
177  break;
178 
180  *((ATTR_PACKED uint16_t *) pCtrl->EP0Buf) = VOLUME_MIN;
181  ret = LPC_OK;
182  break;
183 
185  *((ATTR_PACKED uint16_t *) pCtrl->EP0Buf) = VOLUME_MAX;
186  ret = LPC_OK;
187  break;
188 
190  *((ATTR_PACKED uint16_t *) pCtrl->EP0Buf) = VOLUME_RES;
191  ret = LPC_OK;
192  break;
193  }
194  break;
195  }
196  }
197  }
198 
199  return ret; /* Not Supported */
200 }
201 
206 ErrorCode_t ADC_IF_SetRequest(USB_CORE_CTRL_T *pCtrl)
207 {
208 
209  /*
210  Interface = SetupPacket.wIndex.WB.L;
211  EntityID = SetupPacket.wIndex.WB.H;
212  Request = SetupPacket.bRequest;
213  Value = SetupPacket.wValue.W;
214  ...
215  */
217  if (pCtrl->SetupPacket.wIndex.W == 0x0200) {
218  /* Feature Unit: Interface = 0, ID = 2 */
219  if ((pCtrl->SetupPacket.wValue.WB.L == 0) &&
220  (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_SET_CUR)) {
221  /* Master Channel */
222  switch (pCtrl->SetupPacket.wValue.WB.H) {
223  case AUDIO_MUTE_CONTROL:
224  if (pCtrl->EP0Buf[0]) { /*TODO: set MUTE here */
225  }
226  else { /*TODO: disable MUTE here */
227  }
228  ret = (LPC_OK);
229  break;
230 
232  /*TODO: Set volume here */
233  curr_vol = *((ATTR_PACKED uint16_t *) pCtrl->EP0Buf);
234  ret = (LPC_OK);
235  break;
236  }
237  }
238  }
239 
240  return ret; /* Not Supported */
241 }
242 
247 ErrorCode_t ADC_EP_GetRequest(USB_CORE_CTRL_T *pCtrl)
248 {
249  /*
250  EndPoint = SetupPacket.wIndex.WB.L;
251  Request = SetupPacket.bRequest;
252  Value = SetupPacket.wValue.W;
253  ...
254  */
256 
257  switch (pCtrl->SetupPacket.wIndex.W) {
258  case AUDIO_STREAM_EPNUM:
259  /* Feature Unit: Interface = 0, ID = 2 */
260  if (pCtrl->SetupPacket.wValue.WB.L == 0) {
261  /* Master Channel */
262  if ((pCtrl->SetupPacket.wValue.WB.H == AUDIO_CONTROL_SAMPLING_FREQ) &&
263  (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_GET_CUR) ) {
264  pCtrl->EP0Buf[0] = (uint8_t) (CurrentAudioSampleFrequency & 0xFF);
265  pCtrl->EP0Buf[1] = (uint8_t) ((CurrentAudioSampleFrequency >> 8) & 0xFF);
266  pCtrl->EP0Buf[2] = (uint8_t) ((CurrentAudioSampleFrequency >> 16) & 0xFF);
267  ret = (LPC_OK);
268  }
269  }
270  break;
271 
272  default:
273  break;
274  }
275  return ret; /* Not Supported */
276 }
277 
282 ErrorCode_t ADC_EP_SetRequest(USB_CORE_CTRL_T *pCtrl)
283 {
284 
285  /*
286  EndPoint = SetupPacket.wIndex.WB.L;
287  Request = SetupPacket.bRequest;
288  Value = SetupPacket.wValue.W;
289  ...
290  */
291  uint32_t rate;
293 
294  switch (pCtrl->SetupPacket.wIndex.W) {
295  case AUDIO_STREAM_EPNUM:
296  /* Feature Unit: Interface = 0, ID = 2 */
297  if (pCtrl->SetupPacket.wValue.WB.L == 0) {
298  /* Master Channel */
299  if (pCtrl->SetupPacket.wValue.WB.H == AUDIO_CONTROL_SAMPLING_FREQ) {
300  rate = pCtrl->EP0Buf[0] | (pCtrl->EP0Buf[1] << 8) | (pCtrl->EP0Buf[2] << 16);
301  if (pCtrl->SetupPacket.bRequest == AUDIO_REQUEST_SET_CUR) {
305  ret = LPC_OK;
306  }
307  }
308  }
309  }
310  break;
311 
312  default:
313  break;
314  }
315  return ret; /* Not Supported */
316 }
317 
322 {
323  USB_CORE_CTRL_T *pCtrl = (USB_CORE_CTRL_T *) hUsb;
324  uint16_t wIndex = pCtrl->SetupPacket.wIndex.W;
325  uint16_t wValue = pCtrl->SetupPacket.wValue.W;
326 
327  /* write code to enable/disable audo playback when interface
328  ALT setting is changed */
329  if (wIndex == USB_ADC_SIF1_NUM) {
330  if ((wValue == 0x0001)) {
332  }
333  else {
335  }
336 
337  }
338 
339  return LPC_OK;
340 }
341 
343 ErrorCode_t USB_Configure_Event(USBD_HANDLE_T hUsb)
344 {
345  return LPC_OK;
346 }
347 
351 ErrorCode_t UsbdAdc_ep0_hdlr(USBD_HANDLE_T hUsb, void *data, uint32_t event)
352 {
353  USB_CORE_CTRL_T *pCtrl = (USB_CORE_CTRL_T *) hUsb;
355 
356  if (pCtrl->SetupPacket.bmRequestType.BM.Type == REQUEST_CLASS) {
357  switch (event) {
358  case USB_EVT_SETUP:
359  if ((pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_INTERFACE) &&
360  ((pCtrl->SetupPacket.wIndex.WB.L == USB_ADC_CIF_NUM) || /* IF number correct? */
361  (pCtrl->SetupPacket.wIndex.WB.L == USB_ADC_SIF1_NUM)) ) {
362  switch (pCtrl->SetupPacket.bRequest) {
367 
368  ret = ADC_IF_GetRequest(pCtrl);
369  if (ret == LPC_OK) {
370  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* point to data to be sent */
371  USBD_API->core->DataInStage(pCtrl); /* send requested data */
372  }
373  break;
374 
376  // case AUDIO_REQUEST_SET_MIN:
377  // case AUDIO_REQUEST_SET_MAX:
378  // case AUDIO_REQUEST_SET_RES:
379  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* data to be received */
380 
381  ret = LPC_OK;
382  break;
383  }
384  }
385  else if (pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_ENDPOINT) {
386  switch (pCtrl->SetupPacket.bRequest) {
391  ret = ADC_EP_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 
399  // case AUDIO_REQUEST_SET_MIN:
400  // case AUDIO_REQUEST_SET_MAX:
401  // case AUDIO_REQUEST_SET_RES:
402  pCtrl->EP0Data.pData = pCtrl->EP0Buf; /* data to be received */
403  ret = LPC_OK;
404  break;
405  }
406  }
407  break;
408 
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  }
425  else if (pCtrl->SetupPacket.bmRequestType.BM.Recipient == REQUEST_TO_ENDPOINT) {
426  switch (pCtrl->SetupPacket.bRequest) {
428  // case AUDIO_REQUEST_SET_MIN:
429  // case AUDIO_REQUEST_SET_MAX:
430  // case AUDIO_REQUEST_SET_RES:
431  ret = ADC_EP_SetRequest(pCtrl);
432  if (ret == LPC_OK) {
433  USBD_API->core->StatusInStage(pCtrl); /* send Acknowledge */
434  }
435  break;
436  }
437  }
438  break;
439 
440  default:
441  break;
442  }
443  }
444  return ret;
445 }
446 
450 void UsbdAdc_start_xfr(void)
451 {
452  ISO_packet_size = 0;
453 
454  /* reset audio buffer */
456  ISO_buffer_address = CALLBACK_HAL_GetISOBufferAddress(AUDIO_STREAM_EPNUM, &ISO_packet_size);
457  UsbdDcdDataTransfer(AUDIO_STREAM_EPNUM, (uint8_t *) ISO_buffer_address, 512);
458 }
459 
463 void UsbdAdc_stop_xfr(void)
464 {
465  ISO_packet_size = 0;
466  /* reset audio buffer */
468  USBD_API->hw->ResetEP(UsbHandle, AUDIO_STREAM_EPNUM);
469 }
470 
475 {
476  if (event == USB_EVT_OUT) {
477  ISO_packet_size = Usbd_GetTransferSize((USB_CORE_CTRL_T *) hUsb, AUDIO_STREAM_EPNUM);
478  if (ISO_packet_size != 0) {
479  ISO_packet_size = ISO_packet_size;
480  }
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