From 1e3da34ec86328a86959bc505e1b64226619d10f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 9 Apr 2016 10:09:54 +0200 Subject: [PATCH 1/4] [ARM board] ADC are done 4 times inside the driver now. To be tested on H --- radio/src/opentx.cpp | 39 +---- radio/src/opentx.h | 11 +- radio/src/targets/horus/adc_driver.cpp | 201 ++++++++++++----------- radio/src/targets/sky9x/adc_driver.cpp | 28 +++- radio/src/targets/taranis/adc_driver.cpp | 43 +++-- 5 files changed, 184 insertions(+), 138 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 0beaec4dc..dc30c9141 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1503,27 +1503,17 @@ 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 rawJitter[NUMBER_ANALOG]; - JitterMeter 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 rawJitter[NUMBER_ANALOG]; +JitterMeter 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) @@ -1576,8 +1566,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 @@ -1590,22 +1578,11 @@ void getADC() #endif DEBUG_TIMER_START(debugTimerAdcRead); - for (uint8_t i=0; i<4; i++) { - adcRead(); - for (uint8_t x=0; x> (3 - ANALOG_SCALE); + for (uint8_t x=0; x> (1 - ANALOG_SCALE); #if defined(VIRTUALINPUTS) && defined(JITTER_FILTER) // Jitter filter: diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 5e17361ac..d170135c8 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1750,7 +1750,16 @@ extern uint16_t s_anaFilt[NUMBER_ANALOG]; #if defined(JITTER_MEASURE) extern JitterMeter rawJitter[NUMBER_ANALOG]; extern JitterMeter 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 diff --git a/radio/src/targets/horus/adc_driver.cpp b/radio/src/targets/horus/adc_driver.cpp index 49c45d92b..7353bce5c 100644 --- a/radio/src/targets/horus/adc_driver.cpp +++ b/radio/src/targets/horus/adc_driver.cpp @@ -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,75 @@ 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; + + ADC_CS_LOW(); + delay_01us(1); + SPIx_ReadWriteByte(adcCommands[index]); + ADC_CS_HIGH(); + // 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); + + for (uint8_t i = 0; i < 4; i++) { + ADC_CS_LOW(); + delay_01us(1); + uint16_t val = (0x0fff & SPIx_ReadWriteByte(adcCommands[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 adcStartNextOnChipRead() +{ 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 +200,42 @@ 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); - - DEBUG_TIMER_START(debugTimerAdcLoop); - for (uint32_t adcIndex=0; adcIndexLISR & DMA_LISR_TCIF1) { break; } } - DEBUG_TIMER_STOP(debugTimerAdcWait); +} - // On chip ADC read should have finished +void adcRead() +{ + uint16_t temp[NUMBER_ANALOG-MOUSE1] = { 0 }; + + adcReadSPIDummy(); + for (uint32_t index=0; index> 2; + } } const int8_t ana_direction[NUMBER_ANALOG] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1, 0,0,0}; diff --git a/radio/src/targets/sky9x/adc_driver.cpp b/radio/src/targets/sky9x/adc_driver.cpp index df38418ca..8cd4dc066 100644 --- a/radio/src/targets/sky9x/adc_driver.cpp +++ b/radio/src/targets/sky9x/adc_driver.cpp @@ -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> 2; + } +} + + uint16_t getAnalogValue(uint8_t value) { return adcValues[value]; diff --git a/radio/src/targets/taranis/adc_driver.cpp b/radio/src/targets/taranis/adc_driver.cpp index 2b3ca7f75..810ea883b 100644 --- a/radio/src/targets/taranis/adc_driver.cpp +++ b/radio/src/targets/taranis/adc_driver.cpp @@ -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> 2; + } +} + // TODO void adcStop() { From 9e0e71ad92d7713fbd467f12fbf905cea692df47 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Sun, 10 Apr 2016 21:05:49 +0200 Subject: [PATCH 2/4] ADC crosstalk fixed, new crosstalk and time measurements (for Horus) --- radio/src/debug.cpp | 2 - radio/src/debug.h | 2 - radio/src/targets/horus/adc_driver.cpp | 47 +++++++++++++----------- radio/src/targets/taranis/adc_driver.cpp | 2 +- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/radio/src/debug.cpp b/radio/src/debug.cpp index 101359994..3b1c32a64 100644 --- a/radio/src/debug.cpp +++ b/radio/src/debug.cpp @@ -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 }; diff --git a/radio/src/debug.h b/radio/src/debug.h index 6edabc6f0..299edfcfa 100644 --- a/radio/src/debug.h +++ b/radio/src/debug.h @@ -321,8 +321,6 @@ enum DebugTimers { debugTimerMixes10ms, debugTimerAdcRead, - debugTimerAdcLoop, - debugTimerAdcWait, debugTimerMixerCalcToUsage, debugTimerMixerIterval, diff --git a/radio/src/targets/horus/adc_driver.cpp b/radio/src/targets/horus/adc_driver.cpp index 7353bce5c..def0d6f4c 100644 --- a/radio/src/targets/horus/adc_driver.cpp +++ b/radio/src/targets/horus/adc_driver.cpp @@ -157,27 +157,24 @@ uint32_t adcReadNextSPIChannel(uint8_t index) { uint32_t result = 0; - ADC_CS_LOW(); - delay_01us(1); - SPIx_ReadWriteByte(adcCommands[index]); - ADC_CS_HIGH(); // 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); + // 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); - uint16_t val = (0x0fff & SPIx_ReadWriteByte(adcCommands[index])); + // 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); @@ -191,7 +188,7 @@ uint32_t adcReadNextSPIChannel(uint8_t index) return result >> 2; } -void adcStartNextOnChipRead() +void adcOnChipReadStart() { DMA2_Stream1->CR &= ~DMA_SxCR_EN; // Disable DMA ADC3->SR &= ~(uint32_t) ( ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR ); @@ -202,25 +199,22 @@ void adcStartNextOnChipRead() ADC3->CR2 |= (uint32_t)ADC_CR2_SWSTART; } -void adcEndNextOnChipRead() +bool adcOnChipReadFinished() { - for (uint32_t i=0; i<20000; i++) { - if (DMA2->LISR & DMA_LISR_TCIF1) { - break; - } - } + return (DMA2->LISR & DMA_LISR_TCIF1); } void adcRead() { uint16_t temp[NUMBER_ANALOG-MOUSE1] = { 0 }; + uint8_t noInternalReads = 0; + adcOnChipReadStart(); + adcReadSPIDummy(); adcReadSPIDummy(); for (uint32_t index=0; index> 2; } @@ -243,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]; } diff --git a/radio/src/targets/taranis/adc_driver.cpp b/radio/src/targets/taranis/adc_driver.cpp index 810ea883b..1d010deb5 100644 --- a/radio/src/targets/taranis/adc_driver.cpp +++ b/radio/src/targets/taranis/adc_driver.cpp @@ -185,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]; } From 8ed325c33f83e8b76c2f2db52480fa5a9a70680b Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Sun, 10 Apr 2016 22:20:06 +0200 Subject: [PATCH 3/4] Better precision for Analogs screen --- radio/src/gui/horus/view_statistics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/horus/view_statistics.cpp b/radio/src/gui/horus/view_statistics.cpp index 636fa3c8c..bf14b91e4 100644 --- a/radio/src/gui/horus/view_statistics.cpp +++ b/radio/src/gui/horus/view_statistics.cpp @@ -152,7 +152,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 From 6b73df69357e3995dfbc2070b3ced5bdc9ec3d81 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Sun, 10 Apr 2016 22:27:49 +0200 Subject: [PATCH 4/4] Doc fix for ANALOG_SCALE --- radio/src/opentx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index dc30c9141..920b25500 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1516,7 +1516,7 @@ tmr10ms_t jitterResetTime = 0; #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<