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_transfer 00031 * \page usb_hid_transfer USB HID Transfer Example 00032 * 00033 * \section Purpose 00034 * 00035 * The USB HID Transfer Project 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 * that have UDP interface, depending on the functions included. 00045 * 00046 * \section Description 00047 * 00048 * The demo simulates a customized HID device that reports customized data 00049 * stream, in which informations on LEDs and buttons are packed, to host. 00050 * 00051 * When an Xplained running this program connected to a host (PC for example), 00052 * with USB cable, the Xplained appears as a "USB Human Interface Device" for 00053 * the host.Then you can use the client application to read/write on it. 00054 * 00055 * \section Usage 00056 * 00057 * -# Build the program and download it inside the board. 00058 * Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf 00059 * -# On the computer, open and configure a terminal application 00060 * (e.g. HyperTerminal on Microsoft Windows) with these settings: 00061 * - 115200 baud rate 00062 * - 8 bits of data 00063 * - No parity 00064 * - 1 stop bit 00065 * - No flow control 00066 * -# Start the application. 00067 * -# In the terminal window, the following text should appear: 00068 * \code 00069 * -- USB Device HID Transfer Project xxx -- 00070 * -- SAMxxxxx-xx 00071 * -- Compiled: xxx xx xxxx xx:xx:xx -- 00072 * \endcode 00073 * -# When connecting USB cable to windows, the LED blinks. 00074 * Then new "HID Transfer Device" appears in the 00075 * hardware %device list. 00076 * -# Then you can use the PC program !hidTest.exe to check the !device 00077 * information and run tests. 00078 * -# Find the HID Device whose VID is 03EB and PID is 6201, select item type 00079 * and item to see its attributes. 00080 * -# Type what you want to send in output edit box, use buttons on the right 00081 * side to send. You can see data information in debug terminal. 00082 * -# You can use the buttons above the input edit box to read data from 00083 * !device of monitor the data, then the data and the status of the buttons 00084 * on the board is read and the gray buttons is up or down based on the 00085 * buttons status on the board. 00086 * 00087 * \section References 00088 * - usb_hid_transfer/main.c 00089 * - pio: PIO interface driver 00090 * - pio.h 00091 * - pio_it.h 00092 * - usb: USB Framework, USB HID driver and UDP interface driver 00093 * - \ref usbd_framework 00094 * - \ref usbd_api 00095 * - \ref usbd_hid_tran "hid-Transfer" 00096 * - \ref usbd_hid_xfr_drv 00097 */ 00098 00099 /** 00100 * \file 00101 * 00102 * This file contains all the specific code for the 00103 * usb_hid_transfer example 00104 */ 00105 00106 /** 00107 * Headers 00108 */ 00109 00110 #include "board.h" 00111 00112 #include <HIDDTransferDriver.h> 00113 00114 #include <stdio.h> 00115 #include <string.h> 00116 00117 /** 00118 * Definitions 00119 */ 00120 00121 /** Delay for push-button denounce (ms) */ 00122 #define DEBOUNCE_TIME 10 00123 #define NO_PUSHBUTTON 00124 /** 00125 * External variables 00126 */ 00127 00128 /** HID Transfer driver descriptors */ 00129 extern USBDDriverDescriptors hiddTransferDriverDescriptors; 00130 00131 /** 00132 * Internal variables 00133 */ 00134 00135 /** Pins for Buttons */ 00136 #ifndef NO_PUSHBUTTON 00137 static Pin pinsButtons[] = { PINS_PUSHBUTTONS }; 00138 #endif 00139 00140 #ifndef NO_PUSHBUTTON 00141 /** 00142 * Remote wake-up support (optional) 00143 */ 00144 00145 /** Button for Wake-UP the USB device. */ 00146 static const Pin pinWakeUp = PIN_PUSHBUTTON_1; 00147 00148 /** 00149 * Interrupt service routine for the remote wake-up pin. Starts the debounce 00150 * sequence. 00151 */ 00152 static void WakeUpHandler(const Pin *pin) 00153 { 00154 TRACE_DEBUG("Wake-up handler\n\r"); 00155 00156 /* Check current level on the remote wake-up pin */ 00157 if (!PIO_Get(&pinWakeUp)) 00158 HIDDTransferDriver_RemoteWakeUp(); 00159 } 00160 00161 /** 00162 * Configures the wake-up pin to generate interrupts. 00163 */ 00164 static void _ConfigureWakeUp(void) 00165 { 00166 TRACE_INFO("Wake-up configuration\n\r"); 00167 00168 /* Configure PIO */ 00169 PIO_Configure(&pinWakeUp, 1); 00170 PIO_SetDebounceFilter(&pinWakeUp, DEBOUNCE_TIME); 00171 PIO_ConfigureIt(&pinWakeUp, WakeUpHandler); 00172 PIO_EnableIt(&pinWakeUp); 00173 } 00174 #endif 00175 00176 /* 00177 * Internal Functions 00178 */ 00179 00180 /** 00181 * Display the buffer, 8 byte a line 00182 * 00183 * \param buffer Pointer to the data location 00184 * \param dwLen Size of the data 00185 */ 00186 static void _ShowBuffer(uint8_t *pucBuffer, uint32_t dwLen) 00187 { 00188 uint32_t dw; 00189 00190 for (dw = 0; dw < dwLen; dw++) { 00191 if ((dw & 0x7) == 0) 00192 printf("\n\r"); 00193 00194 printf(" %02x", pucBuffer[dw]); 00195 } 00196 00197 printf("\n\r"); 00198 } 00199 00200 /*---------------------------------------------------------------------------- 00201 * Callbacks re-implementation 00202 *----------------------------------------------------------------------------*/ 00203 00204 /** 00205 * Invoked whenever a SETUP request is received from the host. Forwards the 00206 * request to the standard handler. 00207 */ 00208 void USBDCallbacks_RequestReceived(const USBGenericRequest *request) 00209 { 00210 HIDDTransferDriver_RequestHandler(request); 00211 } 00212 00213 /** 00214 * Invoked when the configuration of the device changes. Start reading 00215 * output reports. 00216 * \param cfgnum New configuration number. 00217 */ 00218 void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) 00219 { 00220 HIDDTransferDriver_ConfigurationChangedHandler(cfgnum); 00221 } 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 * Main function 00249 */ 00250 00251 /** 00252 * Initializes the system and then monitors buttons, sending the 00253 * corresponding character when one is pressed. 00254 * \callgraph 00255 */ 00256 int main(void) 00257 { 00258 uint32_t dwCnt = 0; 00259 uint32_t dwLen; 00260 uint8_t iBuffer[64]; 00261 uint8_t oBuffer[64] = {0x80}; 00262 uint8_t bmLEDs = 0; 00263 uint8_t update; 00264 00265 /* Disable watchdog */ 00266 WDT_Disable(WDT); 00267 00268 SCB_EnableICache(); 00269 SCB_EnableDCache(); 00270 00271 printf("-- USB Device HID Transfer Project %s --\n\r", SOFTPACK_VERSION); 00272 printf("-- %s\n\r", BOARD_NAME); 00273 printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , 00274 COMPILER_NAME); 00275 00276 /* If they are present, configure Vbus & Wake-up pins */ 00277 PIO_InitializeInterrupts(0); 00278 00279 /* If there is on board power, switch it off */ 00280 _ConfigureUotghs(); 00281 00282 #ifndef NO_PUSHBUTTON 00283 /* If there is wakeup pin, configure it */ 00284 _ConfigureWakeUp(); 00285 #endif 00286 00287 /* Configure PINs for LEDs and Buttons */ 00288 LED_Configure(LED_YELLOW0); 00289 LED_Set(LED_YELLOW0); 00290 #if 2 == LED_NUM 00291 LED_Configure(LED_YELLOW1); 00292 LED_Clear(LED_YELLOW1); 00293 #endif 00294 #ifdef NO_PUSHBUTTON 00295 printf("-- : DBG key 1 2 used as buttons\n\r"); 00296 printf("-- : 1st press to push, 2nd press to release\n\r"); 00297 #else 00298 PIO_Configure(pinsButtons, PIO_LISTSIZE(pinsButtons)); 00299 #endif 00300 00301 /* HID driver initialization */ 00302 HIDDTransferDriver_Initialize(&hiddTransferDriverDescriptors); 00303 00304 /* connect if needed */ 00305 USBD_Connect(); 00306 00307 /* Infinite loop */ 00308 while (1) { 00309 if (USBD_GetState() < USBD_STATE_CONFIGURED) 00310 continue; 00311 00312 update = 0; 00313 dwLen = HIDDTransferDriver_Read(iBuffer, 64); 00314 00315 if (dwLen) { 00316 printf("Data In(%u):", (unsigned int) dwLen); 00317 _ShowBuffer(iBuffer, dwLen); 00318 00319 bmLEDs = iBuffer[0]; 00320 update = 1; 00321 } 00322 00323 dwLen = HIDDTransferDriver_ReadReport(iBuffer, 64); 00324 00325 if (dwLen) { 00326 printf("Report In(%u):", (unsigned int)dwLen); 00327 _ShowBuffer(iBuffer, dwLen); 00328 00329 bmLEDs = iBuffer[0]; 00330 update = 1; 00331 } 00332 00333 /* Update the status of LEDs */ 00334 if (update && (0x80 & bmLEDs)) { 00335 /* LED1 */ 00336 if (bmLEDs & 0x01) 00337 LED_Set(LED_YELLOW0); 00338 else 00339 LED_Clear(LED_YELLOW0); 00340 00341 #if 2 == LED_NUM 00342 00343 /* LED2 */ 00344 if (bmLEDs & 0x02) 00345 LED_Set(LED_YELLOW1); 00346 else 00347 LED_Clear(LED_YELLOW1); 00348 00349 #endif 00350 } 00351 00352 /* Update the status of the buttons */ 00353 #ifdef NO_PUSHBUTTON 00354 00355 if (DBG_IsRxReady()) { 00356 uint8_t key = DBG_GetChar(); 00357 00358 switch (key) { 00359 case '1' : 00360 if (oBuffer[0] & 0x01) oBuffer[0] &= ~0x01u; 00361 else oBuffer[0] |= 0x01u; 00362 00363 break; 00364 00365 case '2' : 00366 if (oBuffer[0] & 0x02) oBuffer[0] &= ~0x02u; 00367 else oBuffer[0] |= 0x02u; 00368 00369 break; 00370 } 00371 } 00372 00373 #else 00374 oBuffer[0] = 0x80; 00375 00376 if (PIO_Get(&pinsButtons[PUSHBUTTON_BP1]) == 0) 00377 oBuffer[0] |= 0x01; 00378 00379 #if 2 == BUTTON_NUM 00380 00381 if (PIO_Get(&pinsButtons[PUSHBUTTON_BP2]) == 0) 00382 oBuffer[0] |= 0x02; 00383 00384 #endif 00385 #endif 00386 00387 sprintf((char *)&oBuffer[5], ":%04x:%05u!", 00388 (unsigned int)dwCnt, (unsigned int)dwCnt); 00389 oBuffer[1] = (uint8_t)(dwCnt); 00390 oBuffer[2] = (uint8_t)(dwCnt >> 8); 00391 oBuffer[3] = (uint8_t)(dwCnt >> 16); 00392 oBuffer[4] = (uint8_t)(dwCnt >> 24); 00393 00394 if (USBD_STATUS_SUCCESS == HIDDTransferDriver_Write(oBuffer, 64, 0, 0)) 00395 dwCnt ++; 00396 } 00397 } 00398 /** \endcond */