diff --git a/src/AdvancedADC.cpp b/src/AdvancedADC.cpp index 49f7e23..195f8ec 100644 --- a/src/AdvancedADC.cpp +++ b/src/AdvancedADC.cpp @@ -115,9 +115,14 @@ DMABuffer &AdvancedADC::read() { return NULLBUF; } -int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers) { - ADCName instance = ADC_NP; +int AdvancedADC::getAssignedADC() +{ + return(selected_adc); +} +int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, bool do_start) { + + ADCName instance = ADC_NP; // Sanity checks. if (resolution >= AN_ARRAY_SIZE(ADC_RES_LUT) || (descr && descr->pool)) { return 0; @@ -128,7 +133,9 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl adc_pins[i] = (PinName) (adc_pins[i] & ~(ADC_PIN_ALT_MASK)); } - // Find an ADC that can be used with these set of pins/channels. + + // If ADC not specified find an ADC that can be used with these set of pins/channels. + for (size_t i=0; instance == ADC_NP && iadc.Instance == ((ADC_TypeDef*) tmp_instance)) { instance = tmp_instance; adc_pins[0] = pin; + selected_adc=j+1; } } } } - + if (instance == ADC_NP) { // Couldn't find a free ADC/descriptor. descr = nullptr; @@ -159,6 +167,8 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl // Configure ADC pins. pinmap_pinout(adc_pins[0], PinMap_ADC); + + //If ADC was not specified ensure the remaining channels are mappable to same ADC uint8_t ch_init = 1; for (size_t i=1; ipool = new DMABufferPool(n_samples, n_channels, n_buffers); if (descr->pool == nullptr) { return 0; } + + //Allocate two DMA buffers for double buffering descr->dmabuf[0] = descr->pool->allocate(); descr->dmabuf[1] = descr->pool->allocate(); @@ -202,7 +213,7 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl } // Link DMA handle to ADC handle, and start the ADC. - __HAL_LINKDMA(&descr->adc, DMA_Handle, descr->dma); + __HAL_LINKDMA(&descr->adc, DMA_Handle, descr->dma); if (HAL_ADC_Start_DMA(&descr->adc, (uint32_t *) descr->dmabuf[0]->data(), descr->dmabuf[0]->size()) != HAL_OK) { return 0; } @@ -212,26 +223,90 @@ int AdvancedADC::begin(uint32_t resolution, uint32_t sample_rate, size_t n_sampl hal_dma_enable_dbm(&descr->dma, descr->dmabuf[0]->data(), descr->dmabuf[1]->data()); HAL_NVIC_EnableIRQ(descr->dma_irqn); + if(do_start){ + return(start(sample_rate)); + } + + return 1; +} + +int AdvancedADC::start(uint32_t sample_rate){ // Init, config and start the ADC timer. hal_tim_config(&descr->tim, sample_rate); + + //Start Timer and ADC Capture. If Dual Mode was enabled, then this will also start ADC2 if (HAL_TIM_Base_Start(&descr->tim) != HAL_OK) { return 0; } - + return 1; } -int AdvancedADC::stop() -{ +int AdvancedADC::stop(){ + dac_descr_deinit(descr, true); + return 1; } -AdvancedADC::~AdvancedADC() -{ +void AdvancedADC::clear() { + descr->pool->flush(); +} + +AdvancedADC::~AdvancedADC(){ dac_descr_deinit(descr, true); } +int AdvancedADCDual::begin(AdvancedADC *in1, AdvancedADC *in2, uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers){ + adcIN1=in1; + adcIN2=in2; + + int result=0; + + //Configure first pin on ADC1 + result=adcIN1->begin(resolution,sample_rate,n_samples,n_buffers,1,&(adc_pins_unmapped[0]),false); + if(result!=1 || adcIN1->getAssignedADC()!=1) + { + return(0); + } + //Configure all other pins on ADC2 + result=adcIN2->begin(resolution,sample_rate,n_samples,n_buffers,n_channels-1,&(adc_pins_unmapped[1]),false); + if(result!=1 || adcIN2->getAssignedADC()!=2) + { + return(0); + } + + result=hal_enable_dual_mode(); + + result=adcIN1->start(sample_rate); + + if(result!=1) + { + return(0); + } + + return(1); + +} + +int AdvancedADCDual:: stop(){ + if(adcIN1!=nullptr) + { + adcIN1->stop(); + } + if(adcIN2!=nullptr) + { + adcIN2->stop(); + } + //Always disable dual mode when stopped + int result=hal_disable_dual_mode(); + return(1); +} + +AdvancedADCDual::~AdvancedADCDual(){ + int result=stop(); +} + extern "C" { void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *adc) { adc_descr_t *descr = adc_descr_get(adc->Instance); diff --git a/src/AdvancedADC.h b/src/AdvancedADC.h index 844985b..3fad9b1 100644 --- a/src/AdvancedADC.h +++ b/src/AdvancedADC.h @@ -31,6 +31,8 @@ class AdvancedADC { size_t n_channels; adc_descr_t *descr; PinName adc_pins[AN_MAX_ADC_CHANNELS]; + bool dualMode; + uint8_t selected_adc; public: template @@ -41,21 +43,75 @@ class AdvancedADC { for (auto p : {p0, args...}) { adc_pins[n_channels++] = analogPinToPinName(p); } + dualMode=false; + selected_adc=0; } AdvancedADC(): n_channels(0), descr(nullptr) {} ~AdvancedADC(); bool available(); SampleBuffer read(); - int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers); - int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, size_t n_pins, pin_size_t *pins) { + int getAssignedADC(); + int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, bool do_start=true); + int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers, size_t n_pins, pin_size_t *pins, bool start=true) { if (n_pins > AN_MAX_ADC_CHANNELS) n_pins = AN_MAX_ADC_CHANNELS; for (size_t i = 0; i < n_pins; ++i) { adc_pins[i] = analogPinToPinName(pins[i]); } + n_channels = n_pins; - return begin(resolution, sample_rate, n_samples, n_buffers); + return begin(resolution, sample_rate, n_samples, n_buffers,start); } + + void clear(); + + int start(uint32_t sample_rate); + + //void setADCDualMode(bool dm); + //int enableDualMode(); + //int disableDualMode(); + int stop(); }; +class AdvancedADCDual { + private: + size_t n_channels; + pin_size_t adc_pins_unmapped[AN_MAX_ADC_CHANNELS]; + AdvancedADC *adcIN1; + AdvancedADC *adcIN2; + public: + + //For now ADC1 will always be one pin, and ADC2 will sample the rest + template + AdvancedADCDual(pin_size_t p0, T ... args):n_channels(0), adcIN1(nullptr), adcIN2(nullptr){ + static_assert(sizeof ...(args) < AN_MAX_ADC_CHANNELS+1, + "A maximum of 5 channels can be sampled successively."); + static_assert (sizeof ...(args) >=2, + "At least two channels are required for Dual Mode ADC."); + for (auto p : {p0, args...}) { + adc_pins_unmapped[n_channels++] = p; + } + } + + AdvancedADCDual(): n_channels(0), adcIN1(nullptr), adcIN2(nullptr) + { + } + ~AdvancedADCDual(); + + int begin(AdvancedADC *in1, AdvancedADC *in2,uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers); + int begin(AdvancedADC *in1, AdvancedADC *in2,uint32_t resolution, uint32_t sample_rate, + size_t n_samples, size_t n_buffers, size_t n_pins, pin_size_t *pins) { + if (n_pins > AN_MAX_ADC_CHANNELS) n_pins = AN_MAX_ADC_CHANNELS; + if(n_pins<2) //Cannot run Dual mode with less than two input pins + return(0); + for (size_t i = 0; i < n_pins; ++i) { + adc_pins_unmapped[i] = pins[i]; + Serial.println("Pin: "+String(pins[i])); + } + n_channels = n_pins; + return begin(in1, in2, resolution, sample_rate, n_samples, n_buffers); + } + int stop(); +}; + #endif /* ARDUINO_ADVANCED_ADC_H_ */ diff --git a/src/HALConfig.cpp b/src/HALConfig.cpp index 984d9f7..98d96ae 100644 --- a/src/HALConfig.cpp +++ b/src/HALConfig.cpp @@ -46,18 +46,18 @@ int hal_tim_config(TIM_HandleTypeDef *tim, uint32_t t_freq) { sConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; if (tim->Instance == TIM1) { - __HAL_RCC_TIM1_CLK_ENABLE(); + __HAL_RCC_TIM1_CLK_ENABLE(); } else if (tim->Instance == TIM2) { __HAL_RCC_TIM2_CLK_ENABLE(); - } else if (tim->Instance == TIM3) { + } else if (tim->Instance == TIM3) { __HAL_RCC_TIM3_CLK_ENABLE(); - } else if (tim->Instance == TIM4) { + } else if (tim->Instance == TIM4) { __HAL_RCC_TIM4_CLK_ENABLE(); - } else if (tim->Instance == TIM5) { + } else if (tim->Instance == TIM5) { __HAL_RCC_TIM5_CLK_ENABLE(); - } else if (tim->Instance == TIM6) { + } else if (tim->Instance == TIM6) { __HAL_RCC_TIM6_CLK_ENABLE(); - } + } // Init and config the timer. __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); @@ -167,10 +167,20 @@ static uint32_t ADC_RANK_LUT[] = { ADC_REGULAR_RANK_1, ADC_REGULAR_RANK_2, ADC_REGULAR_RANK_3, ADC_REGULAR_RANK_4, ADC_REGULAR_RANK_5 }; +int hal_enable_dual_mode() { + LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_DUAL_REG_SIMULT); + return(1); +} + +int hal_disable_dual_mode() { + LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_INDEPENDENT); + return(1); +} + int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger, PinName *adc_pins, uint32_t n_channels) { // Set ADC clock source. __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); - + // Enable ADC clock if (adc->Instance == ADC1) { __HAL_RCC_ADC12_CLK_ENABLE(); @@ -206,7 +216,7 @@ int hal_adc_config(ADC_HandleTypeDef *adc, uint32_t resolution, uint32_t trigger sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; - + for (size_t rank=0; rank