Adding support for the Arduino Mega (ATmega1280) to the core and bootloader.

This commit is contained in:
David A. Mellis 2009-03-25 10:50:00 +00:00
parent b89ee8da48
commit a42326aba2
13 changed files with 1093 additions and 91 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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 <string.h>
#include <inttypes.h>
#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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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);