diff --git a/hardware/arduino/sam/cores/arduino/Arduino.h b/hardware/arduino/sam/cores/arduino/Arduino.h index f074d5b27bc..4fae76a2a30 100644 --- a/hardware/arduino/sam/cores/arduino/Arduino.h +++ b/hardware/arduino/sam/cores/arduino/Arduino.h @@ -155,6 +155,16 @@ typedef enum _ETCChannel #define PIN_ATTR_PWM (1UL<<3) #define PIN_ATTR_TIMER (1UL<<4) +#define PIN_STATUS_DIGITAL_INPUT_PULLUP (0x01) +#define PIN_STATUS_DIGITAL_INPUT (0x02) +#define PIN_STATUS_DIGITAL_OUTPUT (0x03) +#define PIN_STATUS_ANALOG (0x04) +#define PIN_STATUS_PWM (0x05) +#define PIN_STATUS_TIMER (0x06) +#define PIN_STATUS_SERIAL (0x07) +#define PIN_STATUS_DW_LOW (0x10) +#define PIN_STATUS_DW_HIGH (0x11) + /* Types used for the tables below */ typedef struct _PinDescription { @@ -170,6 +180,8 @@ typedef struct _PinDescription ETCChannel ulTCChannel ; } PinDescription ; +extern uint8_t g_pinStatus[]; + /* Pins table to be instanciated into variant.cpp */ extern const PinDescription g_APinDescription[] ; diff --git a/hardware/arduino/sam/cores/arduino/wiring_analog.c b/hardware/arduino/sam/cores/arduino/wiring_analog.c index 1385f01ebf5..05029782cc7 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_analog.c +++ b/hardware/arduino/sam/cores/arduino/wiring_analog.c @@ -148,11 +148,12 @@ uint32_t analogRead(uint32_t ulPin) case ADC11 : // Enable the corresponding channel - if (ulChannel != latestSelectedChannel) { + if (adc_get_channel_status(ADC, ulChannel) != 1) { adc_enable_channel( ADC, ulChannel ); - if ( latestSelectedChannel != (uint32_t)-1 ) + if ( latestSelectedChannel != (uint32_t)-1 && ulChannel != latestSelectedChannel) adc_disable_channel( ADC, latestSelectedChannel ); latestSelectedChannel = ulChannel; + g_pinStatus[ulPin] = (g_pinStatus[ulPin] & 0xF0) | PIN_STATUS_ANALOG; } // Start the ADC @@ -189,13 +190,9 @@ static void TC_SetCMR_ChannelB(Tc *tc, uint32_t chan, uint32_t v) } static uint8_t PWMEnabled = 0; -static uint8_t pinEnabled[PINS_COUNT]; static uint8_t TCChanEnabled[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; void analogOutputInit(void) { - uint8_t i; - for (i=0; i> 4 ? PIO_OUTPUT_1 : PIO_OUTPUT_0, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ; + g_pinStatus[ulPin] = (g_pinStatus[ulPin] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; + /* if all pins are output, disable PIO Controller clocking, reduce power consumption */ if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff ) { @@ -78,6 +96,12 @@ extern void digitalWrite( uint32_t ulPin, uint32_t ulVal ) return ; } + if ((g_pinStatus[ulPin] & 0xF) == PIN_STATUS_PWM) { + pinMode(ulPin, OUTPUT); + } + + g_pinStatus[ulPin] = (g_pinStatus[ulPin] & 0x0F) | (ulVal << 4) ; + if ( PIO_GetOutputDataStatus( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin ) == 0 ) { PIO_PullUp( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin, ulVal ) ; @@ -90,6 +114,14 @@ extern void digitalWrite( uint32_t ulPin, uint32_t ulVal ) extern int digitalRead( uint32_t ulPin ) { + if ((g_pinStatus[ulPin] & 0xF) == PIN_STATUS_DIGITAL_OUTPUT) { + return (g_pinStatus[ulPin] & 0xF0) >> 4; + } + + if ((g_pinStatus[ulPin] & 0xF) == PIN_STATUS_ANALOG) { + pinMode(ulPin, INPUT); + } + if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN ) { return LOW ; diff --git a/hardware/arduino/sam/system/libsam/source/adc.c b/hardware/arduino/sam/system/libsam/source/adc.c index 18a1b4c386b..20814a0b1e0 100644 --- a/hardware/arduino/sam/system/libsam/source/adc.c +++ b/hardware/arduino/sam/system/libsam/source/adc.c @@ -192,18 +192,39 @@ void adc_set_resolution(Adc *p_adc,const enum adc_resolution_t resolution) void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger, uint8_t uc_freerun) { - p_adc->ADC_MR |= trigger | ((uc_freerun << 7) & ADC_MR_FREERUN); + //Warning ADC_MR_TRGSEL_Msk does not include ADC_MR_TRGEN. + p_adc->ADC_MR &= ~(ADC_MR_TRGEN | ADC_MR_TRGSEL_Msk | ADC_MR_FREERUN); //Clear all bits related to triggers and freerun + + //Configure FreeRun + if(uc_freerun & ADC_MR_FREERUN == ADC_MR_FREERUN_ON) { //FreeRun is enabled + p_adc->ADC_MR |= ADC_MR_FREERUN_ON; + + //Free Run Mode: Never wait for any trigger + //No need to continue and enable hardware triggers + return; + } + + //Configure hardware triggers + if(trigger & ADC_MR_TRGEN == ADC_MR_TRGEN_EN) { //Hardware trigger is enabled + p_adc->ADC_MR |= (trigger & ADC_MR_TRGSEL_Msk) | ADC_MR_TRGEN_EN; //Set trigger selection bits and enable hardware trigger + } } #elif SAM3U_SERIES /** - * \brief Configure conversion trigger and free run mode. + * \brief Configure conversion trigger. * * \param p_adc Pointer to an ADC instance. * \param trigger Conversion trigger. */ void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger) { - p_adc->ADC_MR |= trigger; + //Warning ADC_MR_TRGSEL_Msk does not include ADC_MR_TRGEN. + p_adc->ADC_MR &= ~(ADC_MR_TRGEN | ADC_MR_TRGSEL_Msk); //Clear all bits related to triggers + + //Configure hardware triggers + if(trigger & ADC_MR_TRGEN == ADC_MR_TRGEN_EN) { //Hardware trigger is enabled + p_adc->ADC_MR |= (trigger & ADC_MR_TRGSEL_Msk) | ADC_MR_TRGEN_EN; //Set trigger selection bits and enable hardware trigger + } } #endif diff --git a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp index f95d8501745..7a0de80a9df 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp +++ b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp @@ -291,6 +291,9 @@ extern const PinDescription g_APinDescription[]= { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER } } ; + +uint8_t g_pinStatus[PINS_COUNT] = {0}; + #ifdef __cplusplus } #endif