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