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_iad_cdc_hid
00030  * \page usb_iad_cdc_hid USB CDC(Serial)+HID(Keyboard) Example
00031  *
00032  * \section Purpose
00033  *
00034  * The USB CDCHID Project will help you to get familiar with the
00035  * USB Device Port(UDP)interface .Also it can help you to be familiar with the USB
00036  * Framework that is used for rapid development of USB-compliant class
00037  * drivers such as USB Communication Device class (CDC), and how to combine
00038  * two USB functions to a single composite device (such as CDC + HID).
00039  *
00040  * \section Requirements
00041  *
00042  * This package can be used with some of Atmel Xplained board that have UDP
00043  * interface, depending on the functions included.
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  * This demo simulates a USB composite device that has USB Serial RS232
00053  * Converter and USB HID Keyboard functions.
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. No device
00057  * driver offered for the device now.
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 CDC HID Device Project 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.
00079  * -# For the windows driver installation and the test functions, please
00080  *      refer to "USB CDC serial converter" &
00081  *      "USB HID Keyboard Project".
00082  * -# You can use the inf file
00083  *    libraries\\usb\\device\\composite\\drv\\CompositeCDCSerial.inf
00084  *    to install the CDC serial  port.
00085  *
00086  * \section Reference
00087  * - usb_iad_cdc_hid/main.c
00088  * - pio: Pin configurations and peripheral configure.
00089  * - usb: USB Device Framework, USB CDC 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_hid "hid" \\ \ref usbd_hid_key "hid-keyboard"
00095  *       - \ref usbd_hid_kbd_drv
00096  *    - \ref usbd_cdc "cdc-serial"
00097  *       - \ref usbd_cdc_serial_drv
00098  * - projects:
00099  *    - \ref usb_hid_keyboard
00100  *    - \ref usb_cdc_serial
00101  *
00102  */
00103 
00104 /**
00105  * \file
00106  *
00107  * This file contains all the specific code for the
00108  * usb_iad_cdc_hid project
00109  */
00110 
00111 /*----------------------------------------------------------------------------
00112  *        Headers
00113  *----------------------------------------------------------------------------*/
00114 
00115 #include "board.h"
00116 
00117 #include <USBD_Config.h>
00118 #include <USBD_LEDs.h>
00119 
00120 #include <CDCHIDDDriver.h>
00121 #include <CDCDSerial.h>
00122 #include <HIDDKeyboard.h>
00123 
00124 #include <string.h>
00125 #include <stdbool.h>
00126 #include <stdint.h>
00127 #include <stdio.h>
00128 
00129 /*---------------------------------------------------------------------------
00130  *      Definitions
00131  *---------------------------------------------------------------------------*/
00132 #define NO_PUSHBUTTON
00133 /** Number of keys used in the example. */
00134 #define NUM_KEYS                    2
00135 
00136 /** Number of non-modifiers keys. */
00137 #define NUM_NORMAL_KEYS             1
00138 
00139 /** Number of modifier keys. */
00140 #define NUM_MODIFIER_KEYS           (NUM_KEYS - NUM_NORMAL_KEYS)
00141 
00142 /** NumLock LED index. */
00143 #define LED_NUMLOCK                 USBD_LEDOTHER
00144 
00145 /** Size in bytes of the packet used for reading data from USB */
00146 #define DATAPACKETSIZE \
00147     CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN)
00148 
00149 /** Size in bytes of the buffer used for reading data from the USB & USART */
00150 #define DATABUFFERSIZE (DATAPACKETSIZE+2)
00151 
00152 /*----------------------------------------------------------------------------
00153  *      External variables
00154  *----------------------------------------------------------------------------*/
00155 
00156 extern const USBDDriverDescriptors cdchiddDriverDescriptors;
00157 
00158 /*---------------------------------------------------------------------------
00159  *      Internal variables
00160  *---------------------------------------------------------------------------*/
00161 
00162 /** Buffer for storing incoming USB data. */
00163 static unsigned char usbSerialBuffer0[DATABUFFERSIZE];
00164 
00165 /** Serial port opened */
00166 static unsigned char isSerialPortON = 0;
00167 
00168 /*- HID */
00169 
00170 #ifdef NO_PUSHBUTTON
00171 #else
00172 /** List of pinsPushButtons to configure for the application. */
00173 static Pin pinsPushButtons[] = {PINS_PUSHBUTTONS};
00174 #endif
00175 
00176 /** Array of key codes produced by each button. */
00177 static uint8_t keyCodes[NUM_KEYS] = {
00178     HIDKeypad_A,
00179     HIDKeypad_NUMLOCK,
00180 };
00181 
00182 /** Current status (pressed or not) for each key. */
00183 static uint8_t keyStatus[NUM_KEYS];
00184 
00185 /*-----------------------------------------------------------------------------
00186  *         Callback re-implementation
00187  *-----------------------------------------------------------------------------*/
00188 
00189 
00190 
00191 /**
00192  * Invoked when the configuration of the device changes. Parse used endpoints.
00193  * \param cfgnum New configuration number.
00194  */
00195 void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
00196 {
00197     CDCHIDDDriver_ConfigurationChangedHandler(cfgnum);
00198 }
00199 
00200 /**
00201  * Invoked when a new SETUP request is received from the host. Forwards the
00202  * request to the Mass Storage device driver handler function.
00203  * \param request  Pointer to a USBGenericRequest instance.
00204  */
00205 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00206 {
00207     CDCHIDDDriver_RequestHandler(request);
00208 }
00209 
00210 /*----------------------------------------------------------------------------
00211  *         Callbacks
00212  *----------------------------------------------------------------------------*/
00213 
00214 /**
00215  * Invoked when the CDC ControlLineState is changed
00216  * \param DTR   New DTR value.
00217  * \param RTS   New RTS value.
00218  */
00219 void CDCDSerial_ControlLineStateChanged(uint8_t DTR,
00220                                     uint8_t RTS)
00221 {
00222     isSerialPortON = DTR;
00223     RTS = RTS; /* dummy */
00224 }
00225 
00226 /**
00227  * Invoked when the status of the keyboard LEDs changes. Turns the num. lock
00228  * LED on or off.
00229  * \param numLockStatus Indicates the current status of the num. lock key.
00230  * \param capsLockStatus Indicates the current status of the caps lock key.
00231  * \param scrollLockStatus Indicates the current status of the scroll lock key
00232  */
00233 void HIDDKeyboardCallbacks_LedsChanged(
00234     uint8_t numLockStatus,
00235     uint8_t capsLockStatus,
00236     uint8_t scrollLockStatus)
00237 {
00238     capsLockStatus = capsLockStatus; 
00239     scrollLockStatus = scrollLockStatus;
00240     /* Num. lock */
00241     if (numLockStatus) {
00242         LED_Set(LED_NUMLOCK);
00243     } else {
00244         LED_Clear(LED_NUMLOCK);
00245     }
00246 }
00247 
00248 /*---------------------------------------------------------------------------
00249  *         Internal functions
00250  *---------------------------------------------------------------------------*/
00251 
00252 /**
00253  * Monitor keyboard buttons & Update key status in HID driver
00254  */
00255 static void _HIDDKeyboardProcessKeys(void)
00256 {
00257     uint32_t i;
00258     uint8_t pressedKeys[NUM_KEYS];
00259     uint8_t pressedKeysSize = 0;
00260     uint8_t releasedKeys[NUM_KEYS];
00261     uint8_t releasedKeysSize = 0;
00262 
00263     /* Monitor buttons */
00264 #ifdef NO_PUSHBUTTON
00265     if (DBG_IsRxReady()) {
00266         uint8_t key = DBG_GetChar();
00267         switch(key) {
00268         case '1': case '2':
00269             i = key - '1';
00270             if (keyStatus[i]) {
00271                 /* Key press simulation */
00272                 TRACE_INFO("Key %u pressed\n\r", (unsigned int)i);
00273                 keyStatus[i] = 0;
00274                 pressedKeys[pressedKeysSize] = keyCodes[i];
00275                 pressedKeysSize ++;
00276                 HIDDKeyboard_RemoteWakeUp();
00277             } else {
00278                 /* Key release simulation */
00279                 TRACE_INFO("Key %u released\n\r", (unsigned int)i);
00280                 keyStatus[i] = 1;
00281                 releasedKeys[releasedKeysSize] = keyCodes[i];
00282                 releasedKeysSize++;
00283             }
00284             break;
00285         default: DBG_PutChar(key);
00286         }
00287     }
00288 #else
00289     for (i=0; i < PIO_LISTSIZE(pinsPushButtons); i++) {
00290         /* Check if button state has changed */
00291         uint8_t isButtonPressed = PIO_Get(&(pinsPushButtons[i]));
00292         if (isButtonPressed != keyStatus[i]) {
00293             /* Update button state */
00294             if (!isButtonPressed) {
00295                 /* Key has been pressed */
00296                 TRACE_INFO("Key %u has been pressed\n\r", i);
00297                 keyStatus[i] = 0;
00298                 pressedKeys[pressedKeysSize] = keyCodes[i];
00299                 pressedKeysSize++;
00300                 HIDDKeyboard_RemoteWakeUp();
00301             } else {
00302                 /* Key has been released */
00303                 TRACE_INFO("Key %u has been released\n\r", i);
00304                 keyStatus[i] = 1;
00305                 releasedKeys[releasedKeysSize] = keyCodes[i];
00306                 releasedKeysSize++;
00307             }
00308         }
00309     }
00310 #endif
00311 
00312     /* Update key status in the HID driver if necessary */
00313     if ((pressedKeysSize != 0) || (releasedKeysSize != 0)) {
00314         uint8_t status;
00315         do {
00316             status = HIDDKeyboard_ChangeKeys(pressedKeys,
00317                                              pressedKeysSize,
00318                                              releasedKeys,
00319                                              releasedKeysSize);
00320         } while (status != USBD_STATUS_SUCCESS);
00321     }
00322 }
00323 
00324 /**
00325  * Configure USBHS settings for USB device
00326  */
00327 static void _ConfigureUotghs(void)
00328 {
00329     /* UTMI parallel mode, High/Full/Low Speed */
00330     /* UUSBCK not used in this configuration (High Speed) */
00331     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00332     /* USB clock register: USB Clock Input is UTMI PLL */
00333     PMC->PMC_USB = PMC_USB_USBS;
00334     /* Enable peripheral clock for USBHS */
00335     PMC_EnablePeripheral(ID_USBHS);    
00336     USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00337     /* Enable PLL 480 MHz */
00338     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00339     /* Wait that PLL is considered locked by the PMC */
00340     while( !(PMC->PMC_SR & PMC_SR_LOCKU) );
00341 
00342     /* IRQ */
00343     NVIC_EnableIRQ(USBHS_IRQn) ;
00344 }
00345 
00346 /*---------------------------------------------------------------------------
00347  *         Exported function
00348  *---------------------------------------------------------------------------*/
00349 /**
00350  * Initializes drivers and start the USB CDCHID device.
00351  */
00352 int main(void)
00353 {
00354     uint8_t usbConnected = 0, serialON = 0;
00355 
00356     /* Disable watchdog */
00357     WDT_Disable( WDT );
00358 
00359     SCB_EnableICache();
00360     SCB_EnableDCache();
00361 
00362     printf("-- USB CDC HID Device Project %s --\n\r", SOFTPACK_VERSION);
00363     printf("-- %s\n\r", BOARD_NAME);
00364     printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00365 
00366     /* If they are present, configure Vbus & Wake-up pins */
00367     PIO_InitializeInterrupts(0);
00368 
00369     /* If there is on board power, switch it off */
00370     _ConfigureUotghs();
00371 
00372     /* ----- HID Function Initialize */
00373 #ifdef NO_PUSHBUTTON
00374     printf( "-- : DBG key 1 2 used as buttons\n\r" );
00375     printf( "-- : 1st press to push, 2nd press to release\n\r" );
00376 #else
00377     /* Initialize key statuses and configure push buttons */
00378     PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons));
00379 #endif
00380     memset(keyStatus, 1, NUM_KEYS);
00381 
00382     /* Configure LEDs */
00383     LED_Configure(LED_NUMLOCK);
00384 
00385 
00386     /* USB CDCHID driver initialization */
00387     CDCHIDDDriver_Initialize(&cdchiddDriverDescriptors);
00388 
00389     /* connect if needed */
00390     USBD_Connect();
00391 
00392     /* Driver loop */
00393     while (1) {
00394         /* Device is not configured */
00395         if (USBD_GetState() < USBD_STATE_CONFIGURED) {
00396             if (usbConnected) {
00397                 printf("-I- USB Disconnect/Suspend\n\r");
00398                 usbConnected = 0;
00399                 /* Serial port closed */
00400                 isSerialPortON = 0;
00401             }
00402         } else {
00403             if (usbConnected == 0) {
00404                 printf("-I- USB Connect\n\r");
00405                 usbConnected = 1;
00406             }
00407             if (!serialON && isSerialPortON) {
00408                 printf("-I- SerialPort ON\n\r");
00409                 /* Start receiving data on the USB */
00410                 CDCDSerial_Read(usbSerialBuffer0,
00411                                 DATAPACKETSIZE,
00412                                 0,
00413                                 0);
00414                 serialON = 1;
00415             } else if (serialON && !isSerialPortON) {
00416                 printf("-I- SeriaoPort OFF\n\r");
00417                 serialON = 0;
00418             }
00419             _HIDDKeyboardProcessKeys();
00420         }
00421     }
00422 }
00423 /** \endcond */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines