feat: 全量同步 254 个常用的 Arduino 扩展库文件
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
#include <M5Core2.h>
|
||||
|
||||
// M5Touch class
|
||||
|
||||
/* static */ M5Touch* M5Touch::instance;
|
||||
|
||||
M5Touch::M5Touch() {
|
||||
if (!instance) instance = this;
|
||||
}
|
||||
|
||||
void M5Touch::begin() {
|
||||
Wire1.begin(21, 22);
|
||||
pinMode(CST_INT, INPUT);
|
||||
|
||||
// By default, the FT6336 will pulse the INT line for every touch
|
||||
// event. But because it shares the Wire1 TwoWire/I2C with other
|
||||
// devices, we cannot easily create an interrupt service routine to
|
||||
// handle these events. So instead, we set the INT wire to polled mode,
|
||||
// so it simply goes low as long as there is at least one valid touch.
|
||||
ft6336(0xA4, 0x00);
|
||||
|
||||
Serial.print("touch: ");
|
||||
if (interval(DEFAULT_INTERVAL) == DEFAULT_INTERVAL) {
|
||||
Serial.printf("FT6336 ready (fw id 0x%02X rel %d, lib 0x%02X%02X)\n",
|
||||
ft6336(0xA6), ft6336(0xAF), ft6336(0xA1), ft6336(0xA2));
|
||||
} else {
|
||||
Serial.println("ERROR - FT6336 not responding");
|
||||
}
|
||||
}
|
||||
|
||||
bool M5Touch::ispressed() { return (digitalRead(CST_INT) == LOW); }
|
||||
|
||||
// Single register read and write
|
||||
|
||||
uint8_t M5Touch::ft6336(uint8_t reg) {
|
||||
Wire1.beginTransmission((uint8_t)CST_DEVICE_ADDR);
|
||||
Wire1.write(reg);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom((uint8_t)CST_DEVICE_ADDR, uint8_t(1));
|
||||
return Wire1.read();
|
||||
}
|
||||
|
||||
void M5Touch::ft6336(uint8_t reg, uint8_t value) {
|
||||
Wire1.beginTransmission(CST_DEVICE_ADDR);
|
||||
Wire1.write(reg);
|
||||
Wire1.write((uint8_t)value);
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
// Reading size bytes into data
|
||||
void M5Touch::ft6336(uint8_t reg, uint8_t size, uint8_t* data) {
|
||||
Wire1.beginTransmission((uint8_t)CST_DEVICE_ADDR);
|
||||
Wire1.write(reg);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom((uint8_t)CST_DEVICE_ADDR, size);
|
||||
for (uint8_t i = 0; i < size; i++) data[i] = Wire1.read();
|
||||
}
|
||||
|
||||
uint8_t M5Touch::interval(uint8_t ivl) {
|
||||
ft6336(0x88, ivl);
|
||||
return interval();
|
||||
}
|
||||
|
||||
uint8_t M5Touch::interval() {
|
||||
_interval = ft6336(0x88);
|
||||
return _interval;
|
||||
}
|
||||
|
||||
// This is normally called from update()
|
||||
bool M5Touch::read() {
|
||||
// true if real read, not a "come back later"
|
||||
wasRead = false;
|
||||
|
||||
// true is something actually changed on the touchpad
|
||||
changed = false;
|
||||
|
||||
// Return immediately if read() is called more frequently than the
|
||||
// touch sensor updates. This prevents unnecessary I2C reads, and the
|
||||
// data can also get corrupted if reads are too close together.
|
||||
if (millis() - _lastRead < _interval) return false;
|
||||
_lastRead = millis();
|
||||
|
||||
Point p[2];
|
||||
uint8_t pts = 0;
|
||||
uint8_t p0f = 0;
|
||||
if (ispressed()) {
|
||||
uint8_t data[11];
|
||||
ft6336(0x02, 11, data);
|
||||
pts = data[0];
|
||||
if (pts > 2) return false;
|
||||
if (pts) {
|
||||
// Read the data. Never mind trying to read the "weight" and
|
||||
// "size" properties or using the built-in gestures: they
|
||||
// are always set to zero.
|
||||
p0f = (data[3] >> 4) ? 1 : 0;
|
||||
p[0].x = ((data[1] << 8) | data[2]) & 0x0fff;
|
||||
p[0].y = ((data[3] << 8) | data[4]) & 0x0fff;
|
||||
if (p[0].x >= TOUCH_W || p[0].y >= TOUCH_H) return false;
|
||||
if (pts == 2) {
|
||||
p[1].x = ((data[7] << 8) | data[8]) & 0x0fff;
|
||||
p[1].y = ((data[9] << 8) | data[10]) & 0x0fff;
|
||||
if (p[1].x >= TOUCH_W || p[1].y >= TOUCH_H) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TFT
|
||||
p[0].rotate(TFT->rotation);
|
||||
p[1].rotate(TFT->rotation);
|
||||
#endif /* TFT */
|
||||
|
||||
if (p[0] != point[0] || p[1] != point[1]) {
|
||||
changed = true;
|
||||
point[0] = p[0];
|
||||
point[1] = p[1];
|
||||
points = pts;
|
||||
point0finger = p0f;
|
||||
}
|
||||
wasRead = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
Point M5Touch::getPressPoint() {
|
||||
read();
|
||||
if (point[0]) return point[0];
|
||||
return Point(-1, -1); // -1, -1 is old API's definition of invalid
|
||||
}
|
||||
|
||||
void M5Touch::update() { read(); }
|
||||
|
||||
void M5Touch::dump() {
|
||||
uint8_t data[256] = {0};
|
||||
ft6336(0x00, 0x80, data);
|
||||
ft6336(0x80, 0x80, data + 0x80);
|
||||
Serial.printf("\n ");
|
||||
for (uint8_t i = 0; i < 16; i++) Serial.printf(".%1X ", i);
|
||||
Serial.printf("\n");
|
||||
for (uint16_t i = 0; i < 0x100; i++) {
|
||||
if (!(i % 16)) Serial.printf("\n%1X. ", i / 16);
|
||||
Serial.printf("%02X ", data[i]);
|
||||
}
|
||||
Serial.printf("\n\n\n");
|
||||
}
|
||||
|
||||
// HotZone class (for compatibility with older M5Core2 code)
|
||||
|
||||
HotZone::HotZone(int16_t x0_, int16_t y0_, int16_t x1_, int16_t y1_,
|
||||
void (*fun_)() /* = nullptr */
|
||||
)
|
||||
: Zone(x0_, y0_, x1_ - x0_, y1_ - y0_) {
|
||||
fun = fun_;
|
||||
}
|
||||
|
||||
void HotZone::setZone(int16_t x0_, int16_t y0_, int16_t x1_, int16_t y1_,
|
||||
void (*fun_)() /*= nullptr */
|
||||
) {
|
||||
set(x0_, y0_, x1_ - x0_, y1_ - y0_);
|
||||
fun = fun_;
|
||||
}
|
||||
|
||||
bool HotZone::inHotZone(Point& p) { return contains(p); }
|
||||
|
||||
bool HotZone::inHotZoneDoFun(Point& p) {
|
||||
if (contains(p)) {
|
||||
if (fun) fun();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user