Open-source keyboard firmware for Atmel AVR and Arm USB families
Find a file
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
.github Force "blank" issue template to end of list (#8387) 2020-03-12 01:27:33 -07:00
.vscode Highlight .inc files as .c files (#8496) 2020-03-20 09:48:55 +01:00
bin Fix edge-case with config 2020-04-08 09:31:14 -07:00
docs Add PS2_MOUSE_ROTATE to compensate for device orientation (#8650) 2020-04-09 01:29:27 -07:00
drivers format code according to conventions [skip ci] 2020-04-08 01:38:16 +00:00
keyboards [Keymap] added vim compatibility, backspace above enter, and general macOS opt… (#8080) 2020-04-10 14:53:13 -07:00
layouts Some refinements of 75_ansi/spidey3 layout (#8581) 2020-04-11 10:10:37 +10:00
lib Don't hide for devs... 2020-04-08 09:31:14 -07:00
quantum Various fixes to how timer differences are calculated (#8585) 2020-04-11 10:14:28 +10:00
tests format code according to conventions [skip ci] 2020-03-13 18:44:56 +00:00
tmk_core Various fixes to how timer differences are calculated (#8585) 2020-04-11 10:14:28 +10:00
users Some refinements of 75_ansi/spidey3 layout (#8581) 2020-04-11 10:10:37 +10:00
util Miscellaneous cleanups (#8639) 2020-04-01 15:49:45 +01:00
.clang-format fix indent size 2019-06-11 01:51:40 -07:00
.clang_complete Vim Layout for Ergodox-EZ (mac only) (#2112) 2017-12-11 21:06:05 -05:00
.editorconfig QMK CLI and JSON keymap support (#6176) 2019-07-15 12:14:27 -07:00
.gitattributes Set eep files to binary mode 2016-08-27 18:37:28 +03:00
.gitignore 2020 February 29 Breaking Changes Update (#8064) 2020-02-29 11:59:30 -08:00
.gitmodules Track master branches for lib/chibios, lib/chibios-contrib, lib/ugfx. (#8273) 2020-03-01 11:51:38 +11:00
.travis.yml Fix unknown key 'IndentPPDirectives' on CI (#7933) 2020-01-19 13:59:57 -08:00
autocomplete.sh Make arguments redo, subproject elimination (#1784) 2017-10-14 11:32:19 -10:00
book.json adds redirects for docs 2017-08-19 08:31:54 -04:00
bootloader.mk Add LUFA mass storage BOOTLOADER "support" (#7729) 2019-12-29 20:53:23 +00:00
build_full_test.mk Add SRC and OPT_DEFS when building tests 2017-07-20 10:17:31 -04:00
build_json.mk Rename qmk json-keymap to qmk json2c (#8372) 2020-03-10 13:51:19 -07:00
build_keyboard.mk Align some ChibiOS build logic (#8461) 2020-03-22 20:48:17 +11:00
build_layout.mk Add a mechanism for force building a particular community layout (#5027) 2019-02-14 20:14:26 -08:00
build_test.mk Initial arm->chibios pass - simplify some platform logic (#8450) 2020-03-21 16:20:04 +11:00
CODE_OF_CONDUCT.md updates the coc 2019-08-24 12:43:39 -04:00
common.mk Move Split Common VPATH addition (#4716) 2018-12-31 08:45:44 -08:00
common_features.mk Add Word Per Minute calculation feature (#8054) 2020-03-23 00:06:16 +11:00
Dockerfile Update docker util script and travis to use new base container 2019-07-14 21:01:38 -07:00
Doxyfile Generate API docs from source code comments (#2491) 2018-03-22 02:50:38 -04:00
doxygen-todo Remove PJRC USB stack 2020-02-08 11:07:43 -08:00
LICENSE add an explicit lisence file for github to pickup 2017-11-13 20:50:54 -05:00
license_GPLv2.md Clarify the quantum license (#1042) 2017-03-28 15:20:36 -07:00
license_GPLv3.md Clarify the quantum license (#1042) 2017-03-28 15:20:36 -07:00
license_Modified_BSD.md Clarify the quantum license (#1042) 2017-03-28 15:20:36 -07:00
Makefile 2020 February 29 Breaking Changes Update (#8064) 2020-02-29 11:59:30 -08:00
message.mk Use FIRMWARE_FORMAT for "Checking file size" message (#8121) 2020-02-10 04:19:08 +11:00
nose2.cfg Setup a python test framework 2019-09-07 07:58:41 -07:00
readme.md Breaking Changes documentation fixes 2020-02-29 12:30:38 -08:00
requirements-dev.txt Use milc for config check, requirements fixes 2020-04-08 09:31:14 -07:00
requirements.txt CLI: Add development mode support 2020-04-08 09:31:14 -07:00
secrets.tar.enc update building for .hex, secrets moving 2017-08-21 21:57:46 -04:00
setup.cfg Add flake8 to our test suite and fix all errors (#7379) 2019-11-20 14:54:18 -08:00
shell.nix Fix up Arm builds with nix-shell. (#8312) 2020-03-07 03:05:51 +11:00
show_options.mk Remove unused LED_BREATHING_TABLE 2020-03-06 22:29:01 -08:00
testlist.mk Add basic infrastrucure for building full tests 2017-06-18 21:08:23 +03:00
Vagrantfile Configure Vagrant to use qmk_base_container (#6194) 2019-07-16 01:20:34 -07:00

Quantum Mechanical Keyboard Firmware

Current Version Build Status Discord Docs Status GitHub contributors GitHub forks

This is a keyboard firmware based on the tmk_keyboard firmware with some useful features for Atmel AVR and ARM controllers, and more specifically, the OLKB product line, the ErgoDox EZ keyboard, and the Clueboard product line.

Documentation

The docs are powered by Docsify and hosted on GitHub. They are also viewable offline; see Previewing the Documentation for more details.

You can request changes by making a fork and opening a pull request, or by clicking the "Edit this page" link at the bottom of any page.

Supported Keyboards

The project also includes community support for lots of other keyboards.

Maintainers

QMK is developed and maintained by Jack Humbert of OLKB with contributions from the community, and of course, Hasu. The OLKB product firmwares are maintained by Jack Humbert, the Ergodox EZ by ZSA Technology Labs, the Clueboard by Zach White, and the Atreus by Phil Hagelberg.

Official Website

qmk.fm is the official website of QMK, where you can find links to this page, the documentation, and the keyboards supported by QMK.