From 3cd1d4e60679b0d6222f945ff06942f8b9350c30 Mon Sep 17 00:00:00 2001
From: Thibaut VIARD <thibaut.viard@atmel.com>
Date: Thu, 15 May 2014 00:07:03 +0200
Subject: [PATCH]  Bringing support of External Interrupts

---
 cores/arduino/Arduino.h                       |  17 --
 cores/arduino/WInterrupts.c                   | 230 ++++++++++++++++++
 cores/arduino/WInterrupts.c.disabled          | 182 --------------
 cores/arduino/WInterrupts.h                   |  53 +++-
 cores/arduino/WVariant.h                      |  66 ++++-
 cores/arduino/wiring_analog.c                 |  12 +-
 cores/arduino/wiring_constants.h              |  18 +-
 cores/arduino/wiring_digital.h                |  10 +-
 .../validation_core/build_as6/test.cppproj    |   4 +
 cores/validation/validation_core/test.cpp     |  85 ++++++-
 variants/arduino_zero/variant.cpp             |  92 +++----
 variants/arduino_zero/variant.h               |   2 +-
 12 files changed, 496 insertions(+), 275 deletions(-)
 create mode 100644 cores/arduino/WInterrupts.c
 delete mode 100644 cores/arduino/WInterrupts.c.disabled

diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h
index ee106b5b..f550858b 100644
--- a/cores/arduino/Arduino.h
+++ b/cores/arduino/Arduino.h
@@ -53,23 +53,6 @@ void yield( void ) ;
 void setup( void ) ;
 void loop( void ) ;
 
-#define NOT_AN_INTERRUPT -1
-
-typedef enum _EExt_Interrupts
-{
-  EXTERNAL_INT_0=0,
-  EXTERNAL_INT_1=1,
-  EXTERNAL_INT_2=2,
-  EXTERNAL_INT_3=3,
-  EXTERNAL_INT_4=4,
-  EXTERNAL_INT_5=5,
-  EXTERNAL_INT_6=6,
-  EXTERNAL_INT_7=7,
-  EXTERNAL_NUM_INTERRUPTS
-} EExt_Interrupts ;
-
-typedef void (*voidFuncPtr)( void ) ;
-
 #include "WVariant.h"
 
 #ifdef __cplusplus
diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c
new file mode 100644
index 00000000..6bbdf362
--- /dev/null
+++ b/cores/arduino/WInterrupts.c
@@ -0,0 +1,230 @@
+/*
+  Copyright (c) 2014 Arduino.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "WInterrupts.h"
+#include "variant.h"
+#include "wiring_digital.h"
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static struct
+{
+  uint32_t _ulPin ;
+  voidFuncPtr _callback ;
+} callbacksInt[EXTERNAL_NUM_INTERRUPTS] ;
+
+/* Configure I/O interrupt sources */
+static void __initialize()
+{
+#if 0
+  int i ;
+
+  for ( i = 0 ; i < EXTERNAL_NUM_INTERRUPTS ; i++ )
+  {
+    callbacksInt[i]._callback = NULL ;
+  }
+#else
+  memset( callbacksInt, 0, sizeof( callbacksInt ) ) ;
+#endif
+
+  NVIC_DisableIRQ( EIC_IRQn ) ;
+  NVIC_ClearPendingIRQ( EIC_IRQn ) ;
+  NVIC_SetPriority( EIC_IRQn, 0 ) ;
+  NVIC_EnableIRQ( EIC_IRQn ) ;
+
+  // Enable GCLK for IEC (External Interrupt Controller)
+  GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_EIC )) ;
+
+/* Shall we do that?
+  // Do a software reset on EIC
+  EIC->CTRL.SWRST.bit = 1 ;
+
+  while ( (EIC->CTRL.SWRST.bit == 1) && (EIC->STATUS.SYNCBUSY.bit == 1) )
+  {
+    // Wait for synchronisation
+  }
+*/
+}
+
+/*
+ * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
+ *        Replaces any previous function that was attached to the interrupt.
+ */
+//void attachInterrupt( uint32_t ulPin, void (*callback)(void), EExt_IntMode mode )
+//void attachInterrupt( uint32_t ulPin, voidFuncPtr callback, EExt_IntMode mode )
+void attachInterrupt( uint32_t ulPin, voidFuncPtr callback, uint32_t ulMode )
+{
+  static int enabled = 0 ;
+  uint32_t ulConfig ;
+  uint32_t ulPos ;
+
+  if ( digitalPinToInterrupt( ulPin ) == NOT_AN_INTERRUPT )
+  {
+    return ;
+  }
+
+  if ( !enabled )
+  {
+    __initialize() ;
+    enabled = 1 ;
+  }
+
+  // Assign pin to EIC
+  pinPeripheral( ulPin, PIO_EXTINT ) ;
+
+  // Assign callback to interrupt
+  callbacksInt[digitalPinToInterrupt( ulPin )]._ulPin = ulPin ;
+  callbacksInt[digitalPinToInterrupt( ulPin )]._callback = callback ;
+
+  // Check if normal interrupt or NMI
+  if ( ulPin != 2 )
+  {
+    // Look for right CONFIG register to be addressed
+    if ( digitalPinToInterrupt( ulPin ) > EXTERNAL_INT_7 )
+    {
+      ulConfig = 1 ;
+    }
+    else
+    {
+      ulConfig = 0 ;
+    }
+
+    // Configure the interrupt mode
+    ulPos = ((digitalPinToInterrupt( ulPin ) >> ulConfig ) << 2) ;
+    switch ( ulMode )
+    {
+      case LOW:
+        EIC->CONFIG[ulConfig].reg = EIC_CONFIG_SENSE0_LOW_Val << ulPos ;
+      break ;
+
+      case HIGH:
+        EIC->CONFIG[ulConfig].reg = EIC_CONFIG_SENSE0_HIGH_Val << ((digitalPinToInterrupt( ulPin ) >> ulConfig ) << 2) ;
+      break ;
+
+      case CHANGE:
+        EIC->CONFIG[ulConfig].reg = EIC_CONFIG_SENSE0_BOTH_Val << ((digitalPinToInterrupt( ulPin ) >> ulConfig ) << 2) ;
+      break ;
+
+      case FALLING:
+        EIC->CONFIG[ulConfig].reg = EIC_CONFIG_SENSE0_FALL_Val << ((digitalPinToInterrupt( ulPin ) >> ulConfig ) << 2) ;
+      break ;
+
+      case RISING:
+        EIC->CONFIG[ulConfig].reg = EIC_CONFIG_SENSE0_RISE_Val << ((digitalPinToInterrupt( ulPin ) >> ulConfig ) << 2) ;
+      break ;
+    }
+
+    // Enable the interrupt
+    EIC->INTENSET.reg = EIC_INTENSET_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ;
+  }
+  else // Handles NMI on pin 2
+  {
+    // Configure the interrupt mode
+    switch ( ulMode )
+    {
+      case LOW:
+        EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_LOW ;
+      break ;
+
+      case HIGH:
+        EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_HIGH ;
+      break ;
+
+      case CHANGE:
+        EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_BOTH ;
+      break ;
+
+      case FALLING:
+        EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_FALL ;
+      break ;
+
+      case RISING:
+        EIC->NMICTRL.reg= EIC_NMICTRL_NMISENSE_RISE ;
+      break ;
+    }
+
+    // Enable the interrupt
+    EIC->INTENSET.reg = EIC_INTENSET_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ;
+  }
+}
+
+/*
+ * \brief Turns off the given interrupt.
+ */
+void detachInterrupt( uint32_t ulPin )
+{
+/*
+  // Retrieve pin information
+  Pio *pio = g_APinDescription[pin].pPort;
+  uint32_t mask = g_APinDescription[pin].ulPin;
+
+  // Disable interrupt
+  pio->PIO_IDR = mask;
+*/
+  if ( digitalPinToInterrupt( ulPin ) == NOT_AN_INTERRUPT )
+  {
+    return ;
+  }
+
+  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ;
+}
+
+/*
+ * External Interrupt Controller NVIC Interrupt Handler
+ */
+void EIC_Handler( void )
+{
+  uint32_t ul ;
+
+  // Test NMI first
+  if ( (EIC->NMIFLAG.reg & EIC_NMIFLAG_NMI) == EIC_NMIFLAG_NMI )
+  {
+    // Call the callback function if assigned
+    if ( callbacksInt[EXTERNAL_INT_NMI]._callback != NULL )
+    {
+      callbacksInt[EXTERNAL_INT_NMI]._callback() ;
+    }
+
+    // Clear the interrupt
+    EIC->NMIFLAG.reg = EIC_NMIFLAG_NMI ;
+  }
+
+  // Test the 16 normal interrupts
+  for ( ul = EXTERNAL_INT_0 ; ul < EXTERNAL_INT_15 ; ul++ )
+  {
+    if ( (EIC->INTFLAG.reg & 1 << ul) != 0 )
+    {
+      // Call the callback function if assigned
+      if ( callbacksInt[ul]._callback != NULL )
+      {
+        callbacksInt[ul]._callback() ;
+      }
+
+      // Clear the interrupt
+      EIC->INTFLAG.reg = 1 << ul ;
+    }
+  }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cores/arduino/WInterrupts.c.disabled b/cores/arduino/WInterrupts.c.disabled
deleted file mode 100644
index 87b83e45..00000000
--- a/cores/arduino/WInterrupts.c.disabled
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-  Copyright (c) 2011-2012 Arduino.  All right reserved.
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
-  See the GNU Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "WInterrupts.h"
-
-typedef void (*interruptCB)(void);
-
-static interruptCB callbacksPioA[32];
-static interruptCB callbacksPioB[32];
-static interruptCB callbacksPioC[32];
-static interruptCB callbacksPioD[32];
-
-/* Configure PIO interrupt sources */
-static void __initialize() {
-	int i;
-	for (i=0; i<32; i++) {
-		callbacksPioA[i] = NULL;
-		callbacksPioB[i] = NULL;
-		callbacksPioC[i] = NULL;
-		callbacksPioD[i] = NULL;
-	}
-
-	pmc_enable_periph_clk(ID_PIOA);
-	NVIC_DisableIRQ(PIOA_IRQn);
-	NVIC_ClearPendingIRQ(PIOA_IRQn);
-	NVIC_SetPriority(PIOA_IRQn, 0);
-	NVIC_EnableIRQ(PIOA_IRQn);
-
-	pmc_enable_periph_clk(ID_PIOB);
-	NVIC_DisableIRQ(PIOB_IRQn);
-	NVIC_ClearPendingIRQ(PIOB_IRQn);
-	NVIC_SetPriority(PIOB_IRQn, 0);
-	NVIC_EnableIRQ(PIOB_IRQn);
-
-	pmc_enable_periph_clk(ID_PIOC);
-	NVIC_DisableIRQ(PIOC_IRQn);
-	NVIC_ClearPendingIRQ(PIOC_IRQn);
-	NVIC_SetPriority(PIOC_IRQn, 0);
-	NVIC_EnableIRQ(PIOC_IRQn);
-
-	pmc_enable_periph_clk(ID_PIOD);
-	NVIC_DisableIRQ(PIOD_IRQn);
-	NVIC_ClearPendingIRQ(PIOD_IRQn);
-	NVIC_SetPriority(PIOD_IRQn, 0);
-	NVIC_EnableIRQ(PIOD_IRQn);
-}
-
-
-void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode)
-{
-	static int enabled = 0;
-	if (!enabled) {
-		__initialize();
-		enabled = 1;
-	}
-
-	// Retrieve pin information
-	Pio *pio = g_APinDescription[pin].pPort;
-	uint32_t mask = g_APinDescription[pin].ulPin;
-	uint32_t pos = 0;
-
-	uint32_t t;
-	for (t = mask; t>1; t>>=1, pos++)
-		;
-
-	// Set callback function
-	if (pio == PIOA)
-		callbacksPioA[pos] = callback;
-	if (pio == PIOB)
-		callbacksPioB[pos] = callback;
-	if (pio == PIOC)
-		callbacksPioC[pos] = callback;
-	if (pio == PIOD)
-		callbacksPioD[pos] = callback;
-
-	// Configure the interrupt mode
-	if (mode == CHANGE) {
-		// Disable additional interrupt mode (detects both rising and falling edges)
-		pio->PIO_AIMDR = mask;
-	} else {
-		// Enable additional interrupt mode
-		pio->PIO_AIMER = mask;
-
-		// Select mode of operation
-		if (mode == LOW) {
-			pio->PIO_LSR = mask;    // "Level" Select Register
-			pio->PIO_FELLSR = mask; // "Falling Edge / Low Level" Select Register
-		}
-		if (mode == HIGH) {
-			pio->PIO_LSR = mask;    // "Level" Select Register
-			pio->PIO_REHLSR = mask; // "Rising Edge / High Level" Select Register
-		}
-		if (mode == FALLING) {
-			pio->PIO_ESR = mask;    // "Edge" Select Register
-			pio->PIO_FELLSR = mask; // "Falling Edge / Low Level" Select Register
-		}
-		if (mode == RISING) {
-			pio->PIO_ESR = mask;    // "Edge" Select Register
-			pio->PIO_REHLSR = mask; // "Rising Edge / High Level" Select Register
-		}
-	}
-
-	// Enable interrupt
-	pio->PIO_IER = mask;
-}
-
-void detachInterrupt(uint32_t pin)
-{
-	// Retrieve pin information
-	Pio *pio = g_APinDescription[pin].pPort;
-	uint32_t mask = g_APinDescription[pin].ulPin;
-
-	// Disable interrupt
-	pio->PIO_IDR = mask;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void PIOA_Handler(void) {
-	uint32_t isr = PIOA->PIO_ISR;
-	uint32_t i;
-	for (i=0; i<32; i++, isr>>=1) {
-		if ((isr & 0x1) == 0)
-			continue;
-		if (callbacksPioA[i])
-			callbacksPioA[i]();
-	}
-}
-
-void PIOB_Handler(void) {
-	uint32_t isr = PIOB->PIO_ISR;
-	uint32_t i;
-	for (i=0; i<32; i++, isr>>=1) {
-		if ((isr & 0x1) == 0)
-			continue;
-		if (callbacksPioB[i])
-			callbacksPioB[i]();
-	}
-}
-
-void PIOC_Handler(void) {
-	uint32_t isr = PIOC->PIO_ISR;
-	uint32_t i;
-	for (i=0; i<32; i++, isr>>=1) {
-		if ((isr & 0x1) == 0)
-			continue;
-		if (callbacksPioC[i])
-			callbacksPioC[i]();
-	}
-}
-
-void PIOD_Handler(void) {
-	uint32_t isr = PIOD->PIO_ISR;
-	uint32_t i;
-	for (i=0; i<32; i++, isr>>=1) {
-		if ((isr & 0x1) == 0)
-			continue;
-		if (callbacksPioD[i])
-			callbacksPioD[i]();
-	}
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/cores/arduino/WInterrupts.h b/cores/arduino/WInterrupts.h
index bb698cdf..8314dff2 100644
--- a/cores/arduino/WInterrupts.h
+++ b/cores/arduino/WInterrupts.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2011-2012 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -8,7 +8,7 @@
 
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   See the GNU Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public
@@ -19,18 +19,61 @@
 #ifndef _WIRING_INTERRUPTS_
 #define _WIRING_INTERRUPTS_
 
-#include "Arduino.h"
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
+//      LOW 0
+//      HIGH 1
+#define CHANGE 2
+#define FALLING 3
+#define RISING 4
 
-void detachInterrupt(uint32_t pin);
+///*
+ //* Interrupt modes
+ //*   The two first values are conflicting with the ones used by Digital API, so we use another name for each.
+ //*/
+//typedef enum _EExt_IntMode
+//{
+  //IM_LOW = 0,
+  //IM_HIGH = 1,
+  //CHANGE = 2,
+  //FALLING = 3,
+  //RISING = 4,
+  //IM_CHANGE = 2,
+  //IM_FALLING = 3,
+  //IM_RISING = 4,
+//} EExt_IntMode ;
+
+#define DEFAULT 1
+#define EXTERNAL 0
+
+typedef void (*voidFuncPtr)( void ) ;
+
+/*
+ * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
+ *        Replaces any previous function that was attached to the interrupt.
+ */
+//void attachInterrupt( uint32_t ulPin, void (*callback)(void), EExt_IntMode mode ) ;
+//void attachInterrupt( uint32_t ulPin, voidFuncPtr callback, EExt_IntMode mode ) ;
+void attachInterrupt( uint32_t ulPin, voidFuncPtr callback, uint32_t mode ) ;
+
+/*
+ * \brief Turns off the given interrupt.
+ */
+void detachInterrupt( uint32_t ulPin ) ;
 
 #ifdef __cplusplus
 }
 #endif
 
+//#ifdef __cplusplus
+//inline operator ::EExt_IntMode( uint32_t ul )
+//{
+  //return (EExt_IntMode)ul ;
+//}
+//#endif
+
 #endif /* _WIRING_INTERRUPTS_ */
diff --git a/cores/arduino/WVariant.h b/cores/arduino/WVariant.h
index 2a05298d..295d7dc6 100644
--- a/cores/arduino/WVariant.h
+++ b/cores/arduino/WVariant.h
@@ -78,6 +78,29 @@ typedef enum _EPortType
 	PORTC=2,
 } EPortType ;
 
