From d300278c66f3b19db0e05e8f64873779bdebc7d2 Mon Sep 17 00:00:00 2001
From: Thibaut VIARD <thibaut.viard@atmel.com>
Date: Wed, 14 May 2014 10:34:15 +0200
Subject: [PATCH]  PWM AnalogWrite refactoring

---
 cores/arduino/WVariant.h                      |  30 +++--
 cores/arduino/wiring_analog.c                 | 104 +++++++++---------
 .../validation_core/test - Copy.cpp           | 100 -----------------
 cores/validation/validation_core/test.cpp     |  66 +++++------
 variants/arduino_zero/variant.cpp             |   2 +
 5 files changed, 96 insertions(+), 206 deletions(-)
 delete mode 100644 cores/validation/validation_core/test - Copy.cpp

diff --git a/cores/arduino/WVariant.h b/cores/arduino/WVariant.h
index 851c7ba7..2a05298d 100644
--- a/cores/arduino/WVariant.h
+++ b/cores/arduino/WVariant.h
@@ -32,20 +32,26 @@ typedef enum _EAnalogChannel
 typedef enum _ETCChannel
 {
   NOT_ON_TIMER=-1,
-	TC3_CH0,
-	TC3_CH1,
-	TCC0_CH0,
-	TCC0_CH1,
-	TCC0_CH4,
-	TCC0_CH5,
-	TCC0_CH6,
-	TCC0_CH7,
-	TCC1_CH0,
-	TCC1_CH1,
-	TCC2_CH0,
-	TCC2_CH1
+	TC3_CH0 = (3<<8)|(0),
+	TC3_CH1 = (3<<8)|(1),
+	TCC0_CH0 = (0<<8)|(0),
+	TCC0_CH1 = (0<<8)|(1),
+	TCC0_CH4 = (0<<8)|(4),
+	TCC0_CH5 = (0<<8)|(5),
+	TCC0_CH6 = (0<<8)|(6),
+	TCC0_CH7 = (0<<8)|(7),
+	TCC1_CH0 = (1<<8)|(0),
+	TCC1_CH1 = (1<<8)|(1),
+	TCC2_CH0 = (2<<8)|(0),
+	TCC2_CH1 = (2<<8)|(1)
 } ETCChannel ;
 
+extern const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM] ;
+
+#define GetTCNumber( x ) ( (x) >> 8 )
+#define GetTCChannelNumber( x ) ( (x) && 0xff )
+#define GetTC( x ) ( g_apTCInstances[(x) >> 8] )
+
 // Definitions for PWM channels
 typedef enum _EPWMChannel
 {
diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c
index 7094cb61..82ec417e 100644
--- a/cores/arduino/wiring_analog.c
+++ b/cores/arduino/wiring_analog.c
@@ -26,13 +26,13 @@ extern "C" {
 uint32_t analogRead( uint32_t ulPin )
 {
   uint32_t ulValue = 0 ;
+/*
   uint32_t ulChannel ;
 
   ulChannel = g_APinDescription[ulPin].ulADCChannelNumber ;
 
   static uint32_t latestSelectedChannel = -1;
 
-/*
   switch ( g_APinDescription[ulPin].ulAnalogChannel )
   {
     // Handling ADC 12 bits channels
@@ -61,7 +61,7 @@ uint32_t analogRead( uint32_t ulPin )
 void analogWrite( uint32_t ulPin, uint32_t ulValue )
  {
    uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
-   uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
+//   uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
    uint8_t isTC = 0 ;
    uint8_t Channelx ;
    Tc* TCx ;
@@ -122,6 +122,19 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
       pinPeripheral( ulPin, g_APinDescription[ulPin].ulPinType ) ;
     }
 
+    Channelx = GetTCChannelNumber( g_APinDescription[ulPin].ulPWMChannel ) ;
+    if ( GetTCChannelNumber( g_APinDescription[ulPin].ulPWMChannel ) >= TCC_INST_NUM )
+    {
+      isTC = 1 ;
+      TCx = (Tc*) GetTC( g_APinDescription[ulPin].ulPWMChannel ) ;
+    }
+    else
+    {
+      isTC = 0 ;
+      TCCx = (Tcc*) GetTC( g_APinDescription[ulPin].ulPWMChannel ) ;
+    }
+
+/*
     switch ( g_APinDescription[ulPin].ulPWMChannel )
     {
       case PWM3_CH0 :
@@ -190,36 +203,45 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
       Channelx = 1;
       break;
     }
+*/
 
-    // --Set PORT
+    // Enable clocks according to TCCx instance to use
+    switch ( GetTCNumber( g_APinDescription[ulPin].ulPWMChannel ) )
+    {
+      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 )) ;
+      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 )) ;
+      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 )) ;
+      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 ));
+      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 ));
+      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 )) ;
+      break ;
+    }
 
