From f397a09a7fe9efec5f5fde4f8bb2e3ce830e0b6e Mon Sep 17 00:00:00 2001
From: Jonathan BAUDIN <jonathan.baudin@atmel.com>
Date: Tue, 3 Jun 2014 10:12:30 +0200
Subject: [PATCH]  Implement DAC

---
 cores/arduino/wiring.c                    |  22 +++-
 cores/arduino/wiring_analog.c             | 121 ++++++++++++----------
 cores/arduino/wiring_analog.h             |   4 +-
 cores/validation/validation_core/test.cpp |   6 ++
 4 files changed, 96 insertions(+), 57 deletions(-)

diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c
index d16960d8..d65e159a 100644
--- a/cores/arduino/wiring.c
+++ b/cores/arduino/wiring.c
@@ -97,7 +97,7 @@ void init( void )
   // Todo
 
   // Initialize Analog Controller
-  //Setting clock
+  // Setting clock
   GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC
                       GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
                       GCLK_CLKCTRL_CLKEN ;
@@ -118,6 +118,26 @@ void init( void )
   {
     // Waiting for synchroinization
   }
+
+  // Initialize DAC
+  // Setting clock
+  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC
+                      GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+                      GCLK_CLKCTRL_CLKEN ;
+
+
+  DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference
+                   DAC_CTRLB_EOEN;  // External Output Enable (Vout)
+  DAC->DATA.reg = 0x3FFul;
+
+  // Enable DAC
+  DAC->CTRLA.bit.ENABLE = 1;
+
+  while(DAC->STATUS.bit.SYNCBUSY != 0)
+  {
+    // Waiting for synchronization
+  }
+
 }
 
 #ifdef __cplusplus
diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c
index 2732a8dc..aa0a0a07 100644
--- a/cores/arduino/wiring_analog.c
+++ b/cores/arduino/wiring_analog.c
@@ -25,14 +25,18 @@ extern "C" {
 
 void analogReference( eAnalogReference ulMode )
 {
+
+  // ATTENTION : On this board the default is note 5volts or 3.3volts BUT 1volt
+
   switch(ulMode)
   {
+    case AR_DEFAULT:
     case INTERNAL:
+    default:
       ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val;
       break;
 
-    case AR_DEFAULT:
-    default:
+    case EXTERNAL:
       ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;
       break;
   }
@@ -75,60 +79,67 @@ uint32_t analogRead( uint32_t ulPin )
 // pins_*.c file.  For the rest of the pins, we default
 // to digital output.
 void analogWrite( uint32_t ulPin, uint32_t ulValue )
- {
-   uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
+{
+  uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
 //   uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
-   uint8_t isTC = 0 ;
-   uint8_t Channelx ;
-   Tc* TCx ;
-   Tcc* TCCx ;
-
-   if ( (attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG )
-   {
-    // EAnalogChannel channel = g_APinDescription[ulPin].ulADCChannelNumber;
-    // if (channel == DA0 || channel == DA1) {
-      // uint32_t chDACC = ((channel == DA0) ? 0 : 1);
-      // if (dacc_get_channel_status(DACC_INTERFACE) == 0) {
-        // /* Enable clock for DACC_INTERFACE */
-        // pmc_enable_periph_clk(DACC_INTERFACE_ID);
-
-        // /* Reset DACC registers */
-        // dacc_reset(DACC_INTERFACE);
-
-        // /* Half word transfer mode */
-        // dacc_set_transfer_mode(DACC_INTERFACE, 0);
-
-        // /* Power save:
-         // * sleep mode  - 0 (disabled)
-         // * fast wakeup - 0 (disabled)
-         // */
-        // dacc_set_power_save(DACC_INTERFACE, 0, 0);
-        // /* Timing:
-         // * refresh        - 0x08 (1024*8 dacc clocks)
-         // * max speed mode -    0 (disabled)
-         // * startup time   - 0x10 (1024 dacc clocks)
-         // */
-        // dacc_set_timing(DACC_INTERFACE, 0x08, 0, 0x10);
-
-        // /* Set up analog current */
-        // dacc_set_analog_control(DACC_INTERFACE, DACC_ACR_IBCTLCH0(0x02) |
-                      // DACC_ACR_IBCTLCH1(0x02) |
-                      // DACC_ACR_IBCTLDACCORE(0x01));
-      // }
-
-      // /* Disable TAG and select output channel chDACC */
-      // dacc_set_channel_selection(DACC_INTERFACE, chDACC);
-
-      // if ((dacc_get_channel_status(DACC_INTERFACE) & (1 << chDACC)) == 0) {
-        // dacc_enable_channel(DACC_INTERFACE, chDACC);
-      // }
-
-      // // Write user value
-      // ulValue = mapResolution(ulValue, _writeResolution, DACC_RESOLUTION);
-      // dacc_write_conversion_data(DACC_INTERFACE, ulValue);
-      // while ((dacc_get_interrupt_status(DACC_INTERFACE) & DACC_ISR_EOC) == 0);
-      // return;
-    // }
+  uint8_t isTC = 0 ;
+  uint8_t Channelx ;
+  Tc* TCx ;
+  Tcc* TCCx ;
+
+  if ( (attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG )
+  {
+    if ( ulPin != 24 )  // Only 1 DAC on A0 (PA02)
+    {
+      return;
+    }
+
+    DAC->DATA.reg = ulValue & 0x3FF;  // Dac on 10 bits.
+
+   // EAnalogChannel channel = g_APinDescription[ulPin].ulADCChannelNumber;
+   // if (channel == DA0 || channel == DA1) {
+     // uint32_t chDACC = ((channel == DA0) ? 0 : 1);
+     // if (dacc_get_channel_status(DACC_INTERFACE) == 0) {
+       // /* Enable clock for DACC_INTERFACE */
+       // pmc_enable_periph_clk(DACC_INTERFACE_ID);
+
+       // /* Reset DACC registers */
+       // dacc_reset(DACC_INTERFACE);
+
+       // /* Half word transfer mode */
+       // dacc_set_transfer_mode(DACC_INTERFACE, 0);
+
+       // /* Power save:
+        // * sleep mode  - 0 (disabled)
+        // * fast wakeup - 0 (disabled)
+        // */
+       // dacc_set_power_save(DACC_INTERFACE, 0, 0);
+       // /* Timing:
+        // * refresh        - 0x08 (1024*8 dacc clocks)
+        // * max speed mode -    0 (disabled)
+        // * startup time   - 0x10 (1024 dacc clocks)
+        // */
+       // dacc_set_timing(DACC_INTERFACE, 0x08, 0, 0x10);
+
+       // /* Set up analog current */
+       // dacc_set_analog_control(DACC_INTERFACE, DACC_ACR_IBCTLCH0(0x02) |
+                     // DACC_ACR_IBCTLCH1(0x02) |
+                     // DACC_ACR_IBCTLDACCORE(0x01));
+     // }
+
+     // /* Disable TAG and select output channel chDACC */
+     // dacc_set_channel_selection(DACC_INTERFACE, chDACC);
+
+     // if ((dacc_get_channel_status(DACC_INTERFACE) & (1 << chDACC)) == 0) {
+       // dacc_enable_channel(DACC_INTERFACE, chDACC);
+     // }
+
+     // // Write user value
+     // ulValue = mapResolution(ulValue, _writeResolution, DACC_RESOLUTION);
+     // dacc_write_conversion_data(DACC_INTERFACE, ulValue);
+     // while ((dacc_get_interrupt_status(DACC_INTERFACE) & DACC_ISR_EOC) == 0);
+     // return;
+   // }
   }
 
   if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM )
diff --git a/cores/arduino/wiring_analog.h b/cores/arduino/wiring_analog.h
index d443be6f..006e5b94 100644
--- a/cores/arduino/wiring_analog.h
+++ b/cores/arduino/wiring_analog.h
@@ -31,9 +31,11 @@ extern "C" {
 typedef enum _eAnalogReference
 {
   AR_DEFAULT,
-  INTERNAL
+  INTERNAL,
+  EXTERNAL
 } eAnalogReference ;
 
+
 /*
  * \brief Configures the reference voltage used for analog input (i.e. the value used as the top of the input range).
  * This function is kept only for compatibility with existing AVR based API.
diff --git a/cores/validation/validation_core/test.cpp b/cores/validation/validation_core/test.cpp
index e86988ab..84ed4013 100644
--- a/cores/validation/validation_core/test.cpp
+++ b/cores/validation/validation_core/test.cpp
@@ -89,6 +89,7 @@ void loop( void )
 {
   volatile int pin_value=0 ;
   static volatile uint8_t duty_cycle=0 ;
+  static volatile uint16_t dac_value=0 ;
 
   // Test digitalWrite
   led_step1() ;
@@ -114,6 +115,11 @@ void loop( void )
   analogWrite(  9, duty_cycle ) ;
   analogWrite(  8, duty_cycle ) ;
 
+  dac_value += 64;
+  analogWrite(A0, dac_value);
+
+
+
   Serial5.print("\r\nAnalog pins: ");
 
   for ( uint32_t i = A0 ; i <= A0+NUM_ANALOG_INPUTS ; i++ )
-- 
GitLab