+typedef enum _EExt_Interrupts
+{
+  EXTERNAL_INT_0 = 0, // Available on pin 11
+  EXTERNAL_INT_1, // Available on pin 13
+  EXTERNAL_INT_2, // Available on pins 10, A0, A5
+  EXTERNAL_INT_3, // Available on pin 12
+  EXTERNAL_INT_4, // Available on pin 6, 8, A3
+  EXTERNAL_INT_5, // Available on pin 7, 9, A4
+  EXTERNAL_INT_6, // Available on pin 16
+  EXTERNAL_INT_7, // Available on pin 17
+  EXTERNAL_INT_8, // Available on pin A1
+  EXTERNAL_INT_9, // Available on pin 3, A2
+  EXTERNAL_INT_10, // Available on pin 0, 21
+  EXTERNAL_INT_11, // Available on pin 1, 20
+  EXTERNAL_INT_12, // Available on pin 18
+  EXTERNAL_INT_13, // Available on pin EDBG_GPIO0 (43)
+  EXTERNAL_INT_14, // Available on pin 4
+  EXTERNAL_INT_15, // Available on pin 5
+  EXTERNAL_INT_NMI, // Available on pin 2
+  EXTERNAL_NUM_INTERRUPTS,
+  NOT_AN_INTERRUPT = -1,
+  EXTERNAL_INT_NONE = NOT_AN_INTERRUPT,
+} EExt_Interrupts ;
 
 //A    B                 C       D          E      F   G   H
 //EIC REF ADC AC PTC DAC SERCOM SERCOM_ALT TC/TCC TCC COM AC/GCLK
