///////////////////////////////////////////////////////////////////////// //// //// //// ex_usb_hid.c //// //// //// //// A simple demo that shows how to use the HID class to send //// //// and receive custom data from the PC. Normally HID is used //// //// with pre-defined classes, such as mice and keyboards, but //// //// can be used for vendor specific classes as shown in this //// //// example. //// //// //// //// The first byte sent by the PIC is the ADC reading //// //// on channel 0 (AN0), the second byte is the status of the //// //// pushbutton. The two bytes sent by the PC are LED on/off //// //// toggle status. If you want to change the protocol to //// //// send/receive more than 2 bytes you must change the HID report //// //// descriptor. //// //// //// //// CCS has provided an example Windows program that reads / writes //// //// to the HID device provided in this example. This Windows //// //// example is called hiddemo.exe. //// //// //// //// For extra documentation on developing your own code, see //// //// the header files and comments located in the other files //// //// of the CCS PIC USB drivers. //// //// //// //// This example will work with the PCM and PCH compilers. //// ///////////////////////////////////////////////////////////////////////// //// //// //// ABOUT HID: //// //// //// //// HID devices are useful because HID drivers are generally //// //// installed and supplied with modern operating systems. //// //// However, since HID is a general device with general drivers //// //// there are limitations to what a HID device can do: //// //// //// //// - A report (message) can't be larger than 255 bytes. //// //// (A report or message != A packet) //// //// //// //// - On slow speed devices the max packet size is 8. //// //// On a full speed device the max packet size is 64. //// //// //// //// - Data is obtained on the host / PC through polling the HID //// //// device (PC polls the PIC) //// //// //// //// - On a full speed device, max polling rate is 1 transaction //// //// per 1ms. This is 64000 bytes per second (64 byte packets //// //// every 1ms). //// //// //// //// - On a slow speed device, max polling rate is 1 transaction //// //// per 10ms. This is 800 bytes per second (8 byte packets every //// //// 10ms) //// //// //// //// - No guarantee that polls will happen at a guaranteed rate. //// //// If you want guaranteed transfer rate you must use Isochronous //// //// transfers, which HID is not. //// //// //// ///////////////////////////////////////////////////////////////////////// //// //// //// WINDOWS DRIVERS: //// //// //// //// USB HID drivers come included with all Windows, starting //// //// with Windows 98 and up. Windows 95 does not include USB //// //// support, unless you are running Windows 95 Gold (aka OSR2, or //// //// Windows 95b). //// //// //// //// If you plug in the USB device, and it is working, a "Found new //// //// device" window should pop-up. The Add Device wizard then will //// //// install the HID drivers automatically. //// //// //// //// If you plug in the USB device and do not get this window then //// //// the device is not working, or USB does not work on your //// //// computer. Goto the Device Manager (Right Click on my Computer, //// //// it is located under one of the Tabs. It is located under the //// //// Hardware tab of Windows2000), and make sure that "Universal //// //// Serial Bus controllers" is installed. Open "Universal Serial //// //// Bus controllers" and you should see 1 or more "USB Root Hubs". //// //// If you see these then that's a good indication that USB is //// //// working on your computer. If you see a question mark and //// //// an unkown USB device then this is quite possibly your USB //// //// device that is not working. //// //// //// ///////////////////////////////////////////////////////////////////////// //// //// //// NOTE ABOUT ENDPOINT BUFFER SIZE: //// //// //// //// Although this application sends and receives only 2 bytes from //// //// the PC, this demo defines USB_EP1_TX_SIZE and USB_EP1_RX_SIZE //// //// to 8 to allocate 8 bytes for these endpoint. These constants //// //// are also used in the endpoint descriptor to specify the //// //// endpoint max size. If you were concious of RAM savings you //// //// could redefine these to 2 (or even 1!), but you would lose //// //// throughput. The reason for throughput loss is that if you send //// //// a packet that is the same size as the max packet size then //// //// you need to send a 0 len packet to specify end of message //// //// marker. The routines usb_puts() and usb_gets() send and //// //// receive multiple packet message, waiting for a 0 len packet //// //// or a packet that is smaller than max-packet size. //// //// //// ///////////////////////////////////////////////////////////////////////// //// //// //// VERSION HISTORY //// //// //// //// June 20th, 2005: 18fxx5x initial release. //// //// //// //// March 22nd, 2005: Cleanup to work with PIC18Fxx5x //// //// //// //// June 24th, 2004: Cleanup to work with updated USB API //// //// //// ///////////////////////////////////////////////////////////////////////// //// (C) Copyright 1996,2005 Custom Computer Services //// //// This source code may only be used by licensed users of the CCS //// //// C compiler. This source code may only be distributed to other //// //// licensed users of the CCS C compiler. No other use, //// //// reproduction or distribution is permitted without written //// //// permission. Derivative programs created using this software //// //// in object code form are not restricted in any way. //// ///////////////////////////////////////////////////////////////////////// //set to 1 to use a PIC's internal USB Peripheral //set to 0 to use a National USBN960x peripheral #define __USB_PIC_PERIF__ 1 #if __USB_PIC_PERIF__ #DEFINE LED1 PIN_A5 #if defined(__PCM__) #include <16C765.h> #device *=16 #fuses HS,NOWDT,NOPROTECT #use delay(clock=24000000) #elif defined(__PCH__) #include <18F4550.h> #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN #use delay(clock=48000000) #endif #else //use the National USBN960x peripheral #DEFINE LED1 PIN_B3 #if defined(__PCM__) #include <16F877A.h> #device *=16 #fuses HS,NOWDT,NOPROTECT,NOLVP #elif defined(__PCH__) #include <18F452.h> #fuses HS,NOWDT,NOPROTECT,NOLVP #endif #use delay(clock=20000000) #endif //endif check to see which peripheral to use #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) ///////////////////////////////////////////////////////////////////////////// // // CCS Library dynamic defines. For dynamic configuration of the CCS Library // for your application several defines need to be made. See the comments // at usb.h for more information // ///////////////////////////////////////////////////////////////////////////// //Tells the CCS PIC USB firmware to include HID handling code. #DEFINE USB_HID_DEVICE TRUE //the following defines needed for the CCS USB PIC driver to enable the TX endpoint 1 // and allocate buffer space on the peripheral #define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers #define USB_EP1_TX_SIZE 8 //allocate 8 bytes in the hardware for transmission //the following defines needed for the CCS USB PIC driver to enable the RX endpoint 1 // and allocate buffer space on the peripheral #define USB_EP1_RX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for OUT bulk/interrupt transfers #define USB_EP1_RX_SIZE 8 //allocate 8 bytes in the hardware for reception ///////////////////////////////////////////////////////////////////////////// // // If you are using a USB connection sense pin, define it here. If you are // not using connection sense, comment out this line. Without connection // sense you will not know if the device gets disconnected. // (connection sense should look like this: // 100k // VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC) // | // +----/\/\/\/\/\-----GND // 100k // (where VBUS is pin1 of the USB connector) // ///////////////////////////////////////////////////////////////////////////// ///only the 18F4550 development kit has this pin #if __USB_PIC_PERIF__ && defined(__PCH__) #define USB_CON_SENSE_PIN PIN_B2 #endif ///////////////////////////////////////////////////////////////////////////// // // Include the CCS USB Libraries. See the comments at the top of these // files for more information // ///////////////////////////////////////////////////////////////////////////// #if __USB_PIC_PERIF__ #if defined(__PCM__) #include //Microchip PIC16C765 hardware layer for usb.c #else #include //Microchip 18Fxx5x hardware layer for usb.c #endif #else #include //National 960x hardware layer for usb.c #endif #include //USB Configuration and Device descriptors for this UBS device #include //handles usb setup tokens and get descriptor reports ///////////////////////////////////////////////////////////////////////////// // // Configure the demonstration I/O // ///////////////////////////////////////////////////////////////////////////// #define LED2 PIN_B4 #define LED3 PIN_B5 #DEFINE BUTTON PIN_A4 #define LED_ON output_low #define LED_OFF output_high ///////////////////////////////////////////////////////////////////////////// // // usb_debug_task() // // When called periodically, displays debugging information over serial // to display enumeration and connection states. Also lights LED1 based upon // enumeration and status. // ///////////////////////////////////////////////////////////////////////////// void usb_debug_task(void) { static int8 last_connected; static int8 last_enumerated; int8 new_connected; int8 new_enumerated; new_connected=usb_attached(); new_enumerated=usb_enumerated(); if (new_enumerated) LED_ON(LED1); else LED_OFF(LED1); if (new_connected && !last_connected) printf("\r\n\nUSB connected, waiting for enumaration..."); if (!new_connected && last_connected) printf("\r\n\nUSB disconnected, waiting for connection..."); if (new_enumerated && !last_enumerated) printf("\r\n\nUSB enumerated by PC/HOST"); if (!new_enumerated && last_enumerated) printf("\r\n\nUSB unenumerated by PC/HOST, waiting for enumeration..."); last_connected=new_connected; last_enumerated=new_enumerated; } void main() { int8 out_data[20]; int8 in_data[2]; int8 send_timer=0; int a = 0; LED_OFF(LED1); LED_OFF(LED2); LED_OFF(LED3); printf("\r\n\nCCS Vendor Specific HID Example"); #ifdef __PCH__ printf("\r\nPCH: v"); printf(__PCH__); #else printf("\r\n\PCM: v"); printf(__PCM__); #endif usb_init_cs(); #if !(__USB_PIC_PERIF__) printf("\r\nUSBN: 0x%X", usbn_get_version()); #endif printf("\r\n"); #if defined(AN0) setup_adc_ports(AN0); #elif defined(AN0_AN1_AN3) setup_adc_ports(AN0_AN1_AN3); #else #error CONFIGURE ADC PORTS SO WE CAN READ CHANNEL 0 #endif setup_adc(ADC_CLOCK_INTERNAL); set_adc_channel(0); while (TRUE) { usb_task(); usb_debug_task(); if (usb_enumerated()) { if (!send_timer) { send_timer=250; // out_data[0]=read_adc(); // out_data[1]=!input(BUTTON); a++; out_data[0]=a; out_data[1]=a; // if (usb_put_packet(1, out_data, 2, USB_DTS_TOGGLE)) // printf("\r\n<-- Sending 2 bytes: 0x%X 0x%X", out_data[0], out_data[1]); if (usb_put_packet(1, out_data, 2, USB_DTS_TOGGLE)) printf("\r\n<-- Sending 2 bytes: 0x%X 0x%X", out_data[0], out_data[1]); } if (usb_kbhit(1)) { usb_get_packet(1, in_data, 2); printf("\r\n--> Received data: 0x%X 0x%X",in_data[0],in_data[1]); if (in_data[0]) {LED_ON(LED2);} else {LED_OFF(LED2);} if (in_data[1]) {LED_ON(LED3);} else {LED_OFF(LED3);} } send_timer--; delay_ms(1); } } }