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