From d7357e8849a2d60ff7486c94b57223ead9a72fac Mon Sep 17 00:00:00 2001
From: Thibaut VIARD <thibaut.viard@atmel.com>
Date: Thu, 8 May 2014 23:31:02 +0200
Subject: [PATCH]  Fixing Digital

---
 cores/arduino/wiring_digital.c | 258 ++++++++++++++++++---------------
 1 file changed, 140 insertions(+), 118 deletions(-)

diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c
index 5716bceb..5733a633 100644
--- a/cores/arduino/wiring_digital.c
+++ b/cores/arduino/wiring_digital.c
@@ -27,153 +27,175 @@
 
 int pinPeripheral( uint32_t ulPin, EPioType ulPeripheral )
 {
-	if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
-	{
-		return -1 ;
-	}
-
-	switch ( ulPeripheral )
-	{
-		case PIO_DIGITAL:
-		case PIO_INPUT:
-		case PIO_INPUT_PULLUP:
-		case PIO_OUTPUT:
-		  // Disable peripheral muxing, done in pinMode
+  if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
+  {
+    return -1 ;
+  }
+
+  switch ( ulPeripheral )
+  {
+    case PIO_DIGITAL:
+    case PIO_INPUT:
+    case PIO_INPUT_PULLUP:
+    case PIO_OUTPUT:
+      // Disable peripheral muxing, done in pinMode
 //			PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].bit.PMUXEN = 0 ;
 
       // Configure pin mode, if requested
-			if ( ulPeripheral == PIO_INPUT )
-			{
-			  pinMode( ulPin, INPUT ) ;
-			}
-			else
-			{
-			  if ( ulPeripheral == PIO_INPUT_PULLUP )
-				{
-				  pinMode( ulPin, INPUT_PULLUP ) ;
-				}
-				else
-				{
-					if ( ulPeripheral == PIO_OUTPUT )
-					{
-					  pinMode( ulPin, OUTPUT ) ;
-					}
-					else
-					{
-					  // PIO_DIGITAL, do we have to do something as all cases are covered?
-					}
-				}
-			}
-		break ;
-
-		case PIO_ANALOG:
-		case PIO_SERCOM:
-		case PIO_SERCOM_ALT:
-		case PIO_TIMER:
-		case PIO_TIMER_ALT:
-		case PIO_EXTINT:
-		case PIO_COM:
-		case PIO_AC_CLK:
+      if ( ulPeripheral == PIO_INPUT )
+      {
+        pinMode( ulPin, INPUT ) ;
+      }
+      else
+      {
+        if ( ulPeripheral == PIO_INPUT_PULLUP )
+        {
+          pinMode( ulPin, INPUT_PULLUP ) ;
+        }
+        else
+        {
+          if ( ulPeripheral == PIO_OUTPUT )
+          {
+            pinMode( ulPin, OUTPUT ) ;
+          }
+          else
+          {
+            // PIO_DIGITAL, do we have to do something as all cases are covered?
+          }
+        }
+      }
+    break ;
+
+    case PIO_ANALOG:
+    case PIO_SERCOM:
+    case PIO_SERCOM_ALT:
+    case PIO_TIMER:
+    case PIO_TIMER_ALT:
+    case PIO_EXTINT:
+    case PIO_COM:
+    case PIO_AC_CLK:
+#if 0
       // Is the pio pin in the lower 16 ones?
-			// The WRCONFIG register allows update of only 16 pin max out of 32
-			if ( g_APinDescription[ulPin].ulPin < 16 )
-			{
-				PORT->Group[g_APinDescription[ulPin].ulPort].WRCONFIG.reg = PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PMUXEN | PORT_WRCONFIG_PMUX( g_APinDescription[ulPin].ulPinType ) |
-																																		 PORT_WRCONFIG_WRPINCFG |
-																																		 PORT_WRCONFIG_PINMASK( g_APinDescription[ulPin].ulPin ) ;
-			}
-			else
-			{
-				PORT->Group[g_APinDescription[ulPin].ulPort].WRCONFIG.reg = PORT_WRCONFIG_HWSEL |
-				                                                             PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PMUXEN | PORT_WRCONFIG_PMUX( g_APinDescription[ulPin].ulPinType ) |
-																																		 PORT_WRCONFIG_WRPINCFG |
-																																		 PORT_WRCONFIG_PINMASK( g_APinDescription[ulPin].ulPin - 16 ) ;
-			}
-		break ;
-
-		case PIO_NOT_A_PIN:
-			return -1l ;
-		break ;
-	}
-
-	return 0l ;
+      // The WRCONFIG register allows update of only 16 pin max out of 32
+      if ( g_APinDescription[ulPin].ulPin < 16 )
+      {
+        PORT->Group[g_APinDescription[ulPin].ulPort].WRCONFIG.reg = PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PMUXEN | PORT_WRCONFIG_PMUX( ulPeripheral ) |
+                                                                    PORT_WRCONFIG_WRPINCFG |
+                                                                    PORT_WRCONFIG_PINMASK( g_APinDescription[ulPin].ulPin ) ;
+      }
+      else
+      {
+        PORT->Group[g_APinDescription[ulPin].ulPort].WRCONFIG.reg = PORT_WRCONFIG_HWSEL |
+                                                                    PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PMUXEN | PORT_WRCONFIG_PMUX( ulPeripheral ) |
+                                                                    PORT_WRCONFIG_WRPINCFG |
+                                                                    PORT_WRCONFIG_PINMASK( g_APinDescription[ulPin].ulPin - 16 ) ;
+      }
+#else
+      if ( g_APinDescription[ulPin].ulPin & 1 ) // is pin odd?
+      {
+        uint32_t temp ;
+
+        // Get whole current setup for both odd and even pins and remove odd one
+        temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXE( 0xF ) ;
+        // Set new muxing
+        PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXO( ulPeripheral ) ;
+        // Enable port mux
+        PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ;
+      }
+      else // even pin
+      {
+        uint32_t temp ;
+
+        temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXO( 0xF ) ;
+        PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXE( ulPeripheral ) ;
+        PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; // Enable port mux
+      }
+#endif
+    break ;
+
+    case PIO_NOT_A_PIN:
+      return -1l ;
+    break ;
+  }
+
+  return 0l ;
 }
 
 void pinMode( uint32_t ulPin, uint32_t ulMode )
 {
-	if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
-	{
-		return ;
-	}
-
-	switch ( ulMode )
-	{
-		case INPUT:
-		  // Set pin to input mode
-			PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
-		  PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
-		break ;
-
-		case INPUT_PULLUP:
-		  // Set pin to input mode with pull-up resistor enabled
-			PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
-		  PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
-		break ;
-
-		case OUTPUT:
-		  // Set pin to output mode
-			PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg&=~(uint8_t)(PORT_PINCFG_INEN) ;
-		  PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
-		break ;
-
-		default:
-		  // do nothing
-		break ;
-	}
+  if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
+  {
+    return ;
+  }
+
+  switch ( ulMode )
+  {
+    case INPUT:
+      // Set pin to input mode
+      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
+      PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+    break ;
+
+    case INPUT_PULLUP:
+      // Set pin to input mode with pull-up resistor enabled
+      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
+      PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+    break ;
+
+    case OUTPUT:
+      // Set pin to output mode
+      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg&=~(uint8_t)(PORT_PINCFG_INEN) ;
+      PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+    break ;
+
+    default:
+      // do nothing
+    break ;
+  }
 }
 
 void digitalWrite( uint32_t ulPin, uint32_t ulVal )
 {
   /* Handle the case the pin isn't usable as PIO */
-	if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
+  if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
   {
     return ;
   }
 
-	// Enable pull-up resistor
-	PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_PULLEN) ;
+  // Enable pull-up resistor
+  PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_PULLEN) ;
 
   switch ( ulVal )
-	{
-	  case LOW:
-			PORT->Group[g_APinDescription[ulPin].ulPort].OUTCLR.reg = (1ul << g_APinDescription[ulPin].ulPin) ;
-		break ;
+  {
+    case LOW:
+      PORT->Group[g_APinDescription[ulPin].ulPort].OUTCLR.reg = (1ul << g_APinDescription[ulPin].ulPin) ;
+    break ;
 
-	  case HIGH:
-			PORT->Group[g_APinDescription[ulPin].ulPort].OUTSET.reg = (1ul << g_APinDescription[ulPin].ulPin) ;
-		break ;
+    case HIGH:
+      PORT->Group[g_APinDescription[ulPin].ulPort].OUTSET.reg = (1ul << g_APinDescription[ulPin].ulPin) ;
+    break ;
 
-		default:
-		break ;
-	}
+    default:
+    break ;
+  }
 
-	return ;
+  return ;
 }
 
 int digitalRead( uint32_t ulPin )
 {
   /* Handle the case the pin isn't usable as PIO */
-	if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
-	{
-		return LOW ;
-	}
+  if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
+  {
+    return LOW ;
+  }
 
-	if ( (PORT->Group[g_APinDescription[ulPin].ulPort].IN.reg & (1ul << g_APinDescription[ulPin].ulPin)) != 0 )
-	{
-		return HIGH ;
-	}
+  if ( (PORT->Group[g_APinDescription[ulPin].ulPort].IN.reg & (1ul << g_APinDescription[ulPin].ulPin)) != 0 )
+  {
+    return HIGH ;
+  }
 
-	return LOW ;
+  return LOW ;
 }
 
 #ifdef __cplusplus
-- 
GitLab