@@ -111,6 +134,7 @@ typedef enum _EPioType
 #define PIN_ATTR_DIGITAL       (1UL<<2)
 #define PIN_ATTR_PWM           (1UL<<3)
 #define PIN_ATTR_TIMER         (1UL<<4)
+#define PIN_ATTR_EXTINT        (1UL<<5)
 
 /* Types used for the table below */
 typedef struct _PinDescription
@@ -122,11 +146,51 @@ typedef struct _PinDescription
   EAnalogChannel ulADCChannelNumber ; /* ADC Channel number in the SAM device */
   EPWMChannel ulPWMChannel ;
   ETCChannel ulTCChannel ;
+  EExt_Interrupts ulExtInt ;
 } PinDescription ;
 
-/* Pins table to be instanciated into variant.cpp */
+/* Pins table to be instantiated into variant.cpp */
 extern const PinDescription g_APinDescription[] ;
 
+/* Generic Clock Multiplexer IDs */
+#define GCM_DFLL48M_REF           (0x00U)
+#define GCM_FDPLL96M_INPUT        (0x01U)
+#define GCM_FDPLL96M_32K          (0x02U)
+#define GCM_WDT                   (0x03U)
+#define GCM_RTC                   (0x04U)
+#define GCM_EIC                   (0x05U)
+#define GCM_USB                   (0x06U)
+#define GCM_EVSYS_CHANNEL_0       (0x07U)
+#define GCM_EVSYS_CHANNEL_1       (0x08U)
+#define GCM_EVSYS_CHANNEL_2       (0x09U)
+#define GCM_EVSYS_CHANNEL_3       (0x0AU)
+#define GCM_EVSYS_CHANNEL_4       (0x0BU)
+#define GCM_EVSYS_CHANNEL_5       (0x0CU)
+#define GCM_EVSYS_CHANNEL_6       (0x0DU)
+#define GCM_EVSYS_CHANNEL_7       (0x0EU)
+#define GCM_EVSYS_CHANNEL_8       (0x0FU)
+#define GCM_EVSYS_CHANNEL_9       (0x10U)
+#define GCM_EVSYS_CHANNEL_10      (0x11U)
+#define GCM_EVSYS_CHANNEL_11      (0x12U)
+#define GCM_SERCOMx_SLOW          (0x13U)
+#define GCM_SERCOM0_CORE          (0x14U)
+#define GCM_SERCOM1_CORE          (0x15U)
+#define GCM_SERCOM2_CORE          (0x16U)
+#define GCM_SERCOM3_CORE          (0x17U)
+#define GCM_SERCOM4_CORE          (0x18U)
+#define GCM_SERCOM5_CORE          (0x19U)
+#define GCM_TCC0_TCC1             (0x1AU)
+#define GCM_TCC2_TC3              (0x1BU)
+#define GCM_TC4_TC5               (0x1CU)
+#define GCM_TC6_TC7               (0x1DU)
+#define GCM_ADC                   (0x1EU)
+#define GCM_AC_DIG                (0x1FU)
+#define GCM_AC_ANA                (0x20U)
+#define GCM_DAC                   (0x21U)
+#define GCM_PTC                   (0x22U)
+#define GCM_I2S_0                 (0x23U)
+#define GCM_I2S_1                 (0x24U)
+
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c
index 82ec417e..2a15282c 100644
--- a/cores/arduino/wiring_analog.c
+++ b/cores/arduino/wiring_analog.c
@@ -210,32 +210,32 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
     {
       case 0: // TCC0
         //Enable GCLK for TCC0 (timer counter input clock)
-        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( 0x1A )) ;
+        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
       break ;
 
       case 1: // TCC1
         //Enable GCLK for TCC1 (timer counter input clock)
