00001 /* ---------------------------------------------------------------------------- */ 00002 /* Atmel Microcontroller Software Support */ 00003 /* SAM Software Package License */ 00004 /* ---------------------------------------------------------------------------- */ 00005 /* Copyright (c) 2015, Atmel Corporation */ 00006 /* */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without */ 00010 /* modification, are permitted provided that the following condition is met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, */ 00013 /* this list of conditions and the disclaimer below. */ 00014 /* */ 00015 /* Atmel's name may not be used to endorse or promote products derived from */ 00016 /* this software without specific prior written permission. */ 00017 /* */ 00018 /* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ 00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ 00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ 00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ 00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ 00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ 00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ 00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00028 /* ---------------------------------------------------------------------------- */ 00029 00030 /** \cond usb_audio_looprec 00031 * \page usb_audio_looprec USB Audio Loopback-Recorder Example 00032 * 00033 * \section Purpose 00034 * 00035 * The USB Audio Loopback-Recorder Example will help you to get 00036 * familiar with the USB Device Port(UDP) and DACC on SAMV7/E7 micro-controllers. 00037 * Also it can help you to be familiar with the USB Framework that is used for 00038 * rapid development of USB-compliant class drivers such as USB Audio Device 00039 * class. 00040 * 00041 * \section Requirements 00042 * 00043 * This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board 00044 * those have both UDP. 00045 * 00046 * \section Description 00047 * 00048 * The demo simulates an USB Desktop Speaker with Microphone which actually 00049 * does not "speak out" but loop back the sound as microphone input. 00050 * 00051 * When an Xplained board running this program connected to a host (PC for 00052 * example), with USB cable, the Xplained board appears as a desktop speaker 00053 * for the host. Then the host can play sound through host software. The audio 00054 * stream from the host is then sent to the Xplained board. At the same time, 00055 * the audio stream received is also sent back to host from Xplained board for 00056 * recording. 00057 * 00058 * \section Usage 00059 * 00060 * -# Build the program and download it inside the board. 00061 * Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf 00062 * -# On the computer, open and configure a terminal application 00063 * (e.g. HyperTerminal on Microsoft Windows) with these settings: 00064 * - 115200 bauds 00065 * - 8 bits of data 00066 * - No parity 00067 * - 1 stop bit 00068 * - No flow control 00069 * -# Start the application. 00070 * -# In the terminal window, the following text should appear: 00071 * \code 00072 * -- USB Device Audio LoopREC Example xxx -- 00073 * -- SAMxxxxx-xx 00074 * -- Compiled: xxx xx xxxx xx:xx:xx -- 00075 * \endcode 00076 * -# When connecting USB cable to windows, the host reports a new USB device 00077 * attachment (if it's the first time you connect an audio speaker demo board to 00078 * your host). 00079 * You can find new "USB Composite Device" and "USB Audio Device" appear in the 00080 * hardware device list. 00081 * -# You can play sound in host side through the USB Audio Device. 00082 * When playing sound, you can also record through the USB Audio Device on 00083 * the host. 00084 * 00085 * \section References 00086 * - usb_audio_looprec/main.c 00087 * - ssc: SSC interface driver 00088 * - usb: USB Framework, Audio Device Class driver and UDP interface driver 00089 * - \ref usbd_framework 00090 * - \ref usbd_api 00091 * - \ref usbd_audio_rec_drv 00092 * 00093 */ 00094 00095 /** 00096 * \file 00097 * 00098 * This file contains all the specific code for the 00099 * usb_audio_looprec example. 00100 */ 00101 00102 /*---------------------------------------------------------------------------- 00103 * Headers 00104 *----------------------------------------------------------------------------*/ 00105 00106 #include "board.h" 00107 00108 #include "USBD_LEDs.h" 00109 #include "USBD_Config.h" 00110 00111 #include "AUDDSpeakerPhoneDriver.h" 00112 00113 #include <stdio.h> 00114 #include <stdbool.h> 00115 #include <stdint.h> 00116 00117 /*---------------------------------------------------------------------------- 00118 * Definitions 00119 *----------------------------------------------------------------------------*/ 00120 00121 /** Number of available audio buffers. */ 00122 #define BUFFER_NUMBER 8 00123 /** Size of one buffer in bytes. */ 00124 #define BUFFER_SIZE (AUDDevice_BYTESPERFRAME \ 00125 + AUDDevice_BYTESPERSUBFRAME) 00126 00127 /*---------------------------------------------------------------------------- 00128 * External variables 00129 *----------------------------------------------------------------------------*/ 00130 00131 /** Descriptor list for USB Audio SpeakerPhone Driver */ 00132 extern const USBDDriverDescriptors auddSpeakerPhoneDriverDescriptors; 00133 00134 /*---------------------------------------------------------------------------- 00135 * Internal variables 00136 *----------------------------------------------------------------------------*/ 00137 00138 /** Data buffers for receiving audio frames from the USB host. */ 00139 COMPILER_ALIGNED(32) static uint8_t buffers[BUFFER_NUMBER][BUFFER_SIZE]; 00140 /** Number of samples stored in each data buffer. */ 00141 //static uint32_t bufferSizes[BUFFER_NUMBER]; 00142 /** Next buffer in which USB data can be stored. */ 00143 static uint32_t inBufferIndex = 0; 00144 /** Number of buffers that can be sent to the DAC. */ 00145 static volatile uint32_t numBuffersToSend = 0; 00146 00147 /** Current state of the playback stream interface. */ 00148 static volatile uint8_t isPlyActive = 0; 00149 /** Current state of the record stream interface. */ 00150 static volatile uint8_t isRecActive = 0; 00151 00152 00153 /*---------------------------------------------------------------------------- 00154 * Internal functions 00155 *----------------------------------------------------------------------------*/ 00156 00157 /** 00158 * Invoked when a frame has been received. 00159 */ 00160 static void FrameReceived(uint32_t unused, 00161 uint8_t status, 00162 uint32_t transferred, 00163 uint32_t remaining) 00164 { 00165 unused = unused; /* dummy */ 00166 transferred = transferred; 00167 remaining = remaining; /* dummy */ 00168 00169 if (status == USBD_STATUS_SUCCESS) { 00170 /* Loopback! add this buffer to write list */ 00171 if (!isRecActive) {} 00172 else { 00173 AUDDSpeakerPhoneDriver_Write(buffers[inBufferIndex], 00174 AUDDevice_BYTESPERFRAME); 00175 } 00176 00177 /* Update input status data */ 00178 //bufferSizes[inBufferIndex] = transferred / AUDDevice_BYTESPERSAMPLE; 00179 inBufferIndex = (inBufferIndex + 1) % BUFFER_NUMBER; 00180 numBuffersToSend++; 00181 00182 } else if (status == USBD_STATUS_ABORTED) { 00183 /* Error , ABORT, add NULL buffer */ 00184 //bufferSizes[inBufferIndex] = 0; 00185 inBufferIndex = (inBufferIndex + 1) % BUFFER_NUMBER; 00186 numBuffersToSend++; 00187 } else { 00188 /* Packet is discarded */ 00189 } 00190 00191 /* Receive next packet */ 00192 AUDDSpeakerPhoneDriver_Read(buffers[inBufferIndex], 00193 AUDDevice_BYTESPERFRAME, 00194 (TransferCallback) FrameReceived, 00195 0); // No optional argument 00196 } 00197 00198 /*---------------------------------------------------------------------------- 00199 * Callbacks re-implementation 00200 *----------------------------------------------------------------------------*/ 00201 /** 00202 * Invoked when the configuration of the device changes. Parse used endpoints. 00203 * \param cfgnum New configuration number. 00204 */ 00205 void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum) 00206 { 00207 AUDDSpeakerPhoneDriver_ConfigurationChangeHandler(cfgnum); 00208 } 00209 00210 /** 00211 * Invoked whenever the active setting of an interface is changed by the 00212 * host. Reset streaming interface. 00213 * \param interface Interface number. 00214 * \param setting Newly active setting. 00215 */ 00216 void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface, 00217 unsigned char setting) 00218 { 00219 AUDDSpeakerPhoneDriver_InterfaceSettingChangedHandler(interface, setting); 00220 } 00221 00222 /** 00223 * Invoked whenever a SETUP request is received from the host. Forwards the 00224 * request to the standard handler. 00225 */ 00226 void USBDCallbacks_RequestReceived(const USBGenericRequest *request) 00227 { 00228 AUDDSpeakerPhoneDriver_RequestHandler(request); 00229 } 00230 00231 /** 00232 * Invoked when an audio channel get muted or unmuted. Mutes/unmutes the 00233 * channel at the DAC level. 00234 * \param mic Microphone/Speaker stream changed. 00235 * \param channel Channel number that changed. 00236 * \param muted Indicates the new mute status of the channel. 00237 */ 00238 void AUDDSpeakerPhoneDriver_MuteChanged(uint8_t mic, 00239 uint8_t channel, 00240 uint8_t muted) 00241 { 00242 /* Speaker Master channel */ 00243 if (!mic && channel == AUDDSpeakerPhoneDriver_MASTERCHANNEL) { 00244 if (muted){ 00245 TRACE_WARNING("MuteMaster "); 00246 } else { 00247 TRACE_INFO("UnmuteMaster "); 00248 } 00249 } 00250 } 00251 00252 /** 00253 * Invoked when an audio streaming interface setting changed. 00254 * Audio stream is automatically reset. 00255 * Actually control streaming rate. 00256 * \param mic Microphone/Speaker stream changed. 00257 * \param newSetting New stream (interface) setting. 00258 */ 00259 void AUDDSpeakerPhoneDriver_StreamSettingChanged(uint8_t mic, 00260 uint8_t newSetting) 00261 { 00262 /* Speaker stream */ 00263 if (!mic) 00264 isPlyActive = (newSetting > 0); 00265 else 00266 isRecActive = (newSetting > 0); 00267 } 00268 00269 /** 00270 * Configure OTG settings for USB device 00271 */ 00272 static void _ConfigureUotghs(void) 00273 { 00274 /* UTMI parallel mode, High/Full/Low Speed */ 00275 /* UOTGCK not used in this configuration (High Speed) */ 00276 PMC->PMC_SCDR = PMC_SCDR_USBCLK; 00277 /* USB clock register: USB Clock Input is UTMI PLL */ 00278 PMC->PMC_USB = PMC_USB_USBS; 00279 /* Enable peripheral clock for USBHS */ 00280 PMC_EnablePeripheral(ID_USBHS); 00281 USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE; 00282 /* Enable PLL 480 MHz */ 00283 PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF); 00284 00285 /* Wait that PLL is considered locked by the PMC */ 00286 while (!(PMC->PMC_SR & PMC_SR_LOCKU)); 00287 00288 /* IRQ */ 00289 NVIC_EnableIRQ(USBHS_IRQn); 00290 } 00291 /*---------------------------------------------------------------------------- 00292 * Exported functions 00293 *----------------------------------------------------------------------------*/ 00294 00295 /** 00296 * \brief usb_audio_looprec Application entry point. 00297 * 00298 * Starts the driver and waits for an audio input stream to forward to the DAC. 00299 */ 00300 int main(void) 00301 { 00302 volatile uint8_t plyOn = 0, recOn = 0; 00303 00304 /* Disable watchdog */ 00305 WDT_Disable(WDT); 00306 00307 SCB_EnableICache(); 00308 SCB_EnableDCache(); 00309 00310 printf("-- USB Device Audio LoopREC Example %s --\n\r", SOFTPACK_VERSION); 00311 printf("-- %s\n\r", BOARD_NAME); 00312 printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , 00313 COMPILER_NAME); 00314 00315 /* If they are present, configure Vbus & Wake-up pins */ 00316 PIO_InitializeInterrupts(0); 00317 00318 /* Interrupt priority */ 00319 NVIC_SetPriority(USBHS_IRQn, 2); 00320 00321 /* Audio STREAM LED */ 00322 LED_Configure(USBD_LEDOTHER); 00323 00324 /* Initialize OTG clocks */ 00325 _ConfigureUotghs(); 00326 00327 /* USB audio driver initialization */ 00328 AUDDSpeakerPhoneDriver_Initialize(&auddSpeakerPhoneDriverDescriptors); 00329 00330 // Start USB stack to authorize VBus monitoring 00331 USBD_Connect(); 00332 00333 /* Infinite loop */ 00334 while (1) { 00335 if (USBD_GetState() < USBD_STATE_CONFIGURED) { 00336 continue; 00337 } 00338 00339 if (plyOn) { 00340 if (isPlyActive == 0) { 00341 printf("plyE "); 00342 plyOn = 0; 00343 } 00344 } else if (isPlyActive) { 00345 /* Try to Start Reading the incoming audio stream */ 00346 AUDDSpeakerPhoneDriver_Read(buffers[inBufferIndex], 00347 AUDDevice_BYTESPERFRAME, 00348 (TransferCallback) FrameReceived, 00349 0); // No optional argument 00350 printf("plyS "); 00351 plyOn = 1; 00352 } 00353 00354 if (recOn) { 00355 if (isRecActive == 0) { 00356 printf("recE "); 00357 recOn = 0; 00358 } 00359 } else if (isRecActive) { 00360 printf("recS "); 00361 recOn = 1; 00362 } 00363 } 00364 } 00365 /** \endcond */