/* Klikimouse5 aneb objects forever! + RX/TX LEDs 3 tlacitka a LED+330 Ohm odpor proti zemi Macros for Mouse and Keyboard (ArduinoMicro) Based on: ButtonMouseControl For Leonardo and Due boards only. http://www.arduino.cc/en/Tutorial/ButtonMouseControl https://www.arduino.cc/en/Tutorial/KeyboardAndMouseControl */ #include #include // set pin numbers for the buttons and led: const int button_B = 4; const int button_C = 3; const int button_A = 2; const int led = 8; // led proti GND const int RXled = 17; // led proti VCC const int TXled = 30; // led proti VCC const int C_led = 10; // led proti GND #define UNUSED(x) (void)(x) #define FAST_MOUSE 25 #define SLOW_MOUSE 1000 #define T_RUNC 80 #define T_RUN 128 #define T_CLIMBC 96 #define T_CLIMB1 900 #define T_CLIMB2 250 #define MOUSE_STEP_MAX 125 class Point { // {{{ int x; int y }; // Beware, Mouse can move only -128..127 public: int x; int y; Point():x(0),y(0){}; // zero constructor Point(const Point &cp):x(cp.x),y(cp.y) {}; // copy constructor Point(int _x, int _y):x(_x),y(_y) {}; // from int bool isZero() {return (x==0 && y==0);}; void set(int _x, int _y) {x=_x;y=_y;}; void set(const Point &val) {x=val.x;y=val.y;}; void add(const Point &val) {x+=val.x;y+=val.y;}; void sub(const Point &val) {x-=val.x;y-=val.y;}; void negate() {x=-x;y=-y;}; void negX() {x=-x;}; void negY() {y=-y;}; void clipBy(int val) { // {{{ if val <0 set (0,0) if (val <0) val=0; x=(x>=0)?min(x,val):max(x,-val); y=(y>=0)?min(y,val):max(y,-val); }; // }}} }; // }}} Point DFS(2*275, 2*342); // DAGGERFALL Full_Screen Point DFS2(275, 342); // DAGGERFALL Full_Screen / 2 = Center Point DFS4(275/2, 342/2); // DAGGERFALL Full_Screen / 4 = moves Point Mouse_at(0,0); // Supposed position of mouse, updated by MouseMoveHere, could/should be set to (0,0) at start of any sequence of more movements Point tgt; // temp variable for target of moving bool MouseMoveHere( Point &tgt ) { // {{{ RELATIVE, TRUE=target reached, tgt=={0,0}; MODIFIES tgt,Mouse_at; Move mouse tovard tgt by moving MOUSE_STEP_MAX on each axe max : Point here={1234,-321}; while (!MouseMoveHere(here)){}; if (here.x==0 && here.y==0) {print("OK");}; if (tgt.isZero()) return true; Point step(tgt); step.clipBy(MOUSE_STEP_MAX); tgt.sub(step); Mouse_at.add(step); //Serial.print(step.x);Serial.print(",");Serial.print(step.y);Serial.print(" => "); //Serial.print(tgt.x);Serial.print(",");Serial.print(tgt.y);Serial.print(" => "); //Serial.print(Mouse_at.x);Serial.print(",");Serial.print(Mouse_at.y);Serial.println(); Mouse.move(step.x,step.y); return tgt.isZero(); }; //}}} class Base{ // {{{ public: virtual void start(){ stop_me=false;}; // initialise class for next round of cycles virtual void restart(){ stop();}; // class button was pressed again, maybe stop it? virtual void stop(){ stop_me=true;}; // prepare class for finishing as soon as possible virtual unsigned long long pause(unsigned long x){ UNUSED(x); return 1;}; // pause ms before next cycle, 0..not changed; x=current internal state (nonzero) virtual unsigned long next(unsigned long x){ UNUSED(x); return 0;}; // next internal state; x=current internal state (nonzero) protected: bool stop_me; // true = finish as soon as possible }; // }}} class Blink : public Base { // {{{ public: virtual void start(){ stop_me=false; count=0;}; virtual void stop(){ stop_me=true; count=0;}; virtual unsigned long long pause(unsigned long x){ UNUSED(x); return 100;}; virtual unsigned long next(unsigned long x){ // {{{ if (x == 1) return 2; if (stop_me) x=0; else if (!count) x=0; else {--count; x=1;}; return x; }; // }}} void set_count(byte x){ if (x) count=x-1; else count=0;}; private: byte count; }; // }}} /* {{{ FAPCEO // {{{ ROUTES #define ROUTES 5 struct T_routes { Point go_there; long clicks; int wait; }; T_routes routes[ROUTES] = { { Point(800,0), 10, 0 }, // 11->case { Point(-200,150), 1, 0 }, // case->floor { Point(-600,-150), 1, 0 }, // floor->11 { Point(800,400), 2, 0 }, // 11->upgrade { Point(-800,-400), 20*60-14, 0 }, // and back to 11 (~60 sec, -14 = other clicks) }; // }}} class FastClickLearn : public Base { // {{{ 20 clicku/sec, ROUTE: 1 min fast click; 11->case; 10 click; case-> floor; click; floor -> 11; click; 11-> upgrade; click; upgrade ->11 public: virtual void start(){ stop_me=false; Mouse_at.set(0,0); route_at=0; }; virtual unsigned long long pause(unsigned long x){ UNUSED(x); return 25;}; virtual unsigned long next(unsigned long x){ // {{{ T_routes *r; // temp if (route_at>ROUTES) stop_me=true; // ERROR if (stop_me) {x=0; Mouse.release(MOUSE_LEFT); tgt.set(Mouse_at); tgt.negate(); while (!MouseMoveHere(tgt)){}; return 0;} switch (x) { case 1: ++x; r=&routes[route_at]; wait=r->wait*4; clicks=r->clicks; tgt.set(r->go_there); while (!MouseMoveHere(tgt)){}; // Move to current target // break; // fall thru !!! case 2: ++x; if (--clicks<0) { ++x; } else { Mouse.press(MOUSE_LEFT); }; break; case 3: (clicks >0)? --x:++x; Mouse.release(MOUSE_LEFT); break; case 4: if (--wait <0) ++x; else break; // if wait <=0 fall thru !!! case 5: ++route_at; if (route_at >=ROUTES) route_at=0; x=1; break; default: x=0;break; }; return x; }; // }}} // case 2: MouseMoveHere(tgt);if (tgt.isZero()) ++x; break; // Move to next target private: unsigned int route_at; int wait; long clicks; }; // }}} }}} */ class Recast : public Base { // {{{ public: virtual void start(){ stop_me=false; count=20;}; virtual void restart(){ count+=20;}; virtual void stop(){ stop_me=true; count=0;}; virtual unsigned long long pause(unsigned long x){ UNUSED(x); return 70;}; virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: ++x;Keyboard.press(KEY_END);break; case 2: ++x;Keyboard.release(KEY_END);break; case 3: ++x;Mouse.press(MOUSE_LEFT);break; case 4: if (stop_me) x=0; else if (!count) x=0; else {--count; x=1;} Mouse.release(MOUSE_LEFT); break; default: x=0;break; } return x; }; // }}} private: byte count; }; // }}} class ClickYes : public Base { // {{{ public: virtual void start(){ stop_me=false; count=40;}; virtual void restart(){ count=+40;}; virtual void stop(){ stop_me=true; count=0;}; virtual unsigned long long pause(unsigned long x){ UNUSED(x); return FAST_MOUSE;}; virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: ++x;Mouse.press(MOUSE_LEFT);break; case 2: ++x;Mouse.release(MOUSE_LEFT);break; case 3: ++x;Keyboard.press('y');break; case 4: if (stop_me) x=0; else if (!count) x=0; else {--count; x=1;} Keyboard.release('y'); break; default: x=0;break; } return x; }; // }}} private: byte count; }; // }}} class Relearn : public Base { // {{{ Rest / Loiter / 3 hours / Enter } x 3 + Center / click / Training public: virtual unsigned long long pause(unsigned long x){ // {{{ unsigned long long p; switch (x) { case 15: case 115: case 215: p=6000;break; // 6sec = 3 hours countdown case 1: case 101: case 201: case 5: case 105: case 205: case 9: case 109: case 209: case 221: case 223: case 220: case 222: case 224: p=60;break; // time to actualise mouse case 6: case 106: case 206: p=FAST_MOUSE+2;break; // longer click on camp case 7: case 107: case 207: case 18: case 118: case 218: case 219: p=200;break; // time to actualise mouse - Trainer screen is slow default: p=FAST_MOUSE;break; }; return p; }; // }}} virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: case 101: case 201: case 2: case 102: case 202: case 3: case 103: case 203: ++x;break; case 4: case 104: case 204: ++x;tgt.set(DFS); while (!MouseMoveHere(tgt)){};break; // ++x;Mouse.move(127,127,0);break; // to right down case 5: case 105: case 205: ++x; // Mouse.move(-120,-50);break; // to Camp case 6: case 106: case 206: ++x;Keyboard.press('r');break; // Mouse.click() is too fast, need press/release (Rest) case 7: case 107: case 207: ++x;Keyboard.release('r');break; case 8: case 108: case 208: ++x;tgt.set(-DFS2.x/2,-1.25*DFS2.y); while (!MouseMoveHere(tgt)){};break; // Mouse is NOT accelerated over long fast moves (To Loiter) case 9: case 109: case 209: ++x;break; // Mouse.move(0,-70,0);break; case 10: case 110: case 210: ++x;Mouse.press(MOUSE_LEFT);break; case 11: case 111: case 211: ++x;Mouse.release(MOUSE_LEFT);break; case 12: case 112: case 212: ++x;Keyboard.press('3');break; // 3 hours case 13: case 113: case 213: ++x;Keyboard.release('3');break; case 14: case 114: case 214: ++x;Keyboard.press(KEY_RETURN);break; case 15: case 115: case 215: ++x;Keyboard.release(KEY_RETURN);break; // wait here // waiting for 3 hour countdown case 16: case 116: case 216: ++x;Keyboard.press(KEY_RETURN);break; case 17: case 117: case 217: ++x;Keyboard.release(KEY_RETURN);break; // x3 case 18: case 118: case 218: ++x;break; // 218->219 to Trainer; else back and again case 19: case 119: ++x;tgt.set(60,300); while (!MouseMoveHere(tgt)){};break; // Mouse is NOT accelerated over long fast moves (Back To Loiter) case 20: case 120: ++x;break; // Mouse.move(0,120,0);break; case 21: case 121: x += (101-21); break; // loop: 23->101, 123->201 // To Trainer case 219: ++x;tgt.set(DFS);while (!MouseMoveHere(tgt)){};break; // click Trainer case 220: ++x;tgt.set(-DFS2.x,-DFS2.y-78);while (!MouseMoveHere(tgt)){}; Mouse.press(MOUSE_LEFT);break; case 221: ++x;Mouse.release(MOUSE_LEFT);break; // Train? case 222: ++x;Mouse.press(MOUSE_LEFT);break; case 223: ++x;Mouse.release(MOUSE_LEFT);break; // yes case 224: ++x;Keyboard.press('y');break; case 225: ++x;Keyboard.release('y');break; // default: x=0;break; } return x; }; // }}} }; // }}} class Skills : public Base { // {{{ Open minor skills tab public: virtual unsigned long long pause(unsigned long x){ UNUSED(x); return FAST_MOUSE;}; virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: case 2: case 3: case 4: ++x;tgt.set(DFS);tgt.negX();tgt.add(tgt); while (!MouseMoveHere(tgt)){}; break; case 5: ++x;Mouse.move(20,-20,0);break; case 6: ++x;break; case 7: ++x;Mouse.press(MOUSE_LEFT);break; // Mouse.click() is too fast, need press/release case 8: ++x;Mouse.release(MOUSE_LEFT);break; case 9: ++x;break; case 10: ++x;Mouse.move(40,-75,0);break; // Mouse is accelerated over long fast moves case 11: ++x;Mouse.press(MOUSE_LEFT);break; case 12: ++x;Mouse.release(MOUSE_LEFT);break; default: x=0;break; }; return x; }; // }}} }; // }}} class Swing : public Base { // {{{ public: virtual void start(){ stop_me=false; count=20;}; virtual void restart(){ count+=20;}; virtual void stop(){ stop_me=true; count=0;}; virtual unsigned long long pause(unsigned long x){ if ((x ==4)) return 1.5*SLOW_MOUSE; else return FAST_MOUSE;}; virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: ++x;tgt.set(DFS);tgt.negate(); while (!MouseMoveHere(tgt)){}; break; case 2: ++x;tgt.set(DFS2.x,DFS4.y); while (!MouseMoveHere(tgt)){}; break; case 3: ++x;Mouse.press(MOUSE_RIGHT);break; case 4: ++x;tgt.set(0,DFS2.x/2); while (!MouseMoveHere(tgt)){}; break; case 5: ++x;Mouse.release(MOUSE_RIGHT);break; case 6: ++x;break; case 7: if (stop_me) x=0; else if (count<0) {x=0;count=0;} else {--count; x=1;}; break; default: x=0;break; }; return x; }; // }}} private: int count; }; // }}} class T_run : public Base { // {{{ public: virtual void start(){ stop_me=false; count+=T_RUNC;}; virtual void stop(){ stop_me=true; count=0;}; virtual unsigned long long pause(unsigned long x){ UNUSED(x); return T_RUN;}; virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: ++x;Keyboard.press(KEY_UP_ARROW);break; case 2: ++x;Keyboard.press('p');break; case 3: ++x;Keyboard.release(KEY_UP_ARROW);break; case 4: ++x;Keyboard.release('p');break; case 5: ++x;Keyboard.press(KEY_DOWN_ARROW);break; case 6: ++x;Keyboard.press('p');break; case 7: ++x;Keyboard.release(KEY_DOWN_ARROW);break; case 8: if (stop_me) x=0; else if (!count) x=0; else {--count; x=1;} Keyboard.release('p'); break; default: x=0;break; } return x; }; // }}} private: byte count; }; // }}} class T_climb : public Base { // {{{ public: virtual void start(){ stop_me=false; count=+T_CLIMBC;}; virtual void stop(){ stop_me=true; count=0;}; virtual unsigned long long pause(unsigned long x){ return (x & 1)?T_CLIMB1:T_CLIMB2;}; virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1: ++x;Keyboard.press(KEY_UP_ARROW);break; case 2: if (stop_me) x=0; else if (!count) x=0; else {--count; x=1;} Keyboard.release(KEY_UP_ARROW); break; default: x=0;break; } return x; }; // }}} private: byte count; }; // }}} class Corners : public Base { // {{{ TL/DR/TR/DL/Tl public: virtual unsigned long long pause(unsigned long x){ // {{{ unsigned long long p; p=1000; // 1s if (x==9) p=10; return p; }; // }}} virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1:++x;//tgt.set(-1000,-1000); ++x;while (!MouseMoveHere(tgt)){delay(D);};break; case 2:tgt.set(DFS2); ++x;while (!MouseMoveHere(tgt)){};break; case 3:tgt.set(DFS2); ++x;while (!MouseMoveHere(tgt)){};break; case 4:tgt.set(DFS2);tgt.negate(); ++x;while (!MouseMoveHere(tgt)){};break; case 5:tgt.set(DFS2);tgt.negY(); ++x;while (!MouseMoveHere(tgt)){};break; case 6:tgt.set(DFS2);tgt.negX(); ++x;while (!MouseMoveHere(tgt)){};break; case 7:tgt.set(DFS2);tgt.negX(); ++x;while (!MouseMoveHere(tgt)){};break; case 8:tgt.set(DFS2);tgt.negY(); ++x;while (!MouseMoveHere(tgt)){};break; case 9:tgt.set(DFS2);tgt.negate(); ++x;while (!MouseMoveHere(tgt)){};break; default: x=0;break; } return x; }; // }}} }; // }}} class TestMove : public Base { // {{{ TL/DR/TR/DL/Tl public: virtual unsigned long long pause(unsigned long x){ // {{{ unsigned long long p; p=FAST_MOUSE; return p; }; // }}} virtual unsigned long next(unsigned long x){ // {{{ switch (x) { case 1:tgt.set(DFS2); ++x;while (!MouseMoveHere(tgt)){};break; case 2:tgt.set(DFS2); ++x;while (!MouseMoveHere(tgt)){};break; case 3:tgt.set(-DFS2.x,-DFS2.y-78); ++x;while (!MouseMoveHere(tgt)){};break; default: x=0;break; } return x; }; // }}} }; // }}} class FastClick : public Base { // {{{ 20 clicku / sec public: virtual unsigned long long pause(unsigned long x){ UNUSED(x); return 25;}; // 20 clicku/sec = 50ms / click = 25 ms / press/release virtual void restart(){ stop_me = true;}; virtual unsigned long next(unsigned long x){ // {{{ // Serial.print(x);Serial.print(" -> "); switch (x) { case 1: ++x;Mouse.press(MOUSE_LEFT);break; case 2: if (stop_me) x=0; else { x=1;} Mouse.release(MOUSE_LEFT); break; default: x=0;break; }; // Serial.print(x);Serial.print(" => "); return x; }; // }}} private: byte count; }; // }}} #define DEFAULT_DELAY 25 #define DEFAULT_DEBOUNCE 100 unsigned long state = 0; // state of state automat - 0 = inactive; 1 = start state Base *automat = NULL; Base *next_automat = NULL; unsigned long c_state = 0; Blink *blink=new Blink; // {{{ Automats #define AUTOMATS 5 struct T_automat {Base *A; Base *B;}; T_automat automats[AUTOMATS] ={ {new Recast, new ClickYes}, // 1 {new T_run, new T_climb}, // 2 {new Relearn, new Skills}, // 3 {new FastClick, new Swing}, // 4 {new Recast, new Swing} // 5 // {new Corners, new TestMove}, }; // {new FastClick, new FastClickLearn}, //}}} unsigned long long responseDelay = DEFAULT_DELAY; // repepeat delay between states unsigned long long debounceDelay = DEFAULT_DEBOUNCE; // debounce delay of the button, in ms bool somePressed=true; // pressed any button => digitalRead()==0 bool debouncing=false; bool led_shines=false; unsigned long milsDebounce; unsigned long milsState; unsigned long currentMillis; void setup() { // {{{ Serial.begin(9600); // initialize the buttons' inputs: pinMode(button_B, INPUT_PULLUP); pinMode(button_C, INPUT_PULLUP); pinMode(button_A, INPUT_PULLUP); pinMode(led, OUTPUT); // initialize mouse control: Mouse.begin(); Keyboard.begin(); milsDebounce=millis(); milsState=millis(); delay(1000); Serial.println("Klikimouse5 2023.07.29 10:45:37 "); Serial.println("{new Recast, new ClickYes}, // 1"); Serial.println("{new T_run, new T_climb}, // 2"); Serial.println("{new Relearn, new Skills}, // 3"); Serial.println("{new FastClick, new Swing}, // 4"); Serial.println("{new Recast, new Swing} // 5"); pinMode(RXled, OUTPUT); pinMode(TXled, OUTPUT); pinMode(C_led, OUTPUT); digitalWrite(RXled,HIGH); digitalWrite(TXled,HIGH); digitalWrite(C_led,LOW); } // }}} void loop() { digitalWrite(RXled,!((c_state+1) & _BV(0))); digitalWrite(TXled,!((c_state+1) & _BV(1))); digitalWrite(C_led, ((c_state+1) & _BV(2))); currentMillis=millis(); // {{{ prolog bool act_B= ! digitalRead(button_B); bool act_C= ! digitalRead(button_C); bool act_A= ! digitalRead(button_A); if (debouncing and ((currentMillis-milsDebounce) >= debounceDelay)) { debouncing = false; }; // }}} if (! debouncing) { // {{{ check for change if ( (act_B || act_C || act_A) != somePressed){ // {{{ somePressed changed ! // {{{ start debouncing milsDebounce=currentMillis; somePressed=(act_B || act_C || act_A); debouncing=true; // }}} if (act_C) { // act_C if possible next_automat = NULL; if (automat) automat->stop(); else { if (++c_state >=AUTOMATS) c_state=0; automat=blink; automat->start(); responseDelay = automat->pause(state); blink->set_count(c_state+1); state = 1; led_shines = false; // Serial.println(c_state); // Serial běží "na pozadí" a bliká LEDkama }; }; if (act_B) { // act_B if possible if (automat && (automat == automats[c_state].B)) automat->restart(); else { if (automat) automat->stop(); next_automat = automats[c_state].B; }; }; if (act_A) { // act_A high priority if (automat && (automat == automats[c_state].A)) automat->restart(); else { if (automat) automat->stop(); next_automat = automats[c_state].A; }; }; }; // }}} }; // }}} ! debouncing if ((currentMillis-milsState) >= responseDelay){ // {{{ next state milsState = currentMillis; // next step if (state == 0) { if (automat) automat->stop(); automat = NULL; responseDelay = DEFAULT_DELAY; if (next_automat) { state = 1; automat = next_automat; next_automat = NULL; automat->start(); responseDelay = automat->pause(state); led_shines = false; }; }; if (state){ responseDelay = automat->pause(state); state = automat->next(state); // Serial.print((long)(void *)automat,HEX);Serial.print(":"); // Serial.println(state); led_shines = !led_shines; } else { led_shines = false; }; digitalWrite(led,led_shines); }; // }}} }