diff --git a/src/board/system76/darp5/include/board/kbscan.h b/src/board/system76/darp5/include/board/kbscan.h index f9327ad..f5b8198 100644 --- a/src/board/system76/darp5/include/board/kbscan.h +++ b/src/board/system76/darp5/include/board/kbscan.h @@ -7,6 +7,11 @@ extern bool kbscan_enabled; +// ms between repeating key +extern uint16_t kbscan_repeat_period; +// ms between pressing key and repeating +extern uint16_t kbscan_repeat_delay; + void kbscan_init(void); void kbscan_event(void); diff --git a/src/board/system76/darp5/kbc.c b/src/board/system76/darp5/kbc.c index a76b80b..a55536d 100644 --- a/src/board/system76/darp5/kbc.c +++ b/src/board/system76/darp5/kbc.c @@ -22,6 +22,42 @@ bool kbc_second = false; // for basically no good reason static bool kbc_translate = true; +// Values from linux/drivers/input/keyboard/atkbd.c +static const uint16_t kbc_typematic_period[32] = { + 33, // 30.0 cps = ~33.33ms + 37, // 26.7 cps = ~37.45ms + 42, // 24.0 cps = ~41.67ms + 46, // 21.8 cps = ~45.87ms + 50, // 20.7 cps = ~48.30ms + 54, // 18.5 cps = ~54.05ms + 58, // 17.1 cps = ~58.48ms + 63, // 16.0 cps = ~62.50ms + 67, // 15.0 cps = ~66.67ms + 75, // 13.3 cps = ~75.19ms + 83, // 12.0 cps = ~83.33ms + 92, // 10.9 cps = ~91.74ms + 100, // 10.0 cps = 100ms + 109, // 9.2 cps = ~108.70ms + 116, // 8.6 cps = ~116.28ms + 125, // 8.0 cps = 125ms + 133, // 7.5 cps = ~133.33ms + 149, // 6.7 cps = ~149.25ms + 167, // 6.0 cps = ~166.67ms + 182, // 5.5 cps = ~181.82ms + 200, // 5.0 cps = 200ms + 217, // 4.6 cps = ~217.39ms + 232, // 4.3 cps = ~232.56ms + 250, // 4.0 cps = 250ms + 270, // 3.7 cps = ~270.27ms + 303, // 3.3 cps = ~303.03ms + 333, // 3.0 cps = ~333.33ms + 370, // 2.7 cps = ~370.37ms + 400, // 2.5 cps = 400ms + 435, // 2.3 cps = ~434.78ms + 470, // 2.1 cps = ~478.19ms + 500, // 2.0 cps = 500ms +}; + bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) { if (!kbc_first) return true; if (kbc_translate) { @@ -55,6 +91,7 @@ enum KbcState { KBC_STATE_WRITE_CONFIG, KBC_STATE_SET_LEDS, KBC_STATE_SCANCODE, + KBC_STATE_TYPEMATIC, KBC_STATE_WRITE_PORT, KBC_STATE_FIRST_PORT_OUTPUT, KBC_STATE_SECOND_PORT_OUTPUT, @@ -172,6 +209,11 @@ void kbc_event(struct Kbc * kbc) { } } break; + case 0xF3: + TRACE(" set typematic rate/delay\n"); + state = KBC_STATE_TYPEMATIC; + kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); + break; case 0xF4: TRACE(" enable scanning\n"); kbscan_enabled = true; @@ -228,6 +270,21 @@ void kbc_event(struct Kbc * kbc) { #endif kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); break; + case KBC_STATE_TYPEMATIC: + TRACE(" set typematic rate/delay\n"); + state = KBC_STATE_NORMAL; + { + // Rate: bits 0-4 + uint16_t period = kbc_typematic_period[data & 0x1F]; + kbscan_repeat_period = period; + + // Delay: bits 5-6 + static const uint16_t delay[4] = {250, 500, 750, 1000}; + uint8_t idx = (data & 0x60) >> 5; + kbscan_repeat_delay = delay[idx]; + } + kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); + break; case KBC_STATE_WRITE_PORT: TRACE(" write port byte\n"); state = KBC_STATE_NORMAL; diff --git a/src/board/system76/darp5/kbscan.c b/src/board/system76/darp5/kbscan.c index 8087b0e..67302bf 100644 --- a/src/board/system76/darp5/kbscan.c +++ b/src/board/system76/darp5/kbscan.c @@ -9,6 +9,8 @@ #include bool kbscan_enabled = false; +uint16_t kbscan_repeat_period = 91; +uint16_t kbscan_repeat_delay = 500; uint8_t sci_extra = 0; @@ -121,6 +123,10 @@ void kbscan_event(void) { static bool debounce = false; static uint32_t debounce_time = 0; + static bool repeat = false; + static uint16_t repeat_key = 0; + static uint32_t repeat_key_time = 0; + // If debounce complete if (debounce) { uint32_t time = time_get(); @@ -166,6 +172,7 @@ void kbscan_event(void) { uint8_t new = ~KSI; uint8_t last = kbscan_last[i]; if (new != last) { + // A key was pressed or released int j; for (j = 0; j < KM_IN; j++) { bool new_b = new & (1 << j); @@ -190,6 +197,17 @@ void kbscan_event(void) { // In the case of ignored key press/release, reset bit reset = true; } + + if (new_b) { + // New key pressed, update last key + repeat_key = key; + repeat_key_time = time_get(); + repeat = false; + } else if (key == repeat_key) { + // Repeat key was released + repeat_key = 0; + repeat = false; + } } else { WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer); } @@ -207,6 +225,28 @@ void kbscan_event(void) { } kbscan_last[i] = new; + } else if (new && repeat_key != 0) { + // A key is being pressed + uint32_t time = time_get(); + static uint32_t repeat_start = 0; + + if (!repeat) { + if (time < repeat_key_time) { + // Overflow, reset repeat_key_time + repeat_key_time = time; + } else if ((time - repeat_key_time) >= kbscan_repeat_delay) { + // Typematic repeat + repeat = true; + repeat_start = time; + } + } + + if (repeat) { + if ((time - repeat_start) > kbscan_repeat_period) { + kbscan_press(repeat_key, true, &layer); + repeat_start = time; + } + } } } diff --git a/src/board/system76/galp3-c/include/board/kbscan.h b/src/board/system76/galp3-c/include/board/kbscan.h index f9327ad..f5b8198 100644 --- a/src/board/system76/galp3-c/include/board/kbscan.h +++ b/src/board/system76/galp3-c/include/board/kbscan.h @@ -7,6 +7,11 @@ extern bool kbscan_enabled; +// ms between repeating key +extern uint16_t kbscan_repeat_period; +// ms between pressing key and repeating +extern uint16_t kbscan_repeat_delay; + void kbscan_init(void); void kbscan_event(void); diff --git a/src/board/system76/galp3-c/kbc.c b/src/board/system76/galp3-c/kbc.c index a76b80b..a55536d 100644 --- a/src/board/system76/galp3-c/kbc.c +++ b/src/board/system76/galp3-c/kbc.c @@ -22,6 +22,42 @@ bool kbc_second = false; // for basically no good reason static bool kbc_translate = true; +// Values from linux/drivers/input/keyboard/atkbd.c +static const uint16_t kbc_typematic_period[32] = { + 33, // 30.0 cps = ~33.33ms + 37, // 26.7 cps = ~37.45ms + 42, // 24.0 cps = ~41.67ms + 46, // 21.8 cps = ~45.87ms + 50, // 20.7 cps = ~48.30ms + 54, // 18.5 cps = ~54.05ms + 58, // 17.1 cps = ~58.48ms + 63, // 16.0 cps = ~62.50ms + 67, // 15.0 cps = ~66.67ms + 75, // 13.3 cps = ~75.19ms + 83, // 12.0 cps = ~83.33ms + 92, // 10.9 cps = ~91.74ms + 100, // 10.0 cps = 100ms + 109, // 9.2 cps = ~108.70ms + 116, // 8.6 cps = ~116.28ms + 125, // 8.0 cps = 125ms + 133, // 7.5 cps = ~133.33ms + 149, // 6.7 cps = ~149.25ms + 167, // 6.0 cps = ~166.67ms + 182, // 5.5 cps = ~181.82ms + 200, // 5.0 cps = 200ms + 217, // 4.6 cps = ~217.39ms + 232, // 4.3 cps = ~232.56ms + 250, // 4.0 cps = 250ms + 270, // 3.7 cps = ~270.27ms + 303, // 3.3 cps = ~303.03ms + 333, // 3.0 cps = ~333.33ms + 370, // 2.7 cps = ~370.37ms + 400, // 2.5 cps = 400ms + 435, // 2.3 cps = ~434.78ms + 470, // 2.1 cps = ~478.19ms + 500, // 2.0 cps = 500ms +}; + bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) { if (!kbc_first) return true; if (kbc_translate) { @@ -55,6 +91,7 @@ enum KbcState { KBC_STATE_WRITE_CONFIG, KBC_STATE_SET_LEDS, KBC_STATE_SCANCODE, + KBC_STATE_TYPEMATIC, KBC_STATE_WRITE_PORT, KBC_STATE_FIRST_PORT_OUTPUT, KBC_STATE_SECOND_PORT_OUTPUT, @@ -172,6 +209,11 @@ void kbc_event(struct Kbc * kbc) { } } break; + case 0xF3: + TRACE(" set typematic rate/delay\n"); + state = KBC_STATE_TYPEMATIC; + kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); + break; case 0xF4: TRACE(" enable scanning\n"); kbscan_enabled = true; @@ -228,6 +270,21 @@ void kbc_event(struct Kbc * kbc) { #endif kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); break; + case KBC_STATE_TYPEMATIC: + TRACE(" set typematic rate/delay\n"); + state = KBC_STATE_NORMAL; + { + // Rate: bits 0-4 + uint16_t period = kbc_typematic_period[data & 0x1F]; + kbscan_repeat_period = period; + + // Delay: bits 5-6 + static const uint16_t delay[4] = {250, 500, 750, 1000}; + uint8_t idx = (data & 0x60) >> 5; + kbscan_repeat_delay = delay[idx]; + } + kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); + break; case KBC_STATE_WRITE_PORT: TRACE(" write port byte\n"); state = KBC_STATE_NORMAL; diff --git a/src/board/system76/galp3-c/kbscan.c b/src/board/system76/galp3-c/kbscan.c index 68e2c86..41a5ddb 100644 --- a/src/board/system76/galp3-c/kbscan.c +++ b/src/board/system76/galp3-c/kbscan.c @@ -10,6 +10,8 @@ #include bool kbscan_enabled = false; +uint16_t kbscan_repeat_period = 91; +uint16_t kbscan_repeat_delay = 500; uint8_t sci_extra = 0; @@ -129,6 +131,10 @@ void kbscan_event(void) { static bool debounce = false; static uint32_t debounce_time = 0; + static bool repeat = false; + static uint16_t repeat_key = 0; + static uint32_t repeat_key_time = 0; + // If debounce complete if (debounce) { uint32_t time = time_get(); @@ -165,6 +171,7 @@ void kbscan_event(void) { uint8_t new = ~KSI; uint8_t last = kbscan_last[i]; if (new != last) { + // A key was pressed or released int j; for (j = 0; j < KM_IN; j++) { bool new_b = new & (1 << j); @@ -189,6 +196,17 @@ void kbscan_event(void) { // In the case of ignored key press/release, reset bit reset = true; } + + if (new_b) { + // New key pressed, update last key + repeat_key = key; + repeat_key_time = time_get(); + repeat = false; + } else if (key == repeat_key) { + // Repeat key was released + repeat_key = 0; + repeat = false; + } } else { WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer); } @@ -206,6 +224,28 @@ void kbscan_event(void) { } kbscan_last[i] = new; + } else if (new && repeat_key != 0) { + // A key is being pressed + uint32_t time = time_get(); + static uint32_t repeat_start = 0; + + if (!repeat) { + if (time < repeat_key_time) { + // Overflow, reset repeat_key_time + repeat_key_time = time; + } else if ((time - repeat_key_time) >= kbscan_repeat_delay) { + // Typematic repeat + repeat = true; + repeat_start = time; + } + } + + if (repeat) { + if ((time - repeat_start) > kbscan_repeat_period) { + kbscan_press(repeat_key, true, &layer); + repeat_start = time; + } + } } } diff --git a/src/board/system76/lemp9/include/board/kbscan.h b/src/board/system76/lemp9/include/board/kbscan.h index f9327ad..f5b8198 100644 --- a/src/board/system76/lemp9/include/board/kbscan.h +++ b/src/board/system76/lemp9/include/board/kbscan.h @@ -7,6 +7,11 @@ extern bool kbscan_enabled; +// ms between repeating key +extern uint16_t kbscan_repeat_period; +// ms between pressing key and repeating +extern uint16_t kbscan_repeat_delay; + void kbscan_init(void); void kbscan_event(void); diff --git a/src/board/system76/lemp9/kbc.c b/src/board/system76/lemp9/kbc.c index a76b80b..a55536d 100644 --- a/src/board/system76/lemp9/kbc.c +++ b/src/board/system76/lemp9/kbc.c @@ -22,6 +22,42 @@ bool kbc_second = false; // for basically no good reason static bool kbc_translate = true; +// Values from linux/drivers/input/keyboard/atkbd.c +static const uint16_t kbc_typematic_period[32] = { + 33, // 30.0 cps = ~33.33ms + 37, // 26.7 cps = ~37.45ms + 42, // 24.0 cps = ~41.67ms + 46, // 21.8 cps = ~45.87ms + 50, // 20.7 cps = ~48.30ms + 54, // 18.5 cps = ~54.05ms + 58, // 17.1 cps = ~58.48ms + 63, // 16.0 cps = ~62.50ms + 67, // 15.0 cps = ~66.67ms + 75, // 13.3 cps = ~75.19ms + 83, // 12.0 cps = ~83.33ms + 92, // 10.9 cps = ~91.74ms + 100, // 10.0 cps = 100ms + 109, // 9.2 cps = ~108.70ms + 116, // 8.6 cps = ~116.28ms + 125, // 8.0 cps = 125ms + 133, // 7.5 cps = ~133.33ms + 149, // 6.7 cps = ~149.25ms + 167, // 6.0 cps = ~166.67ms + 182, // 5.5 cps = ~181.82ms + 200, // 5.0 cps = 200ms + 217, // 4.6 cps = ~217.39ms + 232, // 4.3 cps = ~232.56ms + 250, // 4.0 cps = 250ms + 270, // 3.7 cps = ~270.27ms + 303, // 3.3 cps = ~303.03ms + 333, // 3.0 cps = ~333.33ms + 370, // 2.7 cps = ~370.37ms + 400, // 2.5 cps = 400ms + 435, // 2.3 cps = ~434.78ms + 470, // 2.1 cps = ~478.19ms + 500, // 2.0 cps = 500ms +}; + bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) { if (!kbc_first) return true; if (kbc_translate) { @@ -55,6 +91,7 @@ enum KbcState { KBC_STATE_WRITE_CONFIG, KBC_STATE_SET_LEDS, KBC_STATE_SCANCODE, + KBC_STATE_TYPEMATIC, KBC_STATE_WRITE_PORT, KBC_STATE_FIRST_PORT_OUTPUT, KBC_STATE_SECOND_PORT_OUTPUT, @@ -172,6 +209,11 @@ void kbc_event(struct Kbc * kbc) { } } break; + case 0xF3: + TRACE(" set typematic rate/delay\n"); + state = KBC_STATE_TYPEMATIC; + kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); + break; case 0xF4: TRACE(" enable scanning\n"); kbscan_enabled = true; @@ -228,6 +270,21 @@ void kbc_event(struct Kbc * kbc) { #endif kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); break; + case KBC_STATE_TYPEMATIC: + TRACE(" set typematic rate/delay\n"); + state = KBC_STATE_NORMAL; + { + // Rate: bits 0-4 + uint16_t period = kbc_typematic_period[data & 0x1F]; + kbscan_repeat_period = period; + + // Delay: bits 5-6 + static const uint16_t delay[4] = {250, 500, 750, 1000}; + uint8_t idx = (data & 0x60) >> 5; + kbscan_repeat_delay = delay[idx]; + } + kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT); + break; case KBC_STATE_WRITE_PORT: TRACE(" write port byte\n"); state = KBC_STATE_NORMAL; diff --git a/src/board/system76/lemp9/kbscan.c b/src/board/system76/lemp9/kbscan.c index 68e2c86..41a5ddb 100644 --- a/src/board/system76/lemp9/kbscan.c +++ b/src/board/system76/lemp9/kbscan.c @@ -10,6 +10,8 @@ #include bool kbscan_enabled = false; +uint16_t kbscan_repeat_period = 91; +uint16_t kbscan_repeat_delay = 500; uint8_t sci_extra = 0; @@ -129,6 +131,10 @@ void kbscan_event(void) { static bool debounce = false; static uint32_t debounce_time = 0; + static bool repeat = false; + static uint16_t repeat_key = 0; + static uint32_t repeat_key_time = 0; + // If debounce complete if (debounce) { uint32_t time = time_get(); @@ -165,6 +171,7 @@ void kbscan_event(void) { uint8_t new = ~KSI; uint8_t last = kbscan_last[i]; if (new != last) { + // A key was pressed or released int j; for (j = 0; j < KM_IN; j++) { bool new_b = new & (1 << j); @@ -189,6 +196,17 @@ void kbscan_event(void) { // In the case of ignored key press/release, reset bit reset = true; } + + if (new_b) { + // New key pressed, update last key + repeat_key = key; + repeat_key_time = time_get(); + repeat = false; + } else if (key == repeat_key) { + // Repeat key was released + repeat_key = 0; + repeat = false; + } } else { WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer); } @@ -206,6 +224,28 @@ void kbscan_event(void) { } kbscan_last[i] = new; + } else if (new && repeat_key != 0) { + // A key is being pressed + uint32_t time = time_get(); + static uint32_t repeat_start = 0; + + if (!repeat) { + if (time < repeat_key_time) { + // Overflow, reset repeat_key_time + repeat_key_time = time; + } else if ((time - repeat_key_time) >= kbscan_repeat_delay) { + // Typematic repeat + repeat = true; + repeat_start = time; + } + } + + if (repeat) { + if ((time - repeat_start) > kbscan_repeat_period) { + kbscan_press(repeat_key, true, &layer); + repeat_start = time; + } + } } }