diff --git a/boards.txt b/boards.txt index d4bff7b..df14e89 100644 --- a/boards.txt +++ b/boards.txt @@ -177,3 +177,23 @@ atmega328.bootloader.lock_bits=0x0F atmega328.build.mcu=atmega328p atmega328.build.f_cpu=16000000L atmega328.build.core=arduino + +############################################################## + +mega.name=Arduino Mega + +mega.upload.protocol=stk500 +mega.upload.maximum_size=126976 +mega.upload.speed=57600 + +mega.bootloader.low_fuses=0xFF +mega.bootloader.high_fuses=0xDA +mega.bootloader.extended_fuses=0xF5 +mega.bootloader.path=atmega +mega.bootloader.file=ATmegaBOOT_168_atmega1280.hex +mega.bootloader.unlock_bits=0x3F +mega.bootloader.lock_bits=0x0F + +mega.build.mcu=atmega1280 +mega.build.f_cpu=16000000L +mega.build.core=arduino diff --git a/bootloaders/atmega/ATmegaBOOT_168.c b/bootloaders/atmega/ATmegaBOOT_168.c index 9413f86..8ea1509 100755 --- a/bootloaders/atmega/ATmegaBOOT_168.c +++ b/bootloaders/atmega/ATmegaBOOT_168.c @@ -6,6 +6,12 @@ /* */ /* ATmegaBOOT.c */ /* */ +/* */ +/* 20090308: integrated Mega changes into main bootloader */ +/* source by D. Mellis */ +/* 20080930: hacked for Arduino Mega (with the 1280 */ +/* processor, backwards compatible) */ +/* by D. Cuartielles */ /* 20070626: hacked for Arduino Diecimila (which auto- */ /* resets when a USB connection is made to it) */ /* by D. Mellis */ @@ -101,6 +107,7 @@ /* Adjust to suit whatever pin your hardware uses to enter the bootloader */ /* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */ +/* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */ /* BL0... means UART0, BL1... means UART1 */ #ifdef __AVR_ATmega128__ #define BL_DDR DDRF @@ -108,6 +115,8 @@ #define BL_PIN PINF #define BL0 PINF7 #define BL1 PINF6 +#elif defined __AVR_ATmega1280__ +/* we just don't do anything for the MEGA and enter bootloader on reset anyway*/ #else /* other ATmegas have only one UART, so only one pin is defined to enter bootloader */ #define BL_DDR DDRD @@ -119,26 +128,25 @@ /* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */ /* if monitor functions are included, LED goes on after monitor was entered */ -#ifdef __AVR_ATmega128__ -/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128) */ +#if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__ +/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */ #define LED_DDR DDRB #define LED_PORT PORTB #define LED_PIN PINB #define LED PINB7 #else -/* Onboard LED is connected to pin PB2 (e.g. Crumb8, Crumb168) */ +/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */ +/* other boards like e.g. Crumb8, Crumb168 are using PB2 */ #define LED_DDR DDRB #define LED_PORT PORTB #define LED_PIN PINB -/* 20060803: hacked by DojoCorp, LED pin is B5 in Arduino */ -/* #define LED PINB2 */ #define LED PINB5 #endif /* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */ -#ifdef __AVR_ATmega128__ -#define MONITOR +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) +#define MONITOR 1 #endif @@ -146,7 +154,17 @@ /* manufacturer byte is always the same */ #define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :( -#if defined __AVR_ATmega128__ +#if defined __AVR_ATmega1280__ +#define SIG2 0x97 +#define SIG3 0x03 +#define PAGE_SIZE 0x80U //128 words + +#elif defined __AVR_ATmega1281__ +#define SIG2 0x97 +#define SIG3 0x04 +#define PAGE_SIZE 0x80U //128 words + +#elif defined __AVR_ATmega128__ #define SIG2 0x97 #define SIG3 0x02 #define PAGE_SIZE 0x80U //128 words @@ -282,6 +300,7 @@ int main(void) #else /* We run the bootloader regardless of the state of this pin. Thus, don't put it in a different state than the other pins. --DAM, 070709 + This also applies to Arduino Mega -- DC, 080930 BL_DDR &= ~_BV(BL); BL_PORT |= _BV(BL); */ @@ -298,24 +317,30 @@ int main(void) } #endif +#if defined __AVR_ATmega1280__ + /* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */ + /* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */ + bootuart = 1; +#endif + /* check if flash is programmed already, if not start bootloader anyway */ if(pgm_read_byte_near(0x0000) != 0xFF) { #ifdef __AVR_ATmega128__ - /* no UART was selected, start application */ - if(!bootuart) { - app_start(); - } + /* no UART was selected, start application */ + if(!bootuart) { + app_start(); + } #else - /* check if bootloader pin is set low */ - /* we don't start this part neither for the m8, nor m168 */ - //if(bit_is_set(BL_PIN, BL)) { - // app_start(); - //} + /* check if bootloader pin is set low */ + /* we don't start this part neither for the m8, nor m168 */ + //if(bit_is_set(BL_PIN, BL)) { + // app_start(); + // } #endif } -#ifdef __AVR_ATmega128__ +#ifdef __AVR_ATmega128__ /* no bootuart was selected, default to uart 0 */ if(!bootuart) { bootuart = 1; @@ -324,7 +349,7 @@ int main(void) /* initialize UART(s) depending on CPU defined */ -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) if(bootuart == 1) { UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; @@ -370,12 +395,22 @@ int main(void) UCSRB = _BV(TXEN)|_BV(RXEN); #endif +#if defined __AVR_ATmega1280__ + /* Enable internal pull-up resistor on pin D0 (RX), in order + to supress line noise that prevents the bootloader from + timing out (DAM: 20070509) */ + /* feature added to the Arduino Mega --DC: 080930 */ + DDRE &= ~_BV(PINE0); + PORTE |= _BV(PINE0); +#endif + + /* set LED pin as output */ LED_DDR |= _BV(LED); /* flash onboard LED to signal entering of bootloader */ -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) // 4x for UART0, 5x for UART1 flash_led(NUM_LED_FLASHES + bootuart); #else @@ -383,10 +418,9 @@ int main(void) #endif /* 20050803: by DojoCorp, this is one of the parts provoking the - system to stop listening, cancelled from the original */ + system to stop listening, cancelled from the original */ //putch('\0'); - /* forever loop */ for (;;) { @@ -531,15 +565,18 @@ int main(void) else { //Write to FLASH one page at a time if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME else address_high = 0x00; -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) RAMPZ = address_high; #endif address.word = address.word << 1; //address * 2 -> byte location /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */ if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes cli(); //Disable interrupts, just to be sure - // HACKME: EEPE used to be EEWE +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete +#else + while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete +#endif asm volatile( "clr r17 \n\t" //page_word_count "lds r30,address \n\t" //Address of FLASH location (in bytes) @@ -634,7 +671,7 @@ int main(void) "rjmp write_page \n\t" "block_done: \n\t" "clr __zero_reg__ \n\t" //restore zero register -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +#if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ || __AVR_ATmega1281__ : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" #else : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" @@ -656,7 +693,7 @@ int main(void) else if(ch=='t') { length.byte[1] = getch(); length.byte[0] = getch(); -#if defined __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME else flags.rampz = 0; #endif @@ -680,7 +717,7 @@ int main(void) else { if (!flags.rampz) putch(pgm_read_byte_near(address.word)); -#if defined __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) else putch(pgm_read_byte_far(address.word + 0x10000)); // Hmmmm, yuck FIXME when m256 arrvies #endif @@ -702,7 +739,7 @@ int main(void) putch(0x10); } else { if (++error_count == MAX_ERROR_COUNT) - app_start(); + app_start(); } } @@ -713,7 +750,7 @@ int main(void) } -#ifdef MONITOR +#if defined MONITOR /* here come the extended monitor commands by Erik Lins */ @@ -723,18 +760,20 @@ int main(void) if(ch=='!') { ch = getch(); if(ch=='!') { - -#ifdef __AVR_ATmega128__ + PGM_P welcome = ""; +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) uint16_t extaddr; #endif uint8_t addrl, addrh; #ifdef CRUMB128 - PGM_P welcome = {"ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r"}; + welcome = "ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r"; #elif defined PROBOMEGA128 - PGM_P welcome = {"ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r"}; + welcome = "ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r"; #elif defined SAVVY128 - PGM_P welcome = {"ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r"}; + welcome = "ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r"; +#elif defined __AVR_ATmega1280__ + welcome = "ATmegaBOOT / Arduino Mega - (C) Arduino LLC - 090930\n\r"; #endif /* turn on LED */ @@ -793,7 +832,7 @@ int main(void) putch(getch()); } } -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) /* external bus loop */ else if(ch == 'b') { putch('b'); @@ -872,7 +911,7 @@ void puthex(char ch) { void putch(char ch) { -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) if(bootuart == 1) { while (!(UCSR0A & _BV(UDRE0))); UDR0 = ch; @@ -894,13 +933,28 @@ void putch(char ch) char getch(void) { -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + uint32_t count = 0; if(bootuart == 1) { - while(!(UCSR0A & _BV(RXC0))); - return UDR0; - } + while(!(UCSR0A & _BV(RXC0))) { + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + + return UDR0; + } else if(bootuart == 2) { - while(!(UCSR1A & _BV(RXC1))); + while(!(UCSR1A & _BV(RXC1))) { + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + return UDR1; } return 0; @@ -932,7 +986,7 @@ char getch(void) void getNch(uint8_t count) { while(count--) { -#ifdef __AVR_ATmega128__ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) if(bootuart == 1) { while(!(UCSR0A & _BV(RXC0))); UDR0; diff --git a/bootloaders/atmega/ATmegaBOOT_168_atmega1280.hex b/bootloaders/atmega/ATmegaBOOT_168_atmega1280.hex new file mode 100644 index 0000000..f16e877 --- /dev/null +++ b/bootloaders/atmega/ATmegaBOOT_168_atmega1280.hex @@ -0,0 +1,245 @@ +:020000021000EC +:10F000000C9472F80C9492F80C9492F80C9492F878 +:10F010000C9492F80C9492F80C9492F80C9492F848 +:10F020000C9492F80C9492F80C9492F80C9492F838 +:10F030000C9492F80C9492F80C9492F80C9492F828 +:10F040000C9492F80C9492F80C9492F80C9492F818 +:10F050000C9492F80C9492F80C9492F80C9492F808 +:10F060000C9492F80C9492F80C9492F80C9492F8F8 +:10F070000C9492F80C9492F80C9492F80C9492F8E8 +:10F080000C9492F80C9492F80C9492F80C9492F8D8 +:10F090000C9492F80C9492F80C9492F80C9492F8C8 +:10F0A0000C9492F80C9492F80C9492F80C9492F8B8 +:10F0B0000C9492F80C9492F80C9492F80C9492F8A8 +:10F0C0000C9492F80C9492F80C9492F80C9492F898 +:10F0D0000C9492F80C9492F80C9492F80C9492F888 +:10F0E0000C9492F811241FBECFEFD1E2DEBFCDBF4A +:10F0F00012E0A0E0B2E0EEEDFEEF01E00BBF02C0D7 +:10F1000007900D92A833B107D9F71BBE13E0A8E30F +:10F11000B2E001C01D92A334B107E1F70E9412FAD8 +:10F120000C946DFF0C9400F8982F959595959595F6 +:10F130009595905D8F708A301CF1282F295A809107 +:10F140003802813019F0823071F008958091C0004A +:10F1500085FFFCCF9093C6008091C00085FFFCCF57 +:10F160002093C60008958091C80085FFFCCF90933E +:10F17000CE008091C80085FFFCCF2093CE0008957B +:10F18000282F205DDCCF982F80913802813019F034 +:10F19000823041F008958091C00085FFFCCF9093AC +:10F1A000C60008958091C80085FFFCCF9093CE00E3 +:10F1B0000895EF92FF920F931F9380913802813050 +:10F1C00069F1823031F080E01F910F91FF90EF9054 +:10F1D0000895EE24FF2487018091C80087FD17C0A1 +:10F1E0000894E11CF11C011D111D81E4E81682E464 +:10F1F000F8068FE0080780E0180770F3E0913A0204 +:10F20000F0913B0209958091C80087FFE9CF80917A +:10F21000CE001F910F91FF90EF900895EE24FF24F0 +:10F2200087018091C00087FD17C00894E11CF11C84 +:10F23000011D111D81E4E81682E4F8068FE008073D +:10F2400080E0180770F3E0913A02F0913B020995D3 +:10F250008091C00087FFE9CF8091C6001F910F9178 +:10F26000FF90EF9008950E94D9F8982F809138026E +:10F27000813049F0823091F091366CF490330CF08B +:10F280009053892F08958091C00085FFFCCF909303 +:10F29000C60091369CF39755892F08958091C80038 +:10F2A00085FFFCCF9093CE00E7CF1F930E9433F9E8 +:10F2B000182F0E9433F91295107F810F1F91089526 +:10F2C000982F20913802992339F0213031F02230E3 +:10F2D00061F091509923C9F708958091C00087FF8C +:10F2E000FCCF8091C6009150F5CF8091C80087FF78 +:10F2F000FCCF8091CE009150EDCF1F93182F0E942C +:10F30000D9F8803249F0809139028F5F80933902B9 +:10F31000853091F11F910895809138028130B9F0C4 +:10F320008230C1F78091C80085FFFCCF84E18093D3 +:10F33000CE008091C80085FFFCCF1093CE00809155 +:10F34000C80085FFFCCF80E18093CE00E3CF8091A1 +:10F35000C00085FFFCCF84E18093C6008091C0008F +:10F3600085FFFCCF1093C6008091C00085FFFCCFC5 +:10F3700080E18093C600CECFE0913A02F0913B024B +:10F3800009951F9108950E94D9F8803241F080912B +:10F3900039028F5F80933902853029F10895809179 +:10F3A0003802813089F08230C9F78091C80085FF2A +:10F3B000FCCF84E18093CE008091C80085FFFCCF14 +:10F3C00080E18093CE0008958091C00085FFFCCF3E +:10F3D00084E18093C6008091C00085FFFCCF80E16E +:10F3E0008093C6000895E0913A02F0913B0209959E +:10F3F000089540E951E08823A1F02F9A28EE33E0E8 +:10F40000FA013197F1F721503040D1F72F9828EECB +:10F4100033E0FA013197F1F721503040D1F78150B4 +:10F4200061F708952F923F924F925F926F927F9271 +:10F430008F929F92AF92BF92CF92DF92EF92FF9204 +:10F440000F931F93CF93DF93000081E080933802E6 +:10F4500080E18093C4001092C5001092C00086E045 +:10F460008093C20088E18093C1006898709A279ABF +:10F4700081E00E94F9F9E4E1EE2E7EE1D72E67E902 +:10F48000C62E53E0B52E40E1A42E9924939431E486 +:10F49000832E26E5722E92E5692E80E2582E09E42D +:10F4A000402E13E5312EB0E52B2E0E94D9F8803383 +:10F4B000C9F1813309F452C0803409F4C8C08134E1 +:10F4C00009F4EAC0823489F1853409F4CAC0803570 +:10F4D00049F1823539F1813529F1853509F4ECC0DE +:10F4E000863509F409C1843609F428C1843709F442 +:10F4F000ABC1853709F473C2863709F4D9C08132AC +:10F5000009F4B7C2809139028F5F80933902853048 +:10F5100061F6E0913A02F0913B0209950E94D9F818 +:10F52000803339F60E94C3F9C0CF2091380293E1AD +:10F5300005C0223061F09923A9F391502130C9F719 +:10F540008091C00087FFFCCF8091C600F4CF8091EE +:10F55000C80087FFFCCF8091CE00EDCF0E94D9F884 +:10F56000803281F6809138028130D1F1823009F009 +:10F570009CCF8091C80085FFFCCFE092CE008091A7 +:10F58000C80085FFFCCF8092CE008091C80085FF27 +:10F59000FCCF7092CE008091C80085FFFCCF6092B6 +:10F5A000CE008091C80085FFFCCF5092CE008091A4 +:10F5B000C80085FFFCCF4092CE008091C80085FF37 +:10F5C000FCCF3092CE008091C80085FFFCCF209206 +:10F5D000CE008091C80085FFFCCFA092CE0065CF01 +:10F5E0008091C00085FFFCCFE092C6008091C000F2 +:10F5F00085FFFCCF8092C6008091C00085FFFCCFC4 +:10F600007092C6008091C00085FFFCCF6092C6005A +:10F610008091C00085FFFCCF5092C6008091C00051 +:10F6200085FFFCCF4092C6008091C00085FFFCCFD3 +:10F630003092C6008091C00085FFFCCF2092C600AA +:10F640008091C00085FFFCCFA092C6002ECF0E9403 +:10F65000D9F8863808F466CF0E94D9F80E94C3F919 +:10F6600024CF2091380294E0213041F0223069F01B +:10F67000992309F457CF91502130C1F78091C000F0 +:10F6800087FFFCCF8091C600F3CF8091C80087FF31 +:10F69000FCCF8091CE00ECCF0E94D9F8803841F1A8 +:10F6A000813809F447C0823809F4CAC08839E1F0CA +:10F6B00080E00E947DF9F9CE0E94D9F880933C0247 +:10F6C0000E94D9F880933D020E94C3F9EECE0E94B9 +:10F6D000D9F80E94D9F8182F0E94D9F8112309F4FB +:10F6E0007EC2113009F40AC283E00E947DF9DDCEAA +:10F6F00082E00E947DF9D9CE0E94D9F8803339F397 +:10F700002091380292E0213039F0223061F09923C3 +:10F7100079F291502130C9F78091C00087FFFCCF6A +:10F720008091C600F4CF8091C80087FFFCCF809104 +:10F73000CE00EDCF81E00E947DF9B7CE0E94D9F8CE +:10F7400080933F030E94D9F880933E038091420347 +:10F750008E7F809342030E94D9F8853409F4B3C1A7 +:10F7600080913E0390913F03892B89F000E010E0E7 +:10F770000E94D9F8F801E25CFD4F80830F5F1F4FB4 +:10F7800080913E0390913F030817190788F30E9468 +:10F79000D9F8803209F0B6CE8091420380FFB2C121 +:10F7A00040913C0250913D02440F551F50933D0241 +:10F7B00040933C0260913E0370913F0361157105D7 +:10F7C000F1F080E090E09A01280F391FFC01E25C23 +:10F7D000FD4FE081F999FECF1FBA32BD21BDE0BDDA +:10F7E0000FB6F894FA9AF99A0FBE01968617970702 +:10F7F00050F3460F571F50933D0240933C028091B7 +:10F800003802813081F0823009F04FCE8091C800FB +:10F8100085FFFCCFE092CE008091C80085FFFCCF31 +:10F82000A092CE0042CE8091C00085FFFCCFE09236 +:10F83000C6008091C00085FFFCCFA092C60035CEE7 +:10F8400080E10E947DF931CE0E94D9F880933F0378 +:10F850000E94D9F880933E0320913C0230913D02F2 +:10F8600037FD46C1809142038D7F80934203220F72 +:10F87000331F30933D0220933C020E94D9F8853417 +:10F8800009F430C1809142038E7F809342030E942D +:10F89000D9F8803209F009CE60913802613009F45C +:10F8A0006FC0623009F473C000913E0310913F03B2 +:10F8B0000115110509F440C080914203782F717041 +:10F8C000F82EF69481E0F82240913C0250913D02DE +:10F8D00020E030E013C0FF2009F060C0FA019491ED +:10F8E000613009F43BC0623009F441C0CA0101969D +:10F8F0002F5F3F4FAC0120173107D0F4772359F326 +:10F90000F999FECF52BD41BDF89A90B56130F9F03A +:10F91000623061F78091C80085FFFCCF9093CE00E4 +:10F92000CA0101962F5F3F4FAC012017310730F31A +:10F9300090933D0280933C02613009F4CAC062306A +:10F9400009F0B3CD8091C80085FFFCCF46CE8091F1 +:10F95000C00085FFFCCF9093C600C8CF8091C00047 +:10F9600085FDF9CF8091C00085FFF8CFF4CF80915D +:10F97000C80085FDD3CF8091C80085FFF8CFCECFDA +:10F980008091C00085FFFCCFE092C6008DCF8091B2 +:10F99000C80085FFFCCFE092CE0086CFCA01A0E070 +:10F9A000B0E080509040AF4FBF4FABBFFC0197918C +:10F9B000613061F0623009F099CF8091C80085FD17 +:10F9C000ADCF8091C80085FFF8CFA8CF8091C0004F +:10F9D00085FDC1CF8091C00085FFF8CFBCCF0E94CC +:10F9E000D9F8803209F08ECD80913802813011F142 +:10F9F000823009F05ACD8091C80085FFFCCFE0929B +:10FA0000CE008091C80085FFFCCFD092CE008091BF +:10FA1000C80085FFFCCFC092CE008091C80085FF52 +:10FA2000FCCFB092CE008091C80085FFFCCFA092A1 +:10FA3000CE003BCD8091C00085FFFCCFE092C60098 +:10FA40008091C00085FFFCCFD092C6008091C0009D +:10FA500085FFFCCFC092C6008091C00085FFFCCF1F +:10FA6000B092C6008091C00085FFFCCFA092C60076 +:10FA70001CCD0E94D9F8813209F017CD0E94D9F827 +:10FA8000813209F012CD279A2F98109240032091CD +:10FA90003802E1E491E00EC0223009F4A4C0909352 +:10FAA0004003E92FF0E0E050FE4FE0819F5FEE233E +:10FAB00009F4A0C0213081F78091C00085FFFCCF00 +:10FAC000E093C600ECCF80914203816080934203B3 +:10FAD00047CE8091C00085FDB7CD8091C00085FFE5 +:10FAE000F8CFB2CD80914203816080934203CFCEA4 +:10FAF00080914203826080934203B9CE87E90E94DD +:10FB00007DF9D3CC80913D028823880F880B892111 +:10FB1000809341038BBF80913C0290913D02880FFE +:10FB2000991F90933D0280933C0280913E0380FF99 +:10FB300009C080913E0390913F03019690933F034B +:10FB400080933E03F894F999FECF1127E0913C028F +:10FB5000F0913D02CEE3D2E080913E0390913F03CD +:10FB6000103091F40091570001700130D9F303E097 +:10FB700000935700E8950091570001700130D9F3C8 +:10FB800001E100935700E895099019900091570002 +:10FB900001700130D9F301E000935700E895139507 +:10FBA000103898F011270091570001700130D9F3F7 +:10FBB00005E000935700E89500915700017001306F +:10FBC000D9F301E100935700E8953296029709F0C6 +:10FBD000C7CF103011F00296E5CF112410CE8EE180 +:10FBE0000E947DF962CC8091C80085FFFCCFE09334 +:10FBF000CE0055CF7AE0B72E6DE0A62E5AE3952EB3 +:10FC000040E2842E3DE3732E90E3692E81E3582E6B +:10FC1000213009F442C0223009F45FC00E94D9F8B3 +:10FC2000982F20913802213089F1223009F44EC0FA +:10FC3000943709F46BC0923709F405C1973709F47A +:10FC40007BC0953799F0923609F4BDC09A3601F71A +:10FC5000E0913A02F0913B02099520913802D8CF09 +:10FC60008091C00085FFFCCF9093C6000E94D9F818 +:10FC7000982F80913802813099F38230B9F78091C2 +:10FC8000C80085FFFCCF9093CE00F0CF8091C000DC +:10FC900085FFFCCF9093C600CBCF8091C00085FF3D +:10FCA000FCCFB092C6008091C00085FFFCCFA0922F +:10FCB000C6008091C00085FFFCCF9092C600809165 +:10FCC000C00085FFFCCF8092C600A8CF8091C800FD +:10FCD00085FFFCCF9093CE00ABCF8091C80085FF0D +:10FCE000FCCFB092CE008091C80085FFFCCFA092DF +:10FCF000CE008091C80085FFFCCF9092CE0080910D +:10FD0000C80085FFFCCF8092CE0088CF1F9947C0E6 +:10FD10002F9A213051F0223009F07ACF8091C8001B +:10FD200085FFFCCF6092CE0073CF8091C00085FF2D +:10FD3000FCCF6092C6006CCF0E94D9F8982F8091BA +:10FD400038028130F1F0823009F4ABC00E9455F9DD +:10FD5000082F0E9455F9182F0E94D9F8982F8091EA +:10FD600038028130A9F0823009F4A2C00E9455F90E +:10FD7000D02ECC24F601E10FF11D808320913802B2 +:10FD800047CF8091C00085FFFCCF9093C600DECFA7 +:10FD90008091C00085FFFCCF9093C600E7CF2F98DD +:10FDA000213051F0223009F033CF8091C80085FF17 +:10FDB000FCCF5092CE002CCF8091C00085FFFCCFAD +:10FDC0005092C60025CF213041F1223081F080E8E9 +:10FDD00085BF109274001092750080E091E1FC01E3 +:10FDE000819180E091E13097D1F3CF01F8CF8091FC +:10FDF000C80085FFFCCF82E68093CE008091C800CA +:10FE000085FFFCCF85E78093CE008091C80085FFF9 +:10FE1000FCCF83E78093CE00DACF8091C00085FFCE +:10FE2000FCCF82E68093C6008091C00085FFFCCFA6 +:10FE300085E78093C6008091C00085FFFCCF83E7F3 +:10FE40008093C600C4CF0E94D9F8982F80913802C1 +:10FE50008130C9F08230D1F10E9455F9182F0E94EB +:10FE600055F9982F809138028130A1F0823039F114 +:10FE7000F12EEE24F701E90FF11D80810E9494F824 +:10FE800020913802C5CE8091C00085FFFCCF9093B1 +:10FE9000C600E2CF8091C00085FFFCCF7092C60003 +:10FEA000E7CF8091C80085FFFCCF9093CE004ECF66 +:10FEB0008091C80085FFFCCF9093CE0057CF8091F2 +:10FEC000C80085FFFCCF7092CE00D2CF8091C800D1 +:0EFED00085FFFCCF9093CE00BFCFF894FFCFFC +:10FEDE0041546D656761424F4F54202F204172642B +:10FEEE0075696E6F204D656761202D20284329208E +:10FEFE0041726475696E6F204C4C43202D20303951 +:08FF0E00303933300A0D008088 +:040000031000F000F9 +:00000001FF diff --git a/bootloaders/atmega/Makefile b/bootloaders/atmega/Makefile index 861cedd..6c6c215 100755 --- a/bootloaders/atmega/Makefile +++ b/bootloaders/atmega/Makefile @@ -166,6 +166,21 @@ atmega328_isp: LFUSE = FF atmega328_isp: EFUSE = 05 atmega328_isp: isp +mega: TARGET = atmega1280 +mega: MCU_TARGET = atmega1280 +mega: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' -DBAUD_RATE=57600 +mega: AVR_FREQ = 16000000L +mega: LDSECTION = --section-start=.text=0x1F000 +mega: $(PROGRAM)_atmega1280.hex + +mega_isp: mega +mega_isp: TARGET = atmega1280 +mega_isp: MCU_TARGET = atmega1280 +mega_isp: HFUSE = DA +mega_isp: LFUSE = FF +mega_isp: EFUSE = F5 +mega_isp: isp + isp: $(TARGET) $(ISPFUSES) $(ISPFLASH) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index aab7fc5..f8a959a 100755 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -1,5 +1,5 @@ /* - HarwareSerial.cpp - Hardware serial library for Wiring + HardwareSerial.cpp - Hardware serial library for Wiring Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or @@ -23,36 +23,169 @@ #include #include #include "wiring.h" +#include "wiring_private.h" #include "HardwareSerial.h" +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#define RX_BUFFER_SIZE 128 + +struct ring_buffer { + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; +}; + +ring_buffer rx_buffer = { { 0 }, 0, 0 }; + +#if defined(__AVR_ATmega1280__) +ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; +ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; +ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; +#endif + +inline void store_char(unsigned char c, ring_buffer *rx_buffer) +{ + int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != rx_buffer->tail) { + rx_buffer->buffer[rx_buffer->head] = c; + rx_buffer->head = i; + } +} + +#if defined(__AVR_ATmega1280__) + +SIGNAL(SIG_USART0_RECV) +{ + unsigned char c = UDR0; + store_char(c, &rx_buffer); +} + +SIGNAL(SIG_USART1_RECV) +{ + unsigned char c = UDR1; + store_char(c, &rx_buffer1); +} + +SIGNAL(SIG_USART2_RECV) +{ + unsigned char c = UDR2; + store_char(c, &rx_buffer2); +} + +SIGNAL(SIG_USART3_RECV) +{ + unsigned char c = UDR3; + store_char(c, &rx_buffer3); +} + +#else + +#if defined(__AVR_ATmega8__) +SIGNAL(SIG_UART_RECV) +#else +SIGNAL(USART_RX_vect) +#endif +{ +#if defined(__AVR_ATmega8__) + unsigned char c = UDR; +#else + unsigned char c = UDR0; +#endif + store_char(c, &rx_buffer); +} + +#endif + +// Constructors //////////////////////////////////////////////////////////////// + +HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre) +{ + _rx_buffer = rx_buffer; + _ubrrh = ubrrh; + _ubrrl = ubrrl; + _ucsra = ucsra; + _ucsrb = ucsrb; + _udr = udr; + _rxen = rxen; + _txen = txen; + _rxcie = rxcie; + _udre = udre; +} + // Public Methods ////////////////////////////////////////////////////////////// void HardwareSerial::begin(long speed) { - beginSerial(speed); + *_ubrrh = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8; + *_ubrrl = ((F_CPU / 16 + speed / 2) / speed - 1); + sbi(*_ucsrb, _rxen); + sbi(*_ucsrb, _txen); + sbi(*_ucsrb, _rxcie); } uint8_t HardwareSerial::available(void) { - return serialAvailable(); + return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; } int HardwareSerial::read(void) { - return serialRead(); + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; + _rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + return c; + } } void HardwareSerial::flush() { - serialFlush(); + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // were full, not empty. + _rx_buffer->head = _rx_buffer->tail; } -void HardwareSerial::write(uint8_t b) { - serialWrite(b); +void HardwareSerial::write(uint8_t c) +{ + while (!((*_ucsra) & (1 << _udre))) + ; + + *_udr = c; } // Preinstantiate Objects ////////////////////////////////////////////////////// -HardwareSerial Serial = HardwareSerial(); +#if defined(__AVR_ATmega8__) +HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE); +#else +HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0); +#endif + +#if defined(__AVR_ATmega1280__) +HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1); +HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2); +HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3); +#endif diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index e4cb969..55abf07 100755 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -24,9 +24,27 @@ #include "Print.h" +struct ring_buffer; + class HardwareSerial : public Print { + private: + ring_buffer *_rx_buffer; + volatile uint8_t *_ubrrh; + volatile uint8_t *_ubrrl; + volatile uint8_t *_ucsra; + volatile uint8_t *_ucsrb; + volatile uint8_t *_udr; + uint8_t _rxen; + uint8_t _txen; + uint8_t _rxcie; + uint8_t _udre; public: + HardwareSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre); void begin(long); uint8_t available(void); int read(void); @@ -36,5 +54,11 @@ class HardwareSerial : public Print extern HardwareSerial Serial; +#if defined(__AVR_ATmega1280__) +extern HardwareSerial Serial1; +extern HardwareSerial Serial2; +extern HardwareSerial Serial3; +#endif + #endif diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 8b9003f..69a78b0 100755 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -44,29 +44,101 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { intFunc[interruptNum] = userFunc; - if (interruptNum == 0) { - // Configure the interrupt mode (trigger on low input, any change, rising - // edge, or falling edge). The mode constants were chosen to correspond - // to the configuration bits in the hardware register, so we simply shift - // the mode into place. - EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + // Configure the interrupt mode (trigger on low input, any change, rising + // edge, or falling edge). The mode constants were chosen to correspond + // to the configuration bits in the hardware register, so we simply shift + // the mode into place. - // Enable the interrupt. + // Enable the interrupt. + + switch (interruptNum) { +#if defined(__AVR_ATmega1280__) + case 2: + EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); EIMSK |= (1 << INT0); - } else { + break; + case 3: EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); EIMSK |= (1 << INT1); + break; + case 4: + EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20); + EIMSK |= (1 << INT2); + break; + case 5: + EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30); + EIMSK |= (1 << INT3); + break; + case 0: + EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40); + EIMSK |= (1 << INT4); + break; + case 1: + EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50); + EIMSK |= (1 << INT5); + break; + case 6: + EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60); + EIMSK |= (1 << INT6); + break; + case 7: + EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70); + EIMSK |= (1 << INT7); + break; +#else + case 0: + EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + EIMSK |= (1 << INT0); + break; + case 1: + EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + EIMSK |= (1 << INT1); + break; +#endif } } } void detachInterrupt(uint8_t interruptNum) { if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { - if (interruptNum == 0) - // Disable the interrupt. + // Disable the interrupt. (We can't assume that interruptNum is equal + // to the number of the EIMSK bit to clear, as this isn't true on the + // ATmega8. There, INT0 is 6 and INT1 is 7.) + switch (interruptNum) { +#if defined(__AVR_ATmega1280__) + case 2: EIMSK &= ~(1 << INT0); - else + break; + case 3: EIMSK &= ~(1 << INT1); + break; + case 4: + EIMSK &= ~(1 << INT2); + break; + case 5: + EIMSK &= ~(1 << INT3); + break; + case 0: + EIMSK &= ~(1 << INT4); + break; + case 1: + EIMSK &= ~(1 << INT5); + break; + case 6: + EIMSK &= ~(1 << INT6); + break; + case 7: + EIMSK &= ~(1 << INT7); + break; +#else + case 0: + EIMSK &= ~(1 << INT0); + break; + case 1: + EIMSK &= ~(1 << INT1); + break; +#endif + } intFunc[interruptNum] = 0; } @@ -78,6 +150,50 @@ void attachInterruptTwi(void (*userFunc)(void) ) { } */ +#if defined(__AVR_ATmega1280__) + +SIGNAL(INT0_vect) { + if(intFunc[EXTERNAL_INT_2]) + intFunc[EXTERNAL_INT_2](); +} + +SIGNAL(INT1_vect) { + if(intFunc[EXTERNAL_INT_3]) + intFunc[EXTERNAL_INT_3](); +} + +SIGNAL(INT2_vect) { + if(intFunc[EXTERNAL_INT_4]) + intFunc[EXTERNAL_INT_4](); +} + +SIGNAL(INT3_vect) { + if(intFunc[EXTERNAL_INT_5]) + intFunc[EXTERNAL_INT_5](); +} + +SIGNAL(INT4_vect) { + if(intFunc[EXTERNAL_INT_0]) + intFunc[EXTERNAL_INT_0](); +} + +SIGNAL(INT5_vect) { + if(intFunc[EXTERNAL_INT_1]) + intFunc[EXTERNAL_INT_1](); +} + +SIGNAL(INT6_vect) { + if(intFunc[EXTERNAL_INT_6]) + intFunc[EXTERNAL_INT_6](); +} + +SIGNAL(INT7_vect) { + if(intFunc[EXTERNAL_INT_7]) + intFunc[EXTERNAL_INT_7](); +} + +#else + SIGNAL(INT0_vect) { if(intFunc[EXTERNAL_INT_0]) intFunc[EXTERNAL_INT_0](); @@ -88,6 +204,8 @@ SIGNAL(INT1_vect) { intFunc[EXTERNAL_INT_1](); } +#endif + /* SIGNAL(SIG_2WIRE_SERIAL) { if(twiIntFunc) diff --git a/cores/arduino/pins_arduino.c b/cores/arduino/pins_arduino.c index ef3f168..1c1c088 100755 --- a/cores/arduino/pins_arduino.c +++ b/cores/arduino/pins_arduino.c @@ -51,15 +51,315 @@ // // (PWM+ indicates the additional PWM pins on the ATmega168.) +// ATMEL ATMEGA1280 / ARDUINO +// +// 0-7 PE0-PE7 works +// 8-13 PB0-PB5 works +// 14-21 PA0-PA7 works +// 22-29 PH0-PH7 works +// 30-35 PG5-PG0 works +// 36-43 PC7-PC0 works +// 44-51 PJ7-PJ0 works +// 52-59 PL7-PL0 works +// 60-67 PD7-PD0 works +// A0-A7 PF0-PF7 +// A8-A15 PK0-PK7 +#define PA 1 #define PB 2 #define PC 3 #define PD 4 +#define PE 5 +#define PF 6 +#define PG 7 +#define PH 8 +#define PJ 10 +#define PK 11 +#define PL 12 +#define REPEAT8(x) x, x, x, x, x, x, x, x +#define BV0TO7 _BV(0), _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7) +#define BV7TO0 _BV(7), _BV(6), _BV(5), _BV(4), _BV(3), _BV(2), _BV(1), _BV(0) + + +#if defined(__AVR_ATmega1280__) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + &DDRA, + &DDRB, + &DDRC, + &DDRD, + &DDRE, + &DDRF, + &DDRG, + &DDRH, + NOT_A_PORT, + &DDRJ, + &DDRK, + &DDRL, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + &PORTA, + &PORTB, + &PORTC, + &PORTD, + &PORTE, + &PORTF, + &PORTG, + &PORTH, + NOT_A_PORT, + &PORTJ, + &PORTK, + &PORTL, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PIN, + &PINA, + &PINB, + &PINC, + &PIND, + &PINE, + &PINF, + &PING, + &PINH, + NOT_A_PIN, + &PINJ, + &PINK, + &PINL, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + // PORTLIST + // ------------------------------------------- + PE , // PE 0 ** 0 ** USART0_RX + PE , // PE 1 ** 1 ** USART0_TX + PE , // PE 4 ** 2 ** PWM2 + PE , // PE 5 ** 3 ** PWM3 + PG , // PG 5 ** 4 ** PWM4 + PE , // PE 3 ** 5 ** PWM5 + PH , // PH 3 ** 6 ** PWM6 + PH , // PH 4 ** 7 ** PWM7 + PH , // PH 5 ** 8 ** PWM8 + PH , // PH 6 ** 9 ** PWM9 + PB , // PB 4 ** 10 ** PWM10 + PB , // PB 5 ** 11 ** PWM11 + PB , // PB 6 ** 12 ** PWM12 + PB , // PB 7 ** 13 ** PWM13 + PJ , // PJ 1 ** 14 ** USART3_TX + PJ , // PJ 0 ** 15 ** USART3_RX + PH , // PH 1 ** 16 ** USART2_TX + PH , // PH 0 ** 17 ** USART2_RX + PD , // PD 3 ** 18 ** USART1_TX + PD , // PD 2 ** 19 ** USART1_RX + PD , // PD 1 ** 20 ** I2C_SDA + PD , // PD 0 ** 21 ** I2C_SCL + PA , // PA 0 ** 22 ** D22 + PA , // PA 1 ** 23 ** D23 + PA , // PA 2 ** 24 ** D24 + PA , // PA 3 ** 25 ** D25 + PA , // PA 4 ** 26 ** D26 + PA , // PA 5 ** 27 ** D27 + PA , // PA 6 ** 28 ** D28 + PA , // PA 7 ** 29 ** D29 + PC , // PC 7 ** 30 ** D30 + PC , // PC 6 ** 31 ** D31 + PC , // PC 5 ** 32 ** D32 + PC , // PC 4 ** 33 ** D33 + PC , // PC 3 ** 34 ** D34 + PC , // PC 2 ** 35 ** D35 + PC , // PC 1 ** 36 ** D36 + PC , // PC 0 ** 37 ** D37 + PD , // PD 7 ** 38 ** D38 + PG , // PG 2 ** 39 ** D39 + PG , // PG 1 ** 40 ** D40 + PG , // PG 0 ** 41 ** D41 + PL , // PL 7 ** 42 ** D42 + PL , // PL 6 ** 43 ** D43 + PL , // PL 5 ** 44 ** D44 + PL , // PL 4 ** 45 ** D45 + PL , // PL 3 ** 46 ** D46 + PL , // PL 2 ** 47 ** D47 + PL , // PL 1 ** 48 ** D48 + PL , // PL 0 ** 49 ** D49 + PB , // PB 3 ** 50 ** SPI_MISO + PB , // PB 2 ** 51 ** SPI_MOSI + PB , // PB 1 ** 52 ** SPI_SCK + PB , // PB 0 ** 53 ** SPI_SS + PF , // PF 0 ** 54 ** A0 + PF , // PF 1 ** 55 ** A1 + PF , // PF 2 ** 56 ** A2 + PF , // PF 3 ** 57 ** A3 + PF , // PF 4 ** 58 ** A4 + PF , // PF 5 ** 59 ** A5 + PF , // PF 6 ** 60 ** A6 + PF , // PF 7 ** 61 ** A7 + PK , // PK 0 ** 62 ** A8 + PK , // PK 1 ** 63 ** A9 + PK , // PK 2 ** 64 ** A10 + PK , // PK 3 ** 65 ** A11 + PK , // PK 4 ** 66 ** A12 + PK , // PK 5 ** 67 ** A13 + PK , // PK 6 ** 68 ** A14 + PK , // PK 7 ** 69 ** A15 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + // PIN IN PORT + // ------------------------------------------- + _BV( 0 ) , // PE 0 ** 0 ** USART0_RX + _BV( 1 ) , // PE 1 ** 1 ** USART0_TX + _BV( 4 ) , // PE 4 ** 2 ** PWM2 + _BV( 5 ) , // PE 5 ** 3 ** PWM3 + _BV( 5 ) , // PG 5 ** 4 ** PWM4 + _BV( 3 ) , // PE 3 ** 5 ** PWM5 + _BV( 3 ) , // PH 3 ** 6 ** PWM6 + _BV( 4 ) , // PH 4 ** 7 ** PWM7 + _BV( 5 ) , // PH 5 ** 8 ** PWM8 + _BV( 6 ) , // PH 6 ** 9 ** PWM9 + _BV( 4 ) , // PB 4 ** 10 ** PWM10 + _BV( 5 ) , // PB 5 ** 11 ** PWM11 + _BV( 6 ) , // PB 6 ** 12 ** PWM12 + _BV( 7 ) , // PB 7 ** 13 ** PWM13 + _BV( 1 ) , // PJ 1 ** 14 ** USART3_TX + _BV( 0 ) , // PJ 0 ** 15 ** USART3_RX + _BV( 1 ) , // PH 1 ** 16 ** USART2_TX + _BV( 0 ) , // PH 0 ** 17 ** USART2_RX + _BV( 3 ) , // PD 3 ** 18 ** USART1_TX + _BV( 2 ) , // PD 2 ** 19 ** USART1_RX + _BV( 1 ) , // PD 1 ** 20 ** I2C_SDA + _BV( 0 ) , // PD 0 ** 21 ** I2C_SCL + _BV( 0 ) , // PA 0 ** 22 ** D22 + _BV( 1 ) , // PA 1 ** 23 ** D23 + _BV( 2 ) , // PA 2 ** 24 ** D24 + _BV( 3 ) , // PA 3 ** 25 ** D25 + _BV( 4 ) , // PA 4 ** 26 ** D26 + _BV( 5 ) , // PA 5 ** 27 ** D27 + _BV( 6 ) , // PA 6 ** 28 ** D28 + _BV( 7 ) , // PA 7 ** 29 ** D29 + _BV( 7 ) , // PC 7 ** 30 ** D30 + _BV( 6 ) , // PC 6 ** 31 ** D31 + _BV( 5 ) , // PC 5 ** 32 ** D32 + _BV( 4 ) , // PC 4 ** 33 ** D33 + _BV( 3 ) , // PC 3 ** 34 ** D34 + _BV( 2 ) , // PC 2 ** 35 ** D35 + _BV( 1 ) , // PC 1 ** 36 ** D36 + _BV( 0 ) , // PC 0 ** 37 ** D37 + _BV( 7 ) , // PD 7 ** 38 ** D38 + _BV( 2 ) , // PG 2 ** 39 ** D39 + _BV( 1 ) , // PG 1 ** 40 ** D40 + _BV( 0 ) , // PG 0 ** 41 ** D41 + _BV( 7 ) , // PL 7 ** 42 ** D42 + _BV( 6 ) , // PL 6 ** 43 ** D43 + _BV( 5 ) , // PL 5 ** 44 ** D44 + _BV( 4 ) , // PL 4 ** 45 ** D45 + _BV( 3 ) , // PL 3 ** 46 ** D46 + _BV( 2 ) , // PL 2 ** 47 ** D47 + _BV( 1 ) , // PL 1 ** 48 ** D48 + _BV( 0 ) , // PL 0 ** 49 ** D49 + _BV( 3 ) , // PB 3 ** 50 ** SPI_MISO + _BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI + _BV( 1 ) , // PB 1 ** 52 ** SPI_SCK + _BV( 0 ) , // PB 0 ** 53 ** SPI_SS + _BV( 0 ) , // PF 0 ** 54 ** A0 + _BV( 1 ) , // PF 1 ** 55 ** A1 + _BV( 2 ) , // PF 2 ** 56 ** A2 + _BV( 3 ) , // PF 3 ** 57 ** A3 + _BV( 4 ) , // PF 4 ** 58 ** A4 + _BV( 5 ) , // PF 5 ** 59 ** A5 + _BV( 6 ) , // PF 6 ** 60 ** A6 + _BV( 7 ) , // PF 7 ** 61 ** A7 + _BV( 0 ) , // PK 0 ** 62 ** A8 + _BV( 1 ) , // PK 1 ** 63 ** A9 + _BV( 2 ) , // PK 2 ** 64 ** A10 + _BV( 3 ) , // PK 3 ** 65 ** A11 + _BV( 4 ) , // PK 4 ** 66 ** A12 + _BV( 5 ) , // PK 5 ** 67 ** A13 + _BV( 6 ) , // PK 6 ** 68 ** A14 + _BV( 7 ) , // PK 7 ** 69 ** A15 +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { + // TIMERS + // ------------------------------------------- + NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX + NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX + TIMER3B , // PE 4 ** 2 ** PWM2 + TIMER3C , // PE 5 ** 3 ** PWM3 + TIMER0B , // PG 5 ** 4 ** PWM4 + TIMER3A , // PE 3 ** 5 ** PWM5 + TIMER4A , // PH 3 ** 6 ** PWM6 + TIMER4B , // PH 4 ** 7 ** PWM7 + TIMER4C , // PH 5 ** 8 ** PWM8 + TIMER2B , // PH 6 ** 9 ** PWM9 + TIMER2A , // PB 4 ** 10 ** PWM10 + TIMER1A , // PB 5 ** 11 ** PWM11 + TIMER1B , // PB 6 ** 12 ** PWM12 + TIMER0A , // PB 7 ** 13 ** PWM13 + NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX + NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX + NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX + NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX + NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX + NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX + NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA + NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL + NOT_ON_TIMER , // PA 0 ** 22 ** D22 + NOT_ON_TIMER , // PA 1 ** 23 ** D23 + NOT_ON_TIMER , // PA 2 ** 24 ** D24 + NOT_ON_TIMER , // PA 3 ** 25 ** D25 + NOT_ON_TIMER , // PA 4 ** 26 ** D26 + NOT_ON_TIMER , // PA 5 ** 27 ** D27 + NOT_ON_TIMER , // PA 6 ** 28 ** D28 + NOT_ON_TIMER , // PA 7 ** 29 ** D29 + NOT_ON_TIMER , // PC 7 ** 30 ** D30 + NOT_ON_TIMER , // PC 6 ** 31 ** D31 + NOT_ON_TIMER , // PC 5 ** 32 ** D32 + NOT_ON_TIMER , // PC 4 ** 33 ** D33 + NOT_ON_TIMER , // PC 3 ** 34 ** D34 + NOT_ON_TIMER , // PC 2 ** 35 ** D35 + NOT_ON_TIMER , // PC 1 ** 36 ** D36 + NOT_ON_TIMER , // PC 0 ** 37 ** D37 + NOT_ON_TIMER , // PD 7 ** 38 ** D38 + NOT_ON_TIMER , // PG 2 ** 39 ** D39 + NOT_ON_TIMER , // PG 1 ** 40 ** D40 + NOT_ON_TIMER , // PG 0 ** 41 ** D41 + NOT_ON_TIMER , // PL 7 ** 42 ** D42 + NOT_ON_TIMER , // PL 6 ** 43 ** D43 + TIMER5C , // PL 5 ** 44 ** D44 + TIMER5B , // PL 4 ** 45 ** D45 + TIMER5A , // PL 3 ** 46 ** D46 + NOT_ON_TIMER , // PL 2 ** 47 ** D47 + NOT_ON_TIMER , // PL 1 ** 48 ** D48 + NOT_ON_TIMER , // PL 0 ** 49 ** D49 + NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO + NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI + NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK + NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS + NOT_ON_TIMER , // PF 0 ** 54 ** A0 + NOT_ON_TIMER , // PF 1 ** 55 ** A1 + NOT_ON_TIMER , // PF 2 ** 56 ** A2 + NOT_ON_TIMER , // PF 3 ** 57 ** A3 + NOT_ON_TIMER , // PF 4 ** 58 ** A4 + NOT_ON_TIMER , // PF 5 ** 59 ** A5 + NOT_ON_TIMER , // PF 6 ** 60 ** A6 + NOT_ON_TIMER , // PF 7 ** 61 ** A7 + NOT_ON_TIMER , // PK 0 ** 62 ** A8 + NOT_ON_TIMER , // PK 1 ** 63 ** A9 + NOT_ON_TIMER , // PK 2 ** 64 ** A10 + NOT_ON_TIMER , // PK 3 ** 65 ** A11 + NOT_ON_TIMER , // PK 4 ** 66 ** A12 + NOT_ON_TIMER , // PK 5 ** 67 ** A13 + NOT_ON_TIMER , // PK 6 ** 68 ** A14 + NOT_ON_TIMER , // PK 7 ** 69 ** A15 +}; +#else // these arrays map port names (e.g. port B) to the // appropriate addresses for various functions (e.g. reading // and writing) -const uint8_t PROGMEM port_to_mode_PGM[] = { +const uint16_t PROGMEM port_to_mode_PGM[] = { NOT_A_PORT, NOT_A_PORT, &DDRB, @@ -67,7 +367,7 @@ const uint8_t PROGMEM port_to_mode_PGM[] = { &DDRD, }; -const uint8_t PROGMEM port_to_output_PGM[] = { +const uint16_t PROGMEM port_to_output_PGM[] = { NOT_A_PORT, NOT_A_PORT, &PORTB, @@ -75,7 +375,7 @@ const uint8_t PROGMEM port_to_output_PGM[] = { &PORTD, }; -const uint8_t PROGMEM port_to_input_PGM[] = { +const uint16_t PROGMEM port_to_input_PGM[] = { NOT_A_PORT, NOT_A_PORT, &PINB, @@ -166,4 +466,4 @@ const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { NOT_ON_TIMER, NOT_ON_TIMER, }; - +#endif diff --git a/cores/arduino/pins_arduino.h b/cores/arduino/pins_arduino.h index e0b7add..c7e40fd 100644 --- a/cores/arduino/pins_arduino.h +++ b/cores/arduino/pins_arduino.h @@ -39,14 +39,25 @@ #define TIMER2A 6 #define TIMER2B 7 -extern const uint8_t PROGMEM port_to_mode_PGM[]; -extern const uint8_t PROGMEM port_to_input_PGM[]; -extern const uint8_t PROGMEM port_to_output_PGM[]; +#define TIMER3A 8 +#define TIMER3B 9 +#define TIMER3C 10 +#define TIMER4A 11 +#define TIMER4B 12 +#define TIMER4C 13 +#define TIMER5A 14 +#define TIMER5B 15 +#define TIMER5C 16 + +// On the ATmega1280, the addresses of some of the port registers are +// greater than 255, so we can't store them in uint8_t's. +extern const uint16_t PROGMEM port_to_mode_PGM[]; +extern const uint16_t PROGMEM port_to_input_PGM[]; +extern const uint16_t PROGMEM port_to_output_PGM[]; extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; - extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; // Get the bit location within the hardware port of the given virtual pin. @@ -58,8 +69,8 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; #define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) #define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) #define analogInPinToBit(P) (P) -#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_output_PGM + (P))) ) -#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) ) -#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) ) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) #endif diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index aaf7b86..73c26f2 100755 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -196,6 +196,17 @@ void init() sbi(TCCR2A, WGM20); #endif +#if defined(__AVR_ATmega1280__) + // set timer 3, 4, 5 prescale factor to 64 + sbi(TCCR3B, CS31); sbi(TCCR3B, CS30); + sbi(TCCR4B, CS41); sbi(TCCR4B, CS40); + sbi(TCCR5B, CS51); sbi(TCCR5B, CS50); + // put timer 3, 4, 5 in 8-bit phase correct pwm mode + sbi(TCCR3A, WGM30); + sbi(TCCR4A, WGM40); + sbi(TCCR5A, WGM50); +#endif + // set a2d prescale factor to 128 // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. // XXX: this will not work properly for other clock speeds, and diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index f3767d2..529ad52 100755 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -37,12 +37,18 @@ void analogReference(uint8_t mode) int analogRead(uint8_t pin) { - uint8_t low, high, ch = analogInPinToBit(pin); + uint8_t low, high; // set the analog reference (high two bits of ADMUX) and select the // channel (low 4 bits). this also sets ADLAR (left-adjust result) // to 0 (the default). - ADMUX = (analog_reference << 6) | (pin & 0x0f); + ADMUX = (analog_reference << 6) | (pin & 0x07); + +#if defined(__AVR_ATmega1280__) + // the MUX5 bit of ADCSRB selects whether we're reading from channels + // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). + ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); +#endif // without a delay, we seem to read from the wrong channel //delay(1); @@ -95,23 +101,23 @@ void analogWrite(uint8_t pin, int val) OCR2 = val; #else } else if (digitalPinToTimer(pin) == TIMER0A) { - if (val == 0) { - digitalWrite(pin, LOW); - } else { - // connect pwm to pin on timer 0, channel A - sbi(TCCR0A, COM0A1); - // set pwm duty - OCR0A = val; - } + if (val == 0) { + digitalWrite(pin, LOW); + } else { + // connect pwm to pin on timer 0, channel A + sbi(TCCR0A, COM0A1); + // set pwm duty + OCR0A = val; + } } else if (digitalPinToTimer(pin) == TIMER0B) { - if (val == 0) { - digitalWrite(pin, LOW); - } else { - // connect pwm to pin on timer 0, channel B - sbi(TCCR0A, COM0B1); - // set pwm duty - OCR0B = val; - } + if (val == 0) { + digitalWrite(pin, LOW); + } else { + // connect pwm to pin on timer 0, channel B + sbi(TCCR0A, COM0B1); + // set pwm duty + OCR0B = val; + } } else if (digitalPinToTimer(pin) == TIMER2A) { // connect pwm to pin on timer 2, channel A sbi(TCCR2A, COM2A1); @@ -122,6 +128,49 @@ void analogWrite(uint8_t pin, int val) sbi(TCCR2A, COM2B1); // set pwm duty OCR2B = val; +#endif +#if defined(__AVR_ATmega1280__) + // XXX: need to handle other timers here + } else if (digitalPinToTimer(pin) == TIMER3A) { + // connect pwm to pin on timer 3, channel A + sbi(TCCR3A, COM3A1); + // set pwm duty + OCR3A = val; + } else if (digitalPinToTimer(pin) == TIMER3B) { + // connect pwm to pin on timer 3, channel B + sbi(TCCR3A, COM3B1); + // set pwm duty + OCR3B = val; + } else if (digitalPinToTimer(pin) == TIMER3C) { + // connect pwm to pin on timer 3, channel C + sbi(TCCR3A, COM3C1); + // set pwm duty + OCR3C = val; + } else if (digitalPinToTimer(pin) == TIMER4A) { + // connect pwm to pin on timer 4, channel A + sbi(TCCR4A, COM4A1); + // set pwm duty + OCR4A = val; + } else if (digitalPinToTimer(pin) == TIMER4B) { + // connect pwm to pin on timer 4, channel B + sbi(TCCR4A, COM4B1); + // set pwm duty + OCR4B = val; + } else if (digitalPinToTimer(pin) == TIMER4C) { + // connect pwm to pin on timer 4, channel C + sbi(TCCR4A, COM4C1); + // set pwm duty + OCR4C = val; + } else if (digitalPinToTimer(pin) == TIMER5A) { + // connect pwm to pin on timer 5, channel A + sbi(TCCR5A, COM5A1); + // set pwm duty + OCR5A = val; + } else if (digitalPinToTimer(pin) == TIMER5B) { + // connect pwm to pin on timer 5, channel B + sbi(TCCR5A, COM5B1); + // set pwm duty + OCR5B = val; #endif } else if (val < 128) digitalWrite(pin, LOW); diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 3044e18..1cdbf6c 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -61,6 +61,18 @@ static inline void turnOffPWM(uint8_t timer) if (timer == TIMER2A) cbi(TCCR2A, COM2A1); if (timer == TIMER2B) cbi(TCCR2A, COM2B1); #endif + +#if defined(__AVR_ATmega1280__) + if (timer == TIMER3A) cbi(TCCR3A, COM3A1); + if (timer == TIMER3B) cbi(TCCR3A, COM3B1); + if (timer == TIMER3C) cbi(TCCR3A, COM3C1); + if (timer == TIMER4A) cbi(TCCR4A, COM4A1); + if (timer == TIMER4B) cbi(TCCR4A, COM4B1); + if (timer == TIMER4C) cbi(TCCR4A, COM4C1); + if (timer == TIMER5A) cbi(TCCR5A, COM5A1); + if (timer == TIMER5B) cbi(TCCR5A, COM5B1); + if (timer == TIMER5C) cbi(TCCR5A, COM5C1); +#endif } void digitalWrite(uint8_t pin, uint8_t val) diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h index b30c1f0..2dfe552 100755 --- a/cores/arduino/wiring_private.h +++ b/cores/arduino/wiring_private.h @@ -46,8 +46,18 @@ extern "C"{ #define EXTERNAL_INT_0 0 #define EXTERNAL_INT_1 1 +#define EXTERNAL_INT_2 2 +#define EXTERNAL_INT_3 3 +#define EXTERNAL_INT_4 4 +#define EXTERNAL_INT_5 5 +#define EXTERNAL_INT_6 6 +#define EXTERNAL_INT_7 7 +#if defined(__AVR_ATmega1280__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#else #define EXTERNAL_NUM_INTERRUPTS 2 +#endif typedef void (*voidFuncPtr)(void);