113 lines
3.5 KiB
C++
113 lines
3.5 KiB
C++
|
#include "drivers/Cst816s.h"
|
||
|
#include <SDL2/SDL.h>
|
||
|
#include <libraries/log/nrf_log.h>
|
||
|
#include <cmath>
|
||
|
|
||
|
using namespace Pinetime::Drivers;
|
||
|
|
||
|
/* References :
|
||
|
* This implementation is based on this article :
|
||
|
* https://medium.com/@ly.lee/building-a-rust-driver-for-pinetimes-touch-controller-cbc1a5d5d3e9 Touch panel datasheet (weird chinese
|
||
|
* translation) : https://wiki.pine64.org/images/5/51/CST816S%E6%95%B0%E6%8D%AE%E6%89%8B%E5%86%8CV1.1.en.pdf
|
||
|
*
|
||
|
* TODO : we need a complete datasheet and protocol reference!
|
||
|
* */
|
||
|
|
||
|
//Cst816S::Cst816S(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, twiAddress {twiAddress} {
|
||
|
//}
|
||
|
Cst816S::Cst816S() {
|
||
|
}
|
||
|
|
||
|
bool Cst816S::Init() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
Cst816S::TouchInfos Cst816S::GetTouchInfo() {
|
||
|
int x, y;
|
||
|
uint32_t buttons = SDL_GetMouseState(&x, &y);
|
||
|
|
||
|
Cst816S::TouchInfos info;
|
||
|
info.x = x;
|
||
|
info.y = y;
|
||
|
info.touching = (buttons & SDL_BUTTON_LMASK) != 0;
|
||
|
//info.gesture = gesture;
|
||
|
info.isValid = x > 0 && x <= maxX && y > 0 && y <= maxY;
|
||
|
if(info.isValid) {
|
||
|
if(!is_pressed && info.touching) {
|
||
|
// start klick
|
||
|
pressed_since = std::chrono::steady_clock::now();
|
||
|
is_pressed = true;
|
||
|
is_long_press = false;
|
||
|
is_swipe = false;
|
||
|
is_stationary = true;
|
||
|
x_start = info.x;
|
||
|
y_start = info.y;
|
||
|
} else if(is_pressed && info.touching) {
|
||
|
// is it long press?
|
||
|
if (is_stationary) { // check if while touching we moved away from the start coordinates
|
||
|
double x_diff = static_cast<double>(info.x) - x_start;
|
||
|
double y_diff = static_cast<double>(info.y) - y_start;
|
||
|
double norm = hypot(x_diff, y_diff);
|
||
|
if(norm > 20) { // we moved out of start area
|
||
|
is_stationary = false;
|
||
|
}
|
||
|
}
|
||
|
if (!is_long_press && !is_swipe) { // check for long-press only if it's not yet a long-press and didn't move
|
||
|
std::chrono::duration<double> press_duration = std::chrono::steady_clock::now() - pressed_since;
|
||
|
if(is_stationary && press_duration.count() > 1.0) {
|
||
|
// longer than 1 second pressed, then it is long-press
|
||
|
is_long_press = true;
|
||
|
info.gesture = Gestures::LongPress;
|
||
|
} else if(!is_stationary) {
|
||
|
// moved mouse fast enough to not be a long-press
|
||
|
is_swipe = true;
|
||
|
double x_diff = static_cast<double>(info.x) - x_start;
|
||
|
double y_diff = static_cast<double>(info.y) - y_start;
|
||
|
if (fabs(x_diff) > fabs(y_diff)) {
|
||
|
// x-swipe
|
||
|
if (x_diff < 0) {
|
||
|
info.gesture = Gestures::SlideLeft;
|
||
|
} else {
|
||
|
info.gesture = Gestures::SlideRight;
|
||
|
}
|
||
|
} else {
|
||
|
// y-swipe
|
||
|
if (y_diff < 0) {
|
||
|
info.gesture = Gestures::SlideUp;
|
||
|
} else {
|
||
|
info.gesture = Gestures::SlideDown;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else if(is_pressed && !info.touching) {
|
||
|
// end klick
|
||
|
is_pressed = false;
|
||
|
|
||
|
double x_diff = static_cast<double>(info.x) - x_start;
|
||
|
double y_diff = static_cast<double>(info.y) - y_start;
|
||
|
double norm = hypot(x_diff, y_diff);
|
||
|
if(norm < 20) {
|
||
|
if(is_stationary && !is_long_press && !is_swipe) {
|
||
|
// no swipe with less than 5 pixel mouse movement
|
||
|
info.gesture = Gestures::SingleTap;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return info;
|
||
|
}
|
||
|
|
||
|
void Cst816S::Sleep() {
|
||
|
NRF_LOG_INFO("[TOUCHPANEL] Sleep");
|
||
|
}
|
||
|
|
||
|
void Cst816S::Wakeup() {
|
||
|
Init();
|
||
|
NRF_LOG_INFO("[TOUCHPANEL] Wakeup");
|
||
|
}
|
||
|
|
||
|
bool Cst816S::CheckDeviceIds() {
|
||
|
return chipId == 0xb4 && vendorId == 0 && fwVersion == 1;
|
||
|
}
|