Merge pull request #496 from EdgeTX/unify-adc-driver

Unify / clean-up ADC driver
This commit is contained in:
Raphael Coeffic
2021-08-03 15:48:06 +02:00
committed by GitHub
31 changed files with 851 additions and 706 deletions
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
#include "hal/adc_driver.h"
#define XPOT_DELTA 10
#define XPOT_DELAY 10 /* cycles */
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
#include "hal/adc_driver.h"
#define XPOT_DELTA 10
#define XPOT_DELAY 10 /* cycles */
@@ -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 */
@@ -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)
@@ -48,6 +48,7 @@ void ViewMainDecoration::setSlidersVisible(bool visible)
sliders[SLIDERS_POT3]->setHeight(visible ? TRIM_SQUARE_SIZE : 0);
#endif
#if NUM_SLIDERS > 0
//
// Vertical sliders
//
@@ -65,6 +66,8 @@ void ViewMainDecoration::setSlidersVisible(bool visible)
if (IS_POT_SLIDER_AVAILABLE(EXT2)) {
sliders[SLIDERS_EXT2]->setWidth(visible ? TRIM_SQUARE_SIZE : 0);
}
#endif
#endif
if (visible) {
@@ -135,13 +138,14 @@ void ViewMainDecoration::adjustDecoration()
// Vertical trims/slider are on top of horizontal sliders with a small margin
auto vertTop = pos - HMARGIN - VERTICAL_SLIDERS_HEIGHT;
#if NUM_SLIDERS > 0
// Left side (vertical)
pos = left();
sliders[SLIDERS_REAR_LEFT]->setLeft(pos);
sliders[SLIDERS_REAR_LEFT]->setTop(vertTop);
#if defined(HARDWARE_EXT1) || defined(PCBX12S)
#if defined(HARDWARE_EXT1) || defined(PCBX12S) // TODO: define HARDWARE_EXT1 for X12S
sliders[SLIDERS_EXT1]->setLeft(pos);
if (IS_POT_SLIDER_AVAILABLE(EXT1)) {
auto rl = sliders[SLIDERS_REAR_LEFT];
@@ -195,7 +199,14 @@ void ViewMainDecoration::adjustDecoration()
trims[TRIMS_LV]->setTop(vertTop);
trims[TRIMS_RV]->setLeft(sliders[SLIDERS_REAR_RIGHT]->left() - trims[TRIMS_RV]->width());
trims[TRIMS_RV]->setTop(vertTop);
#else
// No sliders: place the vertical trims on the edge
trims[TRIMS_LV]->setLeft(left());
trims[TRIMS_LV]->setTop(vertTop);
trims[TRIMS_RV]->setLeft(right() - trims[TRIMS_RV]->width());
trims[TRIMS_RV]->setTop(vertTop);
#endif
// Place the flight-mode text box
// -> between horiz trims (if existing)
// else on top of horiz sliders
@@ -265,6 +276,7 @@ void ViewMainDecoration::createSliders()
sliders[SLIDERS_POT3] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT3);
#endif
#if NUM_SLIDERS > 0
r = rect_t { 0, 0, 0, 0 };
sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT);
sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT);
@@ -276,6 +288,7 @@ void ViewMainDecoration::createSliders()
#if defined(HARDWARE_EXT2) || defined(PCBX12S)
sliders[SLIDERS_EXT2] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT2);
#endif
#endif // NUM_SLIDERS > 0
}
void ViewMainDecoration::createTrims()
@@ -19,6 +19,7 @@
*/
#include <opentx.h>
#include "hal/adc_driver.h"
#if defined(PCBSKY9X)
#define HW_SETTINGS_COLUMN (2+(15*FW))
+186
View File
@@ -0,0 +1,186 @@
/*
* 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)
const int8_t adcDirection[NUM_ANALOGS] = {
#if defined(HORUS_STICKS)
1,-1,1,-1,
#else
1,1,-1,-1,
#endif // HORUS_STICKS
// other analogs are the same
-1,-1,-1,1, -1,1,1,-1, -1,-1 };
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};
#elif defined(PCBNV14)
const uint8_t adcMapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/,
4 /*POT1*/, 5 /*POT2*/, 6 /*SWA*/, 14 /*SWB*/,
7 /*SWC*/, 15 /*SWD*/, 8 /*SWE*/, 9 /*SWF*/,
10/*SWG*/, 11/*SWH*/,
12 /*TX_VOLTAGE*/, 13 /* TX_VBAT */ };
const int8_t adcDirection[NUM_ANALOGS] = { 0 /*STICK1*/, 0 /*STICK2*/, 0 /*STICK3*/, 0 /*STICK4*/,
-1 /*POT1*/, 0 /*POT2*/, 0 /*SWA*/, 0 /*SWC*/,
0 /*SWE*/, -1 /*SWF*/, 0 /*SWG*/, -1 /*SWH*/,
0 /*TX_VOLTAGE*/, 0 /*TX_VBAT*/,
0 /*SWB*/, 0 /*SWD*/};
#elif defined(PCBX12S)
const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1, 0,0,0};
#else
#error "ADC driver does not suppport this target"
#endif
uint16_t adcValues[NUM_ANALOGS] __DMA;
#if defined(PCBX10) || defined(PCBX12S)
uint16_t rtcBatteryVoltage;
#endif
bool adcInit(const etx_hal_adc_driver_t* driver)
{
etx_hal_adc_driver = driver;
if (!etx_hal_adc_driver)
return false;
// If there is an init function
// it should succeed
if (etx_hal_adc_driver->init &&
!etx_hal_adc_driver->init()) {
return false;
}
return true;
}
static bool adcSingleRead()
{
if (!etx_hal_adc_driver)
return false;
if (etx_hal_adc_driver->start_conversion &&
!etx_hal_adc_driver->start_conversion())
return false;
if (etx_hal_adc_driver->wait_completion)
etx_hal_adc_driver->wait_completion();
return true;
}
// Declare adcRead() weak so it can be re-declared
#pragma weak adcRead
bool adcRead()
{
uint16_t temp[NUM_ANALOGS] = { 0 };
for (int i=0; i<4; i++) {
if (!adcSingleRead())
return false;
for (uint8_t x=FIRST_ANALOG_ADC; x<NUM_ANALOGS; x++) {
uint16_t val = adcValues[x];
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE()) {
rawJitter[x].measure(val);
}
#endif
temp[x] += val;
}
}
for (uint8_t x=FIRST_ANALOG_ADC; x<NUM_ANALOGS; x++) {
adcValues[x] = temp[x] >> 2;
}
#if NUM_PWMSTICKS > 0
if (STICKS_PWM_ENABLED()) {
sticksPwmRead(adcValues);
}
#endif
return true;
}
#if !defined(SIMU)
uint16_t getRTCBatteryVoltage()
{
#if defined(HAS_TX_RTC_VOLTAGE)
return (getAnalogValue(TX_RTC_VOLTAGE) * ADC_VREF_PREC2) / 2048;
#elif defined(PCBX10) || defined(PCBX12S)
return (rtcBatteryVoltage * 2 * ADC_VREF_PREC2) / 2048;
#elif defined(PCBNV14)
#warning "TODO RTC voltage"
return 330;
#else
#warning "RTC battery not supported on this target"
return 0;
#endif
}
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) || defined(PCBNV14)
index = adcMapping[index];
#endif
if (adcDirection[index] < 0)
return 4095 - adcValues[index];
else
return adcValues[index];
}
#endif // #if !defined(SIMU)
+59
View File
@@ -0,0 +1,59 @@
/*
* 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
#include <stdint.h>
// TODO: move this to the targets
#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)
#elif defined(PCBNV14) && defined(FLYSKY_HALL_STICKS)
#define FIRST_ANALOG_ADC 4
#define NUM_ANALOGS_ADC 10
#define NUM_ANALOGS_ADC_EXT 2
#else
#define FIRST_ANALOG_ADC 0
#define NUM_ANALOGS_ADC NUM_ANALOGS
#endif
// TODO: get rid of this special case
#if defined(PCBX10) || defined(PCBX12S)
extern uint16_t rtcBatteryVoltage;
#endif
struct etx_hal_adc_driver_t {
bool (*init)();
bool (*start_conversion)();
void (*wait_completion)();
};
bool adcInit(const etx_hal_adc_driver_t* driver);
// void adcDeInit();
bool adcRead();
uint16_t getRTCBatteryVoltage();
uint16_t getAnalogValue(uint8_t index);
+1
View File
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
#include "hal/adc_driver.h"
#if defined(LIBOPENUI)
#include "libopenui.h"
+4 -2
View File
@@ -19,7 +19,8 @@
*/
#include "opentx.h"
#include <io/frsky_firmware_update.h>
#include "io/frsky_firmware_update.h"
#include "hal/adc_driver.h"
#if defined(LIBOPENUI)
#include "libopenui.h"
@@ -1058,7 +1059,8 @@ void getADC()
#endif
DEBUG_TIMER_START(debugTimerAdcRead);
adcRead();
if (!adcRead())
TRACE("adcRead failed");
DEBUG_TIMER_STOP(debugTimerAdcRead);
for (uint8_t x=0; x<NUM_ANALOGS; x++) {
@@ -1,288 +0,0 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* 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 "opentx.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
void adcInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
#if defined(ADC_GPIOA_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOA_PINS;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOB_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOB_PINS;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOC_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOC_PINS;
GPIO_Init(GPIOC, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOF_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOF_PINS;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
ADC_MAIN->CR1 = ADC_CR1_SCAN;
ADC_MAIN->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_MAIN->SQR1 = (NUM_ANALOGS_ADC - 1) << 20; // bits 23:20 = number of conversions
#if defined(PCBX10)
if (STICKS_PWM_ENABLED()) {
ADC_MAIN->SQR2 = (ADC_CHANNEL_SLIDER2 << 0) + (ADC_CHANNEL_BATT << 5);
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1 << 0) + (ADC_CHANNEL_POT2 << 5) + (ADC_CHANNEL_POT3 << 10) + (ADC_CHANNEL_EXT1 << 15) + (ADC_CHANNEL_EXT2 << 20) + (ADC_CHANNEL_SLIDER1 << 25);
}
else {
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3 << 0) + (ADC_CHANNEL_EXT1 << 5) + (ADC_CHANNEL_EXT2 << 10) + (ADC_CHANNEL_SLIDER1 << 15) + (ADC_CHANNEL_SLIDER2 << 20) + (ADC_CHANNEL_BATT << 25);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT1 << 20) + (ADC_CHANNEL_POT2 << 25);
}
#elif defined(PCBX9E)
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT4 << 0) + (ADC_CHANNEL_SLIDER3 << 5) + (ADC_CHANNEL_SLIDER4 << 10) + (ADC_CHANNEL_BATT << 15) + (ADC_Channel_Vbat << 20);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT2 << 20) + (ADC_CHANNEL_POT3 << 25);
#elif defined(PCBXLITE)
if (STICKS_PWM_ENABLED()) {
ADC_MAIN->SQR2 = 0;
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1 << 0) + (ADC_CHANNEL_POT2 << 5) + (ADC_CHANNEL_BATT << 10) + (ADC_Channel_Vbat << 15);
}
else {
ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT << 0) + (ADC_Channel_Vbat << 5);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT1 << 20) + (ADC_CHANNEL_POT2 << 25);
}
#elif defined(RADIO_T8) || defined(RADIO_TLITE)
ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT << 0) + (ADC_Channel_Vbat << 5);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15);
#elif defined(PCBX7)
ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT << 0) + (ADC_Channel_Vbat << 5);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT1 << 20) + (ADC_CHANNEL_POT2 << 25);
#elif defined(PCBX9LITE)
ADC_MAIN->SQR2 = (ADC_Channel_Vbat << 0);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT1 << 20) + (ADC_CHANNEL_BATT << 25);
#elif defined(PCBX9D) || defined(PCBX9DP)
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3 << 0) + (ADC_CHANNEL_SLIDER1 << 5) + (ADC_CHANNEL_SLIDER2 << 10) + (ADC_CHANNEL_BATT << 15) + (ADC_Channel_Vbat << 20);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT1 << 20) + (ADC_CHANNEL_POT2 << 25);
#endif
ADC_MAIN->SMPR1 = ADC_MAIN_SMPR1;
ADC_MAIN->SMPR2 = ADC_MAIN_SMPR2;
ADC->CCR = ADC_CCR_VBATE; // Enable vbat sensor
ADC_DMA_Stream->CR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
ADC_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_MAIN->DR);
ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[FIRST_ANALOG_ADC]);
ADC_DMA_Stream->NDTR = NUM_ANALOGS_ADC;
ADC_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#if defined(PCBX10)
ADC1->CR1 = ADC_CR1_SCAN;
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC1->SQR1 = (1 - 1) << 20;
ADC1->SQR2 = 0;
ADC1->SQR3 = (ADC_Channel_Vbat << 0);
ADC1->SMPR1 = (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24);
ADC1->SMPR2 = (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
#endif
#if defined(PCBX9E)
ADC_EXT->CR1 = ADC_CR1_SCAN;
ADC_EXT->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_EXT->SQR1 = (NUM_ANALOGS_ADC_EXT - 1) << 20;
ADC_EXT->SQR2 = 0;
ADC_EXT->SQR3 = (ADC_CHANNEL_POT1 << 0) + (ADC_CHANNEL_SLIDER1 << 5) + (ADC_CHANNEL_SLIDER2 << 10); // conversions 1 to 3
ADC_EXT->SMPR1 = (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24);
ADC_EXT->SMPR2 = (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
ADC_EXT_DMA_Stream->CR = DMA_SxCR_PL | DMA_SxCR_CHSEL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
ADC_EXT_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_EXT->DR);
ADC_EXT_DMA_Stream->M0AR = CONVERT_PTR_UINT(adcValues + NUM_ANALOGS_ADC);
ADC_EXT_DMA_Stream->NDTR = NUM_ANALOGS_ADC_EXT;
ADC_EXT_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#endif
#if NUM_PWMSTICKS > 0
if (STICKS_PWM_ENABLED()) {
sticksPwmInit();
}
#endif
}
void adcSingleRead()
{
ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_MAIN->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADC_SET_DMA_FLAGS();
ADC_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
ADC_MAIN->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#if defined(PCBX10)
ADC1->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADC1->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#endif
#if defined(PCBX9E)
ADC_EXT_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_EXT->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADC_EXT_SET_DMA_FLAGS();
ADC_EXT_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
ADC_EXT->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#endif
#if defined(PCBX9E)
for (unsigned int i=0; i<10000; i++) {
if (ADC_TRANSFER_COMPLETE() && ADC_EXT_TRANSFER_COMPLETE()) {
break;
}
}
ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_EXT_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
#else
for (unsigned int i = 0; i < 10000; i++) {
if (ADC_TRANSFER_COMPLETE()) {
break;
}
}
ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
#endif
#if defined(PCBX10)
if (isVBatBridgeEnabled()) {
rtcBatteryVoltage = ADC1->DR;
}
#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<NUM_ANALOGS; x++) {
uint16_t val = adcValues[x];
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE()) {
rawJitter[x].measure(val);
}
#endif
temp[x] += val;
}
}
for (uint8_t x=FIRST_ANALOG_ADC; x<NUM_ANALOGS; x++) {
adcValues[x] = temp[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)
@@ -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)
@@ -24,6 +24,7 @@ set(STM32LIB_SRC
STM32F2xx_StdPeriph_Driver/src/stm32f2xx_rtc.c
STM32F2xx_StdPeriph_Driver/src/stm32f2xx_pwr.c
STM32F2xx_StdPeriph_Driver/src/stm32f2xx_usart.c
STM32F2xx_StdPeriph_Driver/src/stm32f2xx_adc.c
)
#
@@ -23,6 +23,7 @@ set(STM32LIB_SRC
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rtc.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_pwr.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_adc.c
)
#
@@ -0,0 +1,421 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* 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 "opentx.h"
#include "hal/adc_driver.h"
#include "stm32_hal_adc.h"
static bool adc_disable_dma(DMA_Stream_TypeDef * dma_stream);
static void adc_dma_clear_flags(DMA_Stream_TypeDef * dma_stream);
static void adc_init_pins()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
#if defined(ADC_GPIOA_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOA_PINS;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOB_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOB_PINS;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOC_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOC_PINS;
GPIO_Init(GPIOC, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOF_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOF_PINS;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
}
static void adc_setup_scan_mode(ADC_TypeDef* ADCx, uint8_t nconv)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // Sets ADC_CR1_SCAN
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // Clears ADC_CR2_CONT
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; // Software trigger
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = nconv; // Channel count
ADC_Init(ADCx, &ADC_InitStructure);
// enable ADC_MAIN
ADC_Cmd(ADCx, ENABLE); // ADC_CR2_ADON
// enable DMA for ADC
ADC_DMACmd(ADCx, ENABLE); // ADC_CR2_DMA
ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE); // ADC_CR2_DDS
}
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},
{ADC_CHANNEL_STICK_RH, ADC_SAMPTIME},
#if defined(PCBX10)
{ ADC_CHANNEL_POT1, ADC_SAMPTIME },
{ ADC_CHANNEL_POT2, ADC_SAMPTIME },
{ ADC_CHANNEL_POT3, ADC_SAMPTIME },
{ ADC_CHANNEL_EXT1, ADC_SAMPTIME },
{ ADC_CHANNEL_EXT2, ADC_SAMPTIME },
{ ADC_CHANNEL_SLIDER1, ADC_SAMPTIME },
{ ADC_CHANNEL_SLIDER2, ADC_SAMPTIME },
{ ADC_CHANNEL_BATT, ADC_SAMPTIME }
#else
#if defined(RADIO_T8) || defined(RADIO_TLITE)
// fake channels to fill unsused POT1/POT2
{0, 0},
{0, 0},
#elif defined(PCBX7) || defined(PCBXLITE)
{ADC_CHANNEL_POT1, ADC_SAMPTIME},
{ADC_CHANNEL_POT2, ADC_SAMPTIME},
#elif defined(PCBX9LITE)
{ADC_CHANNEL_POT1, ADC_SAMPTIME},
#elif defined(PCBX9E)
{ADC_CHANNEL_POT2, ADC_SAMPTIME},
{ADC_CHANNEL_POT3, ADC_SAMPTIME},
{ADC_CHANNEL_POT4, ADC_SAMPTIME},
{ADC_CHANNEL_SLIDER3, ADC_SAMPTIME},
{ADC_CHANNEL_SLIDER4, ADC_SAMPTIME},
#elif defined(PCBX9D) || defined(PCBX9DP)
{ADC_CHANNEL_POT1, ADC_SAMPTIME},
{ADC_CHANNEL_POT2, ADC_SAMPTIME},
{ADC_CHANNEL_POT3, ADC_SAMPTIME},
{ADC_CHANNEL_SLIDER1, ADC_SAMPTIME},
{ADC_CHANNEL_SLIDER2, ADC_SAMPTIME},
#elif defined(PCBNV14)
{ADC_CHANNEL_POT1, ADC_SAMPTIME},
{ADC_CHANNEL_POT2, ADC_SAMPTIME},
{ADC_CHANNEL_SWA, ADC_SAMPTIME},
{ADC_CHANNEL_SWC, ADC_SAMPTIME},
{ADC_CHANNEL_SWE, ADC_SAMPTIME},
{ADC_CHANNEL_SWF, ADC_SAMPTIME},
{ADC_CHANNEL_SWG, ADC_SAMPTIME},
{ADC_CHANNEL_SWH, ADC_SAMPTIME},
#endif
{ADC_CHANNEL_BATT, ADC_SAMPTIME},
{ADC_Channel_Vbat, ADC_SAMPTIME}
#endif
};
static const stm32_hal_adc_channel* ADC_MAIN_get_channels()
{
#if (NUM_PWMSTICKS > 0)
if (STICKS_PWM_ENABLED())
return ADC_MAIN_channels + 4;
#endif
return ADC_MAIN_channels + FIRST_ANALOG_ADC;
}
static uint8_t ADC_MAIN_get_nconv()
{
return NUM_ANALOGS_ADC; // based on STICKS_PWM_ENABLED()
}
#if defined(ADC_EXT)
#if defined(PCBX9E)
static const stm32_hal_adc_channel ADC_EXT_channels[] = {
{ADC_CHANNEL_POT1, ADC_SAMPTIME},
{ADC_CHANNEL_SLIDER1, ADC_SAMPTIME},
{ADC_CHANNEL_SLIDER2, ADC_SAMPTIME}
};
static uint8_t ADC_EXT_get_nconv() { return NUM_ANALOGS_ADC_EXT; }
#elif defined(PCBX10)
static const stm32_hal_adc_channel ADC_EXT_channels[] = {
{ ADC_Channel_Vbat, ADC_SAMPTIME }
};
static uint8_t ADC_EXT_get_nconv() { return 1; }
#elif defined(PCBNV14)
static const stm32_hal_adc_channel ADC_EXT_channels[] = {
{ADC_CHANNEL_SWB, ADC_SAMPTIME},
{ADC_CHANNEL_SWD, ADC_SAMPTIME},
};
static uint8_t ADC_EXT_get_nconv() { return NUM_ANALOGS_ADC_EXT; }
#endif
static const stm32_hal_adc_channel* ADC_EXT_get_channels()
{
return ADC_EXT_channels;
}
#endif
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 + FIRST_ANALOG_ADC;
}
#endif
stm32_hal_adc ADC_hal_def[] = {
{
ADC_MAIN,
ADC_DMA_Stream, ADC_DMA_Channel, ADC_MAIN_get_dma_buffer,
ADC_MAIN_get_nconv, ADC_MAIN_get_channels
},
#if defined(ADC_EXT)
{
ADC_EXT,
#if defined(ADC_EXT_DMA_Stream)
ADC_EXT_DMA_Stream, ADC_EXT_DMA_Channel, ADC_EXT_get_dma_buffer,
#else
nullptr, 0, nullptr,
#endif
ADC_EXT_get_nconv, ADC_EXT_get_channels
},
#endif
// required to detect end of ADC definitions
{ nullptr, nullptr, 0, nullptr, nullptr, nullptr },
};
static void adc_init_channels(ADC_TypeDef* adc, const stm32_hal_adc_channel* chan,
uint8_t nconv)
{
if (!chan || !nconv) return;
uint8_t rank = 1;
while (nconv > 0) {
ADC_RegularChannelConfig(adc, chan->adc_channel, rank, chan->sample_time);
nconv--; rank++; chan++;
}
}
static bool adc_init_dma_stream(ADC_TypeDef* adc, DMA_Stream_TypeDef * dma_stream,
uint32_t dma_channel, uint16_t* dest, uint8_t nconv)
{
// Disable DMA before continuing (see ref. manual "Stream configuration procedure")
if (!adc_disable_dma(dma_stream))
return false;
// Clear Interrupt flags
adc_dma_clear_flags(dma_stream);
// setup DMA request
dma_stream->PAR = CONVERT_PTR_UINT(&adc->DR);
dma_stream->M0AR = CONVERT_PTR_UINT(dest);
dma_stream->NDTR = nconv;
// Very high priority, 1 byte transfers, increment memory
dma_stream->CR = DMA_SxCR_PL | dma_channel | DMA_SxCR_MSIZE_0 |
DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
// disable direct mode, half full FIFO
dma_stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
return true;
}
static bool stm32_hal_adc_init()
{
adc_init_pins();
// Init common to all ADCs
ADC_CommonInitTypeDef ADC_CommonInitStruct;
ADC_CommonStructInit(&ADC_CommonInitStruct);
ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInit(&ADC_CommonInitStruct);
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
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();
if (!adc_init_dma_stream(adc_def->adc, adc_def->dma_stream,
adc_def->dma_channel, dma_buffer, nconv))
return false;
}
}
}
// move to next ADC definition
adc_def++;
}
//TODO: move VBat & PWM sticks somewhere else.
// Enable vbat sensor
ADC_VBATCmd(ENABLE);
#if NUM_PWMSTICKS > 0
if (STICKS_PWM_ENABLED()) {
sticksPwmInit();
}
#endif
return true;
}
#define DMA_Stream0_IT_MASK (uint32_t)(DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 | \
DMA_LISR_TEIF0 | DMA_LISR_HTIF0 | \
DMA_LISR_TCIF0)
#define DMA_Stream4_IT_MASK (uint32_t)(DMA_HISR_FEIF4 | DMA_HISR_DMEIF4 | \
DMA_HISR_TEIF4 | DMA_HISR_HTIF4 | \
DMA_HISR_TCIF4)
static void adc_dma_clear_flags(DMA_Stream_TypeDef * dma_stream)
{
// no other choice, sorry for that...
if (dma_stream == DMA2_Stream4) {
/* Reset interrupt pending bits for DMA2 Stream4 */
DMA2->HIFCR = DMA_Stream4_IT_MASK;
} else if (dma_stream == DMA2_Stream0) {
/* Reset interrupt pending bits for DMA2 Stream0 */
DMA2->LIFCR = DMA_Stream0_IT_MASK;
}
}
static bool adc_start_dma_conversion(ADC_TypeDef* ADCx,
DMA_Stream_TypeDef * dma_stream)
{
// Disable DMA before continuing (see ref. manual "Stream configuration procedure")
if (!adc_disable_dma(dma_stream))
return false;
// Clear Interrupt flags
adc_dma_clear_flags(dma_stream);
// Clear ADC status register
ADCx->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
// Enable DMA
dma_stream->CR |= DMA_SxCR_EN;
// Trigger ADC start
ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
return true;
}
static bool adc_disable_dma(DMA_Stream_TypeDef* dma_stream)
{
dma_stream->CR &= ~(uint32_t)DMA_SxCR_EN;
// wait until DMA EN bit gets cleared by hardware
uint16_t uiTimeout = 1000;
while (dma_stream->CR & (uint32_t)DMA_SxCR_EN) {
if (--uiTimeout == 0) {
// Timeout. Failed to disable DMA
return false;
}
}
return true;
}
static void adc_start_single_conversion(ADC_TypeDef* ADCx)
{
ADCx->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
}
static bool stm32_hal_adc_start_read()
{
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) {
if (!adc_start_dma_conversion(adc_def->adc, adc_def->dma_stream))
return false;
} else if (nconv == 1) {
adc_start_single_conversion(adc_def->adc);
}
}
}
// move to next ADC definition
adc_def++;
}
return true;
}
static void stm32_hal_adc_wait_completion()
{
//TODO:
// - iterate through ADCs
// - 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++) {
if (DMA_GetFlagStatus(ADC_DMA_Stream, ADC_DMA_TC_Flag) != RESET &&
DMA_GetFlagStatus(ADC_EXT_DMA_Stream, ADC_EXT_DMA_TC_Flag) != RESET) {
break;
}
}
//TODO: move into completion IRQ trigger
adc_disable_dma(ADC_DMA_Stream);
adc_disable_dma(ADC_EXT_DMA_Stream);
#else
// Wait only for the main ADC, and hope others are done as well
for (unsigned int i = 0; i < 10000; i++) {
if (DMA_GetFlagStatus(ADC_DMA_Stream, ADC_DMA_TC_Flag) != RESET) {
break;
}
}
//TODO: move into completion IRQ trigger
adc_disable_dma(ADC_DMA_Stream);
#if defined(ADC_EXT) && !defined(ADC_EXT_DMA_Stream)
if (isVBatBridgeEnabled()) {
rtcBatteryVoltage = ADC_EXT->DR;
}
#endif
#endif
}
const etx_hal_adc_driver_t stm32_hal_adc_driver = {
stm32_hal_adc_init,
stm32_hal_adc_start_read,
stm32_hal_adc_wait_completion
};
@@ -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 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;
uint32_t dma_channel;
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;
+3 -1
View File
@@ -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)
@@ -137,6 +138,7 @@ elseif (PCB STREQUAL X12S)
)
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
../../hal/adc_driver.cpp
x12s_adc_driver.cpp
)
set(BITMAPS_TARGET x12s_bitmaps)
+13 -1
View File
@@ -20,6 +20,16 @@
#include "opentx.h"
#include "hal/adc_driver.h"
#if !defined(PCBX12S)
#include "../common/arm/stm32/stm32_hal_adc.h"
#define ADC_DRIVER stm32_hal_adc_driver
#else
#include "x12s_adc_driver.h"
#define ADC_DRIVER x12s_adc_driver
#endif
#if defined(__cplusplus)
extern "C" {
#endif
@@ -197,7 +207,9 @@ void boardInit()
}
#endif
adcInit();
if (!adcInit(&ADC_DRIVER))
TRACE("adcInit failed");
lcdInit();
backlightInit();
+4 -5
View File
@@ -318,12 +318,14 @@
#define ADC_CHANNEL_EXT1 ADC_Channel_6 // ADC3_IN6
#define ADC_CHANNEL_EXT2 ADC_Channel_7 // ADC3_IN7
#define ADC_MAIN ADC3
#define ADC_EXT ADC1
#define ADC_SAMPTIME 3
#define ADC_DMA DMA2
#define ADC_DMA_SxCR_CHSEL DMA_SxCR_CHSEL_1
#define ADC_DMA_Channel DMA_Channel_2
#define ADC_DMA_Stream DMA2_Stream0
#define ADC_SET_DMA_FLAGS() ADC_DMA->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0)
#define ADC_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0)
#define ADC_DMA_TC_Flag DMA_FLAG_TCIF0
#if defined(RADIO_TX16S)
#define ADC_VREF_PREC2 330
#elif defined(RADIO_T16) || defined(RADIO_T18)
@@ -333,9 +335,6 @@
#endif
#endif
#define ADC_MAIN_SMPR1 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24);
#define ADC_MAIN_SMPR2 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
// Power
#if defined(RADIO_T18)
#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOB
+17 -18
View File
@@ -19,9 +19,8 @@
*/
#include "opentx.h"
#include "x12s_adc_driver.h"
uint16_t adcValues[NUM_ANALOGS] __DMA;
uint16_t rtcBatteryVoltage;
#define ADC_CS_HIGH() (ADC_SPI_GPIO->BSRRL = ADC_SPI_PIN_CS)
#define ADC_CS_LOW() (ADC_SPI_GPIO->BSRRH = ADC_SPI_PIN_CS)
@@ -100,7 +99,7 @@ static void ADS7952_Init()
ADC_CS_HIGH();
}
void adcInit()
static bool x12s_adc_init()
{
ADS7952_Init();
@@ -137,11 +136,8 @@ void adcInit()
ADC1->SQR3 = (ADC_Channel_Vbat << 0);
ADC1->SMPR1 = (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24);
ADC1->SMPR2 = (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
}
uint16_t getRTCBatteryVoltage()
{
return (rtcBatteryVoltage * 2 * ADC_VREF_PREC2) / 2048;
return true;
}
const uint16_t adcCommands[MOUSE1+2] =
@@ -227,7 +223,9 @@ bool adcOnChipReadFinished()
return (ADC_DMA->LISR & DMA_LISR_TCIF0);
}
void adcRead()
// Re-declare adcRead()
// (takes precedence over hal/adc_driver.cpp)
bool adcRead()
{
uint16_t temp[NUM_ANALOGS-MOUSE1] = { 0 };
uint8_t noInternalReads = 0;
@@ -266,16 +264,17 @@ void adcRead()
if (isVBatBridgeEnabled()) {
rtcBatteryVoltage = ADC1->DR;
}
return true;
}
#if !defined(SIMU)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1, 0,0,0};
//TODO: implement these based on stm32_hal_adc.cpp
//static bool x12s_adc_init();
//static bool x12s_adc_start_read();
//static void x12s_adc_wait_completion();
uint16_t getAnalogValue(uint8_t index)
{
if (ana_direction[index] < 0)
return 4095 - adcValues[index];
else
return adcValues[index];
}
#endif // #if !defined(SIMU)
const etx_hal_adc_driver_t x12s_adc_driver = {
x12s_adc_init,
nullptr,//x12s_adc_start_read,
nullptr,//x12s_adc_wait_completion
};
+26
View File
@@ -0,0 +1,26 @@
/*
* 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
#include "hal/adc_driver.h"
extern const etx_hal_adc_driver_t x12s_adc_driver;
+2 -7
View File
@@ -48,21 +48,16 @@ add_definitions(-DINTERNAL_MODULE_AFHDS2A)
set(TARGET_SRC
${TARGET_SRC}
audio_spi_driver.cpp
adc_driver.cpp
# ../common/arm/stm32/adc_driver.cpp
../common/arm/stm32/mixer_scheduler_driver.cpp
../common/arm/stm32/timers_driver.cpp
)
#set(FIRMWARE_TARGET_SRC
# ${FIRMWARE_TARGET_SRC}
# x12s_adc_driver.cpp
# )
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
battery_driver.cpp
../horus/flyskyHallStick_driver.cpp
../common/arm/stm32/stm32_hal_adc.cpp
../../hal/adc_driver.cpp
)
set(BITMAPS_TARGET nv14_bitmaps)
-325
View File
@@ -1,325 +0,0 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* 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 "opentx.h"
#if defined(SIMU)
// not needed
#elif defined(PCBNV14)
const int8_t ana_direction[NUM_ANALOGS] = { 0 /*STICK1*/, 0 /*STICK2*/, 0 /*STICK3*/, 0 /*STICK4*/,
0 /*POT1*/, 0 /*POT2*/, 0 /*SWA*/, 0 /*SWB*/,
0 /*SWC*/, -1 /*SWD*/, 0 /*SWE*/, -1 /*SWF*/,
0 /*SWH*/, 0 /*SWG*/,
0 /*TX_VOLTAGE*/ };
const uint8_t anas_mapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/,
4 /*POT1*/, 5 /*POT2*/, 6 /*SWA*/, 13 /*SWB*/,
7 /*SWC*/, 14 /*SWD*/, 8 /*SWE*/, 9 /*SWF*/,
11/*SWH*/, 10/*SWG*/,
12 /*TX_VOLTAGE*/ };
#define ANAS_MAPPING anas_mapping // TODO => hal.h
#elif defined(PCBX10)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,-1, 1, 1,1};
#elif defined(PCBX9E)
#if defined(HORUS_STICKS)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,-1,-1, -1};
#else
const int8_t ana_direction[NUM_ANALOGS] = {1,1,-1,-1, -1,-1,-1,1, -1,1,-1,-1, -1};
#endif
const uint8_t anas_mapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/,
10 /*POT1*/, 4 /*POT2*/, 5 /*POT3*/, 6 /*POT4*/,
11 /*SLIDER1*/, 12 /*SLIDER2*/, 7 /*SLIDER3*/, 8 /*SLIDER4*/,
9 /*TX_VOLTAGE*/ };
#define ANAS_MAPPING anas_mapping
#elif defined(PCBX9DP)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1};
#elif defined(PCBX7)
const int8_t ana_direction[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1};
#elif defined(PCBI8)
const int8_t ana_direction[NUM_ANALOGS] = {/*sticks*/1,1,1,1, /*pots*/1,1, /*switches*/1,1,1,1,1,1, /*batt*/1,1};
#elif defined(PCBXLITE)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,-1,1, -1,1, 1};
#elif defined(REV4a)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,-1,0, 1,1, 1};
#else
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,1,0, 1,1, 1};
#endif
#if NUM_PWMSTICKS > 0
#define FIRST_ANALOG_ADC (STICKS_PWM_ENABLED() ? NUM_PWMSTICKS : 0)
#define NUM_MAIN_ANALOGS_ADC (STICKS_PWM_ENABLED() ? (NUM_MAIN_ANALOGS - NUM_PWMSTICKS) : NUM_MAIN_ANALOGS)
#elif defined(PCBX9E)
#define FIRST_ANALOG_ADC 0
#define NUM_MAIN_ANALOGS_ADC 10
#define NUM_MAIN_ANALOGS_ADC_EXT (NUM_MAIN_ANALOGS - 10)
#elif defined(PCBNV14) && defined(FLYSKY_HALL_STICKS)
#define FIRST_ANALOG_ADC 4
#define NUM_MAIN_ANALOGS_ADC 9
#define NUM_SUB_ANALOGS_ADC 2
#else
#define FIRST_ANALOG_ADC 0
#define FIRST_SUB_ANALOG_ADC 0
#define NUM_MAIN_ANALOGS_ADC (SUB_ANALOG_POS)
#define NUM_SUB_ANALOGS_ADC (NUM_ANALOGS - SUB_ANALOG_POS)
#endif
#ifndef NUM_SUB_ANALOGS_ADC
#define NUM_SUB_ANALOGS_ADC 0
#endif
uint16_t adcValues[NUM_ANALOGS] __DMA;
void adcInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
#if defined(ADC_GPIOA_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOA_PINS;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOB_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOB_PINS;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOC_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOC_PINS;
GPIO_Init(GPIOC, &GPIO_InitStructure);
#endif
#if defined(ADC_GPIOF_PINS)
GPIO_InitStructure.GPIO_Pin = ADC_GPIOF_PINS;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
ADC_MAIN->CR1 = ADC_CR1_SCAN;
ADC_MAIN->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_MAIN->SQR1 = (NUM_MAIN_ANALOGS_ADC-1) << 20; // bits 23:20 = number of conversions
#if NUM_SUB_ANALOGS_ADC > 0
ADC_SUB->CR1 = ADC_CR1_SCAN;
ADC_SUB->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_SUB->SQR1 = (NUM_SUB_ANALOGS_ADC-1) << 20; // bits 23:20 = number of conversions
#endif
#if defined(PCBX10)
if (STICKS_PWM_ENABLED()) {
ADC_MAIN->SQR2 = (ADC_CHANNEL_EXT1<<0) + (ADC_CHANNEL_EXT2<<5); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_POT3<<10) + (ADC_CHANNEL_SLIDER1<<15) + (ADC_CHANNEL_SLIDER2<<20) + (ADC_CHANNEL_BATT<<25); // conversions 1 to 6
}
else {
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15) + (ADC_CHANNEL_EXT1<<20) + (ADC_CHANNEL_EXT2<<25); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
}
#elif defined(PCBX9E)
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT4<<0) + (ADC_CHANNEL_SLIDER3<<5) + (ADC_CHANNEL_SLIDER4<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT2<<20) + (ADC_CHANNEL_POT3<<25); // conversions 1 to 6
#elif defined(PCBXLITE)
if (STICKS_PWM_ENABLED()) {
ADC_MAIN->SQR2 = 0;
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_BATT<<10);
}
else {
ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
}
#elif defined(PCBX7)
// TODO why do we invert POT1 and POT2 here?
ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<25) + (ADC_CHANNEL_POT2<<20); // conversions 1 to 6
#elif defined(PCBI8)
ADC_MAIN->SQR2 = (ADC_CHANNEL_SWE<<0) + (ADC_CHANNEL_SWF<<5) + (ADC_CHANNEL_LIBATT<<10) + (ADC_CHANNEL_DRYBATT<<15); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_SWA<<10) + (ADC_CHANNEL_SWB<<15) + (ADC_CHANNEL_SWC<<20) + (ADC_CHANNEL_SWD<<25); // conversions 1 to 6
#elif defined(PCBNV14)
#if !defined(FLYSKY_HALL_STICKS)
ADC_MAIN->SQR1 |= (ADC_CHANNEL_BATT <<0 );
ADC_MAIN->SQR2 = (ADC_CHANNEL_SWA << 0) + (ADC_CHANNEL_SWC << 5) + (ADC_CHANNEL_SWE << 10) + (ADC_CHANNEL_SWF << 15) + (ADC_CHANNEL_SWG << 20) + (ADC_CHANNEL_SWH << 25); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
ADC_SUB->SQR3 = (ADC_CHANNEL_SWB<<0) + (ADC_CHANNEL_SWD<<5); // conversions 1 to 2
#else
ADC_MAIN->SQR2 = (ADC_CHANNEL_SWG << 0) + (ADC_CHANNEL_SWH << 5) + (ADC_CHANNEL_BATT << 10); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_SWA<<10) + (ADC_CHANNEL_SWC<<15) + (ADC_CHANNEL_SWE<<20) + (ADC_CHANNEL_SWF<<25); // conversions 1 to 6
ADC_SUB->SQR3 = (ADC_CHANNEL_SWB<<0) + (ADC_CHANNEL_SWD<<5); // conversions 1 to 2
#endif
#else
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
#endif
ADC_MAIN->SMPR1 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24);
ADC_MAIN->SMPR2 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24) + (ADC_SAMPTIME<<27);
ADC->CCR = 0;
ADC_MAIN_DMA_Stream->CR = DMA_SxCR_PL | ADC_MAIN_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
ADC_MAIN_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_MAIN->DR);
ADC_MAIN_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[FIRST_ANALOG_ADC]);
ADC_MAIN_DMA_Stream->NDTR = NUM_MAIN_ANALOGS_ADC;
ADC_MAIN_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#if NUM_SUB_ANALOGS_ADC > 0
ADC_SUB->SMPR1 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24);
ADC_SUB->SMPR2 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24) + (ADC_SAMPTIME<<27);
ADC->CCR = 0;
ADC_SUB_DMA_Stream->CR = DMA_SxCR_PL | ADC_SUB_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
ADC_SUB_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_SUB->DR);
ADC_SUB_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[SUB_ANALOG_POS]);
ADC_SUB_DMA_Stream->NDTR = NUM_SUB_ANALOGS_ADC;
ADC_SUB_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#endif
#if defined(PCBX9E)
ADC_EXT->CR1 = ADC_CR1_SCAN;
ADC_EXT->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_EXT->SQR1 = (NUM_MAIN_ANALOGS_ADC_EXT-1) << 20;
ADC_EXT->SQR2 = 0;
ADC_EXT->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10); // conversions 1 to 3
ADC_EXT->SMPR1 = 0;
ADC_EXT->SMPR2 = (ADC_EXT_SAMPTIME<<(3*ADC_CHANNEL_POT1)) + (ADC_EXT_SAMPTIME<<(3*ADC_CHANNEL_SLIDER1)) + (ADC_EXT_SAMPTIME<<(3*ADC_CHANNEL_SLIDER2));
ADC_EXT_DMA_Stream->CR = DMA_SxCR_PL | DMA_SxCR_CHSEL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
ADC_EXT_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_EXT->DR);
ADC_EXT_DMA_Stream->M0AR = CONVERT_PTR_UINT(adcValues + NUM_MAIN_ANALOGS_ADC);
ADC_EXT_DMA_Stream->NDTR = NUM_MAIN_ANALOGS_ADC_EXT;
ADC_EXT_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#endif
#if NUM_PWMSTICKS > 0
if (STICKS_PWM_ENABLED()) {
sticksPwmInit();
}
#endif
//Avoid reading wrong values when the adcRead not be called.
adcRead();
}
void adcSingleRead()
{
ADC_MAIN_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_MAIN->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADC_MAIN_SET_DMA_FLAGS();
ADC_MAIN_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
ADC_MAIN->CR2 |= (uint32_t) ADC_CR2_SWSTART;
#if NUM_SUB_ANALOGS_ADC > 0
ADC_SUB_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_SUB->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADC_SUB_SET_DMA_FLAGS();
ADC_SUB_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
ADC_SUB->CR2 |= (uint32_t) ADC_CR2_SWSTART;
#endif
#if defined(PCBX9E)
ADC_EXT_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_EXT->SR &= ~(uint32_t) ( ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR );
ADC_EXT_SET_DMA_FLAGS();
ADC_EXT_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
ADC_EXT->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#endif
#if defined(PCBX9E)
for (unsigned int i=0; i<10000; i++) {
if (ADC_TRANSFER_COMPLETE() && ADC_EXT_TRANSFER_COMPLETE()) {
break;
}
}
ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_EXT_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
#else
for (unsigned int i = 0; i < 10000; i++) {
#if defined(PCBNV14)
if (ADC_MAIN_TRANSFER_COMPLETE() && ADC_SUB_TRANSFER_COMPLETE())
{
break;
}
#else
if (ADC_MAIN_TRANSFER_COMPLETE())
{
break;
}
#endif
}
ADC_MAIN_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
#if defined(PCBNV14)
ADC_SUB_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
#endif
#endif
}
void adcRead()
{
int i, j;
uint16_t temp[NUM_ANALOGS] = { 0 };
for (i = 0; i < 4; i++)
{
adcSingleRead();
for (j = FIRST_ANALOG_ADC; j < NUM_ANALOGS; j++)
{
uint16_t val = adcValues[j];
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE()) {
rawJitter[j].measure(val);
}
#endif
temp[j] += val;
}
}
for (uint8_t x = FIRST_ANALOG_ADC; x < NUM_ANALOGS; x++)
{
adcValues[x] = temp[x] >> 2;
}
#if NUM_PWMSTICKS > 0
if (STICKS_PWM_ENABLED()) {
sticksPwmRead(adcValues);
}
#endif
}
#if !defined(SIMU)
uint16_t getRTCBatteryVoltage()
{
#warning "TODO RTC voltage"
return 330;
}
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(ANAS_MAPPING)
index = ANAS_MAPPING[index];
#endif
if (ana_direction[index] < 0)
return 4095 - adcValues[index];
else
return adcValues[index];
}
#endif // #if !defined(SIMU)
+5 -1
View File
@@ -20,6 +20,10 @@
#include "opentx.h"
#include "touch.h"
#include "hal/adc_driver.h"
#include "../common/arm/stm32/stm32_hal_adc.h"
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
#endif
@@ -171,7 +175,7 @@ void boardInit()
// and this section is un-initialized
memset(&g_FATFS_Obj, 0, sizeof(g_FATFS_Obj));
monitorInit();
adcInit();
adcInit(&stm32_hal_adc_driver);
backlightInit();
lcdInit();
usbInit();
+1 -6
View File
@@ -305,6 +305,7 @@ enum Analogs {
SUB_ANALOG_POS = SWH,
SWITCH_END = SWH,
TX_VOLTAGE,
TX_VBAT,
NUM_ANALOGS
};
@@ -317,8 +318,6 @@ enum CalibratedAnalogs {
CALIBRATED_STICK4,
CALIBRATED_POT1,
CALIBRATED_POT2,
CALIBRATED_SLIDER_REAR_LEFT,
CALIBRATED_SLIDER_REAR_RIGHT,
CALIBRATED_SWA,
CALIBRATED_SWB,
CALIBRATED_SWC,
@@ -335,10 +334,6 @@ enum CalibratedAnalogs {
extern uint16_t adcValues[NUM_ANALOGS];
void adcInit();
void adcRead();
uint16_t getAnalogValue(uint8_t index);
uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
#define BATTERY_WARN 36 // 3.6V
#define BATTERY_MIN 35 // 3.5V
+25 -29
View File
@@ -100,16 +100,17 @@
#define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_DMA2)
#define ADC_RCC_APB2Periph (RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC3)
#if !defined(FLYSKY_HALL_STICKS)
#define ADC_GPIO_PIN_STICK_LH GPIO_Pin_2 // PA.02
#define ADC_GPIO_PIN_STICK_LV GPIO_Pin_3 // PA.03
#define ADC_GPIO_PIN_STICK_RH GPIO_Pin_4 // PA.04
#define ADC_GPIO_PIN_STICK_RV GPIO_Pin_5 // PA.05
#define ADC_GPIO_PIN_STICK_LH GPIO_Pin_2 // PA.02
#define ADC_GPIO_PIN_STICK_LV GPIO_Pin_3 // PA.03
#define ADC_GPIO_PIN_STICK_RH GPIO_Pin_4 // PA.04
#define ADC_GPIO_PIN_STICK_RV GPIO_Pin_5 // PA.05
#else
#define ADC_GPIO_PIN_STICK_LH 0
#define ADC_GPIO_PIN_STICK_LV 0
#define ADC_GPIO_PIN_STICK_RH 0
#define ADC_GPIO_PIN_STICK_RV 0
#define ADC_GPIO_PIN_STICK_LH 0
#define ADC_GPIO_PIN_STICK_LV 0
#define ADC_GPIO_PIN_STICK_RH 0
#define ADC_GPIO_PIN_STICK_RV 0
#endif
#define ADC_GPIO_PIN_POT1 GPIO_Pin_6 // PA.06 VRA
#define ADC_GPIO_PIN_POT2 GPIO_Pin_4 // PC.04 VRB
#define ADC_GPIO_PIN_SWA GPIO_Pin_1 // PB.01
@@ -128,11 +129,17 @@
#define ADC_GPIOF_PINS (GPIO_Pin_8 | GPIO_Pin_10)
#if !defined(FLYSKY_HALL_STICKS)
#define ADC_CHANNEL_STICK_LH ADC_Channel_2 // ADC123_IN2 -> ADC1_IN2
#define ADC_CHANNEL_STICK_LV ADC_Channel_3 // ADC123_IN3 -> ADC1_IN3
#define ADC_CHANNEL_STICK_RH ADC_Channel_4 // ADC12_IN4 -> ADC1_IN4
#define ADC_CHANNEL_STICK_RV ADC_Channel_5 // ADC12_IN5 -> ADC1_IN5
#define ADC_CHANNEL_STICK_LH ADC_Channel_2 // ADC123_IN2 -> ADC1_IN2
#define ADC_CHANNEL_STICK_LV ADC_Channel_3 // ADC123_IN3 -> ADC1_IN3
#define ADC_CHANNEL_STICK_RH ADC_Channel_4 // ADC12_IN4 -> ADC1_IN4
#define ADC_CHANNEL_STICK_RV ADC_Channel_5 // ADC12_IN5 -> ADC1_IN5
#else
#define ADC_CHANNEL_STICK_LH 0
#define ADC_CHANNEL_STICK_LV 0
#define ADC_CHANNEL_STICK_RH 0
#define ADC_CHANNEL_STICK_RV 0
#endif
#define ADC_CHANNEL_POT1 ADC_Channel_6 // ADC12_IN6 -> ADC1_IN6
#define ADC_CHANNEL_POT2 ADC_Channel_14 // ADC12_IN14 -> ADC1_IN14
#define ADC_CHANNEL_SWA ADC_Channel_9 // ADC12_IN9 -> ADC1_IN9
@@ -146,27 +153,16 @@
#define ADC_CHANNEL_BATT ADC_Channel_15 // ADC12_IN15 -> ADC1_IN15
#define ADC_MAIN ADC1
#define ADC_SUB ADC3
#define ADC_EXT ADC3
#define ADC_SAMPTIME 2
#define ADC_DMA DMA2
#define ADC_DMA_SxCR_CHSEL 0 //DMA_SxCR_CHSEL_1
#define ADC_DMA_Channel DMA_Channel_0
#define ADC_DMA_Stream DMA2_Stream4
#define ADC_SET_DMA_FLAGS() ADC_DMA->HIFCR = (DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4)
#define ADC_TRANSFER_COMPLETE() (ADC_DMA->HISR & DMA_HISR_TCIF4)
#define ADC_DMA_TC_Flag DMA_FLAG_TCIF4
// NV14 customized drivers uses this
#define ADC_MAIN_DMA_SxCR_CHSEL 0 // DMA_SxCR_CHSEL_1
#define ADC_MAIN_DMA_Stream DMA2_Stream4
#define ADC_MAIN_SET_DMA_FLAGS() ADC_DMA->HIFCR = (DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4)
#define ADC_MAIN_TRANSFER_COMPLETE() (ADC_DMA->HISR & DMA_HISR_TCIF4)
#define ADC_SUB_DMA_SxCR_CHSEL DMA_Channel_2
#define ADC_SUB_DMA_Stream DMA2_Stream0
#define ADC_SUB_SET_DMA_FLAGS() ADC_DMA->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0)
#define ADC_SUB_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0)
#define ADC_MAIN_SMPR1 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24);
#define ADC_MAIN_SMPR2 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
#define ADC_EXT_DMA_Channel DMA_Channel_2
#define ADC_EXT_DMA_Stream DMA2_Stream0
#define ADC_EXT_DMA_TC_Flag DMA_FLAG_TCIF0
// Power
#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOI
+1
View File
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
#include "hal/adc_driver.h"
uint32_t readKeys()
{
+2 -1
View File
@@ -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
)
+5 -1
View File
@@ -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,8 @@ void boardInit()
}
#endif
adcInit();
if (!adcInit(&stm32_hal_adc_driver))
TRACE("adcInit failed");
lcdInit(); // delaysInit() must be called before
audioInit();
init2MhzTimer();
+2
View File
@@ -553,6 +553,8 @@ enum Analogs {
NUM_ANALOGS
};
#define HAS_TX_RTC_VOLTAGE
#if defined(PCBX9LITE)
#define NUM_POTS 1
#define NUM_SLIDERS 0
+5 -12
View File
@@ -875,18 +875,11 @@
// ADC
#define ADC_MAIN ADC1
#define ADC_DMA DMA2
#define ADC_DMA_SxCR_CHSEL 0
#define ADC_DMA_Channel DMA_Channel_0
#define ADC_DMA_Stream DMA2_Stream4
#define ADC_SET_DMA_FLAGS() ADC_DMA->HIFCR = (DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4)
#define ADC_TRANSFER_COMPLETE() (ADC_DMA->HISR & DMA_HISR_TCIF4)
#define ADC_DMA_TC_Flag DMA_FLAG_TCIF4
#define ADC_SAMPTIME 2 // sample time = 28 cycles
#if defined(RADIO_TLITE)
#define ADC_MAIN_SMPR1 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + ((ADC_SAMPTIME + 1) << 24); // TLite needs +1 for proper RTC Bat measurement.
#define ADC_MAIN_SMPR2 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
#else
#define ADC_MAIN_SMPR1 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24);
#define ADC_MAIN_SMPR2 (ADC_SAMPTIME << 0) + (ADC_SAMPTIME << 3) + (ADC_SAMPTIME << 6) + (ADC_SAMPTIME << 9) + (ADC_SAMPTIME << 12) + (ADC_SAMPTIME << 15) + (ADC_SAMPTIME << 18) + (ADC_SAMPTIME << 21) + (ADC_SAMPTIME << 24) + (ADC_SAMPTIME << 27);
#endif
#if defined(PCBX9E)
#define HARDWARE_POT1
#define HARDWARE_POT2
@@ -928,8 +921,8 @@
#define ADC_EXT ADC3
#define ADC_EXT_DMA DMA2
#define ADC_EXT_DMA_Stream DMA2_Stream0
#define ADC_EXT_SET_DMA_FLAGS() ADC_DMA->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0)
#define ADC_EXT_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0)
#define ADC_EXT_DMA_Channel DMA_Channel_2
#define ADC_EXT_TC_Flag DMA_FLAG_TCIF0
#define ADC_EXT_SAMPTIME 3 // sample time = 56 cycles
#define ADC_VREF_PREC2 300
#elif defined(PCBX9DP)