SAMV71 Xplained Ultra Software Package 1.3

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_hid_aud
00030  *  \page usb_hid_aud USB HID(Keyboard)+Audio(Speaker) Example
00031  *
00032  *  \section Purpose
00033  *
00034  *  The HID Audio Composite Example will help you to get familiar with the
00035  *  USB Device Port(UDP) and SSC on SAMv7 Microcontrollers. Also
00036  *  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 Composite
00038  *  HID and Audio classes.
00039  *
00040  *  \section Requirements
00041  *
00042  *  This package can be used with SAMV71 Xplained Ultra board that have both
00043  *  UDP and SSC.
00044  *
00045  *  \section win_drv_update Windows Driver Update
00046  *
00047  * The composite device is generally supported by Microsoft windows, but some
00048  * patches are needed for muti-interface functions such as CDC & Audio.
00049  *
00050  *  \section Description
00051  *
00052  * The demo simulates a USB device that integrates HID Keyboard and Audio
00053  * Desktop Speaker function.
00054  *
00055  * When the board running this program connected to a host (PC for example), with
00056  * USB cable, host will notice the attachment of a USB device (USB Composite
00057  * Device) with a USB Human Interface Device and a USB Audio Device.
00058  *
00059  *  \section Usage
00060  *
00061  *  -# Build the program and download it inside the SAM V71 Xplained Ultra board. 
00062  *     Please refer to the Getting Started with SAM V71 Microcontrollers.pdf
00063  *  -# On the computer, open and configure a terminal application
00064  *     (e.g. HyperTerminal on Microsoft Windows) with these settings:
00065  *    - 115200 bauds
00066  *    - 8 bits of data
00067  *    - No parity
00068  *    - 1 stop bit
00069  *    - No flow control
00070  *  -# Start the application.
00071  *  -# In the terminal window, the following text should appear:
00072  *  \code
00073  *  -- USB HID + Audio Device Example xxx --
00074  *  -- SAMxxxxx-xx
00075  *  -- Compiled: xxx xx xxxx xx:xx:xx --
00076  *  \endcode
00077  *  -# When connecting USB cable to windows, the LED blinks, and the host
00078  *     reports a new USB device attachment (if it's the first time you connect
00079  *     an %audio speaker demo board to your host). You can find new
00080  *     "USB Composite Device" and "USB Audio Device" appear in the hardware
00081  *     device list.
00082  *  -# You can play sound in host side through the USB Audio Device, and it
00083  *     can be heard from the earphone connected to the board.
00084  *
00085  *  \section References
00086  *  - usb_hid_aud/main.c
00087  *  - pio: Pin configurations and peripheral configure.
00088  *  - ssc: SSC interface driver
00089  *  - usb: USB Framework, HID, Audio function driver and UDP interface driver
00090  *      - \ref usbd_framework
00091  *         - \ref usbd_api
00092  *      - \ref usbd_composite "composite"
00093  *         - \ref usbd_composite_drv
00094  *      - \ref usbd_aud "audio"
00095  *         - \ref usbd_audio_rec_drv
00096  *  - projects: more detailed information for HID(Keyboard) and Audio(Speaker)
00097  *      - \ref usb_core
00098  *      - \ref usb_audio_speaker, \ref usb_audio_headphone
00099  *
00100  */
00101 
00102 /**
00103  *  \file
00104  *
00105  *  This file contains all the specific code for the
00106  *  usb_iad_hid_aud example.
00107  */
00108 
00109 /*----------------------------------------------------------------------------
00110  *         Headers
00111  *----------------------------------------------------------------------------*/
00112 
00113 #include "board.h"
00114 
00115 #include <HIDAUDDDriver.h>
00116 #include <HIDDKeyboard.h>
00117 #include <AUDDFunction.h>
00118 
00119 #include <USBD_Config.h>
00120 #include <USBD_LEDs.h>
00121 
00122 #include <string.h>
00123 
00124 /*----------------------------------------------------------------------------
00125  *         Definitions
00126  *----------------------------------------------------------------------------*/
00127 
00128 #define NO_PUSHBUTTON
00129 
00130 /*- HID */
00131 /** Number of keys used in the example. */
00132 #define NUM_KEYS                    2
00133 
00134 /** Number of non-modifiers keys. */
00135 #define NUM_NORMAL_KEYS             1
00136 
00137 /** Number of modifier keys. */
00138 #define NUM_MODIFIER_KEYS           (NUM_KEYS - NUM_NORMAL_KEYS)
00139 
00140 /** Num lock LED index. */
00141 #define LED_NUMLOCK                 USBD_LEDOTHER
00142 
00143 /*- Audio */
00144 /**  Number of available audio buffers. */
00145 #define BUFFER_NUMBER       500
00146 /**  Size of one buffer in bytes. */
00147 #define BUFFER_SIZE     (AUDDevice_BYTESPERFRAME)
00148 
00149 /**  Delay in ms for starting the DAC transmission
00150      after a frame has been received. */
00151 #define DAC_DELAY           2
00152 
00153 /** SSC: Number of slots in a frame */
00154 #define SLOT_BY_FRAME           (2)
00155 /** SSC: Number of bits in a slot */
00156 #define BITS_BY_SLOT            (16)
00157 #define I2S_SLAVE_TX_SETTING      ((SSC_TCMR_CKS_TK) |        \
00158                                 (SSC_TCMR_CKO_NONE) |      \
00159                                 (SSC_TCMR_START_TF_EDGE) | \
00160                                 (SSC_TCMR_STTDLY(1)) |     \
00161                                 (SSC_TCMR_PERIOD(0)))
00162 
00163 #define I2S_SLAVE_TX_FRM_SETTING  ((SSC_TFMR_DATLEN(BITS_BY_SLOT - 1)) |\
00164                                 (SSC_TFMR_MSBF) |                    \
00165                                 (SSC_TFMR_DATNB(SLOT_BY_FRAME - 1)) |\
00166                                 (SSC_TFMR_FSOS_NONE))
00167 
00168 
00169 #define I2S_SLAVE_RX_SETTING      ((SSC_RCMR_CKS_TK) |       \
00170                                 (SSC_RCMR_CKO_NONE) |     \
00171                                 (SSC_RCMR_CKI) |          \
00172                                 (SSC_RCMR_START_RF_EDGE) |\
00173                                 (SSC_RCMR_STTDLY(1)) |    \
00174                                 (SSC_RCMR_PERIOD(0)))
00175 
00176 #define I2S_SLAVE_RX_FRM_SETTING  ((SSC_RFMR_DATLEN(BITS_BY_SLOT - 1)) |\
00177                                 (SSC_RFMR_MSBF) |                    \
00178                                 (SSC_RFMR_DATNB(SLOT_BY_FRAME - 1)) |\
00179                                 (SSC_RFMR_FSOS_NONE))
00180 
00181 /** TWI clock */
00182 #define TWI_CLOCK               400000
00183 /** Audio sample rate */
00184 #define SAMPLE_RATE             (48000)
00185 
00186 
00187 /*----------------------------------------------------------------------------
00188  *         External variables
00189  *----------------------------------------------------------------------------*/
00190 
00191 /** Descriptor list for USB Audio Speaker Device Driver */
00192 extern const USBDDriverDescriptors hidauddDriverDescriptors;
00193 
00194 /*----------------------------------------------------------------------------
00195  *         Internal variables
00196  *----------------------------------------------------------------------------*/
00197 
00198 /*- HID */
00199 
00200 #ifdef NO_PUSHBUTTON
00201 #else
00202 /** List of pinsPushButtons to configure for the application. */
00203 static Pin pinsPushButtons[] = {PINS_PUSHBUTTONS};
00204 #endif
00205 
00206 /** Array of key codes produced by each button. */
00207 static uint8_t keyCodes[NUM_KEYS] = {
00208     HIDKeypad_A,
00209     HIDKeypad_NUMLOCK,
00210 };
00211 
00212 /** Current status (pressed or not) for each key. */
00213 static uint8_t keyStatus[NUM_KEYS];
00214 
00215 /*- Audio */
00216 /**  Data buffers for receiving audio frames from the USB host. */
00217 
00218 COMPILER_ALIGNED(32) static uint8_t buffers[BUFFER_NUMBER][BUFFER_SIZE];
00219 
00220 /**  Number of samples stored in each data buffer. */
00221 static uint32_t bufferSizes[BUFFER_NUMBER];
00222 /**  Next buffer in which USB data can be stored. */
00223 static uint32_t inBufferIndex = 0;
00224 /**  Next buffer which should be sent to the DAC. */
00225 static uint32_t outBufferIndex = 0;
00226 /**  Number of buffers that can be sent to the DAC. */
00227 static volatile uint32_t numBuffersToSend = 0;
00228 
00229 /**  Current state of the DAC transmission. */
00230 static volatile uint32_t isDacActive = 0;
00231 static volatile uint32_t isFirstFrame = 1;
00232 /**  Number of buffers to wait for before the DAC starts to transmit data. */
00233 static volatile uint32_t dacDelay;
00234 
00235 /** Twi instance*/
00236 static Twid twid;
00237 /** Global DMA driver for all transfer */
00238 COMPILER_ALIGNED(32) static sXdmad dmad;
00239 /** DMA channel for TX */
00240 static uint32_t sscDmaTxChannel;
00241 
00242 /** List of pins to configure. */
00243 static const Pin pinsAudio[] = { PIN_TWI_TWD0, 
00244                                 PIN_TWI_TWCK0, 
00245                                 PIN_SSC_TD, 
00246                                 PIN_SSC_TK, 
00247                                 PIN_SSC_TF, 
00248                                 PIN_SSC_RD, 
00249                                 PIN_SSC_RK, 
00250                                 PIN_SSC_RF, 
00251                                 PIN_PCK2};
00252 
00253 /*----------------------------------------------------------------------------
00254  *         Internal functions
00255  *----------------------------------------------------------------------------*/
00256 /**
00257  * Interrupt handler for the XDMAC.
00258  */
00259 void XDMAC_Handler( void )
00260 {
00261     XDMAD_Handler( &dmad );
00262 }
00263 
00264 /**
00265  *  \brief Start DMA sending/waiting data.
00266  */
00267 static void _SscDma(volatile uint32_t *pReg, uint32_t dmaChannel, 
00268                     void* pBuffer, uint16_t wSize)
00269 {
00270     sXdmad *pDmad = &dmad;
00271     sXdmadCfg xdmadCfg;
00272     
00273     
00274     xdmadCfg.mbr_ubc = wSize ;
00275     xdmadCfg.mbr_sa = (uint32_t) pBuffer;
00276     xdmadCfg.mbr_da = (uint32_t) pReg;
00277     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN 
00278                        | XDMAC_CC_MBSIZE_SINGLE
00279                        | XDMAC_CC_DSYNC_MEM2PER
00280                        | XDMAC_CC_CSIZE_CHK_1 
00281                        | XDMAC_CC_DWIDTH_HALFWORD 
00282                        | XDMAC_CC_SIF_AHB_IF0 
00283                        | XDMAC_CC_DIF_AHB_IF1 
00284                        | XDMAC_CC_SAM_INCREMENTED_AM
00285                        | XDMAC_CC_DAM_FIXED_AM 
00286                        | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber( 
00287                             ID_SSC, XDMAD_TRANSFER_TX));
00288     xdmadCfg.mbr_bc = 0;
00289     xdmadCfg.mbr_ds = 0;
00290     xdmadCfg.mbr_sus = 0;
00291     xdmadCfg.mbr_dus = 0;
00292    
00293     memory_sync();
00294     XDMAD_ConfigureTransfer( pDmad, dmaChannel, &xdmadCfg, 0, 0, (
00295                             XDMAC_CIE_BIE   |
00296                             XDMAC_CIE_DIE   |
00297                             XDMAC_CIE_FIE   |
00298                             XDMAC_CIE_RBIE  |
00299                             XDMAC_CIE_WBIE  |
00300                             XDMAC_CIE_ROIE));
00301     SCB_CleanInvalidateDCache();
00302     XDMAD_StartTransfer( pDmad, dmaChannel );
00303     SSC_EnableTransmitter(SSC);
00304 }
00305 
00306 /**
00307  *  \brief DMA TX callback
00308  */
00309 static void _SscTxCallback(uint8_t status, void* pArg)
00310 {
00311     sXdmad *pDmad = &dmad;
00312     Xdmac *pXdmac = pDmad->pXdmacs;
00313     if (status != XDMAD_OK) return;
00314     pArg = pArg; /*dummy */
00315     if (numBuffersToSend == 0)
00316     {
00317         /* End of transmission */
00318         isDacActive = 0;
00319         return;
00320     }
00321     /* Load next buffer */
00322     memory_sync();
00323     XDMAC_SetSourceAddr(pXdmac, sscDmaTxChannel,  (uint32_t) buffers[outBufferIndex]);
00324     XDMAC_SetMicroblockControl(pXdmac, sscDmaTxChannel, bufferSizes[outBufferIndex]);
00325     outBufferIndex = (outBufferIndex + 1) % BUFFER_NUMBER;
00326     numBuffersToSend --;
00327     XDMAD_StartTransfer( pDmad, sscDmaTxChannel );
00328 }
00329 
00330 /**
00331  * \brief DMA driver configuration
00332  */
00333 static void _ConfigureDma( void )
00334 {
00335     sXdmad *pDmad = &dmad;
00336     /* Driver initialize */
00337     XDMAD_Initialize( pDmad, 0 );
00338     /* IRQ configure */
00339     NVIC_EnableIRQ(XDMAC_IRQn);
00340 
00341     /* Allocate DMA channels for SSC */
00342     sscDmaTxChannel = XDMAD_AllocateChannel( pDmad, XDMAD_TRANSFER_MEMORY, ID_SSC);
00343     if (   sscDmaTxChannel == XDMAD_ALLOC_FAILED ) {
00344         printf("xDMA channel allocation error\n\r");
00345         while(1);
00346     }
00347     /* Set TX callback */
00348     XDMAD_SetCallback(pDmad, sscDmaTxChannel,(XdmadTransferCallback)_SscTxCallback, 0);
00349     XDMAD_PrepareChannel(pDmad, sscDmaTxChannel );
00350 }
00351 
00352 /**
00353  * Enable/Disable audio channels
00354  */
00355 static void AudioPlayEnable(uint8_t enable)
00356 {
00357     if (enable == 1) {
00358         SSC_EnableTransmitter(SSC);
00359     }
00360     else if (enable == 0) {
00361         SSC_DisableTransmitter(SSC);
00362     }
00363 }
00364 
00365 /**
00366  * Adjust codec for sync
00367  * \param adjust Sync case: default(0)/faster(>0)/slower(<0)
00368  */
00369 static void _SyncAdjust(int32_t adjust)
00370 {
00371     if (adjust > 0) {
00372         /* Fractional multiply for FLL_K, Fref = 0x8000 (1/2) */
00373         WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_FLL_CRTL3, 0xFF00);
00374         /* FLL_GAIN=0, FLL_N=187 */
00375         return;
00376     }
00377     if (adjust < 0) {
00378         /* Fractional multiply for FLL_K, Fref = 0x8000 (1/2) */
00379         WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_FLL_CRTL3, 0x5000);
00380         /* FLL_GAIN=0, FLL_N=187 */
00381         return;
00382     }
00383     /* Default: 32K -> 48K*256, FLL: 32768*187.5/16/8
00384      */
00385     /* FLL_FRATIO=4 (/16), FLL_OUTDIV= 7 (/8) */
00386     /* Fractional multiply for FLL_K, Fref = 0x8000 (1/2) */
00387     WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_FLL_CRTL3, 0x8000 + 0x3000);
00388     /* FLL_GAIN=0, FLL_N=187 */
00389     return; 
00390 }
00391 
00392 /**
00393  * Configure the TWI and DACC for audio output.
00394  * \param sampleRate Audio sample rate.
00395  * \param mck        MCK frequency.
00396  */
00397 static void _ConfigureAudioPlay(uint32_t sampleRate, uint32_t mck)
00398 {
00399     /* -- Pins Configuration -- */
00400     PIO_Configure(pinsAudio, PIO_LISTSIZE(pinsAudio));
00401 
00402     /* -- SSC Configuration -- */
00403     sampleRate = sampleRate; /*dummy */
00404     SSC_Configure(SSC,0, mck);
00405     SSC_DisableTransmitter(SSC);
00406     SSC_DisableReceiver(SSC);
00407     SSC_ConfigureTransmitter(SSC, I2S_SLAVE_TX_SETTING,I2S_SLAVE_TX_FRM_SETTING);
00408     SSC_DisableTransmitter(SSC);
00409 
00410     /* Enable TWI peripheral clock */
00411     PMC_EnablePeripheral(ID_TWIHS0);
00412     /* Configure and enable the TWI (required for accessing the DAC) */
00413     TWI_ConfigureMaster(TWIHS0, TWI_CLOCK, mck);
00414     TWID_Initialize(&twid, TWIHS0);
00415     
00416     /* Initialize the audio DAC
00417      */
00418     WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_RESET, 0);
00419     Wait(100);
00420     /* WM8904 as master */
00421     if(WM8904_Read(&twid, WM8904_SLAVE_ADDRESS, 0)!=0x8904){
00422           printf("WM8904 not found!\n\r");
00423           while(1);
00424     }
00425     WM8904_Init(&twid, WM8904_SLAVE_ADDRESS,PMC_MCKR_CSS_SLOW_CLK);
00426     _SyncAdjust(0);
00427     PMC_ConfigurePCK2(PMC_MCKR_CSS_SLOW_CLK, PMC_MCKR_PRES_CLK_1 );
00428     /* Mute */
00429     AudioPlayEnable(0);
00430 }
00431 
00432 /**
00433  * Monitor keyboard buttons & Update key status in HID driver
00434  */
00435 static void HIDDKeyboardProcessKeys(void)
00436 {
00437     uint32_t i;
00438     uint8_t pressedKeys[NUM_KEYS];
00439     uint8_t pressedKeysSize = 0;
00440     uint8_t releasedKeys[NUM_KEYS];
00441     uint8_t releasedKeysSize = 0;
00442 
00443     /* Monitor buttons */
00444 #ifdef NO_PUSHBUTTON
00445     if (DBG_IsRxReady()) {
00446         uint8_t key = DBG_GetChar();
00447         switch(key) {
00448         case '1': case '2':
00449             i = key - '1';
00450             if (keyStatus[i]) {
00451                 /* Key press simulation */
00452                 TRACE_INFO("Key %u pressed\n\r", (unsigned int)i);
00453                 keyStatus[i] = 0;
00454                 pressedKeys[pressedKeysSize] = keyCodes[i];
00455                 pressedKeysSize ++;
00456                 HIDDKeyboard_RemoteWakeUp();
00457             } else {
00458                 /* Key release simulation */
00459                 TRACE_INFO("Key %u released\n\r", (unsigned int)i);
00460                 keyStatus[i] = 1;
00461                 releasedKeys[releasedKeysSize] = keyCodes[i];
00462                 releasedKeysSize++;
00463             }
00464             break;
00465         default: DBG_PutChar(key);
00466         }
00467     }
00468 #else
00469     for (i = 0; i < PIO_LISTSIZE(pinsPushButtons); i++) {
00470         /* Check if button state has changed */
00471         uint8_t isButtonPressed = PIO_Get(&(pinsPushButtons[i]));
00472         if (isButtonPressed != keyStatus[i]) {
00473             /* Update button state */
00474             if (!isButtonPressed)   {
00475                 /* Key has been pressed */
00476                 TRACE_INFO("Key %u has been pressed\n\r", i);
00477                 keyStatus[i] = 0;
00478                 pressedKeys[pressedKeysSize] = keyCodes[i];
00479                 pressedKeysSize++;
00480                 HIDDKeyboard_RemoteWakeUp();
00481             } else {
00482                 /* Key has been released */
00483                 TRACE_INFO("Key %u has been released\n\r", i);
00484                 keyStatus[i] = 1;
00485                 releasedKeys[releasedKeysSize] = keyCodes[i];
00486                 releasedKeysSize++;
00487             }
00488         }
00489     }
00490 #endif
00491 
00492     /* Update key status in the HID driver if necessary */
00493     if ((pressedKeysSize != 0) || (releasedKeysSize != 0)) {
00494         uint8_t status;
00495         do {
00496             status = HIDDKeyboard_ChangeKeys(pressedKeys,
00497                                             pressedKeysSize,
00498                                             releasedKeys,
00499                                             releasedKeysSize);
00500         } while (status != USBD_STATUS_SUCCESS);
00501     }
00502 }
00503 
00504 /**
00505  *  Invoked when a frame has been received.
00506  */
00507 static void FrameReceived(uint32_t unused,
00508                         uint8_t status,
00509                         uint32_t transferred,
00510                         uint32_t remaining)
00511 {
00512     unused = unused; /*dummy */
00513     remaining = remaining; /*dummy */
00514     if (status == USBD_STATUS_SUCCESS) {
00515         bufferSizes[inBufferIndex] = transferred / AUDDevice_BYTESPERSAMPLE;
00516         inBufferIndex = (inBufferIndex + 1) % BUFFER_NUMBER;
00517         numBuffersToSend++;
00518         /* Start DAc transmission if necessary */
00519         if (!isDacActive) {
00520             dacDelay = DAC_DELAY;
00521             isDacActive = 1;
00522         }
00523         /* Wait until a few buffers have been received */
00524         else if (dacDelay > 0) {
00525             dacDelay--;
00526         }
00527         /* Start sending buffers */
00528         else if (isFirstFrame) {
00529             isFirstFrame = 0;
00530             //AudioPlayEnable(1);
00531             _SscDma(&(SSC->SSC_THR), sscDmaTxChannel, buffers[outBufferIndex],
00532                     bufferSizes[outBufferIndex]);
00533             outBufferIndex = (outBufferIndex + 1) % BUFFER_NUMBER;
00534             numBuffersToSend --;
00535         }
00536     }
00537     else if (status == USBD_STATUS_ABORTED) {
00538         /* Error , ABORT, add NULL buffer */
00539         bufferSizes[inBufferIndex] = 0;
00540     } else {
00541         /* Packet is discarded */
00542     }
00543     /* Receive next packet */
00544     AUDDFunction_Read(buffers[inBufferIndex],
00545                     AUDDevice_BYTESPERFRAME,
00546                     (TransferCallback) FrameReceived,
00547                     0); // No optional argument
00548 }
00549 
00550 /*-------------------------------------------
00551  *      USB Device Driver callbacks
00552  *-------------------------------------------*/
00553 /**
00554  * Invoked when the configuration of the device changes. Parse used endpoints.
00555  * \param cfgnum New configuration number.
00556  */
00557 void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
00558 {
00559     HIDAUDDDriver_ConfigurationChangedHandler(cfgnum);
00560 }
00561 
00562 /**
00563  * Invoked whenever the active setting of an interface is changed by the
00564  * host. Reset streaming interface.
00565  * \param interface Interface number.
00566  * \param setting Newly active setting.
00567  */
00568 void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
00569                                             unsigned char setting)
00570 {
00571     HIDAUDDDriver_InterfaceSettingChangedHandler(interface, setting);
00572 }
00573 
00574 /**
00575  *  Invoked whenever a SETUP request is received from the host. Forwards the
00576  *  request to the standard handler.
00577  */
00578 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00579 {
00580     HIDAUDDDriver_RequestHandler(request);
00581 }
00582 
00583 /*-------------------------------------------
00584  *      USB Function driver callbacks
00585  *-------------------------------------------*/
00586 
00587 /**
00588  *  Invoked when an audio channel get muted or unmuted. Mutes/unmutes the
00589  *  channel at the DAC level.
00590  *  \param mic      Microphone/Speaker stream changed.
00591  *  \param channel  Channel number that changed.
00592  *  \param muted    Indicates the new mute status of the channel.
00593  */
00594 void AUDDFunction_MuteChanged(uint8_t mic, uint8_t channel, uint8_t muted)
00595 {
00596     if (mic) return;
00597 
00598     /* Speaker Master channel */
00599     if (channel == AUDD_CH_Master) {
00600         if (muted) {
00601             AudioPlayEnable(0);
00602             TRACE_WARNING("MuteMaster ");
00603         } else {
00604             TRACE_INFO("UnmuteMaster ");
00605             AudioPlayEnable(1);
00606         }
00607     }
00608 }
00609 
00610 /**
00611  *  Invoked when an audio streaming interface setting changed. Actually control
00612  *  streaming rate.
00613  *  \param mic         1 to indicate microphone mute changed.
00614  *  \param newSetting  New stream (interface) setting.
00615  */
00616 void AUDDFunction_StreamSettingChanged(uint8_t mic, uint8_t newSetting)
00617 {
00618     mic = mic; /* dummy */
00619     if (newSetting) {
00620         LED_Set(USBD_LEDOTHER);
00621         //XDMAD_StopTransfer(&dmad, sscDmaTxChannel);
00622         numBuffersToSend = 0;
00623     }
00624     else LED_Clear(USBD_LEDOTHER);
00625 }
00626 
00627 /**
00628  * Invoked when the status of the keyboard LEDs changes. Turns the num. lock
00629  * LED on or off.
00630  * \param numLockStatus Indicates the current status of the num. lock key.
00631  * \param capsLockStatus Indicates the current status of the caps lock key.
00632  * \param scrollLockStatus Indicates the current status of the scroll lock key
00633  */
00634 void HIDDKeyboardCallbacks_LedsChanged(
00635     uint8_t numLockStatus,
00636     uint8_t capsLockStatus,
00637     uint8_t scrollLockStatus)
00638 {
00639     capsLockStatus = capsLockStatus; /* dummy */
00640     scrollLockStatus = scrollLockStatus; /* dummy */
00641     /* Num. lock */
00642     if (numLockStatus) {
00643         LED_Set(LED_NUMLOCK);
00644     } else {
00645         LED_Clear(LED_NUMLOCK);
00646     }
00647 }
00648 
00649 /**
00650  * Configure USB settings for USB device
00651  */
00652 static void _ConfigureUsbhs(void)
00653 {
00654     /* UTMI parallel mode, High/Full/Low Speed */
00655     /* UUSBCK not used in this configuration (High Speed) */
00656     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00657     /* USB clock register: USB Clock Input is UTMI PLL */
00658     PMC->PMC_USB = PMC_USB_USBS;
00659     /* Enable peripheral clock for USBHS */
00660     PMC_EnablePeripheral(ID_USBHS);    
00661     USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00662     /* Enable PLL 480 MHz */
00663     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00664     /* Wait that PLL is considered locked by the PMC */
00665     while( !(PMC->PMC_SR & PMC_SR_LOCKU) );
00666     /* IRQ */
00667     NVIC_EnableIRQ(USBHS_IRQn) ;
00668 }
00669 /*----------------------------------------------------------------------------
00670  *         Exported functions
00671  *----------------------------------------------------------------------------*/
00672 
00673 /**
00674  *  \brief usb_iad_hid_aud Application entry point.
00675  *
00676  *  Starts the driver and waits for an audio input stream to forward to the DAC.
00677  */
00678 int main(void)
00679 {
00680     volatile uint8_t usbConn = 0;
00681     volatile uint8_t audioOn = 0;
00682     volatile uint32_t num = 0;
00683     int32_t  numDiff = 0, prevDiff = 0;
00684     int8_t   clockAdjust = 0;
00685 
00686     /* Disable watchdog */
00687     WDT_Disable( WDT );
00688     
00689     SCB_EnableICache();
00690     SCB_EnableDCache();
00691 
00692 
00693     printf("-- USB HID + Audio Device Example %s --\n\r", SOFTPACK_VERSION);
00694     printf("-- %s\n\r", BOARD_NAME);
00695     printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00696 
00697     TimeTick_Configure();
00698     /* Interrupt priority */
00699     NVIC_SetPriority( USBHS_IRQn, 2 );
00700     
00701     /* If they are present, configure Vbus & Wake-up pins */
00702     PIO_InitializeInterrupts(0);
00703 
00704     /* Initialize all USB power (off) */
00705     _ConfigureUsbhs();
00706 
00707     /* ----- HID Function Initialize */
00708 #ifdef NO_PUSHBUTTON
00709     printf( "-- : DBG key 1 2 used as buttons\n\r" );
00710     printf( "-- : 1st press to push, 2nd press to release\n\r" );
00711 #else
00712     /* Initialize key statuses and configure push buttons */
00713     PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons));
00714 #endif
00715     memset(keyStatus, 1, NUM_KEYS);
00716     //LED_Configure(LED_NUMLOCK);
00717 
00718     /* Audio STREAM LED */
00719     LED_Configure(USBD_LEDOTHER);
00720 
00721     /* Configure Audio */
00722     _ConfigureAudioPlay(AUDDevice_SAMPLERATE, BOARD_MCK);
00723 
00724     /* Configure DMA */
00725     _ConfigureDma();
00726 
00727     /* USB audio driver initialization */
00728     HIDAUDDDriver_Initialize(&hidauddDriverDescriptors);
00729 
00730     /* connect if needed */
00731     USBD_Connect();
00732 
00733     /* Infinite loop */
00734     while (1) {
00735         if (USBD_GetState() < USBD_STATE_CONFIGURED) {
00736             usbConn = 0;
00737             continue;
00738         }
00739         if (audioOn) {
00740             if(isDacActive == 0) {
00741                 AudioPlayEnable(0);
00742                 printf("audE ");
00743                 isFirstFrame = 1;
00744                 audioOn = 0;
00745             } else {
00746                 if (num != numBuffersToSend) {
00747                     num = numBuffersToSend;
00748                 }
00749                 numDiff = numBuffersToSend - DAC_DELAY;
00750                 if (prevDiff != numDiff) {
00751                     prevDiff = numDiff;
00752                     if (numDiff > 0 && clockAdjust != 1) {
00753                       printf("+");
00754                         /* USB too fast or SSC too slow: faster clock */
00755                         clockAdjust = 1;
00756                         _SyncAdjust(1);
00757                     }
00758                     if (numDiff < 0 && clockAdjust != -1) {
00759                       printf("-");
00760                         /* USB too slow or SSC too fast: slower clock */
00761                         clockAdjust = -1;
00762                         _SyncAdjust(-1);
00763                     }
00764                     if (numDiff == 0 && clockAdjust != 0) {
00765                         clockAdjust = 0;
00766                         _SyncAdjust(0);
00767                     }
00768                 }
00769             }
00770         } else if (isDacActive) {
00771             printf("audS ");
00772             audioOn = 1;
00773         }
00774         if (usbConn == 0) {
00775             usbConn = 1;
00776             /* Start Reading the incoming audio stream */
00777             AUDDFunction_Read(buffers[inBufferIndex],
00778                             AUDDevice_BYTESPERFRAME,
00779                             (TransferCallback) FrameReceived,
00780                             0); // No optional argument
00781         }
00782         HIDDKeyboardProcessKeys();
00783     }
00784 }
00785 /** \endcond */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines