SAMV71 Xplained Ultra Software Package 1.5

main.c

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