├── Bootloader ├── Makefile ├── bootloaderconfig.h ├── main.bin ├── main.c ├── main.hex ├── minipov4all.hex ├── usbconfig.h └── usbdrv │ ├── Changelog.txt │ ├── CommercialLicense.txt │ ├── License.txt │ ├── Readme.txt │ ├── USB-ID-FAQ.txt │ ├── USB-IDs-for-free.txt │ ├── asmcommon.inc │ ├── oddebug.c │ ├── oddebug.h │ ├── usbconfig-prototype.h │ ├── usbdrv.c │ ├── usbdrv.h │ ├── usbdrvasm.S │ ├── usbdrvasm.asm │ ├── usbdrvasm.o │ ├── usbdrvasm12.inc │ ├── usbdrvasm128.inc │ ├── usbdrvasm15.inc │ ├── usbdrvasm16.inc │ ├── usbdrvasm165.inc │ ├── usbdrvasm18-crc.inc │ ├── usbdrvasm20.inc │ └── usbportability.h ├── Firmware ├── MiniPOV4Core.ino ├── debug.cpp └── debug.h ├── Hardware ├── Adafruit MiniPOV4 Kit.brd └── Adafruit MiniPOV4 Kit.sch ├── README.md ├── Software ├── MiniPov4_ImageConverter.pde ├── avrdude ├── avrdude.conf └── avrdude.exe └── Test Images ├── minipov4.png ├── minipov4test.png └── rainbow.png /Bootloader/Makefile: -------------------------------------------------------------------------------- 1 | # Name: Makefile 2 | # Project: VUsbTinyBoot, for MiniPOV4 3 | # Author: Frank Zhao 4 | # Creation Date: 2013-06-06 5 | # Tabsize: 4 6 | # Copyright: (c) 2013 by Adafruit Industries 7 | # License: GNU GPL v2 (see License.txt) 8 | 9 | # This makefile is derived from the USBaspLoader makefile 10 | # works best with AVR GCC 4.2.2 (WinAVR 20071221) 11 | ############################################################################### 12 | # Configure the following variables according to your AVR. 13 | # Program the device with 14 | # make fuse # to set the clock generator, boot section size etc. 15 | # make flash # to load the boot loader into flash 16 | # make lock # to protect the boot loader from overwriting 17 | 18 | F_CPU = 12000000 19 | DEVICE = atmega328p 20 | # if the code size is over 2K (under 4K), the BOOTLOADER_ADDRESS is 1000 for 8K devices, 3000 for 16K and 7000 for 32K 21 | # if the code size is under 2K, the BOOTLOADER_ADDRESS is 1800 for 8K devices, 3800 for 16K and 7800 for 32K 22 | # ATmega8, ATmega88, ATmega168 do not support 4K bootloaders 23 | BOOTLOADER_ADDRESS = 7000 24 | FUSEOPT = $(FUSEOPT_328) 25 | LOCKOPT = -U lock:w:0x2F:m 26 | 27 | PROGRAMMER = -c usbtiny 28 | # PROGRAMMER contains AVRDUDE options to address your programmer 29 | 30 | FUSEOPT_8 = -U hfuse:w:0xD0:m -U lfuse:w:0xBF:m 31 | FUSEOPT_88 = -U hfuse:w:0xD5:m -U lfuse:w:0xFF:m -U efuse:w:0xF8:m 32 | FUSEOPT_168 = -U hfuse:w:0xD5:m -U lfuse:w:0xFF:m -U efuse:w:0xF8:m 33 | FUSEOPT_328 = -U lfuse:w:0xFF:m -U hfuse:w:0xD0:m -U efuse:w:0x05:m 34 | # You may have to change the order of these -U commands. 35 | 36 | ############################################################################### 37 | 38 | # Tools: 39 | AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) 40 | CC = avr-gcc 41 | 42 | # Options: 43 | DEFINES = 44 | # Remove the -fno-* options when you use gcc 3, it does not understand them ( -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions ) 45 | CFLAGS = -Wall -Os -I. -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES) 46 | LDFLAGS = -Wl,--relax,--gc-sections -Wl,--section-start=.text=$(BOOTLOADER_ADDRESS) 47 | 48 | OBJECTS = usbdrv/usbdrvasm.o main.o 49 | 50 | # symbolic targets: 51 | all: main.hex 52 | 53 | .c.o: 54 | $(CC) $(CFLAGS) -c $< -o $@ 55 | 56 | .S.o: 57 | $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ 58 | # "-x assembler-with-cpp" should not be necessary since this is the default 59 | # file type for the .S (with capital S) extension. However, upper case 60 | # characters are not always preserved on Windows. To ensure WinAVR 61 | # compatibility define the file type manually. 62 | 63 | .c.s: 64 | $(CC) $(CFLAGS) -S $< -o $@ 65 | 66 | flash: all 67 | $(AVRDUDE) -B 1 -U flash:w:main.hex:i 68 | 69 | readflash: 70 | $(AVRDUDE) -B 1 -U flash:r:read.hex:i 71 | 72 | fuse: 73 | $(AVRDUDE) $(FUSEOPT) 74 | 75 | lock: 76 | $(AVRDUDE) $(LOCKOPT) 77 | 78 | read_fuses: 79 | $(UISP) --rd_fuses 80 | 81 | clean: 82 | rm -f main.hex main.bin *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s 83 | 84 | # file targets: 85 | main.bin: $(OBJECTS) 86 | $(CC) $(CFLAGS) -o main.bin $(OBJECTS) $(LDFLAGS) 87 | 88 | main.hex: main.bin 89 | rm -f main.hex main.eep.hex 90 | avr-objcopy -j .text -j .data -O ihex main.bin main.hex 91 | avr-size main.hex 92 | 93 | disasm: main.bin 94 | avr-objdump -d main.bin 95 | 96 | cpp: 97 | $(CC) $(CFLAGS) -E main.c 98 | 99 | # Special rules for generating hex files for various devices and clock speeds 100 | ALLHEXFILES = hexfiles/mega8_12mhz.hex hexfiles/mega8_15mhz.hex hexfiles/mega8_16mhz.hex \ 101 | hexfiles/mega88_12mhz.hex hexfiles/mega88_15mhz.hex hexfiles/mega88_16mhz.hex hexfiles/mega88_20mhz.hex\ 102 | hexfiles/mega168_12mhz.hex hexfiles/mega168_15mhz.hex hexfiles/mega168_16mhz.hex hexfiles/mega168_20mhz.hex\ 103 | hexfiles/mega328p_12mhz.hex hexfiles/mega328p_15mhz.hex hexfiles/mega328p_16mhz.hex hexfiles/mega328p_20mhz.hex 104 | 105 | allhexfiles: $(ALLHEXFILES) 106 | $(MAKE) clean 107 | avr-size hexfiles/*.hex 108 | 109 | $(ALLHEXFILES): 110 | @[ -d hexfiles ] || mkdir hexfiles 111 | @device=`echo $@ | sed -e 's|.*/mega||g' -e 's|_.*||g'`; \ 112 | clock=`echo $@ | sed -e 's|.*_||g' -e 's|mhz.*||g'`; \ 113 | addr=`echo $$device | sed -e 's/\([0-9]\)8/\1/g' | awk '{printf("%x", ($$1 - 2) * 1024)}'`; \ 114 | echo "### Make with F_CPU=$${clock}000000 DEVICE=atmega$$device BOOTLOADER_ADDRESS=$$addr"; \ 115 | $(MAKE) clean; \ 116 | $(MAKE) main.hex F_CPU=$${clock}000000 DEVICE=atmega$$device BOOTLOADER_ADDRESS=$$addr DEFINES=-DUSE_AUTOCONFIG=1 117 | mv main.hex $@ 118 | -------------------------------------------------------------------------------- /Bootloader/bootloaderconfig.h: -------------------------------------------------------------------------------- 1 | /* Name: bootloaderconfig.h 2 | * Project: USBaspLoader 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2007-12-08 5 | * Tabsize: 4 6 | * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt) 8 | * This Revision: $Id$ 9 | */ 10 | 11 | /* Modified by me@frank-zhao.com for project VUSBtinyBoot 12 | * 13 | * VUSBtinyBoot is a bootloader that emulates a USBtinyISP (from Adafruit Industries) 14 | * 15 | * MiniPOV4 will use VUSBtinyBoot 16 | * 17 | * This code is heavily derived from USBaspLoader, but also from USBtiny, with USBtinyISP's settings 18 | */ 19 | 20 | #ifndef __bootloaderconfig_h_included__ 21 | #define __bootloaderconfig_h_included__ 22 | 23 | /* 24 | General Description: 25 | This file (together with some settings in Makefile) configures the boot loader 26 | according to the hardware. 27 | 28 | This file contains (besides the hardware configuration normally found in 29 | usbconfig.h) two functions or macros: bootLoaderInit() and 30 | bootLoaderCondition(). Whether you implement them as macros or as static 31 | inline functions is up to you, decide based on code size and convenience. 32 | 33 | bootLoaderInit() is called as one of the first actions after reset. It should 34 | be a minimum initialization of the hardware so that the boot loader condition 35 | can be read. This will usually consist of activating a pull-up resistor for an 36 | external jumper which selects boot loader mode. 37 | 38 | bootLoaderCondition() is called immediately after initialization and in each 39 | main loop iteration. If it returns TRUE, the boot loader will be active. If it 40 | returns FALSE, the boot loader jumps to address 0 (the loaded application) 41 | immediately. 42 | 43 | For compatibility with Thomas Fischl's avrusbboot, we also support the macro 44 | names BOOTLOADER_INIT and BOOTLOADER_CONDITION for this functionality. If 45 | these macros are defined, the boot loader usees them. 46 | */ 47 | 48 | /* ---------------------------- Hardware Config ---------------------------- */ 49 | 50 | #define USB_CFG_IOPORTNAME B 51 | /* This is the port where the USB bus is connected. When you configure it to 52 | * "B", the registers PORTB, PINB and DDRB will be used. 53 | */ 54 | #define USB_CFG_DMINUS_BIT 0 55 | /* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. 56 | * This may be any bit in the port. 57 | */ 58 | #define USB_CFG_DPLUS_BIT 1 59 | /* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. 60 | * This may be any bit in the port. Please note that D+ must also be connected 61 | * to interrupt pin INT0! 62 | */ 63 | #define USB_CFG_CLOCK_KHZ (F_CPU/1000) 64 | /* Clock rate of the AVR in MHz. Legal values are 12000, 16000 or 16500. 65 | * The 16.5 MHz version of the code requires no crystal, it tolerates +/- 1% 66 | * deviation from the nominal frequency. All other rates require a precision 67 | * of 2000 ppm and thus a crystal! 68 | * Default if not specified: 12 MHz 69 | */ 70 | 71 | /* ----------------------- Optional Hardware Config ------------------------ */ 72 | 73 | /* #define USB_CFG_PULLUP_IOPORTNAME D */ 74 | /* If you connect the 1.5k pullup resistor from D- to a port pin instead of 75 | * V+, you can connect and disconnect the device from firmware by calling 76 | * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). 77 | * This constant defines the port on which the pullup resistor is connected. 78 | */ 79 | /* #define USB_CFG_PULLUP_BIT 4 */ 80 | /* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined 81 | * above) where the 1.5k pullup resistor is connected. See description 82 | * above for details. 83 | */ 84 | 85 | #ifndef __ASSEMBLER__ /* assembler cannot parse function definitions */ 86 | 87 | #ifndef MCUCSR /* compatibility between ATMega8 and ATMega88 */ 88 | # define MCUCSR MCUSR 89 | #endif 90 | 91 | #endif /* __ASSEMBLER__ */ 92 | 93 | /* ------------------------------------------------------------------------- */ 94 | 95 | #endif /* __bootloader_h_included__ */ 96 | -------------------------------------------------------------------------------- /Bootloader/main.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-MiniPOV4-Kit/067ae4dcad3fcc97ba4ef02da5cda2650d8b921f/Bootloader/main.bin -------------------------------------------------------------------------------- /Bootloader/main.c: -------------------------------------------------------------------------------- 1 | /* VUSBtinyBoot by me@frank-zhao.com 2 | * 3 | * VUSBtinyBoot is a bootloader that emulates a USBtinyISP (from Adafruit Industries) 4 | * 5 | * MiniPOV4 (from Adafruit Industries) will use VUSBtinyBoot 6 | * 7 | * This code is heavily derived from USBaspLoader, but also from USBtiny, with USBtinyISP's settings 8 | 9 | Copyright (c) 2013 Adafruit Industries 10 | All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions 14 | are met: 15 | 16 | * Redistributions of source code must retain the above copyright 17 | notice, this list of conditions and the following disclaimer. 18 | * Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | * Neither the name of the authors nor the names of its contributors 22 | may be used to endorse or promote products derived from this software 23 | without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #include 39 | #ifndef MCUSR 40 | #define MCUSR MCUCSR // hack for enabling ATmega8 support 41 | #endif 42 | #define SIGRD 5 // this is missing from some of the io.h files, this is a hack so avr/boot.h can be used 43 | #include 44 | #include 45 | //#include 46 | #include 47 | #include 48 | //#include 49 | #include 50 | #include // must be included, because of static function declarations are being used, which saves flash space 51 | 52 | // enable features here 53 | #define ENABLE_FLASH_WRITING 54 | #define ENABLE_FLASH_READING 55 | #define ENABLE_EEPROM_WRITING 56 | #define ENABLE_EEPROM_READING 57 | #define ENABLE_SIG_READING 58 | //#define ENABLE_FUSE_READING 59 | #define ENABLE_REQUEST_EXIT // note: enabling this actually decreases code size 60 | #define ENABLE_CLEAN_EXIT // must be used with ENABLE_REQUEST_EXIT 61 | 62 | enum 63 | { 64 | // Generic requests 65 | USBTINY_ECHO, // echo test 66 | USBTINY_READ, // read byte 67 | USBTINY_WRITE, // write byte 68 | USBTINY_CLR, // clear bit 69 | USBTINY_SET, // set bit 70 | // Programming requests 71 | USBTINY_POWERUP, // apply power (wValue:SCK-period, wIndex:RESET) 72 | USBTINY_POWERDOWN, // remove power from chip 73 | USBTINY_SPI, // issue SPI command (wValue:c1c0, wIndex:c3c2) 74 | USBTINY_POLL_BYTES, // set poll bytes for write (wValue:p1p2) 75 | USBTINY_FLASH_READ, // read flash (wIndex:address) 76 | USBTINY_FLASH_WRITE, // write flash (wIndex:address, wValue:timeout) 77 | USBTINY_EEPROM_READ, // read eeprom (wIndex:address) 78 | USBTINY_EEPROM_WRITE, // write eeprom (wIndex:address, wValue:timeout) 79 | USBTINY_DDRWRITE, // set port direction 80 | USBTINY_SPI1 // a single SPI command 81 | }; 82 | 83 | #if (FLASHEND) > 0xFFFF // need long addressing for large flash 84 | # define CUR_ADDR cur_addr.addr 85 | # define addr_t uint32_t 86 | #else 87 | # define CUR_ADDR cur_addr.u16[0] 88 | # define addr_t uint16_t 89 | #endif 90 | 91 | typedef union longConverter { // utility for manipulating address pointer with proper endianness 92 | addr_t addr; 93 | uint16_t u16[sizeof(addr_t)/2]; 94 | uint8_t u8[sizeof(addr_t)]; 95 | } longConverter_t; 96 | 97 | #ifdef ENABLE_REQUEST_EXIT 98 | static uint8_t req_boot_exit; 99 | #endif 100 | static longConverter_t cur_addr; 101 | static uchar dirty = 0; // if flash needs to be written 102 | static uchar cmd0; // current read/write command byte 103 | static uint8_t remaining; // bytes remaining in current transaction 104 | static uchar buffer[8]; // talk via setup 105 | volatile char usbHasRxed = 0; // whether or not USB comm is active 106 | 107 | void (*app_start)(void) = 0x0000; // function at start of flash memory, call to exit bootloader 108 | 109 | // ---------------------------------------------------------------------- 110 | // finishes a write operation if already started 111 | // ---------------------------------------------------------------------- 112 | static void finalize_flash_if_dirty() 113 | { 114 | if (dirty != 0) 115 | { 116 | #ifdef ENABLE_FLASH_WRITING 117 | cli(); 118 | boot_page_write(CUR_ADDR - 2); 119 | sei(); 120 | boot_spm_busy_wait(); 121 | cli(); 122 | boot_rww_enable(); 123 | sei(); 124 | #endif 125 | dirty = 0; 126 | } 127 | } 128 | 129 | // ---------------------------------------------------------------------- 130 | // Handle a non-standard SETUP packet. 131 | // ---------------------------------------------------------------------- 132 | uchar usbFunctionSetup ( uchar data[8] ) 133 | { 134 | uchar req; 135 | usbRequest_t *rq = (void *)data; 136 | 137 | // Generic requests 138 | req = data[1]; 139 | if ( req == USBTINY_ECHO ) 140 | { 141 | //usbMsgPtr = data; 142 | return 8; 143 | } 144 | /* 145 | else if ( req == USBTINY_SET || req == USBTINY_CLR || req == USBTINY_WRITE || req == USBTINY_DDRWRITE || req == USBTINY_POWERUP) { 146 | // do nothing 147 | return 0; 148 | } 149 | //*/ 150 | else if ( req == USBTINY_READ) { 151 | // do nothing 152 | return 1; 153 | } 154 | else if ( req == USBTINY_POWERDOWN ) 155 | { 156 | finalize_flash_if_dirty(); 157 | #ifdef ENABLE_REQUEST_EXIT 158 | req_boot_exit = 1; 159 | #endif 160 | return 0; 161 | } 162 | else if ( req == USBTINY_SPI ) 163 | { 164 | finalize_flash_if_dirty(); // partial page writes are not fully written unless this is called here, it must be HERE 165 | 166 | usbMsgPtr = (usbMsgPtr_t)buffer; 167 | 168 | // this tricks "usbtiny_cmd" into succeeding 169 | buffer[2] = data[3]; 170 | 171 | // for the commands, refer to ATmega datasheet under "Serial Programming Instruction Set" 172 | // usage of avr/boot.h here is experimental 173 | 174 | #ifdef ENABLE_SIG_READING 175 | if (data[2] == 0x30 && data[3] == 0x00) { 176 | // read signature byte 177 | buffer[3] = boot_signature_byte_get(data[4] * 2); 178 | } 179 | #ifndef ENABLE_FUSE_READING 180 | else 181 | { 182 | buffer[3] = 0; 183 | } 184 | #endif 185 | #endif 186 | #ifdef ENABLE_FUSE_READING 187 | if (data[2] == 0x50 && data[3] == 0x00 && data[4] == 0x00) { 188 | // read LFUSE 189 | buffer[3] = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS); 190 | } 191 | else if (data[2] == 0x58 && data[3] == 0x08 && data[4] == 0x00) { 192 | // read HFUSE 193 | buffer[3] = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS); 194 | } 195 | else if (data[2] == 0x50 && data[3] == 0x08 && data[4] == 0x00) { 196 | // read EFUSE 197 | buffer[3] = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS); 198 | } 199 | else if (data[2] == 0x58 && data[3] == 0x00 && data[4] == 0x00) { 200 | // read lock bits 201 | buffer[3] = boot_lock_fuse_bits_get(GET_LOCK_BITS); 202 | } 203 | else if (data[2] == 0x38 && data[3] == 0x00 && data[4] == 0x00) { 204 | // read calibration 205 | buffer[3] = boot_signature_byte_get(0); 206 | } 207 | #endif 208 | #if !defined(ENABLE_SIG_READING) && !defined(ENABLE_FUSE_READING) 209 | buffer[3] = 0; 210 | #endif 211 | 212 | // all other commands are unhandled 213 | 214 | return 4; 215 | } 216 | else if ( req == USBTINY_SPI1 ) 217 | { 218 | // I don't know what this is used for, there are no single SPI transactions in the ISP protocol 219 | finalize_flash_if_dirty(); 220 | return 1; 221 | } 222 | else if ( req == USBTINY_POLL_BYTES ) 223 | { 224 | finalize_flash_if_dirty(); 225 | return 0; 226 | } 227 | CUR_ADDR = *((uint16_t*)(&data[4])); 228 | remaining = rq->wLength.bytes[0]; 229 | if ( req >= USBTINY_FLASH_READ && req <= USBTINY_EEPROM_WRITE ) 230 | { 231 | cmd0 = req; 232 | if ( cmd0 != USBTINY_FLASH_WRITE ) { 233 | finalize_flash_if_dirty(); 234 | } 235 | return USB_NO_MSG; // usbFunctionRead() or usbFunctionWrite() will be called to handle the data 236 | } 237 | 238 | // do nothing if nothing done 239 | return 0; 240 | } 241 | 242 | // ---------------------------------------------------------------------- 243 | // Handle an IN packet. 244 | // ---------------------------------------------------------------------- 245 | uchar usbFunctionRead ( uchar* data, uchar len ) 246 | { 247 | uchar i; 248 | 249 | if(len > remaining) { 250 | len = remaining; 251 | } 252 | 253 | remaining -= len; 254 | 255 | for ( i = 0; i < len; i++ ) 256 | { 257 | if (cmd0 == USBTINY_EEPROM_READ) { 258 | #ifdef ENABLE_EEPROM_READING 259 | *data = eeprom_read_byte((void *)cur_addr.u16[0]); 260 | #endif 261 | } 262 | else if (cmd0 == USBTINY_FLASH_READ) { 263 | #ifdef ENABLE_FLASH_READING 264 | *data = pgm_read_byte((void *)CUR_ADDR); 265 | #endif 266 | } 267 | data++; 268 | CUR_ADDR++; 269 | } 270 | return len; 271 | } 272 | 273 | // ---------------------------------------------------------------------- 274 | // Handle an OUT packet. 275 | // ---------------------------------------------------------------------- 276 | uchar usbFunctionWrite ( uchar* data, uchar len ) 277 | { 278 | uchar i, isLast; 279 | 280 | if(len > remaining) { 281 | len = remaining; 282 | } 283 | remaining -= len; 284 | isLast = remaining == 0; 285 | 286 | if (cmd0 == USBTINY_EEPROM_WRITE) 287 | { 288 | #ifdef ENABLE_EEPROM_WRITING 289 | for ( i = 0; i < len; i++ ) { 290 | eeprom_write_byte((void *)(cur_addr.u16[0]++), *data++); 291 | } 292 | #endif 293 | } 294 | else if (cmd0 == USBTINY_FLASH_WRITE) 295 | { 296 | #ifdef ENABLE_FLASH_WRITING 297 | for ( i = 0; i < len; ) 298 | { 299 | if ((cur_addr.u16[0] & (SPM_PAGESIZE - 1)) == 0) { 300 | // page start, erase 301 | cli(); 302 | boot_page_erase(CUR_ADDR); 303 | sei(); 304 | boot_spm_busy_wait(); 305 | } 306 | 307 | dirty = 1; 308 | cli(); 309 | boot_page_fill(CUR_ADDR, *(short *)data); 310 | sei(); 311 | 312 | CUR_ADDR += 2; 313 | data += 2; 314 | i += 2; 315 | 316 | if ((cur_addr.u16[0] & (SPM_PAGESIZE - 1)) == 0) { 317 | // end of page 318 | finalize_flash_if_dirty(); 319 | } 320 | } 321 | #endif 322 | } 323 | 324 | return isLast; 325 | } 326 | 327 | // ---------------------------------------------------------------------- 328 | // Bootloader main entry point 329 | // ---------------------------------------------------------------------- 330 | int main ( void ) 331 | { 332 | // disable watchdog if previously enabled 333 | MCUSR &= ~(1 << WDRF); 334 | wdt_disable(); 335 | 336 | MCUCR = (1 << IVCE); // enable change of interrupt vectors 337 | MCUCR = (1 << IVSEL); // move interrupts to boot flash section 338 | 339 | // start 16-bit timer1 340 | TCCR1B = 0x05; 341 | 342 | // start USB and force a re-enumeration by faking a disconnect 343 | usbInit(); 344 | usbDeviceDisconnect(); 345 | while (TCNT1 < 3000); 346 | usbDeviceConnect(); 347 | sei(); 348 | 349 | // make LED output 350 | DDRB |= _BV(5); 351 | PORTB |= _BV(5); 352 | 353 | // main program loop 354 | while (1) 355 | { 356 | usbPoll(); 357 | 358 | if ((usbHasRxed == 0 && TCNT1 >= 0x8900) 359 | #ifdef ENABLE_REQUEST_EXIT 360 | || req_boot_exit != 0 361 | #endif 362 | ) { 363 | // requested exit 364 | // or timed out waiting for activity (timeout means not connected to computer) 365 | break; 366 | } 367 | } 368 | 369 | #if defined(ENABLE_REQUEST_EXIT) && defined(ENABLE_CLEAN_EXIT) 370 | // wait to finish all USB comms, avoids "avrdude: error: usbtiny_transmit: usb_control_msg: sending control message failed" 371 | TCNT1 = 0; while (req_boot_exit != 0 && TCNT1 < 3000) usbPoll(); 372 | #endif 373 | 374 | // cleanup! 375 | 376 | // reset timer 377 | TCCR1B = 0; 378 | TCNT1 = 0; 379 | 380 | // deinitialize USB 381 | USB_INTR_ENABLE = 0; 382 | USB_INTR_CFG = 0; 383 | 384 | // move interrupt back 385 | MCUCR = (1 << IVCE); // enable change of interrupt vectors 386 | MCUCR = (0 << IVSEL); // move interrupts to app flash section 387 | 388 | // make LED input 389 | DDRB &= ~_BV(5); 390 | PORTB &= ~_BV(5); 391 | 392 | cli();// disable interrupts 393 | 394 | app_start(); // jump to user app 395 | 396 | return 0; 397 | } 398 | -------------------------------------------------------------------------------- /Bootloader/main.hex: -------------------------------------------------------------------------------- 1 | :1070000058C000008BC000006FC000006DC00000C1 2 | :107010006BC0000069C0000067C0000065C00000D0 3 | :1070200063C0000061C000005FC000005DC00000E0 4 | :107030005BC0000059C0000057C0000055C00000F0 5 | :1070400053C0000051C000004FC000004DC0000000 6 | :107050004BC0000049C0000047C0000045C0000010 7 | :1070600043C0000041C0000009021200010100807D 8 | :107070003209040000000000000012011001FF00AE 9 | :10708000000881179F0C0501010200011003550043 10 | :1070900053004200740069006E0079001203410041 11 | :1070A00064006100660072007500690074000403EA 12 | :1070B000090411241FBECFEFD8E0DEBFCDBF11E021 13 | :1070C000A0E0B1E0E0EBF8E702C005900D92A2303D 14 | :1070D000B107D9F711E0A2E0B1E001C01D92AE33D3 15 | :1070E000B107E1F771D3E2C38BCFA82FB92F80E0AE 16 | :1070F00090E041E050EA609530E009C02D91822790 17 | :107100009795879510F084279527305EC8F36F5FB9 18 | :10711000A8F30895EADF8D939D930895CF93CFB799 19 | :10712000CF93C395189BE9F7189B09C0189B07C01C 20 | :10713000189B05C0189B03C0189B01C0A1C0DF931A 21 | :10714000C0912101DD27C85DDE4F189B02C0DF9191 22 | :10715000EBCF2F930F931F9303B12FEF00FB20F979 23 | :107160004F933F9313B14FEF012700FB21F93BE011 24 | :1071700031C04E7F012F13B1216028C0102F4D7FE9 25 | :107180002260000003B129C04B7F2460012F000062 26 | :1071900013B12BC013B1477F28602AC04F7E03B1C3 27 | :1071A00020612CC04F7D13B120622FC04F7B03B1F3 28 | :1071B000206432C0422703B149934FEF00001027EB 29 | :1071C00010FB20F913B11370C9F1297F91F2012747 30 | :1071D00000FB21F903B1237F89F2315058F11027C8 31 | :1071E00010FB22F913B1277E79F2012700FB23F966 32 | :1071F0002F7C81F203B1102710FB24F92F7971F253 33 | :1072000000C013B1012700FB25F92F7359F200C00C 34 | :1072100003B1102710FB26F9223040F200C013B151 35 | :10722000012700FB27F9243028F64F77206813B197 36 | :107230000000F9CF11E01CBB002717C03B5031956F 37 | :10724000C31BD04011E01CBB0881033CE9F00B34A8 38 | :10725000D9F020911F011981110F1213EDCF0936BA 39 | :1072600041F10D3211F0013E39F7009326013F91B3 40 | :107270004F911F910F912F91DF91CCB3C0FD51CF52 41 | :10728000CF91CFBFCF91189520912601222379F37A 42 | :1072900010912401112311F5343012F1309324019F 43 | :1072A00020932001109121013BE0311B30932101FB 44 | :1072B00017C00091240101308CF40AE530910001DF 45 | :1072C00034FD10C000930001C4E1D1E00FC0279548 46 | :1072D000A8F45150A9F4220F0000F9CF4AE503C0E9 47 | :1072E00042ED01C0432FC4E1D0E032E014B113609D 48 | :1072F000289A14B905B120E413E05F93012756E002 49 | :1073000005B9279520F4515021F4220FF9CF012718 50 | :1073100056E000003B5A05B9D0F2279528F45150A9 51 | :1073200029F4220F0000F9CF012756E0279505B96F 52 | :1073300020F4515021F4220FF9CF012756E0299172 53 | :10734000332305B921F60C7F10912501110FC65189 54 | :10735000D04005B911F010931F0111E01CBB016072 55 | :1073600014B11C7F402F4C7F5F9100C000C005B955 56 | :1073700014B945B97CCF809113018823B1F0F894FA 57 | :10738000E0910F01F0911001329785E08093570052 58 | :10739000E895789407B600FCFDCFF89481E18093DE 59 | :1073A0005700E8957894109213010895AF92BF9218 60 | :1073B000CF92DF92EF92FF920F931F93CF93DF93C1 61 | :1073C0001F92CDB7DEB780912401835087FD54C151 62 | :1073D000909121014CE0A42EB12CA91AB10828E209 63 | :1073E00031E0A20EB31E11E0109304019091200130 64 | :1073F0009D3209F0D0C0883009F03CC183EC809305 65 | :1074000014018AE58093000110920601D5018C9148 66 | :10741000807609F450C011962C91222309F4BEC144 67 | :10742000213009F4BDC1263021F4A5DF10930501F8 68 | :1074300028C02730F9F49FDF87E091E09093230183 69 | :1074400080932201F5018381809309019281903319 70 | :1074500069F481110BC0E481F0E0EE0FFF1F81E2BF 71 | :1074600080935700E491E0930A0102C010920A0150 72 | :1074700024E083C02E3011F47EDF92C1283019F44D 73 | :107480007ADF20E07AC0D50114968D919C911597F2 74 | :107490009093100180930F0116968C9180931101A7 75 | :1074A000822F8950843068F7209312012A3009F422 76 | :1074B00079C161DF77C1F501928110921D0181814F 77 | :1074C000811106C010921E018DE191E022E04AC0B8 78 | :1074D000853019F4909325013BC0863081F5838176 79 | :1074E000813019F48AE790E704C0823041F488E6DD 80 | :1074F00090E7909323018093220122E11CC0833006 81 | :10750000C9F4911108C08EEA90E79093230180930B 82 | :10751000220124E010C0913019F48CE990E7E9CF02 83 | :10752000923041F48CE890E79093230180932201FC 84 | :1075300020E101C020E080E4809306011EC0883075 85 | :1075400059F0893019F49093270102C08A3039F03C 86 | :107550008DE191E020E006C087E291E002C08DE17C 87 | :1075600091E021E0909323018093220106C0F50170 88 | :10757000268180E8809306010BC0D50117968C9177 89 | :107580001797811105C016968C91821708F4282F41 90 | :10759000209301016FC09091060197FF6BC0F0909E 91 | :1075A0001101E82EF81608F4EF2CFE18F0921101E4 92 | :1075B000809112018C30C9F485010FC0F8016191EE 93 | :1075C0008F0180910F01909110019C012F5F3F4F1F 94 | :1075D0003093100120930F015BD1802F8A198E15F3 95 | :1075E00068F3FF2009F444C045C08A30D1F7850113 96 | :1075F00023E0C22EDD24D39435C080910F019091F9 97 | :1076000010018F779927892BF9F0D0921301F89404 98 | :10761000E0910F01F0911001D8018D919D918D01A4 99 | :107620000C01D0925700E8951124789480910F01B5 100 | :107630009091100102969093100180930F018F7723 101 | :107640009927892B79F40DC0F894E0910F01F091FE 102 | :107650001001C0925700E895789407B600FCFDCF62 103 | :10766000D4CF89DE802F8A198E1508F4C6CFB9CF02 104 | :1076700010920101109224018091000184FF83C0C7 105 | :10768000809101018F3F09F47EC0F82E893010F0FF 106 | :1076900098E0F92E8F19809301018091140198E8E8 107 | :1076A000892780931401FF2009F45BC02091060113 108 | :1076B00027FF31C0809111018F1508F4F82E8F1922 109 | :1076C000809311012091120185E1C82E81E0D82E0E 110 | :1076D000EC2C1CC000910F01109110012B3039F4DB 111 | :1076E000C8012983CDD0F6018083298106C02930C5 112 | :1076F00021F4F8018491D6018C93BFEFCB1ADB0AF9 113 | :107700000F5F1F4F1093100100930F018C2D8E19E6 114 | :107710008F1500F323C0809122019091230126FF51 115 | :107720000BC0FC01A5E1B1E02F2D2A0F34913D9350 116 | :1077300031962A13FBCF09C0DC01E5E1F1E02F2DE2 117 | :107740002E0F3D9131932E13FCCF01962F2D2150FA 118 | :10775000820F911D9093230180932201E8E0EF15A1 119 | :1077600060F06F2D85E191E0D5DC8F2D8C5F8C3042 120 | :1077700041F09FEF9093010104C08FEF80930101CE 121 | :107780008EE18093000184E193B1937089F481507C 122 | :10779000D9F71092250110921F010AC028E0EDCE02 123 | :1077A00021E0EBCED5018C9187FDE1CE2FEFE1CE2C 124 | :1077B0000F90DF91CF911F910F91FF90EF90DF908D 125 | :1077C000CF90BF90AF90089584B7877F84BF88E142 126 | :1077D0000FB6F89480936000109260000FBE81E0B5 127 | :1077E00085BF82E085BF85E080938100809169003C 128 | :1077F000826080936900E89A209A80918400909139 129 | :107800008500883B9B40C8F320987894259A2D9A50 130 | :10781000CDDD80910401811107C080918400909199 131 | :1078200085008115994820F480910501882381F312 132 | :10783000109285001092840001C0B8DD809105018E 133 | :10784000882339F08091840090918500883B9B408B 134 | :10785000A0F31092810010928500109284001DBA4E 135 | :107860001092690081E085BF15BE25982D98F89487 136 | :10787000E0910201F0910301099580E090E0089504 137 | :10788000F999FECF92BD81BDF89A992780B50895E8 138 | :10789000262FF999FECF1FBA92BD81BD20BD0FB62C 139 | :1078A000F894FA9AF99A0FBE01960895F894FFCFCA 140 | :0278B0005AFF7D 141 | :040000030000700089 142 | :00000001FF 143 | -------------------------------------------------------------------------------- /Bootloader/usbconfig.h: -------------------------------------------------------------------------------- 1 | /* Name: usbconfig.h 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2005-04-01 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$ 9 | */ 10 | 11 | /* Modified by me@frank-zhao.com for project VUSBtinyBoot 12 | * 13 | * VUSBtinyBoot is a bootloader that emulates a USBtinyISP (from Adafruit Industries) 14 | * 15 | * MiniPOV4 will use VUSBtinyBoot 16 | * 17 | * This code is heavily derived from USBaspLoader, but also from USBtiny, with USBtinyISP's settings 18 | */ 19 | 20 | #ifndef __usbconfig_h_included__ 21 | #define __usbconfig_h_included__ 22 | 23 | /* YOU SHOULD NOT NEED TO MODIFY THIS FILE! All configurations are supposed 24 | * to go into bootloaderconfig.h! 25 | */ 26 | 27 | /* ---------------------------- Hardware Config ---------------------------- */ 28 | 29 | /* All the port and pin assignments, as well as the clock speed and CRC 30 | setting are now in bootloaderconfig.h: */ 31 | 32 | #include "bootloaderconfig.h" 33 | 34 | /* --------------------------- Functional Range ---------------------------- */ 35 | 36 | #define USB_CFG_HAVE_INTRIN_ENDPOINT 0 37 | /* Define this to 1 if you want to compile a version with two endpoints: The 38 | * default control endpoint 0 and an interrupt-in endpoint (any other endpoint 39 | * number). 40 | */ 41 | #define USB_CFG_HAVE_INTRIN_ENDPOINT3 0 42 | /* Define this to 1 if you want to compile a version with three endpoints: The 43 | * default control endpoint 0, an interrupt-in endpoint 3 (or the number 44 | * configured below) and a catch-all default interrupt-in endpoint as above. 45 | * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. 46 | */ 47 | #define USB_CFG_EP3_NUMBER 3 48 | /* If the so-called endpoint 3 is used, it can now be configured to any other 49 | * endpoint number (except 0) with this macro. Default if undefined is 3. 50 | */ 51 | /* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ 52 | /* The above macro defines the startup condition for data toggling on the 53 | * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. 54 | * Since the token is toggled BEFORE sending any data, the first packet is 55 | * sent with the oposite value of this configuration! 56 | */ 57 | #define USB_CFG_IMPLEMENT_HALT 0 58 | /* Define this to 1 if you also want to implement the ENDPOINT_HALT feature 59 | * for endpoint 1 (interrupt endpoint). Although you may not need this feature, 60 | * it is required by the standard. We have made it a config option because it 61 | * bloats the code considerably. 62 | */ 63 | #define USB_CFG_SUPPRESS_INTR_CODE 0 64 | /* Define this to 1 if you want to declare interrupt-in endpoints, but don't 65 | * want to send any data over them. If this macro is defined to 1, functions 66 | * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if 67 | * you need the interrupt-in endpoints in order to comply to an interface 68 | * (e.g. HID), but never want to send any data. This option saves a couple 69 | * of bytes in flash memory and the transmit buffers in RAM. 70 | */ 71 | #define USB_CFG_INTR_POLL_INTERVAL 10 72 | /* If you compile a version with endpoint 1 (interrupt-in), this is the poll 73 | * interval. The value is in milliseconds and must not be less than 10 ms for 74 | * low speed devices. 75 | */ 76 | #ifndef USB_CFG_IS_SELF_POWERED // allow bootloaderconfig.h to override 77 | #define USB_CFG_IS_SELF_POWERED 0 78 | #endif 79 | /* Define this to 1 if the device has its own power supply. Set it to 0 if the 80 | * device is powered from the USB bus. 81 | */ 82 | #ifndef USB_CFG_MAX_BUS_POWER // allow bootloaderconfig.h to override 83 | #define USB_CFG_MAX_BUS_POWER 100 84 | #endif 85 | /* Set this variable to the maximum USB bus power consumption of your device. 86 | * The value is in milliamperes. [It will be divided by two since USB 87 | * communicates power requirements in units of 2 mA.] 88 | */ 89 | #define USB_CFG_IMPLEMENT_FN_WRITE 1 90 | /* Set this to 1 if you want usbFunctionWrite() to be called for control-out 91 | * transfers. Set it to 0 if you don't need it and want to save a couple of 92 | * bytes. 93 | */ 94 | #define USB_CFG_IMPLEMENT_FN_READ 1 95 | /* Set this to 1 if you need to send control replies which are generated 96 | * "on the fly" when usbFunctionRead() is called. If you only want to send 97 | * data from a static buffer, set it to 0 and return the data from 98 | * usbFunctionSetup(). This saves a couple of bytes. 99 | */ 100 | #define USB_CFG_IMPLEMENT_FN_WRITEOUT 0 101 | /* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. 102 | * You must implement the function usbFunctionWriteOut() which receives all 103 | * interrupt/bulk data sent to any endpoint other than 0. The endpoint number 104 | * can be found in 'usbRxToken'. 105 | */ 106 | #define USB_CFG_HAVE_FLOWCONTROL 0 107 | /* Define this to 1 if you want flowcontrol over USB data. See the definition 108 | * of the macros usbDisableAllRequests() and usbEnableAllRequests() in 109 | * usbdrv.h. 110 | */ 111 | #define USB_CFG_DRIVER_FLASH_PAGE 0 112 | /* If the device has more than 64 kBytes of flash, define this to the 64 k page 113 | * where the driver's constants (descriptors) are located. Or in other words: 114 | * Define this to 1 for boot loaders on the ATMega128. 115 | */ 116 | #define USB_CFG_LONG_TRANSFERS 0 117 | /* Define this to 1 if you want to send/receive blocks of more than 254 bytes 118 | * in a single control-in or control-out transfer. Note that the capability 119 | * for long transfers increases the driver size. 120 | */ 121 | #ifndef __ASSEMBLER__ 122 | extern volatile char usbHasRxed; 123 | #endif 124 | #define USB_RX_USER_HOOK(data, len) do { usbHasRxed = 1; } while (0); 125 | /* This macro is a hook if you want to do unconventional things. If it is 126 | * defined, it's inserted at the beginning of received message processing. 127 | * If you eat the received message and don't want default processing to 128 | * proceed, do a return after doing your things. One possible application 129 | * (besides debugging) is to flash a status LED on each packet. 130 | */ 131 | /* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ 132 | /* This macro is a hook if you need to know when an USB RESET occurs. It has 133 | * one parameter which distinguishes between the start of RESET state and its 134 | * end. 135 | */ 136 | /* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */ 137 | /* This macro (if defined) is executed when a USB SET_ADDRESS request was 138 | * received. 139 | */ 140 | #define USB_COUNT_SOF 0 141 | /* define this macro to 1 if you need the global variable "usbSofCount" which 142 | * counts SOF packets. This feature requires that the hardware interrupt is 143 | * connected to D- instead of D+. 144 | */ 145 | /* #ifdef __ASSEMBLER__ 146 | * macro myAssemblerMacro 147 | * in YL, TCNT0 148 | * sts timer0Snapshot, YL 149 | * endm 150 | * #endif 151 | * #define USB_SOF_HOOK myAssemblerMacro 152 | * This macro (if defined) is executed in the assembler module when a 153 | * Start Of Frame condition is detected. It is recommended to define it to 154 | * the name of an assembler macro which is defined here as well so that more 155 | * than one assembler instruction can be used. The macro may use the register 156 | * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages 157 | * immediately after an SOF pulse may be lost and must be retried by the host. 158 | * What can you do with this hook? Since the SOF signal occurs exactly every 159 | * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in 160 | * designs running on the internal RC oscillator. 161 | * Please note that Start Of Frame detection works only if D- is wired to the 162 | * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! 163 | */ 164 | #define USB_CFG_CHECK_DATA_TOGGLING 0 165 | /* define this macro to 1 if you want to filter out duplicate data packets 166 | * sent by the host. Duplicates occur only as a consequence of communication 167 | * errors, when the host does not receive an ACK. Please note that you need to 168 | * implement the filtering yourself in usbFunctionWriteOut() and 169 | * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable 170 | * for each control- and out-endpoint to check for duplicate packets. 171 | */ 172 | #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 173 | /* define this macro to 1 if you want the function usbMeasureFrameLength() 174 | * compiled in. This function can be used to calibrate the AVR's RC oscillator. 175 | */ 176 | #define USB_USE_FAST_CRC 0 177 | /* The assembler module has two implementations for the CRC algorithm. One is 178 | * faster, the other is smaller. This CRC routine is only used for transmitted 179 | * messages where timing is not critical. The faster routine needs 31 cycles 180 | * per byte while the smaller one needs 61 to 69 cycles. The faster routine 181 | * may be worth the 32 bytes bigger code size if you transmit lots of data and 182 | * run the AVR close to its limit. 183 | */ 184 | 185 | /* -------------------------- Device Description --------------------------- */ 186 | 187 | #define USB_CFG_VENDOR_ID 0x81, 0x17 /* = 0x16c0 = 5824 = voti.nl */ 188 | /* USB vendor ID for the device, low byte first. If you have registered your 189 | * own Vendor ID, define it here. Otherwise you may use one of obdev's free 190 | * shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! 191 | */ 192 | #define USB_CFG_DEVICE_ID 0x9F, 0x0C /* = 0x05dc = 1500 */ 193 | /* This is the ID of the product, low byte first. It is interpreted in the 194 | * scope of the vendor ID. If you have registered your own VID with usb.org 195 | * or if you have licensed a PID from somebody else, define it here. Otherwise 196 | * you may use one of obdev's free shared VID/PID pairs. See the file 197 | * USB-IDs-for-free.txt for details! 198 | */ 199 | #define USB_CFG_DEVICE_VERSION 0x05, 0x01 200 | /* Version number of the device: Minor number first, then major number. 201 | */ 202 | #define USB_CFG_VENDOR_NAME 'A','d','a','f','r','u','i','t' 203 | #define USB_CFG_VENDOR_NAME_LEN 8 204 | /* These two values define the vendor name returned by the USB device. The name 205 | * must be given as a list of characters under single quotes. The characters 206 | * are interpreted as Unicode (UTF-16) entities. 207 | * If you don't want a vendor name string, undefine these macros. 208 | * ALWAYS define a vendor name containing your Internet domain name if you use 209 | * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for 210 | * details. 211 | */ 212 | #define USB_CFG_DEVICE_NAME 'U','S','B','t','i','n','y' 213 | #define USB_CFG_DEVICE_NAME_LEN 7 214 | /* Same as above for the device name. If you don't want a device name, undefine 215 | * the macros. See the file USB-IDs-for-free.txt before you assign a name if 216 | * you use a shared VID/PID. 217 | */ 218 | /*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ 219 | /*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ 220 | /* Same as above for the serial number. If you don't want a serial number, 221 | * undefine the macros. 222 | * It may be useful to provide the serial number through other means than at 223 | * compile time. See the section about descriptor properties below for how 224 | * to fine tune control over USB descriptors such as the string descriptor 225 | * for the serial number. 226 | */ 227 | #define USB_CFG_DEVICE_CLASS 0xFF /* set to 0 if deferred to interface */ 228 | #define USB_CFG_DEVICE_SUBCLASS 0 229 | /* See USB specification if you want to conform to an existing device class. 230 | * Class 0xff is "vendor specific". 231 | */ 232 | #define USB_CFG_INTERFACE_CLASS 0 /* define class here if not at device level */ 233 | #define USB_CFG_INTERFACE_SUBCLASS 0 234 | #define USB_CFG_INTERFACE_PROTOCOL 0 235 | /* See USB specification if you want to conform to an existing device class or 236 | * protocol. The following classes must be set at interface level: 237 | * HID class is 3, no subclass and protocol required (but may be useful!) 238 | * CDC class is 2, use subclass 2 and protocol 1 for ACM 239 | */ 240 | /* #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 42 */ 241 | /* Define this to the length of the HID report descriptor, if you implement 242 | * an HID device. Otherwise don't define it or define it to 0. 243 | * If you use this define, you must add a PROGMEM character array named 244 | * "usbHidReportDescriptor" to your code which contains the report descriptor. 245 | * Don't forget to keep the array and this define in sync! 246 | */ 247 | 248 | #define USB_PUBLIC static 249 | /* Use the define above if you #include usbdrv.c instead of linking against it. 250 | * This technique saves a couple of bytes in flash memory. 251 | */ 252 | 253 | /* ------------------- Fine Control over USB Descriptors ------------------- */ 254 | /* If you don't want to use the driver's default USB descriptors, you can 255 | * provide our own. These can be provided as (1) fixed length static data in 256 | * flash memory, (2) fixed length static data in RAM or (3) dynamically at 257 | * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more 258 | * information about this function. 259 | * Descriptor handling is configured through the descriptor's properties. If 260 | * no properties are defined or if they are 0, the default descriptor is used. 261 | * Possible properties are: 262 | * + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched 263 | * at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is 264 | * used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if 265 | * you want RAM pointers. 266 | * + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found 267 | * in static memory is in RAM, not in flash memory. 268 | * + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), 269 | * the driver must know the descriptor's length. The descriptor itself is 270 | * found at the address of a well known identifier (see below). 271 | * List of static descriptor names (must be declared PROGMEM if in flash): 272 | * char usbDescriptorDevice[]; 273 | * char usbDescriptorConfiguration[]; 274 | * char usbDescriptorHidReport[]; 275 | * char usbDescriptorString0[]; 276 | * int usbDescriptorStringVendor[]; 277 | * int usbDescriptorStringDevice[]; 278 | * int usbDescriptorStringSerialNumber[]; 279 | * Other descriptors can't be provided statically, they must be provided 280 | * dynamically at runtime. 281 | * 282 | * Descriptor properties are or-ed or added together, e.g.: 283 | * #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) 284 | * 285 | * The following descriptors are defined: 286 | * USB_CFG_DESCR_PROPS_DEVICE 287 | * USB_CFG_DESCR_PROPS_CONFIGURATION 288 | * USB_CFG_DESCR_PROPS_STRINGS 289 | * USB_CFG_DESCR_PROPS_STRING_0 290 | * USB_CFG_DESCR_PROPS_STRING_VENDOR 291 | * USB_CFG_DESCR_PROPS_STRING_PRODUCT 292 | * USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 293 | * USB_CFG_DESCR_PROPS_HID 294 | * USB_CFG_DESCR_PROPS_HID_REPORT 295 | * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) 296 | * 297 | * Note about string descriptors: String descriptors are not just strings, they 298 | * are Unicode strings prefixed with a 2 byte header. Example: 299 | * int serialNumberDescriptor[] = { 300 | * USB_STRING_DESCRIPTOR_HEADER(6), 301 | * 'S', 'e', 'r', 'i', 'a', 'l' 302 | * }; 303 | */ 304 | 305 | #define USB_CFG_DESCR_PROPS_DEVICE 0 306 | #define USB_CFG_DESCR_PROPS_CONFIGURATION 0 307 | #define USB_CFG_DESCR_PROPS_STRINGS 0 308 | #define USB_CFG_DESCR_PROPS_STRING_0 0 309 | #define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 310 | #define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 311 | #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 312 | #define USB_CFG_DESCR_PROPS_HID 0 313 | #define USB_CFG_DESCR_PROPS_HID_REPORT 0 314 | #define USB_CFG_DESCR_PROPS_UNKNOWN 0 315 | 316 | #define usbMsgPtr_t unsigned short // scalar type yields shortest code 317 | 318 | /* ----------------------- Optional MCU Description ------------------------ */ 319 | 320 | /* The following configurations have working defaults in usbdrv.h. You 321 | * usually don't need to set them explicitly. Only if you want to run 322 | * the driver on a device which is not yet supported or with a compiler 323 | * which is not fully supported (such as IAR C) or if you use a differnt 324 | * interrupt than INT0, you may have to define some of these. 325 | */ 326 | /* #define USB_INTR_CFG MCUCR */ 327 | /* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ 328 | /* #define USB_INTR_CFG_CLR 0 */ 329 | /* #define USB_INTR_ENABLE GIMSK */ 330 | /* #define USB_INTR_ENABLE_BIT INT0 */ 331 | /* #define USB_INTR_PENDING GIFR */ 332 | /* #define USB_INTR_PENDING_BIT INTF0 */ 333 | /* #define USB_INTR_VECTOR INT0_vect */ 334 | 335 | #endif /* __usbconfig_h_included__ */ 336 | -------------------------------------------------------------------------------- /Bootloader/usbdrv/Changelog.txt: -------------------------------------------------------------------------------- 1 | This file documents changes in the firmware-only USB driver for atmel's AVR 2 | microcontrollers. New entries are always appended to the end of the file. 3 | Scroll down to the bottom to see the most recent changes. 4 | 5 | 2005-04-01: 6 | - Implemented endpoint 1 as interrupt-in endpoint. 7 | - Moved all configuration options to usbconfig.h which is not part of the 8 | driver. 9 | - Changed interface for usbVendorSetup(). 10 | - Fixed compatibility with ATMega8 device. 11 | - Various minor optimizations. 12 | 13 | 2005-04-11: 14 | - Changed interface to application: Use usbFunctionSetup(), usbFunctionRead() 15 | and usbFunctionWrite() now. Added configuration options to choose which 16 | of these functions to compile in. 17 | - Assembler module delivers receive data non-inverted now. 18 | - Made register and bit names compatible with more AVR devices. 19 | 20 | 2005-05-03: 21 | - Allow address of usbRxBuf on any memory page as long as the buffer does 22 | not cross 256 byte page boundaries. 23 | - Better device compatibility: works with Mega88 now. 24 | - Code optimization in debugging module. 25 | - Documentation updates. 26 | 27 | 2006-01-02: 28 | - Added (free) default Vendor- and Product-IDs bought from voti.nl. 29 | - Added USBID-License.txt file which defines the rules for using the free 30 | shared VID/PID pair. 31 | - Added Readme.txt to the usbdrv directory which clarifies administrative 32 | issues. 33 | 34 | 2006-01-25: 35 | - Added "configured state" to become more standards compliant. 36 | - Added "HALT" state for interrupt endpoint. 37 | - Driver passes the "USB Command Verifier" test from usb.org now. 38 | - Made "serial number" a configuration option. 39 | - Minor optimizations, we now recommend compiler option "-Os" for best 40 | results. 41 | - Added a version number to usbdrv.h 42 | 43 | 2006-02-03: 44 | - New configuration variable USB_BUFFER_SECTION for the memory section where 45 | the USB rx buffer will go. This defaults to ".bss" if not defined. Since 46 | this buffer MUST NOT cross 256 byte pages (not even touch a page at the 47 | end), the user may want to pass a linker option similar to 48 | "-Wl,--section-start=.mybuffer=0x800060". 49 | - Provide structure for usbRequest_t. 50 | - New defines for USB constants. 51 | - Prepared for HID implementations. 52 | - Increased data size limit for interrupt transfers to 8 bytes. 53 | - New macro usbInterruptIsReady() to query interrupt buffer state. 54 | 55 | 2006-02-18: 56 | - Ensure that the data token which is sent as an ack to an OUT transfer is 57 | always zero sized. This fixes a bug where the host reports an error after 58 | sending an out transfer to the device, although all data arrived at the 59 | device. 60 | - Updated docs in usbdrv.h to reflect changed API in usbFunctionWrite(). 61 | 62 | * Release 2006-02-20 63 | 64 | - Give a compiler warning when compiling with debugging turned on. 65 | - Added Oleg Semyonov's changes for IAR-cc compatibility. 66 | - Added new (optional) functions usbDeviceConnect() and usbDeviceDisconnect() 67 | (also thanks to Oleg!). 68 | - Rearranged tests in usbPoll() to save a couple of instructions in the most 69 | likely case that no actions are pending. 70 | - We need a delay between the SET ADDRESS request until the new address 71 | becomes active. This delay was handled in usbPoll() until now. Since the 72 | spec says that the delay must not exceed 2ms, previous versions required 73 | aggressive polling during the enumeration phase. We have now moved the 74 | handling of the delay into the interrupt routine. 75 | - We must not reply with NAK to a SETUP transaction. We can only achieve this 76 | by making sure that the rx buffer is empty when SETUP tokens are expected. 77 | We therefore don't pass zero sized data packets from the status phase of 78 | a transfer to usbPoll(). This change MAY cause troubles if you rely on 79 | receiving a less than 8 bytes long packet in usbFunctionWrite() to 80 | identify the end of a transfer. usbFunctionWrite() will NEVER be called 81 | with a zero length. 82 | 83 | * Release 2006-03-14 84 | 85 | - Improved IAR C support: tiny memory model, more devices 86 | - Added template usbconfig.h file under the name usbconfig-prototype.h 87 | 88 | * Release 2006-03-26 89 | 90 | - Added provision for one more interrupt-in endpoint (endpoint 3). 91 | - Added provision for one interrupt-out endpoint (endpoint 1). 92 | - Added flowcontrol macros for USB. 93 | - Added provision for custom configuration descriptor. 94 | - Allow ANY two port bits for D+ and D-. 95 | - Merged (optional) receive endpoint number into global usbRxToken variable. 96 | - Use USB_CFG_IOPORTNAME instead of USB_CFG_IOPORT. We now construct the 97 | variable name from the single port letter instead of computing the address 98 | of related ports from the output-port address. 99 | 100 | * Release 2006-06-26 101 | 102 | - Updated documentation in usbdrv.h and usbconfig-prototype.h to reflect the 103 | new features. 104 | - Removed "#warning" directives because IAR does not understand them. Use 105 | unused static variables instead to generate a warning. 106 | - Do not include 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 | 298 | - Moved first DBG1() after odDebugInit() in all examples. 299 | - Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes 300 | V-USB compatible with the new "p" suffix devices (e.g. ATMega328p). 301 | - USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any 302 | more). 303 | - New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with 304 | more than 64 kB flash. 305 | - Built-in configuration descriptor allows custom definition for second 306 | endpoint now. 307 | 308 | * Release 2010-07-15 309 | 310 | - Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255 311 | bytes. 312 | - Avoid a compiler warning for unused parameter in usbHandleResetHook() when 313 | compiler option -Wextra is enabled. 314 | - Fixed wrong hex value for some IDs in USB-IDs-for-free.txt. 315 | - Keep a define for USBATTR_BUSPOWER, although the flag does not exist 316 | in USB 1.1 any more. Set it to 0. This is for backward compatibility. 317 | 318 | * Release 2012-01-09 319 | 320 | - Define a separate (defined) type for usbMsgPtr so that projects using a 321 | tiny memory model can define it to an 8 bit type in usbconfig.h. This 322 | change also saves a couple of bytes when using a scalar 16 bit type. 323 | - Inserted "const" keyword for all PROGMEM declarations because new GCC 324 | requires it. 325 | - Fixed problem with dependence of usbportability.h on usbconfig.h. This 326 | problem occurred with IAR CC only. 327 | - Prepared repository for github.com. 328 | 329 | * Release 2012-12-06 -------------------------------------------------------------------------------- /Bootloader/usbdrv/CommercialLicense.txt: -------------------------------------------------------------------------------- 1 | V-USB Driver Software License Agreement 2 | Version 2012-07-09 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 (now flirc.tv, Inc.). Both owners of the Vendor IDs have 41 | obtained these IDs from the USB Implementers Forum, Inc. (www.usb.org). 42 | OBJECTIVE DEVELOPMENT disclaims all liability which might arise from the 43 | 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 | -------------------------------------------------------------------------------- /Bootloader/usbdrv/Readme.txt: -------------------------------------------------------------------------------- 1 | This is the Readme file to Objective Development's firmware-only USB driver 2 | for Atmel AVR microcontrollers. For more information please visit 3 | http://www.obdev.at/vusb/ 4 | 5 | This directory contains the USB firmware only. Copy it as-is to your own 6 | project and add all .c and .S files to your project (these files are marked 7 | with an asterisk in the list below). Then copy usbconfig-prototype.h as 8 | usbconfig.h to your project and edit it according to your configuration. 9 | 10 | 11 | TECHNICAL DOCUMENTATION 12 | ======================= 13 | The technical documentation (API) for the firmware driver is contained in the 14 | file "usbdrv.h". Please read all of it carefully! Configuration options are 15 | documented in "usbconfig-prototype.h". 16 | 17 | The driver consists of the following files: 18 | Readme.txt ............. The file you are currently reading. 19 | Changelog.txt .......... Release notes for all versions of the driver. 20 | usbdrv.h ............... Driver interface definitions and technical docs. 21 | * usbdrv.c ............... High level language part of the driver. Link this 22 | module to your code! 23 | * usbdrvasm.S ............ Assembler part of the driver. This module is mostly 24 | a stub and includes one of the usbdrvasm*.S files 25 | depending on processor clock. Link this module to 26 | your code! 27 | usbdrvasm*.inc ......... Assembler routines for particular clock frequencies. 28 | Included by usbdrvasm.S, don't link it directly! 29 | asmcommon.inc .......... Common assembler routines. Included by 30 | usbdrvasm*.inc, don't link it directly! 31 | usbconfig-prototype.h .. Prototype for your own usbdrv.h file. 32 | * oddebug.c .............. Debug functions. Only used when DEBUG_LEVEL is 33 | defined to a value greater than 0. Link this module 34 | to your code! 35 | oddebug.h .............. Interface definitions of the debug module. 36 | usbportability.h ....... Header with compiler-dependent stuff. 37 | usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this 38 | module instead of usbdrvasm.S when you assembler 39 | with IAR's tools. 40 | License.txt ............ Open Source license for this driver. 41 | CommercialLicense.txt .. Optional commercial license for this driver. 42 | USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs. 43 | USB-IDs-for-free.txt ... List and terms of use for free shared PIDs. 44 | 45 | (*) ... These files should be linked to your project. 46 | 47 | 48 | CPU CORE CLOCK FREQUENCY 49 | ======================== 50 | We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz, 51 | 16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The 52 | actual clock rate must be configured in usbconfig.h. 53 | 54 | 12 MHz Clock 55 | This is the traditional clock rate of V-USB because it's the lowest clock 56 | rate where the timing constraints of the USB spec can be met. 57 | 58 | 15 MHz Clock 59 | Similar to 12 MHz, but some NOPs inserted. On the other hand, the higher clock 60 | rate allows for some loops which make the resulting code size somewhat smaller 61 | than the 12 MHz version. 62 | 63 | 16 MHz Clock 64 | This clock rate has been added for users of the Arduino board and other 65 | ready-made boards which come with a fixed 16 MHz crystal. It's also an option 66 | if you need the slightly higher clock rate for performance reasons. Since 67 | 16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code 68 | is somewhat tricky and has to insert a leap cycle every third byte. 69 | 70 | 12.8 MHz and 16.5 MHz Clock 71 | The assembler modules for these clock rates differ from the other modules 72 | because they have been built for an RC oscillator with only 1% precision. The 73 | receiver code inserts leap cycles to compensate for clock deviations. 1% is 74 | also the precision which can be achieved by calibrating the internal RC 75 | oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL 76 | oscillator can reach 16.5 MHz with the RC oscillator. This includes the very 77 | popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost 78 | all AVRs can reach 12.8 MHz, although this is outside the specified range. 79 | 80 | See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for 81 | code which calibrates the RC oscillator based on the USB frame clock. 82 | 83 | 18 MHz Clock 84 | This module is closer to the USB specification because it performs an on the 85 | fly CRC check for incoming packets. Packets with invalid checksum are 86 | discarded as required by the spec. If you also implement checks for data 87 | PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING 88 | in usbconfig.h for more info), this ensures data integrity. Due to the CRC 89 | tables and alignment requirements, this code is bigger than modules for other 90 | clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1 91 | and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h. 92 | 93 | 20 MHz Clock 94 | This module is for people who won't do it with less than the maximum. Since 95 | 20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code 96 | uses similar tricks as the 16 MHz module to insert leap cycles. 97 | 98 | 99 | USB IDENTIFIERS 100 | =============== 101 | Every USB device needs a vendor- and a product-identifier (VID and PID). VIDs 102 | are obtained from usb.org for a price of 1,500 USD. Once you have a VID, you 103 | can assign PIDs at will. 104 | 105 | Since an entry level cost of 1,500 USD is too high for most small companies 106 | and hobbyists, we provide some VID/PID pairs for free. See the file 107 | USB-IDs-for-free.txt for details. 108 | 109 | Objective Development also has some license offerings which include product 110 | IDs. See http://www.obdev.at/vusb/ for details. 111 | 112 | 113 | DEVELOPMENT SYSTEM 114 | ================== 115 | This driver has been developed and optimized for the GNU compiler version 3 116 | and 4. We recommend that you use the GNU compiler suite because it is freely 117 | available. V-USB has also been ported to the IAR compiler and assembler. It 118 | has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the 119 | "small" and "tiny" memory model. Not every release is tested with IAR CC and 120 | the driver may therefore fail to compile with IAR. Please note that gcc is 121 | more efficient for usbdrv.c because this module has been deliberately 122 | optimized for gcc. 123 | 124 | Gcc version 3 produces smaller code than version 4 due to new optimizing 125 | capabilities which don't always improve things on 8 bit CPUs. The code size 126 | generated by gcc 4 can be reduced with the compiler options 127 | -fno-move-loop-invariants, -fno-tree-scev-cprop and 128 | -fno-inline-small-functions in addition to -Os. On devices with more than 129 | 8k of flash memory, we also recommend the linker option --relax (written as 130 | -Wl,--relax for gcc) to convert absolute calls into relative where possible. 131 | 132 | For more information about optimizing options see: 133 | 134 | http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html 135 | 136 | These optimizations are good for gcc 4.x. Version 3.x of gcc does not support 137 | most of these options and produces good code anyway. 138 | 139 | 140 | USING V-USB FOR FREE 141 | ==================== 142 | The AVR firmware driver is published under the GNU General Public License 143 | Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is 144 | your choice whether you apply the terms of version 2 or version 3. 145 | 146 | If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the 147 | following things IN ADDITION to the obligations from the GPL: 148 | 149 | (1) Publish your entire project on a web site and drop us a note with the URL. 150 | Use the form at http://www.obdev.at/vusb/feedback.html for your submission. 151 | If you don't have a web site, you can publish the project in obdev's 152 | documentation wiki at 153 | http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects. 154 | 155 | (2) Adhere to minimum publication standards. Please include AT LEAST: 156 | - a circuit diagram in PDF, PNG or GIF format 157 | - full source code for the host software 158 | - a Readme.txt file in ASCII format which describes the purpose of the 159 | project and what can be found in which directories and which files 160 | - a reference to http://www.obdev.at/vusb/ 161 | 162 | (3) If you improve the driver firmware itself, please give us a free license 163 | to your modifications for our commercial license offerings. 164 | 165 | 166 | COMMERCIAL LICENSES FOR V-USB 167 | ============================= 168 | If you don't want to publish your source code under the terms of the GPL, 169 | you can simply pay money for V-USB. As an additional benefit you get 170 | USB PIDs for free, reserved exclusively to you. See the file 171 | "CommercialLicense.txt" for details. 172 | 173 | -------------------------------------------------------------------------------- /Bootloader/usbdrv/USB-ID-FAQ.txt: -------------------------------------------------------------------------------- 1 | Version 2012-07-09 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 (now flirc.tv, Inc.). Both VID owners have received their Vendor-ID 111 | 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 | -------------------------------------------------------------------------------- /Bootloader/usbdrv/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, unless ONLY the operating system's default class driver is used. 90 | The serial number string MUST be available at least in USB language 0x0409 91 | (English/US). 92 | 93 | (2) The serial number MUST start with either an Internet domain name (e.g. 94 | "mycompany.com") registered and owned by you, or an e-mail address under your 95 | control (e.g. "myname@gmx.net"), both terminated with a colon (":") character. 96 | You MAY append any string you like for further discrimination of your devices. 97 | 98 | (3) You are responsible for retaining ownership of the domain or e-mail 99 | address for as long as any of your products are in use. 100 | 101 | (5) Application side device look-up MUST be based on the serial number string 102 | in addition to VID/PID matching. The matching must start at the first 103 | character of the serial number string and include the colon character 104 | terminating your domain or e-mail address. It MAY stop anywhere after that. 105 | 106 | (6) For devices which implement a particular USB device class (e.g. HID), the 107 | operating system's default class driver MUST be used. If an operating system 108 | driver for Vendor Class devices is needed, this driver must be libusb or 109 | libusb-win32 (see http://libusb.org/ and 110 | http://libusb-win32.sourceforge.net/). 111 | 112 | (7) If ONLY the operating system's default class driver is used, e.g. for 113 | mice, keyboards, joysticks, CDC or MIDI devices and no discrimination by an 114 | application is needed, the serial number may be omitted. 115 | 116 | 117 | Table if IDs for discrimination by serial number string: 118 | 119 | PID dec (hex) | VID dec (hex) | Description of use 120 | ===============+===============+=========================================== 121 | 10200 (0x27d8) | 5824 (0x16c0) | For Vendor Class devices with libusb 122 | ---------------+---------------+------------------------------------------- 123 | 10201 (0x27d9) | 5824 (0x16c0) | For generic HID class devices (which are 124 | | | NOT mice, keyboards or joysticks) 125 | ---------------+---------------+------------------------------------------- 126 | 10202 (0x27da) | 5824 (0x16c0) | For USB Mice 127 | ---------------+---------------+------------------------------------------- 128 | 10203 (0x27db) | 5824 (0x16c0) | For USB Keyboards 129 | ---------------+---------------+------------------------------------------- 130 | 10204 (0x27dc) | 5824 (0x16c0) | For USB Joysticks 131 | ---------------+---------------+------------------------------------------- 132 | 10205 (0x27dd) | 5824 (0x16c0) | For CDC-ACM class devices (modems) 133 | ---------------+---------------+------------------------------------------- 134 | 10206 (0x27de) | 5824 (0x16c0) | For MIDI class devices 135 | ---------------+---------------+------------------------------------------- 136 | 137 | 138 | ================= 139 | ORIGIN OF USB-IDs 140 | ================= 141 | 142 | OBJECTIVE DEVELOPMENT Software GmbH has obtained all VID/PID pairs listed 143 | here from Wouter van Ooijen (see www.voti.nl) for exclusive disposition. 144 | Wouter van Ooijen has obtained the VID from the USB Implementers Forum, Inc. 145 | (see www.usb.org). The VID is registered for the company name "Van Ooijen 146 | Technische Informatica". 147 | 148 | 149 | ========== 150 | DISCLAIMER 151 | ========== 152 | 153 | OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any 154 | problems which are caused by the shared use of these VID/PID pairs. 155 | -------------------------------------------------------------------------------- /Bootloader/usbdrv/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 | */ 9 | 10 | /* Do not link this file! Link usbdrvasm.S instead, which includes the 11 | * appropriate implementation! 12 | */ 13 | 14 | /* 15 | General Description: 16 | This file contains assembler code which is shared among the USB driver 17 | implementations for different CPU cocks. Since the code must be inserted 18 | in the middle of the module, it's split out into this file and #included. 19 | 20 | Jump destinations called from outside: 21 | sofError: Called when no start sequence was found. 22 | se0: Called when a package has been successfully received. 23 | overflow: Called when receive buffer overflows. 24 | doReturn: Called after sending data. 25 | 26 | Outside jump destinations used by this module: 27 | waitForJ: Called to receive an already arriving packet. 28 | sendAckAndReti: 29 | sendNakAndReti: 30 | sendCntAndReti: 31 | usbSendAndReti: 32 | 33 | The following macros must be defined before this file is included: 34 | .macro POP_STANDARD 35 | .endm 36 | .macro POP_RETI 37 | .endm 38 | */ 39 | 40 | #define token x1 41 | 42 | overflow: 43 | ldi x2, 1< 0 13 | 14 | #warning "Never compile production devices with debugging enabled" 15 | 16 | static void uartPutc(char c) 17 | { 18 | while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */ 19 | ODDBG_UDR = c; 20 | } 21 | 22 | static uchar hexAscii(uchar h) 23 | { 24 | h &= 0xf; 25 | if(h >= 10) 26 | h += 'a' - (uchar)10 - '0'; 27 | h += '0'; 28 | return h; 29 | } 30 | 31 | static void printHex(uchar c) 32 | { 33 | uartPutc(hexAscii(c >> 4)); 34 | uartPutc(hexAscii(c)); 35 | } 36 | 37 | void odDebug(uchar prefix, uchar *data, uchar len) 38 | { 39 | printHex(prefix); 40 | uartPutc(':'); 41 | while(len--){ 42 | uartPutc(' '); 43 | printHex(*data++); 44 | } 45 | uartPutc('\r'); 46 | uartPutc('\n'); 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /Bootloader/usbdrv/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 | */ 9 | 10 | #ifndef __oddebug_h_included__ 11 | #define __oddebug_h_included__ 12 | 13 | /* 14 | General Description: 15 | This module implements a function for debug logs on the serial line of the 16 | AVR microcontroller. Debugging can be configured with the define 17 | 'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging 18 | calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is 19 | 2, DBG1 and DBG2 logs will be printed. 20 | 21 | A debug log consists of a label ('prefix') to indicate which debug log created 22 | the output and a memory block to dump in hex ('data' and 'len'). 23 | */ 24 | 25 | 26 | #ifndef F_CPU 27 | # define F_CPU 12000000 /* 12 MHz */ 28 | #endif 29 | 30 | /* make sure we have the UART defines: */ 31 | #include "usbportability.h" 32 | 33 | #ifndef uchar 34 | # define uchar unsigned char 35 | #endif 36 | 37 | #if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */ 38 | # warning "Debugging disabled because device has no UART" 39 | # undef DEBUG_LEVEL 40 | #endif 41 | 42 | #ifndef DEBUG_LEVEL 43 | # define DEBUG_LEVEL 0 44 | #endif 45 | 46 | /* ------------------------------------------------------------------------- */ 47 | 48 | #if DEBUG_LEVEL > 0 49 | # define DBG1(prefix, data, len) odDebug(prefix, data, len) 50 | #else 51 | # define DBG1(prefix, data, len) 52 | #endif 53 | 54 | #if DEBUG_LEVEL > 1 55 | # define DBG2(prefix, data, len) odDebug(prefix, data, len) 56 | #else 57 | # define DBG2(prefix, data, len) 58 | #endif 59 | 60 | /* ------------------------------------------------------------------------- */ 61 | 62 | #if DEBUG_LEVEL > 0 63 | extern void odDebug(uchar prefix, uchar *data, uchar len); 64 | 65 | /* Try to find our control registers; ATMEL likes to rename these */ 66 | 67 | #if defined UBRR 68 | # define ODDBG_UBRR UBRR 69 | #elif defined UBRRL 70 | # define ODDBG_UBRR UBRRL 71 | #elif defined UBRR0 72 | # define ODDBG_UBRR UBRR0 73 | #elif defined UBRR0L 74 | # define ODDBG_UBRR UBRR0L 75 | #endif 76 | 77 | #if defined UCR 78 | # define ODDBG_UCR UCR 79 | #elif defined UCSRB 80 | # define ODDBG_UCR UCSRB 81 | #elif defined UCSR0B 82 | # define ODDBG_UCR UCSR0B 83 | #endif 84 | 85 | #if defined TXEN 86 | # define ODDBG_TXEN TXEN 87 | #else 88 | # define ODDBG_TXEN TXEN0 89 | #endif 90 | 91 | #if defined USR 92 | # define ODDBG_USR USR 93 | #elif defined UCSRA 94 | # define ODDBG_USR UCSRA 95 | #elif defined UCSR0A 96 | # define ODDBG_USR UCSR0A 97 | #endif 98 | 99 | #if defined UDRE 100 | # define ODDBG_UDRE UDRE 101 | #else 102 | # define ODDBG_UDRE UDRE0 103 | #endif 104 | 105 | #if defined UDR 106 | # define ODDBG_UDR UDR 107 | #elif defined UDR0 108 | # define ODDBG_UDR UDR0 109 | #endif 110 | 111 | static inline void odDebugInit(void) 112 | { 113 | ODDBG_UCR |= (1< max 25 cycles interrupt disable 38 | ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes 39 | ;Numbers in brackets are maximum cycles since SOF. 40 | USB_INTR_VECTOR: 41 | ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt 42 | push YL ;2 [35] push only what is necessary to sync with edge ASAP 43 | in YL, SREG ;1 [37] 44 | push YL ;2 [39] 45 | ;---------------------------------------------------------------------------- 46 | ; Synchronize with sync pattern: 47 | ;---------------------------------------------------------------------------- 48 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 49 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 50 | ;The first part waits at most 1 bit long since we must be in sync pattern. 51 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 52 | ;waitForJ, ensure that this prerequisite is met. 53 | waitForJ: 54 | inc YL 55 | sbis USBIN, USBMINUS 56 | brne waitForJ ; just make sure we have ANY timeout 57 | waitForK: 58 | ;The following code results in a sampling window of 1/4 bit which meets the spec. 59 | sbis USBIN, USBMINUS 60 | rjmp foundK 61 | sbis USBIN, USBMINUS 62 | rjmp foundK 63 | sbis USBIN, USBMINUS 64 | rjmp foundK 65 | sbis USBIN, USBMINUS 66 | rjmp foundK 67 | sbis USBIN, USBMINUS 68 | rjmp foundK 69 | #if USB_COUNT_SOF 70 | lds YL, usbSofCount 71 | inc YL 72 | sts usbSofCount, YL 73 | #endif /* USB_COUNT_SOF */ 74 | #ifdef USB_SOF_HOOK 75 | USB_SOF_HOOK 76 | #endif 77 | rjmp sofError 78 | foundK: 79 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] 80 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 81 | ;are cycles from center of first sync (double K) bit after the instruction 82 | push YH ;2 [2] 83 | lds YL, usbInputBufOffset;2 [4] 84 | clr YH ;1 [5] 85 | subi YL, lo8(-(usbRxBuf));1 [6] 86 | sbci YH, hi8(-(usbRxBuf));1 [7] 87 | 88 | sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] 89 | rjmp haveTwoBitsK ;2 [10] 90 | pop YH ;2 [11] undo the push from before 91 | rjmp waitForK ;2 [13] this was not the end of sync, retry 92 | haveTwoBitsK: 93 | ;---------------------------------------------------------------------------- 94 | ; push more registers and initialize values while we sample the first bits: 95 | ;---------------------------------------------------------------------------- 96 | push shift ;2 [16] 97 | push x1 ;2 [12] 98 | push x2 ;2 [14] 99 | 100 | in x1, USBIN ;1 [17] <-- sample bit 0 101 | ldi shift, 0xff ;1 [18] 102 | bst x1, USBMINUS ;1 [19] 103 | bld shift, 0 ;1 [20] 104 | push x3 ;2 [22] 105 | push cnt ;2 [24] 106 | 107 | in x2, USBIN ;1 [25] <-- sample bit 1 108 | ser x3 ;1 [26] [inserted init instruction] 109 | eor x1, x2 ;1 [27] 110 | bst x1, USBMINUS ;1 [28] 111 | bld shift, 1 ;1 [29] 112 | ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] 113 | rjmp rxbit2 ;2 [32] 114 | 115 | ;---------------------------------------------------------------------------- 116 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 117 | ;---------------------------------------------------------------------------- 118 | 119 | unstuff0: ;1 (branch taken) 120 | andi x3, ~0x01 ;1 [15] 121 | mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit 122 | in x2, USBIN ;1 [17] <-- sample bit 1 again 123 | ori shift, 0x01 ;1 [18] 124 | rjmp didUnstuff0 ;2 [20] 125 | 126 | unstuff1: ;1 (branch taken) 127 | mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit 128 | andi x3, ~0x02 ;1 [22] 129 | ori shift, 0x02 ;1 [23] 130 | nop ;1 [24] 131 | in x1, USBIN ;1 [25] <-- sample bit 2 again 132 | rjmp didUnstuff1 ;2 [27] 133 | 134 | unstuff2: ;1 (branch taken) 135 | andi x3, ~0x04 ;1 [29] 136 | ori shift, 0x04 ;1 [30] 137 | mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit 138 | nop ;1 [32] 139 | in x2, USBIN ;1 [33] <-- sample bit 3 140 | rjmp didUnstuff2 ;2 [35] 141 | 142 | unstuff3: ;1 (branch taken) 143 | in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] 144 | andi x3, ~0x08 ;1 [35] 145 | ori shift, 0x08 ;1 [36] 146 | rjmp didUnstuff3 ;2 [38] 147 | 148 | unstuff4: ;1 (branch taken) 149 | andi x3, ~0x10 ;1 [40] 150 | in x1, USBIN ;1 [41] <-- sample stuffed bit 4 151 | ori shift, 0x10 ;1 [42] 152 | rjmp didUnstuff4 ;2 [44] 153 | 154 | unstuff5: ;1 (branch taken) 155 | andi x3, ~0x20 ;1 [48] 156 | in x2, USBIN ;1 [49] <-- sample stuffed bit 5 157 | ori shift, 0x20 ;1 [50] 158 | rjmp didUnstuff5 ;2 [52] 159 | 160 | unstuff6: ;1 (branch taken) 161 | andi x3, ~0x40 ;1 [56] 162 | in x1, USBIN ;1 [57] <-- sample stuffed bit 6 163 | ori shift, 0x40 ;1 [58] 164 | rjmp didUnstuff6 ;2 [60] 165 | 166 | ; extra jobs done during bit interval: 167 | ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs] 168 | ; bit 1: se0 check 169 | ; bit 2: overflow check 170 | ; bit 3: recovery from delay [bit 0 tasks took too long] 171 | ; bit 4: none 172 | ; bit 5: none 173 | ; bit 6: none 174 | ; bit 7: jump, eor 175 | rxLoop: 176 | eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others 177 | in x1, USBIN ;1 [1] <-- sample bit 0 178 | st y+, x3 ;2 [3] store data 179 | ser x3 ;1 [4] 180 | nop ;1 [5] 181 | eor x2, x1 ;1 [6] 182 | bst x2, USBMINUS;1 [7] 183 | bld shift, 0 ;1 [8] 184 | in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) 185 | andi x2, USBMASK ;1 [10] 186 | breq se0 ;1 [11] SE0 check for bit 1 187 | andi shift, 0xf9 ;1 [12] 188 | didUnstuff0: 189 | breq unstuff0 ;1 [13] 190 | eor x1, x2 ;1 [14] 191 | bst x1, USBMINUS;1 [15] 192 | bld shift, 1 ;1 [16] 193 | rxbit2: 194 | in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) 195 | andi shift, 0xf3 ;1 [18] 196 | breq unstuff1 ;1 [19] do remaining work for bit 1 197 | didUnstuff1: 198 | subi cnt, 1 ;1 [20] 199 | brcs overflow ;1 [21] loop control 200 | eor x2, x1 ;1 [22] 201 | bst x2, USBMINUS;1 [23] 202 | bld shift, 2 ;1 [24] 203 | in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) 204 | andi shift, 0xe7 ;1 [26] 205 | breq unstuff2 ;1 [27] 206 | didUnstuff2: 207 | eor x1, x2 ;1 [28] 208 | bst x1, USBMINUS;1 [29] 209 | bld shift, 3 ;1 [30] 210 | didUnstuff3: 211 | andi shift, 0xcf ;1 [31] 212 | breq unstuff3 ;1 [32] 213 | in x1, USBIN ;1 [33] <-- sample bit 4 214 | eor x2, x1 ;1 [34] 215 | bst x2, USBMINUS;1 [35] 216 | bld shift, 4 ;1 [36] 217 | didUnstuff4: 218 | andi shift, 0x9f ;1 [37] 219 | breq unstuff4 ;1 [38] 220 | nop2 ;2 [40] 221 | in x2, USBIN ;1 [41] <-- sample bit 5 222 | eor x1, x2 ;1 [42] 223 | bst x1, USBMINUS;1 [43] 224 | bld shift, 5 ;1 [44] 225 | didUnstuff5: 226 | andi shift, 0x3f ;1 [45] 227 | breq unstuff5 ;1 [46] 228 | nop2 ;2 [48] 229 | in x1, USBIN ;1 [49] <-- sample bit 6 230 | eor x2, x1 ;1 [50] 231 | bst x2, USBMINUS;1 [51] 232 | bld shift, 6 ;1 [52] 233 | didUnstuff6: 234 | cpi shift, 0x02 ;1 [53] 235 | brlo unstuff6 ;1 [54] 236 | nop2 ;2 [56] 237 | in x2, USBIN ;1 [57] <-- sample bit 7 238 | eor x1, x2 ;1 [58] 239 | bst x1, USBMINUS;1 [59] 240 | bld shift, 7 ;1 [60] 241 | didUnstuff7: 242 | cpi shift, 0x04 ;1 [61] 243 | brsh rxLoop ;2 [63] loop control 244 | unstuff7: 245 | andi x3, ~0x80 ;1 [63] 246 | ori shift, 0x80 ;1 [64] 247 | in x2, USBIN ;1 [65] <-- sample stuffed bit 7 248 | nop ;1 [66] 249 | rjmp didUnstuff7 ;2 [68] 250 | 251 | macro POP_STANDARD ; 12 cycles 252 | pop cnt 253 | pop x3 254 | pop x2 255 | pop x1 256 | pop shift 257 | pop YH 258 | endm 259 | macro POP_RETI ; 5 cycles 260 | pop YL 261 | out SREG, YL 262 | pop YL 263 | endm 264 | 265 | #include "asmcommon.inc" 266 | 267 | ;---------------------------------------------------------------------------- 268 | ; Transmitting data 269 | ;---------------------------------------------------------------------------- 270 | 271 | txByteLoop: 272 | txBitloop: 273 | stuffN1Delay: ; [03] 274 | ror shift ;[-5] [11] [59] 275 | brcc doExorN1 ;[-4] [60] 276 | subi x4, 1 ;[-3] 277 | brne commonN1 ;[-2] 278 | lsl shift ;[-1] compensate ror after rjmp stuffDelay 279 | nop ;[00] stuffing consists of just waiting 8 cycles 280 | rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear 281 | 282 | sendNakAndReti: ;0 [-19] 19 cycles until SOP 283 | ldi x3, USBPID_NAK ;1 [-18] 284 | rjmp usbSendX3 ;2 [-16] 285 | sendAckAndReti: ;0 [-19] 19 cycles until SOP 286 | ldi x3, USBPID_ACK ;1 [-18] 287 | rjmp usbSendX3 ;2 [-16] 288 | sendCntAndReti: ;0 [-17] 17 cycles until SOP 289 | mov x3, cnt ;1 [-16] 290 | usbSendX3: ;0 [-16] 291 | ldi YL, 20 ;1 [-15] 'x3' is R20 292 | ldi YH, 0 ;1 [-14] 293 | ldi cnt, 2 ;1 [-13] 294 | ; rjmp usbSendAndReti fallthrough 295 | 296 | ; USB spec says: 297 | ; idle = J 298 | ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 299 | ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 300 | ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) 301 | 302 | ;usbSend: 303 | ;pointer to data in 'Y' 304 | ;number of bytes in 'cnt' -- including sync byte 305 | ;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] 306 | ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) 307 | usbSendAndReti: 308 | in x2, USBDDR ;[-12] 12 cycles until SOP 309 | ori x2, USBMASK ;[-11] 310 | sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 311 | out USBDDR, x2 ;[-8] <--- acquire bus 312 | in x1, USBOUT ;[-7] port mirror for tx loop 313 | ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror) 314 | ldi x2, USBMASK ;[-5] 315 | push x4 ;[-4] 316 | doExorN1: 317 | eor x1, x2 ;[-2] [06] [62] 318 | ldi x4, 6 ;[-1] [07] [63] 319 | commonN1: 320 | stuffN2Delay: 321 | out USBOUT, x1 ;[00] [08] [64] <--- set bit 322 | ror shift ;[01] 323 | brcc doExorN2 ;[02] 324 | subi x4, 1 ;[03] 325 | brne commonN2 ;[04] 326 | lsl shift ;[05] compensate ror after rjmp stuffDelay 327 | rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear 328 | doExorN2: 329 | eor x1, x2 ;[04] [12] 330 | ldi x4, 6 ;[05] [13] 331 | commonN2: 332 | nop ;[06] [14] 333 | subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1 334 | out USBOUT, x1 ;[08] [16] <--- set bit 335 | brcs txBitloop ;[09] [25] [41] 336 | 337 | stuff6Delay: 338 | ror shift ;[42] [50] 339 | brcc doExor6 ;[43] 340 | subi x4, 1 ;[44] 341 | brne common6 ;[45] 342 | lsl shift ;[46] compensate ror after rjmp stuffDelay 343 | nop ;[47] stuffing consists of just waiting 8 cycles 344 | rjmp stuff6Delay ;[48] after ror, C bit is reliably clear 345 | doExor6: 346 | eor x1, x2 ;[45] [53] 347 | ldi x4, 6 ;[46] 348 | common6: 349 | stuff7Delay: 350 | ror shift ;[47] [55] 351 | out USBOUT, x1 ;[48] <--- set bit 352 | brcc doExor7 ;[49] 353 | subi x4, 1 ;[50] 354 | brne common7 ;[51] 355 | lsl shift ;[52] compensate ror after rjmp stuffDelay 356 | rjmp stuff7Delay ;[53] after ror, C bit is reliably clear 357 | doExor7: 358 | eor x1, x2 ;[51] [59] 359 | ldi x4, 6 ;[52] 360 | common7: 361 | ld shift, y+ ;[53] 362 | tst cnt ;[55] 363 | out USBOUT, x1 ;[56] <--- set bit 364 | brne txByteLoop ;[57] 365 | 366 | ;make SE0: 367 | cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] 368 | lds x2, usbNewDeviceAddr;[59] 369 | lsl x2 ;[61] we compare with left shifted address 370 | subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3 371 | sbci YH, 0 ;[63] 372 | out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle 373 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 374 | ;set address only after data packet was sent, not after handshake 375 | breq skipAddrAssign ;[01] 376 | sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer 377 | skipAddrAssign: 378 | ;end of usbDeviceAddress transfer 379 | ldi x2, 1< 10.6666666 cycles per bit, 85.333333333 cycles per byte 29 | ; Numbers in brackets are clocks counted from center of last sync bit 30 | ; when instruction starts 31 | 32 | USB_INTR_VECTOR: 33 | ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt 34 | push YL ;[-25] push only what is necessary to sync with edge ASAP 35 | in YL, SREG ;[-23] 36 | push YL ;[-22] 37 | push YH ;[-20] 38 | ;---------------------------------------------------------------------------- 39 | ; Synchronize with sync pattern: 40 | ;---------------------------------------------------------------------------- 41 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 42 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 43 | ;The first part waits at most 1 bit long since we must be in sync pattern. 44 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 45 | ;waitForJ, ensure that this prerequisite is met. 46 | waitForJ: 47 | inc YL 48 | sbis USBIN, USBMINUS 49 | brne waitForJ ; just make sure we have ANY timeout 50 | waitForK: 51 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 52 | sbis USBIN, USBMINUS ;[-15] 53 | rjmp foundK ;[-14] 54 | sbis USBIN, USBMINUS 55 | rjmp foundK 56 | sbis USBIN, USBMINUS 57 | rjmp foundK 58 | sbis USBIN, USBMINUS 59 | rjmp foundK 60 | sbis USBIN, USBMINUS 61 | rjmp foundK 62 | sbis USBIN, USBMINUS 63 | rjmp foundK 64 | #if USB_COUNT_SOF 65 | lds YL, usbSofCount 66 | inc YL 67 | sts usbSofCount, YL 68 | #endif /* USB_COUNT_SOF */ 69 | #ifdef USB_SOF_HOOK 70 | USB_SOF_HOOK 71 | #endif 72 | rjmp sofError 73 | foundK: ;[-12] 74 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] 75 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 76 | ;are cycles from center of first sync (double K) bit after the instruction 77 | push bitcnt ;[-12] 78 | ; [---] ;[-11] 79 | lds YL, usbInputBufOffset;[-10] 80 | ; [---] ;[-9] 81 | clr YH ;[-8] 82 | subi YL, lo8(-(usbRxBuf));[-7] [rx loop init] 83 | sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init] 84 | push shift ;[-5] 85 | ; [---] ;[-4] 86 | ldi bitcnt, 0x55 ;[-3] [rx loop init] 87 | sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) 88 | rjmp haveTwoBitsK ;[-1] 89 | pop shift ;[0] undo the push from before 90 | pop bitcnt ;[2] undo the push from before 91 | rjmp waitForK ;[4] this was not the end of sync, retry 92 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 93 | ; bit times (= 21 cycles). 94 | 95 | ;---------------------------------------------------------------------------- 96 | ; push more registers and initialize values while we sample the first bits: 97 | ;---------------------------------------------------------------------------- 98 | haveTwoBitsK: 99 | push x1 ;[1] 100 | push x2 ;[3] 101 | push x3 ;[5] 102 | ldi shift, 0 ;[7] 103 | ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that 104 | push x4 ;[9] == leap 105 | 106 | in x1, USBIN ;[11] <-- sample bit 0 107 | andi x1, USBMASK ;[12] 108 | bst x1, USBMINUS ;[13] 109 | bld shift, 7 ;[14] 110 | push cnt ;[15] 111 | ldi leap, 0 ;[17] [rx loop init] 112 | ldi cnt, USB_BUFSIZE;[18] [rx loop init] 113 | rjmp rxbit1 ;[19] arrives at [21] 114 | 115 | ;---------------------------------------------------------------------------- 116 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 117 | ;---------------------------------------------------------------------------- 118 | 119 | ; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap" 120 | ; accordingly to approximate this value in the long run. 121 | 122 | unstuff6: 123 | andi x2, USBMASK ;[03] 124 | ori x3, 1<<6 ;[04] will not be shifted any more 125 | andi shift, ~0x80;[05] 126 | mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6 127 | subi leap, -1 ;[07] total duration = 11 bits -> subtract 1/3 128 | rjmp didUnstuff6 ;[08] 129 | 130 | unstuff7: 131 | ori x3, 1<<7 ;[09] will not be shifted any more 132 | in x2, USBIN ;[00] [10] re-sample bit 7 133 | andi x2, USBMASK ;[01] 134 | andi shift, ~0x80;[02] 135 | subi leap, 2 ;[03] total duration = 10 bits -> add 1/3 136 | rjmp didUnstuff7 ;[04] 137 | 138 | unstuffEven: 139 | ori x3, 1<<6 ;[09] will be shifted right 6 times for bit 0 140 | in x1, USBIN ;[00] [10] 141 | andi shift, ~0x80;[01] 142 | andi x1, USBMASK ;[02] 143 | breq se0 ;[03] 144 | subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3 145 | nop2 ;[05] 146 | rjmp didUnstuffE ;[06] 147 | 148 | unstuffOdd: 149 | ori x3, 1<<5 ;[09] will be shifted right 4 times for bit 1 150 | in x2, USBIN ;[00] [10] 151 | andi shift, ~0x80;[01] 152 | andi x2, USBMASK ;[02] 153 | breq se0 ;[03] 154 | subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3 155 | nop2 ;[05] 156 | rjmp didUnstuffO ;[06] 157 | 158 | rxByteLoop: 159 | andi x1, USBMASK ;[03] 160 | eor x2, x1 ;[04] 161 | subi leap, 1 ;[05] 162 | brpl skipLeap ;[06] 163 | subi leap, -3 ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte 164 | nop ;1 165 | skipLeap: 166 | subi x2, 1 ;[08] 167 | ror shift ;[09] 168 | didUnstuff6: 169 | cpi shift, 0xfc ;[10] 170 | in x2, USBIN ;[00] [11] <-- sample bit 7 171 | brcc unstuff6 ;[01] 172 | andi x2, USBMASK ;[02] 173 | eor x1, x2 ;[03] 174 | subi x1, 1 ;[04] 175 | ror shift ;[05] 176 | didUnstuff7: 177 | cpi shift, 0xfc ;[06] 178 | brcc unstuff7 ;[07] 179 | eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others 180 | st y+, x3 ;[09] store data 181 | rxBitLoop: 182 | in x1, USBIN ;[00] [11] <-- sample bit 0/2/4 183 | andi x1, USBMASK ;[01] 184 | eor x2, x1 ;[02] 185 | andi x3, 0x3f ;[03] topmost two bits reserved for 6 and 7 186 | subi x2, 1 ;[04] 187 | ror shift ;[05] 188 | cpi shift, 0xfc ;[06] 189 | brcc unstuffEven ;[07] 190 | didUnstuffE: 191 | lsr x3 ;[08] 192 | lsr x3 ;[09] 193 | rxbit1: 194 | in x2, USBIN ;[00] [10] <-- sample bit 1/3/5 195 | andi x2, USBMASK ;[01] 196 | breq se0 ;[02] 197 | eor x1, x2 ;[03] 198 | subi x1, 1 ;[04] 199 | ror shift ;[05] 200 | cpi shift, 0xfc ;[06] 201 | brcc unstuffOdd ;[07] 202 | didUnstuffO: 203 | subi bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3 204 | brcs rxBitLoop ;[09] 205 | 206 | subi cnt, 1 ;[10] 207 | in x1, USBIN ;[00] [11] <-- sample bit 6 208 | brcc rxByteLoop ;[01] 209 | rjmp overflow 210 | 211 | macro POP_STANDARD ; 14 cycles 212 | pop cnt 213 | pop x4 214 | pop x3 215 | pop x2 216 | pop x1 217 | pop shift 218 | pop bitcnt 219 | endm 220 | macro POP_RETI ; 7 cycles 221 | pop YH 222 | pop YL 223 | out SREG, YL 224 | pop YL 225 | endm 226 | 227 | #include "asmcommon.inc" 228 | 229 | ; USB spec says: 230 | ; idle = J 231 | ; J = (D+ = 0), (D- = 1) 232 | ; K = (D+ = 1), (D- = 0) 233 | ; Spec allows 7.5 bit times from EOP to SOP for replies 234 | 235 | bitstuffN: 236 | eor x1, x4 ;[5] 237 | ldi x2, 0 ;[6] 238 | nop2 ;[7] 239 | nop ;[9] 240 | out USBOUT, x1 ;[10] <-- out 241 | rjmp didStuffN ;[0] 242 | 243 | bitstuff6: 244 | eor x1, x4 ;[5] 245 | ldi x2, 0 ;[6] Carry is zero due to brcc 246 | rol shift ;[7] compensate for ror shift at branch destination 247 | rjmp didStuff6 ;[8] 248 | 249 | bitstuff7: 250 | ldi x2, 0 ;[2] Carry is zero due to brcc 251 | rjmp didStuff7 ;[3] 252 | 253 | 254 | sendNakAndReti: 255 | ldi x3, USBPID_NAK ;[-18] 256 | rjmp sendX3AndReti ;[-17] 257 | sendAckAndReti: 258 | ldi cnt, USBPID_ACK ;[-17] 259 | sendCntAndReti: 260 | mov x3, cnt ;[-16] 261 | sendX3AndReti: 262 | ldi YL, 20 ;[-15] x3==r20 address is 20 263 | ldi YH, 0 ;[-14] 264 | ldi cnt, 2 ;[-13] 265 | ; rjmp usbSendAndReti fallthrough 266 | 267 | ;usbSend: 268 | ;pointer to data in 'Y' 269 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 270 | ;uses: x1...x4, btcnt, shift, cnt, Y 271 | ;Numbers in brackets are time since first bit of sync pattern is sent 272 | ;We don't match the transfer rate exactly (don't insert leap cycles every third 273 | ;byte) because the spec demands only 1.5% precision anyway. 274 | usbSendAndReti: ; 12 cycles until SOP 275 | in x2, USBDDR ;[-12] 276 | ori x2, USBMASK ;[-11] 277 | sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 278 | in x1, USBOUT ;[-8] port mirror for tx loop 279 | out USBDDR, x2 ;[-7] <- acquire bus 280 | ; need not init x2 (bitstuff history) because sync starts with 0 281 | ldi x4, USBMASK ;[-6] exor mask 282 | ldi shift, 0x80 ;[-5] sync byte is first byte sent 283 | txByteLoop: 284 | ldi bitcnt, 0x35 ;[-4] [6] binary 0011 0101 285 | txBitLoop: 286 | sbrs shift, 0 ;[-3] [7] 287 | eor x1, x4 ;[-2] [8] 288 | out USBOUT, x1 ;[-1] [9] <-- out N 289 | ror shift ;[0] [10] 290 | ror x2 ;[1] 291 | didStuffN: 292 | cpi x2, 0xfc ;[2] 293 | brcc bitstuffN ;[3] 294 | lsr bitcnt ;[4] 295 | brcc txBitLoop ;[5] 296 | brne txBitLoop ;[6] 297 | 298 | sbrs shift, 0 ;[7] 299 | eor x1, x4 ;[8] 300 | didStuff6: 301 | out USBOUT, x1 ;[-1] [9] <-- out 6 302 | ror shift ;[0] [10] 303 | ror x2 ;[1] 304 | cpi x2, 0xfc ;[2] 305 | brcc bitstuff6 ;[3] 306 | ror shift ;[4] 307 | didStuff7: 308 | ror x2 ;[5] 309 | sbrs x2, 7 ;[6] 310 | eor x1, x4 ;[7] 311 | nop ;[8] 312 | cpi x2, 0xfc ;[9] 313 | out USBOUT, x1 ;[-1][10] <-- out 7 314 | brcc bitstuff7 ;[0] [11] 315 | ld shift, y+ ;[1] 316 | dec cnt ;[3] 317 | brne txByteLoop ;[4] 318 | ;make SE0: 319 | cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles] 320 | lds x2, usbNewDeviceAddr;[6] 321 | lsl x2 ;[8] we compare with left shifted address 322 | subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3 323 | sbci YH, 0 ;[10] 324 | out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle 325 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 326 | ;set address only after data packet was sent, not after handshake 327 | breq skipAddrAssign ;[0] 328 | sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer 329 | skipAddrAssign: 330 | ;end of usbDeviceAddress transfer 331 | ldi x2, 1< max 52 cycles interrupt disable 31 | ;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes 32 | ;nominal frequency: 16.5 MHz -> 11 cycles per bit 33 | ; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%) 34 | ; Numbers in brackets are clocks counted from center of last sync bit 35 | ; when instruction starts 36 | 37 | 38 | USB_INTR_VECTOR: 39 | ;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt 40 | push YL ;[-23] push only what is necessary to sync with edge ASAP 41 | in YL, SREG ;[-21] 42 | push YL ;[-20] 43 | ;---------------------------------------------------------------------------- 44 | ; Synchronize with sync pattern: 45 | ;---------------------------------------------------------------------------- 46 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 47 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 48 | ;The first part waits at most 1 bit long since we must be in sync pattern. 49 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 50 | ;waitForJ, ensure that this prerequisite is met. 51 | waitForJ: 52 | inc YL 53 | sbis USBIN, USBMINUS 54 | brne waitForJ ; just make sure we have ANY timeout 55 | waitForK: 56 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 57 | sbis USBIN, USBMINUS ;[-15] 58 | rjmp foundK ;[-14] 59 | sbis USBIN, USBMINUS 60 | rjmp foundK 61 | sbis USBIN, USBMINUS 62 | rjmp foundK 63 | sbis USBIN, USBMINUS 64 | rjmp foundK 65 | sbis USBIN, USBMINUS 66 | rjmp foundK 67 | sbis USBIN, USBMINUS 68 | rjmp foundK 69 | #if USB_COUNT_SOF 70 | lds YL, usbSofCount 71 | inc YL 72 | sts usbSofCount, YL 73 | #endif /* USB_COUNT_SOF */ 74 | #ifdef USB_SOF_HOOK 75 | USB_SOF_HOOK 76 | #endif 77 | rjmp sofError 78 | foundK: ;[-12] 79 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] 80 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 81 | ;are cycles from center of first sync (double K) bit after the instruction 82 | push r0 ;[-12] 83 | ; [---] ;[-11] 84 | push YH ;[-10] 85 | ; [---] ;[-9] 86 | lds YL, usbInputBufOffset;[-8] 87 | ; [---] ;[-7] 88 | clr YH ;[-6] 89 | subi YL, lo8(-(usbRxBuf));[-5] [rx loop init] 90 | sbci YH, hi8(-(usbRxBuf));[-4] [rx loop init] 91 | mov r0, x2 ;[-3] [rx loop init] 92 | sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) 93 | rjmp haveTwoBitsK ;[-1] 94 | pop YH ;[0] undo the pushes from before 95 | pop r0 ;[2] 96 | rjmp waitForK ;[4] this was not the end of sync, retry 97 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 98 | ; bit times (= 22 cycles). 99 | 100 | ;---------------------------------------------------------------------------- 101 | ; push more registers and initialize values while we sample the first bits: 102 | ;---------------------------------------------------------------------------- 103 | haveTwoBitsK: ;[1] 104 | push shift ;[1] 105 | push x1 ;[3] 106 | push x2 ;[5] 107 | push x3 ;[7] 108 | ldi shift, 0xff ;[9] [rx loop init] 109 | ori x3, 0xff ;[10] [rx loop init] == ser x3, clear zero flag 110 | 111 | in x1, USBIN ;[11] <-- sample bit 0 112 | bst x1, USBMINUS ;[12] 113 | bld shift, 0 ;[13] 114 | push x4 ;[14] == phase 115 | ; [---] ;[15] 116 | push cnt ;[16] 117 | ; [---] ;[17] 118 | ldi phase, 0 ;[18] [rx loop init] 119 | ldi cnt, USB_BUFSIZE;[19] [rx loop init] 120 | rjmp rxbit1 ;[20] 121 | ; [---] ;[21] 122 | 123 | ;---------------------------------------------------------------------------- 124 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 125 | ;---------------------------------------------------------------------------- 126 | /* 127 | byte oriented operations done during loop: 128 | bit 0: store data 129 | bit 1: SE0 check 130 | bit 2: overflow check 131 | bit 3: catch up 132 | bit 4: rjmp to achieve conditional jump range 133 | bit 5: PLL 134 | bit 6: catch up 135 | bit 7: jump, fixup bitstuff 136 | ; 87 [+ 2] cycles 137 | ------------------------------------------------------------------ 138 | */ 139 | continueWithBit5: 140 | in x2, USBIN ;[055] <-- bit 5 141 | eor r0, x2 ;[056] 142 | or phase, r0 ;[057] 143 | sbrc phase, USBMINUS ;[058] 144 | lpm ;[059] optional nop3; modifies r0 145 | in phase, USBIN ;[060] <-- phase 146 | eor x1, x2 ;[061] 147 | bst x1, USBMINUS ;[062] 148 | bld shift, 5 ;[063] 149 | andi shift, 0x3f ;[064] 150 | in x1, USBIN ;[065] <-- bit 6 151 | breq unstuff5 ;[066] *** unstuff escape 152 | eor phase, x1 ;[067] 153 | eor x2, x1 ;[068] 154 | bst x2, USBMINUS ;[069] 155 | bld shift, 6 ;[070] 156 | didUnstuff6: ;[ ] 157 | in r0, USBIN ;[071] <-- phase 158 | cpi shift, 0x02 ;[072] 159 | brlo unstuff6 ;[073] *** unstuff escape 160 | didUnstuff5: ;[ ] 161 | nop2 ;[074] 162 | ; [---] ;[075] 163 | in x2, USBIN ;[076] <-- bit 7 164 | eor x1, x2 ;[077] 165 | bst x1, USBMINUS ;[078] 166 | bld shift, 7 ;[079] 167 | didUnstuff7: ;[ ] 168 | eor r0, x2 ;[080] 169 | or phase, r0 ;[081] 170 | in r0, USBIN ;[082] <-- phase 171 | cpi shift, 0x04 ;[083] 172 | brsh rxLoop ;[084] 173 | ; [---] ;[085] 174 | unstuff7: ;[ ] 175 | andi x3, ~0x80 ;[085] 176 | ori shift, 0x80 ;[086] 177 | in x2, USBIN ;[087] <-- sample stuffed bit 7 178 | nop ;[088] 179 | rjmp didUnstuff7 ;[089] 180 | ; [---] ;[090] 181 | ;[080] 182 | 183 | unstuff5: ;[067] 184 | eor phase, x1 ;[068] 185 | andi x3, ~0x20 ;[069] 186 | ori shift, 0x20 ;[070] 187 | in r0, USBIN ;[071] <-- phase 188 | mov x2, x1 ;[072] 189 | nop ;[073] 190 | nop2 ;[074] 191 | ; [---] ;[075] 192 | in x1, USBIN ;[076] <-- bit 6 193 | eor r0, x1 ;[077] 194 | or phase, r0 ;[078] 195 | eor x2, x1 ;[079] 196 | bst x2, USBMINUS ;[080] 197 | bld shift, 6 ;[081] no need to check bitstuffing, we just had one 198 | in r0, USBIN ;[082] <-- phase 199 | rjmp didUnstuff5 ;[083] 200 | ; [---] ;[084] 201 | ;[074] 202 | 203 | unstuff6: ;[074] 204 | andi x3, ~0x40 ;[075] 205 | in x1, USBIN ;[076] <-- bit 6 again 206 | ori shift, 0x40 ;[077] 207 | nop2 ;[078] 208 | ; [---] ;[079] 209 | rjmp didUnstuff6 ;[080] 210 | ; [---] ;[081] 211 | ;[071] 212 | 213 | unstuff0: ;[013] 214 | eor r0, x2 ;[014] 215 | or phase, r0 ;[015] 216 | andi x2, USBMASK ;[016] check for SE0 217 | in r0, USBIN ;[017] <-- phase 218 | breq didUnstuff0 ;[018] direct jump to se0 would be too long 219 | andi x3, ~0x01 ;[019] 220 | ori shift, 0x01 ;[020] 221 | mov x1, x2 ;[021] mov existing sample 222 | in x2, USBIN ;[022] <-- bit 1 again 223 | rjmp didUnstuff0 ;[023] 224 | ; [---] ;[024] 225 | ;[014] 226 | 227 | unstuff1: ;[024] 228 | eor r0, x1 ;[025] 229 | or phase, r0 ;[026] 230 | andi x3, ~0x02 ;[027] 231 | in r0, USBIN ;[028] <-- phase 232 | ori shift, 0x02 ;[029] 233 | mov x2, x1 ;[030] 234 | rjmp didUnstuff1 ;[031] 235 | ; [---] ;[032] 236 | ;[022] 237 | 238 | unstuff2: ;[035] 239 | eor r0, x2 ;[036] 240 | or phase, r0 ;[037] 241 | andi x3, ~0x04 ;[038] 242 | in r0, USBIN ;[039] <-- phase 243 | ori shift, 0x04 ;[040] 244 | mov x1, x2 ;[041] 245 | rjmp didUnstuff2 ;[042] 246 | ; [---] ;[043] 247 | ;[033] 248 | 249 | unstuff3: ;[043] 250 | in x2, USBIN ;[044] <-- bit 3 again 251 | eor r0, x2 ;[045] 252 | or phase, r0 ;[046] 253 | andi x3, ~0x08 ;[047] 254 | ori shift, 0x08 ;[048] 255 | nop ;[049] 256 | in r0, USBIN ;[050] <-- phase 257 | rjmp didUnstuff3 ;[051] 258 | ; [---] ;[052] 259 | ;[042] 260 | 261 | unstuff4: ;[053] 262 | andi x3, ~0x10 ;[054] 263 | in x1, USBIN ;[055] <-- bit 4 again 264 | ori shift, 0x10 ;[056] 265 | rjmp didUnstuff4 ;[057] 266 | ; [---] ;[058] 267 | ;[048] 268 | 269 | rxLoop: ;[085] 270 | eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others 271 | in x1, USBIN ;[000] <-- bit 0 272 | st y+, x3 ;[001] 273 | ; [---] ;[002] 274 | eor r0, x1 ;[003] 275 | or phase, r0 ;[004] 276 | eor x2, x1 ;[005] 277 | in r0, USBIN ;[006] <-- phase 278 | ser x3 ;[007] 279 | bst x2, USBMINUS ;[008] 280 | bld shift, 0 ;[009] 281 | andi shift, 0xf9 ;[010] 282 | rxbit1: ;[ ] 283 | in x2, USBIN ;[011] <-- bit 1 284 | breq unstuff0 ;[012] *** unstuff escape 285 | andi x2, USBMASK ;[013] SE0 check for bit 1 286 | didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff 287 | breq se0 ;[014] 288 | eor r0, x2 ;[015] 289 | or phase, r0 ;[016] 290 | in r0, USBIN ;[017] <-- phase 291 | eor x1, x2 ;[018] 292 | bst x1, USBMINUS ;[019] 293 | bld shift, 1 ;[020] 294 | andi shift, 0xf3 ;[021] 295 | didUnstuff1: ;[ ] 296 | in x1, USBIN ;[022] <-- bit 2 297 | breq unstuff1 ;[023] *** unstuff escape 298 | eor r0, x1 ;[024] 299 | or phase, r0 ;[025] 300 | subi cnt, 1 ;[026] overflow check 301 | brcs overflow ;[027] 302 | in r0, USBIN ;[028] <-- phase 303 | eor x2, x1 ;[029] 304 | bst x2, USBMINUS ;[030] 305 | bld shift, 2 ;[031] 306 | andi shift, 0xe7 ;[032] 307 | didUnstuff2: ;[ ] 308 | in x2, USBIN ;[033] <-- bit 3 309 | breq unstuff2 ;[034] *** unstuff escape 310 | eor r0, x2 ;[035] 311 | or phase, r0 ;[036] 312 | eor x1, x2 ;[037] 313 | bst x1, USBMINUS ;[038] 314 | in r0, USBIN ;[039] <-- phase 315 | bld shift, 3 ;[040] 316 | andi shift, 0xcf ;[041] 317 | didUnstuff3: ;[ ] 318 | breq unstuff3 ;[042] *** unstuff escape 319 | nop ;[043] 320 | in x1, USBIN ;[044] <-- bit 4 321 | eor x2, x1 ;[045] 322 | bst x2, USBMINUS ;[046] 323 | bld shift, 4 ;[047] 324 | didUnstuff4: ;[ ] 325 | eor r0, x1 ;[048] 326 | or phase, r0 ;[049] 327 | in r0, USBIN ;[050] <-- phase 328 | andi shift, 0x9f ;[051] 329 | breq unstuff4 ;[052] *** unstuff escape 330 | rjmp continueWithBit5;[053] 331 | ; [---] ;[054] 332 | 333 | macro POP_STANDARD ; 16 cycles 334 | pop cnt 335 | pop x4 336 | pop x3 337 | pop x2 338 | pop x1 339 | pop shift 340 | pop YH 341 | pop r0 342 | endm 343 | macro POP_RETI ; 5 cycles 344 | pop YL 345 | out SREG, YL 346 | pop YL 347 | endm 348 | 349 | #include "asmcommon.inc" 350 | 351 | 352 | ; USB spec says: 353 | ; idle = J 354 | ; J = (D+ = 0), (D- = 1) 355 | ; K = (D+ = 1), (D- = 0) 356 | ; Spec allows 7.5 bit times from EOP to SOP for replies 357 | 358 | bitstuff7: 359 | eor x1, x4 ;[4] 360 | ldi x2, 0 ;[5] 361 | nop2 ;[6] C is zero (brcc) 362 | rjmp didStuff7 ;[8] 363 | 364 | bitstuffN: 365 | eor x1, x4 ;[5] 366 | ldi x2, 0 ;[6] 367 | lpm ;[7] 3 cycle NOP, modifies r0 368 | out USBOUT, x1 ;[10] <-- out 369 | rjmp didStuffN ;[0] 370 | 371 | #define bitStatus x3 372 | 373 | sendNakAndReti: 374 | ldi cnt, USBPID_NAK ;[-19] 375 | rjmp sendCntAndReti ;[-18] 376 | sendAckAndReti: 377 | ldi cnt, USBPID_ACK ;[-17] 378 | sendCntAndReti: 379 | mov r0, cnt ;[-16] 380 | ldi YL, 0 ;[-15] R0 address is 0 381 | ldi YH, 0 ;[-14] 382 | ldi cnt, 2 ;[-13] 383 | ; rjmp usbSendAndReti fallthrough 384 | 385 | ;usbSend: 386 | ;pointer to data in 'Y' 387 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 388 | ;uses: x1...x4, shift, cnt, Y 389 | ;Numbers in brackets are time since first bit of sync pattern is sent 390 | usbSendAndReti: ; 12 cycles until SOP 391 | in x2, USBDDR ;[-12] 392 | ori x2, USBMASK ;[-11] 393 | sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 394 | in x1, USBOUT ;[-8] port mirror for tx loop 395 | out USBDDR, x2 ;[-7] <- acquire bus 396 | ; need not init x2 (bitstuff history) because sync starts with 0 397 | ldi x4, USBMASK ;[-6] exor mask 398 | ldi shift, 0x80 ;[-5] sync byte is first byte sent 399 | ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes 400 | byteloop: 401 | bitloop: 402 | sbrs shift, 0 ;[8] [-3] 403 | eor x1, x4 ;[9] [-2] 404 | out USBOUT, x1 ;[10] [-1] <-- out 405 | ror shift ;[0] 406 | ror x2 ;[1] 407 | didStuffN: 408 | cpi x2, 0xfc ;[2] 409 | brcc bitstuffN ;[3] 410 | nop ;[4] 411 | subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37 412 | brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value 413 | sbrs shift, 0 ;[7] 414 | eor x1, x4 ;[8] 415 | ror shift ;[9] 416 | didStuff7: 417 | out USBOUT, x1 ;[10] <-- out 418 | ror x2 ;[0] 419 | cpi x2, 0xfc ;[1] 420 | brcc bitstuff7 ;[2] 421 | ld shift, y+ ;[3] 422 | dec cnt ;[5] 423 | brne byteloop ;[6] 424 | ;make SE0: 425 | cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles] 426 | lds x2, usbNewDeviceAddr;[8] 427 | lsl x2 ;[10] we compare with left shifted address 428 | out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle 429 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 430 | ;set address only after data packet was sent, not after handshake 431 | subi YL, 2 ;[0] Only assign address on data packets, not ACK/NAK in r0 432 | sbci YH, 0 ;[1] 433 | breq skipAddrAssign ;[2] 434 | sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer 435 | skipAddrAssign: 436 | ;end of usbDeviceAddress transfer 437 | ldi x2, 1< 13.333333 cycles per bit, 106.666667 cycles per byte 37 | ; Numbers in brackets are clocks counted from center of last sync bit 38 | ; when instruction starts 39 | ;register use in receive loop: 40 | ; shift assembles the byte currently being received 41 | ; x1 holds the D+ and D- line state 42 | ; x2 holds the previous line state 43 | ; x4 (leap) is used to add a leap cycle once every three bytes received 44 | ; X3 (leap2) is used to add a leap cycle once every three stuff bits received 45 | ; bitcnt is used to determine when a stuff bit is due 46 | ; cnt holds the number of bytes left in the receive buffer 47 | 48 | USB_INTR_VECTOR: 49 | ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt 50 | push YL ;[-28] push only what is necessary to sync with edge ASAP 51 | in YL, SREG ;[-26] 52 | push YL ;[-25] 53 | push YH ;[-23] 54 | ;---------------------------------------------------------------------------- 55 | ; Synchronize with sync pattern: 56 | ;---------------------------------------------------------------------------- 57 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 58 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 59 | ;The first part waits at most 1 bit long since we must be in sync pattern. 60 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 61 | ;waitForJ, ensure that this prerequisite is met. 62 | waitForJ: 63 | inc YL 64 | sbis USBIN, USBMINUS 65 | brne waitForJ ; just make sure we have ANY timeout 66 | waitForK: 67 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 68 | sbis USBIN, USBMINUS ;[-19] 69 | rjmp foundK ;[-18] 70 | sbis USBIN, USBMINUS 71 | rjmp foundK 72 | sbis USBIN, USBMINUS 73 | rjmp foundK 74 | sbis USBIN, USBMINUS 75 | rjmp foundK 76 | sbis USBIN, USBMINUS 77 | rjmp foundK 78 | sbis USBIN, USBMINUS 79 | rjmp foundK 80 | sbis USBIN, USBMINUS 81 | rjmp foundK 82 | sbis USBIN, USBMINUS 83 | rjmp foundK 84 | sbis USBIN, USBMINUS 85 | rjmp foundK 86 | #if USB_COUNT_SOF 87 | lds YL, usbSofCount 88 | inc YL 89 | sts usbSofCount, YL 90 | #endif /* USB_COUNT_SOF */ 91 | #ifdef USB_SOF_HOOK 92 | USB_SOF_HOOK 93 | #endif 94 | rjmp sofError 95 | foundK: ;[-16] 96 | ;{3, 5} after falling D- edge, average delay: 4 cycles 97 | ;bit0 should be at 34 for center sampling. Currently at 4 so 30 cylces till bit 0 sample 98 | ;use 1 bit time for setup purposes, then sample again. Numbers in brackets 99 | ;are cycles from center of first sync (double K) bit after the instruction 100 | push bitcnt ;[-16] 101 | ; [---] ;[-15] 102 | lds YL, usbInputBufOffset;[-14] 103 | ; [---] ;[-13] 104 | clr YH ;[-12] 105 | subi YL, lo8(-(usbRxBuf));[-11] [rx loop init] 106 | sbci YH, hi8(-(usbRxBuf));[-10] [rx loop init] 107 | push shift ;[-9] 108 | ; [---] ;[-8] 109 | ldi shift,0x40 ;[-7] set msb to "1" so processing bit7 can be detected 110 | nop2 ;[-6] 111 | ; [---] ;[-5] 112 | ldi bitcnt, 5 ;[-4] [rx loop init] 113 | sbis USBIN, USBMINUS ;[-3] we want two bits K (sample 3 cycles too early) 114 | rjmp haveTwoBitsK ;[-2] 115 | pop shift ;[-1] undo the push from before 116 | pop bitcnt ;[1] 117 | rjmp waitForK ;[3] this was not the end of sync, retry 118 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 119 | ; bit times (= 27 cycles). 120 | 121 | ;---------------------------------------------------------------------------- 122 | ; push more registers and initialize values while we sample the first bits: 123 | ;---------------------------------------------------------------------------- 124 | haveTwoBitsK: 125 | push x1 ;[0] 126 | push x2 ;[2] 127 | push x3 ;[4] (leap2) 128 | ldi leap2, 0x55 ;[6] add leap cycle on 2nd,5th,8th,... stuff bit 129 | push x4 ;[7] == leap 130 | ldi leap, 0x55 ;[9] skip leap cycle on 2nd,5th,8th,... byte received 131 | push cnt ;[10] 132 | ldi cnt, USB_BUFSIZE ;[12] [rx loop init] 133 | ldi x2, 1< 38 | #ifndef __IAR_SYSTEMS_ASM__ 39 | # include 40 | #endif 41 | 42 | #define __attribute__(arg) /* not supported on IAR */ 43 | 44 | #ifdef __IAR_SYSTEMS_ASM__ 45 | # define __ASSEMBLER__ /* IAR does not define standard macro for asm */ 46 | #endif 47 | 48 | #ifdef __HAS_ELPM__ 49 | # define PROGMEM __farflash 50 | #else 51 | # define PROGMEM __flash 52 | #endif 53 | 54 | #define USB_READ_FLASH(addr) (*(PROGMEM char *)(addr)) 55 | 56 | /* The following definitions are not needed by the driver, but may be of some 57 | * help if you port a gcc based project to IAR. 58 | */ 59 | #define cli() __disable_interrupt() 60 | #define sei() __enable_interrupt() 61 | #define wdt_reset() __watchdog_reset() 62 | #define _BV(x) (1 << (x)) 63 | 64 | /* assembler compatibility macros */ 65 | #define nop2 rjmp $+2 /* jump to next instruction */ 66 | #define XL r26 67 | #define XH r27 68 | #define YL r28 69 | #define YH r29 70 | #define ZL r30 71 | #define ZH r31 72 | #define lo8(x) LOW(x) 73 | #define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */ 74 | 75 | /* Depending on the device you use, you may get problems with the way usbdrv.h 76 | * handles the differences between devices. Since IAR does not use #defines 77 | * for MCU registers, we can't check for the existence of a particular 78 | * register with an #ifdef. If the autodetection mechanism fails, include 79 | * definitions for the required USB_INTR_* macros in your usbconfig.h. See 80 | * usbconfig-prototype.h and usbdrv.h for details. 81 | */ 82 | 83 | /* ------------------------------------------------------------------------- */ 84 | #elif __CODEVISIONAVR__ /* check for CodeVision AVR */ 85 | /* ------------------------------------------------------------------------- */ 86 | /* This port is not working (yet) */ 87 | 88 | /* #define F_CPU _MCU_CLOCK_FREQUENCY_ seems to be defined automatically */ 89 | 90 | #include 91 | #include 92 | 93 | #define __attribute__(arg) /* not supported on IAR */ 94 | 95 | #define PROGMEM __flash 96 | #define USB_READ_FLASH(addr) (*(PROGMEM char *)(addr)) 97 | 98 | #ifndef __ASSEMBLER__ 99 | static inline void cli(void) 100 | { 101 | #asm("cli"); 102 | } 103 | static inline void sei(void) 104 | { 105 | #asm("sei"); 106 | } 107 | #endif 108 | #define _delay_ms(t) delay_ms(t) 109 | #define _BV(x) (1 << (x)) 110 | #define USB_CFG_USE_SWITCH_STATEMENT 1 /* macro for if() cascase fails for unknown reason */ 111 | 112 | #define macro .macro 113 | #define endm .endmacro 114 | #define nop2 rjmp .+0 /* jump to next instruction */ 115 | 116 | /* ------------------------------------------------------------------------- */ 117 | #else /* default development environment is avr-gcc/avr-libc */ 118 | /* ------------------------------------------------------------------------- */ 119 | 120 | #include 121 | #ifdef __ASSEMBLER__ 122 | # define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ 123 | #else 124 | # include 125 | #endif 126 | 127 | #if USB_CFG_DRIVER_FLASH_PAGE 128 | # define USB_READ_FLASH(addr) pgm_read_byte_far(((long)USB_CFG_DRIVER_FLASH_PAGE << 16) | (long)(addr)) 129 | #else 130 | # define USB_READ_FLASH(addr) pgm_read_byte(addr) 131 | #endif 132 | 133 | #define macro .macro 134 | #define endm .endm 135 | #define nop2 rjmp .+0 /* jump to next instruction */ 136 | 137 | #endif /* development environment */ 138 | 139 | /* for conveniecne, ensure that PRG_RDB exists */ 140 | #ifndef PRG_RDB 141 | # define PRG_RDB(addr) USB_READ_FLASH(addr) 142 | #endif 143 | #endif /* __usbportability_h_INCLUDED__ */ 144 | -------------------------------------------------------------------------------- /Firmware/MiniPOV4Core.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MiniPOV4 Core firmware, Arduino-esque edition 3 | Written by Frank Zhao for Adafruit Industries 4 | 5 | Project can be opened with Arduino IDE and programmed via USBtiny bootlader 6 | by holding down shift while uploading (select USBtinyISP as programmer) 7 | 8 | Licensed under GPL v2 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "debug.h" 18 | 19 | // enable/disable features here 20 | #define ENABLE_USB_DETECT 21 | 22 | // how many 'color loops' 23 | #define COLORLOOPS 1 24 | 25 | // hardware pin config for higher speeds! 26 | #define LED_CATHODES_DDRx DDRB 27 | #define LED_CATHODES_PORTx PORTB 28 | #define LED_RED_PINNUM 4 29 | #define LED_GREEN_PINNUM 3 30 | #define LED_BLUE_PINNUM 5 31 | 32 | #define LED_8_4_PORTx PORTD 33 | #define LED_3_1_PORTx PORTC 34 | 35 | /// arduino pin defines 36 | #define BLUE 13 37 | #define RED 12 38 | #define GREEN 11 39 | #define LED1 A0 40 | #define LED2 A1 41 | #define LED3 A2 42 | #define LED4 3 43 | #define LED5 4 44 | #define LED6 5 45 | #define LED7 6 46 | #define LED8 7 47 | #define TILTSW 10 48 | #define USBDETECT 8 49 | 50 | #define MINSPEED 100 // actually, the fastest speed 51 | #define MAXSPEED 1000 // actually, the slowest speed 52 | 53 | uint8_t led_anodes[] = {LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8}; 54 | uint8_t led_cathodes[] = {RED, GREEN, BLUE}; 55 | //// 56 | 57 | volatile int ani_length; 58 | volatile int ani_idx; 59 | volatile uint8_t colour_idx = 0; // 0 = R, 1 = G, 2 = B, repeating 60 | volatile uint8_t shade_idx = 0; 61 | volatile byte frame_buffer[8]; 62 | 63 | int speed = 0; 64 | 65 | void setup() 66 | { 67 | Serial.begin(115200); 68 | Serial.println("Welcome to MiniPOV 4!"); 69 | 70 | // pin direction setup 71 | pinMode(RED, OUTPUT); 72 | pinMode(BLUE, OUTPUT); 73 | pinMode(GREEN, OUTPUT); 74 | 75 | pinMode(LED8, OUTPUT); 76 | pinMode(LED7, OUTPUT); 77 | pinMode(LED6, OUTPUT); 78 | pinMode(LED5, OUTPUT); 79 | pinMode(LED4, OUTPUT); 80 | pinMode(LED3, OUTPUT); 81 | pinMode(LED2, OUTPUT); 82 | pinMode(LED1, OUTPUT); 83 | 84 | pinMode(TILTSW, INPUT); 85 | pinMode(USBDETECT, INPUT); 86 | 87 | // setup pull-up resistor 88 | digitalWrite(TILTSW, HIGH); // TILTSWITCH_PORTx |= _BV(TILTSWITCH_PINNUM); 89 | 90 | // default off 91 | digitalWrite(RED, LOW); 92 | digitalWrite(BLUE, LOW);; 93 | digitalWrite(GREEN, LOW); 94 | 95 | digitalWrite(LED1, LOW); 96 | digitalWrite(LED2, LOW); 97 | digitalWrite(LED3, LOW); 98 | digitalWrite(LED4, LOW); 99 | digitalWrite(LED5, LOW); 100 | digitalWrite(LED6, LOW); 101 | digitalWrite(LED7, LOW); 102 | digitalWrite(LED1, LOW); 103 | 104 | digitalWrite(USBDETECT, LOW); 105 | 106 | // Strobe all the LEDs (a nice easy test 107 | for (uint8_t c=0; c<3; c++) { 108 | // turn on one color at a time 109 | digitalWrite(led_cathodes[c], HIGH); 110 | for (uint8_t a=0; a<8; a++) { 111 | // turn on one LED at a time 112 | digitalWrite(led_anodes[a], HIGH); 113 | delay(30); 114 | } 115 | // turn it off 116 | digitalWrite(led_cathodes[c], LOW); 117 | for (uint8_t a=0; a<8; a++) { 118 | digitalWrite(led_anodes[a], LOW); 119 | } 120 | } 121 | 122 | // check the animation length 123 | ani_length = (eeprom_read_byte((uint8_t*)0) << 8) + eeprom_read_byte((uint8_t*)1); 124 | Serial.print("Found a "); Serial.print(ani_length); Serial.println(" byte image"); 125 | 126 | pinMode(10, OUTPUT); 127 | 128 | speed = analogRead(3); 129 | Serial.print("Setting speed to "); Serial.println(speed); 130 | // start timer 131 | TCCR1A = 0; 132 | TCCR1B = _BV(WGM12) | 0x05; 133 | OCR1A = map(speed, 0, 1024, MINSPEED, MAXSPEED); // this should not be lower than 500 134 | TIMSK1 |= _BV(OCIE1A); // Output Compare Interrupt Enable (timer 1, OCR1A) 135 | } 136 | 137 | void loop() 138 | { 139 | // it might seem strange that nothing important happens in this loop 140 | // but it is because timer1's ISR is handling all the LED lighting 141 | // with extreme timing precision 142 | // this allows us to implement 8 bit color PWM shading 143 | 144 | #ifdef ENABLE_USB_DETECT 145 | // if USB connection detected, reset and jump to bootloader 146 | if (digitalRead(USBDETECT)) { 147 | wdt_enable(WDTO_15MS); // force watchdog reset 148 | while (1); 149 | } 150 | #endif // ENABLE_USB_DETECT 151 | 152 | if ( abs(speed - analogRead(3)) > 5) { 153 | speed = analogRead(3); 154 | Serial.print("Setting speed to "); Serial.println(speed); 155 | OCR1A = map(speed, 0, 1024, MINSPEED, MAXSPEED); 156 | } 157 | } 158 | 159 | ISR(TIMER1_COMPA_vect) 160 | { 161 | PORTB |= _BV(2); 162 | // show the next frame 163 | // data format is 164 | // 0bRRRGGGBB, eight of them 165 | uint8_t i, b, cathodeport = 0, ledport = 0; 166 | 167 | // We use direct port access is used instead of Arduino-style 168 | // because this needs to be fast 169 | 170 | if (colour_idx == 0) { 171 | cathodeport = _BV(LED_RED_PINNUM); 172 | 173 | for (i = 0; i < 8; i++) { 174 | b = (frame_buffer[i] & 0xE0) >> 5; 175 | if (b > shade_idx) 176 | ledport |= _BV(i); 177 | } 178 | } 179 | else if (colour_idx == 1) 180 | { 181 | cathodeport = _BV(LED_GREEN_PINNUM); 182 | 183 | for (i = 0; i < 8; i++) { 184 | b = (frame_buffer[i] & 0x1C) >> 2; 185 | if (b > shade_idx) 186 | ledport |= _BV(i); 187 | } 188 | } 189 | else if (colour_idx == 2) 190 | { 191 | cathodeport = _BV(LED_BLUE_PINNUM); 192 | 193 | uint8_t s = shade_idx >> 1; 194 | 195 | for (i = 0; i < 8; i++) { 196 | b = frame_buffer[i] & 0x03; 197 | if (b > s) 198 | ledport |= _BV(i); 199 | } 200 | } 201 | PRINT_F("\n\rLEDport = "); DEBUGPRINT_HEX(ledport); 202 | PRINT_F("\tcathodes = "); DEBUGPRINT_HEX(cathodeport); 203 | LED_3_1_PORTx &= ~(0x07); 204 | LED_8_4_PORTx &= ~(0xF8); 205 | LED_CATHODES_PORTx &= ~_BV(LED_RED_PINNUM) & ~_BV(LED_GREEN_PINNUM) & ~_BV(LED_BLUE_PINNUM); 206 | LED_3_1_PORTx |= ledport & 0x7; 207 | LED_8_4_PORTx |= ledport & 0xF8; 208 | LED_CATHODES_PORTx |= cathodeport; 209 | 210 | // next color 211 | colour_idx++; 212 | if (colour_idx >= 3) { 213 | colour_idx = 0; 214 | shade_idx++; 215 | if (shade_idx >= 7) { 216 | shade_idx = 0; 217 | PRINT_F("New Pixel: "); 218 | // simple next frame with roll over 219 | ani_idx++; 220 | if (ani_idx >= ani_length) { 221 | ani_idx = 0; 222 | } 223 | eeprom_read_block((void*)frame_buffer, (const void*)(2 + (ani_idx * 8)), 8); // load next frame 224 | for (uint8_t p=0; p<8; p++) { 225 | DEBUGPRINT_HEX(frame_buffer[p]); 226 | PRINT_F(", "); 227 | } 228 | } 229 | } 230 | PORTB &= ~_BV(2); 231 | } 232 | 233 | -------------------------------------------------------------------------------- /Firmware/debug.cpp: -------------------------------------------------------------------------------- 1 | #include "debug.h" 2 | 3 | 4 | /**************************************************************************/ 5 | /*! 6 | @brief This function will display the number of bytes currently free 7 | in RAM ... useful for debugging! 8 | */ 9 | /**************************************************************************/ 10 | void displayFreeRam(void) 11 | { 12 | extern int __bss_end; 13 | extern int *__brkval; 14 | int free_memory; 15 | if((int)__brkval == 0) { 16 | free_memory = ((int)&free_memory) - ((int)&__bss_end); 17 | } 18 | else { 19 | free_memory = ((int)&free_memory) - ((int)__brkval); 20 | } 21 | 22 | Serial.print(F("Free RAM: ")); 23 | Serial.print(free_memory); 24 | Serial.println(F(" bytes")); 25 | } 26 | 27 | 28 | void uart_putchar(char c) { 29 | loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */ 30 | UDR0 = c; 31 | } 32 | 33 | void printDec(uint8_t h) { 34 | uart_putchar((h / 100) + '0'); 35 | h %= 100; 36 | uart_putchar((h / 10) + '0'); 37 | h %= 10; 38 | uart_putchar(h + '0'); 39 | } 40 | 41 | 42 | void printHex(uint8_t h) { 43 | uint8_t d = h >> 4; 44 | if (d > 10) { 45 | uart_putchar(d - 10 + 'A'); 46 | } else { 47 | uart_putchar(d + '0'); 48 | } 49 | h &= 0xF; 50 | if (h > 10) { 51 | uart_putchar(h - 10 + 'A'); 52 | } else { 53 | uart_putchar(h + '0'); 54 | } 55 | } 56 | 57 | void printHex16(uint16_t h) { 58 | uart_putchar('0'); 59 | uart_putchar('x'); 60 | DEBUGPRINT_HEX(h >> 8); 61 | DEBUGPRINT_HEX(h); 62 | } 63 | 64 | 65 | void printDec16(uint16_t h) { 66 | uart_putchar((h / 10000) + '0'); 67 | h %= 10000; 68 | uart_putchar((h / 1000) + '0'); 69 | h %= 1000; 70 | uart_putchar((h / 100) + '0'); 71 | h %= 100; 72 | uart_putchar((h / 10) + '0'); 73 | h %= 10; 74 | uart_putchar(h + '0'); 75 | } 76 | 77 | 78 | void DEBUGPRINT(const prog_char *fstr) 79 | { 80 | char c; 81 | if(!fstr) return; 82 | while((c = pgm_read_byte(fstr++))) 83 | uart_putchar(c); 84 | } 85 | -------------------------------------------------------------------------------- /Firmware/debug.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define DEBUG_MODE (1) 5 | 6 | void displayFreeRam(void); 7 | void uart_putchar(char c); 8 | void printHex(uint8_t h); 9 | void printHex16(uint16_t h); 10 | void DEBUGPRINT(const prog_char *fstr); 11 | void printDec(uint8_t h); 12 | void printDec16(uint16_t h); 13 | 14 | #ifndef FLASHIFY 15 | #define FLASHIFY(s) ({static const char c[] __attribute__ ((progmem)) = s;c;}) 16 | #endif 17 | 18 | #define PRINT_F(__s) DEBUGPRINT(FLASHIFY(__s)) 19 | 20 | #if (DEBUG_MODE == 1) 21 | #define DEBUGPRINT_F(__s) DEBUGPRINT(FLASHIFY(__s)) 22 | #define DEBUGPRINT_DEC(x) printDec(x) 23 | #define DEBUGPRINT_DEC16(x) printDec16(x) 24 | #define DEBUGPRINT_HEX(x) printHex(x) 25 | #define DEBUGPRINT_HEX16(x) printHex16(x) 26 | #else 27 | #define DEBUGPRINT_F(__s) /* do nothing! */ 28 | #define DEBUGPRINT_DEC(x) 29 | #define DEBUGPRINT_DEC16(x) 30 | #define DEBUGPRINT_HEX(x) 31 | #define DEBUGPRINT_HEX16(x) 32 | #endif 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MiniPOV4-Kit 2 | ============ 3 | 4 | Files, Firmware and Software for the MiniPOV4 color light-painting kit 5 | Pick up a kit here: https://www.adafruit.com/products/1776 6 | 7 | The latest and greatest MiniPOV kit to hit the streets - MiniPOV4! We have added full color RGB LEDs to the kit as well USB programmability to make this the easiest, most fun Persistence-of-Vision & Light Painting kit ever. 8 | 9 | Learn to solder by building this easy kit. About 30 components are soldered onto the custom PCB using a soldering iron, solder and some basic hand tools such as diagonal cutters and wire strippers. Learn as you go, starting with the easier parts and working your way up to the more challenging ones. Takes about an hour or two to complete following our detailed tutorial, depending on your previous soldering experience. 10 | 11 | * Firmware: The Arduino-IDE compatible firmware that draws images from EEPROM 12 | 13 | * Hardware: PCB files in Eagle CAD format 14 | 15 | * Images: some test pix we use 16 | 17 | * Bootloader: The V-USB based bootloader that lets you program the EEPROM over USB for uploading new images. 18 | 19 | * Software: The image uploader, for use with Processing! -------------------------------------------------------------------------------- /Software/MiniPov4_ImageConverter.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Image Converter for MiniPOV4 3 | by Frank Zhao 4 | 5 | requires Processing 2.0, and the library controlP5 2.0.4 (or later) to be installed 6 | also requires avrdude 5.11 or later, installed somewhere that can be called directly 7 | 8 | version 201306111447: 9 | * 8 bit shading added 10 | * fixed image disappearing upon resize 11 | * TODO: implement size limit, I am waiting for the hardware to be finalized 12 | version 201306101727: 13 | * no upscaling from images smaller than 80pix high 14 | version 201306101542: 15 | * almost all basic functionality works 16 | * shading not supported, so 3 bit color only 17 | 18 | */ 19 | 20 | import controlP5.*; 21 | import javax.swing.*; 22 | import javax.swing.filechooser.*; 23 | import java.awt.image.*; 24 | import javax.imageio.*; 25 | import java.io.*; 26 | import java.util.prefs.*; 27 | import java.awt.event.*; 28 | 29 | ControlP5 cp5; 30 | Preferences prefs; 31 | boolean cp5_isReady = false; 32 | PImage img1, img2; 33 | int imgW; 34 | boolean need_redraw = false; 35 | 36 | void setup() 37 | { 38 | // helps the file dialogs remember the last directory 39 | prefs = Preferences.userNodeForPackage(this.getClass()); 40 | 41 | // this makes the file dialogs look pretty 42 | try { 43 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | size(800, 190); 49 | if (frame != null) { 50 | frame.setResizable(true); 51 | } 52 | 53 | background(0, 0, 0); 54 | 55 | cp5 = new ControlP5(this); 56 | 57 | int x = 10; 58 | int yStart = 10; 59 | int ySpace = 20; 60 | int w = 120; 61 | 62 | cp5.addButton("openImg") 63 | .setLabel("Open Image File") 64 | .setValue(0) 65 | .setPosition(x, yStart + (ySpace * 0)) 66 | .setSize(w, ySpace - 1) 67 | ; 68 | 69 | cp5.addButton("saveBin") 70 | .setLabel("Save as BIN File") 71 | .setValue(0) 72 | .setPosition(x, yStart + (ySpace * 1)) 73 | .setSize(w, ySpace - 1) 74 | ; 75 | 76 | cp5.addButton("openBin") 77 | .setLabel("Open BIN File") 78 | .setValue(0) 79 | .setPosition(x, yStart + (ySpace * 2)) 80 | .setSize(w, ySpace - 1) 81 | ; 82 | 83 | cp5.addButton("download") 84 | .setLabel("Download to MiniPOV4") 85 | .setValue(0) 86 | .setPosition(x, yStart + (ySpace * 3)) 87 | .setSize(w, ySpace - 1) 88 | ; 89 | 90 | println("ready"); 91 | 92 | // this version of controlP5 seems to call the events when the buttons are created, so I have a flag here to prevent that 93 | cp5_isReady = true; 94 | 95 | // resizing the window seems to erase the image, so we detect this event and redraw later 96 | frame.addComponentListener(new ComponentAdapter() 97 | { 98 | public void componentResized(ComponentEvent e) 99 | { 100 | if(e.getSource() == frame) { 101 | need_redraw = true; 102 | } 103 | } 104 | }); 105 | } 106 | 107 | void draw() 108 | { 109 | if (need_redraw) { 110 | // resizing the window seems to erase the image, so we detect this event and redraw later 111 | if (img1 != null) image(img1, 10 + 120 + 10, 10); 112 | if (img2 != null) image(img2, 10 + 120 + 10, 10 + 80 + 10); 113 | need_redraw = false; 114 | } 115 | } 116 | 117 | // this mode only supports 3 bit, so only on and off for each color 118 | color colorDownConvert3(color c) 119 | { 120 | // extract the individual channels 121 | int cred = c >> 16 & 0xFF; 122 | int cgreen = c >> 8 & 0xFF; 123 | int cblue = c >> 0 & 0xFF; 124 | 125 | // do color conversion here 126 | if (cred > 0x7F) cred = 0xFF; else cred = 0x00; 127 | if (cgreen > 0x7F) cgreen = 0xFF; else cgreen = 0x00; 128 | if (cblue > 0x7F) cblue = 0xFF; else cblue = 0x00; 129 | 130 | return color(cred, cgreen, cblue); 131 | } 132 | 133 | // this mode supports 8 bit shading 134 | color colorDownConvert8(color c) 135 | { 136 | // extract the individual channels 137 | int cred = c >> 16 & 0xFF; 138 | int cgreen = c >> 8 & 0xFF; 139 | int cblue = c >> 0 & 0xFF; 140 | 141 | // do color conversion here 142 | cred = cred & 0xE0; 143 | cgreen = cgreen & 0xE0; 144 | cblue = cblue & 0xC0; 145 | if (cred == 0xE0) cred = 0xFF; 146 | if (cgreen == 0xE0) cgreen = 0xFF; 147 | if (cblue == 0xC0) cblue = 0xFF; 148 | 149 | return color(cred, cgreen, cblue); 150 | } 151 | 152 | color colorDownConvert(color c) 153 | { 154 | // change the default conversion mode here 155 | return colorDownConvert8(c); 156 | } 157 | 158 | byte colorToByte(color c) 159 | { 160 | // extract the individual channels 161 | int cred = c >> 16 & 0xFF; 162 | int cgreen = c >> 8 & 0xFF; 163 | int cblue = c >> 0 & 0xFF; 164 | 165 | byte b = 0; 166 | 167 | b += cred & 0xE0; 168 | b += cgreen >> 3 & 0x1C; 169 | b += cblue >> 6 & 0x03; 170 | 171 | return b; 172 | } 173 | 174 | color byteToColor(byte b) 175 | { 176 | int cred, cgreen, cblue; 177 | cred = b & 0xE0; 178 | if (cred >= 0xE0) cred = 0xFF; 179 | cgreen = (b & 0x1C) << 3; 180 | if (cgreen >= 0xE0) cgreen = 0xFF; 181 | cblue = (b & 0x03) << 6; 182 | if (cblue >= 0xC0) cblue = 0xFF; 183 | return color(cred, cgreen, cblue); 184 | } 185 | 186 | public void openImg(int val) 187 | { 188 | if (!cp5_isReady) return; 189 | 190 | println("openImg clicked"); 191 | 192 | final JFileChooser fc = new JFileChooser(); 193 | println("Chooser"); 194 | 195 | try { 196 | fc.setCurrentDirectory(new File(prefs.get("LAST_FILECHOOSER_DIR", ""))); 197 | println("set CD"); 198 | } catch (Exception e) { 199 | e.printStackTrace(); 200 | } 201 | 202 | fc.addChoosableFileFilter(new FileNameExtensionFilter("Image Files", ImageIO.getReaderFileSuffixes())); 203 | println("ChoosableFilter"); 204 | 205 | if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) 206 | { 207 | println("Approved"); 208 | String fp = fc.getSelectedFile().getPath(); 209 | println("file: " + fp); 210 | 211 | prefs.put("LAST_FILECHOOSER_DIR", fc.getSelectedFile().getParent()); 212 | 213 | background(0); 214 | 215 | try { 216 | // generate preview 217 | img1 = loadImage(fp); 218 | int w, h; 219 | w = img1.width; 220 | h = img1.height; 221 | float scale = 80.0f / h; 222 | int nw = round(w * scale); 223 | if (scale < 1.0f) { 224 | img1.resize(nw, 80); 225 | } 226 | image(img1, 10 + 120 + 10, 10); 227 | 228 | // down convert to 8 pixel high 229 | PImage si = loadImage(fp); 230 | scale = 8.0f / h; 231 | imgW = round(w * scale); 232 | si.resize(imgW, 8); 233 | si.loadPixels(); 234 | img2 = new PImage(nw, 80); 235 | 236 | // convert for preview 237 | for (int x = 0; x < nw; x++) 238 | { 239 | for (int y = 0; y < 80; y++) 240 | { 241 | color c = si.get(floor(x / 10.0f), floor(y / 10.0f)); 242 | img2.set(x, y, colorDownConvert(c)); 243 | } 244 | } 245 | 246 | image(img2, 10 + 120 + 10, 10 + 80 + 10); 247 | } 248 | catch (Exception e) { 249 | e.printStackTrace(); 250 | JOptionPane.showMessageDialog(null, "Error while loading image: " + e.getMessage()); 251 | } 252 | } else { 253 | println("???"); 254 | } 255 | } 256 | 257 | boolean saveToBin(String fp) 258 | { 259 | if (img2 == null) { 260 | JOptionPane.showMessageDialog(null, "Error: No Image Loaded"); 261 | return false; 262 | } 263 | 264 | try { 265 | FileOutputStream fstream = new FileOutputStream(fp); 266 | BufferedOutputStream bstream = new BufferedOutputStream(fstream); 267 | DataOutputStream dstream = new DataOutputStream(bstream); 268 | 269 | // first 2 bytes indicate size 270 | dstream.writeShort(imgW); 271 | for (int x = 0; x < imgW; x++) 272 | { 273 | for (int y = 0; y < 8; y++) 274 | { 275 | color c = img2.get(x * 10, y * 10); 276 | byte b = colorToByte(c); 277 | dstream.writeByte(b); 278 | } 279 | } 280 | 281 | dstream.close(); 282 | bstream.close(); 283 | fstream.close(); 284 | return true; 285 | } 286 | catch (Exception e) { 287 | e.printStackTrace(); 288 | JOptionPane.showMessageDialog(null, "Error while writing file: " + e.getMessage()); 289 | return false; 290 | } 291 | } 292 | 293 | public void saveBin(int val) 294 | { 295 | if (!cp5_isReady) return; 296 | 297 | println("saveBin clicked"); 298 | 299 | if (img2 == null) { 300 | JOptionPane.showMessageDialog(null, "Error: No Image Loaded"); 301 | return; 302 | } 303 | 304 | final JFileChooser fc = new JFileChooser(); 305 | try { 306 | fc.setCurrentDirectory(new File(prefs.get("LAST_FILECHOOSER_DIR", ""))); 307 | } catch (Exception e) { 308 | e.printStackTrace(); 309 | } 310 | 311 | if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) 312 | { 313 | String fp = fc.getSelectedFile().getPath(); 314 | println("file: " + fp); 315 | 316 | prefs.put("LAST_FILECHOOSER_DIR", fc.getSelectedFile().getParent()); 317 | 318 | saveToBin(fp); 319 | } 320 | } 321 | 322 | public void openBin(int val) 323 | { 324 | if (!cp5_isReady) return; 325 | 326 | println("openBin clicked"); 327 | 328 | final JFileChooser fc = new JFileChooser(); 329 | try { 330 | fc.setCurrentDirectory(new File(prefs.get("LAST_FILECHOOSER_DIR", ""))); 331 | } catch (Exception e) { 332 | e.printStackTrace(); 333 | } 334 | 335 | if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) 336 | { 337 | String fp = fc.getSelectedFile().getPath(); 338 | println("file: " + fp); 339 | 340 | prefs.put("LAST_FILECHOOSER_DIR", fc.getSelectedFile().getParent()); 341 | 342 | background(0); 343 | 344 | try { 345 | FileInputStream fstream = new FileInputStream(fp); 346 | BufferedInputStream bstream = new BufferedInputStream(fstream); 347 | DataInputStream dstream = new DataInputStream(bstream); 348 | 349 | imgW = dstream.readShort(); 350 | img2 = new PImage(imgW * 10, 80); 351 | for (int x = 0; x < imgW; x++) 352 | { 353 | for (int y = 0; y < 8; y++) 354 | { 355 | color c = byteToColor(dstream.readByte()); 356 | for (int xx = 0; xx < 10; xx++) for (int yy = 0; yy < 10; yy++) img2.set((x * 10) + xx, (y * 10) + yy, c); 357 | } 358 | } 359 | 360 | img1 = img2; 361 | image(img1, 10 + 120 + 10, 10); 362 | image(img2, 10 + 120 + 10, 10 + 80 + 10); 363 | 364 | dstream.close(); 365 | bstream.close(); 366 | fstream.close(); 367 | } 368 | catch (Exception e) { 369 | e.printStackTrace(); 370 | JOptionPane.showMessageDialog(null, "Error while reading file: " + e.getMessage()); 371 | } 372 | } 373 | } 374 | 375 | public void download(int val) 376 | { 377 | if (!cp5_isReady) return; 378 | 379 | println("download clicked"); 380 | 381 | if (img2 == null) { 382 | JOptionPane.showMessageDialog(null, "Error: No Image Loaded"); 383 | return; 384 | } 385 | 386 | print("current dir:"); println(sketchPath("")); 387 | if (saveToBin("temp.bin")) 388 | { 389 | String os=System.getProperty("os.name"); 390 | String avrdude = sketchPath("")+"avrdude"; 391 | if (os.contains("Windows")) { 392 | avrdude = sketchPath("")+"avrdude.exe"; 393 | } 394 | if (os.contains("Mac")) { 395 | avrdude = sketchPath("")+"avrdude"; 396 | } 397 | println(os); 398 | // use the VUsbTinyBoot bootloader, for ATmega328P, no fuse safemode, no auto-erase, no progress bar, write the temporary file to eeprom 399 | String[] cmd = { avrdude, "-C"+sketchPath("")+"avrdude.conf", "-cusbtiny", "-pm328p", "-s", "-D", "-q", "-q", "-Ueeprom:w:temp.bin:r" }; 400 | print("shell:"); 401 | for (int i = 0; i < cmd.length; i++) print(" " + cmd[i]); 402 | println(); 403 | Process p = exec(cmd); 404 | String s = new String(); 405 | try { 406 | p.waitFor(); 407 | 408 | // read in everything that avrdude said back 409 | InputStream inStream = p.getInputStream(); 410 | while (inStream.available() > 0) s += char(inStream.read()); 411 | inStream = p.getErrorStream(); 412 | while (inStream.available() > 0) s += char(inStream.read()); 413 | 414 | println("done!"); 415 | println(s); 416 | } 417 | catch (Exception e) { 418 | println("done! (interrupted)"); 419 | println(s); 420 | } 421 | 422 | if (s.toLowerCase().contains("error")) { 423 | JOptionPane.showMessageDialog(null, "Possible Error Detected:\r\n" + s); 424 | } 425 | else { 426 | JOptionPane.showMessageDialog(null, "Done!\r\n" + s); 427 | } 428 | 429 | try { 430 | File f = new File("temp.bin"); 431 | if (f.delete()) { 432 | println("temp.bin deleted"); 433 | } 434 | else { 435 | println("temp.bin not deleted"); 436 | } 437 | } catch (Exception e) { 438 | println("Exception while deleting temp.bin: " + e.getMessage()); 439 | } 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /Software/avrdude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-MiniPOV4-Kit/067ae4dcad3fcc97ba4ef02da5cda2650d8b921f/Software/avrdude -------------------------------------------------------------------------------- /Software/avrdude.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-MiniPOV4-Kit/067ae4dcad3fcc97ba4ef02da5cda2650d8b921f/Software/avrdude.exe -------------------------------------------------------------------------------- /Test Images/minipov4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-MiniPOV4-Kit/067ae4dcad3fcc97ba4ef02da5cda2650d8b921f/Test Images/minipov4.png -------------------------------------------------------------------------------- /Test Images/minipov4test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-MiniPOV4-Kit/067ae4dcad3fcc97ba4ef02da5cda2650d8b921f/Test Images/minipov4test.png -------------------------------------------------------------------------------- /Test Images/rainbow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit-MiniPOV4-Kit/067ae4dcad3fcc97ba4ef02da5cda2650d8b921f/Test Images/rainbow.png --------------------------------------------------------------------------------