Rev 91 | Rev 93 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <avr/io.h>#include <avr/wdt.h>#include <avr/interrupt.h>#include <avr/pgmspace.h>#include <util/delay.h>#include "usbdrv.h"#include "config.h"#ifndef NULL#define NULL ((void *)0)#endif#define USB_GET_LED_STATE 100#define USB_SET_LED_STATE 101/* ------------------------------------------------------------------------- */uint8_t getKey(void);void doButtons(uint8_t);inline void setLeds(uint8_t);struct {int16_t axis[2];uint8_t buttons;} reportBuffer;volatile struct {uint8_t buttons;uint8_t waitup;uint8_t timer;} debounce;volatile struct {uint8_t data;union {uint8_t led_method:1;uint8_t other:1;uint8_t reserved:6;};} config;uint8_t currleds = 1;static uchar idleRate; /* in 4 ms units */volatile uint8_t tmr0_ovf = 0;volatile uint32_t systime = 0;/* ------------------------------------------------------------------------- */const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */0x05, 0x01, // USAGE_PAGE (Generic Desktop)0x09, 0x05, // USAGE (Game Pad)0xa1, 0x01, // COLLECTION (Application)0x09, 0x01, // USAGE (Pointer)0xa1, 0x00, // COLLECTION (Physical)0x09, 0x30, // USAGE (X)0x09, 0x31, // USAGE (Y)0x16, 0x00, 0x80, // Log Min -327680x26, 0xff, 0x7f, // Log max 327680x75, 0x10, // REPORT_SIZE (16)0x95, 0x02, // REPORT_COUNT (2)0x81, 0x02, // INPUT (Data,Var,Abs)0x05, 0x09, // USAGE_PAGE (Button)0x19, 0x01, // USAGE_MINIMUM (Button 1)0x29, 0x08, // USAGE_MAXIMUM (Button 8)0x15, 0x00, // LOGICAL_MINIMUM (0)0x25, 0x01, // LOGICAL_MAXIMUM (1)0x75, 0x01, // REPORT_SIZE (1)0x95, 0x08, // REPORT_COUNT (2)0x81, 0x02, // INPUT (Data,Var,Abs)0xc0, // END_COLLECTION0xc0 // END_COLLECTION};void hadUsbReset(void) {}uchar usbFunctionSetup(uchar data[8]){usbRequest_t *rq = (void *)data;//if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){switch (rq->bRequest ) {case USBRQ_HID_GET_REPORT:return sizeof(reportBuffer);case USBRQ_HID_GET_IDLE:usbMsgPtr = &idleRate;return 1;case USBRQ_HID_SET_IDLE:idleRate = rq->wValue.bytes[1];return 0;case USB_GET_LED_STATE: // send data to PCusbMsgPtr = currleds;return sizeof(currleds);case USB_SET_LED_STATE: // modify reply buffercurrleds = rq->wValue.bytes[0];return 0;}//}return 0;}void usbSendHidReport(uchar * data, uchar len) {usbSetInterrupt(data, len);}int main(void) {DIDR0 = 0x00;/*DDR : 1 = Output, 0 = InputPORT: 1 = Pullup for Input, otherwise set outputPIN : Read input pin*//*PB0 - Output - LED 3PB1 - Output - LED 4PB2 - Output - LED 5PB3 - Output - LED 6PB4 - Output - LED 7PB5 -PB6 -PB7 -*/DDRB = 0B00011111;PORTB = 0B00000000;/*PC0 - Output - ButtonPad Gnd0PC1 - Output - ButtonPad Gnd1PC2 - Input, Pullup - ButtonPad 0PC3 - Input, Pullup - ButtonPad 1PC4 - Input, Pullup - ButtonPad 2PC5 - Input, Pullup - ButtonPad 3*/DDRC = 0B00000011;PORTC = 0B00111111;/*PD0 -PD1 -PD2 -PD3 -PD4 -PD5 - Output - LED 0PD6 - Output - LED 1PD7 - Output - LED 2*/DDRD = 0B11100000;PORTD = 0B00000000;setLeds(0xff);usbDeviceDisconnect();_delay_ms(500);usbDeviceConnect();TIMSK0 = (1<<TOIE0); // Enable timer overflowTCNT0 = 0x00; // Set Timer0 initial value to 0TCCR0B = (1<< CS00) ; // /1 prescalerwdt_enable(WDTO_1S);usbInit();sei();reportBuffer.axis[0] = 0xfffd;reportBuffer.axis[1] = 0xfffd;reportBuffer.buttons = 0x00;config.led_method = 1;setLeds(currleds);for(;;){wdt_reset();usbPoll();uint8_t pressed = getKey();if (config.led_method != rbi(PORTB, 5)) {config.led_method = rbi(PORTB, 5);}if (config.led_method == 1)doButtons(pressed);setLeds(currleds);if(usbInterruptIsReady()){reportBuffer.buttons = pressed;usbSendHidReport(&reportBuffer, sizeof(reportBuffer));}}return 0;}inline void setLeds(uint8_t leds) {PORTB &= 0xE0;PORTB |= (0x1F & (leds >> 3));PORTD &= 0x1F;PORTD |= (0xE0 & (leds << 5));}void doButtons(uint8_t pressed) {// Deboucing// When i key first goes down, wait 5 ms, check it again to see if its still downif (pressed && debounce.buttons == 0 && debounce.timer == 0) {debounce.buttons = pressed;debounce.timer = 5;}// The key has come upif (pressed != debounce.buttons) {debounce.buttons = 0;debounce.timer = 0;debounce.waitup = 0;}// Debounce timer is up, process our buttonif (debounce.buttons && debounce.timer == 0 && debounce.waitup != 1) {uint8_t i = 0;for (i=0; i<=7; i++) {// Button pressed and the led is currently onif ( rbi(debounce.buttons, i) == 1 && rbi(currleds, i) == 1 ) {if ( i == 0 && rbi(currleds, 1) != 1) //Dont turn off com1 if no comm2break;if ( i == 1 && rbi(currleds, 0) != 1) //Dont turn off com2 if no comm1break;cbi(currleds, i);// Button is pressed and led is currently off} else if ( rbi(debounce.buttons, i) == 1 && rbi(currleds, i) == 0 ) {if ( i == 0 && rbi(currleds, 1) == 1) //Turn on comm2, turn off comm1cbi(currleds,1);if ( i == 1 && rbi(currleds, 0) == 1) //Turn on comm1, turn off comm2cbi(currleds,0);sbi(currleds, i);}}//setLeds(currleds);debounce.waitup = 1;}}// Gnd = PC0, PC1// Btn = PC2, PC3, PC4, PC5uint8_t getKey() {uint8_t key = 0;cbi(PORTC, 1);_delay_us(10); // Wait for the port changeif (rbi(PINC, 2) == 0) key = 1;if (rbi(PINC, 3) == 0) key = 2;if (rbi(PINC, 4) == 0) key = 4;if (rbi(PINC, 5) == 0) key = 8;sbi(PORTC, 1);cbi(PORTC, 0);_delay_us(10);if (rbi(PINC, 2) == 0) key = 16;if (rbi(PINC, 3) == 0) key = 32;if (rbi(PINC, 4) == 0) key = 64;if (rbi(PINC, 5) == 0) key = 128;sbi(PORTC, 0);return key;}ISR(TIMER0_OVF_vect) {tmr0_ovf++;// Clk/1 TCCR0B = (1<< CS00);//20.0Mhz, 1ms = 78ovf//16.5Mhz, 1ms = 64ovf//12.0Mhz, 1ms = 46ovfif (tmr0_ovf>=78) {systime++;tmr0_ovf = 0;if (debounce.timer != 0)debounce.timer--;}}