Implement a way to do simple macros

The main thing here is `Macros_::play`, which takes a list of bytes from
PROGMEM, and plays a macro. The array is always a command, followed by
arguments, and the size of the argument depends on the command: key presses and
releases take a 16-bit argument, and the event is injected into the event
handler flow. Waiting and interval change take a 8-bit time. Helpers are
provided to make it a little bit easier to construct a macro.

Of course, the `macroAction` method may do any other side effects, and is not
restricted to returning a sequence of commands.

Fixes #5.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/58/head
Gergely Nagy 8 years ago
parent 516d617cce
commit 44f5de357c

@ -40,10 +40,17 @@ static LEDChaseEffect chaseEffect;
static LEDNumlock numLockEffect (NUMPAD_KEYMAP); static LEDNumlock numLockEffect (NUMPAD_KEYMAP);
void macroAction(uint8_t macroIndex, uint8_t keyState) { const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
if (macroIndex == 1 && key_toggled_on(keyState)) { if (macroIndex == 1 && key_toggled_on(keyState)) {
Serial.print("Keyboard.IO keyboard driver v0.00"); Serial.print("Keyboard.IO keyboard driver v0.00");
return MACRO(I(25),
D(LShift), T(M), U(LShift), T(O), T(D), T(E), T(L),
T(Space),
W(100),
T(0), T(1),
END);
} }
return MACRO_NONE;
} }
void setup() { void setup() {

@ -1,15 +1,56 @@
#include "Keyboardio-Macros.h" #include "Keyboardio-Macros.h"
__attribute__((weak)) __attribute__((weak))
void const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
macroAction(uint8_t macroIndex, uint8_t keyState) { return MACRO_NONE;
}
void Macros_::play(const macro_t *macro_p) {
macro_t macro = END;
uint8_t interval = 0;
Key key;
if (!macro_p)
return;
while (true) {
switch (macro = pgm_read_byte(macro_p++)) {
case MACRO_ACTION_STEP_INTERVAL:
interval = pgm_read_byte(macro_p++);
break;
case MACRO_ACTION_STEP_WAIT: {
uint8_t wait = pgm_read_byte(macro_p++);
delay(wait);
break;
}
case MACRO_ACTION_STEP_KEYDOWN:
key.flags = pgm_read_byte(macro_p++);
key.rawKey = pgm_read_byte(macro_p++);
handle_key_event(key, 255, 255, IS_PRESSED | INJECTED);
Keyboard.sendReport();
break;
case MACRO_ACTION_STEP_KEYUP:
key.flags = pgm_read_byte(macro_p++);
key.rawKey = pgm_read_byte(macro_p++);
handle_key_event(key, 255, 255, WAS_PRESSED | INJECTED);
Keyboard.sendReport();
break;
case END:
default:
return;
}
delay(interval);
}
} }
static bool handleMacroEvent(Key mappedKey, byte row, byte col, uint8_t keyState) { static bool handleMacroEvent(Key mappedKey, byte row, byte col, uint8_t keyState) {
if (!(mappedKey.flags & (SYNTHETIC|IS_MACRO))) if (!(mappedKey.flags & (SYNTHETIC|IS_MACRO)))
return false; return false;
macroAction(mappedKey.rawKey, keyState); const macro_t *m = macroAction(mappedKey.rawKey, keyState);
Macros.play(m);
return true; return true;
} }

@ -2,25 +2,16 @@
#include <KeyboardioFirmware.h> #include <KeyboardioFirmware.h>
#define IS_MACRO B00000001 #include "MacroKeyDefs.h"
#include "MacroSteps.h"
#define M(n) (Key){ KEY_FLAGS|SYNTHETIC|IS_MACRO, n} const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState);
#define Key_macroKey1 M(1)
#define Key_macroKey2 M(2)
#define Key_macroKey3 M(3)
#define Key_macroKey4 M(4)
#define Key_macroKey5 M(5)
#define Key_macroKey6 M(6)
#define Key_macroKey7 M(7)
#define Key_macroKey8 M(8)
#define Key_macroKey9 M(9)
#define Key_macroKey10 M(10)
void macroAction(uint8_t macroIndex, uint8_t keyState);
class Macros_ { class Macros_ {
public: public:
Macros_(void); Macros_(void);
void play(const macro_t *macro_p);
}; };
extern Macros_ Macros; extern Macros_ Macros;

@ -0,0 +1,15 @@
#pragma once
#define IS_MACRO B00000001
#define M(n) (Key){ KEY_FLAGS|SYNTHETIC|IS_MACRO, n}
#define Key_macroKey1 M(1)
#define Key_macroKey2 M(2)
#define Key_macroKey3 M(3)
#define Key_macroKey4 M(4)
#define Key_macroKey5 M(5)
#define Key_macroKey6 M(6)
#define Key_macroKey7 M(7)
#define Key_macroKey8 M(8)
#define Key_macroKey9 M(9)
#define Key_macroKey10 M(10)

@ -0,0 +1,22 @@
#pragma once
typedef enum {
MACRO_ACTION_END,
MACRO_ACTION_STEP_INTERVAL,
MACRO_ACTION_STEP_WAIT,
MACRO_ACTION_STEP_KEYDOWN,
MACRO_ACTION_STEP_KEYUP,
} MacroActionStepType;
typedef uint8_t macro_t;
#define MACRO_NONE 0
#define MACRO(...) ({static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
#define I(n) MACRO_ACTION_STEP_INTERVAL, n
#define W(n) MACRO_ACTION_STEP_WAIT, n
#define D(k) MACRO_ACTION_STEP_KEYDOWN, (Key_ ## k).raw
#define U(k) MACRO_ACTION_STEP_KEYUP, (Key_ ## k).raw
#define T(k) D(k), U(k)
#define END MACRO_ACTION_END
Loading…
Cancel
Save