1
0
Fork 0
Commit graph

16 commits

Author SHA1 Message Date
Purdea Andrei
6c2c3c13e9
Various fixes to how timer differences are calculated (#8585)
* tmk_core/common: Fixing TIMER_DIFF macro to calculate difference correctly after the timer wraps.

Let's go through an example, using the following macro:

If the first timer read is 0xe4 and the second one is 0x32, the timer wrapped.
If the timer would have had more bits, it's new value would have been 0x132,
and the correct difference in time is 0x132 - 0xe4 = 0x4e

old code TIMER_DIFF_8(0x32, 0xe4) = 0xff - 0xe4 + 0x32 = 0x4d, which is wrong.
new code TIMER_DIFF_8(0x32, 0xe4) = 0xff + 1 - 0xe4 + 0x32 = 0x4e, which is correct.

This also gives a chance for a smart compiler to optimize the code using normal
integer overflow.

For example on AVR, the following C code:
uint8_t __attribute__ ((noinline)) test(uint8_t current_timer, uint8_t start_timer)
{
    return TIMER_DIFF_8(current_timer, start_timer);
}
With the original code, it gets translated to the following list of instructions:
00004c6e <test>:
    4c6e:       98 2f           mov     r25, r24
    4c70:       86 1b           sub     r24, r22
    4c72:       96 17           cp      r25, r22
    4c74:       08 f4           brcc    .+2             ; 0x4c78 <test+0xa>
    4c76:       81 50           subi    r24, 0x01       ; 1
    4c78:       08 95           ret
But with this commit, it gets translated to a single instruction:
00004c40 <test>:
    4c40:       86 1b           sub     r24, r22
    4c42:       08 95           ret

This unfortunately doesn't always work so nicely, for example the following C code:
int __attribute__ ((noinline)) test(uint8_t current_timer, uint8_t start_timer)
{
    return TIMER_DIFF_8(current_timer, start_timer);
}
(Note: return type changed to int)
With the original code it gets translated to:
00004c6e <test>:
    4c6e:       28 2f           mov     r18, r24
    4c70:       30 e0           ldi     r19, 0x00       ; 0
    4c72:       46 2f           mov     r20, r22
    4c74:       50 e0           ldi     r21, 0x00       ; 0
    4c76:       86 17           cp      r24, r22
    4c78:       20 f0           brcs    .+8             ; 0x4c82 <test+0x14>
    4c7a:       c9 01           movw    r24, r18
    4c7c:       84 1b           sub     r24, r20
    4c7e:       95 0b           sbc     r25, r21
    4c80:       08 95           ret
    4c82:       c9 01           movw    r24, r18
    4c84:       84 1b           sub     r24, r20
    4c86:       95 0b           sbc     r25, r21
    4c88:       81 50           subi    r24, 0x01       ; 1
    4c8a:       9f 4f           sbci    r25, 0xFF       ; 255
    4c8c:       08 95           ret
Wth this commit it gets translated to:
00004c40 <test>:
    4c40:       28 2f           mov     r18, r24
    4c42:       30 e0           ldi     r19, 0x00       ; 0
    4c44:       46 2f           mov     r20, r22
    4c46:       50 e0           ldi     r21, 0x00       ; 0
    4c48:       86 17           cp      r24, r22
    4c4a:       20 f0           brcs    .+8             ; 0x4c54 <test+0x14>
    4c4c:       c9 01           movw    r24, r18
    4c4e:       84 1b           sub     r24, r20
    4c50:       95 0b           sbc     r25, r21
    4c52:       08 95           ret
    4c54:       c9 01           movw    r24, r18
    4c56:       84 1b           sub     r24, r20
    4c58:       95 0b           sbc     r25, r21
    4c5a:       93 95           inc     r25
    4c5c:       08 95           ret
There is not much performance improvement in this case, however at least with this
commit it functions correctly.

Note: The following commit will improve compiler output for the latter example.

* tmk_core/common: Improve code generation for TIMER_DIFF* macros

Because of integer promotion the compiler is having a hard time generating
efficient code to calculate TIMER_DIFF* macros in some situations.
In the below example, the return value is "int", and this is causing the
trouble.

Example C code:

int __attribute__ ((noinline)) test(uint8_t current_timer, uint8_t start_timer)
{
    return TIMER_DIFF_8(current_timer, start_timer);
}

BEFORE: (with -Os)

00004c40 <test>:
    4c40:       28 2f           mov     r18, r24
    4c42:       30 e0           ldi     r19, 0x00       ; 0
    4c44:       46 2f           mov     r20, r22
    4c46:       50 e0           ldi     r21, 0x00       ; 0
    4c48:       86 17           cp      r24, r22
    4c4a:       20 f0           brcs    .+8             ; 0x4c54 <test+0x14>
    4c4c:       c9 01           movw    r24, r18
    4c4e:       84 1b           sub     r24, r20
    4c50:       95 0b           sbc     r25, r21
    4c52:       08 95           ret
    4c54:       c9 01           movw    r24, r18
    4c56:       84 1b           sub     r24, r20
    4c58:       95 0b           sbc     r25, r21
    4c5a:       93 95           inc     r25
    4c5c:       08 95           ret

AFTER: (with -Os)

00004c40 <test>:
    4c40:       86 1b           sub     r24, r22
    4c42:       90 e0           ldi     r25, 0x00       ; 0
    4c44:       08 95           ret

Note: the example is showing -Os but improvements can be seen at all optimization levels,
including -O0. We never use -O0, but I tested it to make sure that no extra code is
generated in that case.OA

* quantum/debounce: Fix custom wrapping timers in eager_pr and eager_pk debounce algorithms

Please see the below simulated sequence of events:
Column A is the 16-bit value returned by read_timer();
Column B is the value returned by custom_wrap_timer_read();
Column C is the original code: (timer_read() % MAX_DEBOUNCE)

    A,     B,     C
65530,    19,    30
65531,    20,    31
65532,    21,    32
65533,    22,    33
65534,    23,    34
65535,    24,    35
    0     25,     0
    1,    26,     1
    2,    27,     2
    3,    28,     3
    4,    29,     4
    5,    30,     5

read_timer() wraps about every 1.09 seconds, and so debouncing might
fail at these times without this commit.

* quantum/debounce/eager_pr and eager_pk: modifications for code readability according to code review.

* quantum/debounce/eager_pr and eager_pk: modifications for code readability according to code review. (2)
2020-04-11 10:14:28 +10:00
skullY
b624f32f94 clang-format changes 2019-08-30 15:01:52 -07:00
Drashna Jaelre
37be1cb513
Fix debouncing issue for eager algorithms (#6081)
* Fix debouncing issue for eager algos

* Fix up typo issue
2019-07-09 11:09:54 -07:00
Alex Ong
7a1086e405 [core] Fix for eager_pr #5643
Added extra transfer_matrix_values() call whenever counters don't need updating
2019-04-18 15:45:36 -07:00
Alex Ong
d0fb7005d5 Eager pk/pr optimization (#5621)
* Optimizations to eager_pk

* eager_pr also uses changed boolean now.
2019-04-15 12:58:03 -07:00
Alex Ong
17e7762de7 Eager Per Row Debouncing added (added to Ergodox) (#5498)
* Implemented Eager Per Row debouncing algorithm.

Good for when fingers can only press one row at a time (e.g. when keyboard is wired so that "rows" are vertical)

* Added documentation for eager_pr

* Ported ergodox_ez to eager_pr debouncing.

* Removed check for changes in matrix_scan.

* Added further clarification in docs.

* Accidental merge with ergodox_ez

* Small cleanup in eager_pr

* Forgot to debounce_init - this would probably cause seg-faults.
2019-04-03 14:45:55 -07:00
James Churchill
c7c4937eef Clean up debounce a bit (#5255) 2019-03-04 07:44:46 -08:00
alex-ong
562c0d702a Fix compile error in debounce_eager_pk 2019-01-27 00:10:14 +11:00
alex-ong
503e02db79 Merge branch 'debounce_refactor' of https://github.com/alex-ong/qmk_firmware into debounce_refactor 2019-01-26 23:21:27 +11:00
alex-ong
10cc423515 Malloc array in debounce_eager_pk, since split keyboards only use MATRIX_ROWS/2. 2019-01-26 23:18:24 +11:00
Alex Ong
039dde3a51 Fixed compilation error with debounce_sym_g 2019-01-26 22:57:39 +11:00
Alex Ong
7cb8d3c7a7 Bug fix - was using MATRIX_ROWS instead of num_rows 2019-01-26 22:45:25 +11:00
alex-ong
14ed96aa06 Moved debouncing_time variable to inside #if debounce 2019-01-26 18:26:49 +11:00
alex-ong
4d8733591f Working eager_pk 2019-01-26 17:29:02 +11:00
alex-ong
123608fb31 DO NOT USE Revert back to original API to support split_keyboards. 2019-01-26 17:10:27 +11:00
alex-ong
d0b691df0e DO NOT USE - debounce successfully compiled. 2019-01-26 17:03:46 +11:00