-        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( 0x1A )) ;
+        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
       break ;
 
       case 2: // TCC2
         //Enable GCLK for TCC2 (timer counter input clock)
-        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( 0x1B )) ;
+        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ;
       break ;
 
       case 3: // TC3
         //Enable GCLK for TC3 (timer counter input clock)
-        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( 0x1B ));
+        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
       break ;
 
       case 4: // TC4
         //Enable GCLK for TC4 (timer counter input clock)
-        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( 0x1C ));
+        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
       break ;
 
       case 5: // TC5
         //Enable GCLK for TC5 (timer counter input clock)
-        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( 0x1C )) ;
+        GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 )) ;
       break ;
     }
 
diff --git a/cores/arduino/wiring_constants.h b/cores/arduino/wiring_constants.h
index aac3734d..df1d7d58 100644
--- a/cores/arduino/wiring_constants.h
+++ b/cores/arduino/wiring_constants.h
@@ -49,14 +49,15 @@ enum BitOrder {
 	MSBFIRST = 1
 };
 
-//      LOW 0
-//      HIGH 1
-#define CHANGE 2
-#define FALLING 3
-#define RISING 4
-
-#define DEFAULT 1
-#define EXTERNAL 0
+// moved to WInterrupts.h
+////      LOW 0
+////      HIGH 1
+//#define CHANGE 2
+//#define FALLING 3
+//#define RISING 4
+//
+//#define DEFAULT 1
+//#define EXTERNAL 0
 
 // undefine stdlib's abs if encountered
 #ifdef abs
