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 
00030 /** \cond usb_hid_keyboard
00031  * \page usb_hid_keyboard USB HID Keyboard Example
00032  *
00033  * \section Purpose
00034  *
00035  * The USB HID Keyboard Example will help you to get familiar with the
00036  * USB Device Port(UDP) and PIO interface on SAMV7/E7 Microcontrollers. Also
00037  * it can help you to be familiar with the USB Framework that is used for
00038  * rapid development of USB-compliant class drivers such as USB human
00039  * Interface Device class (HID).
00040  *
00041  *  \section Requirements
00042  *
00043  *  This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board.
00044  *
00045  * \section Description
00046  *
00047  * The demo simulates a simple keyboard with a caps lock and 'a' on it.
00048  *
00049  * When a board running this program connected to a host (PC for
00050  * example), with USB cable, the board appears as a HID Keyboard for
00051  * the host. Then you can use the push buttons on the board to input
00052  * letter to the host. E.g, to open a editor and input a letter 'a'.
00053  *
00054  * \section Usage
00055  *
00056  *  -# Build the program and download it inside the board.
00057  *     Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf
00058  * -# On the computer, open and configure a terminal application
00059  *    (e.g. HyperTerminal on Microsoft Windows) with these settings:
00060  *   - 115200 baud rate
00061  *   - 8 bits of data
00062  *   - No parity
00063  *   - 1 stop bit
00064  *   - No flow control
00065  * -# Start the application.
00066  * -# In the terminal window, the following text should appear:
00067  *     \code
00068  *     -- USB Device HID Keyboard Project xxx --
00069  *     -- SAMxxxxx-xx
00070  *     -- Compiled: xxx xx xxxx xx:xx:xx --
00071  *     \endcode
00072  * -# When connecting USB cable to windows, the
00073  *    new "HID Keyboard Device" appears in the
00074  *    hardware %device list.
00075  * -# Once the device is connected and configured, pressing any of the board
00076  *    buttons should send characters to the host PC. Pressing num. lock should
00077  *    also make the third LED toggle its state (on/off).
00078  *
00079  * \section References
00080  * - usb_hid_keyboard/main.c
00081  * - pio: PIO interface driver
00082  *    - pio.h
00083  *    - pio_it.h
00084  * - usb: USB Framework, USB HID driver and UDP interface driver
00085  *    - \ref usbd_framework
00086  *      - \ref usbd_api
00087  *    - \ref usbd_hid_kbd_drv
00088  */
00089 
00090 /**
00091  * \file
00092  *
00093  * This file contains all the specific code for the
00094  * usb_hid_keyboard
00095  *
00096  * \section Contents
00097  *
00098  * The code can be roughly broken down as follows:
00099  *    - Configuration functions
00100  *       - VBus_Configure
00101  *       - ConfigurePit
00102  *       - ConfigureWakeUp
00103  *       - PIO & Timer configurations in start of main
00104  *    - Interrupt handlers
00105  *       - ISR_Vbus
00106  *       - ISR_Pit
00107  *       - WakeUpHandler
00108  *    - Callback functions
00109  *       - HIDDKeyboardCallbacks_LedsChanged
00110  *    - The main function, which implements the program behavior
00111  *
00112  */
00113 
00114 /*-----------------------------------------------------------------------------
00115  *         Headers
00116  *-----------------------------------------------------------------------------*/
00117 
00118 #include "board.h"
00119 
00120 #include "USBD.h"
00121 #include "HIDDKeyboardDriver.h"
00122 #include "USBD_LEDs.h"
00123 
00124 #include <string.h>
00125 #include <stdbool.h>
00126 #include <stdint.h>
00127 
00128 
00129 /*-----------------------------------------------------------------------------
00130  *         Definitions
00131  *-----------------------------------------------------------------------------*/
00132 #define NO_PUSHBUTTON
00133 
00134 /** Number of keys used in the example. */
00135 #define NUM_KEYS                    2
00136 
00137 /** Number of non-modifiers keys. */
00138 #define NUM_NORMAL_KEYS             1
00139 
00140 /** Number of modifier keys. */
00141 #define NUM_MODIFIER_KEYS           (NUM_KEYS - NUM_NORMAL_KEYS)
00142 
00143 /** NumLock LED index. */
00144 #define LED_NUMLOCK                 USBD_LEDOTHER
00145 
00146 /*---------------------------------------------------------------------------
00147  *         External variables
00148  *---------------------------------------------------------------------------*/
00149 
00150 /** Descriptor list for HID keyboard device */
00151 extern USBDDriverDescriptors hiddKeyboardDriverDescriptors;
00152 
00153 /*---------------------------------------------------------------------------
00154  *         Internal variables
00155  *---------------------------------------------------------------------------*/
00156 
00157 #ifdef NO_PUSHBUTTON
00158 #else
00159 /** List of pinsPushButtons to configure for the application. */
00160 static Pin pinsPushButtons[] = {PINS_PUSHBUTTONS};
00161 #endif
00162 
00163 /** Array of key codes produced by each button. */
00164 static uint8_t keyCodes[NUM_KEYS] = {
00165     HIDKeypad_A,
00166     HIDKeypad_NUMLOCK,
00167 };
00168 
00169 /** Current status (pressed or not) for each key. */
00170 static uint8_t keyStatus[NUM_KEYS];
00171 
00172 /*---------------------------------------------------------------------------
00173  *         Callbacks re-implementation
00174  *---------------------------------------------------------------------------*/
00175 
00176 /**
00177  *  Invoked whenever a SETUP request is received from the host. Forwards the
00178  *  request to the standard handler.
00179  */
00180 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00181 {
00182     HIDDKeyboardDriver_RequestHandler(request);
00183 }
00184 
00185 /**
00186  * Invoked when the configuration of the device changes. Start reading
00187  * output reports.
00188  * \param cfgnum New configuration number.
00189  */
00190 void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
00191 {
00192     HIDDKeyboardDriver_ConfigurationChangedHandler(cfgnum);
00193 }
00194 
00195 /**
00196  * Invoked when the status of the keyboard LEDs changes. Turns the num. lock
00197  * LED on or off.
00198  * \param numLockStatus  Indicates the current status of the num. lock key.
00199  * \param capsLockStatus  Indicates the current status of the caps lock key.
00200  * \param scrollLockStatus  Indicates the current status of the scroll lock key.
00201  */
00202 void HIDDKeyboardCallbacks_LedsChanged(
00203     uint8_t numLockStatus,
00204     uint8_t capsLockStatus,
00205     uint8_t scrollLockStatus)
00206 {
00207     printf("%c %c %c\n\r",
00208            numLockStatus ? 'N' : '_',
00209            capsLockStatus ? 'C' : '_',
00210            scrollLockStatus ? 'S' : '_'
00211         );
00212 
00213     /* Num. lock */
00214     if (numLockStatus)
00215         LED_Set(LED_NUMLOCK);
00216     else
00217         LED_Clear(LED_NUMLOCK);
00218 }
00219 
00220 /*----------------------------------------------------------------------------
00221  *         Internal functions
00222  *----------------------------------------------------------------------------*/
00223 /**
00224  * Configure USB settings for USB device
00225  */
00226 static void _ConfigureUotghs(void)
00227 {
00228 
00229     /* UTMI parallel mode, High/Full/Low Speed */
00230     /* UUSBCK not used in this configuration (High Speed) */
00231     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00232     /* USB clock register: USB Clock Input is UTMI PLL */
00233     PMC->PMC_USB = PMC_USB_USBS;
00234     /* Enable peripheral clock for USBHS */
00235     PMC_EnablePeripheral(ID_USBHS);
00236     USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00237     /* Enable PLL 480 MHz */
00238     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00239 
00240     /* Wait that PLL is considered locked by the PMC */
00241     while (!(PMC->PMC_SR & PMC_SR_LOCKU));
00242 
00243     /* IRQ */
00244     NVIC_EnableIRQ(USBHS_IRQn);
00245 }
00246 
00247 
00248 /*---------------------------------------------------------------------------
00249  *         Exported function
00250  *---------------------------------------------------------------------------*/
00251 
00252 /**
00253  * Initializes the system and then monitors buttons, sending the
00254  * corresponding character when one is pressed.
00255  *  \callgraph
00256  */
00257 int main(void)
00258 {
00259     uint32_t i;
00260 
00261     /* Disable watchdog */
00262     WDT_Disable(WDT);
00263 
00264     printf("-- USB Device HID Keyboard Project %s --\n\r", SOFTPACK_VERSION);
00265     printf("-- %s\n\r", BOARD_NAME);
00266     printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ ,
00267             COMPILER_NAME);
00268 
00269     SCB_EnableICache();
00270     SCB_EnableDCache();
00271 
00272     /* If they are present, configure Vbus & Wake-up pins */
00273     PIO_InitializeInterrupts(0);
00274 
00275     _ConfigureUotghs();
00276 
00277 #ifdef NO_PUSHBUTTON
00278     printf("-- : DBG key 1 2 used as buttons\n\r");
00279     printf("-- : 1st press to push, 2nd press to release\n\r");
00280 #else
00281     /* Initialize key statuses and configure push buttons */
00282     PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons));
00283 #endif
00284     memset(keyStatus, 1, NUM_KEYS);
00285 
00286     /* Configure LEDs */
00287     LED_Configure(LED_NUMLOCK);
00288 
00289     /* HID driver initialization */
00290     HIDDKeyboardDriver_Initialize(&hiddKeyboardDriverDescriptors);
00291 
00292     // Start USB stack to authorize VBus monitoring
00293     USBD_Connect();
00294 
00295 
00296     /* Infinite loop */
00297     while (1) {
00298         uint8_t pressedKeys[NUM_KEYS];
00299         uint8_t pressedKeysSize = 0;
00300         uint8_t releasedKeys[NUM_KEYS];
00301         uint8_t releasedKeysSize = 0;
00302 
00303         if (USBD_GetState() < USBD_STATE_CONFIGURED)
00304             continue;
00305 
00306         /* Monitor buttons */
00307 #ifdef NO_PUSHBUTTON
00308 
00309         if (DBG_IsRxReady()) {
00310             uint8_t key = DBG_GetChar();
00311 
00312             switch (key) {
00313             case '1': case '2':
00314                 i = key - '1';
00315 
00316                 if (keyStatus[i]) {
00317                     /* Key press simulation */
00318                     TRACE_INFO("Key %u pressed\n\r", (unsigned int)i);
00319                     keyStatus[i] = 0;
00320                     pressedKeys[pressedKeysSize] = keyCodes[i];
00321                     pressedKeysSize ++;
00322                     HIDDKeyboard_RemoteWakeUp();
00323                 } else {
00324                     /* Key release simulation */
00325                     TRACE_INFO("Key %u released\n\r", (unsigned int)i);
00326                     keyStatus[i] = 1;
00327                     releasedKeys[releasedKeysSize] = keyCodes[i];
00328                     releasedKeysSize++;
00329                 }
00330 
00331                 break;
00332 
00333             default: DBG_PutChar(key);
00334             }
00335         }
00336 
00337 #else
00338 
00339         for (i = 0; i < PIO_LISTSIZE(pinsPushButtons); i++) {
00340             /* Check if button state has changed */
00341             uint8_t isButtonPressed = PIO_Get(&(pinsPushButtons[i]));
00342 
00343             if (isButtonPressed != keyStatus[i]) {
00344                 /* Update button state */
00345                 if (!isButtonPressed) {
00346                     /* Key has been pressed */
00347                     printf("BP %u pressed\n\r", (unsigned int)i);
00348                     keyStatus[i] = 0;
00349                     pressedKeys[pressedKeysSize] = keyCodes[i];
00350                     pressedKeysSize++;
00351                     HIDDKeyboardDriver_RemoteWakeUp();
00352                 } else {
00353                     /* Key has been released */
00354                     printf("BP %u released\n\r", (unsigned int)i);
00355                     keyStatus[i] = 1;
00356                     releasedKeys[releasedKeysSize] = keyCodes[i];
00357                     releasedKeysSize++;
00358                 }
00359             }
00360         }
00361 
00362 #endif
00363 
00364         /* Update key status in the HID driver if necessary */
00365         if ((pressedKeysSize != 0) || (releasedKeysSize != 0)) {
00366             uint8_t status;
00367 
00368             do {
00369                 status = HIDDKeyboardDriver_ChangeKeys(pressedKeys,
00370                                                        pressedKeysSize,
00371                                                        releasedKeys,
00372                                                        releasedKeysSize);
00373             } while (status != USBD_STATUS_SUCCESS);
00374         }
00375     }
00376 }
00377 /** \endcond */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines