From a42326aba2fd9696a4b2e1239a5a222014056ff5 Mon Sep 17 00:00:00 2001
From: "David A. Mellis" <d.mellis@arduino.cc>
Date: Wed, 25 Mar 2009 10:50:00 +0000
Subject: Adding support for the Arduino Mega (ATmega1280) to the core and
 bootloader.

---
 cores/arduino/HardwareSerial.cpp | 149 ++++++++++++++++++-
 cores/arduino/HardwareSerial.h   |  24 +++
 cores/arduino/WInterrupts.c      | 140 ++++++++++++++++--
 cores/arduino/pins_arduino.c     | 308 ++++++++++++++++++++++++++++++++++++++-
 cores/arduino/pins_arduino.h     |  27 +++-
 cores/arduino/wiring.c           |  11 ++
 cores/arduino/wiring_analog.c    |  85 ++++++++---
 cores/arduino/wiring_digital.c   |  12 ++
 cores/arduino/wiring_private.h   |  10 ++
 9 files changed, 717 insertions(+), 49 deletions(-)

(limited to 'cores')

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 <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
 
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);
+      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);
-    } else {
+      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);
+      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);
-    else
+      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);
 
-- 
cgit v1.2.3-18-g5258