-
-
Save erictroebs/3e6ca8aa2b9ed06e0b5527fd38dd2c2f to your computer and use it in GitHub Desktop.
#include "Touch.h" | |
#if defined(_USING_HID) | |
#define CONTACT_COUNT_MAXIMUM 10 | |
#define REPORTID_TOUCH 0x04 | |
#define LSB(v) ((v >> 8) & 0xff) | |
#define MSB(v) (v & 0xff) | |
static const uint8_t _hidReportDescriptor[] PROGMEM = { | |
0x05, 0x0D, // USAGE_PAGE(Digitizers) | |
0x09, 0x04, // USAGE (Touch Screen) | |
0xA1, 0x01, // COLLECTION(Application) | |
0x85, REPORTID_TOUCH, // REPORT_ID (Touch) | |
// define the maximum amount of fingers that the device supports | |
0x09, 0x55, // USAGE (Contact Count Maximum) | |
0x25, CONTACT_COUNT_MAXIMUM, // LOGICAL_MAXIMUM (CONTACT_COUNT_MAXIMUM) | |
0xB1, 0x02, // FEATURE (Data,Var,Abs) | |
// define the actual amount of fingers that are concurrently touching the screen | |
0x09, 0x54, // USAGE (Contact count) | |
0x95, 0x01, // REPORT_COUNT(1) | |
0x75, 0x08, // REPORT_SIZE (8) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
// declare a finger collection | |
0x09, 0x22, // USAGE (Finger) | |
0xA1, 0x02, // COLLECTION (Logical) | |
// declare an identifier for the finger | |
0x09, 0x51, // USAGE (Contact Identifier) | |
0x75, 0x08, // REPORT_SIZE (8) | |
0x95, 0x01, // REPORT_COUNT (1) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
// declare Tip Switch and In Range | |
0x09, 0x42, // USAGE (Tip Switch) | |
0x09, 0x32, // USAGE (In Range) | |
0x15, 0x00, // LOGICAL_MINIMUM (0) | |
0x25, 0x01, // LOGICAL_MAXIMUM (1) | |
0x75, 0x01, // REPORT_SIZE (1) | |
0x95, 0x02, // REPORT_COUNT(2) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
// declare the remaining 6 bits of the first data byte as constant -> the driver will ignore them | |
0x95, 0x06, // REPORT_COUNT (6) | |
0x81, 0x03, // INPUT (Cnst,Ary,Abs) | |
// define absolute X and Y coordinates of 16 bit each (percent values multiplied with 100) | |
0x05, 0x01, // USAGE_PAGE (Generic Desktop) | |
0x09, 0x30, // Usage (X) | |
0x09, 0x31, // Usage (Y) | |
0x16, 0x00, 0x00, // Logical Minimum (0) | |
0x26, 0x10, 0x27, // Logical Maximum (10000) | |
0x36, 0x00, 0x00, // Physical Minimum (0) | |
0x46, 0x10, 0x27, // Physical Maximum (10000) | |
0x66, 0x00, 0x00, // UNIT (None) | |
0x75, 0x10, // Report Size (16), | |
0x95, 0x02, // Report Count (2), | |
0x81, 0x02, // Input (Data,Var,Abs) | |
0xC0, // END_COLLECTION | |
0xC0 // END_COLLECTION | |
// with this declaration a data packet must be sent as: | |
// byte 1 -> "contact count" (always == 1) | |
// byte 2 -> "contact identifier" (any value) | |
// byte 3 -> "Tip Switch" state (bit 0 = Tip Switch up/down, bit 1 = In Range) | |
// byte 4,5 -> absolute X coordinate (0...10000) | |
// byte 6,7 -> absolute Y coordinate (0...10000) | |
}; | |
typedef struct Finger { | |
int contact; | |
int16_t x; | |
int16_t y; | |
} Finger; | |
Finger fingers[CONTACT_COUNT_MAXIMUM]; | |
Touch_::Touch_() { | |
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); | |
HID().AppendDescriptor(&node); | |
for (int i = 0; i < CONTACT_COUNT_MAXIMUM; i++) { | |
fingers[i].contact = 0; | |
fingers[i].x = 0; | |
fingers[i].y = 0; | |
} | |
} | |
void Touch_::begin(void) { | |
} | |
void Touch_::end(void) { | |
} | |
void Touch_::send(uint8_t identifier, uint8_t touch, int16_t x, int16_t y) { | |
// calculate current contact count | |
uint8_t contact = 0; | |
for (int i = 0; i < CONTACT_COUNT_MAXIMUM; i++) { | |
if (fingers[i].contact) { | |
contact += 1; | |
} | |
} | |
// create data array | |
uint8_t data[] = { | |
contact, // contact count | |
identifier, // contact identifier | |
touch, // finger touches display | |
MSB(x), LSB(x), // x | |
MSB(y), LSB(y) // y | |
}; | |
// send packet | |
HID().SendReport(REPORTID_TOUCH, data, 7); | |
} | |
void Touch_::moveFingerTo(uint8_t identifier, int16_t x, int16_t y) { | |
// change finger record | |
fingers[identifier].contact = 1; | |
fingers[identifier].x = x; | |
fingers[identifier].y = y; | |
// send update | |
send(identifier, 1, x, y); | |
} | |
void Touch_::releaseFinger(uint8_t identifier) { | |
// change finger record | |
fingers[identifier].contact = 0; | |
fingers[identifier].x = 0; | |
fingers[identifier].y = 0; | |
// send update | |
send(identifier, 0, 0, 0); | |
} | |
Touch_ Touch; | |
#endif |
#ifndef Touch_h | |
#define Touch_h | |
#include "HID.h" | |
#if !defined(_USING_HID) | |
#warning "Using legacy HID core (non pluggable)" | |
#else | |
class Touch_ { | |
private: | |
void send(uint8_t identifier, uint8_t touch, int16_t x, int16_t y); | |
public: | |
Touch_(void); | |
void begin(void); | |
void end(void); | |
void moveFingerTo(uint8_t finger, int16_t x, int16_t y); | |
void releaseFinger(uint8_t finger); | |
}; | |
extern Touch_ Touch; | |
#endif | |
#endif |
#define BUTTON 2 | |
#include "Touch.h" | |
void setup() { | |
// initialize touch | |
Touch.begin(); | |
// setup pins | |
pinMode(BUTTON, INPUT_PULLUP); | |
} | |
void loop() { | |
if (digitalRead(BUTTON) == LOW) { | |
int16_t x = 5000; | |
int16_t y = 5000; | |
for (; x <= 6000; x+=4) { | |
for (int i = 0; i < 10; i++) { | |
Touch.moveFingerTo(i, x + i * 100, y + i * 100); | |
} | |
} | |
for (; y <= 6000; y+=4) { | |
for (int i = 0; i < 10; i++) { | |
Touch.moveFingerTo(i, x + i * 100, y + i * 100); | |
} | |
} | |
for (; x >= 5000; x-=4) { | |
for (int i = 0; i < 10; i++) { | |
Touch.moveFingerTo(i, x + i * 100, y + i * 100); | |
} | |
} | |
for (; y >= 5000; y-=4) { | |
for (int i = 0; i < 10; i++) { | |
Touch.moveFingerTo(i, x + i * 100, y + i * 100); | |
} | |
} | |
for (int i = 0; i < 10; i++) { | |
Touch.releaseFinger(i); | |
} | |
} | |
} |
Work perfectly with an arduino leonardo (your arduino must have a USB chip (32U4) that can appear as a keyboard or a mouse).
Don't forget to connect BUTTON (2) to ground. --> if (digitalRead(BUTTON) == LOW)
Hi there! It's not working on Android 7.1 neither macOS, any ideas why?
@sobrinho Sorry for the late reply: As @francoisnicolas has mentioned, you have to connect a button to pin 2 and ground. I would not recommend to use the script without a button! Otherwise it could be difficult to flash another sketch from the PC while the Arduino is firing touchscreen input commands.
If this does not work for you, I'm afraid I can not help you. I tested the script with a newer version of Android (probably 11), Windows 10 and Linux Mint, but I do neither have access to MacOS nor such an old version of Android.
It has been a long time now, I'm not in the project anymore. Thanks anyways! :)
Hi there! It's not working on Android 7.1 neither macOS, any ideas why?