-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Expand file tree
/
Copy pathTouchScreenImpl1.cpp
More file actions
179 lines (161 loc) · 4.77 KB
/
Copy pathTouchScreenImpl1.cpp
File metadata and controls
179 lines (161 loc) · 4.77 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include "TouchScreenImpl1.h"
#include "InputBroker.h"
#include "PowerFSM.h"
#include "configuration.h"
#include "main.h"
#include "modules/ExternalNotificationModule.h"
#include "sleep.h"
#include <cstring>
#ifdef MESHTASTIC_INCLUDE_INKHUD
#include "graphics/niche/InkHUD/InkHUD.h"
#include "graphics/niche/InkHUD/SystemApplet.h"
#endif
#if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
TouchScreenImpl1 *touchScreenImpl1;
// Hardware-interrupt wake on the touch IRQ line. Some touch boards
// either drive this pin differently (RAK14014 already owns this interrupt in TFTDisplay) or
// route it through an IO expander, which can't be used with attachInterrupt().
// use ENABLE_TOUCH_INT to indicate that we should enable the interrupt here.
#if defined(SCREEN_TOUCH_INT) && defined(ENABLE_TOUCH_INT)
// The touch controller pulls SCREEN_TOUCH_INT low when a new touch begins. Wake the polling
// thread immediately so the touch is handled without waiting for the next idle poll. The
// periodic poll in TouchScreenBase::runOnce() remains as a fallback. Mirrors the button
// interrupt handling in ButtonThread/InputBroker.
static void touchScreenInterruptHandler()
{
if (touchScreenImpl1) {
touchScreenImpl1->setIntervalFromNow(0);
runASAP = true;
BaseType_t higherWake = 0;
concurrency::mainDelay.interruptFromISR(&higherWake);
}
}
#endif
TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *))
: TouchScreenBase("touchscreen1", width, height), _getTouch(getTouch)
{
}
void TouchScreenImpl1::init()
{
#if ARCH_PORTDUINO
if (portduino_config.touchscreenModule) {
TouchScreenBase::init(true);
inputBroker->registerSource(this);
attachTouchInterrupt();
} else {
TouchScreenBase::init(false);
}
#elif !HAS_TOUCHSCREEN
TouchScreenBase::init(false);
return;
#else
TouchScreenBase::init(true);
if (inputBroker)
inputBroker->registerSource(this);
attachTouchInterrupt();
#endif
#if defined(ENABLE_TOUCH_INT) && defined(ARCH_ESP32)
// Detach/reattach our interrupt around light sleep, so sleep.cpp can configure the touch
// pin as a wake source without our handler interfering.
lsObserver.observe(¬ifyLightSleep);
lsEndObserver.observe(¬ifyLightSleepEnd);
#endif
}
// Attach the touch-controller IRQ so a new touch wakes the polling thread immediately.
// No-op on boards without a usable touch interrupt line.
void TouchScreenImpl1::attachTouchInterrupt()
{
#ifdef ENABLE_TOUCH_INT
pinMode(SCREEN_TOUCH_INT, INPUT_PULLUP);
attachInterrupt(SCREEN_TOUCH_INT, touchScreenInterruptHandler, FALLING);
LOG_INFO("TouchScreen interrupt attached on pin %d", SCREEN_TOUCH_INT);
#endif
}
#ifdef ARCH_ESP32
// Detach our interrupt before light sleep; sleep.cpp configures its own wake-on-touch.
int TouchScreenImpl1::beforeLightSleep(void *unused)
{
#ifdef ENABLE_TOUCH_INT
detachInterrupt(SCREEN_TOUCH_INT);
#endif
return 0; // Indicates success
}
// Reattach our interrupt after waking from light sleep.
int TouchScreenImpl1::afterLightSleep(esp_sleep_wakeup_cause_t cause)
{
attachTouchInterrupt();
return 0; // Indicates success
}
#endif
bool TouchScreenImpl1::getTouch(int16_t &x, int16_t &y)
{
return _getTouch(&x, &y);
}
bool TouchScreenImpl1::fastTapModeEnabled() const
{
#ifdef MESHTASTIC_INCLUDE_INKHUD
const auto *inkhud = NicheGraphics::InkHUD::InkHUD::getInstance();
if (!inkhud) {
return false;
}
for (auto *sa : inkhud->systemApplets) {
if (!sa || !sa->name) {
continue;
}
if (strcmp(sa->name, "Keyboard") == 0) {
return sa->isForeground();
}
}
#endif
return false;
}
bool TouchScreenImpl1::longPressEnabled() const
{
return !fastTapModeEnabled();
}
/**
* @brief forward touchscreen event
*
* @param event
*
* The touchscreen events are translated to input events and reversed
*/
void TouchScreenImpl1::onEvent(const TouchEvent &event)
{
InputEvent e = {};
e.source = event.source;
e.kbchar = 0;
e.touchX = event.x;
e.touchY = event.y;
switch (event.touchEvent) {
case TOUCH_ACTION_LEFT: {
e.inputEvent = INPUT_BROKER_LEFT;
break;
}
case TOUCH_ACTION_RIGHT: {
e.inputEvent = INPUT_BROKER_RIGHT;
break;
}
case TOUCH_ACTION_UP: {
e.inputEvent = INPUT_BROKER_UP;
break;
}
case TOUCH_ACTION_DOWN: {
e.inputEvent = INPUT_BROKER_DOWN;
break;
}
case TOUCH_ACTION_LONG_PRESS: {
e.inputEvent = INPUT_BROKER_SELECT;
break;
}
case TOUCH_ACTION_TAP: {
e.inputEvent = INPUT_BROKER_USER_PRESS;
break;
}
default:
return;
}
this->notifyObservers(&e);
}