SAMV71 Xplained Ultra Software Package 1.4

main.c

Go to the documentation of this file.
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 */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines