From 0e4201f25dd8fc3162f21d27220410039e329a9b Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 24 Jul 2021 10:04:54 +0200 Subject: [PATCH] WiP --- radio/src/gui/128x64/radio_calibration.cpp | 1 + radio/src/gui/colorlcd/radio_calibration.cpp | 1 + radio/src/gui/colorlcd/radio_hardware.cpp | 1 + .../src/gui/common/stdlcd/radio_hardware.cpp | 1 + radio/src/hal/adc_driver.cpp | 145 +++++++++ radio/src/hal/adc_driver.h | 38 ++- radio/src/main.cpp | 1 + radio/src/opentx.cpp | 3 +- .../targets/common/arm/stm32/board_common.h | 7 +- .../{adc_driver.cpp => stm32_hal_adc.cpp} | 285 +++++++----------- .../targets/common/arm/stm32/stm32_hal_adc.h | 45 +++ radio/src/targets/horus/CMakeLists.txt | 3 +- radio/src/targets/horus/board.cpp | 5 +- radio/src/targets/taranis/CMakeLists.txt | 3 +- radio/src/targets/taranis/board.cpp | 5 +- 15 files changed, 350 insertions(+), 194 deletions(-) create mode 100644 radio/src/hal/adc_driver.cpp rename radio/src/targets/common/arm/stm32/{adc_driver.cpp => stm32_hal_adc.cpp} (57%) create mode 100644 radio/src/targets/common/arm/stm32/stm32_hal_adc.h diff --git a/radio/src/gui/128x64/radio_calibration.cpp b/radio/src/gui/128x64/radio_calibration.cpp index 3e1a30d20..2ee780ea8 100644 --- a/radio/src/gui/128x64/radio_calibration.cpp +++ b/radio/src/gui/128x64/radio_calibration.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "hal/adc_driver.h" #define XPOT_DELTA 10 #define XPOT_DELAY 10 /* cycles */ diff --git a/radio/src/gui/colorlcd/radio_calibration.cpp b/radio/src/gui/colorlcd/radio_calibration.cpp index fcf41f723..6947fe522 100644 --- a/radio/src/gui/colorlcd/radio_calibration.cpp +++ b/radio/src/gui/colorlcd/radio_calibration.cpp @@ -22,6 +22,7 @@ #include "radio_calibration.h" #include "sliders.h" #include "view_main_decoration.h" +#include "hal/adc_driver.h" #define XPOT_DELTA 10 #define XPOT_DELAY 5 /* cycles */ diff --git a/radio/src/gui/colorlcd/radio_hardware.cpp b/radio/src/gui/colorlcd/radio_hardware.cpp index 60f1fbe94..6b04ccf95 100644 --- a/radio/src/gui/colorlcd/radio_hardware.cpp +++ b/radio/src/gui/colorlcd/radio_hardware.cpp @@ -24,6 +24,7 @@ #include "radio_diaganas.h" #include "opentx.h" #include "libopenui.h" +#include "hal/adc_driver.h" #define SET_DIRTY() storageDirty(EE_GENERAL) diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 69004bf75..0ff93f0b4 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -19,6 +19,7 @@ */ #include +#include "hal/adc_driver.h" #if defined(PCBSKY9X) #define HW_SETTINGS_COLUMN (2+(15*FW)) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp new file mode 100644 index 000000000..4b36440a3 --- /dev/null +++ b/radio/src/hal/adc_driver.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) EdgeTx + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#include "adc_driver.h" +#include "board.h" + +// IS_POT_SLIDER_AVAILABLE() +#include "opentx.h" + +const etx_hal_adc_driver_t* etx_hal_adc_driver = nullptr; + +#if defined(SIMU) + // not needed +#elif defined(RADIO_T16) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; +#elif defined(RADIO_T18) + const int8_t adcDirection[NUM_ANALOGS] = { 1,-1,1,-1, -1,1,-1, -1,1, -1,1 }; +#elif defined(RADIO_TX16S) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; +#elif defined(PCBX10) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,1, 1, -1}; +#elif defined(PCBX9E) +#if defined(HORUS_STICKS) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,1, -1,-1,-1}; +#else + const int8_t adcDirection[NUM_ANALOGS] = {1,1,-1,-1, -1,-1,-1,1, -1,1,1, -1,-1,-1}; +#endif + const uint8_t adcMapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/, + 11 /*POT1*/, 4 /*POT2*/, 5 /*POT3*/, 6 /*POT4*/, + 12 /*SLIDER1*/, 13 /*SLIDER2*/, 7 /*SLIDER3*/, 8 /*SLIDER4*/, + 9 /*TX_VOLTAGE*/, 10 /*TX_VBAT*/ }; +#elif defined(PCBX9DP) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1, 1}; +#elif defined(PCBX9D) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,0, 1,1, 1, 1}; +#elif defined(RADIO_TX12) + const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, -1,-1, 1, 1}; +#elif defined(PCBX7) + const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1, 1}; +#elif defined(PCBX9LITE) + const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1}; +#elif defined(PCBXLITE) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,-1,1, -1,1, 1, 1}; +#endif + +uint16_t adcValues[NUM_ANALOGS] __DMA; + +#if defined(PCBX10) +uint16_t rtcBatteryVoltage; +#endif + +void adcInit(const etx_hal_adc_driver_t* driver) +{ + etx_hal_adc_driver = driver; + if (etx_hal_adc_driver && etx_hal_adc_driver->init) + etx_hal_adc_driver->init(); +} + +static void adcSingleRead() +{ + if (!etx_hal_adc_driver) return; + + if (etx_hal_adc_driver->start_conversion) + etx_hal_adc_driver->start_conversion(); + + if (etx_hal_adc_driver->wait_completion) + etx_hal_adc_driver->wait_completion(); +} + +void adcRead() +{ + uint16_t temp[NUM_ANALOGS] = { 0 }; + + for (int i=0; i<4; i++) { + adcSingleRead(); + for (uint8_t x=FIRST_ANALOG_ADC; x> 2; + } + +#if NUM_PWMSTICKS > 0 + if (STICKS_PWM_ENABLED()) { + sticksPwmRead(adcValues); + } +#endif +} + +#if defined(PCBX10) +uint16_t getRTCBatteryVoltage() +{ + return (rtcBatteryVoltage * 2 * ADC_VREF_PREC2) / 2048; +} +#else +uint16_t getRTCBatteryVoltage() +{ + return (getAnalogValue(TX_RTC_VOLTAGE) * ADC_VREF_PREC2) / 2048; +} +#endif + +#if !defined(SIMU) +uint16_t getAnalogValue(uint8_t index) +{ + if (IS_POT(index) && !IS_POT_SLIDER_AVAILABLE(index)) { + // Use fixed analog value for non-existing and/or non-connected pots. + // Non-connected analog inputs will slightly follow the adjacent connected analog inputs, + // which produces ghost readings on these inputs. + return 0; + } +#if defined(PCBX9E) + index = adcMapping[index]; +#endif + if (adcDirection[index] < 0) + return 4095 - adcValues[index]; + else + return adcValues[index]; +} +#endif // #if !defined(SIMU) diff --git a/radio/src/hal/adc_driver.h b/radio/src/hal/adc_driver.h index 718351ded..50d1bd168 100644 --- a/radio/src/hal/adc_driver.h +++ b/radio/src/hal/adc_driver.h @@ -21,17 +21,33 @@ #pragma once -struct etx_hal_adc_channel { - const uint8_t adc_channel; - const uint8_t rank; - const uint8_t sample_time; +#include + +#if NUM_PWMSTICKS > 0 + #define FIRST_ANALOG_ADC (STICKS_PWM_ENABLED() ? NUM_PWMSTICKS : 0) + #define NUM_ANALOGS_ADC (STICKS_PWM_ENABLED() ? (NUM_ANALOGS - NUM_PWMSTICKS) : NUM_ANALOGS) +#elif defined(PCBX9E) + #define FIRST_ANALOG_ADC 0 + #define NUM_ANALOGS_ADC 11 + #define NUM_ANALOGS_ADC_EXT (NUM_ANALOGS - NUM_ANALOGS_ADC) +#else + #define FIRST_ANALOG_ADC 0 + #define NUM_ANALOGS_ADC NUM_ANALOGS +#endif + +#if defined(PCBX10) +extern uint16_t rtcBatteryVoltage; +#endif + +struct etx_hal_adc_driver_t { + void (*init)(); + void (*start_conversion)(); + void (*wait_completion)(); }; -typedef const etx_hal_adc_channel* (*etx_hal_adc_get_channels)(); -typedef uint8_t (*etx_hal_adc_get_nconv)(); +void adcInit(const etx_hal_adc_driver_t* driver); +//void adcDeInit(); -struct etx_hal_adc { - ADC_TypeDef* adc; - const etx_hal_adc_get_nconv get_nconv; - const etx_hal_adc_get_channels get_channels; -}; +void adcRead(); +uint16_t getRTCBatteryVoltage(); +uint16_t getAnalogValue(uint8_t index); diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 5c927db79..6c7fa7d55 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "hal/adc_driver.h" #if defined(LIBOPENUI) #include "libopenui.h" diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index ca46b174e..0c0975aff 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -19,7 +19,8 @@ */ #include "opentx.h" -#include +#include "io/frsky_firmware_update.h" +#include "hal/adc_driver.h" #if defined(LIBOPENUI) #include "libopenui.h" diff --git a/radio/src/targets/common/arm/stm32/board_common.h b/radio/src/targets/common/arm/stm32/board_common.h index 43a83ac91..e55424a40 100644 --- a/radio/src/targets/common/arm/stm32/board_common.h +++ b/radio/src/targets/common/arm/stm32/board_common.h @@ -103,12 +103,7 @@ extern "C" { #include "../simu/simpgmspace.h" #endif -// ADC driver -void adcInit(); -void adcRead(); -uint16_t getAnalogValue(uint8_t index); -uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps -uint16_t getRTCBatteryVoltage(); +uint16_t getBatteryVoltage(); // STM32 uses a 25K+25K voltage divider bridge to measure the battery voltage // Measuring VBAT puts considerable drain (22 µA) on the battery instead of normal drain (~10 nA) diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/stm32_hal_adc.cpp similarity index 57% rename from radio/src/targets/common/arm/stm32/adc_driver.cpp rename to radio/src/targets/common/arm/stm32/stm32_hal_adc.cpp index b17ce3a9a..28190dd66 100644 --- a/radio/src/targets/common/arm/stm32/adc_driver.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_hal_adc.cpp @@ -20,58 +20,7 @@ #include "opentx.h" #include "hal/adc_driver.h" - -#if defined(SIMU) - // not needed -#elif defined(RADIO_T16) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; -#elif defined(RADIO_T18) - const int8_t adcDirection[NUM_ANALOGS] = { 1,-1,1,-1, -1,1,-1, -1,1, -1,1 }; -#elif defined(RADIO_TX16S) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; -#elif defined(PCBX10) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,1, 1, -1}; -#elif defined(PCBX9E) -#if defined(HORUS_STICKS) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,1, -1,-1,-1}; -#else - const int8_t adcDirection[NUM_ANALOGS] = {1,1,-1,-1, -1,-1,-1,1, -1,1,1, -1,-1,-1}; -#endif - const uint8_t adcMapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/, - 11 /*POT1*/, 4 /*POT2*/, 5 /*POT3*/, 6 /*POT4*/, - 12 /*SLIDER1*/, 13 /*SLIDER2*/, 7 /*SLIDER3*/, 8 /*SLIDER4*/, - 9 /*TX_VOLTAGE*/, 10 /*TX_VBAT*/ }; -#elif defined(PCBX9DP) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1, 1}; -#elif defined(PCBX9D) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,0, 1,1, 1, 1}; -#elif defined(RADIO_TX12) - const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, -1,-1, 1, 1}; -#elif defined(PCBX7) - const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1, 1}; -#elif defined(PCBX9LITE) - const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1}; -#elif defined(PCBXLITE) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,-1,1, -1,1, 1, 1}; -#endif - -#if NUM_PWMSTICKS > 0 - #define FIRST_ANALOG_ADC (STICKS_PWM_ENABLED() ? NUM_PWMSTICKS : 0) - #define NUM_ANALOGS_ADC (STICKS_PWM_ENABLED() ? (NUM_ANALOGS - NUM_PWMSTICKS) : NUM_ANALOGS) -#elif defined(PCBX9E) - #define FIRST_ANALOG_ADC 0 - #define NUM_ANALOGS_ADC 11 - #define NUM_ANALOGS_ADC_EXT (NUM_ANALOGS - NUM_ANALOGS_ADC) -#else - #define FIRST_ANALOG_ADC 0 - #define NUM_ANALOGS_ADC NUM_ANALOGS -#endif - -uint16_t adcValues[NUM_ANALOGS] __DMA; - -#if defined(PCBX10) -uint16_t rtcBatteryVoltage; -#endif +#include "stm32_hal_adc.h" static void adc_init_pins() { @@ -122,7 +71,7 @@ static void adc_setup_scan_mode(ADC_TypeDef* ADCx, uint8_t nconv) ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE); // ADC_CR2_DDS } -etx_hal_adc_channel ADC_MAIN_channels[] = { +stm32_hal_adc_channel ADC_MAIN_channels[] = { {ADC_CHANNEL_STICK_LH, ADC_SAMPTIME}, {ADC_CHANNEL_STICK_LV, ADC_SAMPTIME}, {ADC_CHANNEL_STICK_RV, ADC_SAMPTIME}, @@ -168,7 +117,7 @@ etx_hal_adc_channel ADC_MAIN_channels[] = { #endif }; -static const etx_hal_adc_channel* ADC_MAIN_get_channels() +static const stm32_hal_adc_channel* ADC_MAIN_get_channels() { #if NUM_PWMSTICKS > 0 if (STICKS_PWM_ENABLED()) @@ -185,7 +134,7 @@ static uint8_t ADC_MAIN_get_nconv() #if defined(ADC_EXT) #if defined(PCBX9E) -static const etx_hal_adc_channel ADC_EXT_channels[] = { +static const stm32_hal_adc_channel ADC_EXT_channels[] = { {ADC_CHANNEL_POT1, ADC_SAMPTIME}, {ADC_CHANNEL_SLIDER1, ADC_SAMPTIME}, {ADC_CHANNEL_SLIDER2, ADC_SAMPTIME} @@ -195,60 +144,82 @@ static uint8_t ADC_EXT_get_nconv() { return NUM_ANALOGS_ADC_EXT; } #elif defined(PCBX10) -static const etx_hal_adc_channel ADC_EXT_channels[] = { +static const stm32_hal_adc_channel ADC_EXT_channels[] = { { ADC_Channel_Vbat, 1, ADC_SAMPTIME } }; static uint8_t ADC_EXT_get_nconv() { return 1; } #endif + +static const stm32_hal_adc_channel* ADC_EXT_get_channels() +{ + return ADC_EXT_channels; +} + #endif -etx_hal_adc ADC_hal_def[] = { - { ADC_MAIN, ADC_MAIN_get_nconv, ADC_MAIN_get_channels }, -#if defined(ADC_EXT) - { ADC_EXT, ADC_EXT_get_nconv, ADC_EXT_get_channels }, +static uint16_t* ADC_MAIN_get_dma_buffer() +{ + return &adcValues[FIRST_ANALOG_ADC]; +} + +#if defined(ADC_EXT) && defined(ADC_EXT_DMA_Stream) +static uint16_t* ADC_EXT_get_dma_buffer() +{ + return adcValues + NUM_ANALOGS_ADC; +} #endif - { nullptr, nullptr, nullptr }, + +stm32_hal_adc ADC_hal_def[] = { + { + ADC_MAIN, + ADC_DMA_Stream, ADC_MAIN_get_dma_buffer, + ADC_MAIN_get_nconv, ADC_MAIN_get_channels + }, +#if defined(ADC_EXT) +#if defined(ADC_EXT_DMA_Stream) + { + ADC_EXT, + ADC_EXT_DMA_Stream, ADC_EXT_get_dma_buffer, + ADC_EXT_get_nconv, ADC_EXT_get_channels + }, +#else + { + ADC_EXT, + nullptr, nullptr, + ADC_EXT_get_nconv, ADC_EXT_get_channels + }, +#endif +#endif + { nullptr, nullptr, nullptr, nullptr, nullptr }, }; - -static void adc_init_channels(const etx_hal_adc* adc_def) +static void adc_init_channels(ADC_TypeDef* adc, const stm32_hal_adc_channel* chan, + uint8_t nconv) { - while (adc_def->adc) { - uint8_t nconv = 0; - if (adc_def->get_nconv) nconv = adc_def->get_nconv(); + if (!chan || !nconv) return; - const etx_hal_adc_channel* chan = nullptr; - if ((nconv > 0) && adc_def->get_channels) - chan = adc_def->get_channels(); - - if (chan) { - uint8_t rank = 1; - while (nconv > 0) { - ADC_RegularChannelConfig(adc_def->adc, chan->adc_channel, rank, - chan->sample_time); - nconv--; rank++; - chan++; - } - } - adc_def++; + uint8_t rank = 1; + while (nconv > 0) { + ADC_RegularChannelConfig(adc, chan->adc_channel, rank, chan->sample_time); + nconv--; rank++; chan++; } } -static void adc_init_dma_channel(ADC_TypeDef* ADCx, DMA_Stream_TypeDef * dma_stream, - uint16_t* dest, uint8_t nconv) +static void adc_init_dma_stream(ADC_TypeDef* adc, DMA_Stream_TypeDef * dma_stream, + uint16_t* dest, uint8_t nconv) { // setup DMA request - dma_stream->CR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC; - dma_stream->PAR = CONVERT_PTR_UINT(&ADCx->DR); + dma_stream->CR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | + DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC; + dma_stream->PAR = CONVERT_PTR_UINT(&adc->DR); dma_stream->M0AR = CONVERT_PTR_UINT(dest); dma_stream->NDTR = nconv; dma_stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0; } - -void adcInit() +static void stm32_hal_adc_init() { adc_init_pins(); @@ -259,26 +230,35 @@ void adcInit() ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStruct); - - adc_setup_scan_mode(ADC_MAIN, NUM_ANALOGS_ADC); -#if defined(PCBX10) // X10 uses ADC3 for "normal" things - adc_setup_scan_mode(ADC_EXT, 1); -#endif -#if defined(PCBX9E) - adc_setup_scan_mode(ADC_EXT, NUM_ANALOGS_ADC_EXT); -#endif + const stm32_hal_adc* adc_def = ADC_hal_def; + while (adc_def->adc) { + uint8_t nconv = 0; + if (adc_def->get_nconv) { + nconv = adc_def->get_nconv(); + if (nconv > 0) { + adc_setup_scan_mode(adc_def->adc, nconv); - // configure each channel - adc_init_channels(ADC_hal_def); + // configure each channel + if (adc_def->get_channels) { + const stm32_hal_adc_channel* chan = adc_def->get_channels(); + adc_init_channels(adc_def->adc, chan, nconv); + } + + if (adc_def->dma_stream && adc_def->get_dma_buffer) { + uint16_t* dma_buffer = adc_def->get_dma_buffer(); + adc_init_dma_stream(adc_def->adc, adc_def->dma_stream, dma_buffer, nconv); + } + } + } + // move to next ADC definition + adc_def++; + } + + //TODO: move VBat & PWM sticks somewhere else. // Enable vbat sensor ADC_VBATCmd(ENABLE); - adc_init_dma_channel(ADC_MAIN, ADC_DMA_Stream, &adcValues[FIRST_ANALOG_ADC], NUM_ANALOGS_ADC); -#if defined(PCBX9E) - adc_init_dma_channel(ADC_EXT, ADC_EXT_DMA_Stream, adcValues + NUM_ANALOGS_ADC, NUM_ANALOGS_ADC_EXT); -#endif - #if NUM_PWMSTICKS > 0 if (STICKS_PWM_ENABLED()) { sticksPwmInit(); @@ -329,20 +309,32 @@ static void adc_start_single_conversion(ADC_TypeDef* ADCx) ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; } -void adcSingleRead() +static void stm32_hal_adc_start_read() { - adc_start_dma_conversion(ADC_MAIN, ADC_DMA_Stream); + const stm32_hal_adc* adc_def = ADC_hal_def; + while (adc_def->adc) { + uint8_t nconv = 0; + if (adc_def->get_nconv) { + nconv = adc_def->get_nconv(); + if (nconv > 0) { + if (adc_def->dma_stream && adc_def->get_dma_buffer) { + adc_start_dma_conversion(adc_def->adc, adc_def->dma_stream); + } else if (nconv == 1){ + adc_start_single_conversion(adc_def->adc); + } + } + } + // move to next ADC definition + adc_def++; + } +} -#if defined(ADC_EXT) -#if defined(ADC_EXT_DMA_Stream) - adc_start_dma_conversion(ADC_EXT, ADC_EXT_DMA_Stream); -#else - // start a single conversion on ADC1 (VBat only) - adc_start_single_conversion(ADC_EXT); -#endif -#endif - - //TODO: replace with IRQ trigger (both) +static void stm32_hal_adc_wait_completion() +{ + //TODO: + // - replace with IRQ trigger (both) + // - move RTC batt reading somewhere else + #if defined(ADC_EXT) && defined(ADC_EXT_DMA_Stream) // Wait for all ADCs to complete for (unsigned int i=0; i<10000; i++) { @@ -350,6 +342,7 @@ void adcSingleRead() break; } } + //TODO: move into completion IRQ trigger adc_disable_dma(ADC_DMA_Stream); adc_disable_dma(ADC_EXT_DMA_Stream); #else @@ -359,9 +352,10 @@ void adcSingleRead() break; } } + //TODO: move into completion IRQ trigger adc_disable_dma(ADC_DMA_Stream); -#if defined(ADC_EXT) +#if defined(ADC_EXT) && !defined(ADC_EXT_DMA_Stream) if (isVBatBridgeEnabled()) { rtcBatteryVoltage = ADC_EXT->DR; } @@ -369,61 +363,8 @@ void adcSingleRead() #endif } -void adcRead() -{ - uint16_t temp[NUM_ANALOGS] = { 0 }; - - for (int i=0; i<4; i++) { - adcSingleRead(); - for (uint8_t x=FIRST_ANALOG_ADC; x> 2; - } - -#if NUM_PWMSTICKS > 0 - if (STICKS_PWM_ENABLED()) { - sticksPwmRead(adcValues); - } -#endif -} - -#if defined(PCBX10) -uint16_t getRTCBatteryVoltage() -{ - return (rtcBatteryVoltage * 2 * ADC_VREF_PREC2) / 2048; -} -#else -uint16_t getRTCBatteryVoltage() -{ - return (getAnalogValue(TX_RTC_VOLTAGE) * ADC_VREF_PREC2) / 2048; -} -#endif - -#if !defined(SIMU) -uint16_t getAnalogValue(uint8_t index) -{ - if (IS_POT(index) && !IS_POT_SLIDER_AVAILABLE(index)) { - // Use fixed analog value for non-existing and/or non-connected pots. - // Non-connected analog inputs will slightly follow the adjacent connected analog inputs, - // which produces ghost readings on these inputs. - return 0; - } -#if defined(PCBX9E) - index = adcMapping[index]; -#endif - if (adcDirection[index] < 0) - return 4095 - adcValues[index]; - else - return adcValues[index]; -} -#endif // #if !defined(SIMU) +const etx_hal_adc_driver_t stm32_hal_adc_driver = { + stm32_hal_adc_init, + stm32_hal_adc_start_read, + stm32_hal_adc_wait_completion +}; diff --git a/radio/src/targets/common/arm/stm32/stm32_hal_adc.h b/radio/src/targets/common/arm/stm32/stm32_hal_adc.h new file mode 100644 index 000000000..3df85ae66 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/stm32_hal_adc.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) EdgeTx + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#pragma once + +struct stm32_hal_adc_channel { + const uint8_t adc_channel; + const uint8_t rank; + const uint8_t sample_time; +}; + +typedef const stm32_hal_adc_channel* (*stm32_hal_adc_get_channels)(); +typedef uint8_t (*stm32_hal_adc_get_nconv)(); +typedef uint16_t* (*stm32_hal_adc_get_dma_buffer)(); + +struct stm32_hal_adc { + ADC_TypeDef* adc; + + DMA_Stream_TypeDef* dma_stream; + const stm32_hal_adc_get_dma_buffer get_dma_buffer; + + const stm32_hal_adc_get_nconv get_nconv; + const stm32_hal_adc_get_channels get_channels; +}; + +// Driver to be passed to adcInit() +extern const etx_hal_adc_driver_t stm32_hal_adc_driver; diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 70e1a2f82..1ff3ea877 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -58,7 +58,8 @@ if (PCB STREQUAL X10) ) set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} - ../common/arm/stm32/adc_driver.cpp + ../common/arm/stm32/stm32_hal_adc.cpp + ../../hal/adc_driver.cpp ) set(BITMAPS_TARGET x10_bitmaps) set(FONTS_TARGET x10_fonts) diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index f24f8f1bf..b192cdda8 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -20,6 +20,9 @@ #include "opentx.h" +#include "hal/adc_driver.h" +#include "../common/arm/stm32/stm32_hal_adc.h" + #if defined(__cplusplus) extern "C" { #endif @@ -197,7 +200,7 @@ void boardInit() } #endif - adcInit(); + adcInit(&stm32_hal_adc_driver); lcdInit(); backlightInit(); diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index e671993ed..64e6a45db 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -470,7 +470,8 @@ set(TARGET_SRC set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} - ../common/arm/stm32/adc_driver.cpp + ../common/arm/stm32/stm32_hal_adc.cpp + ../../hal/adc_driver.cpp ../common/arm/stm32/heartbeat_driver.cpp ../common/arm/stm32/mixer_scheduler_driver.cpp ) diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index 03b6c4c84..c85907b2e 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -20,6 +20,9 @@ #include "opentx.h" +#include "hal/adc_driver.h" +#include "stm32_hal_adc.h" + #if defined(__cplusplus) extern "C" { #endif @@ -159,7 +162,7 @@ void boardInit() } #endif - adcInit(); + adcInit(&stm32_hal_adc_driver); lcdInit(); // delaysInit() must be called before audioInit(); init2MhzTimer();