|
/*
|
|
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 <Keyboard.h>
|
|
#include <Mouse.h>
|
|
|
|
|
|
// 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);
|
|
}; // }}}
|
|
}
|