1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-19 14:25:11 +03:00

Merge pull request #3407 from opentx/bsongis/adc_averaging_done_in_driver_layer

[ARM board] ADC are done 4 times inside the driver now. To be tested …
This commit is contained in:
Bertrand Songis 2016-04-10 22:57:13 +02:00
commit 1f19256722
8 changed files with 192 additions and 147 deletions

View file

@ -221,8 +221,6 @@ const char * debugTimerNames[DEBUG_TIMERS_COUNT] = {
,"Mix eval " // debugTimerEvalMixes,
,"Mix 10ms " // debugTimerMixes10ms,
,"ADC read " // debugTimerAdcRead,
,"ADC loop " // debugTimerAdcLoop,
,"ADC wait " // debugTimerAdcWait,
,"mix-pulses " // debugTimerMixerCalcToUsage
,"mix-int. " // debugTimerMixerIterval
};

View file

@ -321,8 +321,6 @@ enum DebugTimers {
debugTimerMixes10ms,
debugTimerAdcRead,
debugTimerAdcLoop,
debugTimerAdcWait,
debugTimerMixerCalcToUsage,
debugTimerMixerIterval,

View file

@ -162,7 +162,7 @@ bool menuStatsAnalogs(evt_t event)
#if defined(JITTER_MEASURE)
lcdDrawNumber(x+100, y, rawJitter[i].get());
lcdDrawNumber(x+140, y, avgJitter[i].get());
lcdDrawNumber(x+180, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256);
lcdDrawNumber(x+180, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*250/256, PREC1);
#else
lcdDrawNumber(x+100, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256);
#endif

View file

@ -1463,30 +1463,20 @@ uint16_t BandGap = 225;
// G: Note that the above would have set the ADC prescaler to 128, equating to
// 125KHz sample rate. We now sample at 500KHz, with oversampling and other
// filtering options to produce 11-bit results.
uint16_t BandGap = 2040 ;
uint16_t BandGap = 2040;
#elif defined(PCBSTD)
uint16_t BandGap ;
uint16_t BandGap;
#endif
#if defined(JITTER_MEASURE)
JitterMeter<uint16_t> rawJitter[NUMBER_ANALOG];
JitterMeter<uint16_t> avgJitter[NUMBER_ANALOG];
tmr10ms_t jitterResetTime = 0;
#if defined(PCBHORUS)
#define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuStatsAnalogs)
#elif defined(PCBTARANIS)
#define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuGeneralDiagAna)
#elif defined(CLI)
#define JITTER_MEASURE_ACTIVE() (1)
#else
#define JITTER_MEASURE_ACTIVE() (0)
#endif
JitterMeter<uint16_t> rawJitter[NUMBER_ANALOG];
JitterMeter<uint16_t> avgJitter[NUMBER_ANALOG];
tmr10ms_t jitterResetTime = 0;
#endif
#if defined(VIRTUALINPUTS) && defined(JITTER_FILTER)
#define JITTER_FILTER_STRENGTH 4 // tune this value, bigger value - more filtering (range: 1-5) (see explanation below)
#define ANALOG_SCALE 1 // tune this value, bigger value - more filtering (range: 0-3) (see explanation below)
#define ANALOG_SCALE 1 // tune this value, bigger value - more filtering (range: 0-1) (see explanation below)
#define JITTER_ALPHA (1<<JITTER_FILTER_STRENGTH)
#define ANALOG_MULTIPLIER (1<<ANALOG_SCALE)
@ -1536,8 +1526,6 @@ uint16_t anaIn(uint8_t chan)
#if defined(CPUARM)
void getADC()
{
uint16_t temp[NUMBER_ANALOG] = { 0 };
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE() && jitterResetTime < get_tmr10ms()) {
// reset jitter measurement every second
@ -1550,22 +1538,11 @@ void getADC()
#endif
DEBUG_TIMER_START(debugTimerAdcRead);
for (uint8_t i=0; i<4; i++) {
adcRead();
for (uint8_t x=0; x<NUMBER_ANALOG; x++) {
uint16_t val = getAnalogValue(x);
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE()) {
rawJitter[x].measure(val);
}
#endif
temp[x] += val;
}
}
adcRead();
DEBUG_TIMER_STOP(debugTimerAdcRead);
for (uint32_t x=0; x<NUMBER_ANALOG; x++) {
uint16_t v = temp[x] >> (3 - ANALOG_SCALE);
for (uint8_t x=0; x<NUMBER_ANALOG; x++) {
uint16_t v = getAnalogValue(x) >> (1 - ANALOG_SCALE);
#if defined(VIRTUALINPUTS) && defined(JITTER_FILTER)
// Jitter filter:

View file

@ -1790,7 +1790,16 @@ extern uint16_t s_anaFilt[NUMBER_ANALOG];
#if defined(JITTER_MEASURE)
extern JitterMeter<uint16_t> rawJitter[NUMBER_ANALOG];
extern JitterMeter<uint16_t> avgJitter[NUMBER_ANALOG];
#endif // defined(JITTER_MEASURE)
#if defined(PCBHORUS)
#define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuStatsAnalogs)
#elif defined(PCBTARANIS)
#define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuGeneralDiagAna)
#elif defined(CLI)
#define JITTER_MEASURE_ACTIVE() (1)
#else
#define JITTER_MEASURE_ACTIVE() (0)
#endif
#endif
#define WDT_500MS 500

View file

@ -18,11 +18,23 @@
* GNU General Public License for more details.
*/
#include "../../opentx.h"
#include "opentx.h"
#define ADC_CS_HIGH() (ADC_SPI_GPIO->BSRRL = ADC_SPI_PIN_CS)
#define ADC_CS_LOW() (ADC_SPI_GPIO->BSRRH = ADC_SPI_PIN_CS)
#define SPI_STICK1 0
#define SPI_STICK2 1
#define SPI_STICK3 2
#define SPI_STICK4 3
#define SPI_S1 4
#define SPI_6POS 5
#define SPI_S2 6
#define SPI_LS 7
#define SPI_RS 8
#define SPI_TX_VOLTAGE 9
#define SPI_L2 10
#define SPI_L1 11
#define RESETCMD 0x4000
#define MANUAL_MODE 0x1000 // manual mode channel 0
@ -30,7 +42,7 @@
uint16_t adcValues[NUMBER_ANALOG] __DMA;
static u16 SPIx_ReadWriteByte(uint16_t value)
uint16_t SPIx_ReadWriteByte(uint16_t value)
{
while(SPI_I2S_GetFlagStatus(ADC_SPI,SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(ADC_SPI,value);
@ -87,27 +99,13 @@ static void ADS7952_Init()
ADC_CS_LOW();
SPIx_ReadWriteByte(MANUAL_MODE);
ADC_CS_HIGH();
// SPIx_ReadWriteByte(ProgramReg_Auto2 );
// ADC_CS_HIGH();
// asm("nop");
// ADC_CS_LOW();
// SPIx_ReadWriteByte(AutoMode_2);
// ADC_CS_HIGH();
// asm("nop");
// ADC_CS_LOW();
// SPIx_ReadWriteByte(ContinuedSelectMode);
// ADC_CS_HIGH();
// asm("nop");
}
void adcInit()
{
ADS7952_Init();
configure_pins( ADC_GPIO_PIN_MOUSE1 | ADC_GPIO_PIN_MOUSE2, PIN_ANALOG | PIN_PORTF );
configure_pins(ADC_GPIO_PIN_MOUSE1 | ADC_GPIO_PIN_MOUSE2, PIN_ANALOG | PIN_PORTF);
ADC3->CR1 = ADC_CR1_SCAN;
ADC3->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
@ -126,42 +124,72 @@ void adcInit()
DMA2_Stream1->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
}
#define SPI_STICK1 0
#define SPI_STICK2 1
#define SPI_STICK3 2
#define SPI_STICK4 3
#define SPI_S1 4
#define SPI_6POS 5
#define SPI_S2 6
#define SPI_LS 7
#define SPI_RS 8
#define SPI_TX_VOLTAGE 9
#define SPI_L2 10
#define SPI_L1 11
const uint16_t adcCommands[MOUSE1+2] =
{
MANUAL_MODE | ( SPI_STICK1 << 7 ),
MANUAL_MODE | ( SPI_STICK2 << 7 ),
MANUAL_MODE | ( SPI_STICK3 << 7 ),
MANUAL_MODE | ( SPI_STICK4 << 7 ),
MANUAL_MODE | ( SPI_S1 << 7 ),
MANUAL_MODE | ( SPI_6POS << 7 ),
MANUAL_MODE | ( SPI_S2 << 7 ),
MANUAL_MODE | ( SPI_L1 << 7 ),
MANUAL_MODE | ( SPI_L2 << 7 ),
MANUAL_MODE | ( SPI_LS << 7 ),
MANUAL_MODE | ( SPI_RS << 7 ),
MANUAL_MODE | ( SPI_TX_VOLTAGE << 7 ),
MANUAL_MODE | ( 0 << 7 ), // small joystick left/right
MANUAL_MODE | ( 0 << 7 ) // small joystick up/down
MANUAL_MODE | (SPI_STICK1 << 7),
MANUAL_MODE | (SPI_STICK2 << 7),
MANUAL_MODE | (SPI_STICK3 << 7),
MANUAL_MODE | (SPI_STICK4 << 7),
MANUAL_MODE | (SPI_S1 << 7),
MANUAL_MODE | (SPI_6POS << 7),
MANUAL_MODE | (SPI_S2 << 7),
MANUAL_MODE | (SPI_L1 << 7),
MANUAL_MODE | (SPI_L2 << 7),
MANUAL_MODE | (SPI_LS << 7),
MANUAL_MODE | (SPI_RS << 7),
MANUAL_MODE | (SPI_TX_VOLTAGE << 7),
MANUAL_MODE | (0 << 7 ), // small joystick left/right
MANUAL_MODE | (0 << 7 ) // small joystick up/down
};
void adcRead()
void adcReadSPIDummy()
{
const uint16_t * command = adcCommands;
// A dummy command to get things started
// (because the sampled data is lagging behind for two command cycles)
ADC_CS_LOW();
delay_01us(1);
SPIx_ReadWriteByte(adcCommands[0]);
ADC_CS_HIGH();
delay_01us(1);
}
// Start on chip ADC read
uint32_t adcReadNextSPIChannel(uint8_t index)
{
uint32_t result = 0;
// This delay is to allow charging of ADC input capacitor
// after the MUX changes from one channel to the other.
// It was determined experimentally. Biggest problem seems to be
// the cross-talk between A4:S1 and A5:MULTIPOS. Changing S1 for one extreme
// to the other resulted in A5 change of:
//
// delay value A5 change Time needed for adcRead()
// 1 16 0.154ms - 0.156ms
// 300 5 0.197ms - 0.199ms
// 500 0 0.225ms - 0.243ms
delay_01us(300);
for (uint8_t i = 0; i < 4; i++) {
ADC_CS_LOW();
delay_01us(1);
// command is changed to the next index for the last two readings
// (because the sampled data is lagging behind for two command cycles)
uint16_t val = (0x0fff & SPIx_ReadWriteByte(adcCommands[(i>1) ? index+1 : index]));
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE()) {
rawJitter[index].measure(val);
}
#endif
ADC_CS_HIGH();
delay_01us(1);
result += val;
}
return result >> 2;
}
void adcOnChipReadStart()
{
DMA2_Stream1->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC3->SR &= ~(uint32_t) ( ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR );
DMA2->LIFCR = DMA_LIFCR_CTCIF1 | DMA_LIFCR_CHTIF1 |DMA_LIFCR_CTEIF1 | DMA_LIFCR_CDMEIF1 | DMA_LIFCR_CFEIF1; // Write ones to clear bits
@ -169,60 +197,48 @@ void adcRead()
DMA2_Stream1->NDTR = 2;
DMA2_Stream1->CR |= DMA_SxCR_EN; // Enable DMA
ADC3->CR2 |= (uint32_t)ADC_CR2_SWSTART;
}
// A dummy command to get things started
// (because the sampled data is lagging behind for two command cycles)
ADC_CS_LOW();
delay_01us(1);
SPIx_ReadWriteByte(*command); // still sampling the old MUX channel
ADC_CS_HIGH();
delay_01us(1);
bool adcOnChipReadFinished()
{
return (DMA2->LISR & DMA_LISR_TCIF1);
}
DEBUG_TIMER_START(debugTimerAdcLoop);
for (uint32_t adcIndex=0; adcIndex<MOUSE1; adcIndex++) {
// MUX is changed to the channel that was sent in the previous command
// but the data is from the old MUX position
ADC_CS_LOW();
delay_01us(1);
SPIx_ReadWriteByte(*command);
ADC_CS_HIGH();
delay_01us(1);
void adcRead()
{
uint16_t temp[NUMBER_ANALOG-MOUSE1] = { 0 };
uint8_t noInternalReads = 0;
// This delay is to allow charging of ADC input capacitor
// after the MUX changes from one channel to the other.
// It was determined experimentally. Biggest problem seems to be
// the cross-talk between A4:S1 and A5:MULTIPOS. Changing S1 for one extreme
// to the other resulted in A5 change of:
//
// delay value A5 change
// 0 76
// 100 26
// 300 13
// 500 undetectable
delay_01us(500);
++command; // move to the next channel
// First time the wanted ADC channel is actually sampled.
// This is delayed to allow MUX to settle (high input impedance)
// Also the MUX channel is set to the next channel here,
// but the actual MUX change will happen in the next round
ADC_CS_LOW();
delay_01us(1);
adcValues[adcIndex] = (0x0fff & SPIx_ReadWriteByte(*command));
ADC_CS_HIGH();
delay_01us(1);
}
DEBUG_TIMER_STOP(debugTimerAdcLoop);
DEBUG_TIMER_START(debugTimerAdcWait);
for (uint32_t i=0; i<20000; i++) {
if (DMA2->LISR & DMA_LISR_TCIF1) {
break;
adcOnChipReadStart();
adcReadSPIDummy();
adcReadSPIDummy();
for (uint32_t index=0; index<MOUSE1; index++) {
adcValues[index] = adcReadNextSPIChannel(index);
if (noInternalReads < 4 && adcOnChipReadFinished()) {
for (uint8_t x=0; x<NUMBER_ANALOG-MOUSE1; x++) {
uint16_t val = adcValues[MOUSE1+x];
#if defined(JITTER_MEASURE)
if (JITTER_MEASURE_ACTIVE()) {
rawJitter[MOUSE1+x].measure(val);
}
#endif
temp[x] += val;
}
if (++noInternalReads < 4) {
adcOnChipReadStart();
}
}
}
DEBUG_TIMER_STOP(debugTimerAdcWait);
// On chip ADC read should have finished
#if defined(DEBUG)
if (noInternalReads != 4) {
TRACE("Internal ADC problem: reads: %d", noInternalReads);
}
#endif
for (uint8_t x=0; x<NUMBER_ANALOG-MOUSE1; x++) {
adcValues[MOUSE1+x] = temp[x] >> 2;
}
}
const int8_t ana_direction[NUMBER_ANALOG] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1, 0,0,0};
@ -230,7 +246,7 @@ const int8_t ana_direction[NUMBER_ANALOG] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1,
uint16_t getAnalogValue(uint8_t index)
{
if (ana_direction[index] < 0)
return 4096 - adcValues[index];
return 4095 - adcValues[index];
else
return adcValues[index];
}

View file

@ -18,7 +18,7 @@
* GNU General Public License for more details.
*/
#include "../opentx.h"
#include "opentx.h"
uint16_t adcValues[NUMBER_ANALOG];
@ -63,12 +63,13 @@ void adcInit()
// Read 8 (9 for REVB) ADC channels
// Documented bug, must do them 1 by 1
void adcRead()
void adcSingleRead()
{
register Adc *padc;
register uint32_t y;
register uint32_t x;
for (uint8_t i=0; i<4; i++)
padc = ADC;
y = padc->ADC_ISR; // Clear EOC flags
for (y = NUMBER_ANALOG+1; --y > 0;) {
@ -112,6 +113,29 @@ void adcRead()
#endif
}
void adcRead()
{
uint16_t temp[NUMBER_ANALOG] = { 0 };
for (int i=0; i<4; i++) {
adcSingleRead();
for (uint8_t x=0; x<NUMBER_ANALOG; 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=0; x<NUMBER_ANALOG; x++) {
adcValues[x] = temp[x] >> 2;
}
}
uint16_t getAnalogValue(uint8_t value)
{
return adcValues[value];

View file

@ -18,7 +18,7 @@
* GNU General Public License for more details.
*/
#include "../../opentx.h"
#include "opentx.h"
#define PIN_ANALOG 0x0003
#define PIN_PORTA 0x0000
@ -111,13 +111,14 @@ void adcInit()
#endif
}
void adcRead()
void adcSingleRead()
{
DMA2_Stream0->CR &= ~DMA_SxCR_EN ; // Disable DMA
ADC1->SR &= ~(uint32_t) ( ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR ) ;
DMA2->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 |DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0 ; // Write ones to clear bits
DMA2_Stream0->CR |= DMA_SxCR_EN ; // Enable DMA
ADC1->CR2 |= (uint32_t)ADC_CR2_SWSTART ;
DMA2_Stream0->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC1->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
DMA2->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 |
DMA_LIFCR_CFEIF0; // Write ones to clear bits
DMA2_Stream0->CR |= DMA_SxCR_EN; // Enable DMA
ADC1->CR2 |= (uint32_t) ADC_CR2_SWSTART;
#if defined(REV9E)
DMA2_Stream1->CR &= ~DMA_SxCR_EN ; // Disable DMA
@ -125,7 +126,7 @@ void adcRead()
DMA2->LIFCR = DMA_LIFCR_CTCIF1 | DMA_LIFCR_CHTIF1 |DMA_LIFCR_CTEIF1 | DMA_LIFCR_CDMEIF1 | DMA_LIFCR_CFEIF1 ; // Write ones to clear bits
DMA2_Stream1->CR |= DMA_SxCR_EN ; // Enable DMA
ADC3->CR2 |= (uint32_t)ADC_CR2_SWSTART ;
#endif // #if defined(REV9E)
#endif // defined(REV9E)
#if defined(REV9E)
for (unsigned int i=0; i<10000; i++) {
@ -136,15 +137,37 @@ void adcRead()
DMA2_Stream0->CR &= ~DMA_SxCR_EN ; // Disable DMA
DMA2_Stream1->CR &= ~DMA_SxCR_EN ; // Disable DMA
#else
for (unsigned int i=0; i<10000; i++) {
for (unsigned int i = 0; i < 10000; i++) {
if (DMA2->LISR & DMA_LISR_TCIF0) {
break;
}
}
DMA2_Stream0->CR &= ~DMA_SxCR_EN ; // Disable DMA
DMA2_Stream0->CR &= ~DMA_SxCR_EN; // Disable DMA
#endif
}
void adcRead()
{
uint16_t temp[NUMBER_ANALOG] = { 0 };
for (int i=0; i<4; i++) {
adcSingleRead();
for (uint8_t x=0; x<NUMBER_ANALOG; 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=0; x<NUMBER_ANALOG; x++) {
adcValues[x] = temp[x] >> 2;
}
}
// TODO
void adcStop()
{
@ -162,7 +185,7 @@ uint16_t getAnalogValue(uint8_t index)
index = ana_mapping[index];
#endif
if (ana_direction[index] < 0)
return 4096 - adcValues[index];
return 4095 - adcValues[index];
else
return adcValues[index];
}