/** * Project: AVR ATtiny USB Tutorial at http://codeandlife.com/ * Author: Joonas Pihlajamaa, joonas.pihlajamaa@iki.fi * Inspired by V-USB example code by Christian Starkjohann * Copyright: (C) 2012 by Joonas Pihlajamaa * License: GNU GPL v3 (see License.txt) */ #include #include #include #include "usbdrv.h" #define F_CPU 12000000L #include #define USB_LED_OFF 0 #define USB_LED_ON 1 #define USB_DATA_OUT 2 #define USB_DATA_WRITE 3 #define USB_DATA_IN 4 static uchar replyBuf[16] = "Hello, USB!"; static uchar dataReceived = 0, dataLength = 0; // for USB_DATA_IN // this gets called when custom control message is received USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *)data; // cast data to correct type switch(rq->bRequest) { // custom command is in the bRequest field case USB_LED_ON: PORTB |= 1; // turn LED on return 0; case USB_LED_OFF: PORTB &= ~1; // turn LED off return 0; case USB_DATA_OUT: // send data to PC usbMsgPtr = replyBuf; return sizeof(replyBuf); case USB_DATA_WRITE: // modify reply buffer replyBuf[7] = rq->wValue.bytes[0]; replyBuf[8] = rq->wValue.bytes[1]; replyBuf[9] = rq->wIndex.bytes[0]; replyBuf[10] = rq->wIndex.bytes[1]; return 0; case USB_DATA_IN: // receive data from PC dataLength = (uchar)rq->wLength.word; dataReceived = 0; if(dataLength > sizeof(replyBuf)) // limit to buffer size dataLength = sizeof(replyBuf); return USB_NO_MSG; // usbFunctionWrite will be called now } return 0; // should not get here } // This gets called when data is sent from PC to the device USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) { uchar i; for(i = 0; dataReceived < dataLength && i < len; i++, dataReceived++) replyBuf[dataReceived] = data[i]; return (dataReceived == dataLength); // 1 if we received it all, 0 if not } int main() { uchar i; DDRB = 1; // PB0 as output 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(); sei(); // Enable interrupts after re-enumeration while(1) { wdt_reset(); // keep the watchdog happy usbPoll(); } return 0; }