diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index f5337d604967a5042487a275a6ec158a245eab34..9a53c04129ada8e697c0d6bbd3f66ccbb0090250 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -633,7 +633,7 @@ void SERCOM::initClockNVIC( void ) clockId = GCM_SERCOM4_CORE; IdNvic = SERCOM4_IRQn; } - else if(sercom == SERCOM5) + else // if(sercom == SERCOM5) { clockId = GCM_SERCOM5_CORE; IdNvic = SERCOM5_IRQn; diff --git a/cores/arduino/Server.h b/cores/arduino/Server.h index bdd860d2c743d21d6eeb1db91ebd4e06e5b669a4..69e3e39fe68a8a519b104ce6a83b8d094a6953da 100644 --- a/cores/arduino/Server.h +++ b/cores/arduino/Server.h @@ -1,5 +1,6 @@ /* - Copyright (c) 2014 Arduino. All right reserved. + Server.h - Base class that provides Server + Copyright (c) 2011 Adrian McEwen. 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 @@ -8,8 +9,8 @@ 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. + 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 @@ -19,6 +20,8 @@ #ifndef server_h #define server_h +#include "Print.h" + class Server : public Print { public: virtual void begin() =0; diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 455b271d9d6507364baa34085e90a371bdd9e0a5..41285d4f056afc97a551a414a9402cd906dbdf5a 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -105,7 +105,7 @@ uint32_t USBD_Available(uint32_t ep) // Return number of bytes read uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len) { - if (!_usbConfiguration || len < 0) + if (!_usbConfiguration) return -1; uint32_t n = UDD_FifoByteCount(ep); @@ -200,8 +200,8 @@ uint32_t USBD_RecvControl(void* d, uint32_t len) if (read > len) read = len; UDD_Recv(EP0, &buffer); - while (!udd_is_OUT_transf_cplt(EP0)); - for (int i=0; i<read; i++) { + while (!udd_is_OUT_transf_cplt(EP0)); + for (uint32_t i=0; i<read; i++) { data[i] = buffer[i]; } udd_OUT_transfer_allowed(EP0); diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp index 1c626ab110b0c813404c9fcb4cdeb35d0ed588a2..53f16cdc051eb4a7726df7729c711b7951235349 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -1,5 +1,8 @@ /* - Copyright (c) 2014 Arduino. All right reserved. + WString.cpp - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -8,8 +11,8 @@ 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. + 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 @@ -213,10 +216,10 @@ void String::move(String &rhs) String & String::operator = (const String &rhs) { if (this == &rhs) return *this; - + if (rhs.buffer) copy(rhs.buffer, rhs.len); else invalidate(); - + return *this; } @@ -238,7 +241,7 @@ String & String::operator = (const char *cstr) { if (cstr) copy(cstr, strlen(cstr)); else invalidate(); - + return *this; } @@ -481,7 +484,7 @@ unsigned char String::equalsIgnoreCase( const String &s2 ) const const char *p2 = s2.buffer; while (*p1) { if (tolower(*p1++) != tolower(*p2++)) return 0; - } + } return 1; } @@ -512,7 +515,7 @@ char String::charAt(unsigned int loc) const return operator[](loc); } -void String::setCharAt(unsigned int loc, char c) +void String::setCharAt(unsigned int loc, char c) { if (loc < len) buffer[loc] = c; } @@ -618,10 +621,10 @@ String String::substring(unsigned int left, unsigned int right) const left = temp; } String out; - if (left > len) return out; + if (left >= len) return out; if (right > len) right = len; char temp = buffer[right]; // save the replaced character - buffer[right] = '\0'; + buffer[right] = '\0'; out = buffer + left; // pointer arithmetic buffer[right] = temp; //restore character return out; @@ -683,15 +686,16 @@ void String::replace(const String& find, const String& replace) } void String::remove(unsigned int index){ - if (index >= len) { return; } - int count = len - index; - remove(index, count); + // Pass the biggest integer as the count. The remove method + // below will take care of truncating it at the end of the + // string. + remove(index, (unsigned int)-1); } void String::remove(unsigned int index, unsigned int count){ if (index >= len) { return; } if (count <= 0) { return; } - if (index + count > len) { count = len - index; } + if (count > len - index) { count = len - index; } char *writeTo = buffer + index; len = len - count; strncpy(writeTo, buffer + index + count,len - index); diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index b5b65cb9092ef2d9337a5fecb5e7fe3600525a87..02158b7da49c9542cd899928c4c5cfac506cb85c 100644 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -92,46 +92,39 @@ 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 analogReference( AR_DEFAULT ) ; // Analog Reference is AREF pin (3.3v) - ADC->CTRLA.bit.ENABLE = 1; // Enable ADC - while( ADC->STATUS.bit.SYNCBUSY == 1 ) - { - // Waiting for synchronization - } - // 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 ; -/* temporary DAC disable + 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 dde4da055a7e883833037d19785931b360688ca4..317ac8b8f9f8e9e0d716d44b9bf9495b96457272 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -25,32 +25,59 @@ extern "C" { #endif static int _readResolution = 10; -static int _writeResolution = 8; +static int _writeResolution = 10; + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncADC() __attribute__((always_inline, unused)); +static void syncADC() { + while (ADC->STATUS.bit.SYNCBUSY == 1) + ; +} + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncDAC() __attribute__((always_inline, unused)); +static void syncDAC() { + while (DAC->STATUS.bit.SYNCBUSY == 1) + ; +} void analogReadResolution( int res ) { - _readResolution = res ; + syncADC(); + switch ( res ) + { + case 12: + ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val; + break; + case 8: + ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val; + break; + default: + 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) ; } } @@ -62,17 +89,35 @@ static inline uint32_t mapResolution( uint32_t value, uint32_t from, uint32_t to */ void analogReference( eAnalogReference ulMode ) { + syncADC(); switch ( ulMode ) { case AR_INTERNAL: - 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_DEFAULT: case AR_EXTERNAL: - default: + 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; } } @@ -87,29 +132,52 @@ uint32_t analogRead( uint32_t ulPin ) pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType); - ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber; - - // Start conversion - ADC->SWTRIG.bit.START = 1; - - while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 ) + if (ulPin == A0) // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled { - // Waiting for a complete conversion and complete synchronization + syncDAC(); + DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC + //DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off. + syncDAC(); } - // Store the value - valueRead = ADC->RESULT.reg; + pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType); + + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber; // Selection for the positive ADC input + + // 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. + */ + syncADC(); + ADC->CTRLA.bit.ENABLE = 0x01; // Enable ADC + + // Start conversion + syncADC(); + 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. + syncADC(); + 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; + + syncADC(); + ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC + syncADC(); return valueRead; } @@ -135,7 +203,12 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) return; } - DAC->DATA.reg = ulValue & 0x3FF; // Dac on 10 bits. + syncDAC(); + DAC->DATA.reg = ulValue & 0x3FF; // DAC on 10 bits. + syncDAC(); + DAC->CTRLA.bit.ENABLE = 0x01; //Enable ADC + syncDAC(); + return ; } if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM ) diff --git a/cores/arduino/wiring_analog.h b/cores/arduino/wiring_analog.h index d5382dc44d6077a52eab7580ad305ce6b0f2b661..787f711be4c01bd0193bb06fca9875563801ae44 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/platform.txt b/platform.txt index f4b4e6467875e12f7736e6a467204ec63c97c9dc..c7bb76c82dd276166ecc0e9a8858058f64b349d6 100644 --- a/platform.txt +++ b/platform.txt @@ -11,12 +11,12 @@ version=1.8.0 compiler.path={runtime.ide.path}/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/ compiler.c.cmd=arm-none-eabi-gcc -compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os -Wall -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 +compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os -W -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 compiler.c.elf.cmd=arm-none-eabi-gcc compiler.c.elf.flags=-Os -Wl,--gc-sections -save-temps compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=arm-none-eabi-g++ -compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os -Wall -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions +compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os -W -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions compiler.ar.cmd=arm-none-eabi-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arm-none-eabi-objcopy diff --git a/variants/arduino_zero/variant.h b/variants/arduino_zero/variant.h index ab7050cefcff23b1c51a6c0525b10002822379ac..075e66f2f7a8dff50dd31fe3c543b04cccd1dff2 100644 --- a/variants/arduino_zero/variant.h +++ b/variants/arduino_zero/variant.h @@ -57,13 +57,21 @@ extern "C" #define digitalPinToPort(P) ( &(PORT->Group[g_APinDescription[P].ulPort]) ) #define digitalPinToBitMask(P) ( 1 << g_APinDescription[P].ulPin ) -#define digitalPinToTimer(P) ( ) //#define analogInPinToBit(P) ( ) #define portOutputRegister(port) ( &(port->OUT.reg) ) #define portInputRegister(port) ( &(port->IN.reg) ) #define portModeRegister(port) ( &(port->DIR.reg) ) #define digitalPinHasPWM(P) ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER ) +/* + * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD + * architecture. If you need to check if a pin supports PWM you must + * use digitalPinHasPWM(..). + * + * https://github.com/arduino/Arduino/issues/1833 + */ +// #define digitalPinToTimer(P) + // Interrupts #define digitalPinToInterrupt(P) ( g_APinDescription[P].ulExtInt )