@@ -97,7 +98,6 @@ typedef unsigned int word;
 typedef uint8_t boolean ;
 typedef uint8_t byte ;
 
-
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
diff --git a/cores/arduino/wiring_digital.h b/cores/arduino/wiring_digital.h
index 1db6cb56..e4a3ec11 100644
--- a/cores/arduino/wiring_digital.h
+++ b/cores/arduino/wiring_digital.h
@@ -23,12 +23,12 @@
  extern "C" {
 #endif
 
-#define INPUT           (0x0)
-#define OUTPUT          (0x1)
-#define INPUT_PULLUP    (0x2)
+#define INPUT           (0x0ul)
+#define OUTPUT          (0x1ul)
+#define INPUT_PULLUP    (0x2ul)
 
-#define LOW             (0x0)
-#define HIGH            (0x1)
+#define LOW             (0x0ul)
+#define HIGH            (0x1ul)
 
 #include "WVariant.h"
 
diff --git a/cores/validation/validation_core/build_as6/test.cppproj b/cores/validation/validation_core/build_as6/test.cppproj
index 1f5cc024..935a7915 100644
--- a/cores/validation/validation_core/build_as6/test.cppproj
+++ b/cores/validation/validation_core/build_as6/test.cppproj
@@ -385,6 +385,10 @@
       <SubType>compile</SubType>
       <Link>core\WCharacter.h</Link>
     </Compile>
+    <Compile Include="..\..\..\arduino\WInterrupts.c">
+      <SubType>compile</SubType>
+      <Link>core\WInterrupts.c</Link>
+    </Compile>
     <Compile Include="..\..\..\arduino\WInterrupts.h">
       <SubType>compile</SubType>
       <Link>core\WInterrupts.h</Link>
diff --git a/cores/validation/validation_core/test.cpp b/cores/validation/validation_core/test.cpp
index f571465c..0e2a384d 100644
--- a/cores/validation/validation_core/test.cpp
+++ b/cores/validation/validation_core/test.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2011 Arduino.  All right reserved.
+  Copyright (c) 2014 Arduino.  All right reserved.
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -18,6 +18,18 @@
 
 #include "Arduino.h"
 
+static void Interrupt_Pin3( void ) ; // Ext Int Callback in LOW mode
+static void Interrupt_Pin4( void ) ; // Ext Int Callback in HIGH mode
+static void Interrupt_Pin5( void ) ; // Ext Int Callback in FALLING mode
+static void Interrupt_Pin6( void ) ; // Ext Int Callback in RISING mode
+static void Interrupt_Pin7( void ) ; // Ext Int Callback in CHANGE mode
+
+static uint32_t ul_Interrupt_Pin3 = 0 ;
+static uint32_t ul_Interrupt_Pin4 = 0 ;
+static uint32_t ul_Interrupt_Pin5 = 0 ;
+static uint32_t ul_Interrupt_Pin6 = 0 ;
+static uint32_t ul_Interrupt_Pin7 = 0 ;
+
 void setup( void )
 {
   // Initialize the digital pin as an output.
@@ -45,6 +57,13 @@ void setup( void )
 
 //**********************************************
   Serial5.begin( 115200 ) ; // Output to EDBG Virtual COM Port
+
+  // Test External Interrupt
+  attachInterrupt( 3, Interrupt_Pin3, LOW ) ;
+  attachInterrupt( 4, Interrupt_Pin4, HIGH ) ;
+  attachInterrupt( 5, Interrupt_Pin5, FALLING ) ;
+  attachInterrupt( 6, Interrupt_Pin6, RISING ) ;
+  attachInterrupt( 7, Interrupt_Pin7, CHANGE) ;
 }
 
 static void led_step1( void )
@@ -93,11 +112,10 @@ void loop( void )
   analogWrite(  6, duty_cycle ) ;
   analogWrite(  5, duty_cycle ) ;
   analogWrite(  4, duty_cycle ) ;
-  analogWrite(  3, duty_cycle ) ;
 
   Serial5.print("Analog pins: ");
 
-  for ( int i = A1 ; i <= A0+NUM_ANALOG_INPUTS ; i++ )
+  for ( uint32_t i = A1 ; i <= A0+NUM_ANALOG_INPUTS ; i++ )
   {
 /*
     int a = analogRead(i);
@@ -106,4 +124,65 @@ void loop( void )
 */
   }
   Serial5.println();
+
+  Serial5.println("External interrupt pins:");
+  if ( ul_Interrupt_Pin3 == 1 )
+  {
+    Serial5.println( "Pin 3 triggered (LOW)" ) ;
+    ul_Interrupt_Pin3 = 0 ;
+  }
+
+  if ( ul_Interrupt_Pin4 == 1 )
+  {
+    Serial5.println( "Pin 4 triggered (HIGH)" ) ;
+    ul_Interrupt_Pin4 = 0 ;
+  }
+
+  if ( ul_Interrupt_Pin5 == 1 )
+  {
+    Serial5.println( "Pin 5 triggered (FALLING)" ) ;
+    ul_Interrupt_Pin5 = 0 ;
+  }
+
+  if ( ul_Interrupt_Pin6 == 1 )
+  {
+    Serial5.println( "Pin 6 triggered (RISING)" ) ;
+    ul_Interrupt_Pin6 = 0 ;
+  }
+
+  if ( ul_Interrupt_Pin7 == 1 )
+  {
+    Serial5.println( "Pin 3 triggered (CHANGE)" ) ;
+    ul_Interrupt_Pin7 = 0 ;
+  }
+}
+
+// Ext Int Callback in LOW mode
+static void Interrupt_Pin3( void )
+{
+  ul_Interrupt_Pin3 = 1 ;
+}
+
+// Ext Int Callback in HIGH mode
+static void Interrupt_Pin4( void )
+{
+  ul_Interrupt_Pin4 = 1 ;
+}
+
+// Ext Int Callback in CHANGE mode
+static void Interrupt_Pin5( void )
+{
+  ul_Interrupt_Pin5 = 1 ;
+}
+
+// Ext Int Callback in FALLING mode
+static void Interrupt_Pin6( void )
+{
+  ul_Interrupt_Pin6 = 1 ;
+}
+
+// Ext Int Callback in RISING mode
+static void Interrupt_Pin7( void )
+{
+  ul_Interrupt_Pin7 = 1 ;
 }
