├── osccal.o ├── keywords.txt ├── JoystickReadme.txt ├── usbdrvasm.asm ├── oddebug.c ├── ArduinoNotes.txt ├── osccal.c ├── osccal.h ├── oddebug.h ├── osccal.c.lst ├── osctune.h ├── examples ├── PPM_Joystick │ └── PPM_Joystick.ino └── CRSF_Joystick │ └── CRSF_Joystick.ino ├── usbportability.h ├── USB-IDs-for-free.txt ├── DigiKeyboard.h.old ├── USB-ID-FAQ.txt ├── CommercialLicense.txt ├── USBID-License.txt ├── Readme.txt ├── asmcommon.inc ├── DigiJoystick_FPV.h ├── usbdrvasm.S ├── usbdrvasm16.inc ├── Changelog.txt ├── usbdrvasm20.inc ├── usbdrvasm12.inc ├── usbdrvasm165.inc └── usbdrvasm15.inc /osccal.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/DigiJoystick_FPV/master/osccal.o -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | DigiKeyboard KEYWORD1 2 | update KEYWORD2 3 | sendKeyStroke KEYWORD2 -------------------------------------------------------------------------------- /JoystickReadme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/g3gg0/DigiJoystick_FPV/master/JoystickReadme.txt -------------------------------------------------------------------------------- /usbdrvasm.asm: -------------------------------------------------------------------------------- 1 | /* Name: usbdrvasm.asm 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2006-03-01 5 | * Tabsize: 4 6 | * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | * This Revision: $Id$ 9 | */ 10 | 11 | /* 12 | General Description: 13 | The IAR compiler/assembler system prefers assembler files with file extension 14 | ".asm". We simply provide this file as an alias for usbdrvasm.S. 15 | 16 | Thanks to Oleg Semyonov for his help with the IAR tools port! 17 | */ 18 | 19 | #include "usbdrvasm.S" 20 | 21 | end 22 | -------------------------------------------------------------------------------- /oddebug.c: -------------------------------------------------------------------------------- 1 | /* Name: oddebug.c 2 | * Project: AVR library 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2005-01-16 5 | * Tabsize: 4 6 | * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | * This Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $ 9 | */ 10 | 11 | #include "oddebug.h" 12 | 13 | #if DEBUG_LEVEL > 0 14 | 15 | #warning "Never compile production devices with debugging enabled" 16 | 17 | static void uartPutc(char c) 18 | { 19 | while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */ 20 | ODDBG_UDR = c; 21 | } 22 | 23 | static uchar hexAscii(uchar h) 24 | { 25 | h &= 0xf; 26 | if(h >= 10) 27 | h += 'a' - (uchar)10 - '0'; 28 | h += '0'; 29 | return h; 30 | } 31 | 32 | static void printHex(uchar c) 33 | { 34 | uartPutc(hexAscii(c >> 4)); 35 | uartPutc(hexAscii(c)); 36 | } 37 | 38 | void odDebug(uchar prefix, uchar *data, uchar len) 39 | { 40 | printHex(prefix); 41 | uartPutc(':'); 42 | while(len--){ 43 | uartPutc(' '); 44 | printHex(*data++); 45 | } 46 | uartPutc('\r'); 47 | uartPutc('\n'); 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /ArduinoNotes.txt: -------------------------------------------------------------------------------- 1 | Notes On Integrating AVRUSB with Arduino 2 | ======================================== 3 | 4 | * Note the license(s) under which AVRUSB is distributed. 5 | 6 | * See also: http://code.rancidbacon.com/ProjectLogArduinoUSB 7 | 8 | * Note: The pins we use on the PCB (not protoboard) hardware shield are: 9 | 10 | INT0 == PD2 == IC Pin 4 == Arduino Digital Pin 2 == D+ 11 | 12 | ---- == PD4 == -------- == Arduino Digital Pin 4 == D- 13 | 14 | ---- == PD5 == -------- == Arduino Digital Pin 5 == pull-up 15 | 16 | (DONE: Change to not use PD3 so INT1 is left free?) 17 | 18 | * In order to compile a valid 'usbconfig.h' file must exit. The content of this 19 | file will vary depending on whether the device is a generic USB device, 20 | generic HID device or specific class of HID device for example. 21 | 22 | The file 'usbconfig-prototype.h' can be used as a starting point, however 23 | it might be easier to use the 'usbconfig.h' from one of the example projects. 24 | 25 | TODO: Specify the settings that need to be changed to match the shield 26 | design we use. 27 | 28 | * (NOTE: Initial 'usbconfig.h' used will be based on the file from 29 | 'HIDKeys.2007-03-29'.) (Note: Have now upgraded to V-USB 2009-08-22.) 30 | 31 | * Versions of the Arduino IDE prior to 0018 won't compile our library 32 | so it needs to be pre-compiled with: 33 | 34 | avr-g++ -Wall -Os -I. -DF_CPU=16000000 -mmcu=atmega168 -c usbdrvasm.S -c usbdrv.c 35 | -------------------------------------------------------------------------------- /osccal.c: -------------------------------------------------------------------------------- 1 | /* Name: osccal.c 2 | * Author: Christian Starkjohann 3 | * Creation Date: 2008-04-10 4 | * Tabsize: 4 5 | * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH 6 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 7 | * This Revision: $Id: osccal.c 762 2009-08-12 17:10:30Z cs $ 8 | */ 9 | 10 | #include 11 | 12 | #ifndef uchar 13 | #define uchar unsigned char 14 | #endif 15 | 16 | /* ------------------------------------------------------------------------- */ 17 | /* ------------------------ Oscillator Calibration ------------------------- */ 18 | /* ------------------------------------------------------------------------- */ 19 | 20 | /* Calibrate the RC oscillator. Our timing reference is the Start Of Frame 21 | * signal (a single SE0 bit) repeating every millisecond immediately after 22 | * a USB RESET. We first do a binary search for the OSCCAL value and then 23 | * optimize this value with a neighboorhod search. 24 | */ 25 | void calibrateOscillator(void) 26 | { 27 | uchar step = 128; 28 | uchar trialValue = 0, optimumValue; 29 | int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5); 30 | 31 | /* do a binary search: */ 32 | do{ 33 | OSCCAL = trialValue + step; 34 | x = usbMeasureFrameLength(); /* proportional to current real frequency */ 35 | if(x < targetValue) /* frequency still too low */ 36 | trialValue += step; 37 | step >>= 1; 38 | }while(step > 0); 39 | /* We have a precision of +/- 1 for optimum OSCCAL here */ 40 | /* now do a neighborhood search for optimum value */ 41 | optimumValue = trialValue; 42 | optimumDev = x; /* this is certainly far away from optimum */ 43 | for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){ 44 | x = usbMeasureFrameLength() - targetValue; 45 | if(x < 0) 46 | x = -x; 47 | if(x < optimumDev){ 48 | optimumDev = x; 49 | optimumValue = OSCCAL; 50 | } 51 | } 52 | OSCCAL = optimumValue; 53 | } 54 | /* 55 | Note: This calibration algorithm may try OSCCAL values of up to 192 even if 56 | the optimum value is far below 192. It may therefore exceed the allowed clock 57 | frequency of the CPU in low voltage designs! 58 | You may replace this search algorithm with any other algorithm you like if 59 | you have additional constraints such as a maximum CPU clock. 60 | For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g. 61 | ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in 62 | both regions. 63 | */ 64 | -------------------------------------------------------------------------------- /osccal.h: -------------------------------------------------------------------------------- 1 | /* Name: osccal.h 2 | * Author: Christian Starkjohann 3 | * Creation Date: 2008-04-10 4 | * Tabsize: 4 5 | * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH 6 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 7 | * This Revision: $Id: osccal.h 762 2009-08-12 17:10:30Z cs $ 8 | */ 9 | 10 | /* 11 | General Description: 12 | This module contains a function which calibrates the AVR's internal RC 13 | oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be 14 | defined when the module is compiled, best passed in the compiler command 15 | line). The time reference is the USB frame clock of 1 kHz available 16 | immediately after a USB RESET condition. Timing is done by counting CPU 17 | cycles, so all interrupts must be disabled while the calibration runs. For 18 | low level timing measurements, usbMeasureFrameLength() is called. This 19 | function must be enabled in usbconfig.h by defining 20 | USB_CFG_HAVE_MEASURE_FRAME_LENGTH to 1. It is recommended to call 21 | calibrateOscillator() from the reset hook in usbconfig.h: 22 | */ 23 | 24 | #ifndef __ASSEMBLER__ 25 | #include // for sei() 26 | extern void calibrateOscillator(void); 27 | #endif 28 | #define USB_RESET_HOOK(resetStarts) if(!resetStarts){cli(); calibrateOscillator(); sei();} 29 | 30 | /* 31 | This routine is an alternative to the continuous synchronization described 32 | in osctune.h. 33 | 34 | Algorithm used: 35 | calibrateOscillator() first does a binary search in the OSCCAL register for 36 | the best matching oscillator frequency. Then it does a next neighbor search 37 | to find the value with the lowest clock rate deviation. It is guaranteed to 38 | find the best match among neighboring values, but for version 5 oscillators 39 | (which have a discontinuous relationship between OSCCAL and frequency) a 40 | better match might be available in another OSCCAL region. 41 | 42 | Limitations: 43 | This calibration algorithm may try OSCCAL values of up to 192 even if the 44 | optimum value is far below 192. It may therefore exceed the allowed clock 45 | frequency of the CPU in low voltage designs! 46 | Precision depends on the OSCCAL vs. frequency dependency of the oscillator. 47 | Typical precision for an ATMega168 (derived from the OSCCAL vs. F_RC diagram 48 | in the data sheet) should be in the range of 0.4%. Only the 12.8 MHz and 49 | 16.5 MHz versions of V-USB (with built-in receiver PLL) can tolerate this 50 | deviation! All other frequency modules require at least 0.2% precision. 51 | */ 52 | 53 | #ifndef __OSCCAL_H_INCLUDED__ 54 | #define __OSCCAL_H_INCLUDED__ 55 | 56 | //void calibrateOscillator(void); 57 | /* This function calibrates the RC oscillator so that the CPU runs at F_CPU. 58 | * It MUST be called immediately after the end of a USB RESET condition! 59 | * Disable all interrupts during the call! 60 | * It is recommended that you store the resulting value in EEPROM so that a 61 | * good guess value is available after the next reset. 62 | */ 63 | 64 | 65 | #endif /* __OSCCAL_H_INCLUDED__ */ 66 | -------------------------------------------------------------------------------- /oddebug.h: -------------------------------------------------------------------------------- 1 | /* Name: oddebug.h 2 | * Project: AVR library 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2005-01-16 5 | * Tabsize: 4 6 | * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | * This Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $ 9 | */ 10 | 11 | #ifndef __oddebug_h_included__ 12 | #define __oddebug_h_included__ 13 | 14 | /* 15 | General Description: 16 | This module implements a function for debug logs on the serial line of the 17 | AVR microcontroller. Debugging can be configured with the define 18 | 'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging 19 | calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is 20 | 2, DBG1 and DBG2 logs will be printed. 21 | 22 | A debug log consists of a label ('prefix') to indicate which debug log created 23 | the output and a memory block to dump in hex ('data' and 'len'). 24 | */ 25 | 26 | 27 | #ifndef F_CPU 28 | # define F_CPU 12000000 /* 12 MHz */ 29 | #endif 30 | 31 | /* make sure we have the UART defines: */ 32 | #include "usbportability.h" 33 | 34 | #ifndef uchar 35 | # define uchar unsigned char 36 | #endif 37 | 38 | #if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */ 39 | # warning "Debugging disabled because device has no UART" 40 | # undef DEBUG_LEVEL 41 | #endif 42 | 43 | #ifndef DEBUG_LEVEL 44 | # define DEBUG_LEVEL 0 45 | #endif 46 | 47 | /* ------------------------------------------------------------------------- */ 48 | 49 | #if DEBUG_LEVEL > 0 50 | # define DBG1(prefix, data, len) odDebug(prefix, data, len) 51 | #else 52 | # define DBG1(prefix, data, len) 53 | #endif 54 | 55 | #if DEBUG_LEVEL > 1 56 | # define DBG2(prefix, data, len) odDebug(prefix, data, len) 57 | #else 58 | # define DBG2(prefix, data, len) 59 | #endif 60 | 61 | /* ------------------------------------------------------------------------- */ 62 | 63 | #if DEBUG_LEVEL > 0 64 | extern void odDebug(uchar prefix, uchar *data, uchar len); 65 | 66 | /* Try to find our control registers; ATMEL likes to rename these */ 67 | 68 | #if defined UBRR 69 | # define ODDBG_UBRR UBRR 70 | #elif defined UBRRL 71 | # define ODDBG_UBRR UBRRL 72 | #elif defined UBRR0 73 | # define ODDBG_UBRR UBRR0 74 | #elif defined UBRR0L 75 | # define ODDBG_UBRR UBRR0L 76 | #endif 77 | 78 | #if defined UCR 79 | # define ODDBG_UCR UCR 80 | #elif defined UCSRB 81 | # define ODDBG_UCR UCSRB 82 | #elif defined UCSR0B 83 | # define ODDBG_UCR UCSR0B 84 | #endif 85 | 86 | #if defined TXEN 87 | # define ODDBG_TXEN TXEN 88 | #else 89 | # define ODDBG_TXEN TXEN0 90 | #endif 91 | 92 | #if defined USR 93 | # define ODDBG_USR USR 94 | #elif defined UCSRA 95 | # define ODDBG_USR UCSRA 96 | #elif defined UCSR0A 97 | # define ODDBG_USR UCSR0A 98 | #endif 99 | 100 | #if defined UDRE 101 | # define ODDBG_UDRE UDRE 102 | #else 103 | # define ODDBG_UDRE UDRE0 104 | #endif 105 | 106 | #if defined UDR 107 | # define ODDBG_UDR UDR 108 | #elif defined UDR0 109 | # define ODDBG_UDR UDR0 110 | #endif 111 | 112 | static inline void odDebugInit(void) 113 | { 114 | ODDBG_UCR |= (1< 0x3f /* outside I/O addressable range */ 63 | lds YH, OSCCAL ;[6] 64 | #else 65 | in YH, OSCCAL ;[6] assembler modle uses __SFR_OFFSET == 0 66 | #endif 67 | cpi YL, TOLERATED_DEVIATION + 1 ;[10] 68 | brmi notTooHigh ;[11] 69 | subi YH, 1 ;[12] clock rate was too high 70 | ; brcs tuningOverflow ; optionally check for overflow 71 | rjmp osctuneDone ;[13] 72 | notTooHigh: 73 | cpi YL, -TOLERATED_DEVIATION ;[13] 74 | brpl osctuneDone ;[14] not too low 75 | inc YH ;[15] clock rate was too low 76 | ; breq tuningOverflow ; optionally check for overflow 77 | osctuneDone: 78 | #if OSCCAL > 0x3f /* outside I/O addressable range */ 79 | sts OSCCAL, YH ;[12-13] store tuned value 80 | #else 81 | out OSCCAL, YH ;[12-13] store tuned value 82 | #endif 83 | tuningOverflow: 84 | pop YH ;[17] 85 | endm ;[19] max number of cycles 86 | #endif 87 | 88 | #define USB_SOF_HOOK tuneOsccal 89 | -------------------------------------------------------------------------------- /examples/PPM_Joystick/PPM_Joystick.ino: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Compile with Digispark 16.5 MHz 4 | * 5 | * Acts as a Joystick with 6 axis and 6 buttons, receiving PPM signal from an RC remote. 6 | * It struggles with USB interrupts, but filters out PPM data when the USB interrupt fired inbetween. 7 | * For the other, successfully received data, it does an moving average filter to get rid of noise. 8 | * Causes a small latency, but wasn't able to feel it in DRL Simulator (ok, i am a newb so it might be due to this) 9 | * 10 | * Hint: after refactoring parts of the library, this might not work properly. 11 | * 12 | */ 13 | 14 | /* 15 | * Error: multiple definition of `__vector_4' 16 | * 17 | * As we have to use timer1 for overflow counting, disable the arduino milis() timer by editing 18 | * \AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny\wiring.c:92 19 | * 20 | * ISR(MILLISTIMER_OVF_vect, ISR_NOBLOCK) 21 | * to 22 | * void timer_cbr() 23 | * 24 | * Then milis() won't work anymore, but we don't need it for this sketch. 25 | * Change it back after compiling. 26 | */ 27 | 28 | #include 29 | #include "DigiJoystick_FPV.h" 30 | 31 | #define RC_RECEIVER_PORT PB0 32 | #define RISING_EDGE PINB & (1 << RC_RECEIVER_PORT) 33 | #define CHANNELS 12 34 | #define CLOCK_BITS (1 << CS12) 35 | 36 | volatile uint32_t ppmValueMin[CHANNELS]; 37 | volatile uint32_t ppmValueMax[CHANNELS]; 38 | volatile uint16_t ppmValues[CHANNELS]; 39 | uint32_t avgValues[CHANNELS]; 40 | volatile uint16_t overflows = 0; 41 | volatile uint16_t ppmValid = 0; 42 | volatile uint8_t ppmPos = 0; 43 | 44 | extern uint8_t usbActivityCount; 45 | 46 | void setup() 47 | { 48 | pinMode(PB0, INPUT); 49 | pinMode(PB1, OUTPUT); 50 | pinMode(PB2, INPUT); 51 | 52 | for(int pos = 0; pos < CHANNELS; pos++) 53 | { 54 | ppmValueMin[pos] = 1700; 55 | ppmValueMax[pos] = 2500; 56 | ppmValues[pos] = 0; 57 | } 58 | 59 | GIMSK |= 1< 122 | #ifdef __ASSEMBLER__ 123 | # define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ 124 | #else 125 | # include 126 | #endif 127 | 128 | #define USB_READ_FLASH(addr) pgm_read_byte(addr) 129 | 130 | #define macro .macro 131 | #define endm .endm 132 | #define nop2 rjmp .+0 /* jump to next instruction */ 133 | 134 | #endif /* development environment */ 135 | 136 | /* for conveniecne, ensure that PRG_RDB exists */ 137 | #ifndef PRG_RDB 138 | # define PRG_RDB(addr) USB_READ_FLASH(addr) 139 | #endif 140 | #endif /* __usbportability_h_INCLUDED__ */ 141 | -------------------------------------------------------------------------------- /USB-IDs-for-free.txt: -------------------------------------------------------------------------------- 1 | Version 2009-08-22 2 | 3 | =========================== 4 | FREE USB-IDs FOR SHARED USE 5 | =========================== 6 | 7 | Objective Development has reserved a set of USB Product-IDs for use according 8 | to the guidelines outlined below. For more information about the concept of 9 | USB IDs please see the file USB-ID-FAQ.txt. Objective Development guarantees 10 | that the IDs listed below are not used by any USB compliant devices. 11 | 12 | 13 | ==================== 14 | MECHANISM OF SHARING 15 | ==================== 16 | 17 | From a technical point of view, two different devices can share the same USB 18 | Vendor- and Product-ID if they require the same driver on operating system 19 | level. We make use of this fact by assigning separate IDs for various device 20 | classes. On application layer, devices must be distinguished by their textual 21 | name or serial number. We offer separate sets of IDs for discrimination by 22 | textual name and for serial number. 23 | 24 | Examples for shared use of USB IDs are included with V-USB in the "examples" 25 | subdirectory. 26 | 27 | 28 | ====================================== 29 | IDs FOR DISCRIMINATION BY TEXTUAL NAME 30 | ====================================== 31 | 32 | If you use one of the IDs listed below, your device and host-side software 33 | must conform to these rules: 34 | 35 | (1) The USB device MUST provide a textual representation of the manufacturer 36 | and product identification. The manufacturer identification MUST be available 37 | at least in USB language 0x0409 (English/US). 38 | 39 | (2) The textual manufacturer identification MUST contain either an Internet 40 | domain name (e.g. "mycompany.com") registered and owned by you, or an e-mail 41 | address under your control (e.g. "myname@gmx.net"). You can embed the domain 42 | name or e-mail address in any string you like, e.g. "Objective Development 43 | http://www.obdev.at/vusb/". 44 | 45 | (3) You are responsible for retaining ownership of the domain or e-mail 46 | address for as long as any of your products are in use. 47 | 48 | (4) You may choose any string for the textual product identification, as long 49 | as this string is unique within the scope of your textual manufacturer 50 | identification. 51 | 52 | (5) Application side device look-up MUST be based on the textual manufacturer 53 | and product identification in addition to VID/PID matching. The driver 54 | matching MUST be a comparison of the entire strings, NOT a sub-string match. 55 | 56 | (6) For devices which implement a particular USB device class (e.g. HID), the 57 | operating system's default class driver MUST be used. If an operating system 58 | driver for Vendor Class devices is needed, this driver must be libusb or 59 | libusb-win32 (see http://libusb.org/ and 60 | http://libusb-win32.sourceforge.net/). 61 | 62 | Table if IDs for discrimination by textual name: 63 | 64 | PID dec (hex) | VID dec (hex) | Description of use 65 | ==============+===============+============================================ 66 | 1500 (0x05dc) | 5824 (0x16c0) | For Vendor Class devices with libusb 67 | --------------+---------------+-------------------------------------------- 68 | 1503 (0x05df) | 5824 (0x16c0) | For generic HID class devices (which are 69 | | | NOT mice, keyboards or joysticks) 70 | --------------+---------------+-------------------------------------------- 71 | 1505 (0x05e1) | 5824 (0x16c0) | For CDC-ACM class devices (modems) 72 | --------------+---------------+-------------------------------------------- 73 | 1508 (0x05e4) | 5824 (0x16c0) | For MIDI class devices 74 | --------------+---------------+-------------------------------------------- 75 | 76 | Note that Windows caches the textual product- and vendor-description for 77 | mice, keyboards and joysticks. Name-bsed discrimination is therefore not 78 | recommended for these device classes. 79 | 80 | 81 | ======================================= 82 | IDs FOR DISCRIMINATION BY SERIAL NUMBER 83 | ======================================= 84 | 85 | If you use one of the IDs listed below, your device and host-side software 86 | must conform to these rules: 87 | 88 | (1) The USB device MUST provide a textual representation of the serial 89 | number. The serial number string MUST be available at least in USB language 90 | 0x0409 (English/US). 91 | 92 | (2) The serial number MUST start with either an Internet domain name (e.g. 93 | "mycompany.com") registered and owned by you, or an e-mail address under your 94 | control (e.g. "myname@gmx.net"), both terminated with a colon (":") character. 95 | You MAY append any string you like for further discrimination of your devices. 96 | 97 | (3) You are responsible for retaining ownership of the domain or e-mail 98 | address for as long as any of your products are in use. 99 | 100 | (5) Application side device look-up MUST be based on the serial number string 101 | in addition to VID/PID matching. The matching must start at the first 102 | character of the serial number string and include the colon character 103 | terminating your domain or e-mail address. It MAY stop anywhere after that. 104 | 105 | (6) For devices which implement a particular USB device class (e.g. HID), the 106 | operating system's default class driver MUST be used. If an operating system 107 | driver for Vendor Class devices is needed, this driver must be libusb or 108 | libusb-win32 (see http://libusb.org/ and 109 | http://libusb-win32.sourceforge.net/). 110 | 111 | Table if IDs for discrimination by serial number string: 112 | 113 | PID dec (hex) | VID dec (hex) | Description of use 114 | ===============+===============+=========================================== 115 | 10200 (0x27d8) | 5824 (0x16c0) | For Vendor Class devices with libusb 116 | ---------------+---------------+------------------------------------------- 117 | 10201 (0x27d9) | 5824 (0x16c0) | For generic HID class devices (which are 118 | | | NOT mice, keyboards or joysticks) 119 | ---------------+---------------+------------------------------------------- 120 | 10202 (0x27da) | 5824 (0x16c0) | For USB Mice 121 | ---------------+---------------+------------------------------------------- 122 | 10203 (0x27db) | 5824 (0x16c0) | For USB Keyboards 123 | ---------------+---------------+------------------------------------------- 124 | 10204 (0x27db) | 5824 (0x16c0) | For USB Joysticks 125 | ---------------+---------------+------------------------------------------- 126 | 10205 (0x27dc) | 5824 (0x16c0) | For CDC-ACM class devices (modems) 127 | ---------------+---------------+------------------------------------------- 128 | 10206 (0x27dd) | 5824 (0x16c0) | For MIDI class devices 129 | ---------------+---------------+------------------------------------------- 130 | 131 | 132 | ================= 133 | ORIGIN OF USB-IDs 134 | ================= 135 | 136 | OBJECTIVE DEVELOPMENT Software GmbH has obtained all VID/PID pairs listed 137 | here from Wouter van Ooijen (see www.voti.nl) for exclusive disposition. 138 | Wouter van Ooijen has obtained the VID from the USB Implementers Forum, Inc. 139 | (see www.usb.org). The VID is registered for the company name "Van Ooijen 140 | Technische Informatica". 141 | 142 | 143 | ========== 144 | DISCLAIMER 145 | ========== 146 | 147 | OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any 148 | problems which are caused by the shared use of these VID/PID pairs. 149 | -------------------------------------------------------------------------------- /DigiKeyboard.h.old: -------------------------------------------------------------------------------- 1 | /* 2 | * Based on Obdev's AVRUSB code and under the same license. 3 | * 4 | * TODO: Make a proper file header. :-) 5 | * Modified for Digispark by Digistump 6 | */ 7 | #ifndef __DigiKeyboard_h__ 8 | #define __DigiKeyboard_h__ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "usbdrv.h" 16 | 17 | // TODO: Work around Arduino 12 issues better. 18 | //#include 19 | //#undef int() 20 | 21 | typedef uint8_t byte; 22 | 23 | 24 | #define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke 25 | 26 | 27 | static uchar idleRate; // in 4 ms units 28 | 29 | 30 | /* We use a simplifed keyboard report descriptor which does not support the 31 | * boot protocol. We don't allow setting status LEDs and but we do allow 32 | * simultaneous key presses. 33 | * The report descriptor has been created with usb.org's "HID Descriptor Tool" 34 | * which can be downloaded from http://www.usb.org/developers/hidpage/. 35 | * Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted 36 | * for the second INPUT item. 37 | */ 38 | PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */ 39 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 40 | 0x09, 0x06, // USAGE (Keyboard) 41 | 0xa1, 0x01, // COLLECTION (Application) 42 | 0x05, 0x07, // USAGE_PAGE (Keyboard) 43 | 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 44 | 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 45 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 46 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 47 | 0x75, 0x01, // REPORT_SIZE (1) 48 | 0x95, 0x08, // REPORT_COUNT (8) 49 | 0x81, 0x02, // INPUT (Data,Var,Abs) 50 | 0x95, 0x01, // REPORT_COUNT (simultaneous keystrokes) 51 | 0x75, 0x08, // REPORT_SIZE (8) 52 | 0x25, 0x65, // LOGICAL_MAXIMUM (101) 53 | 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 54 | 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 55 | 0x81, 0x00, // INPUT (Data,Ary,Abs) 56 | 0xc0 // END_COLLECTION 57 | }; 58 | 59 | 60 | 61 | /* Keyboard usage values, see usb.org's HID-usage-tables document, chapter 62 | * 10 Keyboard/Keypad Page for more codes. 63 | */ 64 | #define MOD_CONTROL_LEFT (1<<0) 65 | #define MOD_SHIFT_LEFT (1<<1) 66 | #define MOD_ALT_LEFT (1<<2) 67 | #define MOD_GUI_LEFT (1<<3) 68 | #define MOD_CONTROL_RIGHT (1<<4) 69 | #define MOD_SHIFT_RIGHT (1<<5) 70 | #define MOD_ALT_RIGHT (1<<6) 71 | #define MOD_GUI_RIGHT (1<<7) 72 | 73 | #define KEY_A 4 74 | #define KEY_B 5 75 | #define KEY_C 6 76 | #define KEY_D 7 77 | #define KEY_E 8 78 | #define KEY_F 9 79 | #define KEY_G 10 80 | #define KEY_H 11 81 | #define KEY_I 12 82 | #define KEY_J 13 83 | #define KEY_K 14 84 | #define KEY_L 15 85 | #define KEY_M 16 86 | #define KEY_N 17 87 | #define KEY_O 18 88 | #define KEY_P 19 89 | #define KEY_Q 20 90 | #define KEY_R 21 91 | #define KEY_S 22 92 | #define KEY_T 23 93 | #define KEY_U 24 94 | #define KEY_V 25 95 | #define KEY_W 26 96 | #define KEY_X 27 97 | #define KEY_Y 28 98 | #define KEY_Z 29 99 | #define KEY_1 30 100 | #define KEY_2 31 101 | #define KEY_3 32 102 | #define KEY_4 33 103 | #define KEY_5 34 104 | #define KEY_6 35 105 | #define KEY_7 36 106 | #define KEY_8 37 107 | #define KEY_9 38 108 | #define KEY_0 39 109 | 110 | #define KEY_ENTER 40 111 | 112 | #define KEY_SPACE 44 113 | 114 | #define KEY_F1 58 115 | #define KEY_F2 59 116 | #define KEY_F3 60 117 | #define KEY_F4 61 118 | #define KEY_F5 62 119 | #define KEY_F6 63 120 | #define KEY_F7 64 121 | #define KEY_F8 65 122 | #define KEY_F9 66 123 | #define KEY_F10 67 124 | #define KEY_F11 68 125 | #define KEY_F12 69 126 | 127 | #define KEY_ARROW_LEFT 0x50 128 | 129 | 130 | class DigiKeyboardDevice { 131 | public: 132 | DigiKeyboardDevice () { 133 | TIMSK &= !(1bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ 204 | /* class request type */ 205 | 206 | if(rq->bRequest == USBRQ_HID_GET_REPORT){ 207 | /* wValue: ReportType (highbyte), ReportID (lowbyte) */ 208 | 209 | /* we only have one report type, so don't look at wValue */ 210 | // TODO: Ensure it's okay not to return anything here? 211 | return 0; 212 | 213 | }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ 214 | // usbMsgPtr = &idleRate; 215 | // return 1; 216 | return 0; 217 | }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ 218 | idleRate = rq->wValue.bytes[1]; 219 | } 220 | }else{ 221 | /* no vendor specific requests implemented */ 222 | } 223 | return 0; 224 | } 225 | #ifdef __cplusplus 226 | } // extern "C" 227 | #endif 228 | 229 | 230 | #endif // __DigiKeyboard_h__ 231 | -------------------------------------------------------------------------------- /USB-ID-FAQ.txt: -------------------------------------------------------------------------------- 1 | Version 2009-08-22 2 | 3 | ========================== 4 | WHY DO WE NEED THESE IDs? 5 | ========================== 6 | 7 | USB is more than a low level protocol for data transport. It also defines a 8 | common set of requests which must be understood by all devices. And as part 9 | of these common requests, the specification defines data structures, the 10 | USB Descriptors, which are used to describe the properties of the device. 11 | 12 | From the perspective of an operating system, it is therefore possible to find 13 | out basic properties of a device (such as e.g. the manufacturer and the name 14 | of the device) without a device-specific driver. This is essential because 15 | the operating system can choose a driver to load based on this information 16 | (Plug-And-Play). 17 | 18 | Among the most important properties in the Device Descriptor are the USB 19 | Vendor- and Product-ID. Both are 16 bit integers. The most simple form of 20 | driver matching is based on these IDs. The driver announces the Vendor- and 21 | Product-IDs of the devices it can handle and the operating system loads the 22 | appropriate driver when the device is connected. 23 | 24 | It is obvious that this technique only works if the pair Vendor- plus 25 | Product-ID is unique: Only devices which require the same driver can have the 26 | same pair of IDs. 27 | 28 | 29 | ===================================================== 30 | HOW DOES THE USB STANDARD ENSURE THAT IDs ARE UNIQUE? 31 | ===================================================== 32 | 33 | Since it is so important that USB IDs are unique, the USB Implementers Forum, 34 | Inc. (usb.org) needs a way to enforce this legally. It is not forbidden by 35 | law to build a device and assign it any random numbers as IDs. Usb.org 36 | therefore needs an agreement to regulate the use of USB IDs. The agreement 37 | binds only parties who agreed to it, of course. Everybody else is free to use 38 | any numbers for their IDs. 39 | 40 | So how can usb.org ensure that every manufacturer of USB devices enters into 41 | an agreement with them? They do it via trademark licensing. Usb.org has 42 | registered the trademark "USB", all associated logos and related terms. If 43 | you want to put an USB logo on your product or claim that it is USB 44 | compliant, you must license these trademarks from usb.org. And this is where 45 | you enter into an agreement. See the "USB-IF Trademark License Agreement and 46 | Usage Guidelines for the USB-IF Logo" at 47 | http://www.usb.org/developers/logo_license/. 48 | 49 | Licensing the USB trademarks requires that you buy a USB Vendor-ID from 50 | usb.org (one-time fee of ca. 2,000 USD), that you become a member of usb.org 51 | (yearly fee of ca. 4,000 USD) and that you meet all the technical 52 | specifications from the USB spec. 53 | 54 | This means that most hobbyists and small companies will never be able to 55 | become USB compliant, just because membership is so expensive. And you can't 56 | be compliant with a driver based on V-USB anyway, because the AVR's port pins 57 | don't meet the electrical specifications for USB. So, in principle, all 58 | hobbyists and small companies are free to choose any random numbers for their 59 | IDs. They have nothing to lose... 60 | 61 | There is one exception worth noting, though: If you use a sub-component which 62 | implements USB, the vendor of the sub-components may guarantee USB 63 | compliance. This might apply to some or all of FTDI's solutions. 64 | 65 | 66 | ======================================================================= 67 | WHY SHOULD YOU OBTAIN USB IDs EVEN IF YOU DON'T LICENSE USB TRADEMARKS? 68 | ======================================================================= 69 | 70 | You have learned in the previous section that you are free to choose any 71 | numbers for your IDs anyway. So why not do exactly this? There is still the 72 | technical issue. If you choose IDs which are already in use by somebody else, 73 | operating systems will load the wrong drivers and your device won't work. 74 | Even if you choose IDs which are not currently in use, they may be in use in 75 | the next version of the operating system or even after an automatic update. 76 | 77 | So what you need is a pair of Vendor- and Product-IDs for which you have the 78 | guarantee that no USB compliant product uses them. This implies that no 79 | operating system will ever ship with drivers responsible for these IDs. 80 | 81 | 82 | ============================================== 83 | HOW DOES OBJECTIVE DEVELOPMENT HANDLE USB IDs? 84 | ============================================== 85 | 86 | Objective Development gives away pairs of USB-IDs with their V-USB licenses. 87 | In order to ensure that these IDs are unique, Objective Development has an 88 | agreement with the company/person who has bought the USB Vendor-ID from 89 | usb.org. This agreement ensures that a range of USB Product-IDs is reserved 90 | for assignment by Objective Development and that the owner of the Vendor-ID 91 | won't give it to anybody else. 92 | 93 | This means that you have to trust three parties to ensure uniqueness of 94 | your IDs: 95 | 96 | - Objective Development, that they don't give the same PID to more than 97 | one person. 98 | - The owner of the Vendor-ID that they don't assign PIDs from the range 99 | assigned to Objective Development to anybody else. 100 | - Usb.org that they don't assign the same Vendor-ID a second time. 101 | 102 | 103 | ================================== 104 | WHO IS THE OWNER OF THE VENDOR-ID? 105 | ================================== 106 | 107 | Objective Development has obtained ranges of USB Product-IDs under two 108 | Vendor-IDs: Under Vendor-ID 5824 from Wouter van Ooijen (Van Ooijen 109 | Technische Informatica, www.voti.nl) and under Vendor-ID 8352 from Jason 110 | Kotzin (Clay Logic, www.claylogic.com). Both VID owners have received their 111 | Vendor-ID directly from usb.org. 112 | 113 | 114 | ========================================================================= 115 | CAN I USE USB-IDs FROM OBJECTIVE DEVELOPMENT WITH OTHER DRIVERS/HARDWARE? 116 | ========================================================================= 117 | 118 | The short answer is: Yes. All you get is a guarantee that the IDs are never 119 | assigned to anybody else. What more do you need? 120 | 121 | 122 | ============================ 123 | WHAT ABOUT SHARED ID PAIRS? 124 | ============================ 125 | 126 | Objective Development has reserved some PID/VID pairs for shared use. You 127 | have no guarantee of uniqueness for them, except that no USB compliant device 128 | uses them. In order to avoid technical problems, we must ensure that all 129 | devices with the same pair of IDs use the same driver on kernel level. For 130 | details, see the file USB-IDs-for-free.txt. 131 | 132 | 133 | ====================================================== 134 | I HAVE HEARD THAT SUB-LICENSING OF USB-IDs IS ILLEGAL? 135 | ====================================================== 136 | 137 | A 16 bit integer number cannot be protected by copyright laws. It is not 138 | sufficiently complex. And since none of the parties involved entered into the 139 | USB-IF Trademark License Agreement, we are not bound by this agreement. So 140 | there is no reason why it should be illegal to sub-license USB-IDs. 141 | 142 | 143 | ============================================= 144 | WHO IS LIABLE IF THERE ARE INCOMPATIBILITIES? 145 | ============================================= 146 | 147 | Objective Development disclaims all liabilities which might arise from the 148 | assignment of IDs. If you guarantee product features to your customers 149 | without proper disclaimer, YOU are liable for that. 150 | -------------------------------------------------------------------------------- /CommercialLicense.txt: -------------------------------------------------------------------------------- 1 | V-USB Driver Software License Agreement 2 | Version 2009-08-03 3 | 4 | THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN 5 | ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING 6 | THE AMOUNT ACCORDING TO SECTION 4 ("PAYMENT") TO OBJECTIVE DEVELOPMENT. 7 | 8 | 9 | 1 DEFINITIONS 10 | 11 | 1.1 "OBJECTIVE DEVELOPMENT" shall mean OBJECTIVE DEVELOPMENT Software GmbH, 12 | Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA. 13 | 14 | 1.2 "You" shall mean the Licensee. 15 | 16 | 1.3 "V-USB" shall mean all files included in the package distributed under 17 | the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/) 18 | unless otherwise noted. This includes the firmware-only USB device 19 | implementation for Atmel AVR microcontrollers, some simple device examples 20 | and host side software examples and libraries. 21 | 22 | 23 | 2 LICENSE GRANTS 24 | 25 | 2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source 26 | code of V-USB. 27 | 28 | 2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the 29 | non-exclusive right to use, copy and distribute V-USB with your hardware 30 | product(s), restricted by the limitations in section 3 below. 31 | 32 | 2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify 33 | the source code and your copy of V-USB according to your needs. 34 | 35 | 2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB 36 | Product ID(s), sent to you in e-mail. These Product IDs are reserved 37 | exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID 38 | ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen 39 | Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from 40 | Jason Kotzin (Clay Logic, www.claylogic.com). Both owners of the Vendor IDs 41 | have obtained these IDs from the USB Implementers Forum, Inc. 42 | (www.usb.org). OBJECTIVE DEVELOPMENT disclaims all liability which might 43 | arise from the assignment of USB IDs. 44 | 45 | 2.5 USB Certification. Although not part of this agreement, we want to make 46 | it clear that you cannot become USB certified when you use V-USB or a USB 47 | Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't 48 | meet the electrical specifications required by the USB specification and 49 | the USB Implementers Forum certifies only members who bought a Vendor ID of 50 | their own. 51 | 52 | 53 | 3 LICENSE RESTRICTIONS 54 | 55 | 3.1 Number of Units. Only one of the following three definitions is 56 | applicable. Which one is determined by the amount you pay to OBJECTIVE 57 | DEVELOPMENT, see section 4 ("Payment") below. 58 | 59 | Hobby License: You may use V-USB according to section 2 above in no more 60 | than 5 hardware units. These units must not be sold for profit. 61 | 62 | Entry Level License: You may use V-USB according to section 2 above in no 63 | more than 150 hardware units. 64 | 65 | Professional License: You may use V-USB according to section 2 above in 66 | any number of hardware units, except for large scale production ("unlimited 67 | fair use"). Quantities below 10,000 units are not considered large scale 68 | production. If your reach quantities which are obviously large scale 69 | production, you must pay a license fee of 0.10 EUR per unit for all units 70 | above 10,000. 71 | 72 | 3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber 73 | any copy of V-USB, or any of the rights granted herein. 74 | 75 | 3.3 Transfer. You may not transfer your rights under this Agreement to 76 | another party without OBJECTIVE DEVELOPMENT's prior written consent. If 77 | such consent is obtained, you may permanently transfer this License to 78 | another party. The recipient of such transfer must agree to all terms and 79 | conditions of this Agreement. 80 | 81 | 3.4 Reservation of Rights. OBJECTIVE DEVELOPMENT retains all rights not 82 | expressly granted. 83 | 84 | 3.5 Non-Exclusive Rights. Your license rights under this Agreement are 85 | non-exclusive. 86 | 87 | 3.6 Third Party Rights. This Agreement cannot grant you rights controlled 88 | by third parties. In particular, you are not allowed to use the USB logo or 89 | other trademarks owned by the USB Implementers Forum, Inc. without their 90 | consent. Since such consent depends on USB certification, it should be 91 | noted that V-USB will not pass certification because it does not 92 | implement checksum verification and the microcontroller ports do not meet 93 | the electrical specifications. 94 | 95 | 96 | 4 PAYMENT 97 | 98 | The payment amount depends on the variation of this agreement (according to 99 | section 3.1) into which you want to enter. Concrete prices are listed on 100 | OBJECTIVE DEVELOPMENT's web site, usually at 101 | http://www.obdev.at/vusb/license.html. You agree to pay the amount listed 102 | there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor 103 | or reseller. 104 | 105 | 106 | 5 COPYRIGHT AND OWNERSHIP 107 | 108 | V-USB is protected by copyright laws and international copyright 109 | treaties, as well as other intellectual property laws and treaties. V-USB 110 | is licensed, not sold. 111 | 112 | 113 | 6 TERM AND TERMINATION 114 | 115 | 6.1 Term. This Agreement shall continue indefinitely. However, OBJECTIVE 116 | DEVELOPMENT may terminate this Agreement and revoke the granted license and 117 | USB-IDs if you fail to comply with any of its terms and conditions. 118 | 119 | 6.2 Survival of Terms. All provisions regarding secrecy, confidentiality 120 | and limitation of liability shall survive termination of this agreement. 121 | 122 | 123 | 7 DISCLAIMER OF WARRANTY AND LIABILITY 124 | 125 | LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 126 | KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE 127 | DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER 128 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 129 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 130 | NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE 131 | TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL 132 | RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO 133 | STATE/JURISDICTION. 134 | 135 | LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, 136 | IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY 137 | SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER 138 | (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 139 | BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY 140 | LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE 141 | PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE 142 | DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY 143 | CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS 144 | AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB. 145 | 146 | 147 | 8 MISCELLANEOUS TERMS 148 | 149 | 8.1 Marketing. OBJECTIVE DEVELOPMENT has the right to mention for marketing 150 | purposes that you entered into this agreement. 151 | 152 | 8.2 Entire Agreement. This document represents the entire agreement between 153 | OBJECTIVE DEVELOPMENT and you. It may only be modified in writing signed by 154 | an authorized representative of both, OBJECTIVE DEVELOPMENT and you. 155 | 156 | 8.3 Severability. In case a provision of these terms and conditions should 157 | be or become partly or entirely invalid, ineffective, or not executable, 158 | the validity of all other provisions shall not be affected. 159 | 160 | 8.4 Applicable Law. This agreement is governed by the laws of the Republic 161 | of Austria. 162 | 163 | 8.5 Responsible Courts. The responsible courts in Vienna/Austria will have 164 | exclusive jurisdiction regarding all disputes in connection with this 165 | agreement. 166 | 167 | -------------------------------------------------------------------------------- /USBID-License.txt: -------------------------------------------------------------------------------- 1 | Royalty-Free Non-Exclusive Use of USB Product-IDs 2 | ================================================= 3 | 4 | Version 2009-04-13 5 | 6 | Strictly speaking, this is not a license. You can't give a license to use 7 | a simple number (such as e.g. 1500) for any purpose. This is a set of rules 8 | which should make it possible to build USB devices without the requirement 9 | for individual USB IDs. If you break one of the rules, you will run into 10 | technical problems sooner or later, but you don't risk legal trouble. 11 | 12 | 13 | OBJECTIVE DEVELOPMENT Software GmbH hereby grants you the non-exclusive 14 | right to use four USB.org vendor-ID (VID) / product-ID (PID) pairs with 15 | products based on Objective Development's firmware-only USB driver for 16 | Atmel AVR microcontrollers: 17 | 18 | * VID = 5824 (=0x16c0) / PID = 1500 (=0x5dc) for devices implementing no 19 | USB device class (vendor-class devices with USB class = 0xff). Devices 20 | using this pair will be referred to as "VENDOR CLASS" devices. 21 | 22 | * VID = 5824 (=0x16c0) / PID = 1503 (=0x5df) for HID class devices 23 | (excluding mice and keyboards). Devices using this pair will be referred 24 | to as "HID CLASS" devices. 25 | 26 | * VID = 5824 (=0x16c0) / PID = 1505 (=0x5e1) for CDC class modem devices 27 | Devices using this pair will be referred to as "CDC-ACM CLASS" devices. 28 | 29 | * VID = 5824 (=0x16c0) / PID = 1508 (=0x5e4) for MIDI class devices 30 | Devices using this pair will be referred to as "MIDI CLASS" devices. 31 | 32 | Since the granted right is non-exclusive, the same VID/PID pairs may be 33 | used by many companies and individuals for different products. To avoid 34 | conflicts, your device and host driver software MUST adhere to the rules 35 | outlined below. 36 | 37 | OBJECTIVE DEVELOPMENT Software GmbH has obtained these VID/PID pairs from 38 | Wouter van Ooijen (see www.voti.nl) for exclusive disposition. Wouter van 39 | Ooijen has obtained the VID from the USB Implementers Forum, Inc. 40 | (see www.usb.org). The VID is registered for the company name 41 | "Van Ooijen Technische Informatica". 42 | 43 | 44 | RULES AND RESTRICTIONS 45 | ====================== 46 | 47 | (1) The USB device MUST provide a textual representation of the 48 | manufacturer and product identification. The manufacturer identification 49 | MUST be available at least in USB language 0x0409 (English/US). 50 | 51 | (2) The textual manufacturer identification MUST contain either an Internet 52 | domain name (e.g. "mycompany.com") registered and owned by you, or an 53 | e-mail address under your control (e.g. "myname@gmx.net"). You can embed 54 | the domain name or e-mail address in any string you like, e.g. "Objective 55 | Development http://www.obdev.at/vusb/". 56 | 57 | (3) You are responsible for retaining ownership of the domain or e-mail 58 | address for as long as any of your products are in use. 59 | 60 | (4) You may choose any string for the textual product identification, as 61 | long as this string is unique within the scope of your textual manufacturer 62 | identification. 63 | 64 | (5) Matching of device-specific drivers MUST be based on the textual 65 | manufacturer and product identification in addition to the usual VID/PID 66 | matching. This means that operating system features which are based on 67 | VID/PID matching only (e.g. Windows kernel level drivers, automatic actions 68 | when the device is plugged in etc) MUST NOT be used. The driver matching 69 | MUST be a comparison of the entire strings, NOT a sub-string match. For 70 | CDC-ACM CLASS and MIDI CLASS devices, a generic class driver should be used 71 | and the matching is based on the USB device class. 72 | 73 | (6) The extent to which VID/PID matching is allowed for non device-specific 74 | drivers or features depends on the operating system and particular VID/PID 75 | pair used: 76 | 77 | * Mac OS X, Linux, FreeBSD and other Unixes: No VID/PID matching is 78 | required and hence no VID/PID-only matching is allowed at all. 79 | 80 | * Windows: The operating system performs VID/PID matching for the kernel 81 | level driver. You are REQUIRED to use libusb-win32 (see 82 | http://libusb-win32.sourceforge.net/) as the kernel level driver for 83 | VENDOR CLASS devices. HID CLASS devices all use the generic HID class 84 | driver shipped with Windows, except mice and keyboards. You therefore 85 | MUST NOT use any of the shared VID/PID pairs for mice or keyboards. 86 | CDC-ACM CLASS devices require a ".inf" file which matches on the VID/PID 87 | pair. This ".inf" file MUST load the "usbser" driver to configure the 88 | device as modem (COM-port). 89 | 90 | (7) OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any 91 | problems which are caused by the shared use of these VID/PID pairs. You 92 | have been warned that the sharing of VID/PID pairs may cause problems. If 93 | you want to avoid them, get your own VID/PID pair for exclusive use. 94 | 95 | 96 | HOW TO IMPLEMENT THESE RULES 97 | ============================ 98 | 99 | The following rules are for VENDOR CLASS and HID CLASS devices. CDC-ACM 100 | CLASS and MIDI CLASS devices use the operating system's class driver and 101 | don't need a custom driver. 102 | 103 | The host driver MUST iterate over all devices with the given VID/PID 104 | numbers in their device descriptors and query the string representation for 105 | the manufacturer name in USB language 0x0409 (English/US). It MUST compare 106 | the ENTIRE string with your textual manufacturer identification chosen in 107 | (2) above. A substring search for your domain or e-mail address is NOT 108 | acceptable. The driver MUST NOT touch the device (other than querying the 109 | descriptors) unless the strings match. 110 | 111 | For all USB devices with matching VID/PID and textual manufacturer 112 | identification, the host driver must query the textual product 113 | identification and string-compare it with the name of the product it can 114 | control. It may only initialize the device if the product matches exactly. 115 | 116 | Objective Development provides examples for these matching rules with the 117 | "PowerSwitch" project (using libusb) and with the "Automator" project 118 | (using Windows calls on Windows and libusb on Unix). 119 | 120 | 121 | Technical Notes: 122 | ================ 123 | 124 | Sharing the same VID/PID pair among devices is possible as long as ALL 125 | drivers which match the VID/PID also perform matching on the textual 126 | identification strings. This is easy on all operating systems except 127 | Windows, since Windows establishes a static connection between the VID/PID 128 | pair and a kernel level driver. All devices with the same VID/PID pair must 129 | therefore use THE SAME kernel level driver. 130 | 131 | We therefore demand that you use libusb-win32 for VENDOR CLASS devices. 132 | This is a generic kernel level driver which allows all types of USB access 133 | for user space applications. This is only a partial solution of the 134 | problem, though, because different device drivers may come with different 135 | versions of libusb-win32 and they may not work with the libusb version of 136 | the respective other driver. You are therefore encouraged to test your 137 | driver against a broad range of libusb-win32 versions. Do not use new 138 | features in new versions, or check for their existence before you use them. 139 | When a new libusb-win32 becomes available, make sure that your driver is 140 | compatible with it. 141 | 142 | For HID CLASS devices it is necessary that all those devices bind to the 143 | same kernel driver: Microsoft's generic USB HID driver. This is true for 144 | all HID devices except those with a specialized driver. Currently, the only 145 | HIDs with specialized drivers are mice and keyboards. You therefore MUST 146 | NOT use a shared VID/PID with mouse and keyboard devices. 147 | 148 | Sharing the same VID/PID among different products is unusual and probably 149 | violates the USB specification. If you do it, you do it at your own risk. 150 | 151 | To avoid possible incompatibilities, we highly recommend that you get your 152 | own VID/PID pair if you intend to sell your product. Objective 153 | Development's commercial licenses for V-USB include a PID for 154 | unrestricted exclusive use. 155 | -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | 2 | ToDo: write readme. 3 | 4 | for now the explanation is here: 5 | http://www.g3gg0.de/wordpress/arduino/attiny85-a-simple-crossfire-usb-adapter/ 6 | 7 | Important hint: 8 | PB1: CRSF Rx 9 | PB2/PB3: bridged to remap USB INT 10 | 11 | 12 | Original readme: 13 | ________________________________ 14 | This is the Readme file to Objective Development's firmware-only USB driver 15 | for Atmel AVR microcontrollers. For more information please visit 16 | http://www.obdev.at/vusb/ 17 | 18 | This directory contains the USB firmware only. Copy it as-is to your own 19 | project and add all .c and .S files to your project (these files are marked 20 | with an asterisk in the list below). Then copy usbconfig-prototype.h as 21 | usbconfig.h to your project and edit it according to your configuration. 22 | 23 | 24 | TECHNICAL DOCUMENTATION 25 | ======================= 26 | The technical documentation (API) for the firmware driver is contained in the 27 | file "usbdrv.h". Please read all of it carefully! Configuration options are 28 | documented in "usbconfig-prototype.h". 29 | 30 | The driver consists of the following files: 31 | Readme.txt ............. The file you are currently reading. 32 | Changelog.txt .......... Release notes for all versions of the driver. 33 | usbdrv.h ............... Driver interface definitions and technical docs. 34 | * usbdrv.c ............... High level language part of the driver. Link this 35 | module to your code! 36 | * usbdrvasm.S ............ Assembler part of the driver. This module is mostly 37 | a stub and includes one of the usbdrvasm*.S files 38 | depending on processor clock. Link this module to 39 | your code! 40 | usbdrvasm*.inc ......... Assembler routines for particular clock frequencies. 41 | Included by usbdrvasm.S, don't link it directly! 42 | asmcommon.inc .......... Common assembler routines. Included by 43 | usbdrvasm*.inc, don't link it directly! 44 | usbconfig-prototype.h .. Prototype for your own usbdrv.h file. 45 | * oddebug.c .............. Debug functions. Only used when DEBUG_LEVEL is 46 | defined to a value greater than 0. Link this module 47 | to your code! 48 | oddebug.h .............. Interface definitions of the debug module. 49 | usbportability.h ....... Header with compiler-dependent stuff. 50 | usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this 51 | module instead of usbdrvasm.S when you assembler 52 | with IAR's tools. 53 | License.txt ............ Open Source license for this driver. 54 | CommercialLicense.txt .. Optional commercial license for this driver. 55 | USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs. 56 | USB-IDs-for-free.txt ... List and terms of use for free shared PIDs. 57 | 58 | (*) ... These files should be linked to your project. 59 | 60 | 61 | CPU CORE CLOCK FREQUENCY 62 | ======================== 63 | We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz, 64 | 16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The 65 | actual clock rate must be configured in usbdrv.h unless you use the default 66 | 12 MHz. 67 | 68 | 12 MHz Clock 69 | This is the traditional clock rate of V-USB because it's the lowest clock 70 | rate where the timing constraints of the USB spec can be met. 71 | 72 | 15 MHz Clock 73 | Similar to 12 MHz, but some NOPs inserted. On the other hand, the higher clock 74 | rate allows for some loops which make the resulting code size somewhat smaller 75 | than the 12 MHz version. 76 | 77 | 16 MHz Clock 78 | This clock rate has been added for users of the Arduino board and other 79 | ready-made boards which come with a fixed 16 MHz crystal. It's also an option 80 | if you need the slightly higher clock rate for performance reasons. Since 81 | 16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code 82 | is somewhat tricky and has to insert a leap cycle every third byte. 83 | 84 | 12.8 MHz and 16.5 MHz Clock 85 | The assembler modules for these clock rates differ from the other modules 86 | because they have been built for an RC oscillator with only 1% precision. The 87 | receiver code inserts leap cycles to compensate for clock deviations. 1% is 88 | also the precision which can be achieved by calibrating the internal RC 89 | oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL 90 | oscillator can reach 16.5 MHz with the RC oscillator. This includes the very 91 | popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost 92 | all AVRs can reach 12.8 MHz, although this is outside the specified range. 93 | 94 | See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for 95 | code which calibrates the RC oscillator based on the USB frame clock. 96 | 97 | 18 MHz Clock 98 | This module is closer to the USB specification because it performs an on the 99 | fly CRC check for incoming packets. Packets with invalid checksum are 100 | discarded as required by the spec. If you also implement checks for data 101 | PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING 102 | in usbconfig.h for more info), this ensures data integrity. Due to the CRC 103 | tables and alignment requirements, this code is bigger than modules for other 104 | clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1 105 | and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h. 106 | 107 | 20 MHz Clock 108 | This module is for people who won't do it with less than the maximum. Since 109 | 20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code 110 | uses similar tricks as the 16 MHz module to insert leap cycles. 111 | 112 | 113 | USB IDENTIFIERS 114 | =============== 115 | Every USB device needs a vendor- and a product-identifier (VID and PID). VIDs 116 | are obtained from usb.org for a price of 1,500 USD. Once you have a VID, you 117 | can assign PIDs at will. 118 | 119 | Since an entry level cost of 1,500 USD is too high for most small companies 120 | and hobbyists, we provide some VID/PID pairs for free. See the file 121 | USB-IDs-for-free.txt for details. 122 | 123 | Objective Development also has some license offerings which include product 124 | IDs. See http://www.obdev.at/vusb/ for details. 125 | 126 | 127 | DEVELOPMENT SYSTEM 128 | ================== 129 | This driver has been developed and optimized for the GNU compiler version 3 130 | (gcc 3). It does work well with gcc 4, but with bigger code size. We recommend 131 | that you use the GNU compiler suite because it is freely available. V-USB 132 | has also been ported to the IAR compiler and assembler. It has been tested 133 | with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the "small" and "tiny" 134 | memory model. Not every release is tested with IAR CC and the driver may 135 | therefore fail to compile with IAR. Please note that gcc is more efficient for 136 | usbdrv.c because this module has been deliberately optimized for gcc. 137 | 138 | 139 | USING V-USB FOR FREE 140 | ==================== 141 | The AVR firmware driver is published under the GNU General Public License 142 | Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is 143 | your choice whether you apply the terms of version 2 or version 3. 144 | 145 | If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the 146 | following things IN ADDITION to the obligations from the GPL: 147 | 148 | (1) Publish your entire project on a web site and drop us a note with the URL. 149 | Use the form at http://www.obdev.at/vusb/feedback.html for your submission. 150 | If you don't have a web site, you can publish the project in obdev's 151 | documentation wiki at 152 | http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects. 153 | 154 | (2) Adhere to minimum publication standards. Please include AT LEAST: 155 | - a circuit diagram in PDF, PNG or GIF format 156 | - full source code for the host software 157 | - a Readme.txt file in ASCII format which describes the purpose of the 158 | project and what can be found in which directories and which files 159 | - a reference to http://www.obdev.at/vusb/ 160 | 161 | (3) If you improve the driver firmware itself, please give us a free license 162 | to your modifications for our commercial license offerings. 163 | 164 | 165 | COMMERCIAL LICENSES FOR V-USB 166 | ============================= 167 | If you don't want to publish your source code under the terms of the GPL, 168 | you can simply pay money for V-USB. As an additional benefit you get 169 | USB PIDs for free, reserved exclusively to you. See the file 170 | "CommercialLicense.txt" for details. 171 | 172 | -------------------------------------------------------------------------------- /asmcommon.inc: -------------------------------------------------------------------------------- 1 | /* Name: asmcommon.inc 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2007-11-05 5 | * Tabsize: 4 6 | * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | * Revision: $Id$ 9 | */ 10 | 11 | /* Do not link this file! Link usbdrvasm.S instead, which includes the 12 | * appropriate implementation! 13 | */ 14 | 15 | /* 16 | General Description: 17 | This file contains assembler code which is shared among the USB driver 18 | implementations for different CPU cocks. Since the code must be inserted 19 | in the middle of the module, it's split out into this file and #included. 20 | 21 | Jump destinations called from outside: 22 | sofError: Called when no start sequence was found. 23 | se0: Called when a package has been successfully received. 24 | overflow: Called when receive buffer overflows. 25 | doReturn: Called after sending data. 26 | 27 | Outside jump destinations used by this module: 28 | waitForJ: Called to receive an already arriving packet. 29 | sendAckAndReti: 30 | sendNakAndReti: 31 | sendCntAndReti: 32 | usbSendAndReti: 33 | 34 | The following macros must be defined before this file is included: 35 | .macro POP_STANDARD 36 | .endm 37 | .macro POP_RETI 38 | .endm 39 | */ 40 | 41 | #define token x1 42 | 43 | overflow: 44 | ldi x2, 1< 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "usbdrv.h" 24 | //#include "devdesc.h" 25 | #include "oddebug.h" 26 | #include "usbconfig.h" 27 | 28 | const static uchar *rt_usbHidReportDescriptor=NULL; 29 | static uchar rt_usbHidReportDescriptorSize=0; 30 | const static uchar *rt_usbDeviceDescriptor=NULL; 31 | static uchar rt_usbDeviceDescriptorSize=0; 32 | 33 | 34 | #define HID_REPORT_SIZE (6+2) 35 | 36 | /* What was most recently read from the controller */ 37 | unsigned char last_built_report[HID_REPORT_SIZE]; 38 | /* What was most recently sent to the host */ 39 | unsigned char last_sent_report[HID_REPORT_SIZE]; 40 | 41 | // report frequency set to default of 50hz 42 | #define DIGIJOYSTICK_DEFAULT_REPORT_INTERVAL 80 43 | static unsigned char must_report = 0; 44 | static unsigned char idle_rate = DIGIJOYSTICK_DEFAULT_REPORT_INTERVAL / 4; // in units of 4ms 45 | // new minimum report frequency system: 46 | static unsigned long last_report_time = 0; 47 | 48 | 49 | const unsigned char gcn64_usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] PROGMEM = { 50 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 51 | 0x09, 0x05, // USAGE (Gamepad) 52 | 0xa1, 0x01, // COLLECTION (Application) 53 | 54 | 0x09, 0x01, // USAGE (Pointer) 55 | 0xa1, 0x00, // COLLECTION (Physical) 56 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 57 | 0x09, 0x30, // USAGE (X) 58 | 0x09, 0x31, // USAGE (Y) 59 | 0x09, 0x32, // USAGE (Z) 60 | 0x09, 0x33, // USAGE (Rx) 61 | 0x09, 0x34, // USAGE (Ry) 62 | 0x09, 0x35, // USAGE (Rz) 63 | 0x09, 0x36, // USAGE (Slider) 64 | 0x09, 0x36, // USAGE (Slider) 65 | 0x09, 0x36, // USAGE (Slider) 66 | 0x09, 0x36, // USAGE (Slider) 67 | 0x09, 0x36, // USAGE (Slider) 68 | 0x09, 0x36, // USAGE (Slider) 69 | 0x09, 0x36, // USAGE (Slider) 70 | 0x09, 0x36, // USAGE (Slider) 71 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 72 | 0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255) 73 | 0x75, 0x08, // REPORT_SIZE (8) 74 | 0x95, 0x0E, // REPORT_COUNT (14) 75 | 0x81, 0x02, // INPUT (Data,Var,Abs) 76 | 0xc0, // END_COLLECTION (Physical) 77 | 78 | 0x05, 0x09, // USAGE_PAGE (Button) 79 | 0x19, 0x01, // USAGE_MINIMUM (Button 1) 80 | 0x29, 0x10, // USAGE_MAXIMUM (Button 16) 81 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 82 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 83 | 0x75, 0x01, // REPORT_SIZE (1) 84 | 0x95, 0x10, // REPORT_COUNT (8) 85 | 0x81, 0x02, // INPUT (Data,Var,Abs) 86 | 87 | 0xc0 // END_COLLECTION (Application) 88 | }; 89 | 90 | #define USBDESCR_DEVICE 1 91 | 92 | const unsigned char usbDescrDevice[] PROGMEM = { /* USB device descriptor */ 93 | 18, /* sizeof(usbDescrDevice): length of descriptor in bytes */ 94 | USBDESCR_DEVICE, /* descriptor type */ 95 | 0x01, 0x01, /* USB version supported */ 96 | USB_CFG_DEVICE_CLASS, 97 | USB_CFG_DEVICE_SUBCLASS, 98 | 0, /* protocol */ 99 | 8, /* max packet size */ 100 | USB_CFG_VENDOR_ID, /* 2 bytes */ 101 | USB_CFG_DEVICE_ID, /* 2 bytes */ 102 | USB_CFG_DEVICE_VERSION, /* 2 bytes */ 103 | #if USB_CFG_VENDOR_NAME_LEN 104 | 1, /* manufacturer string index */ 105 | #else 106 | 0, /* manufacturer string index */ 107 | #endif 108 | #if USB_CFG_DEVICE_NAME_LEN 109 | 2, /* product string index */ 110 | #else 111 | 0, /* product string index */ 112 | #endif 113 | #if USB_CFG_SERIAL_NUMBER_LENGTH 114 | 3, /* serial number string index */ 115 | #else 116 | 0, /* serial number string index */ 117 | #endif 118 | 1, /* number of configurations */ 119 | }; 120 | 121 | 122 | 123 | 124 | class DigiJoystick_FPV { 125 | public: 126 | DigiJoystick_FPV () { 127 | cli(); 128 | usbDeviceDisconnect(); 129 | _delay_ms(250); 130 | usbDeviceConnect(); 131 | 132 | rt_usbHidReportDescriptor = gcn64_usbHidReportDescriptor; 133 | rt_usbHidReportDescriptorSize = sizeof(gcn64_usbHidReportDescriptor); 134 | rt_usbDeviceDescriptor = usbDescrDevice; 135 | rt_usbDeviceDescriptorSize = sizeof(usbDescrDevice); 136 | 137 | usbInit(); 138 | 139 | sei(); 140 | 141 | last_report_time = millis(); 142 | } 143 | 144 | /* returns true if there is data to be sent */ 145 | bool update() { 146 | usbPoll(); 147 | 148 | // instead of above code, use millis arduino system to enforce minimum reporting frequency 149 | unsigned long current_millis = millis(); 150 | unsigned long time_since_last_report = current_millis - last_report_time; 151 | 152 | if (time_since_last_report >= 100) { 153 | must_report = 1; 154 | } 155 | 156 | // if the report has changed, try force an update anyway 157 | if (memcmp(last_built_report, last_sent_report, HID_REPORT_SIZE)) { 158 | must_report = 1; 159 | } 160 | 161 | // if we want to send a report, signal the host computer to ask us for it with a usb 'interrupt' 162 | if (must_report) { 163 | if (usbInterruptIsReady()) { 164 | must_report = 0; 165 | last_report_time = current_millis; 166 | memcpy(last_sent_report, last_built_report, HID_REPORT_SIZE); 167 | usbSetInterrupt(last_sent_report, HID_REPORT_SIZE); 168 | } 169 | return true; 170 | } 171 | return false; 172 | } 173 | 174 | // delay while updating until we are finished delaying 175 | void delay(long milli) { 176 | unsigned long last = millis(); 177 | while (milli > 0) { 178 | unsigned long now = millis(); 179 | milli -= now - last; 180 | last = now; 181 | update(); 182 | } 183 | } 184 | 185 | void setX(byte value) { 186 | last_built_report[0] = value; 187 | } 188 | 189 | void setY(byte value) { 190 | last_built_report[1] = value; 191 | } 192 | 193 | void setZ(byte value) { 194 | last_built_report[2] = value; 195 | } 196 | 197 | void setXROT(byte value) { 198 | last_built_report[3] = value; 199 | } 200 | 201 | void setYROT(byte value) { 202 | last_built_report[4] = value; 203 | } 204 | 205 | void setZROT(byte value) { 206 | last_built_report[5] = value; 207 | } 208 | 209 | void setX(char value) { 210 | setX(*(reinterpret_cast(&value))); 211 | } 212 | 213 | void setY(char value) { 214 | setY(*(reinterpret_cast(&value))); 215 | } 216 | 217 | void setXROT(char value) { 218 | setXROT(*(reinterpret_cast(&value))); 219 | } 220 | 221 | void setYROT(char value) { 222 | setYROT(*(reinterpret_cast(&value))); 223 | } 224 | 225 | void setZROT(char value) { 226 | setZROT(*(reinterpret_cast(&value))); 227 | } 228 | void setSLIDER(char value) { 229 | setSLIDER(*(reinterpret_cast(&value))); 230 | } 231 | 232 | void setButtons(unsigned char low, unsigned char high) { 233 | last_built_report[6] = low; 234 | last_built_report[7] = high; 235 | } 236 | 237 | void setButtons(char low,char high) { 238 | setButtons(*reinterpret_cast(&low),*reinterpret_cast(&high)); 239 | } 240 | 241 | void setValues(unsigned char values[]) { 242 | memcpy(last_built_report, values, HID_REPORT_SIZE); 243 | } 244 | 245 | void setValues(char values[]) { 246 | unsigned char *foo = reinterpret_cast(values);//preserves bit values in cast 247 | memcpy(last_built_report, foo, HID_REPORT_SIZE); 248 | } 249 | }; 250 | 251 | // Create global singleton object for users to make use of 252 | DigiJoystick_FPV DigiJoystick = DigiJoystick_FPV(); 253 | 254 | 255 | 256 | 257 | 258 | #ifdef __cplusplus 259 | extern "C"{ 260 | #endif 261 | // USB_PUBLIC uchar usbFunctionSetup 262 | 263 | uchar usbFunctionSetup(uchar data[8]) { 264 | usbRequest_t *rq = (usbRequest_t *)data; 265 | 266 | if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { // class request type 267 | if (rq->bRequest == USBRQ_HID_GET_REPORT){ // wValue: ReportType (highbyte), ReportID (lowbyte) 268 | // we only have one report type, so don't look at wValue 269 | //curGamepad->buildReport(reportBuffer); 270 | //return curGamepad->report_size; 271 | usbMsgPtr = (usbMsgPtr_t)last_sent_report; 272 | return HID_REPORT_SIZE; 273 | } else if (rq->bRequest == USBRQ_HID_GET_IDLE) { 274 | usbMsgPtr = (usbMsgPtr_t)&idle_rate; 275 | return 1; 276 | } else if (rq->bRequest == USBRQ_HID_SET_IDLE) { 277 | idle_rate = rq->wValue.bytes[1]; 278 | } 279 | } else { 280 | /* no vendor specific requests implemented */ 281 | } 282 | return 0; 283 | } 284 | 285 | uchar usbFunctionDescriptor(struct usbRequest *rq) { 286 | if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD) { 287 | return 0; 288 | } 289 | 290 | if (rq->bRequest == USBRQ_GET_DESCRIPTOR) { 291 | // USB spec 9.4.3, high byte is descriptor type 292 | switch (rq->wValue.bytes[1]) { 293 | case USBDESCR_DEVICE: 294 | usbMsgPtr = (usbMsgPtr_t)rt_usbDeviceDescriptor; 295 | return rt_usbDeviceDescriptorSize; 296 | 297 | case USBDESCR_HID_REPORT: 298 | usbMsgPtr = (usbMsgPtr_t)rt_usbHidReportDescriptor; 299 | return rt_usbHidReportDescriptorSize; 300 | 301 | } 302 | } 303 | 304 | return 0; 305 | } 306 | 307 | #ifdef __cplusplus 308 | } // extern "C" 309 | #endif 310 | 311 | 312 | #endif // __DigiKeyboard_h__ 313 | -------------------------------------------------------------------------------- /examples/CRSF_Joystick/CRSF_Joystick.ino: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Compile with Digispark 16.5 MHz 4 | */ 5 | #include 6 | #include "DigiJoystick_FPV.h" 7 | 8 | #define RC_RECEIVER_PORT PB0 9 | #define CRSF_HIGH (PINB & (1 << RC_RECEIVER_PORT)) 10 | #define CHANNELS 12 11 | #define CLOCK_BITS (1 << CS10) 12 | 13 | /* just for reference, peripheral usage was actually troublesome */ 14 | #define BAUD_RATE 420000 15 | 16 | /* 17 | from https://github.com/betaflight/betaflight/pull/1662/files 18 | 0x14 Link statistics 19 | Uplink is the connection from the ground to the UAV and downlink the opposite direction. 20 | Payload: 21 | uint8_t UplinkRSSI Ant.1(dBm*­1) 22 | uint8_t UplinkRSSI Ant.2(dBm*­1) 23 | uint8_t Uplink Package success rate / Link quality ( % ) 24 | int8_t Uplink SNR ( db ) 25 | uint8_t Diversity active antenna ( enum ant. 1 = 0, ant. 2 ) 26 | uint8_t RF Mode ( enum 4fps = 0 , 50fps, 150hz) 27 | uint8_t Uplink TX Power ( enum 0mW = 0, 10mW, 25 mW, 100 mW, 500 mW, 1000 mW, 2000mW ) 28 | uint8_t Downlink RSSI ( dBm * ­-1 ) 29 | uint8_t Downlink package success rate / Link quality ( % ) 30 | int8_t Downlink SNR ( db ) 31 | */ 32 | #define RX_BUFFER_SIZE (28) 33 | volatile uint8_t *receiveBuffer = NULL; 34 | volatile uint8_t receiveLength = 0; 35 | volatile uint8_t validRcData = 0; 36 | volatile uint8_t receivedRcData[RX_BUFFER_SIZE]; 37 | volatile uint8_t receivedLinkData[RX_BUFFER_SIZE]; 38 | volatile uint8_t report[16]; 39 | volatile uint16_t channelValues[CHANNELS]; 40 | volatile uint16_t framesReceived = 0; 41 | volatile uint16_t lastFrameNumber = 0; 42 | 43 | /* USB code will update this counter. used to check if an USB interrupt happened. 44 | * If so, we will withdraw our sampling result 45 | */ 46 | extern uint8_t usbActivityCount; 47 | 48 | 49 | void setup() 50 | { 51 | pinMode(PB0, INPUT_PULLUP); 52 | pinMode(PB1, OUTPUT); 53 | pinMode(PB2, INPUT); 54 | 55 | for(int pos = 0; pos < CHANNELS; pos++) 56 | { 57 | channelValues[pos] = 0; 58 | } 59 | 60 | /* enable USB interrupt */ 61 | GIMSK |= 1<= receiveLength) 197 | { 198 | if(receiveLength == 0x18) 199 | { 200 | validRcData = 1; 201 | PCMSK &= ~(1 << PCINT0); 202 | framesReceived++; 203 | } 204 | state = STATE_WAIT_SYNC; 205 | } 206 | break; 207 | } 208 | 209 | /* if we are done receiving, enable USB interrupt again */ 210 | if(state == STATE_WAIT_SYNC) 211 | { 212 | GIMSK |= (1<> 3; 223 | } 224 | 225 | uint8_t crc8 (uint8_t *addr, uint8_t len) 226 | { 227 | uint8_t crc=0; 228 | for (uint8_t i=0; i 1000) 258 | { 259 | /* normal state, handle CRSF interrupts */ 260 | PCMSK |= (1 << PCINT0); 261 | state = 1; 262 | } 263 | return; 264 | 265 | case 1: 266 | /* make sure at least every 50ms a transfer happens */ 267 | if(currentTime - lastTransfer > 10) 268 | { 269 | /* disable CRSF for now and resend last report */ 270 | usbSetInterrupt(&report[0], 8); 271 | state = 4; 272 | } 273 | else if(validRcData) 274 | { 275 | validRcData = 0; 276 | 277 | /* only handle packets with correct checksum */ 278 | if(crc8((uint8_t*)receivedRcData, 0x18) == 0) 279 | { 280 | /* CRC correct, do another loop and then parse content */ 281 | state = 2; 282 | } 283 | } 284 | break; 285 | 286 | case 2: 287 | { 288 | uint8_t chanBits = 0; 289 | uint8_t channel = 0; 290 | uint32_t value = 0; 291 | 292 | /* go through all payload bytes */ 293 | for(int pos = 0; pos < 22; pos++) 294 | { 295 | /* fetch 8 bits */ 296 | value |= ((uint32_t)receivedRcData[1 + pos]) << chanBits; 297 | chanBits += 8; 298 | 299 | /* when we got enough (11) bits, treat this as a sample */ 300 | if(chanBits >= 11) 301 | { 302 | channelValues[channel++] = (value & 0x7FF); 303 | /* keep remaining bits */ 304 | value >>= 11; 305 | chanBits -= 11; 306 | } 307 | } 308 | 309 | /* content parsed, another loop and then build packet */ 310 | state = 3; 311 | break; 312 | } 313 | 314 | case 3: 315 | { 316 | /* determine (3-state) buttons from channels 4 to 10 */ 317 | uint16_t buttons = 0; 318 | for(int pos = 0; pos < 6; pos++) 319 | { 320 | uint8_t value = getConverted(4+pos); 321 | uint16_t bitVal1 = 1<<(2*pos); 322 | uint16_t bitVal2 = 1<<(2*pos+1); 323 | 324 | if(value >= 0xC0) 325 | { 326 | buttons |= bitVal2; 327 | } 328 | else if(value >= 0x40) 329 | { 330 | buttons |= bitVal1; 331 | } 332 | } 333 | 334 | report[0] = getConverted(0); 335 | report[1] = getConverted(1); 336 | report[2] = getConverted(2); 337 | report[3] = getConverted(3); 338 | report[4] = getConverted(4); 339 | report[5] = getConverted(5); 340 | report[6] = getConverted(6); 341 | report[7] = getConverted(7); 342 | report[8] = getConverted(8); 343 | report[9] = getConverted(9); 344 | report[10] = getConverted(10); 345 | report[11] = getConverted(11); 346 | report[12] = (byte)receivedLinkData[6] << 3; 347 | report[13] = (byte)receivedLinkData[7]; 348 | report[14] = (byte)(buttons); 349 | report[15] = (byte)(buttons >> 8); 350 | 351 | /* we built the frame to send, set INT data */ 352 | usbSetInterrupt(&report[0], 8); 353 | state = 4; 354 | break; 355 | } 356 | 357 | case 4: 358 | /* queue second part of our HID data in the next interrupt */ 359 | if(usbInterruptIsReady()) 360 | { 361 | usbSetInterrupt(&report[8], 8); 362 | state = 5; 363 | } 364 | break; 365 | 366 | case 5: 367 | /* when interrupt buffer is empty, make sure we receive CRSF frames again */ 368 | if(usbInterruptIsReady()) 369 | { 370 | lastTransfer = currentTime; 371 | PCMSK |= (1 << PCINT0); 372 | state = 1; 373 | } 374 | break; 375 | } 376 | } 377 | 378 | -------------------------------------------------------------------------------- /usbdrvasm.S: -------------------------------------------------------------------------------- 1 | /* Name: usbdrvasm.S 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2007-06-13 5 | * Tabsize: 4 6 | * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | * Revision: $Id: usbdrvasm.S 761 2009-08-12 16:30:23Z cs $ 9 | */ 10 | 11 | /* 12 | General Description: 13 | This module is the assembler part of the USB driver. This file contains 14 | general code (preprocessor acrobatics and CRC computation) and then includes 15 | the file appropriate for the given clock rate. 16 | */ 17 | 18 | #define __SFR_OFFSET 0 /* used by avr-libc's register definitions */ 19 | #include "usbportability.h" 20 | #include "usbdrv.h" /* for common defs */ 21 | 22 | /* register names */ 23 | #define x1 r16 24 | #define x2 r17 25 | #define shift r18 26 | #define cnt r19 27 | #define x3 r20 28 | #define x4 r21 29 | #define x5 r22 30 | #define bitcnt x5 31 | #define phase x4 32 | #define leap x4 33 | 34 | /* Some assembler dependent definitions and declarations: */ 35 | 36 | #ifdef __IAR_SYSTEMS_ASM__ 37 | extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset 38 | extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen 39 | extern usbTxBuf, usbTxStatus1, usbTxStatus3 40 | # if USB_COUNT_SOF 41 | extern usbSofCount 42 | # endif 43 | public usbCrc16 44 | public usbCrc16Append 45 | 46 | COMMON INTVEC 47 | # ifndef USB_INTR_VECTOR 48 | ORG INT0_vect 49 | # else /* USB_INTR_VECTOR */ 50 | ORG USB_INTR_VECTOR 51 | # undef USB_INTR_VECTOR 52 | # endif /* USB_INTR_VECTOR */ 53 | # define USB_INTR_VECTOR usbInterruptHandler 54 | rjmp USB_INTR_VECTOR 55 | RSEG CODE 56 | 57 | #else /* __IAR_SYSTEMS_ASM__ */ 58 | 59 | # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */ 60 | # define USB_INTR_VECTOR SIG_INTERRUPT0 61 | # endif 62 | .text 63 | .global USB_INTR_VECTOR 64 | .type USB_INTR_VECTOR, @function 65 | .global usbCrc16 66 | .global usbCrc16Append 67 | #endif /* __IAR_SYSTEMS_ASM__ */ 68 | 69 | 70 | #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */ 71 | # define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING 72 | # define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg 73 | #else /* It's a memory address, use lds and sts */ 74 | # define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING 75 | # define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg 76 | #endif 77 | 78 | #define usbTxLen1 usbTxStatus1 79 | #define usbTxBuf1 (usbTxStatus1 + 1) 80 | #define usbTxLen3 usbTxStatus3 81 | #define usbTxBuf3 (usbTxStatus3 + 1) 82 | 83 | 84 | ;---------------------------------------------------------------------------- 85 | ; Utility functions 86 | ;---------------------------------------------------------------------------- 87 | 88 | #ifdef __IAR_SYSTEMS_ASM__ 89 | /* Register assignments for usbCrc16 on IAR cc */ 90 | /* Calling conventions on IAR: 91 | * First parameter passed in r16/r17, second in r18/r19 and so on. 92 | * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer) 93 | * Result is passed in r16/r17 94 | * In case of the "tiny" memory model, pointers are only 8 bit with no 95 | * padding. We therefore pass argument 1 as "16 bit unsigned". 96 | */ 97 | RTMODEL "__rt_version", "3" 98 | /* The line above will generate an error if cc calling conventions change. 99 | * The value "3" above is valid for IAR 4.10B/W32 100 | */ 101 | # define argLen r18 /* argument 2 */ 102 | # define argPtrL r16 /* argument 1 */ 103 | # define argPtrH r17 /* argument 1 */ 104 | 105 | # define resCrcL r16 /* result */ 106 | # define resCrcH r17 /* result */ 107 | 108 | # define ptrL ZL 109 | # define ptrH ZH 110 | # define ptr Z 111 | # define byte r22 112 | # define bitCnt r19 113 | # define polyL r20 114 | # define polyH r21 115 | # define scratch r23 116 | 117 | #else /* __IAR_SYSTEMS_ASM__ */ 118 | /* Register assignments for usbCrc16 on gcc */ 119 | /* Calling conventions on gcc: 120 | * First parameter passed in r24/r25, second in r22/23 and so on. 121 | * Callee must preserve r1-r17, r28/r29 122 | * Result is passed in r24/r25 123 | */ 124 | # define argLen r22 /* argument 2 */ 125 | # define argPtrL r24 /* argument 1 */ 126 | # define argPtrH r25 /* argument 1 */ 127 | 128 | # define resCrcL r24 /* result */ 129 | # define resCrcH r25 /* result */ 130 | 131 | # define ptrL XL 132 | # define ptrH XH 133 | # define ptr x 134 | # define byte r18 135 | # define bitCnt r19 136 | # define polyL r20 137 | # define polyH r21 138 | # define scratch r23 139 | 140 | #endif 141 | 142 | #if USB_USE_FAST_CRC 143 | 144 | ; This implementation is faster, but has bigger code size 145 | ; Thanks to Slawomir Fras (BoskiDialer) for this code and to Shay Green for 146 | ; even further optimizations! 147 | ; It implements the following C pseudo-code: 148 | ; unsigned table(unsigned char x) 149 | ; { 150 | ; unsigned value; 151 | ; 152 | ; value = (unsigned)x << 6; 153 | ; value ^= (unsigned)x << 7; 154 | ; if(parity(x)) 155 | ; value ^= 0xc001; 156 | ; return value; 157 | ; } 158 | ; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen) 159 | ; { 160 | ; unsigned crc = 0xffff; 161 | ; 162 | ; while(argLen--) 163 | ; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc); 164 | ; return ~crc; 165 | ; } 166 | 167 | ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen); 168 | ; argPtr r24+25 / r16+r17 169 | ; argLen r22 / r18 170 | ; temp variables: 171 | ; byte r18 / r22 172 | ; scratch r23 173 | ; resCrc r24+r25 / r16+r17 174 | ; ptr X / Z 175 | usbCrc16: 176 | movw ptrL, argPtrL 177 | ldi resCrcL, 0xFF 178 | ldi resCrcH, 0xFF 179 | clr bitCnt ; zero reg 180 | rjmp usbCrc16LoopTest 181 | usbCrc16ByteLoop: 182 | ld byte, ptr+ 183 | eor byte, resCrcL ; scratch is now 'x' in table() 184 | mov scratch, byte ; compute parity of 'x' 185 | swap byte 186 | eor byte, scratch 187 | mov resCrcL, byte 188 | lsr byte 189 | lsr byte 190 | eor byte, resCrcL 191 | inc byte 192 | andi byte, 2 ; byte is now parity(x) << 1 193 | cp bitCnt, byte ; c = (byte != 0), then put in high bit 194 | ror scratch ; so that after xoring, shifting, and xoring, it gives 195 | ror byte ; the desired 0xC0 with resCrcH 196 | mov resCrcL, byte 197 | eor resCrcL, resCrcH 198 | mov resCrcH, scratch 199 | lsr scratch 200 | ror byte 201 | eor resCrcH, scratch 202 | eor resCrcL, byte 203 | usbCrc16LoopTest: 204 | subi argLen, 1 205 | brsh usbCrc16ByteLoop 206 | com resCrcL 207 | com resCrcH 208 | ret 209 | 210 | #else /* USB_USE_FAST_CRC */ 211 | 212 | ; This implementation is slower, but has less code size 213 | ; 214 | ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen); 215 | ; argPtr r24+25 / r16+r17 216 | ; argLen r22 / r18 217 | ; temp variables: 218 | ; byte r18 / r22 219 | ; bitCnt r19 220 | ; poly r20+r21 221 | ; scratch r23 222 | ; resCrc r24+r25 / r16+r17 223 | ; ptr X / Z 224 | usbCrc16: 225 | mov ptrL, argPtrL 226 | mov ptrH, argPtrH 227 | ldi resCrcL, 0 228 | ldi resCrcH, 0 229 | ldi polyL, lo8(0xa001) 230 | ldi polyH, hi8(0xa001) 231 | com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set 232 | ldi bitCnt, 0 ; loop counter with starnd condition = end condition 233 | rjmp usbCrcLoopEntry 234 | usbCrcByteLoop: 235 | ld byte, ptr+ 236 | eor resCrcL, byte 237 | usbCrcBitLoop: 238 | ror resCrcH ; carry is always set here (see brcs jumps to here) 239 | ror resCrcL 240 | brcs usbCrcNoXor 241 | eor resCrcL, polyL 242 | eor resCrcH, polyH 243 | usbCrcNoXor: 244 | subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times 245 | brcs usbCrcBitLoop 246 | usbCrcLoopEntry: 247 | subi argLen, -1 248 | brcs usbCrcByteLoop 249 | usbCrcReady: 250 | ret 251 | ; Thanks to Reimar Doeffinger for optimizing this CRC routine! 252 | 253 | #endif /* USB_USE_FAST_CRC */ 254 | 255 | ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len); 256 | usbCrc16Append: 257 | rcall usbCrc16 258 | st ptr+, resCrcL 259 | st ptr+, resCrcH 260 | ret 261 | 262 | #undef argLen 263 | #undef argPtrL 264 | #undef argPtrH 265 | #undef resCrcL 266 | #undef resCrcH 267 | #undef ptrL 268 | #undef ptrH 269 | #undef ptr 270 | #undef byte 271 | #undef bitCnt 272 | #undef polyL 273 | #undef polyH 274 | #undef scratch 275 | 276 | 277 | #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH 278 | #ifdef __IAR_SYSTEMS_ASM__ 279 | /* Register assignments for usbMeasureFrameLength on IAR cc */ 280 | /* Calling conventions on IAR: 281 | * First parameter passed in r16/r17, second in r18/r19 and so on. 282 | * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer) 283 | * Result is passed in r16/r17 284 | * In case of the "tiny" memory model, pointers are only 8 bit with no 285 | * padding. We therefore pass argument 1 as "16 bit unsigned". 286 | */ 287 | # define resL r16 288 | # define resH r17 289 | # define cnt16L r30 290 | # define cnt16H r31 291 | # define cntH r18 292 | 293 | #else /* __IAR_SYSTEMS_ASM__ */ 294 | /* Register assignments for usbMeasureFrameLength on gcc */ 295 | /* Calling conventions on gcc: 296 | * First parameter passed in r24/r25, second in r22/23 and so on. 297 | * Callee must preserve r1-r17, r28/r29 298 | * Result is passed in r24/r25 299 | */ 300 | # define resL r24 301 | # define resH r25 302 | # define cnt16L r24 303 | # define cnt16H r25 304 | # define cntH r26 305 | #endif 306 | # define cnt16 cnt16L 307 | 308 | ; extern unsigned usbMeasurePacketLength(void); 309 | ; returns time between two idle strobes in multiples of 7 CPU clocks 310 | .global usbMeasureFrameLength 311 | usbMeasureFrameLength: 312 | ldi cntH, 6 ; wait ~ 10 ms for D- == 0 313 | clr cnt16L 314 | clr cnt16H 315 | usbMFTime16: 316 | dec cntH 317 | breq usbMFTimeout 318 | usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe) 319 | sbiw cnt16, 1 ;[0] [6] 320 | breq usbMFTime16 ;[2] 321 | sbic USBIN, USBMINUS ;[3] 322 | rjmp usbMFWaitStrobe ;[4] 323 | usbMFWaitIdle: ; then wait until idle again 324 | sbis USBIN, USBMINUS ;1 wait for D- == 1 325 | rjmp usbMFWaitIdle ;2 326 | ldi cnt16L, 1 ;1 represents cycles so far 327 | clr cnt16H ;1 328 | usbMFWaitLoop: 329 | in cntH, USBIN ;[0] [7] 330 | adiw cnt16, 1 ;[1] 331 | breq usbMFTimeout ;[3] 332 | andi cntH, USBMASK ;[4] 333 | brne usbMFWaitLoop ;[5] 334 | usbMFTimeout: 335 | #if resL != cnt16L 336 | mov resL, cnt16L 337 | mov resH, cnt16H 338 | #endif 339 | ret 340 | 341 | #undef resL 342 | #undef resH 343 | #undef cnt16 344 | #undef cnt16L 345 | #undef cnt16H 346 | #undef cntH 347 | 348 | #endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */ 349 | 350 | ;---------------------------------------------------------------------------- 351 | ; Now include the clock rate specific code 352 | ;---------------------------------------------------------------------------- 353 | 354 | #ifndef USB_CFG_CLOCK_KHZ 355 | # ifdef F_CPU 356 | # define USB_CFG_CLOCK_KHZ (F_CPU/1000) 357 | # else 358 | # error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!" 359 | # endif 360 | #endif 361 | 362 | #if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */ 363 | # if USB_CFG_CLOCK_KHZ == 18000 364 | # include "usbdrvasm18-crc.inc" 365 | # else 366 | # error "USB_CFG_CLOCK_KHZ is not one of the supported rates for USB_CFG_CHECK_CRC!" 367 | # endif 368 | #else /* USB_CFG_CHECK_CRC */ 369 | # if USB_CFG_CLOCK_KHZ == 12000 370 | # include "usbdrvasm12.inc" 371 | # elif USB_CFG_CLOCK_KHZ == 12800 372 | # include "usbdrvasm128.inc" 373 | # elif USB_CFG_CLOCK_KHZ == 15000 374 | # include "usbdrvasm15.inc" 375 | # elif USB_CFG_CLOCK_KHZ == 16000 376 | # include "usbdrvasm16.inc" 377 | # elif USB_CFG_CLOCK_KHZ == 16500 378 | # include "usbdrvasm165.inc" 379 | # elif USB_CFG_CLOCK_KHZ == 20000 380 | # include "usbdrvasm20.inc" 381 | # else 382 | # error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!" 383 | # endif 384 | #endif /* USB_CFG_CHECK_CRC */ 385 | -------------------------------------------------------------------------------- /usbdrvasm16.inc: -------------------------------------------------------------------------------- 1 | /* Name: usbdrvasm16.inc 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2007-06-15 5 | * Tabsize: 4 6 | * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | * Revision: $Id: usbdrvasm16.inc 760 2009-08-09 18:59:43Z cs $ 9 | */ 10 | 11 | /* Do not link this file! Link usbdrvasm.S instead, which includes the 12 | * appropriate implementation! 13 | */ 14 | 15 | /* 16 | General Description: 17 | This file is the 16 MHz version of the asssembler part of the USB driver. It 18 | requires a 16 MHz crystal (not a ceramic resonator and not a calibrated RC 19 | oscillator). 20 | 21 | See usbdrv.h for a description of the entire driver. 22 | 23 | Since almost all of this code is timing critical, don't change unless you 24 | really know what you are doing! Many parts require not only a maximum number 25 | of CPU cycles, but even an exact number of cycles! 26 | */ 27 | 28 | ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes 29 | ;nominal frequency: 16 MHz -> 10.6666666 cycles per bit, 85.333333333 cycles per byte 30 | ; Numbers in brackets are clocks counted from center of last sync bit 31 | ; when instruction starts 32 | 33 | USB_INTR_VECTOR: 34 | ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt 35 | push YL ;[-25] push only what is necessary to sync with edge ASAP 36 | in YL, SREG ;[-23] 37 | push YL ;[-22] 38 | push YH ;[-20] 39 | ;---------------------------------------------------------------------------- 40 | ; Synchronize with sync pattern: 41 | ;---------------------------------------------------------------------------- 42 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 43 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 44 | ;The first part waits at most 1 bit long since we must be in sync pattern. 45 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 46 | ;waitForJ, ensure that this prerequisite is met. 47 | waitForJ: 48 | inc YL 49 | sbis USBIN, USBMINUS 50 | brne waitForJ ; just make sure we have ANY timeout 51 | waitForK: 52 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 53 | sbis USBIN, USBMINUS ;[-15] 54 | rjmp foundK ;[-14] 55 | sbis USBIN, USBMINUS 56 | rjmp foundK 57 | sbis USBIN, USBMINUS 58 | rjmp foundK 59 | sbis USBIN, USBMINUS 60 | rjmp foundK 61 | sbis USBIN, USBMINUS 62 | rjmp foundK 63 | sbis USBIN, USBMINUS 64 | rjmp foundK 65 | #if USB_COUNT_SOF 66 | lds YL, usbSofCount 67 | inc YL 68 | sts usbSofCount, YL 69 | #endif /* USB_COUNT_SOF */ 70 | #ifdef USB_SOF_HOOK 71 | USB_SOF_HOOK 72 | #endif 73 | rjmp sofError 74 | foundK: ;[-12] 75 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] 76 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 77 | ;are cycles from center of first sync (double K) bit after the instruction 78 | push bitcnt ;[-12] 79 | ; [---] ;[-11] 80 | lds YL, usbInputBufOffset;[-10] 81 | ; [---] ;[-9] 82 | clr YH ;[-8] 83 | subi YL, lo8(-(usbRxBuf));[-7] [rx loop init] 84 | sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init] 85 | push shift ;[-5] 86 | ; [---] ;[-4] 87 | ldi bitcnt, 0x55 ;[-3] [rx loop init] 88 | sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) 89 | rjmp haveTwoBitsK ;[-1] 90 | pop shift ;[0] undo the push from before 91 | pop bitcnt ;[2] undo the push from before 92 | rjmp waitForK ;[4] this was not the end of sync, retry 93 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 94 | ; bit times (= 21 cycles). 95 | 96 | ;---------------------------------------------------------------------------- 97 | ; push more registers and initialize values while we sample the first bits: 98 | ;---------------------------------------------------------------------------- 99 | haveTwoBitsK: 100 | push x1 ;[1] 101 | push x2 ;[3] 102 | push x3 ;[5] 103 | ldi shift, 0 ;[7] 104 | ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that 105 | push x4 ;[9] == leap 106 | 107 | in x1, USBIN ;[11] <-- sample bit 0 108 | andi x1, USBMASK ;[12] 109 | bst x1, USBMINUS ;[13] 110 | bld shift, 7 ;[14] 111 | push cnt ;[15] 112 | ldi leap, 0 ;[17] [rx loop init] 113 | ldi cnt, USB_BUFSIZE;[18] [rx loop init] 114 | rjmp rxbit1 ;[19] arrives at [21] 115 | 116 | ;---------------------------------------------------------------------------- 117 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 118 | ;---------------------------------------------------------------------------- 119 | 120 | ; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap" 121 | ; accordingly to approximate this value in the long run. 122 | 123 | unstuff6: 124 | andi x2, USBMASK ;[03] 125 | ori x3, 1<<6 ;[04] will not be shifted any more 126 | andi shift, ~0x80;[05] 127 | mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6 128 | subi leap, -1 ;[07] total duration = 11 bits -> subtract 1/3 129 | rjmp didUnstuff6 ;[08] 130 | 131 | unstuff7: 132 | ori x3, 1<<7 ;[09] will not be shifted any more 133 | in x2, USBIN ;[00] [10] re-sample bit 7 134 | andi x2, USBMASK ;[01] 135 | andi shift, ~0x80;[02] 136 | subi leap, 2 ;[03] total duration = 10 bits -> add 1/3 137 | rjmp didUnstuff7 ;[04] 138 | 139 | unstuffEven: 140 | ori x3, 1<<6 ;[09] will be shifted right 6 times for bit 0 141 | in x1, USBIN ;[00] [10] 142 | andi shift, ~0x80;[01] 143 | andi x1, USBMASK ;[02] 144 | breq se0 ;[03] 145 | subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3 146 | nop2 ;[05] 147 | rjmp didUnstuffE ;[06] 148 | 149 | unstuffOdd: 150 | ori x3, 1<<5 ;[09] will be shifted right 4 times for bit 1 151 | in x2, USBIN ;[00] [10] 152 | andi shift, ~0x80;[01] 153 | andi x2, USBMASK ;[02] 154 | breq se0 ;[03] 155 | subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3 156 | nop2 ;[05] 157 | rjmp didUnstuffO ;[06] 158 | 159 | rxByteLoop: 160 | andi x1, USBMASK ;[03] 161 | eor x2, x1 ;[04] 162 | subi leap, 1 ;[05] 163 | brpl skipLeap ;[06] 164 | subi leap, -3 ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte 165 | nop ;1 166 | skipLeap: 167 | subi x2, 1 ;[08] 168 | ror shift ;[09] 169 | didUnstuff6: 170 | cpi shift, 0xfc ;[10] 171 | in x2, USBIN ;[00] [11] <-- sample bit 7 172 | brcc unstuff6 ;[01] 173 | andi x2, USBMASK ;[02] 174 | eor x1, x2 ;[03] 175 | subi x1, 1 ;[04] 176 | ror shift ;[05] 177 | didUnstuff7: 178 | cpi shift, 0xfc ;[06] 179 | brcc unstuff7 ;[07] 180 | eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others 181 | st y+, x3 ;[09] store data 182 | rxBitLoop: 183 | in x1, USBIN ;[00] [11] <-- sample bit 0/2/4 184 | andi x1, USBMASK ;[01] 185 | eor x2, x1 ;[02] 186 | andi x3, 0x3f ;[03] topmost two bits reserved for 6 and 7 187 | subi x2, 1 ;[04] 188 | ror shift ;[05] 189 | cpi shift, 0xfc ;[06] 190 | brcc unstuffEven ;[07] 191 | didUnstuffE: 192 | lsr x3 ;[08] 193 | lsr x3 ;[09] 194 | rxbit1: 195 | in x2, USBIN ;[00] [10] <-- sample bit 1/3/5 196 | andi x2, USBMASK ;[01] 197 | breq se0 ;[02] 198 | eor x1, x2 ;[03] 199 | subi x1, 1 ;[04] 200 | ror shift ;[05] 201 | cpi shift, 0xfc ;[06] 202 | brcc unstuffOdd ;[07] 203 | didUnstuffO: 204 | subi bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3 205 | brcs rxBitLoop ;[09] 206 | 207 | subi cnt, 1 ;[10] 208 | in x1, USBIN ;[00] [11] <-- sample bit 6 209 | brcc rxByteLoop ;[01] 210 | rjmp overflow 211 | 212 | macro POP_STANDARD ; 14 cycles 213 | pop cnt 214 | pop x4 215 | pop x3 216 | pop x2 217 | pop x1 218 | pop shift 219 | pop bitcnt 220 | endm 221 | macro POP_RETI ; 7 cycles 222 | pop YH 223 | pop YL 224 | out SREG, YL 225 | pop YL 226 | endm 227 | 228 | #include "asmcommon.inc" 229 | 230 | ; USB spec says: 231 | ; idle = J 232 | ; J = (D+ = 0), (D- = 1) 233 | ; K = (D+ = 1), (D- = 0) 234 | ; Spec allows 7.5 bit times from EOP to SOP for replies 235 | 236 | bitstuffN: 237 | eor x1, x4 ;[5] 238 | ldi x2, 0 ;[6] 239 | nop2 ;[7] 240 | nop ;[9] 241 | out USBOUT, x1 ;[10] <-- out 242 | rjmp didStuffN ;[0] 243 | 244 | bitstuff6: 245 | eor x1, x4 ;[5] 246 | ldi x2, 0 ;[6] Carry is zero due to brcc 247 | rol shift ;[7] compensate for ror shift at branch destination 248 | rjmp didStuff6 ;[8] 249 | 250 | bitstuff7: 251 | ldi x2, 0 ;[2] Carry is zero due to brcc 252 | rjmp didStuff7 ;[3] 253 | 254 | 255 | sendNakAndReti: 256 | ldi x3, USBPID_NAK ;[-18] 257 | rjmp sendX3AndReti ;[-17] 258 | sendAckAndReti: 259 | ldi cnt, USBPID_ACK ;[-17] 260 | sendCntAndReti: 261 | mov x3, cnt ;[-16] 262 | sendX3AndReti: 263 | ldi YL, 20 ;[-15] x3==r20 address is 20 264 | ldi YH, 0 ;[-14] 265 | ldi cnt, 2 ;[-13] 266 | ; rjmp usbSendAndReti fallthrough 267 | 268 | ;usbSend: 269 | ;pointer to data in 'Y' 270 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 271 | ;uses: x1...x4, btcnt, shift, cnt, Y 272 | ;Numbers in brackets are time since first bit of sync pattern is sent 273 | ;We don't match the transfer rate exactly (don't insert leap cycles every third 274 | ;byte) because the spec demands only 1.5% precision anyway. 275 | usbSendAndReti: ; 12 cycles until SOP 276 | in x2, USBDDR ;[-12] 277 | ori x2, USBMASK ;[-11] 278 | sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 279 | in x1, USBOUT ;[-8] port mirror for tx loop 280 | out USBDDR, x2 ;[-7] <- acquire bus 281 | ; need not init x2 (bitstuff history) because sync starts with 0 282 | ldi x4, USBMASK ;[-6] exor mask 283 | ldi shift, 0x80 ;[-5] sync byte is first byte sent 284 | txByteLoop: 285 | ldi bitcnt, 0x35 ;[-4] [6] binary 0011 0101 286 | txBitLoop: 287 | sbrs shift, 0 ;[-3] [7] 288 | eor x1, x4 ;[-2] [8] 289 | out USBOUT, x1 ;[-1] [9] <-- out N 290 | ror shift ;[0] [10] 291 | ror x2 ;[1] 292 | didStuffN: 293 | cpi x2, 0xfc ;[2] 294 | brcc bitstuffN ;[3] 295 | lsr bitcnt ;[4] 296 | brcc txBitLoop ;[5] 297 | brne txBitLoop ;[6] 298 | 299 | sbrs shift, 0 ;[7] 300 | eor x1, x4 ;[8] 301 | didStuff6: 302 | out USBOUT, x1 ;[-1] [9] <-- out 6 303 | ror shift ;[0] [10] 304 | ror x2 ;[1] 305 | cpi x2, 0xfc ;[2] 306 | brcc bitstuff6 ;[3] 307 | ror shift ;[4] 308 | didStuff7: 309 | ror x2 ;[5] 310 | sbrs x2, 7 ;[6] 311 | eor x1, x4 ;[7] 312 | nop ;[8] 313 | cpi x2, 0xfc ;[9] 314 | out USBOUT, x1 ;[-1][10] <-- out 7 315 | brcc bitstuff7 ;[0] [11] 316 | ld shift, y+ ;[1] 317 | dec cnt ;[3] 318 | brne txByteLoop ;[4] 319 | ;make SE0: 320 | cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles] 321 | lds x2, usbNewDeviceAddr;[6] 322 | lsl x2 ;[8] we compare with left shifted address 323 | subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3 324 | sbci YH, 0 ;[10] 325 | out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle 326 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 327 | ;set address only after data packet was sent, not after handshake 328 | breq skipAddrAssign ;[0] 329 | sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer 330 | skipAddrAssign: 331 | ;end of usbDeviceAddress transfer 332 | ldi x2, 1< when compiling with IAR. 107 | - Introduced USB_CFG_DESCR_PROPS_* in usbconfig.h to configure how each 108 | USB descriptor should be handled. It is now possible to provide descriptor 109 | data in Flash, RAM or dynamically at runtime. 110 | - STALL is now a status in usbTxLen* instead of a message. We can now conform 111 | to the spec and leave the stall status pending until it is cleared. 112 | - Made usbTxPacketCnt1 and usbTxPacketCnt3 public. This allows the 113 | application code to reset data toggling on interrupt pipes. 114 | 115 | * Release 2006-07-18 116 | 117 | - Added an #if !defined __ASSEMBLER__ to the warning in usbdrv.h. This fixes 118 | an assembler error. 119 | - usbDeviceDisconnect() takes pull-up resistor to high impedance now. 120 | 121 | * Release 2007-02-01 122 | 123 | - Merged in some code size improvements from usbtiny (thanks to Dick 124 | Streefland for these optimizations!) 125 | - Special alignment requirement for usbRxBuf not required any more. Thanks 126 | again to Dick Streefland for this hint! 127 | - Reverted to "#warning" instead of unused static variables -- new versions 128 | of IAR CC should handle this directive. 129 | - Changed Open Source license to GNU GPL v2 in order to make linking against 130 | other free libraries easier. We no longer require publication of the 131 | circuit diagrams, but we STRONGLY encourage it. If you improve the driver 132 | itself, PLEASE grant us a royalty free license to your changes for our 133 | commercial license. 134 | 135 | * Release 2007-03-29 136 | 137 | - New configuration option "USB_PUBLIC" in usbconfig.h. 138 | - Set USB version number to 1.10 instead of 1.01. 139 | - Code used USB_CFG_DESCR_PROPS_STRING_DEVICE and 140 | USB_CFG_DESCR_PROPS_STRING_PRODUCT inconsistently. Changed all occurrences 141 | to USB_CFG_DESCR_PROPS_STRING_PRODUCT. 142 | - New assembler module for 16.5 MHz RC oscillator clock with PLL in receiver 143 | code. 144 | - New assembler module for 16 MHz crystal. 145 | - usbdrvasm.S contains common code only, clock-specific parts have been moved 146 | to usbdrvasm12.S, usbdrvasm16.S and usbdrvasm165.S respectively. 147 | 148 | * Release 2007-06-25 149 | 150 | - 16 MHz module: Do SE0 check in stuffed bits as well. 151 | 152 | * Release 2007-07-07 153 | 154 | - Define hi8(x) for IAR compiler to limit result to 8 bits. This is necessary 155 | for negative values. 156 | - Added 15 MHz module contributed by V. Bosch. 157 | - Interrupt vector name can now be configured. This is useful if somebody 158 | wants to use a different hardware interrupt than INT0. 159 | 160 | * Release 2007-08-07 161 | 162 | - Moved handleIn3 routine in usbdrvasm16.S so that relative jump range is 163 | not exceeded. 164 | - More config options: USB_RX_USER_HOOK(), USB_INITIAL_DATATOKEN, 165 | USB_COUNT_SOF 166 | - USB_INTR_PENDING can now be a memory address, not just I/O 167 | 168 | * Release 2007-09-19 169 | 170 | - Split out common parts of assembler modules into separate include file 171 | - Made endpoint numbers configurable so that given interface definitions 172 | can be matched. See USB_CFG_EP3_NUMBER in usbconfig-prototype.h. 173 | - Store endpoint number for interrupt/bulk-out so that usbFunctionWriteOut() 174 | can handle any number of endpoints. 175 | - Define usbDeviceConnect() and usbDeviceDisconnect() even if no 176 | USB_CFG_PULLUP_IOPORTNAME is defined. Directly set D+ and D- to 0 in this 177 | case. 178 | 179 | * Release 2007-12-01 180 | 181 | - Optimize usbDeviceConnect() and usbDeviceDisconnect() for less code size 182 | when USB_CFG_PULLUP_IOPORTNAME is not defined. 183 | 184 | * Release 2007-12-13 185 | 186 | - Renamed all include-only assembler modules from *.S to *.inc so that 187 | people don't add them to their project sources. 188 | - Distribute leap bits in tx loop more evenly for 16 MHz module. 189 | - Use "macro" and "endm" instead of ".macro" and ".endm" for IAR 190 | - Avoid compiler warnings for constant expr range by casting some values in 191 | USB descriptors. 192 | 193 | * Release 2008-01-21 194 | 195 | - Fixed bug in 15 and 16 MHz module where the new address set with 196 | SET_ADDRESS was already accepted at the next NAK or ACK we send, not at 197 | the next data packet we send. This caused problems when the host polled 198 | too fast. Thanks to Alexander Neumann for his help and patience debugging 199 | this issue! 200 | 201 | * Release 2008-02-05 202 | 203 | - Fixed bug in 16.5 MHz module where a register was used in the interrupt 204 | handler before it was pushed. This bug was introduced with version 205 | 2007-09-19 when common parts were moved to a separate file. 206 | - Optimized CRC routine (thanks to Reimar Doeffinger). 207 | 208 | * Release 2008-02-16 209 | 210 | - Removed outdated IAR compatibility stuff (code sections). 211 | - Added hook macros for USB_RESET_HOOK() and USB_SET_ADDRESS_HOOK(). 212 | - Added optional routine usbMeasureFrameLength() for calibration of the 213 | internal RC oscillator. 214 | 215 | * Release 2008-02-28 216 | 217 | - USB_INITIAL_DATATOKEN defaults to USBPID_DATA1 now, which means that we 218 | start with sending USBPID_DATA0. 219 | - Changed defaults in usbconfig-prototype.h 220 | - Added free USB VID/PID pair for MIDI class devices 221 | - Restructured AVR-USB as separate package, not part of PowerSwitch any more. 222 | 223 | * Release 2008-04-18 224 | 225 | - Restructured usbdrv.c so that it is easier to read and understand. 226 | - Better code optimization with gcc 4. 227 | - If a second interrupt in endpoint is enabled, also add it to config 228 | descriptor. 229 | - Added config option for long transfers (above 254 bytes), see 230 | USB_CFG_LONG_TRANSFERS in usbconfig.h. 231 | - Added 20 MHz module contributed by Jeroen Benschop. 232 | 233 | * Release 2008-05-13 234 | 235 | - Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length 236 | was not incremented, pointer to length was incremented instead. 237 | - Added code to command line tool(s) which claims an interface. This code 238 | is disabled by default, but may be necessary on newer Linux kernels. 239 | - Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING". 240 | - New header "usbportability.h" prepares ports to other development 241 | environments. 242 | - Long transfers (above 254 bytes) did not work when usbFunctionRead() was 243 | used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!] 244 | - In hiddata.c (example code for sending/receiving data over HID), use 245 | USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so 246 | that we need not claim the interface. 247 | - in usbPoll() loop 20 times polling for RESET state instead of 10 times. 248 | This accounts for the higher clock rates we now support. 249 | - Added a module for 12.8 MHz RC oscillator with PLL in receiver loop. 250 | - Added hook to SOF code so that oscillator can be tuned to USB frame clock. 251 | - Added timeout to waitForJ loop. Helps preventing unexpected hangs. 252 | - Added example code for oscillator tuning to libs-device (thanks to 253 | Henrik Haftmann for the idea to this routine). 254 | - Implemented option USB_CFG_SUPPRESS_INTR_CODE. 255 | 256 | * Release 2008-10-22 257 | 258 | - Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and 259 | similar, not offset of 0x20 needs to be added. 260 | - Allow distribution under GPLv3 for those who have to link against other 261 | code distributed under GPLv3. 262 | 263 | * Release 2008-11-26 264 | 265 | - Removed libusb-win32 dependency for hid-data example in Makefile.windows. 266 | It was never required and confused many people. 267 | - Added extern uchar usbRxToken to usbdrv.h. 268 | - Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser. 269 | 270 | * Release 2009-03-23 271 | 272 | - Hid-mouse example used settings from hid-data example, fixed that. 273 | - Renamed project to V-USB due to a trademark issue with Atmel(r). 274 | - Changed CommercialLicense.txt and USBID-License.txt to make the 275 | background of USB ID registration clearer. 276 | 277 | * Release 2009-04-15 278 | 279 | - Changed CommercialLicense.txt to reflect the new range of PIDs from 280 | Jason Kotzin. 281 | - Removed USBID-License.txt in favor of USB-IDs-for-free.txt and 282 | USB-ID-FAQ.txt 283 | - Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in 284 | the center between bit 0 and 1 of each byte. This is where the data lines 285 | are expected to change and the sampled data may therefore be nonsense. 286 | We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-. 287 | - Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed, 288 | the unstuffing code in the receiver routine was 1 cycle too long. If 289 | multiple bytes had the unstuffing in bit 6, the error summed up until the 290 | receiver was out of sync. 291 | - Included option for faster CRC routine. 292 | Thanks to Slawomir Fras (BoskiDialer) for this code! 293 | - Updated bits in Configuration Descriptor's bmAttributes according to 294 | USB 1.1 (in particular bit 7, it is a must-be-set bit now). 295 | 296 | * Release 2009-08-22 297 | -------------------------------------------------------------------------------- /usbdrvasm20.inc: -------------------------------------------------------------------------------- 1 | /* Name: usbdrvasm20.inc 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Jeroen Benschop 4 | * Based on usbdrvasm16.inc from Christian Starkjohann 5 | * Creation Date: 2008-03-05 6 | * Tabsize: 4 7 | * Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH 8 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 9 | * Revision: $Id: usbdrvasm20.inc 740 2009-04-13 18:23:31Z cs $ 10 | */ 11 | 12 | /* Do not link this file! Link usbdrvasm.S instead, which includes the 13 | * appropriate implementation! 14 | */ 15 | 16 | /* 17 | General Description: 18 | This file is the 20 MHz version of the asssembler part of the USB driver. It 19 | requires a 20 MHz crystal (not a ceramic resonator and not a calibrated RC 20 | oscillator). 21 | 22 | See usbdrv.h for a description of the entire driver. 23 | 24 | Since almost all of this code is timing critical, don't change unless you 25 | really know what you are doing! Many parts require not only a maximum number 26 | of CPU cycles, but even an exact number of cycles! 27 | */ 28 | 29 | #define leap2 x3 30 | #ifdef __IAR_SYSTEMS_ASM__ 31 | #define nextInst $+2 32 | #else 33 | #define nextInst .+0 34 | #endif 35 | 36 | ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes 37 | ;nominal frequency: 20 MHz -> 13.333333 cycles per bit, 106.666667 cycles per byte 38 | ; Numbers in brackets are clocks counted from center of last sync bit 39 | ; when instruction starts 40 | ;register use in receive loop: 41 | ; shift assembles the byte currently being received 42 | ; x1 holds the D+ and D- line state 43 | ; x2 holds the previous line state 44 | ; x4 (leap) is used to add a leap cycle once every three bytes received 45 | ; X3 (leap2) is used to add a leap cycle once every three stuff bits received 46 | ; bitcnt is used to determine when a stuff bit is due 47 | ; cnt holds the number of bytes left in the receive buffer 48 | 49 | USB_INTR_VECTOR: 50 | ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt 51 | push YL ;[-28] push only what is necessary to sync with edge ASAP 52 | in YL, SREG ;[-26] 53 | push YL ;[-25] 54 | push YH ;[-23] 55 | ;---------------------------------------------------------------------------- 56 | ; Synchronize with sync pattern: 57 | ;---------------------------------------------------------------------------- 58 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 59 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 60 | ;The first part waits at most 1 bit long since we must be in sync pattern. 61 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 62 | ;waitForJ, ensure that this prerequisite is met. 63 | waitForJ: 64 | inc YL 65 | sbis USBIN, USBMINUS 66 | brne waitForJ ; just make sure we have ANY timeout 67 | waitForK: 68 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 69 | sbis USBIN, USBMINUS ;[-19] 70 | rjmp foundK ;[-18] 71 | sbis USBIN, USBMINUS 72 | rjmp foundK 73 | sbis USBIN, USBMINUS 74 | rjmp foundK 75 | sbis USBIN, USBMINUS 76 | rjmp foundK 77 | sbis USBIN, USBMINUS 78 | rjmp foundK 79 | sbis USBIN, USBMINUS 80 | rjmp foundK 81 | sbis USBIN, USBMINUS 82 | rjmp foundK 83 | sbis USBIN, USBMINUS 84 | rjmp foundK 85 | sbis USBIN, USBMINUS 86 | rjmp foundK 87 | #if USB_COUNT_SOF 88 | lds YL, usbSofCount 89 | inc YL 90 | sts usbSofCount, YL 91 | #endif /* USB_COUNT_SOF */ 92 | #ifdef USB_SOF_HOOK 93 | USB_SOF_HOOK 94 | #endif 95 | rjmp sofError 96 | foundK: ;[-16] 97 | ;{3, 5} after falling D- edge, average delay: 4 cycles 98 | ;bit0 should be at 34 for center sampling. Currently at 4 so 30 cylces till bit 0 sample 99 | ;use 1 bit time for setup purposes, then sample again. Numbers in brackets 100 | ;are cycles from center of first sync (double K) bit after the instruction 101 | push bitcnt ;[-16] 102 | ; [---] ;[-15] 103 | lds YL, usbInputBufOffset;[-14] 104 | ; [---] ;[-13] 105 | clr YH ;[-12] 106 | subi YL, lo8(-(usbRxBuf));[-11] [rx loop init] 107 | sbci YH, hi8(-(usbRxBuf));[-10] [rx loop init] 108 | push shift ;[-9] 109 | ; [---] ;[-8] 110 | ldi shift,0x40 ;[-7] set msb to "1" so processing bit7 can be detected 111 | nop2 ;[-6] 112 | ; [---] ;[-5] 113 | ldi bitcnt, 5 ;[-4] [rx loop init] 114 | sbis USBIN, USBMINUS ;[-3] we want two bits K (sample 3 cycles too early) 115 | rjmp haveTwoBitsK ;[-2] 116 | pop shift ;[-1] undo the push from before 117 | pop bitcnt ;[1] 118 | rjmp waitForK ;[3] this was not the end of sync, retry 119 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 120 | ; bit times (= 27 cycles). 121 | 122 | ;---------------------------------------------------------------------------- 123 | ; push more registers and initialize values while we sample the first bits: 124 | ;---------------------------------------------------------------------------- 125 | haveTwoBitsK: 126 | push x1 ;[0] 127 | push x2 ;[2] 128 | push x3 ;[4] (leap2) 129 | ldi leap2, 0x55 ;[6] add leap cycle on 2nd,5th,8th,... stuff bit 130 | push x4 ;[7] == leap 131 | ldi leap, 0x55 ;[9] skip leap cycle on 2nd,5th,8th,... byte received 132 | push cnt ;[10] 133 | ldi cnt, USB_BUFSIZE ;[12] [rx loop init] 134 | ldi x2, 1< max 25 cycles interrupt disable 39 | ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes 40 | ;Numbers in brackets are maximum cycles since SOF. 41 | USB_INTR_VECTOR: 42 | ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt 43 | push YL ;2 [35] push only what is necessary to sync with edge ASAP 44 | in YL, SREG ;1 [37] 45 | push YL ;2 [39] 46 | ;---------------------------------------------------------------------------- 47 | ; Synchronize with sync pattern: 48 | ;---------------------------------------------------------------------------- 49 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 50 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 51 | ;The first part waits at most 1 bit long since we must be in sync pattern. 52 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 53 | ;waitForJ, ensure that this prerequisite is met. 54 | waitForJ: 55 | inc YL 56 | sbis USBIN, USBMINUS 57 | brne waitForJ ; just make sure we have ANY timeout 58 | waitForK: 59 | ;The following code results in a sampling window of 1/4 bit which meets the spec. 60 | sbis USBIN, USBMINUS 61 | rjmp foundK 62 | sbis USBIN, USBMINUS 63 | rjmp foundK 64 | sbis USBIN, USBMINUS 65 | rjmp foundK 66 | sbis USBIN, USBMINUS 67 | rjmp foundK 68 | sbis USBIN, USBMINUS 69 | rjmp foundK 70 | #if USB_COUNT_SOF 71 | lds YL, usbSofCount 72 | inc YL 73 | sts usbSofCount, YL 74 | #endif /* USB_COUNT_SOF */ 75 | #ifdef USB_SOF_HOOK 76 | USB_SOF_HOOK 77 | #endif 78 | rjmp sofError 79 | foundK: 80 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] 81 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 82 | ;are cycles from center of first sync (double K) bit after the instruction 83 | push YH ;2 [2] 84 | lds YL, usbInputBufOffset;2 [4] 85 | clr YH ;1 [5] 86 | subi YL, lo8(-(usbRxBuf));1 [6] 87 | sbci YH, hi8(-(usbRxBuf));1 [7] 88 | 89 | sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] 90 | rjmp haveTwoBitsK ;2 [10] 91 | pop YH ;2 [11] undo the push from before 92 | rjmp waitForK ;2 [13] this was not the end of sync, retry 93 | haveTwoBitsK: 94 | ;---------------------------------------------------------------------------- 95 | ; push more registers and initialize values while we sample the first bits: 96 | ;---------------------------------------------------------------------------- 97 | push shift ;2 [16] 98 | push x1 ;2 [12] 99 | push x2 ;2 [14] 100 | 101 | in x1, USBIN ;1 [17] <-- sample bit 0 102 | ldi shift, 0xff ;1 [18] 103 | bst x1, USBMINUS ;1 [19] 104 | bld shift, 0 ;1 [20] 105 | push x3 ;2 [22] 106 | push cnt ;2 [24] 107 | 108 | in x2, USBIN ;1 [25] <-- sample bit 1 109 | ser x3 ;1 [26] [inserted init instruction] 110 | eor x1, x2 ;1 [27] 111 | bst x1, USBMINUS ;1 [28] 112 | bld shift, 1 ;1 [29] 113 | ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] 114 | rjmp rxbit2 ;2 [32] 115 | 116 | ;---------------------------------------------------------------------------- 117 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 118 | ;---------------------------------------------------------------------------- 119 | 120 | unstuff0: ;1 (branch taken) 121 | andi x3, ~0x01 ;1 [15] 122 | mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit 123 | in x2, USBIN ;1 [17] <-- sample bit 1 again 124 | ori shift, 0x01 ;1 [18] 125 | rjmp didUnstuff0 ;2 [20] 126 | 127 | unstuff1: ;1 (branch taken) 128 | mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit 129 | andi x3, ~0x02 ;1 [22] 130 | ori shift, 0x02 ;1 [23] 131 | nop ;1 [24] 132 | in x1, USBIN ;1 [25] <-- sample bit 2 again 133 | rjmp didUnstuff1 ;2 [27] 134 | 135 | unstuff2: ;1 (branch taken) 136 | andi x3, ~0x04 ;1 [29] 137 | ori shift, 0x04 ;1 [30] 138 | mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit 139 | nop ;1 [32] 140 | in x2, USBIN ;1 [33] <-- sample bit 3 141 | rjmp didUnstuff2 ;2 [35] 142 | 143 | unstuff3: ;1 (branch taken) 144 | in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] 145 | andi x3, ~0x08 ;1 [35] 146 | ori shift, 0x08 ;1 [36] 147 | rjmp didUnstuff3 ;2 [38] 148 | 149 | unstuff4: ;1 (branch taken) 150 | andi x3, ~0x10 ;1 [40] 151 | in x1, USBIN ;1 [41] <-- sample stuffed bit 4 152 | ori shift, 0x10 ;1 [42] 153 | rjmp didUnstuff4 ;2 [44] 154 | 155 | unstuff5: ;1 (branch taken) 156 | andi x3, ~0x20 ;1 [48] 157 | in x2, USBIN ;1 [49] <-- sample stuffed bit 5 158 | ori shift, 0x20 ;1 [50] 159 | rjmp didUnstuff5 ;2 [52] 160 | 161 | unstuff6: ;1 (branch taken) 162 | andi x3, ~0x40 ;1 [56] 163 | in x1, USBIN ;1 [57] <-- sample stuffed bit 6 164 | ori shift, 0x40 ;1 [58] 165 | rjmp didUnstuff6 ;2 [60] 166 | 167 | ; extra jobs done during bit interval: 168 | ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs] 169 | ; bit 1: se0 check 170 | ; bit 2: overflow check 171 | ; bit 3: recovery from delay [bit 0 tasks took too long] 172 | ; bit 4: none 173 | ; bit 5: none 174 | ; bit 6: none 175 | ; bit 7: jump, eor 176 | rxLoop: 177 | eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others 178 | in x1, USBIN ;1 [1] <-- sample bit 0 179 | st y+, x3 ;2 [3] store data 180 | ser x3 ;1 [4] 181 | nop ;1 [5] 182 | eor x2, x1 ;1 [6] 183 | bst x2, USBMINUS;1 [7] 184 | bld shift, 0 ;1 [8] 185 | in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) 186 | andi x2, USBMASK ;1 [10] 187 | breq se0 ;1 [11] SE0 check for bit 1 188 | andi shift, 0xf9 ;1 [12] 189 | didUnstuff0: 190 | breq unstuff0 ;1 [13] 191 | eor x1, x2 ;1 [14] 192 | bst x1, USBMINUS;1 [15] 193 | bld shift, 1 ;1 [16] 194 | rxbit2: 195 | in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) 196 | andi shift, 0xf3 ;1 [18] 197 | breq unstuff1 ;1 [19] do remaining work for bit 1 198 | didUnstuff1: 199 | subi cnt, 1 ;1 [20] 200 | brcs overflow ;1 [21] loop control 201 | eor x2, x1 ;1 [22] 202 | bst x2, USBMINUS;1 [23] 203 | bld shift, 2 ;1 [24] 204 | in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) 205 | andi shift, 0xe7 ;1 [26] 206 | breq unstuff2 ;1 [27] 207 | didUnstuff2: 208 | eor x1, x2 ;1 [28] 209 | bst x1, USBMINUS;1 [29] 210 | bld shift, 3 ;1 [30] 211 | didUnstuff3: 212 | andi shift, 0xcf ;1 [31] 213 | breq unstuff3 ;1 [32] 214 | in x1, USBIN ;1 [33] <-- sample bit 4 215 | eor x2, x1 ;1 [34] 216 | bst x2, USBMINUS;1 [35] 217 | bld shift, 4 ;1 [36] 218 | didUnstuff4: 219 | andi shift, 0x9f ;1 [37] 220 | breq unstuff4 ;1 [38] 221 | nop2 ;2 [40] 222 | in x2, USBIN ;1 [41] <-- sample bit 5 223 | eor x1, x2 ;1 [42] 224 | bst x1, USBMINUS;1 [43] 225 | bld shift, 5 ;1 [44] 226 | didUnstuff5: 227 | andi shift, 0x3f ;1 [45] 228 | breq unstuff5 ;1 [46] 229 | nop2 ;2 [48] 230 | in x1, USBIN ;1 [49] <-- sample bit 6 231 | eor x2, x1 ;1 [50] 232 | bst x2, USBMINUS;1 [51] 233 | bld shift, 6 ;1 [52] 234 | didUnstuff6: 235 | cpi shift, 0x02 ;1 [53] 236 | brlo unstuff6 ;1 [54] 237 | nop2 ;2 [56] 238 | in x2, USBIN ;1 [57] <-- sample bit 7 239 | eor x1, x2 ;1 [58] 240 | bst x1, USBMINUS;1 [59] 241 | bld shift, 7 ;1 [60] 242 | didUnstuff7: 243 | cpi shift, 0x04 ;1 [61] 244 | brsh rxLoop ;2 [63] loop control 245 | unstuff7: 246 | andi x3, ~0x80 ;1 [63] 247 | ori shift, 0x80 ;1 [64] 248 | in x2, USBIN ;1 [65] <-- sample stuffed bit 7 249 | nop ;1 [66] 250 | rjmp didUnstuff7 ;2 [68] 251 | 252 | macro POP_STANDARD ; 12 cycles 253 | pop cnt 254 | pop x3 255 | pop x2 256 | pop x1 257 | pop shift 258 | pop YH 259 | endm 260 | macro POP_RETI ; 5 cycles 261 | pop YL 262 | out SREG, YL 263 | pop YL 264 | endm 265 | 266 | #include "asmcommon.inc" 267 | 268 | ;---------------------------------------------------------------------------- 269 | ; Transmitting data 270 | ;---------------------------------------------------------------------------- 271 | 272 | txByteLoop: 273 | txBitloop: 274 | stuffN1Delay: ; [03] 275 | ror shift ;[-5] [11] [59] 276 | brcc doExorN1 ;[-4] [60] 277 | subi x4, 1 ;[-3] 278 | brne commonN1 ;[-2] 279 | lsl shift ;[-1] compensate ror after rjmp stuffDelay 280 | nop ;[00] stuffing consists of just waiting 8 cycles 281 | rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear 282 | 283 | sendNakAndReti: ;0 [-19] 19 cycles until SOP 284 | ldi x3, USBPID_NAK ;1 [-18] 285 | rjmp usbSendX3 ;2 [-16] 286 | sendAckAndReti: ;0 [-19] 19 cycles until SOP 287 | ldi x3, USBPID_ACK ;1 [-18] 288 | rjmp usbSendX3 ;2 [-16] 289 | sendCntAndReti: ;0 [-17] 17 cycles until SOP 290 | mov x3, cnt ;1 [-16] 291 | usbSendX3: ;0 [-16] 292 | ldi YL, 20 ;1 [-15] 'x3' is R20 293 | ldi YH, 0 ;1 [-14] 294 | ldi cnt, 2 ;1 [-13] 295 | ; rjmp usbSendAndReti fallthrough 296 | 297 | ; USB spec says: 298 | ; idle = J 299 | ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 300 | ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 301 | ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) 302 | 303 | ;usbSend: 304 | ;pointer to data in 'Y' 305 | ;number of bytes in 'cnt' -- including sync byte 306 | ;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] 307 | ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) 308 | usbSendAndReti: 309 | in x2, USBDDR ;[-12] 12 cycles until SOP 310 | ori x2, USBMASK ;[-11] 311 | sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 312 | out USBDDR, x2 ;[-8] <--- acquire bus 313 | in x1, USBOUT ;[-7] port mirror for tx loop 314 | ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror) 315 | ldi x2, USBMASK ;[-5] 316 | push x4 ;[-4] 317 | doExorN1: 318 | eor x1, x2 ;[-2] [06] [62] 319 | ldi x4, 6 ;[-1] [07] [63] 320 | commonN1: 321 | stuffN2Delay: 322 | out USBOUT, x1 ;[00] [08] [64] <--- set bit 323 | ror shift ;[01] 324 | brcc doExorN2 ;[02] 325 | subi x4, 1 ;[03] 326 | brne commonN2 ;[04] 327 | lsl shift ;[05] compensate ror after rjmp stuffDelay 328 | rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear 329 | doExorN2: 330 | eor x1, x2 ;[04] [12] 331 | ldi x4, 6 ;[05] [13] 332 | commonN2: 333 | nop ;[06] [14] 334 | subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1 335 | out USBOUT, x1 ;[08] [16] <--- set bit 336 | brcs txBitloop ;[09] [25] [41] 337 | 338 | stuff6Delay: 339 | ror shift ;[42] [50] 340 | brcc doExor6 ;[43] 341 | subi x4, 1 ;[44] 342 | brne common6 ;[45] 343 | lsl shift ;[46] compensate ror after rjmp stuffDelay 344 | nop ;[47] stuffing consists of just waiting 8 cycles 345 | rjmp stuff6Delay ;[48] after ror, C bit is reliably clear 346 | doExor6: 347 | eor x1, x2 ;[45] [53] 348 | ldi x4, 6 ;[46] 349 | common6: 350 | stuff7Delay: 351 | ror shift ;[47] [55] 352 | out USBOUT, x1 ;[48] <--- set bit 353 | brcc doExor7 ;[49] 354 | subi x4, 1 ;[50] 355 | brne common7 ;[51] 356 | lsl shift ;[52] compensate ror after rjmp stuffDelay 357 | rjmp stuff7Delay ;[53] after ror, C bit is reliably clear 358 | doExor7: 359 | eor x1, x2 ;[51] [59] 360 | ldi x4, 6 ;[52] 361 | common7: 362 | ld shift, y+ ;[53] 363 | tst cnt ;[55] 364 | out USBOUT, x1 ;[56] <--- set bit 365 | brne txByteLoop ;[57] 366 | 367 | ;make SE0: 368 | cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] 369 | lds x2, usbNewDeviceAddr;[59] 370 | lsl x2 ;[61] we compare with left shifted address 371 | subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3 372 | sbci YH, 0 ;[63] 373 | out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle 374 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 375 | ;set address only after data packet was sent, not after handshake 376 | breq skipAddrAssign ;[01] 377 | sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer 378 | skipAddrAssign: 379 | ;end of usbDeviceAddress transfer 380 | ldi x2, 1< max 52 cycles interrupt disable 32 | ;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes 33 | ;nominal frequency: 16.5 MHz -> 11 cycles per bit 34 | ; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%) 35 | ; Numbers in brackets are clocks counted from center of last sync bit 36 | ; when instruction starts 37 | 38 | 39 | USB_INTR_VECTOR: 40 | ;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt 41 | push YL ;[-23] push only what is necessary to sync with edge ASAP 42 | in YL, SREG ;[-21] 43 | push YL ;[-20] 44 | ;---------------------------------------------------------------------------- 45 | ; Synchronize with sync pattern: 46 | ;---------------------------------------------------------------------------- 47 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 48 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 49 | ;The first part waits at most 1 bit long since we must be in sync pattern. 50 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 51 | ;waitForJ, ensure that this prerequisite is met. 52 | waitForJ: 53 | inc YL 54 | sbis USBIN, USBMINUS 55 | brne waitForJ ; just make sure we have ANY timeout 56 | waitForK: 57 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 58 | sbis USBIN, USBMINUS ;[-15] 59 | rjmp foundK ;[-14] 60 | sbis USBIN, USBMINUS 61 | rjmp foundK 62 | sbis USBIN, USBMINUS 63 | rjmp foundK 64 | sbis USBIN, USBMINUS 65 | rjmp foundK 66 | sbis USBIN, USBMINUS 67 | rjmp foundK 68 | sbis USBIN, USBMINUS 69 | rjmp foundK 70 | #if USB_COUNT_SOF 71 | lds YL, usbSofCount 72 | inc YL 73 | sts usbSofCount, YL 74 | #endif /* USB_COUNT_SOF */ 75 | #ifdef USB_SOF_HOOK 76 | USB_SOF_HOOK 77 | #endif 78 | rjmp sofError 79 | foundK: ;[-12] 80 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] 81 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 82 | ;are cycles from center of first sync (double K) bit after the instruction 83 | push r0 ;[-12] 84 | ; [---] ;[-11] 85 | push YH ;[-10] 86 | ; [---] ;[-9] 87 | lds YL, usbInputBufOffset;[-8] 88 | ; [---] ;[-7] 89 | clr YH ;[-6] 90 | subi YL, lo8(-(usbRxBuf));[-5] [rx loop init] 91 | sbci YH, hi8(-(usbRxBuf));[-4] [rx loop init] 92 | mov r0, x2 ;[-3] [rx loop init] 93 | sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) 94 | rjmp haveTwoBitsK ;[-1] 95 | pop YH ;[0] undo the pushes from before 96 | pop r0 ;[2] 97 | rjmp waitForK ;[4] this was not the end of sync, retry 98 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 99 | ; bit times (= 22 cycles). 100 | 101 | ;---------------------------------------------------------------------------- 102 | ; push more registers and initialize values while we sample the first bits: 103 | ;---------------------------------------------------------------------------- 104 | haveTwoBitsK: ;[1] 105 | push shift ;[1] 106 | push x1 ;[3] 107 | push x2 ;[5] 108 | push x3 ;[7] 109 | ldi shift, 0xff ;[9] [rx loop init] 110 | ori x3, 0xff ;[10] [rx loop init] == ser x3, clear zero flag 111 | 112 | in x1, USBIN ;[11] <-- sample bit 0 113 | bst x1, USBMINUS ;[12] 114 | bld shift, 0 ;[13] 115 | push x4 ;[14] == phase 116 | ; [---] ;[15] 117 | push cnt ;[16] 118 | ; [---] ;[17] 119 | ldi phase, 0 ;[18] [rx loop init] 120 | ldi cnt, USB_BUFSIZE;[19] [rx loop init] 121 | rjmp rxbit1 ;[20] 122 | ; [---] ;[21] 123 | 124 | ;---------------------------------------------------------------------------- 125 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 126 | ;---------------------------------------------------------------------------- 127 | /* 128 | byte oriented operations done during loop: 129 | bit 0: store data 130 | bit 1: SE0 check 131 | bit 2: overflow check 132 | bit 3: catch up 133 | bit 4: rjmp to achieve conditional jump range 134 | bit 5: PLL 135 | bit 6: catch up 136 | bit 7: jump, fixup bitstuff 137 | ; 87 [+ 2] cycles 138 | ------------------------------------------------------------------ 139 | */ 140 | continueWithBit5: 141 | in x2, USBIN ;[055] <-- bit 5 142 | eor r0, x2 ;[056] 143 | or phase, r0 ;[057] 144 | sbrc phase, USBMINUS ;[058] 145 | lpm ;[059] optional nop3; modifies r0 146 | in phase, USBIN ;[060] <-- phase 147 | eor x1, x2 ;[061] 148 | bst x1, USBMINUS ;[062] 149 | bld shift, 5 ;[063] 150 | andi shift, 0x3f ;[064] 151 | in x1, USBIN ;[065] <-- bit 6 152 | breq unstuff5 ;[066] *** unstuff escape 153 | eor phase, x1 ;[067] 154 | eor x2, x1 ;[068] 155 | bst x2, USBMINUS ;[069] 156 | bld shift, 6 ;[070] 157 | didUnstuff6: ;[ ] 158 | in r0, USBIN ;[071] <-- phase 159 | cpi shift, 0x02 ;[072] 160 | brlo unstuff6 ;[073] *** unstuff escape 161 | didUnstuff5: ;[ ] 162 | nop2 ;[074] 163 | ; [---] ;[075] 164 | in x2, USBIN ;[076] <-- bit 7 165 | eor x1, x2 ;[077] 166 | bst x1, USBMINUS ;[078] 167 | bld shift, 7 ;[079] 168 | didUnstuff7: ;[ ] 169 | eor r0, x2 ;[080] 170 | or phase, r0 ;[081] 171 | in r0, USBIN ;[082] <-- phase 172 | cpi shift, 0x04 ;[083] 173 | brsh rxLoop ;[084] 174 | ; [---] ;[085] 175 | unstuff7: ;[ ] 176 | andi x3, ~0x80 ;[085] 177 | ori shift, 0x80 ;[086] 178 | in x2, USBIN ;[087] <-- sample stuffed bit 7 179 | nop ;[088] 180 | rjmp didUnstuff7 ;[089] 181 | ; [---] ;[090] 182 | ;[080] 183 | 184 | unstuff5: ;[067] 185 | eor phase, x1 ;[068] 186 | andi x3, ~0x20 ;[069] 187 | ori shift, 0x20 ;[070] 188 | in r0, USBIN ;[071] <-- phase 189 | mov x2, x1 ;[072] 190 | nop ;[073] 191 | nop2 ;[074] 192 | ; [---] ;[075] 193 | in x1, USBIN ;[076] <-- bit 6 194 | eor r0, x1 ;[077] 195 | or phase, r0 ;[078] 196 | eor x2, x1 ;[079] 197 | bst x2, USBMINUS ;[080] 198 | bld shift, 6 ;[081] no need to check bitstuffing, we just had one 199 | in r0, USBIN ;[082] <-- phase 200 | rjmp didUnstuff5 ;[083] 201 | ; [---] ;[084] 202 | ;[074] 203 | 204 | unstuff6: ;[074] 205 | andi x3, ~0x40 ;[075] 206 | in x1, USBIN ;[076] <-- bit 6 again 207 | ori shift, 0x40 ;[077] 208 | nop2 ;[078] 209 | ; [---] ;[079] 210 | rjmp didUnstuff6 ;[080] 211 | ; [---] ;[081] 212 | ;[071] 213 | 214 | unstuff0: ;[013] 215 | eor r0, x2 ;[014] 216 | or phase, r0 ;[015] 217 | andi x2, USBMASK ;[016] check for SE0 218 | in r0, USBIN ;[017] <-- phase 219 | breq didUnstuff0 ;[018] direct jump to se0 would be too long 220 | andi x3, ~0x01 ;[019] 221 | ori shift, 0x01 ;[020] 222 | mov x1, x2 ;[021] mov existing sample 223 | in x2, USBIN ;[022] <-- bit 1 again 224 | rjmp didUnstuff0 ;[023] 225 | ; [---] ;[024] 226 | ;[014] 227 | 228 | unstuff1: ;[024] 229 | eor r0, x1 ;[025] 230 | or phase, r0 ;[026] 231 | andi x3, ~0x02 ;[027] 232 | in r0, USBIN ;[028] <-- phase 233 | ori shift, 0x02 ;[029] 234 | mov x2, x1 ;[030] 235 | rjmp didUnstuff1 ;[031] 236 | ; [---] ;[032] 237 | ;[022] 238 | 239 | unstuff2: ;[035] 240 | eor r0, x2 ;[036] 241 | or phase, r0 ;[037] 242 | andi x3, ~0x04 ;[038] 243 | in r0, USBIN ;[039] <-- phase 244 | ori shift, 0x04 ;[040] 245 | mov x1, x2 ;[041] 246 | rjmp didUnstuff2 ;[042] 247 | ; [---] ;[043] 248 | ;[033] 249 | 250 | unstuff3: ;[043] 251 | in x2, USBIN ;[044] <-- bit 3 again 252 | eor r0, x2 ;[045] 253 | or phase, r0 ;[046] 254 | andi x3, ~0x08 ;[047] 255 | ori shift, 0x08 ;[048] 256 | nop ;[049] 257 | in r0, USBIN ;[050] <-- phase 258 | rjmp didUnstuff3 ;[051] 259 | ; [---] ;[052] 260 | ;[042] 261 | 262 | unstuff4: ;[053] 263 | andi x3, ~0x10 ;[054] 264 | in x1, USBIN ;[055] <-- bit 4 again 265 | ori shift, 0x10 ;[056] 266 | rjmp didUnstuff4 ;[057] 267 | ; [---] ;[058] 268 | ;[048] 269 | 270 | rxLoop: ;[085] 271 | eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others 272 | in x1, USBIN ;[000] <-- bit 0 273 | st y+, x3 ;[001] 274 | ; [---] ;[002] 275 | eor r0, x1 ;[003] 276 | or phase, r0 ;[004] 277 | eor x2, x1 ;[005] 278 | in r0, USBIN ;[006] <-- phase 279 | ser x3 ;[007] 280 | bst x2, USBMINUS ;[008] 281 | bld shift, 0 ;[009] 282 | andi shift, 0xf9 ;[010] 283 | rxbit1: ;[ ] 284 | in x2, USBIN ;[011] <-- bit 1 285 | breq unstuff0 ;[012] *** unstuff escape 286 | andi x2, USBMASK ;[013] SE0 check for bit 1 287 | didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff 288 | breq se0 ;[014] 289 | eor r0, x2 ;[015] 290 | or phase, r0 ;[016] 291 | in r0, USBIN ;[017] <-- phase 292 | eor x1, x2 ;[018] 293 | bst x1, USBMINUS ;[019] 294 | bld shift, 1 ;[020] 295 | andi shift, 0xf3 ;[021] 296 | didUnstuff1: ;[ ] 297 | in x1, USBIN ;[022] <-- bit 2 298 | breq unstuff1 ;[023] *** unstuff escape 299 | eor r0, x1 ;[024] 300 | or phase, r0 ;[025] 301 | subi cnt, 1 ;[026] overflow check 302 | brcs overflow ;[027] 303 | in r0, USBIN ;[028] <-- phase 304 | eor x2, x1 ;[029] 305 | bst x2, USBMINUS ;[030] 306 | bld shift, 2 ;[031] 307 | andi shift, 0xe7 ;[032] 308 | didUnstuff2: ;[ ] 309 | in x2, USBIN ;[033] <-- bit 3 310 | breq unstuff2 ;[034] *** unstuff escape 311 | eor r0, x2 ;[035] 312 | or phase, r0 ;[036] 313 | eor x1, x2 ;[037] 314 | bst x1, USBMINUS ;[038] 315 | in r0, USBIN ;[039] <-- phase 316 | bld shift, 3 ;[040] 317 | andi shift, 0xcf ;[041] 318 | didUnstuff3: ;[ ] 319 | breq unstuff3 ;[042] *** unstuff escape 320 | nop ;[043] 321 | in x1, USBIN ;[044] <-- bit 4 322 | eor x2, x1 ;[045] 323 | bst x2, USBMINUS ;[046] 324 | bld shift, 4 ;[047] 325 | didUnstuff4: ;[ ] 326 | eor r0, x1 ;[048] 327 | or phase, r0 ;[049] 328 | in r0, USBIN ;[050] <-- phase 329 | andi shift, 0x9f ;[051] 330 | breq unstuff4 ;[052] *** unstuff escape 331 | rjmp continueWithBit5;[053] 332 | ; [---] ;[054] 333 | 334 | macro POP_STANDARD ; 16 cycles 335 | pop cnt 336 | pop x4 337 | pop x3 338 | pop x2 339 | pop x1 340 | pop shift 341 | pop YH 342 | pop r0 343 | endm 344 | macro POP_RETI ; 5 cycles 345 | pop YL 346 | out SREG, YL 347 | pop YL 348 | endm 349 | 350 | #include "asmcommon.inc" 351 | 352 | 353 | ; USB spec says: 354 | ; idle = J 355 | ; J = (D+ = 0), (D- = 1) 356 | ; K = (D+ = 1), (D- = 0) 357 | ; Spec allows 7.5 bit times from EOP to SOP for replies 358 | 359 | bitstuff7: 360 | eor x1, x4 ;[4] 361 | ldi x2, 0 ;[5] 362 | nop2 ;[6] C is zero (brcc) 363 | rjmp didStuff7 ;[8] 364 | 365 | bitstuffN: 366 | eor x1, x4 ;[5] 367 | ldi x2, 0 ;[6] 368 | lpm ;[7] 3 cycle NOP, modifies r0 369 | out USBOUT, x1 ;[10] <-- out 370 | rjmp didStuffN ;[0] 371 | 372 | #define bitStatus x3 373 | 374 | sendNakAndReti: 375 | ldi cnt, USBPID_NAK ;[-19] 376 | rjmp sendCntAndReti ;[-18] 377 | sendAckAndReti: 378 | ldi cnt, USBPID_ACK ;[-17] 379 | sendCntAndReti: 380 | mov r0, cnt ;[-16] 381 | ldi YL, 0 ;[-15] R0 address is 0 382 | ldi YH, 0 ;[-14] 383 | ldi cnt, 2 ;[-13] 384 | ; rjmp usbSendAndReti fallthrough 385 | 386 | ;usbSend: 387 | ;pointer to data in 'Y' 388 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 389 | ;uses: x1...x4, shift, cnt, Y 390 | ;Numbers in brackets are time since first bit of sync pattern is sent 391 | usbSendAndReti: ; 12 cycles until SOP 392 | in x2, USBDDR ;[-12] 393 | ori x2, USBMASK ;[-11] 394 | sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 395 | in x1, USBOUT ;[-8] port mirror for tx loop 396 | out USBDDR, x2 ;[-7] <- acquire bus 397 | ; need not init x2 (bitstuff history) because sync starts with 0 398 | ldi x4, USBMASK ;[-6] exor mask 399 | ldi shift, 0x80 ;[-5] sync byte is first byte sent 400 | ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes 401 | byteloop: 402 | bitloop: 403 | sbrs shift, 0 ;[8] [-3] 404 | eor x1, x4 ;[9] [-2] 405 | out USBOUT, x1 ;[10] [-1] <-- out 406 | ror shift ;[0] 407 | ror x2 ;[1] 408 | didStuffN: 409 | cpi x2, 0xfc ;[2] 410 | brcc bitstuffN ;[3] 411 | nop ;[4] 412 | subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37 413 | brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value 414 | sbrs shift, 0 ;[7] 415 | eor x1, x4 ;[8] 416 | ror shift ;[9] 417 | didStuff7: 418 | out USBOUT, x1 ;[10] <-- out 419 | ror x2 ;[0] 420 | cpi x2, 0xfc ;[1] 421 | brcc bitstuff7 ;[2] 422 | ld shift, y+ ;[3] 423 | dec cnt ;[5] 424 | brne byteloop ;[6] 425 | ;make SE0: 426 | cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles] 427 | lds x2, usbNewDeviceAddr;[8] 428 | lsl x2 ;[10] we compare with left shifted address 429 | out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle 430 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 431 | ;set address only after data packet was sent, not after handshake 432 | subi YL, 2 ;[0] Only assign address on data packets, not ACK/NAK in r0 433 | sbci YH, 0 ;[1] 434 | breq skipAddrAssign ;[2] 435 | sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer 436 | skipAddrAssign: 437 | ;end of usbDeviceAddress transfer 438 | ldi x2, 1< 10.0 cycles per bit, 80.0 cycles per byte 30 | ; Numbers in brackets are clocks counted from center of last sync bit 31 | ; when instruction starts 32 | 33 | ;---------------------------------------------------------------------------- 34 | ; order of registers pushed: 35 | ; YL, SREG [sofError] YH, shift, x1, x2, x3, bitcnt, cnt, x4 36 | ;---------------------------------------------------------------------------- 37 | USB_INTR_VECTOR: 38 | push YL ;2 push only what is necessary to sync with edge ASAP 39 | in YL, SREG ;1 40 | push YL ;2 41 | ;---------------------------------------------------------------------------- 42 | ; Synchronize with sync pattern: 43 | ; 44 | ; sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 45 | ; sync up with J to K edge during sync pattern -- use fastest possible loops 46 | ;The first part waits at most 1 bit long since we must be in sync pattern. 47 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 48 | ;waitForJ, ensure that this prerequisite is met. 49 | waitForJ: 50 | inc YL 51 | sbis USBIN, USBMINUS 52 | brne waitForJ ; just make sure we have ANY timeout 53 | ;------------------------------------------------------------------------------- 54 | ; The following code results in a sampling window of < 1/4 bit 55 | ; which meets the spec. 56 | ;------------------------------------------------------------------------------- 57 | waitForK: ;- 58 | sbis USBIN, USBMINUS ;1 [00] <-- sample 59 | rjmp foundK ;2 [01] 60 | sbis USBIN, USBMINUS ; <-- sample 61 | rjmp foundK 62 | sbis USBIN, USBMINUS ; <-- sample 63 | rjmp foundK 64 | sbis USBIN, USBMINUS ; <-- sample 65 | rjmp foundK 66 | sbis USBIN, USBMINUS ; <-- sample 67 | rjmp foundK 68 | sbis USBIN, USBMINUS ; <-- sample 69 | rjmp foundK 70 | #if USB_COUNT_SOF 71 | lds YL, usbSofCount 72 | inc YL 73 | sts usbSofCount, YL 74 | #endif /* USB_COUNT_SOF */ 75 | #ifdef USB_SOF_HOOK 76 | USB_SOF_HOOK 77 | #endif 78 | rjmp sofError 79 | ;------------------------------------------------------------------------------ 80 | ; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for 81 | ; center sampling] 82 | ; we have 1 bit time for setup purposes, then sample again. 83 | ; Numbers in brackets are cycles from center of first sync (double K) 84 | ; bit after the instruction 85 | ;------------------------------------------------------------------------------ 86 | foundK: ;- [02] 87 | lds YL, usbInputBufOffset;2 [03+04] tx loop 88 | push YH ;2 [05+06] 89 | clr YH ;1 [07] 90 | subi YL, lo8(-(usbRxBuf)) ;1 [08] [rx loop init] 91 | sbci YH, hi8(-(usbRxBuf)) ;1 [09] [rx loop init] 92 | push shift ;2 [10+11] 93 | ser shift ;1 [12] 94 | sbis USBIN, USBMINUS ;1 [-1] [13] <--sample:we want two bits K (sample 1 cycle too early) 95 | rjmp haveTwoBitsK ;2 [00] [14] 96 | pop shift ;2 [15+16] undo the push from before 97 | pop YH ;2 [17+18] undo the push from before 98 | rjmp waitForK ;2 [19+20] this was not the end of sync, retry 99 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 100 | ; bit times (= 20 cycles). 101 | 102 | ;---------------------------------------------------------------------------- 103 | ; push more registers and initialize values while we sample the first bits: 104 | ;---------------------------------------------------------------------------- 105 | haveTwoBitsK: ;- [01] 106 | push x1 ;2 [02+03] 107 | push x2 ;2 [04+05] 108 | push x3 ;2 [06+07] 109 | push bitcnt ;2 [08+09] 110 | in x1, USBIN ;1 [00] [10] <-- sample bit 0 111 | bst x1, USBMINUS ;1 [01] 112 | bld shift, 0 ;1 [02] 113 | push cnt ;2 [03+04] 114 | ldi cnt, USB_BUFSIZE ;1 [05] 115 | push x4 ;2 [06+07] tx loop 116 | rjmp rxLoop ;2 [08] 117 | ;---------------------------------------------------------------------------- 118 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 119 | ;---------------------------------------------------------------------------- 120 | unstuff0: ;- [07] (branch taken) 121 | andi x3, ~0x01 ;1 [08] 122 | mov x1, x2 ;1 [09] x2 contains last sampled (stuffed) bit 123 | in x2, USBIN ;1 [00] [10] <-- sample bit 1 again 124 | andi x2, USBMASK ;1 [01] 125 | breq se0Hop ;1 [02] SE0 check for bit 1 126 | ori shift, 0x01 ;1 [03] 0b00000001 127 | nop ;1 [04] 128 | rjmp didUnstuff0 ;2 [05] 129 | ;----------------------------------------------------- 130 | unstuff1: ;- [05] (branch taken) 131 | mov x2, x1 ;1 [06] x1 contains last sampled (stuffed) bit 132 | andi x3, ~0x02 ;1 [07] 133 | ori shift, 0x02 ;1 [08] 0b00000010 134 | nop ;1 [09] 135 | in x1, USBIN ;1 [00] [10] <-- sample bit 2 again 136 | andi x1, USBMASK ;1 [01] 137 | breq se0Hop ;1 [02] SE0 check for bit 2 138 | rjmp didUnstuff1 ;2 [03] 139 | ;----------------------------------------------------- 140 | unstuff2: ;- [05] (branch taken) 141 | andi x3, ~0x04 ;1 [06] 142 | ori shift, 0x04 ;1 [07] 0b00000100 143 | mov x1, x2 ;1 [08] x2 contains last sampled (stuffed) bit 144 | nop ;1 [09] 145 | in x2, USBIN ;1 [00] [10] <-- sample bit 3 146 | andi x2, USBMASK ;1 [01] 147 | breq se0Hop ;1 [02] SE0 check for bit 3 148 | rjmp didUnstuff2 ;2 [03] 149 | ;----------------------------------------------------- 150 | unstuff3: ;- [00] [10] (branch taken) 151 | in x2, USBIN ;1 [01] [11] <-- sample stuffed bit 3 one cycle too late 152 | andi x2, USBMASK ;1 [02] 153 | breq se0Hop ;1 [03] SE0 check for stuffed bit 3 154 | andi x3, ~0x08 ;1 [04] 155 | ori shift, 0x08 ;1 [05] 0b00001000 156 | rjmp didUnstuff3 ;2 [06] 157 | ;---------------------------------------------------------------------------- 158 | ; extra jobs done during bit interval: 159 | ; 160 | ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs], 161 | ; overflow check, jump to the head of rxLoop 162 | ; bit 1: SE0 check 163 | ; bit 2: SE0 check, recovery from delay [bit 0 tasks took too long] 164 | ; bit 3: SE0 check, recovery from delay [bit 0 tasks took too long] 165 | ; bit 4: SE0 check, none 166 | ; bit 5: SE0 check, none 167 | ; bit 6: SE0 check, none 168 | ; bit 7: SE0 check, reconstruct: x3 is 0 at bit locations we changed, 1 at others 169 | ;---------------------------------------------------------------------------- 170 | rxLoop: ;- [09] 171 | in x2, USBIN ;1 [00] [10] <-- sample bit 1 (or possibly bit 0 stuffed) 172 | andi x2, USBMASK ;1 [01] 173 | brne SkipSe0Hop ;1 [02] 174 | se0Hop: ;- [02] 175 | rjmp se0 ;2 [03] SE0 check for bit 1 176 | SkipSe0Hop: ;- [03] 177 | ser x3 ;1 [04] 178 | andi shift, 0xf9 ;1 [05] 0b11111001 179 | breq unstuff0 ;1 [06] 180 | didUnstuff0: ;- [06] 181 | eor x1, x2 ;1 [07] 182 | bst x1, USBMINUS ;1 [08] 183 | bld shift, 1 ;1 [09] 184 | in x1, USBIN ;1 [00] [10] <-- sample bit 2 (or possibly bit 1 stuffed) 185 | andi x1, USBMASK ;1 [01] 186 | breq se0Hop ;1 [02] SE0 check for bit 2 187 | andi shift, 0xf3 ;1 [03] 0b11110011 188 | breq unstuff1 ;1 [04] do remaining work for bit 1 189 | didUnstuff1: ;- [04] 190 | eor x2, x1 ;1 [05] 191 | bst x2, USBMINUS ;1 [06] 192 | bld shift, 2 ;1 [07] 193 | nop2 ;2 [08+09] 194 | in x2, USBIN ;1 [00] [10] <-- sample bit 3 (or possibly bit 2 stuffed) 195 | andi x2, USBMASK ;1 [01] 196 | breq se0Hop ;1 [02] SE0 check for bit 3 197 | andi shift, 0xe7 ;1 [03] 0b11100111 198 | breq unstuff2 ;1 [04] 199 | didUnstuff2: ;- [04] 200 | eor x1, x2 ;1 [05] 201 | bst x1, USBMINUS ;1 [06] 202 | bld shift, 3 ;1 [07] 203 | didUnstuff3: ;- [07] 204 | andi shift, 0xcf ;1 [08] 0b11001111 205 | breq unstuff3 ;1 [09] 206 | in x1, USBIN ;1 [00] [10] <-- sample bit 4 207 | andi x1, USBMASK ;1 [01] 208 | breq se0Hop ;1 [02] SE0 check for bit 4 209 | eor x2, x1 ;1 [03] 210 | bst x2, USBMINUS ;1 [04] 211 | bld shift, 4 ;1 [05] 212 | didUnstuff4: ;- [05] 213 | andi shift, 0x9f ;1 [06] 0b10011111 214 | breq unstuff4 ;1 [07] 215 | nop2 ;2 [08+09] 216 | in x2, USBIN ;1 [00] [10] <-- sample bit 5 217 | andi x2, USBMASK ;1 [01] 218 | breq se0 ;1 [02] SE0 check for bit 5 219 | eor x1, x2 ;1 [03] 220 | bst x1, USBMINUS ;1 [04] 221 | bld shift, 5 ;1 [05] 222 | didUnstuff5: ;- [05] 223 | andi shift, 0x3f ;1 [06] 0b00111111 224 | breq unstuff5 ;1 [07] 225 | nop2 ;2 [08+09] 226 | in x1, USBIN ;1 [00] [10] <-- sample bit 6 227 | andi x1, USBMASK ;1 [01] 228 | breq se0 ;1 [02] SE0 check for bit 6 229 | eor x2, x1 ;1 [03] 230 | bst x2, USBMINUS ;1 [04] 231 | bld shift, 6 ;1 [05] 232 | didUnstuff6: ;- [05] 233 | cpi shift, 0x02 ;1 [06] 0b00000010 234 | brlo unstuff6 ;1 [07] 235 | nop2 ;2 [08+09] 236 | in x2, USBIN ;1 [00] [10] <-- sample bit 7 237 | andi x2, USBMASK ;1 [01] 238 | breq se0 ;1 [02] SE0 check for bit 7 239 | eor x1, x2 ;1 [03] 240 | bst x1, USBMINUS ;1 [04] 241 | bld shift, 7 ;1 [05] 242 | didUnstuff7: ;- [05] 243 | cpi shift, 0x04 ;1 [06] 0b00000100 244 | brlo unstuff7 ;1 [07] 245 | eor x3, shift ;1 [08] reconstruct: x3 is 0 at bit locations we changed, 1 at others 246 | nop ;1 [09] 247 | in x1, USBIN ;1 [00] [10] <-- sample bit 0 248 | st y+, x3 ;2 [01+02] store data 249 | eor x2, x1 ;1 [03] 250 | bst x2, USBMINUS ;1 [04] 251 | bld shift, 0 ;1 [05] 252 | subi cnt, 1 ;1 [06] 253 | brcs overflow ;1 [07] 254 | rjmp rxLoop ;2 [08] 255 | ;----------------------------------------------------- 256 | unstuff4: ;- [08] 257 | andi x3, ~0x10 ;1 [09] 258 | in x1, USBIN ;1 [00] [10] <-- sample stuffed bit 4 259 | andi x1, USBMASK ;1 [01] 260 | breq se0 ;1 [02] SE0 check for stuffed bit 4 261 | ori shift, 0x10 ;1 [03] 262 | rjmp didUnstuff4 ;2 [04] 263 | ;----------------------------------------------------- 264 | unstuff5: ;- [08] 265 | ori shift, 0x20 ;1 [09] 266 | in x2, USBIN ;1 [00] [10] <-- sample stuffed bit 5 267 | andi x2, USBMASK ;1 [01] 268 | breq se0 ;1 [02] SE0 check for stuffed bit 5 269 | andi x3, ~0x20 ;1 [03] 270 | rjmp didUnstuff5 ;2 [04] 271 | ;----------------------------------------------------- 272 | unstuff6: ;- [08] 273 | andi x3, ~0x40 ;1 [09] 274 | in x1, USBIN ;1 [00] [10] <-- sample stuffed bit 6 275 | andi x1, USBMASK ;1 [01] 276 | breq se0 ;1 [02] SE0 check for stuffed bit 6 277 | ori shift, 0x40 ;1 [03] 278 | rjmp didUnstuff6 ;2 [04] 279 | ;----------------------------------------------------- 280 | unstuff7: ;- [08] 281 | andi x3, ~0x80 ;1 [09] 282 | in x2, USBIN ;1 [00] [10] <-- sample stuffed bit 7 283 | andi x2, USBMASK ;1 [01] 284 | breq se0 ;1 [02] SE0 check for stuffed bit 7 285 | ori shift, 0x80 ;1 [03] 286 | rjmp didUnstuff7 ;2 [04] 287 | 288 | macro POP_STANDARD ; 16 cycles 289 | pop x4 290 | pop cnt 291 | pop bitcnt 292 | pop x3 293 | pop x2 294 | pop x1 295 | pop shift 296 | pop YH 297 | endm 298 | macro POP_RETI ; 5 cycles 299 | pop YL 300 | out SREG, YL 301 | pop YL 302 | endm 303 | 304 | #include "asmcommon.inc" 305 | 306 | ;--------------------------------------------------------------------------- 307 | ; USB spec says: 308 | ; idle = J 309 | ; J = (D+ = 0), (D- = 1) 310 | ; K = (D+ = 1), (D- = 0) 311 | ; Spec allows 7.5 bit times from EOP to SOP for replies 312 | ;--------------------------------------------------------------------------- 313 | bitstuffN: ;- [04] 314 | eor x1, x4 ;1 [05] 315 | clr x2 ;1 [06] 316 | nop ;1 [07] 317 | rjmp didStuffN ;1 [08] 318 | ;--------------------------------------------------------------------------- 319 | bitstuff6: ;- [04] 320 | eor x1, x4 ;1 [05] 321 | clr x2 ;1 [06] 322 | rjmp didStuff6 ;1 [07] 323 | ;--------------------------------------------------------------------------- 324 | bitstuff7: ;- [02] 325 | eor x1, x4 ;1 [03] 326 | clr x2 ;1 [06] 327 | nop ;1 [05] 328 | rjmp didStuff7 ;1 [06] 329 | ;--------------------------------------------------------------------------- 330 | sendNakAndReti: ;- [-19] 331 | ldi x3, USBPID_NAK ;1 [-18] 332 | rjmp sendX3AndReti ;1 [-17] 333 | ;--------------------------------------------------------------------------- 334 | sendAckAndReti: ;- [-17] 335 | ldi cnt, USBPID_ACK ;1 [-16] 336 | sendCntAndReti: ;- [-16] 337 | mov x3, cnt ;1 [-15] 338 | sendX3AndReti: ;- [-15] 339 | ldi YL, 20 ;1 [-14] x3==r20 address is 20 340 | ldi YH, 0 ;1 [-13] 341 | ldi cnt, 2 ;1 [-12] 342 | ; rjmp usbSendAndReti fallthrough 343 | ;--------------------------------------------------------------------------- 344 | ;usbSend: 345 | ;pointer to data in 'Y' 346 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 347 | ;uses: x1...x4, btcnt, shift, cnt, Y 348 | ;Numbers in brackets are time since first bit of sync pattern is sent 349 | ;We need not to match the transfer rate exactly because the spec demands 350 | ;only 1.5% precision anyway. 351 | usbSendAndReti: ;- [-13] 13 cycles until SOP 352 | in x2, USBDDR ;1 [-12] 353 | ori x2, USBMASK ;1 [-11] 354 | sbi USBOUT, USBMINUS ;2 [-09-10] prepare idle state; D+ and D- must have been 0 (no pullups) 355 | in x1, USBOUT ;1 [-08] port mirror for tx loop 356 | out USBDDR, x2 ;1 [-07] <- acquire bus 357 | ; need not init x2 (bitstuff history) because sync starts with 0 358 | ldi x4, USBMASK ;1 [-06] exor mask 359 | ldi shift, 0x80 ;1 [-05] sync byte is first byte sent 360 | ldi bitcnt, 6 ;1 [-04] 361 | txBitLoop: ;- [-04] [06] 362 | sbrs shift, 0 ;1 [-03] [07] 363 | eor x1, x4 ;1 [-02] [08] 364 | ror shift ;1 [-01] [09] 365 | didStuffN: ;- [09] 366 | out USBOUT, x1 ;1 [00] [10] <-- out N 367 | ror x2 ;1 [01] 368 | cpi x2, 0xfc ;1 [02] 369 | brcc bitstuffN ;1 [03] 370 | dec bitcnt ;1 [04] 371 | brne txBitLoop ;1 [05] 372 | sbrs shift, 0 ;1 [06] 373 | eor x1, x4 ;1 [07] 374 | ror shift ;1 [08] 375 | didStuff6: ;- [08] 376 | nop ;1 [09] 377 | out USBOUT, x1 ;1 [00] [10] <-- out 6 378 | ror x2 ;1 [01] 379 | cpi x2, 0xfc ;1 [02] 380 | brcc bitstuff6 ;1 [03] 381 | sbrs shift, 0 ;1 [04] 382 | eor x1, x4 ;1 [05] 383 | ror shift ;1 [06] 384 | ror x2 ;1 [07] 385 | didStuff7: ;- [07] 386 | ldi bitcnt, 6 ;1 [08] 387 | cpi x2, 0xfc ;1 [09] 388 | out USBOUT, x1 ;1 [00] [10] <-- out 7 389 | brcc bitstuff7 ;1 [01] 390 | ld shift, y+ ;2 [02+03] 391 | dec cnt ;1 [04] 392 | brne txBitLoop ;1 [05] 393 | makeSE0: 394 | cbr x1, USBMASK ;1 [06] prepare SE0 [spec says EOP may be 19 to 23 cycles] 395 | lds x2, usbNewDeviceAddr;2 [07+08] 396 | lsl x2 ;1 [09] we compare with left shifted address 397 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 398 | ;set address only after data packet was sent, not after handshake 399 | out USBOUT, x1 ;1 [00] [10] <-- out SE0-- from now 2 bits==20 cycl. until bus idle 400 | subi YL, 20 + 2 ;1 [01] Only assign address on data packets, not ACK/NAK in x3 401 | sbci YH, 0 ;1 [02] 402 | breq skipAddrAssign ;1 [03] 403 | sts usbDeviceAddr, x2 ;2 [04+05] if not skipped: SE0 is one cycle longer 404 | ;---------------------------------------------------------------------------- 405 | ;end of usbDeviceAddress transfer 406 | skipAddrAssign: ;- [03/04] 407 | ldi x2, 1<