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_cdc
00030  *  \page usb_cdc USB communication device class Example
00031  *
00032  *  \section Purpose
00033  *
00034  *  The USB communication device class Example will help you to get familiar
00035  *  with the USB communication device class 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 communication 
00038  *  device class.
00039  *
00040  *  \section Requirements
00041  *
00042  *  This package can be used with SAMV71 Xplained board
00043  *  The device uses the USB communication device class (CDC) drivers to take 
00044  *  advantage of the installed PC RS-232
00045  *  software to talk over the USB.
00046  *
00047  *  \section Usage
00048  *
00049  *  -# Build the program and download it inside the SAM V71 Xplained Ultra board. 
00050  *     Please refer to the Getting Started with SAM V71 Microcontrollers.pdf
00051  *  -# On the computer, open and configure a terminal application
00052  *     (e.g. HyperTerminal on Microsoft Windows) with these settings:
00053  *    - 115200 bauds
00054  *    - 8 bits of data
00055  *    - No parity
00056  *    - 1 stop bit
00057  *    - No flow control
00058  *  -# Start the application.
00059  *  -# In the terminal window, the following text should appear:
00060  *  \code
00061  *  -- USB Device CDC Serial Project xxx --
00062  *  -- SAMxxxxx-xx
00063  *  -- Compiled: xxx xx xxxx xx:xx:xx --
00064  *  \endcode
00065  *
00066  *  \section References
00067  *  - usb_cdc/main.c
00068  *  - usb: USB Framework, USB communication device class driver
00069  *      - \ref usbd_framework
00070  *      - \ref usbd_api
00071  *      - \ref usbd_cdc
00072  */
00073 
00074 /**
00075  *  \file
00076  *
00077  *  This file contains all the specific code for the
00078  *  usb_cdc example.
00079  */
00080 /*----------------------------------------------------------------------------
00081  *         Headers
00082  *----------------------------------------------------------------------------*/
00083 
00084 #include "board.h"
00085 
00086 #include "USBD.h"
00087 #include "CDCDSerialDriver.h"
00088 
00089 #include <stdbool.h>
00090 #include <stdint.h>
00091 
00092 /*----------------------------------------------------------------------------
00093  *      Definitions
00094  *----------------------------------------------------------------------------*/
00095 
00096 /** Size in bytes of the packet used for reading data from the USB & USART */
00097 #define DATAPACKETSIZE (64)
00098 
00099 /** Size in bytes of the buffer used for reading data from the USB & USART */
00100 #define DATABUFFERSIZE (DATAPACKETSIZE+2)
00101 
00102 /** Pins used for USART transfer */
00103 #define PINS_USART      PIN_USART2_TXD, PIN_USART2_RXD
00104 /** Register base for USART operation */
00105 #define BASE_USART      USART2
00106 /** USART ID */
00107 #define ID_USART        ID_USART2
00108 
00109 /** test buffer size */
00110 #define TEST_BUFFER_SIZE    (2*1024)
00111 /** write loop count */
00112 #define TEST_COUNT          (30)
00113 
00114 /*----------------------------------------------------------------------------
00115  *      External variables
00116  *----------------------------------------------------------------------------*/
00117 
00118 extern const USBDDriverDescriptors cdcdSerialDriverDescriptors;
00119 
00120 /*----------------------------------------------------------------------------
00121  *      Internal variables
00122  *----------------------------------------------------------------------------*/
00123 
00124 /** Global DMA driver for all transfer */
00125 static sXdmad dmad;
00126 
00127 /** DMA channel for RX */
00128 static uint32_t usartDmaRxChannel;
00129 /** DMA channel for TX */
00130 static uint32_t usartDmaTxChannel;
00131 
00132 /** USART link list for data RX */
00133 static LinkedListDescriporView1 dmaRxLinkList[2];
00134 
00135 /** List of pins that must be configured for use by the application. */
00136 static const Pin pins[] = {PINS_USART};
00137 
00138 /** Double-buffer for storing incoming USART data. */
00139 static uint8_t usartBuffers[2][DATABUFFERSIZE];
00140 
00141 /** Current USART buffer index. */
00142 static uint8_t usartCurrentBuffer = 0;
00143 
00144 /** Buffer for storing incoming USB data. */
00145 static uint8_t usbBuffer[DATABUFFERSIZE];
00146 
00147 /** Serial Port ON/OFF */
00148 static uint8_t isCdcSerialON = 0;
00149 
00150 /** CDC Echo back ON/OFF */
00151 static uint8_t isCdcEchoON = 0;
00152 
00153 /** USB Tx flag */
00154 static volatile uint8_t txDoneFlag = 0;
00155 /** Test buffer */
00156 static uint8_t testBuffer[TEST_BUFFER_SIZE];
00157 
00158 /*----------------------------------------------------------------------------
00159  *  Interrupt handlers
00160  *----------------------------------------------------------------------------*/
00161 /**
00162  * ISR for xDMA interrupt
00163  */
00164 void XDMAC_Handler(void)
00165 {
00166     XDMAD_Handler(&dmad);
00167 }
00168 
00169 /**
00170  * USART interrupt handler
00171  */
00172 void USART2_Handler(void)
00173 {
00174     Usart *pUs = BASE_USART;
00175     uint32_t status;
00176     uint16_t serialState;
00177 
00178     status  = USART_GetStatus(pUs);
00179     status &= USART_GetItMask(pUs);
00180 
00181     /* If USB device is not configured, do nothing */
00182     if (!isCdcSerialON) {
00183         USART_DisableIt(pUs, 0xFFFFFFFF);
00184         return;
00185     }
00186 
00187     /* Errors */
00188     serialState = CDCDSerialDriver_GetSerialState();
00189     /* Overrun */
00190     if ((status & US_CSR_OVRE) != 0) {
00191         TRACE_WARNING( "USART_IrqHandler: Overrun\n\r");
00192         serialState |= CDCSerialState_OVERRUN;
00193     }
00194     /* Framing error */
00195     if ((status & US_CSR_FRAME) != 0) {
00196         TRACE_WARNING( "USART_IrqHandler: Framing error\n\r");
00197         serialState |= CDCSerialState_FRAMING;
00198     }
00199     CDCDSerialDriver_SetSerialState(serialState);
00200 }
00201 
00202 static void _UsartDmaRx(uint32_t );
00203 
00204 /*-----------------------------------------------------------------------------
00205  *         Callback re-implementation
00206  *-----------------------------------------------------------------------------*/
00207 /**
00208  * Invoked when the configuration of the device changes. Parse used endpoints.
00209  * \param cfgnum New configuration number.
00210  */
00211 void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
00212 {
00213     CDCDSerialDriver_ConfigurationChangedHandler(cfgnum);
00214 }
00215 
00216 /**
00217  * Invoked when a new SETUP request is received from the host. Forwards the
00218  * request to the Mass Storage device driver handler function.
00219  * \param request  Pointer to a USBGenericRequest instance.
00220  */
00221 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00222 {
00223     CDCDSerialDriver_RequestHandler(request);
00224 }
00225 
00226 /*----------------------------------------------------------------------------
00227  *         Internal functions
00228  *----------------------------------------------------------------------------*/
00229 
00230 
00231 /**
00232  *  \brief Send single buffer data through DMA
00233  */
00234 static void _UsartDmaTx( uint32_t dwDestAddr,
00235                          void* pBuffer, uint16_t wSize )
00236 {
00237     sXdmad *pDmad = &dmad;
00238     /* Setup transfer */
00239     sXdmadCfg xdmadCfg;
00240     xdmadCfg.mbr_ubc = wSize ;
00241     xdmadCfg.mbr_sa = (uint32_t) pBuffer;
00242     xdmadCfg.mbr_da = (uint32_t) dwDestAddr;
00243     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN 
00244                     | XDMAC_CC_MEMSET_NORMAL_MODE 
00245                     | XDMAC_CC_CSIZE_CHK_1 
00246                     | XDMAC_CC_DWIDTH_BYTE
00247                     | XDMAC_CC_SIF_AHB_IF0 
00248                     | XDMAC_CC_DIF_AHB_IF1 
00249                     | XDMAC_CC_SAM_INCREMENTED_AM 
00250                     | XDMAC_CC_DAM_FIXED_AM
00251                     | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_USART, XDMAD_TRANSFER_TX ));
00252     xdmadCfg.mbr_bc = 0;
00253     XDMAD_ConfigureTransfer( pDmad, usartDmaTxChannel, &xdmadCfg, 0, 0, (
00254                                 XDMAC_CIE_BIE   |
00255                                 XDMAC_CIE_DIE   |
00256                                 XDMAC_CIE_FIE   |
00257                                 XDMAC_CIE_RBIE  |
00258                                 XDMAC_CIE_WBIE  |
00259                                 XDMAC_CIE_ROIE));
00260     XDMAD_StartTransfer( pDmad, usartDmaTxChannel );
00261 }
00262 
00263 /**
00264  *  \brief Prepare link list for USART RX
00265  *  Ringed link list initialized for 2 USART buffer.
00266  */
00267 static void _UsartDmaRxSetup( void )
00268 {
00269     uint8_t i;
00270     Usart *pUs = BASE_USART;
00271     for (i = 0; i < 2; i++) {
00272         dmaRxLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 
00273                                 | XDMA_UBC_NDE_FETCH_EN
00274                                 | XDMA_UBC_NSEN_UPDATED 
00275                                 | XDMAC_CUBC_UBLEN(DATAPACKETSIZE);
00276         dmaRxLinkList[i].mbr_sa  = (uint32_t)&pUs->US_RHR;
00277         dmaRxLinkList[i].mbr_da = (uint32_t)usartBuffers[i];
00278         dmaRxLinkList[i].mbr_nda = (uint32_t)&dmaRxLinkList[i];
00279     }
00280 }
00281 
00282 /**
00283  *  \brief Start waiting USART data
00284  *  Start DMA, the 1st DMA buffer is free USART buffer assigned.
00285  */
00286 static void _UsartDmaRx( uint32_t startBuffer )
00287 {
00288     sXdmad *pDmad = &dmad;
00289     sXdmadCfg xdmadUsartRxCfg;
00290     uint32_t xdmaUsartRxCndc, xdmaInt;
00291     xdmadUsartRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN 
00292                             | XDMAC_CC_MBSIZE_SINGLE 
00293                             | XDMAC_CC_DSYNC_PER2MEM 
00294                             | XDMAC_CC_CSIZE_CHK_1 
00295                             | XDMAC_CC_DWIDTH_BYTE
00296                             | XDMAC_CC_SIF_AHB_IF1 
00297                             | XDMAC_CC_DIF_AHB_IF0 
00298                             | XDMAC_CC_SAM_FIXED_AM 
00299                             | XDMAC_CC_DAM_INCREMENTED_AM 
00300                             | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber( ID_USART, XDMAD_TRANSFER_RX ));
00301     xdmaUsartRxCndc = XDMAC_CNDC_NDVIEW_NDV1 
00302                     | XDMAC_CNDC_NDE_DSCR_FETCH_EN 
00303                     | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00304                     | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;
00305     xdmaInt = XDMAC_CIE_LIE;
00306     
00307     XDMAD_ConfigureTransfer( pDmad, usartDmaRxChannel, &xdmadUsartRxCfg, 
00308                 xdmaUsartRxCndc, (uint32_t)&dmaRxLinkList[startBuffer], xdmaInt);
00309     XDMAD_StartTransfer(pDmad, usartDmaRxChannel);
00310 }
00311 
00312 /**
00313  * DBGU help dump
00314  */
00315 static void _DebugHelp(void)
00316 {
00317     printf("\n\r==========================================================\n\r");
00318     printf("-- ESC to Enable/Disable ECHO on cdc serial --\n\r");
00319     printf("-- Press 't' to test transfer --\n\r");
00320     printf("\n\r==========================================================\n\r");
00321 }
00322 
00323 /*----------------------------------------------------------------------------
00324  * Callback invoked when data has been received on the USB.
00325  *----------------------------------------------------------------------------*/
00326 static void _UsbDataReceived(uint32_t unused,
00327                             uint8_t status,
00328                             uint32_t received,
00329                             uint32_t remaining)
00330 {
00331     unused = unused;
00332     Usart *pUs = BASE_USART;
00333 
00334     /* Check that data has been received successfully */
00335     if (status == USBD_STATUS_SUCCESS) {
00336 
00337         /* Send back CDC data */
00338         if (isCdcEchoON) {
00339             CDCDSerialDriver_Write(usbBuffer, received, 0, 0);
00340         }
00341         /* Send data through USART */
00342         if (isCdcSerialON) {
00343             _UsartDmaTx( (uint32_t)&pUs->US_THR, usbBuffer, received );
00344         }
00345 
00346         /* Check if bytes have been discarded */
00347         if ((received == DATAPACKETSIZE) && (remaining > 0)) {
00348             TRACE_WARNING(
00349                       "_UsbDataReceived: %u bytes discarded\n\r",
00350                       (unsigned int)remaining);
00351         }
00352     } else {
00353         TRACE_WARNING( "_UsbDataReceived: Transfer error\n\r");
00354     }
00355 }
00356 
00357 /**
00358  * Callback invoked when data has been sent.
00359  */
00360 static void _UsbDataSent(void)
00361 {
00362     txDoneFlag = 1;
00363 }
00364 
00365 /**
00366  * \brief DMA RX callback function
00367  */
00368 static void _UsDmaRxCallback( uint8_t status, void *pArg)
00369 {
00370     pArg = pArg;
00371     if (status != XDMAD_OK) return;
00372 
00373     /* Send buffer through the USB */
00374     while (CDCDSerialDriver_Write(usartBuffers[usartCurrentBuffer],
00375                             DATAPACKETSIZE, 0, 0) != USBD_STATUS_SUCCESS);
00376     
00377     /* Restart read on buffer */
00378     usartCurrentBuffer = 1 - usartCurrentBuffer;
00379     _UsartDmaRx(usartCurrentBuffer);
00380     
00381 }
00382 
00383 /**
00384  * \brief DMA TX callback function
00385  */
00386 static void _UsDmaTxCallback( uint8_t status, void *pArg)
00387 {
00388     pArg = pArg;
00389     if (status != XDMAD_OK) return;
00390 
00391     /* Restart USB read */
00392     CDCDSerialDriver_Read(usbBuffer,
00393                         DATAPACKETSIZE,
00394                         (TransferCallback) _UsbDataReceived,
00395                         0);
00396 }
00397 
00398 /**
00399  * \brief DMA driver configuration
00400  */
00401 static void _ConfigureDma( void )
00402 {
00403     sXdmad *pDmad = &dmad;
00404     /* Driver initialize */
00405     XDMAD_Initialize( &dmad, 0 );
00406     /* IRQ configure */
00407     NVIC_EnableIRQ(XDMAC_IRQn);
00408 
00409     /* Allocate DMA channels for USART */
00410     usartDmaTxChannel = XDMAD_AllocateChannel( pDmad, XDMAD_TRANSFER_MEMORY, ID_USART);
00411     usartDmaRxChannel = XDMAD_AllocateChannel( pDmad, ID_USART, XDMAD_TRANSFER_MEMORY);
00412 
00413     /* Set RX callback */
00414     XDMAD_SetCallback(pDmad, usartDmaRxChannel,(XdmadTransferCallback)_UsDmaRxCallback, 
00415             0);
00416     /* Set TX callback */
00417     XDMAD_SetCallback(pDmad, usartDmaTxChannel,(XdmadTransferCallback)_UsDmaTxCallback, 
00418             0);
00419     XDMAD_PrepareChannel( pDmad, usartDmaRxChannel);
00420     XDMAD_PrepareChannel( pDmad, usartDmaTxChannel);
00421 }
00422 
00423 /**
00424  * Configure USART to work @ 115200
00425  */
00426 static void _ConfigureUsart(void)
00427 {
00428     PIO_Configure(pins, PIO_LISTSIZE(pins));
00429     PMC_EnablePeripheral(ID_USART);
00430     USART_DisableIt(BASE_USART, 0xFFFFFFFF);
00431     USART_Configure(BASE_USART,
00432                     USART_MODE_ASYNCHRONOUS,
00433                     115200,
00434                     BOARD_MCK);
00435 
00436     USART_SetTransmitterEnabled(BASE_USART, 1);
00437     USART_SetReceiverEnabled(BASE_USART, 1);
00438     NVIC_EnableIRQ(USART2_IRQn);
00439 }
00440 
00441 /**
00442  * Test USB CDC Serial 
00443  */
00444 static void _SendText(void)
00445 {
00446     uint32_t i, testCnt;
00447 
00448     if (!isCdcSerialON) {
00449         printf("\n\r!! Host serial program not ready!\n\r");
00450         return;
00451     }
00452     printf("\n\r- USB CDC Serial writing ...\n\r");
00453 
00454     /* Test data initialize */
00455     for (i = 0; i < TEST_BUFFER_SIZE; i ++) testBuffer[i] = (i % 10) + '0';
00456 
00457     printf("- Send 0,1,2 ... to host:\n\r");
00458     for (testCnt = 0; testCnt < TEST_COUNT; testCnt ++) {
00459         txDoneFlag = 0;
00460         CDCDSerialDriver_Write(testBuffer,
00461                                TEST_BUFFER_SIZE,
00462                                (TransferCallback) _UsbDataSent, 0);
00463         while(!txDoneFlag);
00464     }
00465     /* Finish sending */
00466     CDCDSerialDriver_Write(testBuffer, 0, 0, 0);
00467 }
00468 
00469 /**
00470  * Configure USBHS settings for USB device
00471  */
00472 static void _ConfigureUotghs(void)
00473 {
00474   
00475     /* UTMI parallel mode, High/Full/Low Speed */
00476     /* UOTGCK not used in this configuration (High Speed) */
00477     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00478     /* USB clock register: USB Clock Input is UTMI PLL */
00479     PMC->PMC_USB = PMC_USB_USBS;
00480     /* Enable peripheral clock for USBHS */
00481     PMC_EnablePeripheral(ID_USBHS);    
00482     USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00483     /* Enable PLL 480 MHz */
00484     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00485     /* Wait that PLL is considered locked by the PMC */
00486     while( !(PMC->PMC_SR & PMC_SR_LOCKU) );
00487 
00488     /* IRQ */
00489     NVIC_EnableIRQ(USBHS_IRQn) ;
00490 }
00491 
00492 
00493 /*_____ E X P O R T E D   F U N C T I O N S ________________________________*/
00494 
00495 /*! \brief Main function. Execution starts here.
00496  */
00497 int main(void)
00498 { 
00499       uint8_t isUsbConnected = 0;
00500     /* Disable watchdog */
00501     WDT_Disable( WDT ) ;
00502 
00503 
00504     SCB_EnableICache();
00505     SCB_EnableDCache();
00506 
00507     /* Output example information */
00508     printf("-- USB Device CDC Serial Project %s --\n\r", SOFTPACK_VERSION);
00509     printf("-- %s\n\r", BOARD_NAME);
00510     printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00511 
00512     /* Initialize PIO interrupts */
00513     PIO_InitializeInterrupts(0);
00514     
00515     /* Interrupt priority */
00516     NVIC_SetPriority( USBHS_IRQn, 2 );
00517     
00518     /* Configure DMA driver */
00519     _ConfigureDma();
00520 
00521     /* Configure USART */
00522     _ConfigureUsart();
00523     _UsartDmaRxSetup();
00524     
00525     /* Initialize OTG clocks */
00526     _ConfigureUotghs();
00527 
00528     /* CDC serial driver initialization */
00529     CDCDSerialDriver_Initialize(&cdcdSerialDriverDescriptors);
00530 
00531     /* Help information */
00532     _DebugHelp();
00533 
00534      // Start USB stack to authorize VBus monitoring
00535     USBD_Connect();
00536 
00537     /* Driver loop */
00538     while (1) {
00539         /* Device is not configured */
00540         if (USBD_GetState() < USBD_STATE_CONFIGURED) {
00541             if (isUsbConnected) {
00542                 isUsbConnected = 0;
00543                 isCdcSerialON  = 0;
00544             }
00545         } else if (isUsbConnected == 0) {
00546             isUsbConnected = 1;
00547         }
00548 
00549         /* Serial port ON/OFF */
00550         if (CDCDSerialDriver_GetControlLineState() & CDCControlLineState_DTR) {
00551             if (!isCdcSerialON) {
00552                 isCdcSerialON = 1;
00553 
00554                 /* Start receiving data on the USART */
00555                 usartCurrentBuffer = 0;
00556                 _UsartDmaRx( usartCurrentBuffer );
00557                 USART_EnableIt( BASE_USART, US_CSR_FRAME | US_CSR_OVRE );
00558                 /* Start receiving data on the USB */
00559                 CDCDSerialDriver_Read(usbBuffer,
00560                                     DATAPACKETSIZE,
00561                                     (TransferCallback) _UsbDataReceived,
00562                                     0);
00563             }
00564         } else if (isCdcSerialON) {
00565             isCdcSerialON = 0;
00566         }
00567 
00568         if (DBG_IsRxReady()) {
00569             uint8_t key = DBG_GetChar();
00570             /* ESC: CDC Echo ON/OFF */
00571             if (key == 27) {
00572                 printf("** CDC Echo %s\n\r",
00573                         isCdcEchoON ? "OFF" : "ON");
00574                 isCdcEchoON = !isCdcEchoON;
00575             }
00576             /* 't': Test CDC writing  */
00577             else if (key == 't') {
00578                 _SendText();
00579             } else {
00580                 printf("Alive\n\r");
00581                 CDCDSerialDriver_Write((char*)"Alive\n\r", 8, 0, 0);
00582                 _DebugHelp();
00583             }
00584         }
00585     }
00586 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines