ESP8266 ILI9341 display support code with printf sources, wire-frame viewer and custom fonts  1.0
ESP8266ILI9341DisplayProject
xpt2046.c
Go to the documentation of this file.
1 
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <math.h>
30 
31 #include "user_config.h"
32 
33 #if DISPLAY
34 
35 #ifdef XPT2046
36 #include "xpt2046.h"
37 
38 #include "display/ili9341.h"
39 
43 
44 extern window *tft;
45 
46 #ifndef XPT2046_CS
47 #error You must define the XPT2046 GPIO pin
48 #endif
49 
52 
54 uint32_t XPT2046_clock = -1;
55 
57 xpt2046_t xpt2046;
58 
62 void XPT2046_spi_init(void)
63 {
64  XPT2046_clock = 40;
65  chip_select_init(XPT2046_CS);
67  xpt2046.rotation = tft->rotation;
68 }
69 
70 
73 void XPT2046_key_flush()
74 {
75  xpt2046.state = 0;
76  xpt2046.ms = 0;
77  xpt2046.ind = 0;
78  xpt2046.head = 0;
79  xpt2046.tail = 0;
80 }
81 
82 
125 {
126  uint8_t buf[3];
127  uint16_t val;
128 
129  // First byte to send is the command
130  buf[0] = cmd;
131  // 0 is ignored as a command NOOP, used here to read the reply from the ADC
132  buf[1] = 0;
133  buf[2] = 0;
134 
135  spi_begin(XPT2046_clock, XPT2046_CS);
136  // Send three bytes and read the result
137  spi_TXRX_buffer(buf,3);
138  spi_end(XPT2046_CS);
139 
140  // buf[0] - Ignore data read back from the first command byte - is has no valid data
141 
142  // Extract the ADC 12 bit reply - ADC result starts one bit AFTER the MSB bit position
143  val = buf[1]; // MSB
144  val <<= 8;
145  val |= buf[2]; // LSB
146 
147  // Align 12 bit result to LSB bit position
148  val >>= 3;
149 
150  if(val < 0)
151  val = 0;
152  if(val >4095)
153  val = 4095;
154  return(val);
155 }
156 
162 //MEMSPACE
164 {
165  int Z1,Z2,Z;
166 
169  // of the touch pressure
170  Z = (4095 - Z2) + Z1;
171  if(Z < 0)
172  Z = -Z;
173  if(Z > 300)
174  {
175  switch (tft->rotation)
176  {
177  case 0:
178  // reverse X
179  xpt2046.rotation = 0;
180  *X = 4095 - XPT2046_read(XPT2046_READ_X);
182  break;
183 
184  case 1:
185  // swap X and Y
186  xpt2046.rotation = 1;
189  break;
190 
191  case 2:
192  // reverse Y
193  xpt2046.rotation = 2;
195  *Y = 4095 - XPT2046_read(XPT2046_READ_Y);
196  break;
197 
198  case 3:
199  xpt2046.rotation = 3;
200  // swap X and Y and reverse X and Y
201  *X = 4095 - XPT2046_read(XPT2046_READ_Y);
202  *Y = 4095 - XPT2046_read(XPT2046_READ_X);
203  break;
204  }
205  return(1); // 1 = touch event
206  }
207  return(0); // no touch event
208 }
209 
210 
211 #if 0
212 MEMSPACE
220 {
221  int XC,YC, XL,YL, XD, YD;
222  long Xavg,Yavg;
223  int count; // Sample counter - to compute average
224 
225  Xavg = 0; // X average
226  Yavg = 0; // Y average
227 
228  for(count=0;count<XPT2046_SAMPLES;++count)
229  {
230  // X and Y if touched - otherwise 0,0
231  if(!XPT2046_xy_raw(X, Y))
232  break;
233  XC = *X;
234  YC = *Y;
235  // Has the permitted peak to peak NOISE maximum been exceeded ?
236  if(count)
237  {
238  XD = XC - XL;
239  if(XD < 0)
240  XD = -XD;
241  YD = YC - YL;
242  if(YD < 0)
243  YD = -YD;
244  if(XD > 20 || YD > 20)
245  break;
246  }
247 
248  // Update average
249  Xavg += XC;
250  Yavg += YC;
251  XL = XC;
252  YL = YC;
253  }
254 
255  // FIXME testing shows we need at least 2 samples in a row to be ok
256  if(count)
257  {
258  Xavg /= count;
259  Yavg /= count;
260  }
261  *X = (uint16_t) Xavg;
262  *Y = (uint16_t) Yavg;
263  return(count);
264 }
265 #else
266 
267 
274 int XPT2046_loop;
275 MEMSPACE
276 int nearest_run(int *v, int size, int minsamples, int *count)
277 {
278 
279  int i,j;
280  int val;
281  int diff,diffavg;
282  int run;
283  int sum;
284  int noise;
285  int min_run = 1;
286  int average = 0;
287  int min_noise = 65536;
288 
289  for(i=0;i<size;++i)
290  {
291  val = v[i];
292  sum = val;
293  run = 0;
294  noise = 0;
295 
296  for(j=i+1;j<size;++j)
297  {
298  // compute differences
299  diff = v[j] - val;
300  if(diff < 0)
301  diff = -diff;
302 
303  ++run;
304 
305  // this is run+1 sample we have averaged
306  sum += v[j];
307 
308  noise += diff;
309 
310  // FIXME we want average signal to noise ratio
311  // always favor longer runs if better or equal noise
312  if(run >= minsamples)
313  {
314  if((noise/run) <= min_noise/min_run)
315  {
316  min_noise = noise;;
317  min_run = run;
318  // we have run + 1 elements
319  average = sum/(run+1);
320  }
321  }
322  }
323  }
324 
325  // we have run + 1 elements
326  *count = min_run+1;
327  if(min_run >= minsamples)
328  {
329  return(average);
330  }
331  return(-1);
332 }
333 
340 MEMSPACE
342 {
343  int XS[XPT2046_SAMPLES+1];
344  int YS[XPT2046_SAMPLES+1];
345  int Xavg,Yavg;
346  int xcount,ycount;
347 
348  int i;
349  for(i=0;i<XPT2046_SAMPLES;++i)
350  {
351  // X and Y if touched - otherwise 0,0
352  if(!XPT2046_xy_raw(X, Y))
353  break;
354  XS[i] = *X;
355  YS[i] = *Y;
356  }
357 
358  if(i >= 3)
359  {
360  Xavg = nearest_run((int *) &XS, i, 3, &xcount);
361  Yavg = nearest_run((int *) &YS, i, 3, &ycount);
362 
363  if(Xavg >= 0 && Yavg >= 0)
364  {
365  *X = (uint16_t) Xavg;
366  *Y = (uint16_t) Yavg;
367  #if XPT2046_DEBUG & 2
368  printf("X:%4d, Y:%4d, XN:%2d, YN:%d\n",
369  (int)Xavg, (int)Yavg, (int)xcount,(int)ycount);
370  #endif
371  return(i);
372  }
373  }
374  return(0);
375 }
376 
377 
378 #endif
379 
385 int XPT2046_loop;
386 MEMSPACE
388 {
389 
390  int T;
391  XPT2046_loop = 0;
392  while(1)
393  {
394  T = XPT2046_xy_filtered(X, Y);
395  XPT2046_loop += T;
396  if(!T)
397  return(0);
398  if(T >= XPT2046_SAMPLES/2)
399  return(1);
400  }
401 }
402 
403 
407 MEMSPACE
408 void XPT2046_task()
409 {
410  uint16_t X,Y;
411  int T;
412 
413  T = XPT2046_xy_filtered((uint16_t *)&X, (uint16_t *)&Y);
414 
415  // Key debounce state machine
416  switch(xpt2046.state)
417  {
418  // Full init
419  case 0:
420  xpt2046.state = 1;
421  xpt2046.ms = 0;
422  xpt2046.ind = 0;
423  xpt2046.head = 0;
424  xpt2046.tail = 0;
425  // Fall through to state 1
426  case 1:
427  // FIXME this can be a lower count for a button as we are not drawing here
428  if(T) // key is down and noise level is in range
429  {
430  // wait for key down debounce time before taking a sample
431  if(++xpt2046.ms < XPT2046_DEBOUNCE)
432  break;
433 
434  if(xpt2046.ind < XPT2046_EVENTS )
435  {
436  xpt2046.XQ[xpt2046.head] = X;
437  xpt2046.YQ[xpt2046.head] = Y;
438  if(++xpt2046.head >= XPT2046_EVENTS)
439  xpt2046.head = 0;
440  xpt2046.ind++;
441  xpt2046.state = 2;
442  xpt2046.ms = 0;
443  }
444  else
445  {
446  xpt2046.ms = 0;
447  }
448  } // if (T)
449  else // Restart timer and wait for touch debounce time
450  {
451  xpt2046.ms = 0;
452  }
453  break;
454 
455  // Wait for touch release debounce time
456  case 2:
457  // Released ?
458  if(T == 0)
459  {
460  // Debounce release time - valid key depress cycle done
461  if(++xpt2046.ms >= XPT2046_DEBOUNCE)
462  {
463  xpt2046.ms = 0;
464  xpt2046.state = 1;
465  }
466  }
467  else // Still depressed
468  {
469  xpt2046.ms = 0;
470  }
471  break;
472 
473 
474  // Error INIT
475  default:
476  xpt2046.state = 0;
477  break;
478  }
479 }
480 
481 
486 MEMSPACE
487 int XPT2046_key(uint16_t *X, uint16_t *Y)
488 {
489  XPT2046_task();
490  if(xpt2046.ind > 0)
491  {
492  *X = (uint16_t) xpt2046.XQ[xpt2046.tail];
493  *Y = (uint16_t) xpt2046.YQ[xpt2046.tail];
494  if(++xpt2046.tail >= XPT2046_EVENTS)
495  xpt2046.tail = 0;
496  xpt2046.ind--;
497  return(1);
498  }
499  *X = 0;
500  *Y = 0;
501  return(0);
502 }
503 
504 // ===========================================================================
505 
506 //
507 #ifdef ESP8266
508 int __errno;
509 #endif
510 
518 MEMSPACE
519 int sdev(uint16_t *samples, int size, sdev_t *Z)
520 {
521  int i;
522  float val, delta, sum, sqsum;
523 
524  Z->min = ~0;
525  Z->max = 0;
526 
527 // error in sample size ?
528  if(size < 2)
529  return(0);
530 
531  sum = 0.0;
532  for(i=0; i<size ; i++) {
533  val = samples[i];
534  if(Z->min > val)
535  Z->min = val;
536  if(Z->max < val)
537  Z->max = val;
538  sum += val;
539  }
540  Z->mean = sum / (float) size;
541  sqsum = 0.0;
542  for(i=0;i<size;++i) {
543  val = samples[i];
544  if(val < 0 || val > 4095)
545  continue; // reject
546  delta = val - Z->mean;
547  sqsum += (delta * delta);
548  }
549  val = sqsum / (float) (i - 1);
550  Z->sdev = sqrt(val);
551  return(1);
552 }
553 
554 #endif // XPT2046
555 #endif // DISPLAY
MEMSPACE int nearest_run(int *v, int size, int minsamples, int *count)
int ms
Definition: xpt2046.h:55
unsigned short uint16_t
Definition: send.c:18
uint16_t max
Definition: xpt2046.h:75
#define XPT2046_EVENTS
Definition: xpt2046.h:31
int ind
Definition: xpt2046.h:67
MEMSPACE int XPT2046_xy_filtered_test(uint16_t *X, uint16_t *Y)
#define XPT2046_READ_Z1
Definition: xpt2046.h:35
void spi_begin(uint32_t clock, int pin)
SPI chip enable function Function waits for current tranaction to finish before proceeding.
Definition: hal.c:355
Master include file for project Includes all project includes and defines here.
Cordic_T X
Main Cordic routine - used for basic trig and vector rotations We use fixed point numbers...
Definition: cordic.c:102
uint8_t rotation
Definition: ili9341.h:46
#define XPT2046_DEBOUNCE
Definition: xpt2046.h:30
int state
Definition: xpt2046.h:54
MEMSPACE int sdev(uint16_t *samples, int size, sdev_t *Z)
unsigned int uint32_t
Definition: send.c:19
Cordic_T Y
Definition: cordic.c:102
uint16_t XPT2046_read(uint8_t cmd)
MEMSPACE void XPT2046_spi_init(void)
uint16_t YQ[XPT2046_EVENTS+1]
Definition: xpt2046.h:71
#define XPT2046_READ_X
Definition: xpt2046.h:37
void spi_end(uint8_t pin)
SPI chip disable function wait for current tranaction to finish!
Definition: hal.c:388
void chip_select_init(uint8_t pin)
CHIP select HAL.
Definition: hal.c:198
window * tft
Definition: ili9341.c:45
int XPT2046_xy_raw(uint16_t *X, uint16_t *Y)
MEMSPACE uint16_t sum(char *name)
sum of a file with 16bit hex and integer results
Definition: posix_tests.c:626
#define XPT2046_READ_Z2
Definition: xpt2046.h:36
int head
Definition: xpt2046.h:68
Cordic_T Z
Definition: cordic.c:102
int rotation
Definition: xpt2046.h:58
void spi_TXRX_buffer(const uint8_t *data, int count)
SPI write/read buffer.
Definition: hal.c:442
MEMSPACE int XPT2046_xy_filtered(uint16_t *X, uint16_t *Y)
MEMSPACE int XPT2046_key(uint16_t *X, uint16_t *Y)
MEMSPACE void XPT2046_task(void)
uint16_t XQ[XPT2046_EVENTS+1]
Definition: xpt2046.h:70
int tail
Definition: xpt2046.h:69
float mean
Definition: xpt2046.h:76
MEMSPACE void XPT2046_key_flush(void)
#define MEMSPACE
Definition: cpu.h:25
MEMSPACE int printf(const char *format,...)
Definition: ili9341.h:34
float sdev
Definition: xpt2046.h:76
Definition: xpt2046.h:74
ili9341 driver inspired by Adafruit ili9341 code All code in this file has been rewritten by Mike Gor...
#define XPT2046_READ_Y
only need 4 commands for reading position or touch information
Definition: xpt2046.h:34
#define XPT2046_SAMPLES
number of time to read and average results
Definition: xpt2046.h:29
unsigned char uint8_t
Definition: send.c:17
uint16_t min
Definition: xpt2046.h:75