/** * \file bootloader/bootloaderconfig.h * \brief This file (together with some settings in Makefile) configures the * boot loader according to the hardware. * * This file contains (besides the hardware configuration normally found in * usbconfig.h) two functions or macros: bootLoaderInit() and * bootLoaderCondition(). Whether you implement them as macros or as static * inline functions is up to you, decide based on code size and convenience. * * bootLoaderInit() is called as one of the first actions after reset. It should * be a minimum initialization of the hardware so that the boot loader condition * can be read. This will usually consist of activating a pull-up resistor for an * external jumper which selects boot loader mode. * * bootLoaderCondition() is called immediately after initialization and in each * main loop iteration. If it returns TRUE, the boot loader will be active. If it * returns FALSE, the boot loader jumps to address 0 (the loaded application) * immediately. * * For compatibility with Thomas Fischl's avrusbboot, we also support the macro * names BOOTLOADER_INIT and BOOTLOADER_CONDITION for this functionality. If * these macros are defined, the boot loader usees them. * * \author Ronald Schaten * \version $Id$ * * License: GNU GPL v2 (see License.txt) */ #ifndef __bootloaderconfig_h_included__ #define __bootloaderconfig_h_included__ /* ---------------------------- Hardware Config ---------------------------- */ /** This is the port where the USB bus is connected. When you configure it to * "B", the registers PORTB, PINB and DDRB will be used. */ #define USB_CFG_IOPORTNAME D /** This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. * This may be any bit in the port. */ #define USB_CFG_DMINUS_BIT 0 /** This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. * This may be any bit in the port. Please note that D+ must also be connected * to interrupt pin INT0! */ #define USB_CFG_DPLUS_BIT 2 /** Clock rate of the AVR in MHz. Legal values are 12000, 16000 or 16500. * The 16.5 MHz version of the code requires no crystal, it tolerates +/- 1% * deviation from the nominal frequency. All other rates require a precision * of 2000 ppm and thus a crystal! * Default if not specified: 12 MHz */ #define USB_CFG_CLOCK_KHZ (F_CPU/1000) /* ----------------------- Optional Hardware Config ------------------------ */ /* If you connect the 1.5k pullup resistor from D- to a port pin instead of * V+, you can connect and disconnect the device from firmware by calling * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). * This constant defines the port on which the pullup resistor is connected. */ /* #define USB_CFG_PULLUP_IOPORTNAME D */ /* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined * above) where the 1.5k pullup resistor is connected. See description * above for details. */ /* #define USB_CFG_PULLUP_BIT 4 */ /* ------------------------------------------------------------------------- */ /* ---------------------- feature / code size options ---------------------- */ /* ------------------------------------------------------------------------- */ /** If HAVE_EEPROM_PAGED_ACCESS is defined to 1, page mode access to EEPROM is * compiled in. Whether page mode or byte mode access is used by AVRDUDE * depends on the target device. Page mode is only used if the device supports * it, e.g. for the ATMega88, 168 etc. You can save quite a bit of memory by * disabling page mode EEPROM access. Costs ~ 138 bytes. */ #define HAVE_EEPROM_PAGED_ACCESS 1 /** If HAVE_EEPROM_BYTE_ACCESS is defined to 1, byte mode access to EEPROM is * compiled in. Byte mode is only used if the device (as identified by its * signature) does not support page mode for EEPROM. It is required for * accessing the EEPROM on the ATMega8. Costs ~54 bytes. */ #define HAVE_EEPROM_BYTE_ACCESS 1 /** If this macro is defined to 1, the boot loader will exit shortly after the * programmer closes the connection to the device. Costs ~36 bytes. */ #define BOOTLOADER_CAN_EXIT 1 /** This macro defines the signature bytes returned by the emulated USBasp to * the programmer software. They should match the actual device at least in * memory size and features. If you don't define this, values for ATMega8, * ATMega88, ATMega168 and ATMega328 are guessed correctly. */ #define SIGNATURE_BYTES 0x1e, 0x95, 0x02, 0 /* ATMega32 */ /* The following block guesses feature options so that the resulting code * should fit into 2k bytes boot block with the given device and clock rate. * Activate by passing "-DUSE_AUTOCONFIG=1" to the compiler. * This requires gcc 3.4.6 for small enough code size! */ #if USE_AUTOCONFIG # undef HAVE_EEPROM_PAGED_ACCESS # define HAVE_EEPROM_PAGED_ACCESS (USB_CFG_CLOCK_KHZ >= 16000) # undef HAVE_EEPROM_BYTE_ACCESS # define HAVE_EEPROM_BYTE_ACCESS 1 # undef BOOTLOADER_CAN_EXIT # define BOOTLOADER_CAN_EXIT 1 # undef SIGNATURE_BYTES #endif /* USE_AUTOCONFIG */ /* ------------------------------------------------------------------------- */ #ifndef __ASSEMBLER__ /* assembler cannot parse function definitions */ #ifdef MODELSUNTYPE5 # define SRCLOCKON PORTC |= (1 << PC5) # define SRCLOCKOFF PORTC &= ~(1 << PC5) # define SRDATAON PORTC |= (1 << PC6) # define SRDATAOFF PORTC &= ~(1 << PC6) # define SRSTROBEON PORTC |= (1 << PC7) # define SRSTROBEOFF PORTC &= ~(1 << PC7) # define KEYROW 16 #endif uint8_t ledbrightness = 0; ///< brightness level of the leds, between 0 and 127 uint8_t ledcounter = 0; ///< needed for PWM operation int8_t leddirection = 1; ///< indicates if leds fade higher or lower /** * Prepare IO-ports for detection of bootloader-condition, which happens in * bootLoaderCondition(). */ #ifdef MODELIBMMODELM static inline void bootLoaderInit(void) { // switch on leds DDRD |= (1 << PIND4) | (1 << PIND5) | (1 << PIND6); PORTD &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6)); // choose matrix position for hotkey. we use KEY_D, so we set row 4 // and later look for column 5 DDRA = (1 << DDA4); PORTA = ~(1 << PINA4); DDRB &= ~(1 << PB5); PORTB |= (1 << PB5); DDRC = 0x00; PORTC = 0xff; } #endif #ifdef MODELMAYHEM static inline void bootLoaderInit(void) { // switch on leds DDRD |= (1 << PIND1) | (1 << PIND3) | (1 << PIND6) | (1 << PIND7); PORTD &= ~((1 << PIND1) | (1 << PIND3) | (1 << PIND6) | (1 << PIND7)); // choose matrix position for hotkey. we use KEY_D, so we set row 4 // and later look for column 5 DDRA = (1 << DDA4); PORTA = ~(1 << PINA4); DDRB &= ~(1 << PB5); PORTB |= (1 << PB5); DDRC = 0x00; PORTC = 0xff; } #endif #ifdef MODELSUNTYPE5 static inline void bootLoaderInit(void) { // configure ports DDRA = 0x00; PORTA = 0xff; DDRB = (1 << PB4) |(1 << PB5) | (1 << PB6) | (1 << PB7); PORTB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3); DDRC = (1 << PC5) | (1 << PC6) | (1 << PC7); PORTC = (1 << PC0) | (1 << PC1) | (1 << PC2) | (1 << PC3) | (1 << PC4); DDRD &= ~((1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7)); PORTD |= (1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7); // switch on leds PORTB &= ~((1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7)); // choose matrix position for hotkey. we use KEY_D, so we set all // rows to 1 except for row 16 (KEYROW) and later look for column 12 SRDATAON; SRSTROBEOFF; uint8_t i = 0; for (i = 0; i < (21 - KEYROW); i++) { SRCLOCKON; SRCLOCKOFF; } SRDATAOFF; SRCLOCKON; SRCLOCKOFF; SRDATAON; for (i = 0; i < KEYROW; i++) { SRCLOCKON; SRCLOCKOFF; } SRSTROBEON; SRSTROBEOFF; } #endif #ifdef MODELIBMHOST static inline void bootLoaderInit(void) { // choose matrix position for hotkey. we use KEY_D, so we set row 13 DDRA = 0x00; PORTA = 0xff; DDRC = (1 << DDC2); PORTC = ~(1 << PINC2); DDRD &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7)); PORTD |= ((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7)); // and later look for column 6 DDRB &= ~(1 << PB6); PORTB |= (1 << PB6); } #endif /** * Clean up after boot loader action. In this case: switch off all LEDs. */ #ifdef MODELIBMMODELM static inline void bootLoaderExit(void) { // switch off leds PORTD |= (1 << PIND4) | (1 << PIND5) | (1 << PIND6); } #endif #ifdef MODELMAYHEM static inline void bootLoaderExit(void) { // switch off leds PORTD |= (1 << PIND1) | (1 << PIND3) | (1 << PIND6) | (1 << PIND7); } #endif #ifdef MODELSUNTYPE5 static inline void bootLoaderExit(void) { // switch off leds PORTB |= (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7); } #endif #ifdef MODELIBMHOST static inline void bootLoaderExit(void) { // do nothing } #endif /** * Check if conditions for boot loader are met. This function is called in an * endless loop, so we use our spare time to display a nice running light on * the LEDs. * \return 1 if bootloader should be active, 0 otherwise */ #ifdef MODELIBMMODELM static inline uint8_t bootLoaderCondition() { // look for pin 5 if (!(PINB & (1 << PINB5))) { // boot loader active, fade leds ledcounter++; if (ledcounter < ledbrightness) { // switch on leds PORTD &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6)); } else { // switch off leds PORTD |= (1 << PIND4) | (1 << PIND5) | (1 << PIND6); } if (ledcounter == 255) { ledcounter = 0; ledbrightness += leddirection; if (ledbrightness == 255) { leddirection = -leddirection; ledbrightness += leddirection; } } return 1; } else { // no boot loader return 0; } } #endif #ifdef MODELMAYHEM static inline uint8_t bootLoaderCondition() { // look for pin 5 if (!(PINB & (1 << PINB5))) { // boot loader active, fade leds ledcounter++; if (ledcounter < ledbrightness) { // switch on leds PORTD &= ~((1 << PIND1) | (1 << PIND3) | (1 << PIND6) | (1 << PIND7)); } else { // switch off leds PORTD |= (1 << PIND1) | (1 << PIND3) | (1 << PIND6) | (1 << PIND7); } if (ledcounter == 255) { ledcounter = 0; ledbrightness += leddirection; if (ledbrightness == 255) { leddirection = -leddirection; ledbrightness += leddirection; } } return 1; } else { // no boot loader return 0; } } #endif #ifdef MODELSUNTYPE5 static inline uint8_t bootLoaderCondition() { // look for pin 12, KEY_D if (!(PINC & (1 << PINC4))) { // boot loader active, fade leds ledcounter++; if (ledcounter < ledbrightness) { // switch on leds PORTB &= ~((1 << PINB4) | (1 << PINB5) | (1 << PINB6) | (1 << PINB7)); } else { // switch off leds PORTB |= (1 << PINB4) | (1 << PINB5) | (1 << PINB6) | (1 << PINB7); } if (ledcounter == 255) { ledcounter = 0; ledbrightness += leddirection; if (ledbrightness == 255) { leddirection = -leddirection; ledbrightness += leddirection; } } return 1; } else { // no boot loader return 0; } } #endif #ifdef MODELIBMHOST static inline uint8_t bootLoaderCondition() { // look for pin 6 if (!(PINB & (1 << PINB6))) { // boot loader active return 1; } else { // no boot loader return 0; } } #endif #endif /* __ASSEMBLER__ */ /* ------------------------------------------------------------------------- */ #endif /* __bootloader_h_included__ */