diff --git a/variants/arduino_zero/variant.cpp b/variants/arduino_zero/variant.cpp
index 8bf63478..27ff3791 100644
--- a/variants/arduino_zero/variant.cpp
+++ b/variants/arduino_zero/variant.cpp
@@ -108,85 +108,85 @@ const PinDescription g_APinDescription[]=
   // 0 .. 19 - Digital pins
   // ----------------------
   // 0/1 - SERCOM/UART (Serial1)
-  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RX: SERCOM0/PAD[2]
-  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // TX: SERCOM0/PAD[3]
+  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // RX: SERCOM0/PAD[2]
+  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // TX: SERCOM0/PAD[3]
 
   // 2..12
-  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0 }, // TCC0/WO[0]
-  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1 }, // TCC0/WO[1]
-  { PORTA, 14, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH4, TCC0_CH4 }, // TCC0/WO[4]
-  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH5, TCC0_CH5 }, // TCC0/WO[5]
-  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH6, TCC0_CH6 }, // TCC0/WO[6]
-  { PORTA, 21, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH7, TCC0_CH7 }, // TCC0/WO[7]
-  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0 }, // TCC1/WO[0]
-  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1 }, // TCC1/WO[1]
-  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0 }, // TC3/WO[0]
-  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0 }, // TCC2/WO[0]
-  { PORTA, 19, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1 }, // TC3/WO[1]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // TCC0/WO[0]
+  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  { PORTA, 14, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH4, TCC0_CH4, EXTERNAL_INT_14 }, // TCC0/WO[4]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH5, TCC0_CH5, EXTERNAL_INT_15 }, // TCC0/WO[5]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
+  { PORTA, 21, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_5 }, // TCC0/WO[7]
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_4 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_5 }, // TCC1/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 19, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_3 }, // TC3/WO[1]
 
   // 13 (LED)
