diff options
Diffstat (limited to 'quantum/dynamic_macro.h')
| -rw-r--r-- | quantum/dynamic_macro.h | 82 | 
1 files changed, 67 insertions, 15 deletions
diff --git a/quantum/dynamic_macro.h b/quantum/dynamic_macro.h index 64093f293..f242405de 100644 --- a/quantum/dynamic_macro.h +++ b/quantum/dynamic_macro.h @@ -40,6 +40,7 @@  enum dynamic_macro_keycodes {      DYN_REC_START1 = DYNAMIC_MACRO_RANGE,      DYN_REC_START2, +    DYN_REC_STOP,      DYN_MACRO_PLAY1,      DYN_MACRO_PLAY2,  }; @@ -47,11 +48,22 @@ enum dynamic_macro_keycodes {  /* Blink the LEDs to notify the user about some event. */  void dynamic_macro_led_blink(void)  { +#ifdef BACKLIGHT_ENABLE      backlight_toggle();      _delay_ms(100);      backlight_toggle(); +#endif  } +/* Convenience macros used for retrieving the debug info. All of them + * need a `direction` variable accessible at the call site. + */ +#define DYNAMIC_MACRO_CURRENT_SLOT() (direction > 0 ? 1 : 2) +#define DYNAMIC_MACRO_CURRENT_LENGTH(BEGIN, POINTER) \ +    ((int)(direction * ((POINTER) - (BEGIN)))) +#define DYNAMIC_MACRO_CURRENT_CAPACITY(BEGIN, END2) \ +    ((int)(direction * ((END2) - (BEGIN)) + 1)) +  /**   * Start recording of the dynamic macro.   * @@ -61,6 +73,8 @@ void dynamic_macro_led_blink(void)  void dynamic_macro_record_start(      keyrecord_t **macro_pointer, keyrecord_t *macro_buffer)  { +    dprintln("dynamic macro recording: started"); +      dynamic_macro_led_blink();      clear_keyboard(); @@ -78,6 +92,8 @@ void dynamic_macro_record_start(  void dynamic_macro_play(      keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction)  { +    dprintf("dynamic macro: slot %d playback\n", DYNAMIC_MACRO_CURRENT_SLOT()); +      uint32_t saved_layer_state = layer_state;      clear_keyboard(); @@ -96,35 +112,68 @@ void dynamic_macro_play(  /**   * Record a single key in a dynamic macro.   * + * @param macro_buffer[in] The start of the used macro buffer.   * @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 macro2_end[in] The end of the other macro.   * @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_buffer,      keyrecord_t **macro_pointer, -    keyrecord_t *macro_end2, +    keyrecord_t *macro2_end,      int8_t direction,      keyrecord_t *record)  { -    if (*macro_pointer + direction != macro_end2) { +    /* If we've just started recording, ignore all the key releases. */ +    if (!record->event.pressed && *macro_pointer == macro_buffer) { +        dprintln("dynamic macro: ignoring a leading key-up event"); +        return; +    } + +    /* The other end of the other macro is the last buffer element it +     * is safe to use before overwriting the other macro. +     */ +    if (*macro_pointer - direction != macro2_end) {          **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(); +        dynamic_macro_led_blink();      } + +    dprintf( +        "dynamic macro: slot %d length: %d/%d\n", +        DYNAMIC_MACRO_CURRENT_SLOT(), +        DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, *macro_pointer), +        DYNAMIC_MACRO_CURRENT_CAPACITY(macro_buffer, macro2_end));  }  /**   * 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) +void dynamic_macro_record_end( +    keyrecord_t *macro_buffer, +    keyrecord_t *macro_pointer, +    int8_t direction, +    keyrecord_t **macro_end)  {      dynamic_macro_led_blink(); +    /* Do not save the keys being held when stopping the recording, +     * i.e. the keys used to access the layer DYN_REC_STOP is on. +     */ +    while (macro_pointer != macro_buffer && +           (macro_pointer - direction)->event.pressed) { +        dprintln("dynamic macro: trimming a trailing key-down event"); +        macro_pointer -= direction; +    } + +    dprintf( +        "dynamic macro: slot %d saved, length: %d\n", +        DYNAMIC_MACRO_CURRENT_SLOT(), +        DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, macro_pointer)); +      *macro_end = macro_pointer;  } @@ -152,7 +201,7 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)       * ¯o_buffer   macro_end       *  v                   v       * +------------------------------------------------------------+ -     * |>>>>>> MACRO1 >>>>>>|    |<<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| +     * |>>>>>> MACRO1 >>>>>>      <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<|       * +------------------------------------------------------------+       *                           ^                                 ^       *                         r_macro_end                  r_macro_buffer @@ -209,18 +258,17 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)      } else {          /* A macro is being recorded right now. */          switch (keycode) { -        case MO(_DYN): -            /* Use the layer key used to access the macro recording as -             * a stop button. */ +        case DYN_REC_STOP: +            /* Stop the macro recording. */              if (record->event.pressed) { /* Ignore the initial release                                            * just after the recoding                                            * starts. */                  switch (macro_id) {                  case 1: -                    dynamic_macro_record_end(macro_pointer, ¯o_end); +                    dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end);                      break;                  case 2: -                    dynamic_macro_record_end(macro_pointer, &r_macro_end); +                    dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end);                      break;                  }                  macro_id = 0; @@ -230,10 +278,10 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)              /* Store the key in the macro buffer and process it normally. */              switch (macro_id) {              case 1: -                dynamic_macro_record_key(¯o_pointer, r_macro_end, +1, record); +                dynamic_macro_record_key(macro_buffer, ¯o_pointer, r_macro_end, +1, record);                  break;              case 2: -                dynamic_macro_record_key(¯o_pointer, macro_end, -1, record); +                dynamic_macro_record_key(r_macro_buffer, ¯o_pointer, macro_end, -1, record);                  break;              }              return true; @@ -244,4 +292,8 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)      return true;  } +#undef DYNAMIC_MACRO_CURRENT_SLOT +#undef DYNAMIC_MACRO_CURRENT_LENGTH +#undef DYNAMIC_MACRO_CURRENT_CAPACITY +  #endif  | 
