@@ -67,6 +67,37 @@ TAMC_GT911 ts = TAMC_GT911(TOUCH_GT911_SDA, TOUCH_GT911_SCL, TOUCH_GT911_INT, TO
6767#include <SPI.h>
6868XPT2046_Touchscreen ts (TOUCH_XPT2046_CS , TOUCH_XPT2046_INT );
6969
70+ // --- Rolling-median filter -----------------------------------------------------
71+ // This resistive panel occasionally returns a wildly off raw reading (a single
72+ // sample can jump 30%+, e.g. raw X 1304 among neighbours around 850), which then
73+ // maps onto the wrong control. Each physical touch yields several samples, so keep
74+ // a short window of raw readings and report their per-axis MEDIAN, which discards
75+ // the odd outlier (a mean would still be dragged toward it). A gap since the last
76+ // sample starts a fresh window (= a new, separate touch). We withhold the press
77+ // until a few samples are in, so the very first (possibly bad) sample can't land
78+ // the press on the wrong control.
79+ #define TOUCH_MEDIAN_WINDOW 7 // raw samples retained
80+ #define TOUCH_MEDIAN_MIN 3 // samples for the normal path (median rejects 1 outlier)
81+ #define TOUCH_MEDIAN_FLOOR 2 // fewest samples the time fallback will accept
82+ #define TOUCH_SETTLE_MS 45 // commit a short touch by now even with < MIN samples
83+ #define TOUCH_NEW_TOUCH_GAP_MS 120 // gap that marks the start of a new touch
84+ static int touchRawX [TOUCH_MEDIAN_WINDOW ];
85+ static int touchRawY [TOUCH_MEDIAN_WINDOW ];
86+ static uint8_t touchSampleCount = 0 ;
87+ static uint8_t touchSampleHead = 0 ;
88+ static unsigned long touchLastSampleMs = 0 ;
89+ static unsigned long touchStartMs = 0 ; // time of the first sample of the current touch
90+
91+ static int touch_median (const int * src , uint8_t n ) {
92+ int tmp [TOUCH_MEDIAN_WINDOW ];
93+ for (uint8_t i = 0 ; i < n ; i ++ ) tmp [i ] = src [i ];
94+ for (uint8_t i = 1 ; i < n ; i ++ ) { // insertion sort; n is tiny (<= window)
95+ int v = tmp [i ], j = i ;
96+ while (j > 0 && tmp [j - 1 ] > v ) { tmp [j ] = tmp [j - 1 ]; j -- ; }
97+ tmp [j ] = v ;
98+ }
99+ return tmp [n / 2 ];
100+ }
70101#endif
71102
72103#if defined(TOUCH_FT6X36 )
@@ -184,13 +215,39 @@ bool touch_touched()
184215 if (ts .touched ())
185216 {
186217 TS_Point p = ts .getPoint ();
187- Serial .printf ("Touch Raw remap from %d/%d @%d" , p .x , p .y , p .z );
218+
219+ unsigned long nowMs = millis ();
220+ if (nowMs - touchLastSampleMs > TOUCH_NEW_TOUCH_GAP_MS ) {
221+ // Long gap since the last sample -> this is a new touch; drop the old window.
222+ touchSampleCount = 0 ;
223+ touchSampleHead = 0 ;
224+ touchStartMs = nowMs ;
225+ }
226+ touchLastSampleMs = nowMs ;
227+
228+ touchRawX [touchSampleHead ] = p .x ;
229+ touchRawY [touchSampleHead ] = p .y ;
230+ touchSampleHead = (touchSampleHead + 1 ) % TOUCH_MEDIAN_WINDOW ;
231+ if (touchSampleCount < TOUCH_MEDIAN_WINDOW ) touchSampleCount ++ ;
232+
233+ // Commit the press once we have enough samples for a solid median, OR after a
234+ // short settle time with at least a couple of samples (so a brief tap that only
235+ // produces 2 reads still registers instead of being silently dropped).
236+ bool ready = (touchSampleCount >= TOUCH_MEDIAN_MIN ) ||
237+ (touchSampleCount >= TOUCH_MEDIAN_FLOOR && (nowMs - touchStartMs ) >= TOUCH_SETTLE_MS );
238+ if (!ready ) {
239+ return false;
240+ }
241+
242+ int mx = touch_median (touchRawX , touchSampleCount );
243+ int my = touch_median (touchRawY , touchSampleCount );
244+ Serial .printf ("Touch raw %d/%d @%d -> median %d/%d (n=%d)" , p .x , p .y , p .z , mx , my , touchSampleCount );
188245#if defined(TOUCH_SWAP_XY )
189- touch_last_x = map (p . y , TOUCH_MAP_X1 , TOUCH_MAP_X2 , 0 , gfx -> width () - 1 );
190- touch_last_y = map (p . x , TOUCH_MAP_Y1 , TOUCH_MAP_Y2 , 0 , gfx -> height () - 1 );
246+ touch_last_x = map (my , TOUCH_MAP_X1 , TOUCH_MAP_X2 , 0 , gfx -> width () - 1 );
247+ touch_last_y = map (mx , TOUCH_MAP_Y1 , TOUCH_MAP_Y2 , 0 , gfx -> height () - 1 );
191248#else
192- touch_last_x = map (p . x , TOUCH_MAP_X1 , TOUCH_MAP_X2 , 0 , gfx -> width () - 1 );
193- touch_last_y = map (p . y , TOUCH_MAP_Y1 , TOUCH_MAP_Y2 , 0 , gfx -> height () - 1 );
249+ touch_last_x = map (mx , TOUCH_MAP_X1 , TOUCH_MAP_X2 , 0 , gfx -> width () - 1 );
250+ touch_last_y = map (my , TOUCH_MAP_Y1 , TOUCH_MAP_Y2 , 0 , gfx -> height () - 1 );
194251#endif
195252 return true;
196253 }
0 commit comments