diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index 03b17c24ca769d2bb0e7f32b249fb29632c1d4a9..ba40e23f9bbdeaf779195ebcea65ebdcd42e5f84 100644 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -93,46 +93,42 @@ void init( void ) // Initialize Analog Controller // Setting clock + while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC - GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source GCLK_CLKCTRL_CLKEN ; - ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV128 | // Divide Clock by 512. - ADC_CTRLB_RESSEL_10BIT; // Result on 10 bits + while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains + + ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 | // Divide Clock by 512. + ADC_CTRLB_RESSEL_10BIT; // 10 bits resolution as default + + ADC->SAMPCTRL.reg = 0x3f; // Set max Sampling Time Length + + while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND; // No Negative input (Internal Ground) // Averaging (see table 31-2 p.816 datasheet) - ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_2 | // 2 samples - ADC_AVGCTRL_ADJRES(0x01ul); // Adjusting result by 1 + ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_64 | // 64 samples + ADC_AVGCTRL_ADJRES(0x04ul); // Adjusting result by 4 - ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_AREFA; // RReference AREFA (pin AREF) [default] + while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains - ADC->CTRLA.bit.ENABLE = 1; // Enable ADC - while( ADC->STATUS.bit.SYNCBUSY == 1 ) - { - // Waiting for synchroinization - } + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val; + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V // Initialize DAC // Setting clock + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ); GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC - GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source GCLK_CLKCTRL_CLKEN ; - + while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains 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 - } - + DAC_CTRLB_EOEN ; // External Output Enable (Vout) } #ifdef __cplusplus diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index f894a5b7df2475267b7206db7a9311827ab7caa6..dd3f4d3fcdc7f293e762492d79014c50ec9895ac 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -28,77 +28,144 @@ static int _writeResolution = 8; void analogReadResolution( int res ) { - _readResolution = res ; + switch ( res ) + { + case 12: + while( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val; + break; + case 8: + while( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val; + break; + default: + while( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val; + break; + } + _readResolution = res ; } void analogWriteResolution( int res ) { - _writeResolution = res ; + _writeResolution = res ; } static inline uint32_t mapResolution( uint32_t value, uint32_t from, uint32_t to ) { - if ( from == to ) + if ( from == to ) { - return value ; + return value ; } - if ( from > to ) + if ( from > to ) { - return value >> (from-to) ; + return value >> (from-to) ; } - else + else { - return value << (to-from) ; + return value << (to-from) ; } } void analogReference( eAnalogReference ulMode ) { - // ATTENTION : On this board the default is not 5volts or 3.3volts BUT 1volt - + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); switch ( ulMode ) { - case AR_DEFAULT: case AR_INTERNAL: - default: - ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; + case AR_INTERNAL2V23: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 1/1.48 VDDANA = 1/1.48* 3V3 = 2.2297 break; case AR_EXTERNAL: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; break; + + case AR_INTERNAL1V0: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; // 1.0V voltage reference + break; + + case AR_INTERNAL1V65: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V + break; + + case AR_DEFAULT: + default: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val; + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V + break; } } uint32_t analogRead( uint32_t ulPin ) { uint32_t valueRead = 0; - pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType); - ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber; + if (ulPin < A0) ulPin += A0; - // Start conversion - ADC->SWTRIG.bit.START = 1; + if (ulPin == A0) // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled + { + while ( DAC->STATUS.bit.SYNCBUSY == 1 ); + DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC + //DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off. + while ( DAC->STATUS.bit.SYNCBUSY == 1 ); + } - while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 ) + if (ulPin != TEMP) + { + pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType); + + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber; // Selection for the positive ADC input + } + else { - // Waiting for a complete conversion and complete synchronization + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->INPUTCTRL.bit.MUXPOS = ulPin & 0x7F; // Selection for the positive ADC input + //ADC->INPUTCTRL.bit.MUXPOS = 0x18; // Selection for the positive ADC input + + SYSCTRL->VREF.bit.TSEN = 0x1; // Temperature sensor is enabled and routed to an ADC input channel. } - // Store the value - valueRead = ADC->RESULT.reg; + // Control A + /* + * Bit 1 – ENABLE: Enable + * 0: The ADC is disabled. + * 1: The ADC is enabled. + * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The + * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register + * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete. + * + * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be + * configured. The first conversion after the reference is changed must not be used. + */ + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->CTRLA.bit.ENABLE = 0x01; // Enable ADC + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + + // Start conversion + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->SWTRIG.bit.START = 1; // Clear the Data Ready flag ADC->INTFLAG.bit.RESRDY = 1; - // Flush the ADC for further conversions - //ADC->SWTRIG.bit.FLUSH = 1; + // Start conversion again, since The first conversion after the reference is changed must not be used. + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->SWTRIG.bit.START = 1; - while( ADC->STATUS.bit.SYNCBUSY == 1 || ADC->SWTRIG.bit.FLUSH == 1 ) - { - // Waiting for synchronization - } + // Store the value + while ( ADC->INTFLAG.bit.RESRDY == 0 ); // Waiting for conversion to complete + valueRead = ADC->RESULT.reg; + + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); + ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC + while ( ADC->STATUS.bit.SYNCBUSY == 1 ); return valueRead; } @@ -124,7 +191,12 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) return; } - DAC->DATA.reg = ulValue & 0x3FF; // Dac on 10 bits. + while ( DAC->STATUS.bit.SYNCBUSY == 1 ); + DAC->DATA.reg = ulValue & 0x3FF; // DAC on 10 bits. + while ( DAC->STATUS.bit.SYNCBUSY == 1 ); + DAC->CTRLA.bit.ENABLE = 0x01; //Enable ADC + while ( DAC->STATUS.bit.SYNCBUSY == 1 ); + return ; } if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM ) diff --git a/cores/arduino/wiring_analog.h b/cores/arduino/wiring_analog.h index 493e207d8e3dbc85975368aa45dc6ec8d3182064..70dcee89a4b8f46f459959e2be3d4e067e8cd607 100644 --- a/cores/arduino/wiring_analog.h +++ b/cores/arduino/wiring_analog.h @@ -32,7 +32,10 @@ typedef enum _eAnalogReference { AR_DEFAULT, AR_INTERNAL, - AR_EXTERNAL + AR_EXTERNAL, + AR_INTERNAL1V0, + AR_INTERNAL1V65, + AR_INTERNAL2V23 } eAnalogReference ; diff --git a/variants/arduino_zero/variant.h b/variants/arduino_zero/variant.h index ab7050cefcff23b1c51a6c0525b10002822379ac..da0eaf39dc101353f4bd23c80af6ab65041c9c8c 100644 --- a/variants/arduino_zero/variant.h +++ b/variants/arduino_zero/variant.h @@ -92,6 +92,7 @@ static const uint8_t A2 = PIN_A2 ; static const uint8_t A3 = PIN_A3 ; static const uint8_t A4 = PIN_A4 ; static const uint8_t A5 = PIN_A5 ; +static const uint8_t TEMP = 0x98 ; #define ADC_RESOLUTION 12 /*