diff --git a/miosix/arch/cortexM3_efm32gg/common/drivers/adc.cpp b/miosix/arch/cortexM3_efm32gg/common/drivers/adc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad3cb9331da38ff6fc0e6cd883459ee7b9b4a181 --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/common/drivers/adc.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (C) 2023 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include "adc.h" +#include "miosix.h" + +Adc& Adc::instance() +{ + static Adc singleton; + return singleton; +} + +void Adc::powerMode(AdcPowerMode mode) +{ + ADC0->CTRL &= ~ 0b11; //Clear WARMUPMODE field + //NOTE: from an implementation perspective Off is the same as OnDemand + //but from a logical perspective Off is used to turn the ADC off after it + //has been turned on, while OnDemand is used to pay the startup cost at + //every conversion + if(mode==On) + { + ADC0->CTRL |= ADC_CTRL_WARMUPMODE_KEEPADCWARM; + while((ADC0->STATUS & ADC_STATUS_WARM)==0) ; + } +} + +unsigned short Adc::readChannel(int channel) +{ + auto temp = ADC0->SINGLECTRL; + temp &= ~(0xf<<8); //Clear INPUTSEL field + temp |= (channel & 0xf)<<8; + ADC0->SINGLECTRL = temp; + ADC0->CMD=ADC_CMD_SINGLESTART; + while((ADC0->STATUS & ADC_STATUS_SINGLEDV)==0) ; + return ADC0->SINGLEDATA; +} + +Adc::Adc() +{ + { + miosix::FastInterruptDisableLock dLock; + CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_ADC0; + } + ADC0->CTRL = 0b11111<<16 //TIMEBASE ?? + | (4-1)<<8 //PRESC 48/4=12MHz < 13MHz OK + | ADC_CTRL_LPFMODE_RCFILT + | ADC_CTRL_WARMUPMODE_NORMAL; + //TODO: expose more options + ADC0->SINGLECTRL = ADC_SINGLECTRL_AT_256CYCLES + | ADC_SINGLECTRL_REF_VDD + | ADC_SINGLECTRL_RES_12BIT + | ADC_SINGLECTRL_ADJ_RIGHT; +} diff --git a/miosix/arch/cortexM3_efm32gg/common/drivers/adc.h b/miosix/arch/cortexM3_efm32gg/common/drivers/adc.h new file mode 100644 index 0000000000000000000000000000000000000000..07c5eeb7b6b20e529eddbec511edb4d8e9662a40 --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/common/drivers/adc.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2023 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#pragma once + +/** + * Efm32 ADC driver + * + * Example code + * \code + * { + * FastInterruptDisableLock dLock; + * //GPIO digital logic must be disabled to use as ADC input + * expansion::gpio0::mode(Mode::DISABLED); //GPIO0 is PD3 or ADC0_CH3 + * expansion::gpio1::mode(Mode::OUTPUT_HIGH); + * } + * auto& adc=Adc::instance(); + * adc.powerMode(Adc::OnDemand); + * for(;;) + * { + * iprintf("%d\n",adc.readChannel(3)); + * Thread::sleep(500); + * } + * \endcode + */ +class Adc +{ +public: + /** + * Possible ADC power modes + */ + enum AdcPowerMode + { + Off, On, OnDemand + }; + + /** + * \return an instance to the ADC (singleton) + */ + static Adc& instance(); + + /** + * Change the ADC power mode + * \param mode power mode + */ + void powerMode(AdcPowerMode mode); + + /** + * Read an ADC channel + * \param channel channel to read + * \return ADC sample, in the 0..4095 range + */ + unsigned short readChannel(int channel); + +public: + Adc(); +}; diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index ac7765758b7fd2d66bfbd2f645c500641dad9ff4..c591e9942d14a4d317a51dbce963532100be8e1e 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -2248,6 +2248,7 @@ else ifeq ($(ARCH),cortexM3_efm32gg) ARCH_SRC += \ arch/common/core/interrupts_cortexMx.cpp \ arch/common/drivers/serial_efm32.cpp \ + $(ARCH_INC)/drivers/adc.cpp \ $(ARCH_INC)/interfaces-impl/portability.cpp \ $(ARCH_INC)/interfaces-impl/gpio_impl.cpp \ $(ARCH_INC)/interfaces-impl/delays.cpp \