/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ #ifndef DYNAMIC_MACROS_H #define DYNAMIC_MACROS_H #include "action_layer.h" #ifndef DYNAMIC_MACRO_SIZE /* May be overridden with a custom value. Be aware that the effective * macro length is half of this value: each keypress is recorded twice * because of the down-event and up-event. This is not a bug, it's the * intended behavior. */ #define DYNAMIC_MACRO_SIZE 256 #endif /* DYNAMIC_MACRO_RANGE must be set as the last element of user's * "planck_keycodes" enum prior to including this header. This allows * us to 'extend' it. */ enum dynamic_macro_keycodes { DYN_REC_START1 = DYNAMIC_MACRO_RANGE, DYN_REC_START2, DYN_MACRO_PLAY1, DYN_MACRO_PLAY2, }; /* Blink the LEDs to notify the user about some event. */ void dynamic_macro_led_blink(void) { backlight_toggle(); _delay_ms(100); backlight_toggle(); } /** * Start recording of the dynamic macro. * * @param[out] macro_pointer The new macro buffer iterator. * @param[in] macro_buffer The macro buffer used to initialize macro_pointer. */ void dynamic_macro_record_start( keyrecord_t **macro_pointer, keyrecord_t *macro_buffer) { dynamic_macro_led_blink(); clear_keyboard(); layer_clear(); *macro_pointer = macro_buffer; } /** * Play the dynamic macro. * * @param macro_buffer[in] The beginning of the macro buffer being played. * @param macro_end[in] The element after the last macro buffer element. * @param direction[in] Either +1 or -1, which way to iterate the buffer. */ void dynamic_macro_play( keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction) { uint32_t saved_layer_state = layer_state; clear_keyboard(); layer_clear(); while (macro_buffer != macro_end) { process_record(macro_buffer); macro_buffer += direction; } clear_keyboard(); layer_state = saved_layer_state; } /** * Record a single key in a dynamic macro. * * @param macro_pointer[in,out] The current buffer position. * @param macro_end2[in] The end of the other macro which shouldn't be overwritten. * @param direction[in] Either +1 or -1, which way to iterate the buffer. * @param record[in] The current keypress. */ void dynamic_macro_record_key( keyrecord_t **macro_pointer, keyrecord_t *macro_end2, int8_t direction, keyrecord_t *record) { if (*macro_pointer + direction != macro_end2) { **macro_pointer = *record; *macro_pointer += direction; } else { /* Notify about the end of buffer. The blinks are paired * because they should happen on both down and up events. */ backlight_toggle(); } } /** * End recording of the dynamic macro. Essentially just update the * pointer to the end of the macro. */ void dynamic_macro_record_end(keyrecord_t *macro_pointer, keyrecord_t **macro_end) { dynamic_macro_led_blink(); *macro_end = macro_pointer; } /* Handle the key events related to the dynamic macros. Should be * called from process_record_user() like this: * * bool process_record_user(uint16_t keycode, keyrecord_t *record) { * if (!process_record_dynamic_macro(keycode, record)) { * return false; * } * <...THE REST OF THE FUNCTION...> * } */ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record) { /* Both macros use the same buffer but read/write on different * ends of it. * * Macro1 is written left-to-right starting from the