+    // Set PORT
     if ( isTC )
     {
-      // -- Enable clocks according to TCCx instance to use
-      switch ( (uint32_t)TCx )
-      {
-        case (uint32_t)TC3 :
-          //Enable TCx Bus clock (Timer counter control clock)
-          PM->APBCMASK.reg |= PM_APBCMASK_TC3;
-          //Enable GCLK for TC3 (timer counter input clock)
-          GCLK->CLKCTRL.reg = (uint16_t) ((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | ( 0x1B << GCLK_CLKCTRL_ID_Pos)));
-        break ;
-
-        case (uint32_t) TC4 :
-          //Enable TCx Bus clock (Timer counter control clock)
-          PM->APBCMASK.reg |= PM_APBCMASK_TC4;
-          //Enable GCLK for TC4 (timer counter input clock)
-          GCLK->CLKCTRL.reg = (uint16_t) ((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | ( 0x1C << GCLK_CLKCTRL_ID_Pos)));
-        break ;
-
-        case (uint32_t) TC5 :
-          //Enable TCx Bus clock (Timer counter control clock)
-          PM->APBCMASK.reg |= PM_APBCMASK_TC5;
-          //Enable GCLK for TC5 (timer counter input clock)
-          GCLK->CLKCTRL.reg = (uint16_t) ((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | ( 0x1C << GCLK_CLKCTRL_ID_Pos)));
-        break ;
-      }
-
       // -- Configure TC
       //DISABLE TCx
       TCx->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
@@ -233,35 +255,9 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
       TCx->COUNT8.PER.reg = 0xFF;
       // Enable TCx
       TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
-
     }
     else
     {
-       // -- Enable clocks according to TCCx instance to use
-       switch ( (uint32_t) TCCx )
-       {
-        case (uint32_t) TCC0 :
-          //Enable TCC0 Bus clock (Timer counter control clock)
-          PM->APBCMASK.reg |= PM_APBCMASK_TCC0;
-          //Enable GCLK for TCC0 (timer counter input clock)
-          GCLK->CLKCTRL.reg = (uint16_t) ((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | ( 0x1A << GCLK_CLKCTRL_ID_Pos)));
-        break;
-
-        case (uint32_t) TCC1 :
-          //Enable TCC1 Bus clock (Timer counter control clock)
-          PM->APBCMASK.reg |= PM_APBCMASK_TCC1;
-          //Enable GCLK for TCC1 (timer counter input clock)
-          GCLK->CLKCTRL.reg = (uint16_t) ((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | ( 0x1A << GCLK_CLKCTRL_ID_Pos)));
-        break;
-
-        case (uint32_t) TCC2 :
-          //Enable TCC2 Bus clock (Timer counter control clock)
-          PM->APBCMASK.reg |= PM_APBCMASK_TCC2;
-          //Enable GCLK for TCC2 (timer counter input clock)
-          GCLK->CLKCTRL.reg = (uint16_t) ((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | ( 0x1B << GCLK_CLKCTRL_ID_Pos)));
-        break;
-      }
-
       // -- Configure TCC
 
       //DISABLE TCCx
diff --git a/cores/validation/validation_core/test - Copy.cpp b/cores/validation/validation_core/test - Copy.cpp
deleted file mode 100644
index ac1e28d1..00000000
--- a/cores/validation/validation_core/test - Copy.cpp	
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-  Copyright (c) 2011 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 "Arduino.h"
-
-void setup( void )
-{
-  // Initialize the digital pin as an output.
-  // Pin PIN_LED has a LED connected on most Arduino boards:
-  //pinMode( PIN_LED, OUTPUT ) ;
-  //digitalWrite( PIN_LED, LOW ) ;
-
-  // Initialize the PIN_LED2 digital pin as an output.
-  pinMode( PIN_LED2, OUTPUT ) ;
-  digitalWrite( PIN_LED2, HIGH ) ;
-
-  // Initialize the PIN_LED2 digital pin as an output.
-  pinMode( PIN_LED3, OUTPUT ) ;
-  digitalWrite( PIN_LED3, LOW ) ;
-
-  // Initialize the PIN 2 digital pin as an input.
-  pinMode( 2, INPUT ) ;
-
-//**********************************************
-// Clock output on pin 4 for measure
-
-  pinPeripheral( 4, PIO_AC_CLK ) ; // Clock Gen 0
-  pinPeripheral( 5, PIO_AC_CLK ) ; // Clock Gen 1
-  pinPeripheral( 13, PIO_AC_CLK ) ; // Clock Gen 3
-
-//**********************************************
-
-  Serial.begin( 115200 ) ;
-}
-
-static void led_step1( void )
-{
-//  digitalWrite( PIN_LED, LOW ) ;  // set the LED on
-  digitalWrite( PIN_LED2, LOW ) ;   // set the red LED off
-  digitalWrite( PIN_LED3, HIGH ) ;   // set the red LED off
-}
-
-static void led_step2( void )
-{
-//  digitalWrite( PIN_LED, HIGH ) ;   // set the LED off
-  digitalWrite( PIN_LED2, HIGH ) ;  // set the red LED on
-  digitalWrite( PIN_LED3, LOW ) ;  // set the red LED on
-}
-
-void loop( void )
-{
-  volatile int pin_value=0 ;
-
-  // Test digitalWrite
-  led_step1() ;
-  delay( 1000 ) ;              // wait for a second
-  led_step2() ;
-  delay( 1000 ) ;              // wait for a second
-
-  // Test Serial output
-  Serial.write( '-' ) ;   // send a char
-  Serial.write( "test1\n" ) ;   // send a string
-  Serial.write( "test2" ) ;   // send another string
-
-  // Test digitalRead: connect pin 2 to either GND or 3.3V. !!!! NOT on 5V pin !!!!
-  pin_value=digitalRead( 2 ) ;
-  Serial.write( "pin 2 value is " ) ;
-  Serial.write( (pin_value == LOW)?"LOW\n":"HIGH\n" ) ;
-  delay( 1000 ) ;              // wait for a second
-
-
-/*
-  Serial.print("Analog pins: ");
-
-  for ( int i = A1 ; i <= A0+NUM_ANALOG_INPUTS ; i++ )
-  {
-    int a = analogRead(i);
-    Serial.print(a, DEC);
-    Serial.print(" ");
-  }
-  Serial.println();
-  delay(100);
-*/
-
-}
diff --git a/cores/validation/validation_core/test.cpp b/cores/validation/validation_core/test.cpp
index 9202715c..cb418220 100644
--- a/cores/validation/validation_core/test.cpp
+++ b/cores/validation/validation_core/test.cpp
@@ -44,8 +44,7 @@ void setup( void )
   pinPeripheral( 13, PIO_AC_CLK ) ; // Clock Gen 3
 
 //**********************************************
-
-  Serial.begin( 115200 ) ;
+  Serial5.begin( 115200 ) ; // Output to EDBG Virtual COM Port
 }
 
 static void led_step1( void )
