344 lines
10 KiB
C
344 lines
10 KiB
C
|
/* Name: main.c
|
||
|
* Project: hid-mouse, a very simple HID example
|
||
|
* Author: Christian Starkjohann
|
||
|
* Creation Date: 2008-04-07
|
||
|
* Tabsize: 4
|
||
|
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||
|
* This Revision: $Id: main.c 692 2008-11-07 15:07:40Z cs $
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
This example should run on most AVRs with only little changes. No special
|
||
|
hardware resources except INT0 are used. You may have to change usbconfig.h for
|
||
|
different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
|
||
|
at least be connected to INT0 as well.
|
||
|
|
||
|
We use VID/PID 0x046D/0xC00E which is taken from a Logitech mouse. Don't
|
||
|
publish any hardware using these IDs! This is for demonstration only!
|
||
|
*/
|
||
|
|
||
|
#include <avr/io.h>
|
||
|
#include <avr/wdt.h>
|
||
|
#include <avr/interrupt.h> /* for sei() */
|
||
|
#include <util/delay.h> /* for _delay_ms() */
|
||
|
|
||
|
|
||
|
#include <avr/pgmspace.h> /* required by usbdrv.h */
|
||
|
#include "usbdrv.h"
|
||
|
#include "oddebug.h" /* This is also an example for using debug macros */
|
||
|
|
||
|
/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
|
||
|
* 10 Keyboard/Keypad Page for more codes.
|
||
|
*/
|
||
|
#define MOD_CONTROL_LEFT (1<<0)
|
||
|
#define MOD_SHIFT_LEFT (1<<1)
|
||
|
#define MOD_ALT_LEFT (1<<2)
|
||
|
#define MOD_GUI_LEFT (1<<3)
|
||
|
#define MOD_CONTROL_RIGHT (1<<4)
|
||
|
#define MOD_SHIFT_RIGHT (1<<5)
|
||
|
#define MOD_ALT_RIGHT (1<<6)
|
||
|
#define MOD_GUI_RIGHT (1<<7)
|
||
|
|
||
|
#define KEY_A 4
|
||
|
#define KEY_B 5
|
||
|
#define KEY_C 6
|
||
|
#define KEY_D 7
|
||
|
#define KEY_E 8
|
||
|
#define KEY_F 9
|
||
|
#define KEY_G 10
|
||
|
#define KEY_H 11
|
||
|
#define KEY_I 12
|
||
|
#define KEY_J 13
|
||
|
#define KEY_K 14
|
||
|
#define KEY_L 15
|
||
|
#define KEY_M 16
|
||
|
#define KEY_N 17
|
||
|
#define KEY_O 18
|
||
|
#define KEY_P 19
|
||
|
#define KEY_Q 20
|
||
|
#define KEY_R 21
|
||
|
#define KEY_S 22
|
||
|
#define KEY_T 23
|
||
|
#define KEY_U 24
|
||
|
#define KEY_V 25
|
||
|
#define KEY_W 26
|
||
|
#define KEY_X 27
|
||
|
#define KEY_Y 28
|
||
|
#define KEY_Z 29
|
||
|
#define KEY_1 30
|
||
|
#define KEY_2 31
|
||
|
#define KEY_3 32
|
||
|
#define KEY_4 33
|
||
|
#define KEY_5 34
|
||
|
#define KEY_6 35
|
||
|
#define KEY_7 36
|
||
|
#define KEY_8 37
|
||
|
#define KEY_9 38
|
||
|
#define KEY_0 39
|
||
|
|
||
|
#define KEY_F1 58
|
||
|
#define KEY_F2 59
|
||
|
#define KEY_F3 60
|
||
|
#define KEY_F4 61
|
||
|
#define KEY_F5 62
|
||
|
#define KEY_F6 63
|
||
|
#define KEY_F7 64
|
||
|
#define KEY_F8 65
|
||
|
#define KEY_F9 66
|
||
|
#define KEY_F10 67
|
||
|
#define KEY_F11 68
|
||
|
#define KEY_F12 69
|
||
|
|
||
|
#define KEY_RETURN 40
|
||
|
#define KEY_UP 82
|
||
|
#define KEY_DOWN 81
|
||
|
#define KEY_LEFT 80
|
||
|
#define KEY_RIGHT 79
|
||
|
|
||
|
/* ------------------------------------------------------------------------- */
|
||
|
/* ----------------------------- USB interface ----------------------------- */
|
||
|
/* ------------------------------------------------------------------------- */
|
||
|
|
||
|
PROGMEM char usbHidReportDescriptor[63] = {
|
||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||
|
0x09, 0x06, // USAGE (Keyboard)
|
||
|
0xa1, 0x01, // COLLECTION (Application)
|
||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||
|
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||
|
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||
|
0x95, 0x08, // REPORT_COUNT (8)
|
||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||
|
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||
|
0x95, 0x05, // REPORT_COUNT (5)
|
||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||
|
0x05, 0x08, // USAGE_PAGE (LEDs)
|
||
|
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
|
||
|
0x29, 0x05, // USAGE_MAXIMUM (Kana)
|
||
|
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||
|
0x75, 0x03, // REPORT_SIZE (3)
|
||
|
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
|
||
|
0x95, 0x06, // REPORT_COUNT (6)
|
||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||
|
0x25, 0x65, // LOGICAL_MAXIMUM (101)
|
||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||
|
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||
|
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||
|
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||
|
0xc0 // END_COLLECTION
|
||
|
};
|
||
|
|
||
|
|
||
|
typedef struct{
|
||
|
uchar buttonMask;
|
||
|
uchar reserved;
|
||
|
uchar buttons[6];
|
||
|
}report_t;
|
||
|
|
||
|
static report_t reportBuffer;
|
||
|
static uchar idleRate; /* repeat rate for keyboards, never used for mice */
|
||
|
|
||
|
|
||
|
|
||
|
/* The following function advances sin/cos by a fixed angle
|
||
|
* and stores the difference to the previous coordinates in the report
|
||
|
* descriptor.
|
||
|
* The algorithm is the simulation of a second order differential equation.
|
||
|
*/
|
||
|
static void sendButton(void)
|
||
|
{
|
||
|
int result=0;
|
||
|
reportBuffer.buttonMask=0;
|
||
|
reportBuffer.reserved=0;
|
||
|
uchar freeKey=2;
|
||
|
|
||
|
reportBuffer.buttons[0]=0;
|
||
|
reportBuffer.buttons[1]=0;
|
||
|
reportBuffer.buttons[2]=0;
|
||
|
reportBuffer.buttons[3]=0;
|
||
|
reportBuffer.buttons[4]=0;
|
||
|
reportBuffer.buttons[5]=0;
|
||
|
|
||
|
// ADMUX=_BV(REFS0)|_BV(ADLAR)|_BV(MUX2)|_BV(MUX1)|_BV(MUX0);
|
||
|
// ADCSRA|=(1<<ADSC);
|
||
|
// while((ADCSRA&(1<<ADSC)));
|
||
|
//result+=ADCH;
|
||
|
/* ADCSRA|=(1<<ADSC);
|
||
|
while((ADCSRA&(1<<ADSC)));
|
||
|
result+=ADCH;
|
||
|
ADCSRA|=(1<<ADSC);
|
||
|
while((ADCSRA&(1<<ADSC)));
|
||
|
result+=ADCH;
|
||
|
|
||
|
result=result/3;*/
|
||
|
|
||
|
// if (result>160)
|
||
|
// reportBuffer.buttons[0]=KEY_A;
|
||
|
// else if (result<120)
|
||
|
// reportBuffer.buttons[0]=KEY_D;
|
||
|
|
||
|
|
||
|
// result=0;
|
||
|
// ADMUX=_BV(REFS0)|_BV(ADLAR)|_BV(MUX2)|_BV(MUX1);
|
||
|
// ADCSRA|=(1<<ADSC);
|
||
|
// while((ADCSRA&(1<<ADSC)));
|
||
|
// result+=ADCH;
|
||
|
/* ADCSRA|=(1<<ADSC);
|
||
|
while((ADCSRA&(1<<ADSC)));
|
||
|
result+=ADCH;
|
||
|
ADCSRA|=(1<<ADSC);
|
||
|
while((ADCSRA&(1<<ADSC)));
|
||
|
result+=ADCH;
|
||
|
|
||
|
result=result/3;*/
|
||
|
|
||
|
// if (result>150)
|
||
|
// reportBuffer.buttons[1]=KEY_W;
|
||
|
// else if (result<90)
|
||
|
// reportBuffer.buttons[1]=KEY_X;
|
||
|
|
||
|
if ((~PINB&(1<<PB0)))
|
||
|
reportBuffer.buttons[0]=KEY_W;
|
||
|
else if ((~PINB&(1<<PB1)))
|
||
|
reportBuffer.buttons[0]=KEY_S;
|
||
|
|
||
|
if ((~PINB&(1<<PB2)))
|
||
|
reportBuffer.buttons[1]=KEY_A;
|
||
|
else if ((~PINB&(1<<PB3)))
|
||
|
reportBuffer.buttons[1]=KEY_D;
|
||
|
|
||
|
reportBuffer.buttons[2]=0;
|
||
|
reportBuffer.buttons[3]=0;
|
||
|
reportBuffer.buttons[4]=0;
|
||
|
reportBuffer.buttons[5]=0;
|
||
|
|
||
|
|
||
|
if ((~PINC&(1<<PC0))&&freeKey<=5){
|
||
|
reportBuffer.buttons[freeKey]=KEY_F;
|
||
|
freeKey++;
|
||
|
}
|
||
|
if ((~PINC&(1<<PC1))&&freeKey<=5){
|
||
|
reportBuffer.buttons[freeKey]=KEY_G;
|
||
|
freeKey++;
|
||
|
}
|
||
|
if ((~PINC&(1<<PC2))&&freeKey<=5){
|
||
|
reportBuffer.buttons[freeKey]=KEY_H;
|
||
|
freeKey++;
|
||
|
}
|
||
|
if ((~PINC&(1<<PC3))&&freeKey<=5){
|
||
|
reportBuffer.buttons[freeKey]=KEY_Y;
|
||
|
freeKey++;
|
||
|
}
|
||
|
if ((~PINC&(1<<PC4))&&freeKey<=5){
|
||
|
reportBuffer.buttons[freeKey]=KEY_R;
|
||
|
freeKey++;
|
||
|
}
|
||
|
if ((~PINC&(1<<PC5))&&freeKey<=5){
|
||
|
reportBuffer.buttons[freeKey]=KEY_T;
|
||
|
freeKey++;
|
||
|
}
|
||
|
// if ((~PINB&(1<<PB1))&&freeKey<=5){
|
||
|
// reportBuffer.buttons[freeKey]=KEY_V;
|
||
|
// freeKey++;
|
||
|
// }
|
||
|
// if ((~PINB&(1<<PB2))&&freeKey<=5){
|
||
|
// reportBuffer.buttons[freeKey]=KEY_B;
|
||
|
// freeKey++;
|
||
|
// }
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/* ------------------------------------------------------------------------- */
|
||
|
|
||
|
usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||
|
{
|
||
|
usbRequest_t *rq = (void *)data;
|
||
|
|
||
|
/* The following requests are never used. But since they are required by
|
||
|
* the specification, we implement them in this example.
|
||
|
*/
|
||
|
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
|
||
|
DBG1(0x50, &rq->bRequest, 1); /* debug output: print our request */
|
||
|
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
|
||
|
/* we only have one report type, so don't look at wValue */
|
||
|
usbMsgPtr = (void *)&reportBuffer;
|
||
|
return sizeof(reportBuffer);
|
||
|
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
|
||
|
usbMsgPtr = &idleRate;
|
||
|
return 1;
|
||
|
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
|
||
|
idleRate = rq->wValue.bytes[1];
|
||
|
}
|
||
|
}else{
|
||
|
/* no vendor specific requests implemented */
|
||
|
}
|
||
|
return 0; /* default for not implemented requests: return no data back to host */
|
||
|
}
|
||
|
|
||
|
|
||
|
void adcInit(){
|
||
|
|
||
|
DDRC=0;
|
||
|
DDRB=0;
|
||
|
PORTC=0xff;
|
||
|
PORTB=0xff;
|
||
|
//PORTB=(1<<PB1)|(1<<PB2);
|
||
|
//ADMUX=(1<<REFS0);
|
||
|
//ADCSRA=(1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
|
||
|
|
||
|
}
|
||
|
|
||
|
/* ------------------------------------------------------------------------- */
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
uchar i;
|
||
|
|
||
|
wdt_enable(WDTO_1S);
|
||
|
/* Even if you don't use the watchdog, turn it off here. On newer devices,
|
||
|
* the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
|
||
|
*/
|
||
|
DBG1(0x00, 0, 0); /* debug output: main starts */
|
||
|
/* RESET status: all port bits are inputs without pull-up.
|
||
|
* That's the way we need D+ and D-. Therefore we don't need any
|
||
|
* additional hardware initialization.
|
||
|
*/
|
||
|
|
||
|
adcInit();
|
||
|
|
||
|
odDebugInit();
|
||
|
usbInit();
|
||
|
usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
|
||
|
i = 0;
|
||
|
while(--i){ /* fake USB disconnect for > 250 ms */
|
||
|
wdt_reset();
|
||
|
_delay_ms(1);
|
||
|
}
|
||
|
usbDeviceConnect();
|
||
|
sei();
|
||
|
DBG1(0x01, 0, 0); /* debug output: main loop starts */
|
||
|
for(;;){ /* main event loop */
|
||
|
DBG1(0x02, 0, 0); /* debug output: main loop iterates */
|
||
|
wdt_reset();
|
||
|
usbPoll();
|
||
|
if(usbInterruptIsReady()){
|
||
|
/* called after every poll of the interrupt endpoint */
|
||
|
sendButton();
|
||
|
DBG1(0x03, 0, 0); /* debug output: interrupt report prepared */
|
||
|
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* ------------------------------------------------------------------------- */
|