#include "usbdrv/usbdrv.h" // F_CPU in usbconfig.h #include "usbdrv/osccal.h" #include #include #include #define FOREVER while(1) #define uns16 uint16_t /* Pin assignment: * * PB2 (7) = D+ (USB data line) * PB1 (6) = D- (USB data line) * PB0 (5) = trigger input (active low with pull-up) * PB4 (3) = analog input (ADC2) * PB3 (2) = analog input (ADC3) * PB5 (1) = analog input (ADC0) */ /* USB report descriptor */ PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { 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) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0 // END_COLLECTION }; #define NO_KEY 0 #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_RETURN 40 #define KEY_TAB 43 #define ARROW_RIGHT 79 #define ARROW_LEFT 80 #define ARROW_DOWN 81 #define ARROW_UP 82 #define SHIFT_TAB 0xFE #define LAST_KEY 0xFF static const uchar keyReport[] = { KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, }; static uchar key[100]; static uchar key_ind; static void store_key(uchar k) { key[key_ind++] = k; key[key_ind++] = NO_KEY; } static void adc_to_key(void) { uns16 val = ADC, div = 1000; for(uchar digit = 4;digit;digit--,val %= div,div /= 10) store_key(keyReport[val / div]); } #define MUX_DELAY 20 // us-wartezeit nach mux umschaltung static void read_adc(void) { DIDR0 = _BV(ADC0D) | _BV(ADC3D) | _BV(ADC2D); // analog-eingänge ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 16 MHz / 128 = 125kHz ADMUX = _BV(REFS1); // ADC0 _delay_us(MUX_DELAY); // s&h einpendeln lassen ADCSRA |= _BV(ADSC); // neue wandlung starten while(ADCSRA & _BV(ADSC)); // conversion complete? key_ind = 0; adc_to_key(); store_key(KEY_TAB); ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0); // ADC3 _delay_us(MUX_DELAY); // s&h einpendeln lassen ADCSRA |= _BV(ADSC); // neue wandlung starten while(ADCSRA & _BV(ADSC)); // conversion complete? adc_to_key(); store_key(KEY_TAB); ADMUX = _BV(REFS1) | _BV(MUX1); // ADC2 _delay_us(MUX_DELAY); // s&h einpendeln lassen ADCSRA |= _BV(ADSC); // neue wandlung starten while(ADCSRA & _BV(ADSC)); // conversion complete? adc_to_key(); store_key(KEY_TAB); // ADC4 (Temperatur) ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); _delay_us(MUX_DELAY); // s&h einpendeln lassen ADCSRA |= _BV(ADSC); // neue wandlung starten while(ADCSRA & _BV(ADSC)); // conversion complete? adc_to_key(); store_key(SHIFT_TAB); store_key(SHIFT_TAB); store_key(SHIFT_TAB); store_key(KEY_RETURN); // nächste zeile ansteuern key[key_ind] = LAST_KEY; key_ind = 0; } static uchar reportBuffer[2]; // buffer for HID reports static uchar idleRate; // in 4 ms units static void buildReport(void) { uchar c = key[key_ind]; if(c == SHIFT_TAB) { reportBuffer[0] = _BV(1); // left shift modifier reportBuffer[1] = KEY_TAB; key_ind++; } else if(c != LAST_KEY) { reportBuffer[0] = NO_KEY; reportBuffer[1] = c; key_ind++; } else reportBuffer[0] = reportBuffer[1] = NO_KEY; } USB_PUBLIC uchar usbFunctionSetup(unsigned char data[8]) { usbRequest_t *rq = (void *)data; usbMsgPtr = (void *)&reportBuffer; if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */ /* we only have one report type, so don't look at wValue */ buildReport(); 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; } USB_PUBLIC void usbEventResetReady(void) // calibrateOscillator { calibrateOscillator(); } int main(void) { uchar i; wdt_enable(WDTO_2S); usbInit(); usbDeviceDisconnect(); // enforce re-enumeration for(i = 50; i; i--) { // wait 500 ms wdt_reset(); // keep the watchdog happy _delay_ms(10); } usbDeviceConnect(); PORTB |= _BV(PB0); // pull-up on trigger input sei(); // Enable interrupts after re-enumeration key[key_ind = 0] = LAST_KEY; FOREVER { //main event loop wdt_reset(); usbPoll(); if(key[key_ind] == LAST_KEY) { // alle zeichen weggearbeitet?? if(!(PINB & _BV(PB0))) { read_adc(); for(i = 100; i; i--) { // wait 1000 ms wdt_reset(); // keep the watchdog happy _delay_ms(10); } } } else if(usbInterruptIsReady()) { buildReport(); // nächstes zeichen übertragen _delay_ms(100); usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer)); } } return 0; } /* ENDE */