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_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     pArg = pArg; /*dummy */
00314     if (numBuffersToSend == 0)
00315     {
00316         /* End of transmission */
00317         isDacActive = 0;
00318         return;
00319     }
00320     /* Load next buffer */
00321     memory_sync();
00322     XDMAC_SetSourceAddr(pXdmac, sscDmaTxChannel,  (uint32_t) buffers[outBufferIndex]);
00323     XDMAC_SetMicroblockControl(pXdmac, sscDmaTxChannel, bufferSizes[outBufferIndex]);
00324     outBufferIndex = (outBufferIndex + 1) % BUFFER_NUMBER;
00325     numBuffersToSend --;
00326     XDMAD_StartTransfer( pDmad, sscDmaTxChannel );
00327 }
00328 
00329 /**
00330  * \brief DMA driver configuration
00331  */
00332 static void _ConfigureDma( void )
00333 {
00334     sXdmad *pDmad = &dmad;
00335     /* Driver initialize */
00336     XDMAD_Initialize( pDmad, 0 );
00337     /* IRQ configure */
00338     NVIC_EnableIRQ(XDMAC_IRQn);
00339 
00340     /* Allocate DMA channels for SSC */
00341     sscDmaTxChannel = XDMAD_AllocateChannel( pDmad, XDMAD_TRANSFER_MEMORY, ID_SSC);
00342     if (   sscDmaTxChannel == XDMAD_ALLOC_FAILED ) {
00343         printf("xDMA channel allocation error\n\r");
00344         while(1);
00345     }
00346     /* Set TX callback */
00347     XDMAD_SetCallback(pDmad, sscDmaTxChannel,(XdmadTransferCallback)_SscTxCallback, 0);
00348     XDMAD_PrepareChannel(pDmad, sscDmaTxChannel );
00349 }
00350 
00351 /**
00352  * Enable/Disable audio channels
00353  */
00354 static void AudioPlayEnable(uint8_t enable)
00355 {
00356     if (enable == 1) {
00357         SSC_EnableTransmitter(SSC);
00358     }
00359     else if (enable == 0) {
00360         SSC_DisableTransmitter(SSC);
00361     }
00362 }
00363 
00364 /**
00365  * Adjust codec for sync
00366  * \param adjust Sync case: default(0)/faster(>0)/slower(<0)
00367  */
00368 static void _SyncAdjust(int32_t adjust)
00369 {
00370     if (adjust > 0) {
00371         /* Fractional multiply for FLL_K, Fref = 0x8000 (1/2) */
00372         WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_FLL_CRTL3, 0xFF00);
00373         /* FLL_GAIN=0, FLL_N=187 */
00374         return;
00375     }
00376     if (adjust < 0) {
00377         /* Fractional multiply for FLL_K, Fref = 0x8000 (1/2) */
00378         WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_FLL_CRTL3, 0x5000);
00379         /* FLL_GAIN=0, FLL_N=187 */
00380         return;
00381     }
00382     /* Default: 32K -> 48K*256, FLL: 32768*187.5/16/8
00383      */
00384     /* FLL_FRATIO=4 (/16), FLL_OUTDIV= 7 (/8) */
00385     /* Fractional multiply for FLL_K, Fref = 0x8000 (1/2) */
00386     WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_FLL_CRTL3, 0x8000 + 0x3000);
00387     /* FLL_GAIN=0, FLL_N=187 */
00388     return; 
00389 }
00390 
00391 /**
00392  * Configure the TWI and DACC for audio output.
00393  * \param sampleRate Audio sample rate.
00394  * \param mck        MCK frequency.
00395  */
00396 static void _ConfigureAudioPlay(uint32_t sampleRate, uint32_t mck)
00397 {
00398     /* -- Pins Configuration -- */
00399     PIO_Configure(pinsAudio, PIO_LISTSIZE(pinsAudio));
00400 
00401     /* -- SSC Configuration -- */
00402     sampleRate = sampleRate; /*dummy */
00403     SSC_Configure(SSC,0, mck);
00404     SSC_DisableTransmitter(SSC);
00405     SSC_DisableReceiver(SSC);
00406     SSC_ConfigureTransmitter(SSC, I2S_SLAVE_TX_SETTING,I2S_SLAVE_TX_FRM_SETTING);
00407     SSC_DisableTransmitter(SSC);
00408 
00409     /* Enable TWI peripheral clock */
00410     PMC_EnablePeripheral(ID_TWIHS0);
00411     /* Configure and enable the TWI (required for accessing the DAC) */
00412     TWI_ConfigureMaster(TWIHS0, TWI_CLOCK, mck);
00413     TWID_Initialize(&twid, TWIHS0);
00414     
00415     /* Initialize the audio DAC
00416      */
00417     WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, WM8904_REG_RESET, 0);
00418     Wait(100);
00419     /* WM8904 as master */
00420     if(WM8904_Read(&twid, WM8904_SLAVE_ADDRESS, 0)!=0x8904){
00421           printf("WM8904 not found!\n\r");
00422           while(1);
00423     }
00424     WM8904_Init(&twid, WM8904_SLAVE_ADDRESS,PMC_MCKR_CSS_SLOW_CLK);
00425     _SyncAdjust(0);
00426     PMC_ConfigurePCK2(PMC_MCKR_CSS_SLOW_CLK, PMC_MCKR_PRES_CLK_1 );
00427     /* Mute */
00428     AudioPlayEnable(0);
00429 }
00430 
00431 /**
00432  * Monitor keyboard buttons & Update key status in HID driver
00433  */
00434 static void HIDDKeyboardProcessKeys(void)
00435 {
00436     uint32_t i;
00437     uint8_t pressedKeys[NUM_KEYS];
00438     uint8_t pressedKeysSize = 0;
00439     uint8_t releasedKeys[NUM_KEYS];
00440     uint8_t releasedKeysSize = 0;
00441 
00442     /* Monitor buttons */
00443 #ifdef NO_PUSHBUTTON
00444     if (DBG_IsRxReady()) {
00445         uint8_t key = DBG_GetChar();
00446         switch(key) {
00447         case '1': case '2':
00448             i = key - '1';
00449             if (keyStatus[i]) {
00450                 /* Key press simulation */
00451                 TRACE_INFO("Key %u pressed\n\r", (unsigned int)i);
00452                 keyStatus[i] = 0;
00453                 pressedKeys[pressedKeysSize] = keyCodes[i];
00454                 pressedKeysSize ++;
00455                 HIDDKeyboard_RemoteWakeUp();
00456             } else {
00457                 /* Key release simulation */
00458                 TRACE_INFO("Key %u released\n\r", (unsigned int)i);
00459                 keyStatus[i] = 1;
00460                 releasedKeys[releasedKeysSize] = keyCodes[i];
00461                 releasedKeysSize++;
00462             }
00463             break;
00464         default: DBG_PutChar(key);
00465         }
00466     }
00467 #else
00468     for (i = 0; i < PIO_LISTSIZE(pinsPushButtons); i++) {
00469         /* Check if button state has changed */
00470         uint8_t isButtonPressed = PIO_Get(&(pinsPushButtons[i]));
00471         if (isButtonPressed != keyStatus[i]) {
00472             /* Update button state */
00473             if (!isButtonPressed)   {
00474                 /* Key has been pressed */
00475                 TRACE_INFO("Key %u has been pressed\n\r", i);
00476                 keyStatus[i] = 0;
00477                 pressedKeys[pressedKeysSize] = keyCodes[i];
00478                 pressedKeysSize++;
00479                 HIDDKeyboard_RemoteWakeUp();
00480             } else {
00481                 /* Key has been released */
00482                 TRACE_INFO("Key %u has been released\n\r", i);
00483                 keyStatus[i] = 1;
00484                 releasedKeys[releasedKeysSize] = keyCodes[i];
00485                 releasedKeysSize++;
00486             }
00487         }
00488     }
00489 #endif
00490 
00491     /* Update key status in the HID driver if necessary */
00492     if ((pressedKeysSize != 0) || (releasedKeysSize != 0)) {
00493         uint8_t status;
00494         do {
00495             status = HIDDKeyboard_ChangeKeys(pressedKeys,
00496                                             pressedKeysSize,
00497                                             releasedKeys,
00498                                             releasedKeysSize);
00499         } while (status != USBD_STATUS_SUCCESS);
00500     }
00501 }
00502 
00503 /**
00504  *  Invoked when a frame has been received.
00505  */
00506 static void FrameReceived(uint32_t unused,
00507                         uint8_t status,
00508                         uint32_t transferred,
00509                         uint32_t remaining)
00510 {
00511     unused = unused; /*dummy */
00512     remaining = remaining; /*dummy */
00513     if (status == USBD_STATUS_SUCCESS) {
00514         bufferSizes[inBufferIndex] = transferred / AUDDevice_BYTESPERSAMPLE;
00515         inBufferIndex = (inBufferIndex + 1) % BUFFER_NUMBER;
00516         numBuffersToSend++;
00517         /* Start DAc transmission if necessary */
00518         if (!isDacActive) {
00519             dacDelay = DAC_DELAY;
00520             isDacActive = 1;
00521         }
00522         /* Wait until a few buffers have been received */
00523         else if (dacDelay > 0) {
00524             dacDelay--;
00525         }
00526         /* Start sending buffers */
00527         else if (isFirstFrame) {
00528             isFirstFrame = 0;
00529             //AudioPlayEnable(1);
00530             _SscDma(&(SSC->SSC_THR), sscDmaTxChannel, buffers[outBufferIndex],
00531                     bufferSizes[outBufferIndex]);
00532             outBufferIndex = (outBufferIndex + 1) % BUFFER_NUMBER;
00533             numBuffersToSend --;
00534         }
00535     }
00536     else if (status == USBD_STATUS_ABORTED) {
00537         /* Error , ABORT, add NULL buffer */
00538         bufferSizes[inBufferIndex] = 0;
00539     } else {
00540         /* Packet is discarded */
00541     }
00542     /* Receive next packet */
00543     AUDDFunction_Read(buffers[inBufferIndex],
00544                     AUDDevice_BYTESPERFRAME,
00545                     (TransferCallback) FrameReceived,
00546                     0); // No optional argument
00547 }
00548 
00549 /*-------------------------------------------
00550  *      USB Device Driver callbacks
00551  *-------------------------------------------*/
00552 /**
00553  * Invoked when the configuration of the device changes. Parse used endpoints.
00554  * \param cfgnum New configuration number.
00555  */
00556 void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
00557 {
00558     HIDAUDDDriver_ConfigurationChangedHandler(cfgnum);
00559 }
00560 
00561 /**
00562  * Invoked whenever the active setting of an interface is changed by the
00563  * host. Reset streaming interface.
00564  * \param interface Interface number.
00565  * \param setting Newly active setting.
00566  */
00567 void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
00568                                             unsigned char setting)
00569 {
00570     HIDAUDDDriver_InterfaceSettingChangedHandler(interface, setting);
00571 }
00572 
00573 /**
00574  *  Invoked whenever a SETUP request is received from the host. Forwards the
00575  *  request to the standard handler.
00576  */
00577 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00578 {
00579     HIDAUDDDriver_RequestHandler(request);
00580 }
00581 
00582 /*-------------------------------------------
00583  *      USB Function driver callbacks
00584  *-------------------------------------------*/
00585 
00586 /**
00587  *  Invoked when an audio channel get muted or unmuted. Mutes/unmutes the
00588  *  channel at the DAC level.
00589  *  \param mic      Microphone/Speaker stream changed.
00590  *  \param channel  Channel number that changed.
00591  *  \param muted    Indicates the new mute status of the channel.
00592  */
00593 void AUDDFunction_MuteChanged(uint8_t mic, uint8_t channel, uint8_t muted)
00594 {
00595     if (mic) return;
00596 
00597     /* Speaker Master channel */
00598     if (channel == AUDD_CH_Master) {
00599         if (muted) {
00600             AudioPlayEnable(0);
00601             TRACE_WARNING("MuteMaster ");
00602         } else {
00603             TRACE_INFO("UnmuteMaster ");
00604             AudioPlayEnable(1);
00605         }
00606     }
00607 }
00608 
00609 /**
00610  *  Invoked when an audio streaming interface setting changed. Actually control
00611  *  streaming rate.
00612  *  \param mic         1 to indicate microphone mute changed.
00613  *  \param newSetting  New stream (interface) setting.
00614  */
00615 void AUDDFunction_StreamSettingChanged(uint8_t mic, uint8_t newSetting)
00616 {
00617     mic = mic; /* dummy */
00618     if (newSetting) {
00619         LED_Set(USBD_LEDOTHER);
00620         //XDMAD_StopTransfer(&dmad, sscDmaTxChannel);
00621         numBuffersToSend = 0;
00622     }
00623     else LED_Clear(USBD_LEDOTHER);
00624 }
00625 
00626 /**
00627  * Invoked when the status of the keyboard LEDs changes. Turns the num. lock
00628  * LED on or off.
00629  * \param numLockStatus Indicates the current status of the num. lock key.
00630  * \param capsLockStatus Indicates the current status of the caps lock key.
00631  * \param scrollLockStatus Indicates the current status of the scroll lock key
00632  */
00633 void HIDDKeyboardCallbacks_LedsChanged(
00634     uint8_t numLockStatus,
00635     uint8_t capsLockStatus,
00636     uint8_t scrollLockStatus)
00637 {
00638     capsLockStatus = capsLockStatus; /* dummy */
00639     scrollLockStatus = scrollLockStatus; /* dummy */
00640     /* Num. lock */
00641     if (numLockStatus) {
00642         LED_Set(LED_NUMLOCK);
00643     } else {
00644         LED_Clear(LED_NUMLOCK);
00645     }
00646 }
00647 
00648 /**
00649  * Configure USB settings for USB device
00650  */
00651 static void _ConfigureUsbhs(void)
00652 {
00653     /* UTMI parallel mode, High/Full/Low Speed */
00654     /* UUSBCK not used in this configuration (High Speed) */
00655     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00656     /* USB clock register: USB Clock Input is UTMI PLL */
00657     PMC->PMC_USB = PMC_USB_USBS;
00658     /* Enable peripheral clock for USBHS */
00659     PMC_EnablePeripheral(ID_USBHS);    
00660     USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00661     /* Enable PLL 480 MHz */
00662     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00663     /* Wait that PLL is considered locked by the PMC */
00664     while( !(PMC->PMC_SR & PMC_SR_LOCKU) );
00665     /* IRQ */
00666     NVIC_EnableIRQ(USBHS_IRQn) ;
00667 }
00668 /*----------------------------------------------------------------------------
00669  *         Exported functions
00670  *----------------------------------------------------------------------------*/
00671 
00672 /**
00673  *  \brief usb_iad_hid_aud Application entry point.
00674  *
00675  *  Starts the driver and waits for an audio input stream to forward to the DAC.
00676  */
00677 int main(void)
00678 {
00679     volatile uint8_t usbConn = 0;
00680     volatile uint8_t audioOn = 0;
00681     volatile uint32_t num = 0;
00682     int32_t  numDiff = 0, prevDiff = 0;
00683     int8_t   clockAdjust = 0;
00684 
00685     /* Disable watchdog */
00686     WDT_Disable( WDT );
00687     
00688     SCB_EnableICache();
00689     SCB_EnableDCache();
00690 
00691 
00692     printf("-- USB HID + Audio Device Example %s --\n\r", SOFTPACK_VERSION);
00693     printf("-- %s\n\r", BOARD_NAME);
00694     printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00695 
00696     TimeTick_Configure();
00697     /* Interrupt priority */
00698     NVIC_SetPriority( USBHS_IRQn, 2 );
00699     
00700     /* If they are present, configure Vbus & Wake-up pins */
00701     PIO_InitializeInterrupts(0);
00702 
00703     /* Initialize all USB power (off) */
00704     _ConfigureUsbhs();
00705 
00706     /* ----- HID Function Initialize */
00707 #ifdef NO_PUSHBUTTON
00708     printf( "-- : DBG key 1 2 used as buttons\n\r" );
00709     printf( "-- : 1st press to push, 2nd press to release\n\r" );
00710 #else
00711     /* Initialize key statuses and configure push buttons */
00712     PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons));
00713 #endif
00714     memset(keyStatus, 1, NUM_KEYS);
00715     //LED_Configure(LED_NUMLOCK);
00716 
00717     /* Audio STREAM LED */
00718     LED_Configure(USBD_LEDOTHER);
00719 
00720     /* Configure Audio */
00721     _ConfigureAudioPlay(AUDDevice_SAMPLERATE, BOARD_MCK);
00722 
00723     /* Configure DMA */
00724     _ConfigureDma();
00725 
00726     /* USB audio driver initialization */
00727     HIDAUDDDriver_Initialize(&hidauddDriverDescriptors);
00728 
00729     /* connect if needed */
00730     USBD_Connect();
00731 
00732     /* Infinite loop */
00733     while (1) {
00734         if (USBD_GetState() < USBD_STATE_CONFIGURED) {
00735             usbConn = 0;
00736             continue;
00737         }
00738         if (audioOn) {
00739             if(isDacActive == 0) {
00740                 AudioPlayEnable(0);
00741                 printf("audE ");
00742                 isFirstFrame = 1;
00743                 audioOn = 0;
00744             } else {
00745                 if (num != numBuffersToSend) {
00746                     num = numBuffersToSend;
00747                 }
00748                 numDiff = numBuffersToSend - DAC_DELAY;
00749                 if (prevDiff != numDiff) {
00750                     prevDiff = numDiff;
00751                     if (numDiff > 0 && clockAdjust != 1) {
00752                       printf("+");
00753                         /* USB too fast or SSC too slow: faster clock */
00754                         clockAdjust = 1;
00755                         _SyncAdjust(1);
00756                     }
00757                     if (numDiff < 0 && clockAdjust != -1) {
00758                       printf("-");
00759                         /* USB too slow or SSC too fast: slower clock */
00760                         clockAdjust = -1;
00761                         _SyncAdjust(-1);
00762                     }
00763                     if (numDiff == 0 && clockAdjust != 0) {
00764                         clockAdjust = 0;
00765                         _SyncAdjust(0);
00766                     }
00767                 }
00768             }
00769         } else if (isDacActive) {
00770             printf("audS ");
00771             audioOn = 1;
00772         }
00773         if (usbConn == 0) {
00774             usbConn = 1;
00775             /* Start Reading the incoming audio stream */
00776             AUDDFunction_Read(buffers[inBufferIndex],
00777                             AUDDevice_BYTESPERFRAME,
00778                             (TransferCallback) FrameReceived,
00779                             0); // No optional argument
00780         }
00781         HIDDKeyboardProcessKeys();
00782     }
00783 }
00784 /** \endcond */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines