forked from afarhan/ubitxv6
-
Notifications
You must be signed in to change notification settings - Fork 11
/
touch.cpp
139 lines (114 loc) · 4.56 KB
/
touch.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "touch.h"
#include <SPI.h>
#include "pin_definitions.h"
#include "settings.h"
constexpr int16_t Z_THRESHOLD = 400;
constexpr uint8_t MSEC_THRESHOLD = 3;//Max sample rate is 125kHz, but we'll limit ourselves conservatively
constexpr uint8_t START_COMMAND = 1 << 7;
constexpr uint8_t CHANNEL_Y = 1 << 4;
constexpr uint8_t CHANNEL_Z1 = 3 << 4;
constexpr uint8_t CHANNEL_Z2 = 4 << 4;
constexpr uint8_t CHANNEL_X = 5 << 4;
constexpr uint8_t CHANNEL_TEMPERATURE = 7 << 4;
constexpr uint8_t USE_8_INSTEAD_OF_12_BIT = 1 << 3;
constexpr uint8_t USE_SINGLE_ENDED_MEASUREMENT = 1 << 2;
constexpr uint8_t POWER_OFF = 0 << 0;
constexpr uint8_t POWER_ADC = 1 << 0;
constexpr uint8_t POWER_REF = 2 << 0;
constexpr uint8_t POWER_ADC_REF = 3 << 0;
constexpr uint16_t MEASURE_X = START_COMMAND | POWER_ADC | CHANNEL_Y;//X and Y channel labelling flip due to screen orientation
constexpr uint16_t MEASURE_Y = START_COMMAND | POWER_ADC | CHANNEL_X;//X and Y channel labelling flip due to screen orientation
constexpr uint16_t MEASURE_Z1 = START_COMMAND | POWER_ADC | CHANNEL_Z1;
constexpr uint16_t MEASURE_Z2 = START_COMMAND | POWER_ADC | CHANNEL_Z2;
constexpr uint8_t RAW_READ_TO_12BIT_VALUE_SHIFT = 3;//16 bits read, zero-padded, but the MSB of the 16 is where the "BUSY" signal is asserted, so only need to shift by 3 instead of 4
uint32_t msraw=0x80000000;
int16_t xraw=0, yraw=0, zraw=0;
constexpr uint8_t rotation = 1;
SPISettings spiSettingsTouch(2000000,MSBFIRST,SPI_MODE0);
int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) {
int16_t da, db, dc;
int16_t reta = 0;
if ( x > y ) da = x - y; else da = y - x;
if ( x > z ) db = x - z; else db = z - x;
if ( z > y ) dc = z - y; else dc = y - z;
if ( da <= db && da <= dc ) reta = (x + y) >> 1;
else if ( db <= da && db <= dc ) reta = (x + z) >> 1;
else reta = (y + z) >> 1; // else if ( dc <= da && dc <= db ) reta = (x + y) >> 1;
return (reta);
}
uint16_t touchReadChannel(uint8_t channel_command){
//We assume that SPI.beginTransaction has already been called, and CS is LOW
SPI.transfer(channel_command);//Throw away any bytes here
const uint16_t tmpH = SPI.transfer(0) & 0x7F;//Leading 0 (during "busy" signal), followed by bits 11-5
const uint16_t tmpL = SPI.transfer(0);//Bits 4-0, followed by 0s
return tmpH << 5 | tmpL >> 3;
}
void touch_update(){
uint32_t now = millis();
if (now - msraw < MSEC_THRESHOLD){
return;
}
SPI.beginTransaction(spiSettingsTouch);
digitalWrite(PIN_TOUCH_CS, LOW);
int16_t z1 = touchReadChannel(MEASURE_Z1);//~0 when not pressed, increases with pressure
int32_t z = z1;
int16_t z2 = touchReadChannel(MEASURE_Z2);//~4095 when not pressed, decreases with pressure
z += (4095 - z2);
//Serial.print(F("z1:"));Serial.print(z1);Serial.print(F(" z2:"));Serial.print(z2);Serial.print(F(" z:"));Serial.println(z);
zraw = z;
if (zraw < Z_THRESHOLD) {//Don't bother reading x/y if we're not being touched
digitalWrite(PIN_TOUCH_CS, HIGH);
SPI.endTransaction();
return;
}
// make 3 x-y measurements
int16_t data[6];
data[0] = touchReadChannel(MEASURE_X);
data[1] = touchReadChannel(MEASURE_Y);
data[2] = touchReadChannel(MEASURE_X);
data[3] = touchReadChannel(MEASURE_Y);
data[4] = touchReadChannel(MEASURE_X);
data[5] = touchReadChannel(MEASURE_Y & ~POWER_ADC_REF);//Turn off sensor
digitalWrite(PIN_TOUCH_CS, HIGH);
SPI.endTransaction();
int16_t x = touch_besttwoavg( data[0], data[2], data[4] );
int16_t y = touch_besttwoavg( data[1], data[3], data[5] );
msraw = now; // good read completed, set wait
switch (rotation) {
case 0:
xraw = 4095 - y;
yraw = x;
break;
case 1:
xraw = x;
yraw = y;
break;
case 2:
xraw = y;
yraw = 4095 - x;
break;
default: // 3
xraw = 4095 - x;
yraw = 4095 - y;
}
}
void initTouch(){
pinMode(PIN_TOUCH_CS, OUTPUT);
digitalWrite(PIN_TOUCH_CS, HIGH);
}
bool readTouch(Point *const touch_point_out){
touch_update();
//Serial.print(F("readTouch found zraw of "));Serial.println(zraw);
if (zraw >= Z_THRESHOLD) {
touch_point_out->x = xraw;
touch_point_out->y = yraw;
//Serial.print(ts_point.x); Serial.print(",");Serial.println(ts_point.y);
return true;
}
return false;
}
void scaleTouch(Point *const touch_point_in_out){
touch_point_in_out->x = ((long)(touch_point_in_out->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX;
touch_point_in_out->y = ((long)(touch_point_in_out->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY;
//Serial.print(p->x); Serial.print(",");Serial.println(p->y);
}