Dulcimer/bootloader/bootloaderconfig.h

316 lines
11 KiB
C
Raw Normal View History

2008-07-09 22:47:12 +02:00
/**
* \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 <ronald@schatenseite.de>
* \version $Id$
2008-07-09 22:47:12 +02:00
*
* 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)
2008-11-01 22:22:37 +01:00
# 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
2008-07-09 22:47:12 +02:00
/**
* Prepare IO-ports for detection of bootloader-condition, which happens in
* bootLoaderCondition().
*/
#ifdef MODELIBMMODELM
2008-07-09 22:47:12 +02:00
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;
2008-07-09 22:47:12 +02:00
}
#endif
2008-11-12 22:45:43 +01:00
#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
2008-07-09 22:47:12 +02:00
/**
* Clean up after boot loader action. In this case: switch off all LEDs.
*/
#ifdef MODELIBMMODELM
2008-07-09 22:47:12 +02:00
static inline void bootLoaderExit(void) {
// switch off leds
PORTD |= (1 << PIND4) | (1 << PIND5) | (1 << PIND6);
}
#endif
2008-11-12 22:45:43 +01:00
#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
2008-07-09 22:47:12 +02:00
/**
* 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
2008-07-09 22:47:12 +02:00
static inline uint8_t bootLoaderCondition() {
// look for pin 5
if (!(PINB & (1 << PINB5))) {
// boot loader active, fade leds
2008-07-09 22:47:12 +02:00
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) {
2008-07-09 22:47:12 +02:00
ledcounter = 0;
ledbrightness += leddirection;
if (ledbrightness == 255) {
leddirection = -leddirection;
ledbrightness += leddirection;
}
2008-07-09 22:47:12 +02:00
}
return 1;
} else {
// no boot loader
2008-11-12 22:45:43 +01:00
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
2008-07-09 22:47:12 +02:00
return 0;
}
}
#endif
#ifdef MODELSUNTYPE5
static inline uint8_t bootLoaderCondition() {
// look for pin 12, KEY_D
2008-11-01 22:22:37 +01:00
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
2008-07-09 22:47:12 +02:00
#endif /* __ASSEMBLER__ */
/* ------------------------------------------------------------------------- */
#endif /* __bootloader_h_included__ */