277 lines
5.3 KiB
C++
277 lines
5.3 KiB
C++
#include <Wire.h>
|
|
#include <Adafruit_RGBLCDShield.h>
|
|
#include <utility/Adafruit_MCP23017.h>
|
|
#include "Keyboard.h"
|
|
#include "Mouse.h"
|
|
|
|
// The shield uses the I2C SCL and SDA pins. On classic Arduinos
|
|
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
|
|
// However, you can connect other I2C sensors to the I2C bus and share
|
|
// the I2C bus.
|
|
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
|
|
|
|
// These #defines make it easy to set the backlight color
|
|
#define RED 0x1
|
|
#define YELLOW 0x3
|
|
#define GREEN 0x2
|
|
#define TEAL 0x6
|
|
#define BLUE 0x4
|
|
#define VIOLET 0x5
|
|
#define WHITE 0x7
|
|
|
|
|
|
unsigned long lcdTimeout = 1500;
|
|
unsigned long lcdLastSet = 0;
|
|
|
|
unsigned long debounceDelay = 50;
|
|
|
|
typedef struct
|
|
{
|
|
unsigned long lastDebounceTime = 0;
|
|
bool state = false;
|
|
bool lastState = false;
|
|
} DebounceButton;
|
|
|
|
DebounceButton up, down, left, right, select;
|
|
|
|
typedef enum {
|
|
MODE_LEFT_CLICK,
|
|
MODE_WALKING,
|
|
MODE_COUNT
|
|
} Mode;
|
|
Mode currMode = MODE_LEFT_CLICK;
|
|
|
|
char *modeNames[] = {
|
|
"Click mode ",
|
|
"Keyboard mode "
|
|
};
|
|
|
|
int modeColors[] = {
|
|
WHITE,
|
|
YELLOW
|
|
};
|
|
|
|
extern void clickActivate();
|
|
extern void clickSlower();
|
|
extern void clickFaster();
|
|
|
|
extern void walkForward();
|
|
extern void walkBackward();
|
|
extern void holdShift();
|
|
|
|
void (*upButtonFuncs[])() = { NULL, walkForward };
|
|
void (*downButtonFuncs[])() = { clickActivate, walkBackward };
|
|
void (*leftButtonFuncs[])() = { clickSlower, holdShift };
|
|
void (*rightButtonFuncs[])() = { clickFaster, NULL };
|
|
|
|
extern void cancelClicking();
|
|
extern void cancelWalking();
|
|
|
|
void (*cancelModeFuncs[])() = { cancelClicking, cancelWalking };
|
|
|
|
bool doClicking = false;
|
|
unsigned long lastClickTime = 0;
|
|
int clickColor = 0;
|
|
|
|
bool doWalking = false;
|
|
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
|
|
// set columns and rows:
|
|
lcd.begin(16, 2);
|
|
|
|
Mouse.begin();
|
|
Keyboard.begin();
|
|
|
|
lcd.print("AutoClicker 3000");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("For Jasper");
|
|
lcd.setBacklight(VIOLET);
|
|
|
|
lcdLastSet = millis();
|
|
}
|
|
|
|
void debounce(DebounceButton &b, bool reading) {
|
|
if ((millis() - b.lastDebounceTime) > debounceDelay) {
|
|
b.lastState = b.state;
|
|
b.state = reading;
|
|
b.lastDebounceTime = millis();
|
|
}
|
|
}
|
|
|
|
bool triggered(DebounceButton &b) {
|
|
return b.state and !b.lastState;
|
|
}
|
|
|
|
int clickDelay = 100; // millis
|
|
int delayChange = 10; // millis
|
|
|
|
void loop() {
|
|
uint8_t buttons = lcd.readButtons();
|
|
|
|
debounce(up, buttons & BUTTON_UP);
|
|
debounce(down, buttons & BUTTON_DOWN);
|
|
debounce(left, buttons & BUTTON_LEFT);
|
|
debounce(right, buttons & BUTTON_RIGHT);
|
|
debounce(select, buttons & BUTTON_SELECT);
|
|
|
|
if (buttons) {
|
|
if (triggered(up)) {
|
|
if (upButtonFuncs[currMode] != NULL) {
|
|
upButtonFuncs[currMode]();
|
|
}
|
|
}
|
|
|
|
if (triggered(down)) {
|
|
if (downButtonFuncs[currMode] != NULL) {
|
|
downButtonFuncs[currMode]();
|
|
}
|
|
}
|
|
|
|
if (triggered(left)) {
|
|
if (leftButtonFuncs[currMode] != NULL) {
|
|
leftButtonFuncs[currMode]();
|
|
}
|
|
}
|
|
|
|
if (triggered(right)) {
|
|
if (rightButtonFuncs[currMode] != NULL) {
|
|
rightButtonFuncs[currMode]();
|
|
}
|
|
}
|
|
|
|
if (triggered(select)) {
|
|
if (cancelModeFuncs[currMode] != NULL) {
|
|
cancelModeFuncs[currMode]();
|
|
}
|
|
changeMode();
|
|
}
|
|
}
|
|
|
|
// TODO make into mode-specific action func
|
|
if (doClicking) {
|
|
unsigned long time = millis();
|
|
if ((unsigned long)(time - lastClickTime) >= clickDelay) {
|
|
if (clickColor == RED) {
|
|
clickColor = WHITE;
|
|
} else {
|
|
clickColor = RED;
|
|
}
|
|
lcd.setBacklight(clickColor);
|
|
Mouse.click(MOUSE_LEFT);
|
|
lastClickTime = time;
|
|
}
|
|
}
|
|
|
|
// clear second lcd line after a while
|
|
if (lcdLastSet > 0 && millis() > lcdLastSet + lcdTimeout) {
|
|
lcd.setCursor(0, 0);
|
|
lcd.print(modeNames[currMode]);
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(" ");
|
|
lcdLastSet = 0;
|
|
}
|
|
}
|
|
|
|
void changeMode() {
|
|
currMode = (currMode + 1) % MODE_COUNT;
|
|
lcd.setCursor(0, 0);
|
|
lcd.print(modeNames[currMode]);
|
|
lcd.setBacklight(modeColors[currMode]);
|
|
}
|
|
|
|
void flashLCD(char* msg) {
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(msg);
|
|
lcdLastSet = millis();
|
|
}
|
|
|
|
void updateLCD(char* msg) {
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(msg);
|
|
lcdLastSet = 0;
|
|
}
|
|
|
|
void clearLCD() {
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(" ");
|
|
lcdLastSet = 0;
|
|
}
|
|
|
|
// mode functions
|
|
|
|
void clickActivate() {
|
|
doClicking = !doClicking;
|
|
|
|
lcd.setBacklight(WHITE);
|
|
if (doClicking) {
|
|
flashLCD("Start clicking ");
|
|
} else {
|
|
flashLCD("Stop clicking ");
|
|
}
|
|
}
|
|
|
|
void clickSlower() {
|
|
if (clickDelay < 1000) {
|
|
clickDelay += delayChange;
|
|
}
|
|
flashLCD("Slower ");
|
|
}
|
|
|
|
void clickFaster() {
|
|
if (clickDelay > 50) {
|
|
clickDelay -= delayChange;
|
|
}
|
|
flashLCD("Faster ");
|
|
}
|
|
|
|
void cancelClicking() {
|
|
doClicking = false;
|
|
}
|
|
|
|
//
|
|
// walking mode
|
|
//
|
|
void walkForward() {
|
|
if (!doWalking) {
|
|
walk('w', "Forward ");
|
|
} else {
|
|
cancelWalking();
|
|
clearLCD();
|
|
}
|
|
}
|
|
|
|
void walkBackward() {
|
|
if (!doWalking) {
|
|
walk('s', "Backward ");
|
|
} else {
|
|
cancelWalking();
|
|
clearLCD();
|
|
}
|
|
}
|
|
|
|
void holdShift() {
|
|
if (!doWalking) {
|
|
walk(KEY_LEFT_SHIFT, "Shift ");
|
|
} else {
|
|
cancelWalking();
|
|
clearLCD();
|
|
}
|
|
}
|
|
|
|
void walk(char key, char* msg) {
|
|
cancelWalking();
|
|
|
|
Keyboard.press(key);
|
|
doWalking = true;
|
|
|
|
updateLCD(msg);
|
|
}
|
|
|
|
void cancelWalking() {
|
|
doWalking = false;
|
|
Keyboard.releaseAll();
|
|
}
|