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