-  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM2_CH1, NOT_ON_TIMER }, // TCC2/WO[1]
+  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM2_CH1, NOT_ON_TIMER, EXTERNAL_INT_1 }, // TCC2/WO[1]
 
   // 14 (GND)
-  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER },
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
 
   // 15 (AREF)
-  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // DAC/VREFP
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
 
   // 16..17 I2C (SDA/SCL and also EDBG:SDA/SCL)
-  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0]
-  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1]
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1]
 
   // 18..23 SPI (ICSP:MISO,SCK,MOSI)
-  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MISO: SERCOM4/PAD[0]
-  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // 5V0
-  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCK: SERCOM4/PAD[3]
-  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI: SERCOM4/PAD[2]
-  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RESET
-  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // GND
+  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MISO: SERCOM4/PAD[0]
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 5V0
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3]
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2]
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // RESET
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // GND
 
   // 24..29 - Analog pins
   // --------------------
   // 24 - A0 (DAC output)
-  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER }, // DAC/VOUT
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT
 
   // 25..29 - A1-A5
-  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[2]
-  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[3]
-  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[4]
-  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[5]
-  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[10]
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // ADC/AIN[2]
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // ADC/AIN[3]
+  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ADC/AIN[5]
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10]
 
   // 30..31 - RX/TX LEDS (PB03/PA27)
-  { PORTB,  3, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // use as pure output
+  { PORTB,  3, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // use as pure output
   { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // use as pure output
 
   // 32..33 - USB
-  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/SOF
-  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DM
-  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DP
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/SOF
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
 
   // 35 .. 46 - EDBG
   // ----------------------
   // 35/36 - EDBG/UART
-  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // TX: SERCOM5/PAD[2]
-  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RX: SERCOM5/PAD[3]
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // TX: SERCOM5/PAD[2]
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // RX: SERCOM5/PAD[3]
 
   // 37/38 I2C (SDA/SCL and also EDBG:SDA/SCL)
-  { PORTA, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0]
-  { PORTA, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1]
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCL: SERCOM3/PAD[1]
 
   // 39 .. 42 - EDBG/SPI
-  { PORTA, 19, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MISO: SERCOM1/PAD[3]
-  { PORTA, 16, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI: SERCOM1/PAD[0]
-  { PORTA, 18, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SS: SERCOM1/PAD[2]
-  { PORTA, 17, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCK: SERCOM1/PAD[1]
+  { PORTA, 19, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MISO: SERCOM1/PAD[3]
+  { PORTA, 16, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MOSI: SERCOM1/PAD[0]
+  { PORTA, 18, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SS: SERCOM1/PAD[2]
+  { PORTA, 17, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCK: SERCOM1/PAD[1]
 
   // 43 .. 46 - EDBG/Digital
-  { PORTA, 13, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER }, // EIC/EXTINT[13] *TCC2/WO[1] TCC0/WO[7]
-  { PORTA, 21, PIO_PWM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH7, NOT_ON_TIMER }, // Pin 7
-  { PORTA,  6, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH0, NOT_ON_TIMER }, // Pin 8
-  { PORTA,  7, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH1, NOT_ON_TIMER }, // Pin 9
+  { PORTA, 13, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER, EXTERNAL_INT_13 }, // EIC/EXTINT[13] *TCC2/WO[1] TCC0/WO[7]
+  { PORTA, 21, PIO_PWM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH7, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 7
+  { PORTA,  6, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH0, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 8
+  { PORTA,  7, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH1, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 9
 } ;
 
 const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
diff --git a/variants/arduino_zero/variant.h b/variants/arduino_zero/variant.h
index aa76bd06..a9ef5bda 100644
--- a/variants/arduino_zero/variant.h
+++ b/variants/arduino_zero/variant.h
@@ -70,7 +70,7 @@ extern "C"{
 #define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
 
 // Interrupts
-#define digitalPinToInterrupt(p)  (-1) // ((p) < NUM_DIGITAL_PINS ? (p) : -1)
+#define digitalPinToInterrupt(P)   ( g_APinDescription[P].ulExtInt )
 
 // LEDs
 #define PIN_LED_13           (13u)
-- 
GitLab