/* Klikimouse3 aneb objects forever! 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; #define UNUSED(x) (void)(x) #define FAST_MOUSE 25 class Base{ // {{{ public: virtual void start(){ stop_me=false;}; // initialise class for next round of cycles 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; }; // }}} class Recast : public Base { // {{{ public: virtual void start(){ stop_me=false; count=10;}; 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('c');break; case 2: ++x;Keyboard.release('c');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 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: p=60;break; // time to actualise mouse 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: case 4: case 104: case 204: ++x;Mouse.move(127,127,0);break; case 5: case 105: case 205: ++x;Mouse.move(-60,-20,0);break; case 6: case 106: case 206: ++x;Mouse.press(MOUSE_LEFT);break; // Mouse.click() is too fast, need press/release (Rest) case 7: case 107: case 207: ++x;Mouse.release(MOUSE_LEFT);break; case 8: case 108: case 208: ++x;Mouse.move(-20,-120,0);break; // Mouse is accelerated over long fast moves (To Loiter) case 9: case 109: case 209: ++x;Mouse.move(0,-60,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;Mouse.move(20,120,0);break; // Mouse is accelerated over long fast moves (Back To Loiter) case 20: case 120: ++x;Mouse.move(0,120,0);break; case 21: case 121: x += (101-21); break; // loop: 23->101, 123->201 // To Trainer case 219: ++x;Mouse.move(-80,-30,0);break; // click Trainer case 220: ++x;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;Mouse.move(-127,127,0);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 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;Mouse.move(-127,127,0);break; case 5: ++x;Mouse.move(127,-120,0);break; case 6: ++x;break; case 7: ++x;Mouse.press(MOUSE_RIGHT);break; // Mouse.click() is too fast, need press/release case 8: ++x;Mouse.move(0,-120,0);break; case 9: ++x;break; case 10: ++x;Mouse.release(MOUSE_RIGHT);break; case 11: ++x;break; case 12: if (stop_me) x=0; else x=3;break; // infinite loop default: x=0;break; }; return x; }; // }}} }; // }}} #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 3 struct T_automat {Base *A; Base *B;}; T_automat automats[AUTOMATS] ={ {new Recast, new ClickYes}, {new Relearn, new Skills}, {new Recast, new Swing} }; //}}} 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() { // {{{ // 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(); } // }}} void loop() { 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; }; }; if (act_B) { // act_B if possible if (automat) automat->stop(); next_automat = automats[c_state].B; }; if (act_A) { // act_A high priority 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); led_shines = !led_shines; } else { led_shines = false; }; digitalWrite(led,led_shines); }; // }}} }