KlikiMouse2.ino (Source)

/*
	Klikimouse2 aneb DAGGER 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>

// {{{ STATES
#define START_A 1
#define START_B 100
#define START_C 200

#define CYCLES_A 50
#define CYCLES_B 40
#define CYCLES_C 1

#define DELAY_A 70
#define DELAY_B 20
#define DELAY_C 10

// }}}

#define DEFAULT_DELAY 25
#define DEFAULT_DEBOUNCE 50


// 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;

unsigned int state = 0;		// state of state automat - 0 = inactive
unsigned int restart_state = 0;	// state for next itaration - 0 = inactive
unsigned int cycles_left = 0;	// if != 0 && state == 0 then decrease and restart with restart_state
unsigned long long next_responseDelay = DEFAULT_DELAY;	// repepeat delay between states after restart

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
				restart_state = START_C;
				cycles_left = CYCLES_C;
				next_responseDelay = DELAY_C;
				
			};
			if (act_B) {	// act_B if possible
				restart_state = START_B;
				cycles_left = CYCLES_B;
				next_responseDelay = DELAY_B;
			};
			if (act_A) {	// act_A high priority
				restart_state = START_A;
				cycles_left = CYCLES_A;
				next_responseDelay = DELAY_A;
			};
		};	// }}}
	};	// }}} ! debouncing
	
	if ((currentMillis-milsState) >= responseDelay){
		milsState = currentMillis;	// next step
		if (state == 0) {
			if (cycles_left == 0) {
				restart_state = 0;	// stop it
				responseDelay = DEFAULT_DELAY;
			} else {	// {{{ new cycle
				state = restart_state;
				responseDelay = next_responseDelay;
				--cycles_left;
			};	// }}}
		};
		if (state){
			switch (state) {	// {{{ state automat
				case 0: break;
				
				case START_A +0: ++state;Keyboard.press('c');break;
				case START_A +1: ++state;Keyboard.release('c');break;
				case START_A +2: ++state;Mouse.press(MOUSE_LEFT);break;
				case START_A +3: ++state;Mouse.release(MOUSE_LEFT);break;
				case START_A +4: state = 0;break;
				
				case START_B +0: ++state;Mouse.press(MOUSE_LEFT);break;
				case START_B +1: ++state;Mouse.release(MOUSE_LEFT);break;
				case START_B +2: ++state;Keyboard.press('y');break;
				case START_B +3: ++state;Keyboard.release('y');break;
				case START_B +4: state = 0;break;
				
				case START_C +0: state = 0;break;
				
				default: state = 0;break;
			};	// }}}
			led_shines = !led_shines;
		} else {
			led_shines = false;
		};
		digitalWrite(led,led_shines);
	};
}