@@ -62,63 +61,50 @@ static void led_step2( void )
   digitalWrite( PIN_LED3, LOW ) ;  // set the red LED on
 }
 
-static void analog_write_step( void )
-{
-  uint8_t duty_cycle ;
-
-	// test PWM generation on all PWM pins (duty cycle from 0x00 to 0xFF)
-	for( duty_cycle = 0x00 ; duty_cycle <= 0xFF ; duty_cycle++ )
-	{
-		analogWrite( 13, duty_cycle ) ;
-		analogWrite( 12, duty_cycle ) ;
-		analogWrite( 11, duty_cycle ) ;
-		analogWrite( 10 ,duty_cycle ) ;
-		analogWrite(  9, duty_cycle ) ;
-		analogWrite(  8, duty_cycle ) ;
-		analogWrite(  7, duty_cycle ) ;
-		analogWrite(  6, duty_cycle ) ;
-		analogWrite(  5, duty_cycle ) ;
-		analogWrite(  4, duty_cycle ) ;
-		analogWrite(  3, duty_cycle ) ;
-//    analogWrite(  2, duty_cycle ) ;
-
-		delay( 10 ) ;
-	}
-}
-
 void loop( void )
 {
   volatile int pin_value=0 ;
+  static volatile uint8_t duty_cycle=0 ;
 
   // Test digitalWrite
   led_step1() ;
-  delay( 1000 ) ;              // wait for a second
+  delay( 500 ) ;              // wait for a second
   led_step2() ;
-  delay( 1000 ) ;              // wait for a second
+  delay( 500 ) ;              // wait for a second
 
   // Test Serial output
-  Serial.write( '-' ) ;   // send a char
-  Serial.write( "test1\n" ) ;   // send a string
-  Serial.write( "test2" ) ;   // send another string
+  Serial5.write( '-' ) ;   // send a char
+  Serial5.write( "test1\n" ) ;   // send a string
+  Serial5.write( "test2" ) ;   // send another string
 
   // Test digitalRead: connect pin 2 to either GND or 3.3V. !!!! NOT on 5V pin !!!!
   pin_value=digitalRead( 2 ) ;
-  Serial.write( "pin 2 value is " ) ;
-  Serial.write( (pin_value == LOW)?"LOW\n":"HIGH\n" ) ;
-  delay( 1000 ) ;              // wait for a second
-
-  analog_write_step();
+  Serial5.write( "pin 2 value is " ) ;
+  Serial5.write( (pin_value == LOW)?"LOW\n":"HIGH\n" ) ;
+
+  duty_cycle+=8 ;//=(uint8_t)(millis() & 0xff) ;
+  analogWrite( 13, duty_cycle ) ;
+  analogWrite( 12, duty_cycle ) ;
+  analogWrite( 11, duty_cycle ) ;
+  analogWrite( 10 ,duty_cycle ) ;
+  analogWrite(  9, duty_cycle ) ;
+  analogWrite(  8, duty_cycle ) ;
+  analogWrite(  7, duty_cycle ) ;
+  analogWrite(  6, duty_cycle ) ;
+  analogWrite(  5, duty_cycle ) ;
+  analogWrite(  4, duty_cycle ) ;
+  analogWrite(  3, duty_cycle ) ;
 
 /*
-  Serial.print("Analog pins: ");
+  Serial5.print("Analog pins: ");
 
   for ( int i = A1 ; i <= A0+NUM_ANALOG_INPUTS ; i++ )
   {
     int a = analogRead(i);
-    Serial.print(a, DEC);
-    Serial.print(" ");
+    Serial5.print(a, DEC);
+    Serial5.print(" ");
   }
-  Serial.println();
+  Serial5.println();
   delay(100);
 */
 }
diff --git a/variants/arduino_zero/variant.cpp b/variants/arduino_zero/variant.cpp
index 224f8851..8bf63478 100644
--- a/variants/arduino_zero/variant.cpp
+++ b/variants/arduino_zero/variant.cpp
@@ -188,3 +188,5 @@ const PinDescription g_APinDescription[]=
   { 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
 } ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
-- 
GitLab