Created
October 27, 2012 17:25
-
-
Save sash13/3965409 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <avr/io.h> | |
| #include <avr/interrupt.h> | |
| #include <avr/wdt.h> | |
| //#include <avr/eeprom.h> | |
| #include <util/delay.h> | |
| #include <avr/pgmspace.h> | |
| #include <string.h> | |
| #include "usbdrv.h" | |
| /*#define JOI2 PINB | |
| #define D0 PB1 | |
| #define D1 PB2 | |
| #define D2 PB4 | |
| #define D3 PB3 | |
| #define D4 PB0 | |
| #define D5 PB5 | |
| #define SEL2 PD7 | |
| */ | |
| #define JOI2 PINB | |
| #define SEL2 PD7 | |
| #define JOI1 PINC | |
| #define D0 PC1 | |
| #define D1 PC2 | |
| #define D2 PC3 | |
| #define D3 PC4 | |
| #define D4 PC0 | |
| #define D5 PC5 | |
| #define SEL1 PD6 | |
| #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 RightArrow 79 | |
| #define LeftArrow 80 | |
| #define DownArrow 81 | |
| #define UpArrow 82 | |
| #define ENTER 40 | |
| // ************************ | |
| // *** USB HID ROUTINES *** | |
| // ************************ | |
| // From Frank Zhao's USB Business Card project | |
| // http://www.frank-zhao.com/cache/usbbusinesscard_details.php | |
| PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { | |
| 0x05, 0x01, // USAGE_PAGE (Generic Desktop) | |
| 0x09, 0x06, // USAGE (Keyboard) | |
| 0xa1, 0x01, // COLLECTION (Application) | |
| 0x75, 0x01, // REPORT_SIZE (1) | |
| 0x95, 0x08, // REPORT_COUNT (8) | |
| 0x05, 0x07, // USAGE_PAGE (Keyboard)(Key Codes) | |
| 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)(224) | |
| 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)(231) | |
| 0x15, 0x00, // LOGICAL_MINIMUM (0) | |
| 0x25, 0x01, // LOGICAL_MAXIMUM (1) | |
| 0x81, 0x02, // INPUT (Data,Var,Abs) ; Modifier byte | |
| 0x95, 0x01, // REPORT_COUNT (1) | |
| 0x75, 0x08, // REPORT_SIZE (8) | |
| 0x81, 0x03, // INPUT (Cnst,Var,Abs) ; Reserved byte | |
| 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) ; LED report | |
| 0x95, 0x01, // REPORT_COUNT (1) | |
| 0x75, 0x03, // REPORT_SIZE (3) | |
| 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) ; LED report padding | |
| 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)(Key Codes) | |
| 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))(0) | |
| 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)(101) | |
| 0x81, 0x00, // INPUT (Data,Ary,Abs) | |
| 0xc0 // END_COLLECTION | |
| }; | |
| typedef struct { | |
| uint8_t modifier; | |
| uint8_t reserved; | |
| uint8_t keycode[6]; | |
| } keyboard_report_t; | |
| static uint8_t idle_rate = 500 / 4; // see HID1_11.pdf sect 7.2.4 | |
| static uint8_t protocol_version = 0; // see HID1_11.pdf sect 7.2.6 | |
| static keyboard_report_t keyboard_report; // sent to PC | |
| static keyboard_report_t keyboard_report_1; // sent to PC2 | |
| static keyboard_report_t keyboard_report_old; // sent to PC | |
| //volatile static uchar LED_state = 0xff; // received from PC | |
| static uchar idleRate; // repeat rate for keyboards | |
| //uchar keyDidChange=1; | |
| usbMsgLen_t 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: // send "no keys pressed" if asked here | |
| // wValue: ReportType (highbyte), ReportID (lowbyte) | |
| usbMsgPtr = (void *)&keyboard_report; // we only have this one | |
| keyboard_report.modifier = 0; | |
| keyboard_report.keycode[0] = 0; | |
| return sizeof(keyboard_report); | |
| //case USBRQ_HID_SET_REPORT: // if wLength == 1, should be LED state | |
| // return (rq->wLength.word == 1) ? USB_NO_MSG : 0; | |
| case USBRQ_HID_GET_IDLE: // send idle rate to PC as required by spec | |
| usbMsgPtr = &idleRate; | |
| return 1; | |
| case USBRQ_HID_SET_IDLE: // save idle rate as required by spec | |
| idleRate = rq->wValue.bytes[1]; | |
| return 0; | |
| } | |
| } | |
| return 0; // by default don't return any data | |
| } | |
| #define NUM_LOCK 1 | |
| #define CAPS_LOCK 2 | |
| #define SCROLL_LOCK 4 | |
| usbMsgLen_t usbFunctionWrite(uint8_t * data, uchar len) { | |
| /*if (data[0] == LED_state) | |
| return 1; | |
| else | |
| LED_state = data[0]; | |
| // LED state changed | |
| if(LED_state & CAPS_LOCK) | |
| PORTB |= 1 << PB1; // LED on | |
| else | |
| PORTB &= ~(1 << PB1); // LED off | |
| */ | |
| return 1; // Data read, not expecting more | |
| } | |
| static void hardwareInit(void) | |
| { | |
| uchar i, j; | |
| PORTB = 0xff; /* activate all pull-ups */ | |
| DDRB = 0; /* all pins input */ | |
| PORTC = 0xff; /* activate all pull-ups */ | |
| DDRC = 0; /* all pins input */ | |
| //PORTD = 0xfc; /* 1111 1100 bin: activate pull-ups except on USB lines */ | |
| DDRD = 1 << PD7; // select joi 1 | |
| DDRD = 1 << PD6; // select joi 2 | |
| PORTD |= 1 << SEL1; | |
| PORTD |= 1 << SEL2; | |
| } | |
| /*void usbSendHidReport(uchar * data, uchar len) | |
| { | |
| while(1) | |
| { | |
| usbPoll(); | |
| if (usbInterruptIsReady()) | |
| { | |
| buildReport('x'); | |
| usbSetInterrupt(data, len); | |
| break; | |
| } | |
| } | |
| }*/ | |
| /*static uchar keyPressed(void) | |
| { | |
| if(!(PINB & (1<<PB0))) { | |
| return 'a'; | |
| } | |
| return '0'; | |
| }*/ | |
| static void keyPressed(void) | |
| { | |
| uchar i, mask, x, standart[6], low_select[6], pulse_select[6], standart1[6], low_select1[6], pulse_select1[6]; | |
| PORTD |= 1 << SEL1; | |
| //PORTD |= 1 << SEL2; | |
| for(i=0; i<sizeof(keyboard_report); i++) // clear report initially | |
| ((uchar *)&keyboard_report)[i] = 0; | |
| for(i=0; i<sizeof(keyboard_report_1); i++) // clear report initially | |
| ((uchar *)&keyboard_report_1)[i] = 0; | |
| /*if(!(JOI2 & (1<<D4))) { | |
| keyboard_report.keycode[0] = KEY_B; | |
| } | |
| if(!(JOI2 & (1<<D5))) { | |
| keyboard_report.keycode[1] = KEY_C; | |
| } | |
| if(!(JOI2 & (1<<D0))) { | |
| keyboard_report.keycode[2] = UpArrow; | |
| } | |
| if(!(JOI2 & (1<<D1))) { | |
| keyboard_report.keycode[2] = DownArrow; | |
| } | |
| if(!(JOI2 & (1<<D2))) { | |
| keyboard_report.keycode[3] = LeftArrow; | |
| } | |
| if(!(JOI2 & (1<<D3))) { | |
| keyboard_report.keycode[3] = RightArrow; | |
| } | |
| // Low Select | |
| PORTD &= ~(1 << SEL2); | |
| _delay_ms(10); | |
| if(!(JOI2 & (1<<D4))) { | |
| keyboard_report.keycode[4] = KEY_A; | |
| } | |
| if(!(JOI2 & (1<<D5))) { | |
| keyboard_report.keycode[5] = ENTER; | |
| }*/ | |
| /*if(!(JOI1 & (1<<D4))) { | |
| keyboard_report.keycode[0] = KEY_B; | |
| } | |
| if(!(JOI1 & (1<<D5))) { | |
| keyboard_report.keycode[1] = KEY_C; | |
| } | |
| if(!(JOI1 & (1<<D0))) { | |
| keyboard_report.keycode[2] = UpArrow; | |
| } | |
| if(!(JOI1 & (1<<D1))) { | |
| keyboard_report.keycode[2] = DownArrow; | |
| } | |
| if(!(JOI1 & (1<<D2))) { | |
| keyboard_report.keycode[3] = LeftArrow; | |
| } | |
| if(!(JOI1 & (1<<D3))) { | |
| keyboard_report.keycode[3] = RightArrow; | |
| }*/ | |
| //x = JOI1; | |
| //JOI1//////////////////////////////////////////////////////////////////////////////////////// | |
| mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI1 & mask)) | |
| standart[i]=1; | |
| else | |
| standart[i]=0; | |
| mask <<= 1; | |
| } | |
| /*mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI2 & mask)) | |
| standart1[i]=1; | |
| else | |
| standart1[i]=0; | |
| mask <<= 1; | |
| }*/ | |
| // Low Select | |
| //PORTD &= ~(1 << SEL2); | |
| PORTD &= ~(1 << SEL1); | |
| _delay_us(10); | |
| mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI1 & mask)) | |
| low_select[i]=1; | |
| else | |
| low_select[i]=0; | |
| mask <<= 1; | |
| } | |
| /*mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI2 & mask)) | |
| low_select1[i]=1; | |
| else | |
| low_select1[i]=0; | |
| mask <<= 1; | |
| }*/ | |
| //PORTD |= 1 << SEL2; | |
| PORTD |= 1 << SEL1; | |
| _delay_us(10); | |
| //pULSE MODE | |
| PORTD &= ~(1 << SEL1); | |
| //PORTD &= ~(1 << SEL2); | |
| _delay_us(300); | |
| PORTD |= 1 << SEL1; | |
| //PORTD |= 1 << SEL2; | |
| _delay_us(300); | |
| PORTD &= ~(1 << SEL1); | |
| //PORTD &= ~(1 << SEL2); | |
| _delay_us(300); | |
| PORTD |= 1 << SEL1; | |
| //PORTD |= 1 << SEL2; | |
| _delay_us(300); | |
| mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI1 & mask)) | |
| pulse_select[i]=1; | |
| else | |
| pulse_select[i]=0; | |
| mask <<= 1; | |
| } | |
| mask = 1; | |
| /*for(i=0;i<6;i++){ | |
| if(!(JOI2 & mask)) | |
| pulse_select1[i]=1; | |
| else | |
| pulse_select1[i]=0; | |
| mask <<= 1; | |
| }*/ | |
| PORTD &= ~(1 << SEL1); | |
| //PORTD &= ~(1 << SEL2); | |
| _delay_us(300); | |
| PORTD |= 1 << SEL1; | |
| //PORTD |= 1 << SEL2; | |
| _delay_us(300); | |
| //JOI2//////////////////////////////////////////////////////////////////////////////////////// | |
| /*mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI2 & mask)) | |
| standart1[i]=1; | |
| else | |
| standart1[i]=0; | |
| mask <<= 1; | |
| } | |
| // Low Select | |
| PORTD &= ~(1 << SEL2); | |
| _delay_us(10); | |
| mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI2 & mask)) | |
| low_select1[i]=1; | |
| else | |
| low_select1[i]=0; | |
| mask <<= 1; | |
| } | |
| PORTD |= 1 << SEL2; | |
| _delay_us(10); | |
| //pULSE MODE | |
| PORTD &= ~(1 << SEL2); | |
| _delay_us(300); | |
| PORTD |= 1 << SEL2; | |
| _delay_us(300); | |
| PORTD &= ~(1 << SEL2); | |
| _delay_us(300); | |
| PORTD |= 1 << SEL2; | |
| _delay_us(300); | |
| mask = 1; | |
| for(i=0;i<6;i++){ | |
| if(!(JOI2 & mask)) | |
| pulse_select1[i]=1; | |
| else | |
| pulse_select1[i]=0; | |
| mask <<= 1; | |
| } | |
| PORTD &= ~(1 << SEL2); | |
| _delay_us(300); | |
| PORTD |= 1 << SEL2; | |
| _delay_us(300);*/ | |
| //////////////////////////////////////////////////////////////////////////////////////// | |
| if(standart[D4]) { | |
| keyboard_report.keycode[0] = KEY_V; | |
| } | |
| if(standart[D5]) { | |
| keyboard_report.keycode[1] = KEY_C; | |
| } | |
| if(standart[D0]) { | |
| keyboard_report.keycode[2] = UpArrow; | |
| } | |
| if(standart[D1]) { | |
| keyboard_report.keycode[2] = DownArrow; | |
| } | |
| if(standart[D2]) { | |
| keyboard_report.keycode[3] = LeftArrow; | |
| } | |
| if(standart[D3]) { | |
| keyboard_report.keycode[3] = RightArrow; | |
| } | |
| if(low_select[D4]) { | |
| keyboard_report.keycode[4] = KEY_N; | |
| } | |
| if(low_select[D5]) { | |
| keyboard_report.keycode[5] = ENTER; | |
| } | |
| if(pulse_select[D0]) { | |
| keyboard_report.keycode[0] = KEY_Z; | |
| } | |
| if(pulse_select[D1]) { | |
| keyboard_report.keycode[1] = KEY_Y; | |
| } | |
| if(pulse_select[D2]) { | |
| keyboard_report.keycode[4] = KEY_X; | |
| } | |
| if(pulse_select[D3]) { | |
| keyboard_report.keycode[5] = KEY_1; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////// | |
| /* if(standart1[D4]) { | |
| keyboard_report_1.keycode[0] = KEY_E; | |
| } | |
| if(standart1[D5]) { | |
| keyboard_report_1.keycode[1] = KEY_R; | |
| } | |
| if(standart1[D0]) { | |
| keyboard_report_1.keycode[2] = KEY_W; | |
| } | |
| if(standart1[D1]) { | |
| keyboard_report_1.keycode[2] = KEY_S; | |
| } | |
| if(standart1[D2]) { | |
| keyboard_report_1.keycode[3] = KEY_A; | |
| } | |
| if(standart1[D3]) { | |
| keyboard_report_1.keycode[3] = KEY_D; | |
| } | |
| if(low_select1[D4]) { | |
| keyboard_report_1.keycode[4] = KEY_T; | |
| } | |
| if(low_select1[D5]) { | |
| keyboard_report_1.keycode[5] = ENTER; | |
| }*/ | |
| /*if(pulse_select1[D0]) { | |
| keyboard_report_1.keycode[0] = KEY_F; | |
| } | |
| if(pulse_select1[D1]) { | |
| keyboard_report_1.keycode[1] = KEY_G; | |
| } | |
| if(pulse_select1[D2]) { | |
| keyboard_report_1.keycode[4] = KEY_H; | |
| } | |
| if(pulse_select1[D3]) { | |
| keyboard_report_1.keycode[5] = KEY_2; | |
| }*/ | |
| } | |
| #define STATE_WAIT 0 | |
| #define STATE_SEND_KEY 1 | |
| #define STATE_RELEASE_KEY 2 | |
| int main() { | |
| uchar i, button_release_counter = 0, state = STATE_WAIT, key, lastKey = 0, keyDidChange = 0; | |
| uint8_t to_send = 1; | |
| hardwareInit(); | |
| //DDRB = 1 << PB1; // PB0 as output | |
| //PORTB = 1 << PB0; // PB1 is input with internal pullup resistor activated | |
| for(i=0; i<sizeof(keyboard_report); i++) // clear report initially | |
| ((uchar *)&keyboard_report)[i] = 0; | |
| for(i=0; i<sizeof(keyboard_report_1); i++) // clear report initially | |
| ((uchar *)&keyboard_report_1)[i] = 0; | |
| wdt_enable(WDTO_1S); // enable 1s watchdog timer | |
| usbInit(); | |
| usbDeviceDisconnect(); // enforce re-enumeration | |
| for(i = 0; i<250; i++) { // wait 500 ms | |
| wdt_reset(); // keep the watchdog happy | |
| _delay_ms(2); | |
| } | |
| usbDeviceConnect(); | |
| //TCCR0B |= (1 << CS01); // timer 0 at clk/8 will generate randomness | |
| sei(); // Enable interrupts after re-enumeration | |
| //while(1) { | |
| // wdt_reset(); // keep the watchdog happy | |
| // usbPoll(); | |
| // key = keyPressed(); | |
| // if(lastKey != key){ | |
| // lastKey = key; | |
| // keyDidChange = 1; | |
| // } | |
| /*if(!(PINB & (1<<PB1))) { // button pressed (PB1 at ground voltage) | |
| // also check if some time has elapsed since last button press | |
| if(state == STATE_WAIT && button_release_counter == 255) | |
| state = STATE_SEND_KEY; | |
| button_release_counter = 0; // now button needs to be released a while until retrigger | |
| } | |
| if(button_release_counter < 255) | |
| button_release_counter++; // increase release counter | |
| */ | |
| // characters are sent when messageState == STATE_SEND and after receiving | |
| // the initial LED state from PC (good way to wait until device is recognized) | |
| //if(usbInterruptIsReady() && state != STATE_WAIT && LED_state != 0xff){ | |
| // if(usbInterruptIsReady()){ | |
| /*switch(state) { | |
| case STATE_SEND_KEY: | |
| buildReport('x'); | |
| state = STATE_RELEASE_KEY; // release next | |
| break; | |
| case STATE_RELEASE_KEY: | |
| buildReport('0'); | |
| state = STATE_WAIT; // go back to waiting | |
| break; | |
| default: | |
| state = STATE_WAIT; // should not happen | |
| }*/ | |
| // buildReport(lastKey); | |
| // start sending | |
| // usbSetInterrupt((void *)&keyboard_report, sizeof(keyboard_report)); | |
| // } | |
| //} | |
| /* while (1) | |
| { | |
| usbPoll(); | |
| */ | |
| /* | |
| * this area is where you should set the movement | |
| * and button values of the reports using the input | |
| * method of your choice | |
| * | |
| */ | |
| /* | |
| if (memcmp(&keyboard_report, &keyboard_report_old, sizeof(keyboard_report_t)) != 0) | |
| { | |
| to_send = 1; | |
| } | |
| usbPoll(); | |
| if (to_send != 0) | |
| { | |
| // send the data if needed | |
| usbSendHidReport(&keyboard_report, sizeof(keyboard_report_t)); | |
| } | |
| usbPoll(); | |
| memcpy(&keyboard_report_old, &keyboard_report, sizeof(keyboard_report_t)); | |
| to_send = 0; // reset flag | |
| }*/ | |
| while(1) { | |
| wdt_reset(); // keep the watchdog happy | |
| usbPoll(); | |
| keyPressed(); | |
| /*key = keyPressed(); | |
| if(lastKey != key){ | |
| lastKey = key; | |
| keyDidChange = 1; | |
| }*/ | |
| /*if(!(PINB & (1<<PB1))) { // button pressed (PB1 at ground voltage) | |
| // also check if some time has elapsed since last button press | |
| if(state == STATE_WAIT && button_release_counter == 255) | |
| state = STATE_SEND_KEY; | |
| button_release_counter = 0; // now button needs to be released a while until retrigger | |
| } | |
| if(button_release_counter < 255) | |
| button_release_counter++; // increase release counter | |
| */ | |
| // characters are sent when messageState == STATE_SEND and after receiving | |
| // the initial LED state from PC (good way to wait until device is recognized) | |
| //if(usbInterruptIsReady() && state != STATE_WAIT && LED_state != 0xff){ | |
| /*if (memcmp(&keyboard_report, &keyboard_report_old, sizeof(keyboard_report)) != 0) { | |
| to_send = 1; | |
| }*/ | |
| if(usbInterruptIsReady()){ | |
| /*switch(state) { | |
| case STATE_SEND_KEY: | |
| buildReport('x'); | |
| state = STATE_RELEASE_KEY; // release next | |
| break; | |
| case STATE_RELEASE_KEY: | |
| buildReport('0'); | |
| state = STATE_WAIT; // go back to waiting | |
| break; | |
| default: | |
| state = STATE_WAIT; // should not happen | |
| }*/ | |
| //buildReport(lastKey); | |
| // start sending | |
| usbSetInterrupt((void *)&keyboard_report, sizeof(keyboard_report)); | |
| } | |
| /*if(usbInterruptIsReady()){ | |
| usbSetInterrupt((void *)&keyboard_report_1, sizeof(keyboard_report_1)); | |
| }*/ | |
| // memcpy(&keyboard_report_old, &keyboard_report, sizeof(keyboard_report)); | |
| //to_send = 0; | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment