Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
EEL 4924 Electrical Engineering Design
(Senior Design)
Final Design Report
19 April 2011
Project Name: Finger Pointer
Team Members:
Name: Nunn, Christopher Name: Hamilton, Travis
Project Abstract: Our project is intended to replace a mouse with a glove that the user will wear. The cursor will track
the index finger of the user while clicking will be achieved by pressing buttons connected to the middle
finger of the user. These buttons can easily be pressed with the thumb of the user, while still maintaining
pointing ability with the index finger.
We accomplished our goal by using an infrared led on the index finger that is detected by a
CMUcam2 at the base of a computer monitor. The CMUCam2 is a camera that was developed by
Carnegie Melon University that has an on-board processor capable of performing image processing /
tracking. The CMUcam2 communicates the tracking information of the index finger to a PIC18F27J53
microcontroller. The microcontroller converts x and y coordinates from the CMUCam2 into data
packets to be sent to the computer. Then, following USB HID (Human Interface Device) protocol, the
microcontroller sends the data packets to the computer through a USB cable. Because the HID protocol
is followed correctly, our project works on a Windows or Mac computer without the need for additional
drivers.
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 2/26 Final Design Report: Finger Pointer
Table of Contents
Project Features and Objectives .................................................................................................................................3
Concept and Technology ............................................................................................................................................3
Fig.1: Block Diagram of Sonar System. ...................................................................................................................3
Fig. 2: CMUCam2 theoretical blob detection. ........................................................................................................4
Fig 3. Block Diagram of the CMU Cam System .......................................................................................................5
Implementation: .........................................................................................................................................................6
Fig. 4: The Remote Unit. .........................................................................................................................................6
Fig. 5: The completed Base Unit .............................................................................................................................6
Fig. 6: CMUCam2 actual blob .................................................................................................................................7
Fig. 7: The basic software design flowchart for the PIC18F27J53. .........................................................................7
Materials and Resources: ...........................................................................................................................................8
Separation of Work ....................................................................................................................................................9
Gantt Chart .................................................................................................................................................................9
Appendix A: Altium Schematics and PCBs ............................................................................................................... 10
Remote Schematic ............................................................................................................................................... 10
Remote PCB ......................................................................................................................................................... 10
Base Schematic .................................................................................................................................................... 11
Base PCB .............................................................................................................................................................. 11
Appendix B: C code for PIC18F27J53 ....................................................................................................................... 12
Mouse.c: .............................................................................................................................................................. 12
Usb_descriptors.c: ............................................................................................................................................... 20
InitializeCMU.c: .................................................................................................................................................... 24
StartTrack.c: ......................................................................................................................................................... 25
GetTrack.c: ........................................................................................................................................................... 25
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 3/26 Final Design Report: Finger Pointer
Project Features and Objectives
The main objective is to create a glove that can control the functions of a standard mouse (Cursor
movement, left and right clicking). Features include:
• Image tracking of the index finger by the CMU Cam2
• Wireless glove realized by battery supply and XBEE 802.15.4
• USB 2.0 connectivity realized by PIC18F27J53 microcontroller
Concept and Technology
The hardest decision in our design was determining the best way to track the user’s index finger. The
technologies considered were infrared range detecting, sonar, and image processing. The problem
encountered with infrared range detecting was the narrow signals associated with it; therefore the glove
would be very “directional”. We feared with infrared, the index finger would have to be pointed directly
at the sensor to register a distance and therefore we would not be able to receive signals at multiple
detectors to triangulate the location of the emitter.
Because of the problems with IR, we then switched to the idea of sonar. The block diagram for the
sonar signal is shown in Fig. 1. Sonar emits a wider signal, making it a better solution for our
application. We were going to have four receivers to triangulate the position of the emitter. Our major
concern with this design was the resolution of our detection. We were unsure if the sensors would be
accurate and consistent enough to be a good HID. After hearing negative reviews about a Nintendo
Power Glove (used sonar to implement an HID device), we decided to use image processing.
Fig.1: Block Diagram of Sonar System.
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 4/26 Final Design Report: Finger Pointer
Image tracking is a resource intensive process that relies on sophisticated software algorithms. After
research and suggestions from peers, we purchased a CMUCam2. This camera was developed by
Carnegie Mellon University and does onboard image processing at up to 50 frames/second with up to a
resolution of 160 x 255. We determined that this resolution and frame rate would allow us to implement
a well designed HID. The CMUCam2 serially communicates to the PIC microcontroller and
continuously sends tracking coordinates of the centroids of defined blobs.
In order for us to effectively track the infrared LED, modifications needed to be performed to the lens
assembly on the CMUCam2. First, the infrared light filter was removed. This allows light waves in the
infrared spectrum to pass through the lens. If this filter had not been removed, we would not have been
able to see our target. Next, we want to reduce the chance for interference of what we are trying to
track. Because we only want the camera to detect our infrared LED, we added a visible light filter. This
filter blocks light waves in the visible light spectrum. Exposed photo film was used as the visible light
filter because it does a good job of blocking visible light while allowing infrared to pass. After these
modifications, the infrared LED creates a blob similar to figure 2.
Fig. 2: After modification to the CMUCam2, the infrared LED creates a blob similar to what is shown above.
The CMUCam2 locates the center of this blob and sends the X and Y coordinates back to the
PIC18F27 J53 as a pixel location. This location is compared to the previous frames blob center location
and the difference of the X’s and the difference of the Y’s are noted. This comparison is how mouse
data is conveyed to the PC. The mouse does not send a set of coordinates every time it updates, but
rather it sends the difference from the current frames X and Y and the previous frames X and Y. A
typical mouse will update at about 100 hz, but because we must wait for the new coordinates from the
CMUCam2, we can only refresh as fast as we get the new tracking parameters from the camera. This
refresh rate depends on settings in the CMUCam2 such as baud rate, high or low resolution, and window
size. This causes our mouse to not be as responsive as other mice, but it should only be noticeable in
fast paced activities such as game play. The block diagram for the HID device using the CMUCam2 is
shown in Fig. 3.
Once we receive data telling us where the user’s index finger is, we need to actually send the data to
the PC. The PIC 18F27J53 has 2 EUSART ports (we only need to use 1) and supports USB 2.0
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 5/26 Final Design Report: Finger Pointer
capabilities. By following HID protocol when initializing the USB communication, we enable any
computer system to automatically download the drivers necessary to support the emulated mouse.
There are two XBEE devices used to transmit the states of the left and right click buttons on the
glove. We purchased the low power with chip antenna model (XB24-ACI-001) for two reasons.
Firstly, we needed the low power because the glove is operating from two AAA batteries, and secondly,
the on chip antenna is not invasive to the user like the integrated wire antenna is.
Fig 3. Block Diagram of the CMU Cam System
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 6/26 Final Design Report: Finger Pointer
Implementation:
When implementing our design, we broke the project into two major sections; remote and base. The
remote consists of the glove unit and the base consists of the CMUCam2 and PIC18F27J53. The final
Remote Unit is shown in figure 4 and the final Base Unit in figure 5.
Fig. 4: The Remote Unit. The IR LED and XBEE run off the 2 AAA batteries.
Fig. 5: The completed Base Unit. This picture shows the box opened; inside is the CMUCam2 and Base PCB. On the base PCB are the receiving XBEE
and the PIC18F27J53. The USB connection from this box goes to the computer and the computer automatically recognizes the HID device.
As stated before, adjustments to the lens assembly of the CMUCam2 were required to improve the
performance of the tracking capabilities. After the infrared cutoff filter was removed, and the visible
light filter was added, the camera could only see our IR LED when tracking in a lit room. An image
taken of the IR LED in a well lit room is shown in figure 6.
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 7/26 Final Design Report: Finger Pointer
Fig. 6: This picture was taken by the CMUCam2 after the lens modifications were made. This picture is in a room with the lights on, and the infrared LED
two feet away from the camera.
Currently, we are operating the CMUCam2 at a baud rate of 57,600. This is because at 48 MHz (the
speed required for the USB), 57,600 is the highest baud rate we can achieve without significant error.
This baud rate has an error of 0.16% which can be considered negligible for our application.
The software we have written for the PIC18F27J53 was written in C and can be found in Appendix
A. The basic design of the software is shown in figure 7.
Fig. 7: The basic software design flowchart for the PIC18F27J53.
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 8/26 Final Design Report: Finger Pointer
During Initialize USB, we send the report description, HID description and device description to the
computer. The computer then installs the correct HID device driver and begins communication with the
PIC18F27J53.
Next, we initialize communication with the CMUCam2. We open a USART connection on the
PIC18F27J53 with 8 data bits 1 stop bit, no parity at 57,600 baud. We reset the camera, set the tracking
parameters we want the camera to track, and then send the start tracking command. After the start
tracking command has been sent, the CMUCam2 continually sends updated tracking parameters as
quickly as it can process them.
In the “Get Tracking Data” stage, we wait for a new tracking parameter to arrive from the
CMUCam2. Once it receives the new parameters, it goes to the “Compute new mouse data” stage. In
this stage, we subtract the old parameters from the new to determine how far the mouse has moved since
the last time we saw the tracking parameters. If this number is small, we have implemented a switch
statement to ignore initial small values and then start to average them. If the number is larger (the
mouse is moving farther) we skip over the switch statement designed to remove jerkiness. Then, the x
and y coordinates are scaled up and sent to the computer in the “Update Mouse” stage. Here, the new
status of the mouse is transmitted in 3 bytes over the USB connection. After the mouse has been
updated, we go back to the “Get Tracking Data” stage where we wait for new parameters from the
camera.
Materials and Resources:
PART QTY Price Total
PIC18f27J53 1 $3.89 $3.89
CMUCam2 1 $179.00 $179.00
XBEE RF Module (XB24-ACI-001) 2 $19.00 $38.00
IR LED 1 $1.99 $1.99
Photo Film 1 $3.99 $3.99
Glove 1 $20.00 $20.00
AAA Batteries 2 $1.50 $3.00
Push Buttons 3 $0.50 $1.50
Battery Holder 1 $2.08 $2.08
USB Type B Jack 1 $1.00 $1.00
Voltage Regulator (LM3940IT) 1 $2.14 $2.14
Level Shifter (MAX232CPE) 1 $1.85 $1.85
NXT Lens Assembly 1 $13.90 $13.90
USB Cable 1 $5.00 $5.00
Miscellaneous Resistors and Capacitors
$6.00
TOTAL
$283.34
University of Florida Electrical & Computer Engineering
Page 9/26 Final Design Report: Finger Pointer
Separation of Work
TASK
Preliminary Research
CMU Cam Interface
USB Interface
Xbee Interface
Prototyping
Board Construction
Troubleshooting
Gantt Chart
0
Preliminary Research
CMU Cam interface …
USB Interface Programming
Xbee Interface Programming
Prototyping
Board Construction
Troubleshooting
EEL 4924—Spring 2011
Final Design Report: Finger Pointer
CHRIS TRAVIS
60%
70%
30%
50%
50%
40%
50%
2 4 6 8 10
Timeline
18-Apr-11
TRAVIS
40%
30%
70%
50%
50%
60%
50%
12 14
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 10/26 Final Design Report: Finger Pointer
Appendix A: Altium Schematics and PCBs
Remote Schematic:
Remote PCB:
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 11/26 Final Design Report: Finger Pointer
Base Schematic:
Base PCB:
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 12/26 Final Design Report: Finger Pointer
Appendix B: C code for PIC18F27J53
Mouse.c:
/********************************************************************
********************************************************************/
#ifndef USBMOUSE_C
#define USBMOUSE_C
/** INCLUDES *******************************************************/
#include "./USB/usb.h"
#include "./USB/usb_function_hid.h"
#include "/HardwareProfile - PIC18F47J53 PIM.h"
#include "p18f27j53.h"
#include "delays.h"
#include "CMU.h"
#include "stdio.h"
#include "usart.h"
#include "stdlib.h"
/** CONFIGURATION **************************************************/
#pragma config WDTEN = OFF //WDT disabled (enabled by SWDTEN bit)
#pragma config PLLDIV = 2 //Divide by 2 to send 4 MHz to PLL
#pragma config STVREN = ON //stack overflow/underflow reset enabled
#pragma config XINST = OFF //Extended instruction set disabled
#pragma config CPUDIV = OSC1 //No CPU system clock divide
#pragma config CP0 = OFF //Program memory is not code-protected
#pragma config OSC = INTOSCPLL //Internal oscillator, PLL enabled, 48 MHz for USB
#pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
#pragma config IESO = OFF //Two-Speed Start-up disabled
#pragma config WDTPS = 32768 //1:32768
#pragma config DSWDTOSC = INTOSCREF //DSWDT uses INTOSC/INTRC as clock
#pragma config RTCOSC = T1OSCREF //RTCC uses T1OSC/T1CKI as clock
#pragma config DSBOREN = OFF //Zero-Power BOR disabled in Deep Sleep
#pragma config DSWDTEN = OFF //Disabled
#pragma config DSWDTPS = 8192 //1:8,192 (8.5 seconds)
#pragma config IOL1WAY = OFF //IOLOCK bit can be set and cleared
#pragma config MSSP7B_EN = MSK7 //7 Bit address masking
#pragma config WPFP = PAGE_1 //Write Protect Program Flash Page 0
#pragma config WPEND = PAGE_0 //Start protection at page 0
#pragma config WPCFG = OFF //Write/Erase last page protect Disabled
#pragma config WPDIS = OFF //WPFP[5:0], WPEND, and WPCFG bits ignored
#pragma config CFGPLLEN = OFF
#define BAUD_RATE_GEN 12 // 77 for 48MHz BRLOW 9600 Baud 12 for 57,600 BRLOW
typedef struct{
int x;
int y;
} Coordinate;
/** VARIABLES ******************************************************/
#pragma udata
Coordinate newdata,olddata,TrackParams,TrackParams1,TrackParams2;
BYTE old_sw2,old_sw3;
BOOL emulate_mode,first_time;
BYTE movement_length;
BYTE vector = 0;
char buffer[3];
unsigned char Ack[12],dummy[30];
int filter_countx =0;
int filter_county =0;
USB_HANDLE lastTransmission;
/**DEBUG VARIABLES**************************************************/
int i,j;
unsigned char Rxdata[15],x_data[4],y_data[4],dummy[30];
Coordinate cords;
//The direction that the mouse will move in
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 13/26 Final Design Report: Finger Pointer
ROM signed char dir_table[]={-4,-4,-4, 0, 4, 4, 4, 0};
/** PRIVATE PROTOTYPES *********************************************/
void BlinkUSBStatus(void);
BOOL Switch2IsPressed(void);
BOOL Switch3IsPressed(void);
void Emulate_Mouse(void);
static void InitializeSystem(void);
void ProcessIO(void);
void UserInit(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
/** DECLARATIONS ***************************************************/
#pragma code
/********************************************************************
* Function: void main(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Main program entry point.
*
* Note: None
*******************************************************************/
void main(void)
{
int i;
first_time=1;
TRISAbits.TRISA0=1; //Sets RA0 as input for Left Click Button
TRISAbits.TRISA1=1; //Sets RA1 as input for Right Click Button
Delay10KTCYx(200); //Wait for Camera initialization data to come out
Delay10KTCYx(200);
InitializeSystem(); //Initializes USB - BEWARE OF PLL MULT EN!!!
while(1)
{
#if defined(USB_POLLING)
// Check bus status and service USB interrupts.
USBDeviceTasks(); // Interrupt or polling method. If using polling, must call
// this function periodically. This function will take care
// of processing and responding to SETUP transactions
// (such as during the enumeration process when you first
// plug in). USB hosts require that USB devices should accept
// and process SETUP packets in a timely fashion. Therefore,
// when using polling, this function should be called
// regularly (such as once every 1.8ms or faster** [see
// inline code comments in usb_device.c for explanation when
// "or faster" applies]) In most cases, the USBDeviceTasks()
// function does not take very long to execute (ex: <100
// instruction cycles) before it returns.
#endif
// Application-specific tasks.
// Application related code may be added here, or in the ProcessIO() function.
ProcessIO();
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 14/26 Final Design Report: Finger Pointer
}//end while
}//end main
/********************************************************************
* Function: static void InitializeSystem(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: InitializeSystem is a centralize initialization
* routine. All required USB initialization routines
* are called from here.
*
* User application initialization routine should
* also be called from here.
*
* Note: None
*******************************************************************/
static void InitializeSystem(void)
{
ADCON1 |= 0x0F; // Default all pins to digital
//On the PIC18F87J50 Family of USB microcontrollers, the PLL will not power up and be enabled
//by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
//This allows the device to power up at a lower initial operating frequency, which can be
//advantageous when powered from a source which is not gauranteed to be adequate for 48MHz
//operation. On these devices, user firmware needs to manually set the OSCTUNE<PLLEN> bit to
//power up the PLL.
{
unsigned int pll_startup_counter = 600;
OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
while(pll_startup_counter--);
}
//Device switches over automatically to PLL output after PLL is locked and ready.
//Configure all I/O pins to use digital input buffers. The PIC18F87J50 Family devices
//use the ANCONx registers to control this, which is different from other devices which
//use the ADCON1 register for this purpose.
ANCON0 = 0xFF; // Default all pins to digital
ANCON1 = 0xFF; // Default all pins to digital
UserInit();
USBDeviceInit(); //usb_device.c. Initializes USB module SFRs and firmware
//variables to known states.
}//end InitializeSystem
/******************************************************************************
* Function: void UserInit(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This routine should take care of all of the demo code
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 15/26 Final Design Report: Finger Pointer
* initialization that is required.
*
* Note:
*
*****************************************************************************/
void UserInit(void)
{
// //Initialize all of the LED pins
// mInitAllLEDs();
//
// //Initialize all of the push buttons
// mInitAllSwitches();
// old_sw2 = sw2;
// old_sw3 = sw3;
//Initialize all of the mouse data to 0,0,0 (no movement)
buffer[0]=buffer[1]=buffer[2]=0;
//enable emulation mode. This means that the mouse data
//will be send to the PC causing the mouse to move. If this is
//set to FALSE then the demo board will send 0,0,0 resulting
//in no mouse movement
emulate_mode = TRUE;
//initialize the variable holding the handle for the last
// transmission
lastTransmission = 0;
}//end UserInit
/********************************************************************
* Function: void ProcessIO(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function is a place holder for other user
* routines. It is a mixture of both USB and
* non-USB tasks.
*
* Note: None
*******************************************************************/
void ProcessIO(void)
{
// User Application USB tasks
if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
//Call the function that emulates the mouse
Emulate_Mouse();
}//end ProcessIO
/******************************************************************************
* Function: void Emulate_Mouse(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: The ownership of the USB buffers will change according
* to the required operation
*
* Overview: This routine will emulate the function of the mouse. It
* does this by sending IN packets of data to the host.
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 16/26 Final Design Report: Finger Pointer
*
* The generic function HIDTxPacket() is used to send HID
* IN packets over USB to the host.
*
* Note:
*
*****************************************************************************/
void Emulate_Mouse(void)
{
olddata = newdata;
if (first_time)
{
first_time=0;
Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE &
USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, BAUD_RATE_GEN);
InitializeCMU();
StartTrack();
}
newdata = GetTrack();
if (newdata.x == 0 && newdata.y == 0) //Keeps the mouse from going crazy when out of range of camera part 1 of 2
{
olddata.x = newdata.x;
olddata.y = newdata.y;
}
TrackParams.x = newdata.x - olddata.x;
TrackParams.y = newdata.y - olddata.y;
if(PORTAbits.RA0) //Checks for left clicking
{
hid_report_in[0] = 1;
}
else if (PORTAbits.RA1) //Checks for right clicking
{
hid_report_in[0] = 2;
}
else
{
hid_report_in[0] = 0;
}
if(TrackParams.x < 2 && TrackParams.x > -2)
{
switch (filter_countx)
{
case 0:
TrackParams1.x=TrackParams.x;
TrackParams.x=0;
filter_countx++;
break;
case 1:
TrackParams2.x=TrackParams.x;
TrackParams.x= (TrackParams1.x + TrackParams2.x)/2;
filter_countx++;
break;
case 2:
TrackParams.x = (TrackParams.x + TrackParams1.x + TrackParams2.x)/3;
filter_countx = 0;
break;
default:
TrackParams.x = 0;
filter_countx =0;
break;
}
}
if(TrackParams.y < 2 && TrackParams.y > -2)
{
switch (filter_county)
{
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 17/26 Final Design Report: Finger Pointer
case 0:
TrackParams1.y=TrackParams.y;
TrackParams.y=0;
filter_county++;
break;
case 1:
TrackParams2.y=TrackParams.y;
TrackParams.y = (TrackParams1.y + TrackParams2.y)/2;
filter_county++;
break;
case 2:
TrackParams.y = (TrackParams.y + TrackParams1.y + TrackParams2.y)/3;
filter_county = 0;
break;
default:
TrackParams.y = 0;
filter_county =0;
break;
}
}
if (olddata.x == 0 && olddata.y == 0) //Keeps the mouse from going crazy when out of range of camera part 2 of 2
{
TrackParams.x = 0;
TrackParams.y = 0;
}
if(HIDTxHandleBusy(lastTransmission) == 0)
{
//hid_report_in[0] = buffer[0];
hid_report_in[1] = TrackParams.x*-10; //originally 16
hid_report_in[2] = TrackParams.y*6; //originally -8
//Send the 3 byte packet over USB to the host.
lastTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);
}
}//end Emulate_Mouse
/*******************************************************************
* Function: void USBCBInitEP(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function is called when the device becomes
* initialized, which occurs after the host sends a
* SET_CONFIGURATION (wValue not = 0) request. This
* callback function should initialize the endpoints
* for the device's usage according to the current
* configuration.
*
* Note: None
*******************************************************************/
void USBCBInitEP(void)
{
//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
}
/********************************************************************
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 18/26 Final Design Report: Finger Pointer
* Function: void USBCBSendResume(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: The USB specifications allow some types of USB
* peripheral devices to wake up a host PC (such
* as if it is in a low power suspend to RAM state).
* This can be a very useful feature in some
* USB applications, such as an Infrared remote
* control receiver. If a user presses the "power"
* button on a remote control, it is nice that the
* IR receiver can detect this signalling, and then
* send a USB "command" to the PC to wake up.
*
* The USBCBSendResume() "callback" function is used
* to send this special USB signalling which wakes
* up the PC. This function may be called by
* application firmware to wake up the PC. This
* function will only be able to wake up the host if
* all of the below are true:
*
* 1. The USB driver used on the host PC supports
* the remote wakeup capability.
* 2. The USB configuration descriptor indicates
* the device is remote wakeup capable in the
* bmAttributes field.
* 3. The USB host PC is currently sleeping,
* and has previously sent your device a SET
* FEATURE setup packet which "armed" the
* remote wakeup capability.
*
* If the host has not armed the device to perform remote wakeup,
* then this function will return without actually performing a
* remote wakeup sequence. This is the required behavior,
* as a USB device that has not been armed to perform remote
* wakeup must not drive remote wakeup signalling onto the bus;
* doing so will cause USB compliance testing failure.
*
* This callback should send a RESUME signal that
* has the period of 1-15ms.
*
* Note: This function does nothing and returns quickly, if the USB
* bus and host are not in a suspended condition, or are
* otherwise not in a remote wakeup ready state. Therefore, it
* is safe to optionally call this function regularly, ex:
* anytime application stimulus occurs, as the function will
* have no effect, until the bus really is in a state ready
* to accept remote wakeup.
*
* When this function executes, it may perform clock switching,
* depending upon the application specific code in
* USBCBWakeFromSuspend(). This is needed, since the USB
* bus will no longer be suspended by the time this function
* returns. Therefore, the USB module will need to be ready
* to receive traffic from the host.
*
* The modifiable section in this routine may be changed
* to meet the application needs. Current implementation
* temporary blocks other functions from executing for a
* period of ~3-15 ms depending on the core frequency.
*
* According to USB 2.0 specification section 7.1.7.7,
* "The remote wakeup device must hold the resume signaling
* for at least 1 ms but for no more than 15 ms."
* The idea here is to use a delay counter loop, using a
* common value that would work over a wide range of core
* frequencies.
* That value selected is 1800. See table below:
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 19/26 Final Design Report: Finger Pointer
* ==========================================================
* Core Freq(MHz) MIP RESUME Signal Period (ms)
* ==========================================================
* 48 12 1.05
* 4 1 12.6
* ==========================================================
* * These timing could be incorrect when using code
* optimization or extended instruction mode,
* or when having other interrupts enabled.
* Make sure to verify using the MPLAB SIM's Stopwatch
* and verify the actual signal on an oscilloscope.
*******************************************************************/
void USBCBSendResume(void)
{
static WORD delay_count;
//First verify that the host has armed us to perform remote wakeup.
//It does this by sending a SET_FEATURE request to enable remote wakeup,
//usually just before the host goes to standby mode (note: it will only
//send this SET_FEATURE request if the configuration descriptor declares
//the device as remote wakeup capable, AND, if the feature is enabled
//on the host (ex: on Windows based hosts, in the device manager
//properties page for the USB device, power management tab, the
//"Allow this device to bring the computer out of standby." checkbox
//should be checked).
if(USBGetRemoteWakeupStatus() == TRUE)
{
//Verify that the USB bus is in fact suspended, before we send
//remote wakeup signalling.
if(USBIsBusSuspended() == TRUE)
{
USBMaskInterrupts();
//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE; //So we don't execute this code again,
//until a new suspend condition is detected.
//Section 7.1.7.7 of the USB 2.0 specifications indicates a USB
//device must continuously see 5ms+ of idle on the bus, before it sends
//remote wakeup signalling. One way to be certain that this parameter
//gets met, is to add a 2ms+ blocking delay here (2ms plus at
//least 3ms from bus idle to USBIsBusSuspended() == TRUE, yeilds
//5ms+ total delay since start of idle).
delay_count = 3600U;
do
{
delay_count--;
}while(delay_count);
//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
USBResumeControl = 0; //Finished driving resume signalling
USBUnmaskInterrupts();
}
}
}
/*******************************************************************
* Function: BOOL USER_USB_CALLBACK_EVENT_HANDLER(
* USB_EVENT event, void *pdata, WORD size)
*
* PreCondition: None
*
* Input: USB_EVENT event - the type of event
* void *pdata - pointer to the event data
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 20/26 Final Design Report: Finger Pointer
* WORD size - size of the event data
*
* Output: None
*
* Side Effects: None
*
* Overview: This function is called from the USB stack to
* notify a user application that a USB event
* occured. This callback is in interrupt context
* when the USB_INTERRUPT option is selected.
*
* Note: None
*******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_TRANSFER:
//Add application specific callback task or callback function here if desired.
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
//Add application specific callback task or callback function here if desired.
//The EVENT_TRANSFER_TERMINATED event occurs when the host performs a CLEAR
//FEATURE (endpoint halt) request on an application endpoint which was
//previously armed (UOWN was = 1). Here would be a good place to:
//1. Determine which endpoint the transaction that just got terminated was
// on, by checking the handle value in the *pdata.
//2. Re-arm the endpoint if desired (typically would be the case for OUT
// endpoints).
break;
default:
break;
}
return TRUE;
}
/** EOF mouse.c *************************************************/
#endif
Usb_descriptors.c:
/********************************************************************
FileName: usb_descriptors.c
Dependencies: See INCLUDES section
Processor: PIC18 or PIC24 USB Microcontrollers
Hardware: The code is natively intended to be used on the following
hardware platforms: PICDEM™ FS USB Demo Board,
PIC18F87J50 FS USB Plug-In Module, or
Explorer 16 + PIC24 USB PIM. The firmware may be
modified for use on other USB platforms by editing the
HardwareProfile.h file.
Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 21/26 Final Design Report: Finger Pointer
Company: Microchip Technology, Inc.
Software License Agreement:
The software supplied herewith by Microchip Technology Incorporated
(the “Company”) for its PIC® Microcontroller is intended and
supplied to you, the Company’s customer, for use solely and
exclusively on Microchip PIC Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.
THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------
[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.
This type is defined in usb_ch9.h Each entry into this structure
needs to be the correct length for the data type of the entry.
[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array. Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually. This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.
The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.
[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were
changed in v2.x of the stack from a structure to a BYTE array. As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field. For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"
Take the following example:
// Endpoint Descriptor //
0x07, //the size of this descriptor //
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_IN, //EndpointAddress
_INT, //Attributes
0x08,0x00, //size (note: 2 bytes)
0x02, //Interval
The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 22/26 Final Design Report: Finger Pointer
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.
-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:
rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};
The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};
A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};
The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.
-------------------------------------------------------------------
The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.
********************************************************************/
/*********************************************************************
* Descriptor specific type definitions are defined in:
* usb_device.h
*
* Configuration options are defined in:
* usb_config.h
********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C
/** INCLUDES *******************************************************/
#include "./USB/usb.h"
#include "./USB/usb_function_hid.h"
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 23/26 Final Design Report: Finger Pointer
/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
MY_VID, // Vendor ID
MY_PID, // Product ID: Mouse in a circle fw demo
0x0003, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
DESC_CONFIG_WORD(0x0022), // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
1, // Number of endpoints in this intf
HID_INTF, // Class code
BOOT_INTF_SUBCLASS, // Subclass code
HID_PROTOCOL_MOUSE, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes RRoj hack
DSC_HID, // HID descriptor type
DESC_CONFIG_WORD(0x0111), // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
DESC_CONFIG_WORD(50), //sizeof(hid_rpt01), // Size of the report descriptor
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_IN, //EndpointAddress
_INTERRUPT, //Attributes
DESC_CONFIG_WORD(3), //size
0x01 //Interval
};
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 24/26 Final Design Report: Finger Pointer
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'M','o','u','s','e',' ','I','n',' ','a',' ',
'C','i','r','c','l','e',' ','D','e','m','o'
}};
//Class specific descriptor - HID mouse
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x02, /* Usage (Mouse) */
0xA1, 0x01, /* Collection (Application) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x05, 0x09, /* Usage Page (Buttons) */
0x19, 0x01, /* Usage Minimum (01) */
0x29, 0x03, /* Usage Maximum (03) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (0) */
0x95, 0x03, /* Report Count (3) */
0x75, 0x01, /* Report Size (1) */
0x81, 0x02, /* Input (Data, Variable, Absolute) */
0x95, 0x01, /* Report Count (1) */
0x75, 0x05, /* Report Size (5) */
0x81, 0x01, /* Input (Constant) ;5 bit padding */
0x05, 0x01, /* Usage Page (Generic Desktop) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x15, 0x81, /* Logical Minimum (-127) */
0x25, 0x7F, /* Logical Maximum (127) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x02, /* Report Count (2) */
0x81, 0x06, /* Input (Data, Variable, Relative) */
0xC0, 0xC0}
};/* End Collection,End Collection */
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
(ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
InitializeCMU.c:
#include <usart.h>
#include <delays.h>
#include <stdio.h>
void InitializeCMU(void)
{
unsigned char Ack[12],dummy[30];
do
{
Delay10KTCYx(200); //2 sec delay
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 25/26 Final Design Report: Finger Pointer
printf("RS\r"); //Reset CMUcam
gets1USART((char *)Ack,4);
} while (Ack[0] != 'A');
gets1USART((char *)dummy,18); //Empties Buffer of CMUCam Version info
Delay10KTCYx(200); //2 sec delay
}
StartTrack.c:
#include <usart.h>
#include <stdio.h>
void StartTrack (void)
{
unsigned char Ack[12];
do
{
printf("DS 2 1\r"); // Scales down horizontal axis < 100
gets1USART((char *)Ack,5);
} while (Ack[0] != 'A');
Delay10KTCYx(200);
Delay10KTCYx(200);
Delay10KTCYx(200);
Delay10KTCYx(200);
do
{
printf("TC 50 240 50 240 50 240\r"); // Set tracking params
gets1USART((char *)Ack,4);
} while (Ack[0] != 'A');
}
GetTrack.c:
#include <usart.h>
#include <stdlib.h>
typedef struct{
int x;
int y;
} Coordinate;
Coordinate GetTrack (void)
{
int i,j;
unsigned char Rxdata[15],x_data[4],y_data[4],dummy[30];
Coordinate cords;
gets1USART((char *)Rxdata,9);
i=2;
j=0;
while (Rxdata[i] != ' ') //Parses X-Centroid
{ x_data[j]=Rxdata[i];
i++;
j++;
}
x_data[j]=0; // Terminates string
cords.x=atoi((char *)x_data);
i++;
j=0;
while (Rxdata[i] != ' ') //Parses Y-Centroid
{ y_data[j]=Rxdata[i];
i++;
j++;
}
University of Florida EEL 4924—Spring 2011 18-Apr-11 Electrical & Computer Engineering
Page 26/26 Final Design Report: Finger Pointer
y_data[j]=0;
cords.y=atoi((char *)y_data);
dummy[0]='0';
while (dummy[0] != '\r') //Empties buffer with data we don't need
{
gets1USART((char *)dummy,1);
}
return cords;
}