mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-08-06 15:23:28 +00:00
Compare commits
1304 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
10e4487ba3 | ||
![]() |
8ea7f4f45f | ||
![]() |
4b03b6f7f4 | ||
![]() |
1ebd243cdc | ||
![]() |
b185816717 | ||
![]() |
501f2fdef1 | ||
![]() |
5b5d74a267 | ||
![]() |
6c4b6531fe | ||
![]() |
82bb47a2f1 | ||
![]() |
9517d90e84 | ||
![]() |
79d992d1e7 | ||
![]() |
cd67074f72 | ||
![]() |
01c7108db5 | ||
![]() |
f440111b4b | ||
![]() |
56933b9b9f | ||
![]() |
e03d72d71e | ||
![]() |
563723392f | ||
![]() |
2ae700c8c8 | ||
![]() |
666861dd6f | ||
![]() |
35f922df73 | ||
![]() |
af03b92246 | ||
![]() |
d354b1f0a4 | ||
![]() |
95022bc366 | ||
![]() |
399be2a9b3 | ||
![]() |
ab2a43edb0 | ||
![]() |
d17caeb8ec | ||
![]() |
10f7f6009d | ||
![]() |
9346bd6f80 | ||
![]() |
a5a1f860c0 | ||
![]() |
3a69d688f2 | ||
![]() |
e2e6ff43ab | ||
![]() |
b953a585d6 | ||
![]() |
dfeba3f9b6 | ||
![]() |
df3a81b31e | ||
![]() |
f1b082320e | ||
![]() |
8d6ad23b09 | ||
![]() |
a6a1289003 | ||
![]() |
644dd9c388 | ||
![]() |
3076f86dc1 | ||
![]() |
6b1f96dca8 | ||
![]() |
c59f87a5d7 | ||
![]() |
08bf9f9e74 | ||
![]() |
cba76092eb | ||
![]() |
5cf70f3993 | ||
![]() |
54b932e844 | ||
![]() |
9971caa632 | ||
![]() |
15faffacf4 | ||
![]() |
e3888281f4 | ||
![]() |
1e7661651c | ||
![]() |
f05b1b54a9 | ||
![]() |
59832e7654 | ||
![]() |
0f086df89f | ||
![]() |
6ab0a6e796 | ||
![]() |
c1dc676d28 | ||
![]() |
138c3e7042 | ||
![]() |
a5a65fb1e2 | ||
![]() |
fc85ebecd4 | ||
![]() |
2989f9ce2b | ||
![]() |
bcab02b654 | ||
![]() |
3aae5300e2 | ||
![]() |
41347cdcec | ||
![]() |
33802ab5cd | ||
![]() |
eaa8c18174 | ||
![]() |
3a77ef5fa3 | ||
![]() |
1124e51b11 | ||
![]() |
c7dab4bb25 | ||
![]() |
cc08e3082e | ||
![]() |
02fb0de59b | ||
![]() |
8724a70c4c | ||
![]() |
485e4524f4 | ||
![]() |
ce91dd4bf3 | ||
![]() |
5909c243d4 | ||
![]() |
67976da039 | ||
![]() |
05ac139a29 | ||
![]() |
81164c1663 | ||
![]() |
c66df16644 | ||
![]() |
15385d4113 | ||
![]() |
16d55b14b7 | ||
![]() |
c41c8ff780 | ||
![]() |
c21d5a0973 | ||
![]() |
3afe0ea9b9 | ||
![]() |
1c0e8a6bb4 | ||
![]() |
10d9e8ed37 | ||
![]() |
d9613e6a33 | ||
![]() |
9c2cfe5c27 | ||
![]() |
f98e983141 | ||
![]() |
feae8f2980 | ||
![]() |
35b329052c | ||
![]() |
e8a65baf41 | ||
![]() |
d82e002737 | ||
![]() |
c78ef391dc | ||
![]() |
1bf657be41 | ||
![]() |
8897ab9b11 | ||
![]() |
50611bd814 | ||
![]() |
86b0acbae0 | ||
![]() |
24a741649d | ||
![]() |
0a9476bc2a | ||
![]() |
3fadfb565d | ||
![]() |
66b5c5eff2 | ||
![]() |
6e97a4c8b9 | ||
![]() |
429474d1c3 | ||
![]() |
6f9934c669 | ||
![]() |
c84650a147 | ||
![]() |
30afa1ccd3 | ||
![]() |
b8443863c0 | ||
![]() |
c731628946 | ||
![]() |
ca9edc5fe3 | ||
![]() |
a952bf2d31 | ||
![]() |
44d1b2e717 | ||
![]() |
8ddbb19df1 | ||
![]() |
95fd2ce81a | ||
![]() |
23222625c2 | ||
![]() |
4368611bfd | ||
![]() |
ccb15c2d29 | ||
![]() |
628d4a91b9 | ||
![]() |
9454f98099 | ||
![]() |
64572b5c4b | ||
![]() |
776d1adc76 | ||
![]() |
386cff8cf5 | ||
![]() |
e7497b3fba | ||
![]() |
6dc2d5956f | ||
![]() |
88a783a8a7 | ||
![]() |
3aef2bef8f | ||
![]() |
078586b21a | ||
![]() |
7bdc41b025 | ||
![]() |
66d52d8cd2 | ||
![]() |
0f8b0d971f | ||
![]() |
3270cbeb46 | ||
![]() |
ad9674c5af | ||
![]() |
e4aadf2c05 | ||
![]() |
f00402a2f3 | ||
![]() |
e1e13c53ac | ||
![]() |
1512e07817 | ||
![]() |
ad5cbe5982 | ||
![]() |
58f2e0439e | ||
![]() |
ddcb1794fa | ||
![]() |
adfd34c451 | ||
![]() |
3c156e130b | ||
![]() |
10782789be | ||
![]() |
cf3b683232 | ||
![]() |
a8967778d4 | ||
![]() |
503b762538 | ||
![]() |
88c09aa892 | ||
![]() |
69bb9b7386 | ||
![]() |
f3394139de | ||
![]() |
3e0789c961 | ||
![]() |
2ffac90c99 | ||
![]() |
e6a13e0b1c | ||
![]() |
aaea5e24b6 | ||
![]() |
b337ba798e | ||
![]() |
94e94ffb5b | ||
![]() |
cfc9a358c5 | ||
![]() |
e4236278b5 | ||
![]() |
81a17f4270 | ||
![]() |
bb9fbd66e9 | ||
![]() |
5edce6ba26 | ||
![]() |
91b44016f9 | ||
![]() |
45e16fd543 | ||
![]() |
a7afaa36a1 | ||
![]() |
d7c1b890f1 | ||
![]() |
0dee334bce | ||
![]() |
a422309354 | ||
![]() |
683ba8b8d4 | ||
![]() |
aae3b35c0f | ||
![]() |
abf1902ff5 | ||
![]() |
aa90cf1da8 | ||
![]() |
7595f53856 | ||
![]() |
8af767cb1d | ||
![]() |
a9f65b760a | ||
![]() |
53f11668a3 | ||
![]() |
2ef68a84b6 | ||
![]() |
489bee0ee4 | ||
![]() |
ed8d1d1ae7 | ||
![]() |
f38a3b7408 | ||
![]() |
16fe4b8b77 | ||
![]() |
84ca67f158 | ||
![]() |
cb80b59e93 | ||
![]() |
95bbd799a4 | ||
![]() |
1ff5ee255f | ||
![]() |
9cd3ffa5ba | ||
![]() |
ff7f70314e | ||
![]() |
db829c9453 | ||
![]() |
bd1c048a76 | ||
![]() |
4d33d72975 | ||
![]() |
7ce5402417 | ||
![]() |
b5ebdf1b3a | ||
![]() |
d7c90d805f | ||
![]() |
5f2c434954 | ||
![]() |
f2eb080aa2 | ||
![]() |
f12dcb0659 | ||
![]() |
262a607334 | ||
![]() |
7ef98e7f61 | ||
![]() |
d46fa2274c | ||
![]() |
e024147ce5 | ||
![]() |
c60cafae41 | ||
![]() |
38162af5a7 | ||
![]() |
e680af98d2 | ||
![]() |
4ba0cb7ebc | ||
![]() |
4b839db384 | ||
![]() |
e041ec1655 | ||
![]() |
75201c73a0 | ||
![]() |
8e71d3d053 | ||
![]() |
e69da2db2c | ||
![]() |
dc40f00aaf | ||
![]() |
c1481629fd | ||
![]() |
83eecdce22 | ||
![]() |
780b7722fb | ||
![]() |
86ac56cd7f | ||
![]() |
c1e69bcef0 | ||
![]() |
78019c3e21 | ||
![]() |
76bc235508 | ||
![]() |
fed9c97ddb | ||
![]() |
9f0dbc21a3 | ||
![]() |
c731432765 | ||
![]() |
f450bdbb41 | ||
![]() |
4fa1924bd7 | ||
![]() |
7b33897b97 | ||
![]() |
d705918f50 | ||
![]() |
a3f1defcd4 | ||
![]() |
fb579aae49 | ||
![]() |
67654e4a82 | ||
![]() |
952a4c8312 | ||
![]() |
b9ea10a80d | ||
![]() |
4e72224aa3 | ||
![]() |
1bfec6ddd9 | ||
![]() |
db9204c7e1 | ||
![]() |
27b8046867 | ||
![]() |
359aff6c49 | ||
![]() |
36f4f1e9b8 | ||
![]() |
f487b726cd | ||
![]() |
5cecc1ea1e | ||
![]() |
b9ed9d33d3 | ||
![]() |
2ac0927fd7 | ||
![]() |
9dad914841 | ||
![]() |
50481ce7ed | ||
![]() |
74a2edd903 | ||
![]() |
805e13a6d0 | ||
![]() |
fcd55e2f04 | ||
![]() |
8685409784 | ||
![]() |
1d85fe176a | ||
![]() |
a42e3ba2cb | ||
![]() |
c745cbb77a | ||
![]() |
6b1ae7e6aa | ||
![]() |
a602ef75fb | ||
![]() |
1ba93875ba | ||
![]() |
33074bcbad | ||
![]() |
555b1640b2 | ||
![]() |
f149c07d68 | ||
![]() |
2c92ee1f56 | ||
![]() |
0c42f91f4c | ||
![]() |
8ef82c466e | ||
![]() |
ad86894ae7 | ||
![]() |
af455a8368 | ||
![]() |
ac37a94e49 | ||
![]() |
24ae9232e2 | ||
![]() |
14cb662280 | ||
![]() |
3d183ed7a0 | ||
![]() |
4e30f4d102 | ||
![]() |
329eb4b8df | ||
![]() |
bf92957ff2 | ||
![]() |
33bd17a68a | ||
![]() |
7daad08a91 | ||
![]() |
d689f76110 | ||
![]() |
5d2deaca06 | ||
![]() |
8e7517aebc | ||
![]() |
b5f425b275 | ||
![]() |
47ce1a9ed0 | ||
![]() |
85f344db49 | ||
![]() |
225af5d161 | ||
![]() |
870cc37365 | ||
![]() |
9093f877a2 | ||
![]() |
5e9c078c78 | ||
![]() |
fe50bee988 | ||
![]() |
999326acc8 | ||
![]() |
8cbaea9e8d | ||
![]() |
e7d8ccdbb2 | ||
![]() |
c45d7e526c | ||
![]() |
f078980fb1 | ||
![]() |
619eb0071e | ||
![]() |
2b9b267e8e | ||
![]() |
f9bd9d3b26 | ||
![]() |
168ce1a743 | ||
![]() |
120c42255b | ||
![]() |
f9853433c1 | ||
![]() |
caf61a19c6 | ||
![]() |
ca6a3e0832 | ||
![]() |
4b2da8daf4 | ||
![]() |
c3ce06c2e7 | ||
![]() |
9f1f43bb86 | ||
![]() |
c4d87f3073 | ||
![]() |
8bb2eeaabb | ||
![]() |
c492dd7912 | ||
![]() |
7622678bd0 | ||
![]() |
0728a6b753 | ||
![]() |
e468380be6 | ||
![]() |
8456625655 | ||
![]() |
6ad813e811 | ||
![]() |
4d22bc9de0 | ||
![]() |
d49dcdd667 | ||
![]() |
f952d4f7b7 | ||
![]() |
8be058d55d | ||
![]() |
40e694ea0d | ||
![]() |
445cd95d17 | ||
![]() |
7d5ba88e6f | ||
![]() |
704934c427 | ||
![]() |
47ea522e79 | ||
![]() |
f663ba5ed0 | ||
![]() |
de0153f339 | ||
![]() |
3633330e1a | ||
![]() |
855dd2d218 | ||
![]() |
aa1c1c3865 | ||
![]() |
de68d294ec | ||
![]() |
f0a1ab5488 | ||
![]() |
1a2a838bc2 | ||
![]() |
67474f7e3f | ||
![]() |
39c473a639 | ||
![]() |
f871f7a56f | ||
![]() |
e0bdd51177 | ||
![]() |
fba7d4e32f | ||
![]() |
cab49809ad | ||
![]() |
42696a4f8c | ||
![]() |
a4dfa45f37 | ||
![]() |
616dc7dd5d | ||
![]() |
44f9017cb8 | ||
![]() |
3c4fa68000 | ||
![]() |
cb556b7a16 | ||
![]() |
87317a3af6 | ||
![]() |
92b7dff3ae | ||
![]() |
0dc74dd8c4 | ||
![]() |
6529cbac0d | ||
![]() |
139d28eaae | ||
![]() |
a1f129edd5 | ||
![]() |
73699cccbc | ||
![]() |
229dbcc547 | ||
![]() |
c738ce2f65 | ||
![]() |
c0b3034721 | ||
![]() |
f90688e550 | ||
![]() |
0f453bc5f7 | ||
![]() |
21357b658a | ||
![]() |
2c5ad9189c | ||
![]() |
b0dbe7365b | ||
![]() |
af2c506383 | ||
![]() |
59d503e3b9 | ||
![]() |
b63b2106d8 | ||
![]() |
a2af0a352b | ||
![]() |
6aae926b5f | ||
![]() |
49dd1edb69 | ||
![]() |
7437a38899 | ||
![]() |
381884fa9b | ||
![]() |
f706e1e80e | ||
![]() |
46c77febf7 | ||
![]() |
fdbf67e0da | ||
![]() |
bb35f6a6f5 | ||
![]() |
c87b2efef8 | ||
![]() |
2a65709db6 | ||
![]() |
451e600476 | ||
![]() |
6f391094ab | ||
![]() |
5b067ffc16 | ||
![]() |
b4e7d4ffae | ||
![]() |
30c65a2547 | ||
![]() |
4d59657b83 | ||
![]() |
d46b8ef67c | ||
![]() |
adc06c5b3b | ||
![]() |
6c78f80fa1 | ||
![]() |
3d9fff1d28 | ||
![]() |
975c2422f3 | ||
![]() |
a4efb55a39 | ||
![]() |
96ac448a0f | ||
![]() |
216f9ed2c1 | ||
![]() |
c66d65df58 | ||
![]() |
f7e5d712c2 | ||
![]() |
49abff9071 | ||
![]() |
2d4ae0fe7b | ||
![]() |
4f923b1673 | ||
![]() |
cacf495c91 | ||
![]() |
a88cfa395b | ||
![]() |
6e78655e17 | ||
![]() |
b0c8cbe462 | ||
![]() |
962adbea3a | ||
![]() |
7c32fbf493 | ||
![]() |
459f672879 | ||
![]() |
cd0e32ff9e | ||
![]() |
7229997e7d | ||
![]() |
5fbd55999b | ||
![]() |
ff1b625168 | ||
![]() |
fe5bcae8b3 | ||
![]() |
cba4c1deb5 | ||
![]() |
d79fe65291 | ||
![]() |
ee6c86d8e9 | ||
![]() |
0a69225637 | ||
![]() |
b84b6107ff | ||
![]() |
bc79e51990 | ||
![]() |
a67b32425b | ||
![]() |
058737f116 | ||
![]() |
c9a06965c9 | ||
![]() |
2c9ffd4739 | ||
![]() |
f7cffcbcd4 | ||
![]() |
2e402741a8 | ||
![]() |
2013f63134 | ||
![]() |
32661df8cd | ||
![]() |
661f4aaa8a | ||
![]() |
27f9f3196d | ||
![]() |
89446bafb8 | ||
![]() |
2bcac45650 | ||
![]() |
c8cff1489a | ||
![]() |
c4f910b1b3 | ||
![]() |
edebe56f6b | ||
![]() |
3a8e13a74a | ||
![]() |
1afb394d59 | ||
![]() |
1aacbc44d1 | ||
![]() |
793de76bb4 | ||
![]() |
f176daa1ca | ||
![]() |
459ccb681f | ||
![]() |
1fe7743af8 | ||
![]() |
a0467fda38 | ||
![]() |
9e9b604234 | ||
![]() |
eb4cf713bc | ||
![]() |
9395a8700c | ||
![]() |
4bbef61d60 | ||
![]() |
266ff3339a | ||
![]() |
c01eb55109 | ||
![]() |
6e9b4a8309 | ||
![]() |
1e5df7117d | ||
![]() |
6888165b48 | ||
![]() |
8070b1ba88 | ||
![]() |
726499553c | ||
![]() |
1d7e57ab85 | ||
![]() |
0cb7133e0d | ||
![]() |
f63a60a72a | ||
![]() |
f68bb0cc3d | ||
![]() |
2f01c6ee18 | ||
![]() |
10f5767010 | ||
![]() |
b5d6f287d9 | ||
![]() |
3e5e4f7427 | ||
![]() |
a13e918d47 | ||
![]() |
b31df1af94 | ||
![]() |
7a2124db6b | ||
![]() |
45f044907c | ||
![]() |
01d2a03258 | ||
![]() |
1960e25048 | ||
![]() |
8fbea13a8f | ||
![]() |
d78a2b8145 | ||
![]() |
76e35e02cc | ||
![]() |
272b3309dd | ||
![]() |
11c308d436 | ||
![]() |
482c9fbbf2 | ||
![]() |
5ecb1b2d39 | ||
![]() |
8b90822f6e | ||
![]() |
9f36aa640e | ||
![]() |
284a5267d5 | ||
![]() |
d844f5af70 | ||
![]() |
2eeb30cd5a | ||
![]() |
1531087617 | ||
![]() |
c7599bf49f | ||
![]() |
45c2a05e3a | ||
![]() |
fbdc65e2e9 | ||
![]() |
34b9c51d9c | ||
![]() |
50835bb138 | ||
![]() |
e7acd39b78 | ||
![]() |
70fce6564f | ||
![]() |
323c6dfe72 | ||
![]() |
bb1550313c | ||
![]() |
28ff51175b | ||
![]() |
c16ee22784 | ||
![]() |
1b7101f065 | ||
![]() |
c4cc697aef | ||
![]() |
b6f9ca3b09 | ||
![]() |
603c8d1f06 | ||
![]() |
4a83021fe0 | ||
![]() |
9570b1bbb4 | ||
![]() |
4511201d80 | ||
![]() |
5f23f21216 | ||
![]() |
086c9c714e | ||
![]() |
9c596c1c5b | ||
![]() |
cd64425fdd | ||
![]() |
860deb774e | ||
![]() |
ec7ce15c11 | ||
![]() |
30ffae2317 | ||
![]() |
940280c435 | ||
![]() |
940c294d26 | ||
![]() |
f2dec4d3cf | ||
![]() |
ef7c79b781 | ||
![]() |
8711dda0d3 | ||
![]() |
8b9617f93d | ||
![]() |
96101adea9 | ||
![]() |
d828e991a9 | ||
![]() |
afb9179b65 | ||
![]() |
5faf5383ad | ||
![]() |
4bf5f9424e | ||
![]() |
2fbf68f2d2 | ||
![]() |
9c31a7adba | ||
![]() |
1ff51579ec | ||
![]() |
e52fc935b0 | ||
![]() |
539cc45fba | ||
![]() |
57dd756507 | ||
![]() |
e3395beda0 | ||
![]() |
7a3a57e457 | ||
![]() |
0fbb1e550a | ||
![]() |
0976db7e5e | ||
![]() |
207f0b00fa | ||
![]() |
4a37af79e9 | ||
![]() |
e4a4ed3b0c | ||
![]() |
7ddae97c89 | ||
![]() |
ea0cf42eef | ||
![]() |
bfbcfbc83e | ||
![]() |
967ed19d77 | ||
![]() |
342ab6ab80 | ||
![]() |
0b2eae7686 | ||
![]() |
924823cfb4 | ||
![]() |
ccab502241 | ||
![]() |
c23667608c | ||
![]() |
dc037f1391 | ||
![]() |
b86fa3daf3 | ||
![]() |
bc8fe91fd1 | ||
![]() |
e3f9569acd | ||
![]() |
ebbcb83998 | ||
![]() |
6bebb1233d | ||
![]() |
e4cf0a40a5 | ||
![]() |
b3508271f8 | ||
![]() |
c4eb0df428 | ||
![]() |
becaf325a3 | ||
![]() |
2f637e4ea1 | ||
![]() |
0384237544 | ||
![]() |
bc7a745227 | ||
![]() |
7f34a6b635 | ||
![]() |
9f0a2a78a0 | ||
![]() |
fee953c4f8 | ||
![]() |
fb4a6ad30e | ||
![]() |
a2ff3c4d14 | ||
![]() |
ed2ba645c0 | ||
![]() |
e1437c1859 | ||
![]() |
741856dd57 | ||
![]() |
3abb609348 | ||
![]() |
6eab8a0b61 | ||
![]() |
08ef4b4a96 | ||
![]() |
12fe78ee57 | ||
![]() |
bdb1b10e99 | ||
![]() |
a0efe93239 | ||
![]() |
bbfb709a6a | ||
![]() |
0140baf7e0 | ||
![]() |
b0024470ed | ||
![]() |
ccbbf16389 | ||
![]() |
a0305f5e7e | ||
![]() |
c2a0cebf8b | ||
![]() |
ef1b050b32 | ||
![]() |
4bee445c2f | ||
![]() |
7921c5d9b8 | ||
![]() |
72b1ff5899 | ||
![]() |
eee6dd3544 | ||
![]() |
510138f525 | ||
![]() |
07e37c857c | ||
![]() |
a21e487fbc | ||
![]() |
9eeb6048ff | ||
![]() |
f079dd90ed | ||
![]() |
b846480d5a | ||
![]() |
abec529e62 | ||
![]() |
bc010d62ca | ||
![]() |
bc15c4f4ab | ||
![]() |
f37a134f71 | ||
![]() |
f650b03fb7 | ||
![]() |
410d09675a | ||
![]() |
e9b3a12c6e | ||
![]() |
424eeb8af7 | ||
![]() |
97122d203b | ||
![]() |
06d4c0a396 | ||
![]() |
0050033aca | ||
![]() |
b58f9ef1e2 | ||
![]() |
02551ae499 | ||
![]() |
6499eb6a3c | ||
![]() |
2b9f200a2a | ||
![]() |
9e99a9b98c | ||
![]() |
e4d46a1c00 | ||
![]() |
7141de19d9 | ||
![]() |
c82865efab | ||
![]() |
d8d65bbf5f | ||
![]() |
58d7e9fa0e | ||
![]() |
6de4a53c7c | ||
![]() |
3d3c2e1d3f | ||
![]() |
3d4f0028d6 | ||
![]() |
6e948feb6a | ||
![]() |
076b9d482f | ||
![]() |
08f6e64137 | ||
![]() |
4b9c3dc2e5 | ||
![]() |
ba3ec0f081 | ||
![]() |
d3cea9ed93 | ||
![]() |
5f00df0c4c | ||
![]() |
cd73949682 | ||
![]() |
4e3a96ff3e | ||
![]() |
ae7a076964 | ||
![]() |
78d5224a1d | ||
![]() |
088888937a | ||
![]() |
9fe3fc4c04 | ||
![]() |
6b1c58629f | ||
![]() |
3b1abe0dee | ||
![]() |
3b14c032e0 | ||
![]() |
fb66f0a3fb | ||
![]() |
1d8b0ccc81 | ||
![]() |
92e5361fc5 | ||
![]() |
8ea8a80c5b | ||
![]() |
788cbcf828 | ||
![]() |
28e10eedda | ||
![]() |
6c3e404839 | ||
![]() |
f7ccbfcea8 | ||
![]() |
8ac9940a76 | ||
![]() |
ac24f203cc | ||
![]() |
d0eabd083e | ||
![]() |
e0b7c70743 | ||
![]() |
9bca381b98 | ||
![]() |
d612d617ee | ||
![]() |
687d05dfb1 | ||
![]() |
a8a714c46e | ||
![]() |
6e32dd123f | ||
![]() |
82a830196f | ||
![]() |
6a79d99ea2 | ||
![]() |
2e4a75e2bc | ||
![]() |
c3f3b34d7c | ||
![]() |
98278968b7 | ||
![]() |
361003934e | ||
![]() |
c10b011828 | ||
![]() |
6eefc20c2a | ||
![]() |
2282104526 | ||
![]() |
9b9587527f | ||
![]() |
461153150b | ||
![]() |
c1a6b5f430 | ||
![]() |
25e93b4b67 | ||
![]() |
2f26e14dc6 | ||
![]() |
bad589ec59 | ||
![]() |
eead2c6087 | ||
![]() |
04293bcd5b | ||
![]() |
e7cc5a35c2 | ||
![]() |
9808bfaf26 | ||
![]() |
2ab307a940 | ||
![]() |
4086729f5e | ||
![]() |
4701001524 | ||
![]() |
6e618baa57 | ||
![]() |
825ef0bd96 | ||
![]() |
58600d3f65 | ||
![]() |
f145696dad | ||
![]() |
7fe01239dd | ||
![]() |
32910738fd | ||
![]() |
4889625015 | ||
![]() |
744940bbd9 | ||
![]() |
0bec817479 | ||
![]() |
80fd81ad6b | ||
![]() |
d16d866597 | ||
![]() |
0032cb026b | ||
![]() |
854a94f383 | ||
![]() |
4a6cfb06c5 | ||
![]() |
a9a2817f3a | ||
![]() |
4286b81af0 | ||
![]() |
fa740c1286 | ||
![]() |
69804bb243 | ||
![]() |
a3db72df72 | ||
![]() |
000eb14d78 | ||
![]() |
d3721bdff9 | ||
![]() |
c56b9a1ce9 | ||
![]() |
bdd8d2679b | ||
![]() |
629cfc7f5e | ||
![]() |
0f596881b3 | ||
![]() |
15df82cdf3 | ||
![]() |
1de39e5632 | ||
![]() |
b89b2030af | ||
![]() |
fa6cf85727 | ||
![]() |
92385b3fb6 | ||
![]() |
3f392c09b6 | ||
![]() |
47f8947bf5 | ||
![]() |
9ef4526a2f | ||
![]() |
15b5ff1dc2 | ||
![]() |
21a00b7f02 | ||
![]() |
568cae28ec | ||
![]() |
167daa9cf8 | ||
![]() |
d00ac5dfb6 | ||
![]() |
ea43bc8972 | ||
![]() |
dba8148764 | ||
![]() |
12333b7c5e | ||
![]() |
e34eca361f | ||
![]() |
c990dc1e6c | ||
![]() |
200444f8d2 | ||
![]() |
4764aa8711 | ||
![]() |
e6266b19be | ||
![]() |
4b74f985ec | ||
![]() |
d4be07dad3 | ||
![]() |
9d3b26a475 | ||
![]() |
3c74edbc69 | ||
![]() |
686a9d35ff | ||
![]() |
b0335b2731 | ||
![]() |
93e7a8f74c | ||
![]() |
d0abad27ab | ||
![]() |
86e30c2609 | ||
![]() |
c6b7a0d386 | ||
![]() |
8a4a0c25fd | ||
![]() |
60e5733c48 | ||
![]() |
3b34858b77 | ||
![]() |
e7434c874b | ||
![]() |
69e0ad1b2c | ||
![]() |
a3933bdbe7 | ||
![]() |
1193e45bf4 | ||
![]() |
f209f91c7c | ||
![]() |
385d49cc39 | ||
![]() |
5cc3ab38c9 | ||
![]() |
3dbbd4cf44 | ||
![]() |
0f9b7b9768 | ||
![]() |
c9eaf1ac2b | ||
![]() |
d949932c08 | ||
![]() |
2f9eb4cd22 | ||
![]() |
bad662b830 | ||
![]() |
c3ab20511d | ||
![]() |
78362b1dc1 | ||
![]() |
eb84f134c1 | ||
![]() |
b3987d7b3a | ||
![]() |
1f09fcaa69 | ||
![]() |
b338a4d886 | ||
![]() |
1fd2f2f022 | ||
![]() |
c9c63806a7 | ||
![]() |
5460489b51 | ||
![]() |
ecb2121069 | ||
![]() |
1272371f15 | ||
![]() |
80d92525db | ||
![]() |
297bda1c1f | ||
![]() |
5772ac8bf6 | ||
![]() |
958e3f85cb | ||
![]() |
b139d34924 | ||
![]() |
0ea476a311 | ||
![]() |
8937c14514 | ||
![]() |
92da1f0b97 | ||
![]() |
a7cb1ceade | ||
![]() |
42eeb315a5 | ||
![]() |
ac3dfa742a | ||
![]() |
e02f4798f9 | ||
![]() |
cf4b493c24 | ||
![]() |
220b1c9db4 | ||
![]() |
346bfb2a05 | ||
![]() |
0f0530c5a4 | ||
![]() |
08acb7ab68 | ||
![]() |
70ce4ba56f | ||
![]() |
1b0272e801 | ||
![]() |
22ceab9c08 | ||
![]() |
930446fe96 | ||
![]() |
dd763f2988 | ||
![]() |
83c7c66e8c | ||
![]() |
ec7abc2ce2 | ||
![]() |
0b894ca99c | ||
![]() |
cdb69da86e | ||
![]() |
c18cbcc5ad | ||
![]() |
c23e6dff78 | ||
![]() |
4f4c6e04d9 | ||
![]() |
057bc5da80 | ||
![]() |
e4a0a5f4e1 | ||
![]() |
993d4058a1 | ||
![]() |
79f080a43f | ||
![]() |
d57bd0f65c | ||
![]() |
d9fe855923 | ||
![]() |
df1467c86d | ||
![]() |
7c81ae287c | ||
![]() |
3710522549 | ||
![]() |
1ff68165b8 | ||
![]() |
33579efee3 | ||
![]() |
588991af69 | ||
![]() |
5aa55a7154 | ||
![]() |
03090d6571 | ||
![]() |
f99f46773e | ||
![]() |
66de3308e5 | ||
![]() |
0e542b297d | ||
![]() |
c0df341f5c | ||
![]() |
186b1b2ba2 | ||
![]() |
4237d35e83 | ||
![]() |
0d65bbaa44 | ||
![]() |
70acf36d16 | ||
![]() |
c59a81b792 | ||
![]() |
3f5f6030f8 | ||
![]() |
b21faf768e | ||
![]() |
3b09add349 | ||
![]() |
613e5752d7 | ||
![]() |
4c82a40a0a | ||
![]() |
86ea85e3ab | ||
![]() |
3942b6f372 | ||
![]() |
c72c01afd4 | ||
![]() |
cb87f5fbeb | ||
![]() |
d02301e59d | ||
![]() |
b4ae7badd4 | ||
![]() |
2ddcd81020 | ||
![]() |
869b648088 | ||
![]() |
00af37a659 | ||
![]() |
792a480244 | ||
![]() |
febf27361a | ||
![]() |
3b3a1b2a63 | ||
![]() |
194dc0984e | ||
![]() |
e071206c58 | ||
![]() |
48bd8263a3 | ||
![]() |
249eab34e1 | ||
![]() |
7c7feb44b2 | ||
![]() |
f64245b10b | ||
![]() |
acc4bedddc | ||
![]() |
c02666c4cb | ||
![]() |
517f6d2c22 | ||
![]() |
156ed69b46 | ||
![]() |
7c7078faf3 | ||
![]() |
c957eed04b | ||
![]() |
f1299f3292 | ||
![]() |
ce5cdc6f8a | ||
![]() |
e2d4cd1a41 | ||
![]() |
98e1e18f6b | ||
![]() |
215b71716a | ||
![]() |
c7b56bee96 | ||
![]() |
b506c498a7 | ||
![]() |
a536e1bd8f | ||
![]() |
78fef0a46a | ||
![]() |
245797f6b9 | ||
![]() |
a260cbbea6 | ||
![]() |
99905dcfa3 | ||
![]() |
55102ed980 | ||
![]() |
24c898218b | ||
![]() |
7d2cfadb55 | ||
![]() |
06f698a496 | ||
![]() |
395fd7bb56 | ||
![]() |
fc8cf8ec82 | ||
![]() |
242336d475 | ||
![]() |
4e8af9d41b | ||
![]() |
871d35aa43 | ||
![]() |
2d8703f6cc | ||
![]() |
c125d0a7a0 | ||
![]() |
997d1b2bb5 | ||
![]() |
db54a7b79e | ||
![]() |
671d066c84 | ||
![]() |
b531bd3b04 | ||
![]() |
8dc2502177 | ||
![]() |
547410b655 | ||
![]() |
1b4f47c8ee | ||
![]() |
d9fe755f7e | ||
![]() |
c8b721d7c6 | ||
![]() |
60d8d8677a | ||
![]() |
0d04d95326 | ||
![]() |
7222df36e7 | ||
![]() |
b8438c74e3 | ||
![]() |
cb9b81cc10 | ||
![]() |
904c5613f4 | ||
![]() |
37cbf7bcec | ||
![]() |
4c14b11fc7 | ||
![]() |
3df52050c1 | ||
![]() |
349646bfe0 | ||
![]() |
62c0146419 | ||
![]() |
7b85962673 | ||
![]() |
19795a4dcc | ||
![]() |
13de2f415f | ||
![]() |
f047840d0f | ||
![]() |
fb297a5644 | ||
![]() |
2c9e210c36 | ||
![]() |
12fce9b88d | ||
![]() |
00b8a12d06 | ||
![]() |
f8a2401370 | ||
![]() |
3f2521115d | ||
![]() |
0d405ad38e | ||
![]() |
28c78023c5 | ||
![]() |
ea3f74874f | ||
![]() |
a88e690351 | ||
![]() |
0f3e933db9 | ||
![]() |
f3b518ae40 | ||
![]() |
b70ac594c6 | ||
![]() |
a1c89fec72 | ||
![]() |
1a49eb5be1 | ||
![]() |
5bd239e1c0 | ||
![]() |
53b0ee3f7e | ||
![]() |
3d2e5bfe63 | ||
![]() |
3c7fc3c82e | ||
![]() |
2ec2f80bfc | ||
![]() |
6ff08202a5 | ||
![]() |
06cf6982bb | ||
![]() |
1ca7dcb0b2 | ||
![]() |
5d0c38794f | ||
![]() |
83c12a516b | ||
![]() |
08f31f664a | ||
![]() |
9758bcb28b | ||
![]() |
4f7cd5699e | ||
![]() |
bf05f773bd | ||
![]() |
de7da0b48f | ||
![]() |
b3e7a4e798 | ||
![]() |
0091897cc8 | ||
![]() |
758bf20706 | ||
![]() |
ea1c7f1856 | ||
![]() |
a57b313153 | ||
![]() |
7ff85e241b | ||
![]() |
7c7a2be4b0 | ||
![]() |
51dbca2332 | ||
![]() |
bcfb70a4cb | ||
![]() |
296f267f2b | ||
![]() |
14efd8aa41 | ||
![]() |
e999ade100 | ||
![]() |
f5fe6fe5cc | ||
![]() |
84cd07b0d3 | ||
![]() |
6104609afa | ||
![]() |
5cbac94d08 | ||
![]() |
e937fc4513 | ||
![]() |
b0e99c803d | ||
![]() |
463c97f4c6 | ||
![]() |
98f4cb4f87 | ||
![]() |
776b0bd2c9 | ||
![]() |
f0926f6c2a | ||
![]() |
245d355176 | ||
![]() |
c3a9c8c177 | ||
![]() |
1ef5c639ce | ||
![]() |
d939f1041b | ||
![]() |
dfa3017c92 | ||
![]() |
b49c5a562d | ||
![]() |
688426b502 | ||
![]() |
a6a13f9626 | ||
![]() |
d2be3a7339 | ||
![]() |
aaf58155c7 | ||
![]() |
12946d0565 | ||
![]() |
95c742ec27 | ||
![]() |
d91987ab9a | ||
![]() |
db540e2832 | ||
![]() |
a0b10593df | ||
![]() |
65f4b94cda | ||
![]() |
70a37b9cf5 | ||
![]() |
208fbce9a7 | ||
![]() |
21976f47d8 | ||
![]() |
054021e875 | ||
![]() |
f5c2cd2eb7 | ||
![]() |
0e30266711 | ||
![]() |
656a8327f4 | ||
![]() |
1fed91f272 | ||
![]() |
7fe491bb54 | ||
![]() |
7675e80f5c | ||
![]() |
2b960b8bd7 | ||
![]() |
955047dd7d | ||
![]() |
0a5997b0af | ||
![]() |
0adf03c754 | ||
![]() |
2cebac6f2f | ||
![]() |
a50c0049f6 | ||
![]() |
e620a7beb2 | ||
![]() |
d699fd1fb4 | ||
![]() |
e38331d94c | ||
![]() |
e85ec9a09a | ||
![]() |
562b853a8f | ||
![]() |
69abe5b405 | ||
![]() |
a9cb3835ca | ||
![]() |
e1f1e1582e | ||
![]() |
65f803a1de | ||
![]() |
706f1b433c | ||
![]() |
841a2721bc | ||
![]() |
d48e3053b9 | ||
![]() |
d7a4b14bc6 | ||
![]() |
74d3223fb5 | ||
![]() |
3f0292d726 | ||
![]() |
3f96b88e73 | ||
![]() |
5e812cc4be | ||
![]() |
8c8a320e92 | ||
![]() |
43b21cffe0 | ||
![]() |
58c31f5632 | ||
![]() |
1778858e24 | ||
![]() |
19006c9753 | ||
![]() |
2e08c72e95 | ||
![]() |
57f408cff5 | ||
![]() |
c4d778a302 | ||
![]() |
82dcb17338 | ||
![]() |
a8c230743a | ||
![]() |
3c84157d83 | ||
![]() |
4989af356e | ||
![]() |
a2fa12d631 | ||
![]() |
412c6bf447 | ||
![]() |
9aa953ecb4 | ||
![]() |
9fddb1b5fa | ||
![]() |
07a817d3e5 | ||
![]() |
56beaf7d3f | ||
![]() |
3f11f41ec7 | ||
![]() |
4e02253aaf | ||
![]() |
2773082d9d | ||
![]() |
19b70b2737 | ||
![]() |
61b64bb82a | ||
![]() |
f11437aef3 | ||
![]() |
fc13315300 | ||
![]() |
72d3270547 | ||
![]() |
92d0a71af7 | ||
![]() |
08b405e1e9 | ||
![]() |
13eda1b1a2 | ||
![]() |
e8d577c081 | ||
![]() |
ceb3ef955e | ||
![]() |
bc2ebef876 | ||
![]() |
7bdfbde35d | ||
![]() |
584d38b5f5 | ||
![]() |
9307762d76 | ||
![]() |
1b96038115 | ||
![]() |
78f0b5fb02 | ||
![]() |
64603ab647 | ||
![]() |
ca946f6116 | ||
![]() |
63fe92017c | ||
![]() |
817de51c12 | ||
![]() |
6609197cde | ||
![]() |
421621fbf1 | ||
![]() |
21610d245a | ||
![]() |
bdfb1bc2b5 | ||
![]() |
76b21a4b90 | ||
![]() |
027570a21b | ||
![]() |
bd72a577a2 | ||
![]() |
aec4125989 | ||
![]() |
c272b2422b | ||
![]() |
c50009d5d4 | ||
![]() |
823165b9b7 | ||
![]() |
9947f1051d | ||
![]() |
c5e255a417 | ||
![]() |
bae3e03e5f | ||
![]() |
facca23315 | ||
![]() |
071e0c2029 | ||
![]() |
2b55c419ea | ||
![]() |
83e1b9ab6e | ||
![]() |
ca598c3df6 | ||
![]() |
4588c979bd | ||
![]() |
60ee8bddfc | ||
![]() |
5f9fb01020 | ||
![]() |
c4960b7579 | ||
![]() |
d4917318cc | ||
![]() |
047a7f4e33 | ||
![]() |
c8ab8e0bab | ||
![]() |
038a86a9b8 | ||
![]() |
9ae15e8c79 | ||
![]() |
666cb44673 | ||
![]() |
03c790a0f2 | ||
![]() |
29b4f83a1f | ||
![]() |
e6bcc232ed | ||
![]() |
5eb4675fda | ||
![]() |
0fcefdc013 | ||
![]() |
fe744eb1ad | ||
![]() |
85e20a5cf4 | ||
![]() |
da5aed6bef | ||
![]() |
acb9cf12c4 | ||
![]() |
ade3bdf7e7 | ||
![]() |
83bc0b9e80 | ||
![]() |
29ebb99b1f | ||
![]() |
355f075b57 | ||
![]() |
c2ca57c8f4 | ||
![]() |
5c8b23ccff | ||
![]() |
13a8d1681c | ||
![]() |
b30d0361c5 | ||
![]() |
063a74b660 | ||
![]() |
3ff635b9a8 | ||
![]() |
2c98c4dd4e | ||
![]() |
8c66c5aa9b | ||
![]() |
b7dc2eb9ab | ||
![]() |
00fc35539d | ||
![]() |
65c9da5a65 | ||
![]() |
d1819f02df | ||
![]() |
e1cdfdc0e7 | ||
![]() |
97c18bfbc4 | ||
![]() |
0e76b27661 | ||
![]() |
bd4c66a26b | ||
![]() |
7c57efaaf9 | ||
![]() |
d4dc2a577f | ||
![]() |
92839f8a09 | ||
![]() |
907c1c64cf | ||
![]() |
8b9e3e9979 | ||
![]() |
6600f32d35 | ||
![]() |
e9fa41631c | ||
![]() |
91efcfb43a | ||
![]() |
24f59c2d72 | ||
![]() |
398a7e5b3f | ||
![]() |
48db3ad6ef | ||
![]() |
12b43f55d6 | ||
![]() |
6d6340a82b | ||
![]() |
67beec5e94 | ||
![]() |
09a53d1aa3 | ||
![]() |
4f9e5d4cde | ||
![]() |
cf17a8eb95 | ||
![]() |
207b17bc4d | ||
![]() |
1baa99c647 | ||
![]() |
e9e6054ee7 | ||
![]() |
4e4a3449a7 | ||
![]() |
7c17b87215 | ||
![]() |
62ceb46e9d | ||
![]() |
2c0201e80f | ||
![]() |
51509ec07b | ||
![]() |
b215bc3aba | ||
![]() |
0928496220 | ||
![]() |
a8904d47b7 | ||
![]() |
32a47e7af4 | ||
![]() |
b27c20d204 | ||
![]() |
b87895dc12 | ||
![]() |
2344b6865a | ||
![]() |
3d45861216 | ||
![]() |
e184da91a6 | ||
![]() |
d36d5ecfad | ||
![]() |
7baeaae9bb | ||
![]() |
c85e010d45 | ||
![]() |
097df6afdb | ||
![]() |
6574ac52ad | ||
![]() |
751a1789b5 | ||
![]() |
ac7b1d0bf3 | ||
![]() |
7369e195c2 | ||
![]() |
30f4b4d763 | ||
![]() |
9236c3a9d0 | ||
![]() |
c2dd19de51 | ||
![]() |
6d88794960 | ||
![]() |
7a710fb426 | ||
![]() |
c8b35b6230 | ||
![]() |
995464cb9c | ||
![]() |
45c73b13e1 | ||
![]() |
9b85bd68a4 | ||
![]() |
ce91b36c5d | ||
![]() |
2521b970e5 | ||
![]() |
598c392709 | ||
![]() |
4d218566cc | ||
![]() |
a4b2baa2ba | ||
![]() |
4b80ee46f8 | ||
![]() |
9b398a8f31 | ||
![]() |
c30170b868 | ||
![]() |
39b483ad32 | ||
![]() |
88ebf92184 | ||
![]() |
8d792cfb5f | ||
![]() |
bd1b51cbd1 | ||
![]() |
3028662fa3 | ||
![]() |
aea2d6845a | ||
![]() |
a502ce43c3 | ||
![]() |
b0e30862d6 | ||
![]() |
146873fd8e | ||
![]() |
b3b617633c | ||
![]() |
9ae8a45197 | ||
![]() |
a8bb5840ad | ||
![]() |
d353fcb99c | ||
![]() |
f0bde7906d | ||
![]() |
24b0cda3e8 | ||
![]() |
1ab8f969f6 | ||
![]() |
58af0305f5 | ||
![]() |
c7cc20918b | ||
![]() |
924573ece2 | ||
![]() |
5f06fce2c5 | ||
![]() |
4b13c49578 | ||
![]() |
98642ca028 | ||
![]() |
82dc8faaf3 | ||
![]() |
0b09189087 | ||
![]() |
3d6d899666 | ||
![]() |
cb13dd0a33 | ||
![]() |
af4bc251f9 | ||
![]() |
e79fb2c26e | ||
![]() |
3e0f8f9c8b | ||
![]() |
b0a31f0bf3 | ||
![]() |
a91034b802 | ||
![]() |
2f85f6fbff | ||
![]() |
32340e14fb | ||
![]() |
b7da69ec85 | ||
![]() |
f36112e957 | ||
![]() |
30cdf9331a | ||
![]() |
8252f378d9 | ||
![]() |
d7f9e6fcf1 | ||
![]() |
5c07363054 | ||
![]() |
b6e9ef8dd1 | ||
![]() |
e58ab6d326 | ||
![]() |
02781979d6 | ||
![]() |
69b484600f | ||
![]() |
de79d55187 | ||
![]() |
580cb2c1df | ||
![]() |
d9eae3ef03 | ||
![]() |
05e6cc2655 | ||
![]() |
8b572de523 | ||
![]() |
18e561b82c | ||
![]() |
c785148445 | ||
![]() |
b43bdc1c69 | ||
![]() |
5a5ecd7dd9 | ||
![]() |
60be8d9f24 | ||
![]() |
3f85e90126 | ||
![]() |
3eefe31a54 | ||
![]() |
7be65f2cd0 | ||
![]() |
016b4be751 | ||
![]() |
db80209e69 | ||
![]() |
716924de3e | ||
![]() |
d88dca3ca7 | ||
![]() |
9c1097e768 | ||
![]() |
f7eb030e91 | ||
![]() |
aae1814319 | ||
![]() |
78fdd40622 | ||
![]() |
43b6f031b1 | ||
![]() |
3e27ceee42 | ||
![]() |
67f374029d | ||
![]() |
30fd69886d | ||
![]() |
ed528403fd | ||
![]() |
faae375ccd | ||
![]() |
b0fd064491 | ||
![]() |
abf466e57d | ||
![]() |
157319fbd0 | ||
![]() |
39ff121d73 | ||
![]() |
8018f4db2d | ||
![]() |
1a159a38ed | ||
![]() |
a0bf235644 | ||
![]() |
f420741f9b | ||
![]() |
0b7b74f56a | ||
![]() |
80b2b710da | ||
![]() |
3814dacf27 | ||
![]() |
7576f6162e | ||
![]() |
e8a02afc8c | ||
![]() |
357a888d80 | ||
![]() |
7f5656996c | ||
![]() |
b008a9afe6 | ||
![]() |
d8e3294aea | ||
![]() |
a8d073368f | ||
![]() |
44d93285d1 | ||
![]() |
8e0af2f5ba | ||
![]() |
da76734fe0 | ||
![]() |
c029c5b187 | ||
![]() |
294cfd8d33 | ||
![]() |
622e94c6cd | ||
![]() |
ba7f52aaeb | ||
![]() |
307013a2f8 | ||
![]() |
f68abbf6c8 | ||
![]() |
897c4cd175 | ||
![]() |
1f2807c2de | ||
![]() |
b160913309 | ||
![]() |
867fded980 | ||
![]() |
d1730ec760 | ||
![]() |
4057d44989 | ||
![]() |
2bfcb6bfc5 | ||
![]() |
1f42071238 | ||
![]() |
400423d10b | ||
![]() |
54ef02dead | ||
![]() |
044b4aaf01 | ||
![]() |
ccb4b81b3f | ||
![]() |
e269977387 | ||
![]() |
0cb4da2c74 | ||
![]() |
9b0c734733 | ||
![]() |
fffee6ade1 | ||
![]() |
97ddc7ea18 | ||
![]() |
3afd2d81b8 | ||
![]() |
2543bad250 | ||
![]() |
a056d94561 | ||
![]() |
573d1fbb92 | ||
![]() |
437446ba8f | ||
![]() |
8640b43214 | ||
![]() |
09fc6cab34 | ||
![]() |
7e8dc2e570 | ||
![]() |
263536586d | ||
![]() |
7aa4cc9603 | ||
![]() |
e26bc21d14 | ||
![]() |
5c2b46dc47 | ||
![]() |
713d34cda4 | ||
![]() |
cce301ae83 | ||
![]() |
08e08b660c | ||
![]() |
cff3c3bf28 | ||
![]() |
b7cb4111ea | ||
![]() |
184c362324 | ||
![]() |
1d1c0503b6 | ||
![]() |
01e74b0ac6 | ||
![]() |
c0cb2ab1c1 | ||
![]() |
7281e86e98 | ||
![]() |
86812f22e4 | ||
![]() |
b83fb9eb71 | ||
![]() |
3736db6081 | ||
![]() |
b19187c62c | ||
![]() |
4a7725b3ee | ||
![]() |
93a1c5ca16 | ||
![]() |
407d6a2b67 | ||
![]() |
d7523c1260 | ||
![]() |
a7f093b40c | ||
![]() |
b9a38487f3 | ||
![]() |
9f400794c0 | ||
![]() |
12efb28e13 | ||
![]() |
3972978c8d | ||
![]() |
b327d20402 | ||
![]() |
ca451c5aa0 | ||
![]() |
7a75af8342 | ||
![]() |
d03bc3a9c1 | ||
![]() |
c12e429da2 | ||
![]() |
9219f9e724 | ||
![]() |
f4ff225c00 | ||
![]() |
a68b0ed9a2 | ||
![]() |
a2dee4494d | ||
![]() |
6cfc3cd940 | ||
![]() |
e84e9a2004 | ||
![]() |
232b9dabbe | ||
![]() |
7b2c09de59 | ||
![]() |
e571f53ae9 | ||
![]() |
6fc4f1eddd | ||
![]() |
be73820f7b | ||
![]() |
81a2113cbd | ||
![]() |
d17572b125 | ||
![]() |
517d607fa4 | ||
![]() |
1110fe6c6f | ||
![]() |
eefc05e078 | ||
![]() |
f1e09dd388 | ||
![]() |
0def9ed528 | ||
![]() |
c73125eea7 | ||
![]() |
306d02aa93 | ||
![]() |
b8ddfd34ec | ||
![]() |
14eccef7bf | ||
![]() |
aab5c44c7d | ||
![]() |
563d5919b3 | ||
![]() |
0fee906e09 | ||
![]() |
c2fd7f1b5b | ||
![]() |
faa3e62e70 | ||
![]() |
5f5a6fff8b | ||
![]() |
f1c33423b0 | ||
![]() |
5f8e8540fb | ||
![]() |
4f6f7b59cf | ||
![]() |
e2e287ec5f | ||
![]() |
dfcd4f0d25 | ||
![]() |
b2271d984d | ||
![]() |
8d3fca57a3 | ||
![]() |
fced377ac0 | ||
![]() |
7b8a013826 | ||
![]() |
5263dfd465 | ||
![]() |
13206b2f87 | ||
![]() |
cb9be8a9dc | ||
![]() |
a1af8542c7 | ||
![]() |
1a5dc278bc | ||
![]() |
10c1e1b3ab | ||
![]() |
00c1401d3c | ||
![]() |
a9b3c0a807 | ||
![]() |
406dc2fb2d |
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -26,7 +26,8 @@
|
||||
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
- [ ] My code follows the code style of this project.
|
||||
- [ ] My code follows the code style of this project: [**C**](https://docs.qmk.fm/#/coding_conventions_c), [**Python**](https://docs.qmk.fm/#/coding_conventions_python)
|
||||
- [ ] I have read the [**PR Checklist** document](https://docs.qmk.fm/#/pr_checklist) and have made the appropriate changes.
|
||||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have read the [**CONTRIBUTING** document](https://docs.qmk.fm/#/contributing).
|
||||
|
42
.github/labeler.yml
vendored
Normal file
42
.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
core:
|
||||
- quantum/**/*
|
||||
- tmk_core/**/*
|
||||
- drivers/**/*
|
||||
- tests/**/*
|
||||
- util/**/*
|
||||
- platforms/**/*
|
||||
- Makefile
|
||||
- '*.mk'
|
||||
dependencies:
|
||||
- any:
|
||||
- 'lib/**/*'
|
||||
- '!lib/python/**/*'
|
||||
keyboard:
|
||||
- any:
|
||||
- 'keyboards/**/*'
|
||||
- '!keyboards/**/keymaps/**/*'
|
||||
keymap:
|
||||
- users/**/*
|
||||
- layouts/**/*
|
||||
- keyboards/**/keymaps/**/*
|
||||
via:
|
||||
- keyboards/**/keymaps/via/*
|
||||
cli:
|
||||
- bin/qmk
|
||||
- requirements.txt
|
||||
- lib/python/**/*
|
||||
python:
|
||||
- '**/*.py'
|
||||
documentation:
|
||||
- docs/**/*
|
||||
translation:
|
||||
- docs/fr-fr/**/*
|
||||
- docs/es/**/*
|
||||
- docs/ja/**/*
|
||||
- docs/he-il/**/*
|
||||
- docs/pt-br/**/*
|
||||
- docs/zh-cn/**/*
|
||||
- docs/de/**/*
|
||||
- docs/ru-ru/**/*
|
||||
CI:
|
||||
- .github/**/*
|
42
.github/workflows/api.yml
vendored
Normal file
42
.github/workflows/api.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Update API Data
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'keyboards/**'
|
||||
- 'layouts/community/**'
|
||||
|
||||
jobs:
|
||||
api_data:
|
||||
runs-on: ubuntu-latest
|
||||
container: qmkfm/base_container
|
||||
|
||||
# protect against those who develop with their fork on master
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Generate API Data
|
||||
run: qmk generate-api
|
||||
|
||||
- name: Install rsync
|
||||
run: |
|
||||
apt-get update && apt-get install -y rsync
|
||||
|
||||
- name: Upload API Data
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
with:
|
||||
ACCESS_TOKEN: ${{ secrets.API_TOKEN_GITHUB }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BRANCH: main
|
||||
FOLDER: api_data/v1
|
||||
CLEAN: true
|
||||
GIT_CONFIG_EMAIL: hello@qmk.fm
|
||||
REPOSITORY_NAME: qmk/qmk_keyboards
|
||||
TARGET_FOLDER: v1
|
33
.github/workflows/auto_tag.yaml
vendored
Normal file
33
.github/workflows/auto_tag.yaml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Essential files modified
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- quantum/**/*
|
||||
- tmk_core/**/*
|
||||
- drivers/**/*
|
||||
- tests/**/*
|
||||
- util/**/*
|
||||
- platforms/**/*
|
||||
- Makefile
|
||||
- '*.mk'
|
||||
|
||||
jobs:
|
||||
tag:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# protect against those who develop with their fork on master
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Bump version and push tag
|
||||
uses: anothrNick/github-tag-action@1.26.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DEFAULT_BUMP: 'patch'
|
42
.github/workflows/develop_api.yml
vendored
Normal file
42
.github/workflows/develop_api.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Update Develop API Data
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- 'keyboards/**'
|
||||
- 'layouts/community/**'
|
||||
|
||||
jobs:
|
||||
api_data:
|
||||
runs-on: ubuntu-latest
|
||||
container: qmkfm/base_container
|
||||
|
||||
# protect against those who work in their fork on develop
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Generate API Data
|
||||
run: qmk generate-api
|
||||
|
||||
- name: Install rsync
|
||||
run: |
|
||||
apt-get update && apt-get install -y rsync
|
||||
|
||||
- name: Upload API Data
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
with:
|
||||
ACCESS_TOKEN: ${{ secrets.API_TOKEN_GITHUB }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BRANCH: main
|
||||
FOLDER: api_data/v1
|
||||
CLEAN: true
|
||||
GIT_CONFIG_EMAIL: hello@qmk.fm
|
||||
REPOSITORY_NAME: qmk/qmk_keyboards_devel
|
||||
TARGET_FOLDER: v1
|
37
.github/workflows/develop_update.yml
vendored
Normal file
37
.github/workflows/develop_update.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Update develop after master merge
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
|
||||
jobs:
|
||||
develop_update:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout develop
|
||||
run: |
|
||||
git fetch origin master develop
|
||||
git checkout develop
|
||||
|
||||
- name: Check if branch locked
|
||||
id: check_locked
|
||||
uses: andstor/file-existence-action@v1
|
||||
with:
|
||||
files: ".locked"
|
||||
|
||||
- name: Update develop from master
|
||||
if: steps.check_locked.outputs.files_exists == 'false'
|
||||
run: |
|
||||
git config --global user.name "QMK Bot"
|
||||
git config --global user.email "hello@qmk.fm"
|
||||
git merge origin/master
|
||||
git push origin develop
|
43
.github/workflows/docs.yml
vendored
Normal file
43
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Generate Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'tmk_core/**'
|
||||
- 'quantum/**'
|
||||
- 'platforms/**'
|
||||
- 'docs/**'
|
||||
- '.github/workflows/docs.yml'
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: ubuntu-latest
|
||||
container: qmkfm/base_container
|
||||
|
||||
# protect against those who develop with their fork on master
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update && apt-get install -y rsync nodejs npm doxygen
|
||||
npm install -g moxygen
|
||||
|
||||
- name: Build docs
|
||||
run: |
|
||||
qmk --verbose generate-docs
|
||||
|
||||
- name: Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BASE_BRANCH: master
|
||||
BRANCH: gh-pages
|
||||
FOLDER: .build/docs
|
||||
GIT_CONFIG_EMAIL: hello@qmk.fm
|
34
.github/workflows/format.yaml
vendored
Normal file
34
.github/workflows/format.yaml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Format Codebase
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
container: qmkfm/base_container
|
||||
|
||||
# protect against those who develop with their fork on master
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update && apt-get install -y dos2unix
|
||||
|
||||
- name: Format files
|
||||
run: |
|
||||
bin/qmk cformat -a
|
||||
bin/qmk pyformat
|
||||
bin/qmk fileformat
|
||||
|
||||
- name: Commit files
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "Format code according to conventions for ${GITHUB_SHA}"
|
||||
commit_user_name: QMK Bot
|
||||
commit_user_email: hello@qmk.fm
|
14
.github/workflows/labeler.yml
vendored
Normal file
14
.github/workflows/labeler.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: "Pull Request Labeler"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, ready_for_review, locked]
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@main
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
configuration-path: '.github/labeler.yml'
|
55
.github/workflows/lint.yml
vendored
Normal file
55
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: PR Lint keyboards
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'keyboards/**'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: qmkfm/base_container
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: trilom/file-changes-action@v1.2.4
|
||||
id: file_changes
|
||||
with:
|
||||
output: '\n'
|
||||
|
||||
- name: Print info
|
||||
run: |
|
||||
git rev-parse --short HEAD
|
||||
echo ${{ github.event.pull_request.base.sha }}
|
||||
echo '${{ steps.file_changes.outputs.files}}'
|
||||
|
||||
- name: Run qmk lint
|
||||
shell: 'bash {0}'
|
||||
run: |
|
||||
QMK_CHANGES=$(echo -e '${{ steps.file_changes.outputs.files}}')
|
||||
QMK_KEYBOARDS=$(qmk list-keyboards)
|
||||
|
||||
exit_code=0
|
||||
for KB in $QMK_KEYBOARDS; do
|
||||
KEYBOARD_CHANGES=$(echo "$QMK_CHANGES" | grep -E '^(keyboards/'${KB}'/)')
|
||||
if [[ -z "$KEYBOARD_CHANGES" ]]; then
|
||||
# skip as no changes for this keyboard
|
||||
continue
|
||||
fi
|
||||
|
||||
KEYMAP_ONLY=$(echo "$KEYBOARD_CHANGES" | grep -cv /keymaps/)
|
||||
if [[ $KEYMAP_ONLY -gt 0 ]]; then
|
||||
echo "linting ${KB}"
|
||||
|
||||
qmk lint --keyboard ${KB} && qmk info -l --keyboard ${KB}
|
||||
exit_code=$(($exit_code + $?))
|
||||
fi
|
||||
done
|
||||
if [[ $exit_code -gt 255 ]]; then
|
||||
exit 255
|
||||
fi
|
||||
exit $exit_code
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -16,6 +16,7 @@
|
||||
*.swp
|
||||
tags
|
||||
*~
|
||||
api_data/v1
|
||||
build/
|
||||
.build/
|
||||
*.bak
|
||||
@@ -73,3 +74,6 @@ __pycache__
|
||||
|
||||
# prerequisites for updating ChibiOS
|
||||
/util/fmpp*
|
||||
|
||||
# Allow to exist but don't include it in the repo
|
||||
user_song_list.h
|
||||
|
8
.gitmodules
vendored
8
.gitmodules
vendored
@@ -12,7 +12,13 @@
|
||||
branch = master
|
||||
[submodule "lib/googletest"]
|
||||
path = lib/googletest
|
||||
url = https://github.com/google/googletest
|
||||
url = https://github.com/qmk/googletest
|
||||
[submodule "lib/lufa"]
|
||||
path = lib/lufa
|
||||
url = https://github.com/qmk/lufa
|
||||
[submodule "lib/vusb"]
|
||||
path = lib/vusb
|
||||
url = https://github.com/qmk/v-usb
|
||||
[submodule "lib/printf"]
|
||||
path = lib/printf
|
||||
url = https://github.com/qmk/printf
|
||||
|
@@ -18,20 +18,15 @@ addons:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-7
|
||||
packages:
|
||||
- pandoc
|
||||
- diffutils
|
||||
- dos2unix
|
||||
- doxygen
|
||||
- clang-format-7
|
||||
- libstdc++-7-dev
|
||||
install:
|
||||
- npm install -g moxygen
|
||||
script:
|
||||
- git fetch --depth=50 origin $TRAVIS_BRANCH:$TRAVIS_BRANCH
|
||||
- git rev-parse --short HEAD
|
||||
- git diff --name-only HEAD $TRAVIS_BRANCH
|
||||
- bash util/travis_test.sh
|
||||
- bash util/travis_build.sh
|
||||
- bash util/travis_docs.sh
|
||||
after_script:
|
||||
bash util/travis_compiled_push.sh
|
||||
notifications:
|
||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -16,7 +16,8 @@
|
||||
"*.hpp": "cpp",
|
||||
"xstddef": "c",
|
||||
"type_traits": "c",
|
||||
"utility": "c"
|
||||
"utility": "c",
|
||||
"ranges": "c"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.trimAutoWhitespace": false,
|
||||
|
30
Makefile
30
Makefile
@@ -272,11 +272,24 @@ endef
|
||||
define PARSE_RULE
|
||||
RULE := $1
|
||||
COMMANDS :=
|
||||
REQUIRE_PLATFORM_KEY :=
|
||||
# If the rule starts with all, then continue the parsing from
|
||||
# PARSE_ALL_KEYBOARDS
|
||||
ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all),true)
|
||||
KEYBOARD_RULE=all
|
||||
$$(eval $$(call PARSE_ALL_KEYBOARDS))
|
||||
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-avr),true)
|
||||
KEYBOARD_RULE=all
|
||||
REQUIRE_PLATFORM_KEY := avr
|
||||
$$(eval $$(call PARSE_ALL_KEYBOARDS))
|
||||
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-chibios),true)
|
||||
KEYBOARD_RULE=all
|
||||
REQUIRE_PLATFORM_KEY := chibios
|
||||
$$(eval $$(call PARSE_ALL_KEYBOARDS))
|
||||
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-arm_atsam),true)
|
||||
KEYBOARD_RULE=all
|
||||
REQUIRE_PLATFORM_KEY := arm_atsam
|
||||
$$(eval $$(call PARSE_ALL_KEYBOARDS))
|
||||
else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,test),true)
|
||||
$$(eval $$(call PARSE_TEST))
|
||||
# If the rule starts with the name of a known keyboard, then continue
|
||||
@@ -447,7 +460,7 @@ define PARSE_KEYMAP
|
||||
# Format it in bold
|
||||
KB_SP := $(BOLD)$$(KB_SP)$(NO_COLOR)
|
||||
# Specify the variables that we are passing forward to submake
|
||||
MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM)
|
||||
MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY)
|
||||
# And the first part of the make command
|
||||
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_keyboard.mk $$(MAKE_TARGET)
|
||||
# The message to display
|
||||
@@ -466,6 +479,8 @@ define BUILD
|
||||
LOG=$$$$($$(MAKE_CMD) $$(MAKE_VARS) SILENT=true 2>&1) ; \
|
||||
if [ $$$$? -gt 0 ]; \
|
||||
then $$(PRINT_ERROR_PLAIN); \
|
||||
elif [ "$$$$LOG" = "skipped" ] ; \
|
||||
then $$(PRINT_SKIPPED_PLAIN); \
|
||||
elif [ "$$$$LOG" != "" ] ; \
|
||||
then $$(PRINT_WARNING_PLAIN); \
|
||||
else \
|
||||
@@ -562,14 +577,16 @@ endef
|
||||
%:
|
||||
# Check if we have the CMP tool installed
|
||||
cmp $(ROOT_DIR)/Makefile $(ROOT_DIR)/Makefile >/dev/null 2>&1; if [ $$? -gt 0 ]; then printf "$(MSG_NO_CMP)"; exit 1; fi;
|
||||
# Ensure that python3 is installed. This check can be removed after python is used in more places.
|
||||
if ! python3 --version 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; fi
|
||||
# Ensure that bin/qmk works. This will be a failing check after the next develop merge on 2020 Aug 29.
|
||||
if ! bin/qmk hello 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; fi
|
||||
# Check if the submodules are dirty, and display a warning if they are
|
||||
ifndef SKIP_GIT
|
||||
if [ ! -e lib/chibios ]; then git submodule sync lib/chibios && git submodule update --depth 50 --init lib/chibios; fi
|
||||
if [ ! -e lib/chibios-contrib ]; then git submodule sync lib/chibios-contrib && git submodule update --depth 50 --init lib/chibios-contrib; fi
|
||||
if [ ! -e lib/ugfx ]; then git submodule sync lib/ugfx && git submodule update --depth 50 --init lib/ugfx; fi
|
||||
if [ ! -e lib/lufa ]; then git submodule sync lib/lufa && git submodule update --depth 50 --init lib/lufa; fi
|
||||
if [ ! -e lib/vusb ]; then git submodule sync lib/vusb && git submodule update --depth 50 --init lib/vusb; fi
|
||||
if [ ! -e lib/printf ]; then git submodule sync lib/printf && git submodule update --depth 50 --init lib/printf; fi
|
||||
git submodule status --recursive 2>/dev/null | \
|
||||
while IFS= read -r x; do \
|
||||
case "$$x" in \
|
||||
@@ -635,12 +652,13 @@ else
|
||||
endif
|
||||
ifndef SKIP_VERSION
|
||||
BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S")
|
||||
else
|
||||
BUILD_DATE := 2020-01-01-00:00:00
|
||||
endif
|
||||
|
||||
$(shell echo '#define QMK_VERSION "$(GIT_VERSION)"' > $(ROOT_DIR)/quantum/version.h)
|
||||
$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(ROOT_DIR)/quantum/version.h)
|
||||
$(shell echo '#define CHIBIOS_VERSION "$(CHIBIOS_VERSION)"' >> $(ROOT_DIR)/quantum/version.h)
|
||||
$(shell echo '#define CHIBIOS_CONTRIB_VERSION "$(CHIBIOS_CONTRIB_VERSION)"' >> $(ROOT_DIR)/quantum/version.h)
|
||||
else
|
||||
BUILD_DATE := NA
|
||||
endif
|
||||
|
||||
include $(ROOT_DIR)/testlist.mk
|
||||
|
1
api_data/_config.yml
Normal file
1
api_data/_config.yml
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-cayman
|
5
api_data/readme.md
Normal file
5
api_data/readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# QMK Keyboard Metadata
|
||||
|
||||
This directory contains machine parsable data about keyboards supported by QMK. The latest version is always available online at <https://keyboards.qmk.fm>.
|
||||
|
||||
Do not edit anything here by hand. It is generated with the `qmk generate-api` command.
|
@@ -27,6 +27,8 @@
|
||||
# qmk-dfu QMK DFU (LUFA + blinkenlight)
|
||||
# bootloadHID HIDBootFlash compatible (ATmega32A)
|
||||
# USBasp USBaspLoader (ATmega328P)
|
||||
# kiibohd Input:Club Kiibohd bootloader (only used on their boards)
|
||||
# stm32duino STM32Duino (STM32F103x8)
|
||||
#
|
||||
# BOOTLOADER_SIZE can still be defined manually, but it's recommended
|
||||
# you add any possible configuration to this list
|
||||
@@ -34,30 +36,30 @@
|
||||
ifeq ($(strip $(BOOTLOADER)), atmel-dfu)
|
||||
OPT_DEFS += -DBOOTLOADER_ATMEL_DFU
|
||||
OPT_DEFS += -DBOOTLOADER_DFU
|
||||
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
ifneq (,$(filter $(MCU), at90usb1286 at90usb1287))
|
||||
BOOTLOADER_SIZE = 8192
|
||||
endif
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), lufa-dfu)
|
||||
OPT_DEFS += -DBOOTLOADER_LUFA_DFU
|
||||
OPT_DEFS += -DBOOTLOADER_DFU
|
||||
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
ifneq (,$(filter $(MCU), at90usb1286 at90usb1287))
|
||||
BOOTLOADER_SIZE = 8192
|
||||
endif
|
||||
endif
|
||||
ifeq ($(strip $(BOOTLOADER)), qmk-dfu)
|
||||
OPT_DEFS += -DBOOTLOADER_QMK_DFU
|
||||
OPT_DEFS += -DBOOTLOADER_DFU
|
||||
ifneq (,$(filter $(MCU), at90usb646 atmega16u2 atmega16u4 atmega32u2 atmega32u4))
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
|
||||
BOOTLOADER_SIZE = 4096
|
||||
endif
|
||||
ifeq ($(strip $(MCU)), at90usb1286)
|
||||
ifneq (,$(filter $(MCU), at90usb1286 at90usb1287))
|
||||
BOOTLOADER_SIZE = 8192
|
||||
endif
|
||||
endif
|
||||
@@ -89,7 +91,30 @@ ifeq ($(strip $(BOOTLOADER)), lufa-ms)
|
||||
BOOTLOADER_SIZE = 6144
|
||||
FIRMWARE_FORMAT = bin
|
||||
endif
|
||||
|
||||
ifdef BOOTLOADER_SIZE
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=$(strip $(BOOTLOADER_SIZE))
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(BOOTLOADER)), kiibohd)
|
||||
OPT_DEFS += -DBOOTLOADER_KIIBOHD
|
||||
ifeq ($(strip $(MCU_ORIG)), MK20DX128)
|
||||
MCU_LDSCRIPT = MK20DX128BLDR4
|
||||
endif
|
||||
ifeq ($(strip $(MCU_ORIG)), MK20DX256)
|
||||
MCU_LDSCRIPT = MK20DX256BLDR8
|
||||
endif
|
||||
|
||||
DFU_ARGS = -d 1C11:B007
|
||||
DFU_SUFFIX_ARGS = -v 1C11 -p B007
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(BOOTLOADER)), stm32duino)
|
||||
OPT_DEFS += -DBOOTLOADER_STM32DUINO
|
||||
MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
|
||||
BOARD = STM32_F103_STM32DUINO
|
||||
# STM32F103 does NOT have an USB bootloader in ROM (only serial), so setting anything here does not make much sense
|
||||
STM32_BOOTLOADER_ADDRESS = 0x80000000
|
||||
|
||||
DFU_ARGS = -d 1EAF:0003 -a2 -R
|
||||
DFU_SUFFIX_ARGS = -v 1EAF -p 0003
|
||||
endif
|
||||
|
@@ -16,7 +16,6 @@ include common.mk
|
||||
KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD))
|
||||
TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP)
|
||||
KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE)
|
||||
STM32_PATH := quantum/stm32
|
||||
|
||||
# Force expansion
|
||||
TARGET := $(TARGET)
|
||||
@@ -138,7 +137,7 @@ endif
|
||||
|
||||
ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes)
|
||||
TARGET := $(TARGET)_proton_c
|
||||
include $(STM32_PATH)/proton_c.mk
|
||||
include platforms/chibios/GENERIC_STM32_F303XC/configs/proton_c.mk
|
||||
OPT_DEFS += -DCONVERT_TO_PROTON_C
|
||||
endif
|
||||
|
||||
@@ -148,12 +147,6 @@ endif
|
||||
|
||||
include quantum/mcu_selection.mk
|
||||
|
||||
ifdef MCU_FAMILY
|
||||
OPT_DEFS += -DQMK_STM32
|
||||
KEYBOARD_PATHS += $(STM32_PATH)
|
||||
endif
|
||||
|
||||
|
||||
# Find all the C source files to be compiled in subfolders.
|
||||
KEYBOARD_SRC :=
|
||||
|
||||
@@ -324,6 +317,13 @@ SRC += $(TMK_COMMON_SRC)
|
||||
OPT_DEFS += $(TMK_COMMON_DEFS)
|
||||
EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS)
|
||||
|
||||
SKIP_COMPILE := no
|
||||
ifneq ($(REQUIRE_PLATFORM_KEY),)
|
||||
ifneq ($(REQUIRE_PLATFORM_KEY),$(PLATFORM_KEY))
|
||||
SKIP_COMPILE := yes
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(TMK_PATH)/$(PLATFORM_KEY).mk
|
||||
ifneq ($(strip $(PROTOCOL)),)
|
||||
include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk
|
||||
@@ -359,7 +359,13 @@ $(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC) $(GFXINC)
|
||||
$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
|
||||
|
||||
# Default target.
|
||||
ifeq ($(SKIP_COMPILE),no)
|
||||
all: build check-size
|
||||
else
|
||||
all:
|
||||
echo "skipped" >&2
|
||||
endif
|
||||
|
||||
build: elf cpfirmware
|
||||
check-size: build
|
||||
objs-size: build
|
||||
|
@@ -3,8 +3,14 @@ LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/))))
|
||||
|
||||
define SEARCH_LAYOUTS_REPO
|
||||
LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP)
|
||||
LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json
|
||||
LAYOUT_KEYMAP_C := $$(LAYOUT_KEYMAP_PATH)/keymap.c
|
||||
ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","")
|
||||
ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_JSON))","")
|
||||
-include $$(LAYOUT_KEYMAP_PATH)/rules.mk
|
||||
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
|
||||
KEYMAP_JSON := $$(LAYOUT_KEYMAP_JSON)
|
||||
KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH)
|
||||
else ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","")
|
||||
-include $$(LAYOUT_KEYMAP_PATH)/rules.mk
|
||||
KEYMAP_C := $$(LAYOUT_KEYMAP_C)
|
||||
KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH)
|
||||
@@ -24,4 +30,7 @@ ifneq ($(FORCE_LAYOUT),)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS)))
|
||||
$(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS)))
|
||||
|
||||
# Use rule from build_json.mk, but update prerequisite in case KEYMAP_JSON was updated
|
||||
$(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
|
||||
|
@@ -49,6 +49,7 @@ endif
|
||||
|
||||
include common_features.mk
|
||||
include $(TMK_PATH)/common.mk
|
||||
include $(QUANTUM_PATH)/sequencer/tests/rules.mk
|
||||
include $(QUANTUM_PATH)/serial_link/tests/rules.mk
|
||||
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
|
||||
include build_full_test.mk
|
||||
|
@@ -21,4 +21,5 @@ COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras
|
||||
COMMON_VPATH += $(QUANTUM_PATH)/audio
|
||||
COMMON_VPATH += $(QUANTUM_PATH)/process_keycode
|
||||
COMMON_VPATH += $(QUANTUM_PATH)/api
|
||||
COMMON_VPATH += $(QUANTUM_PATH)/sequencer
|
||||
COMMON_VPATH += $(DRIVER_PATH)
|
||||
|
@@ -17,9 +17,15 @@ SERIAL_PATH := $(QUANTUM_PATH)/serial_link
|
||||
|
||||
QUANTUM_SRC += \
|
||||
$(QUANTUM_DIR)/quantum.c \
|
||||
$(QUANTUM_DIR)/led.c \
|
||||
$(QUANTUM_DIR)/keymap_common.c \
|
||||
$(QUANTUM_DIR)/keycode_config.c
|
||||
|
||||
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
|
||||
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
|
||||
CONSOLE_ENABLE = yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
|
||||
OPT_DEFS += -DAPI_SYSEX_ENABLE
|
||||
OPT_DEFS += -DAPI_ENABLE
|
||||
@@ -38,6 +44,13 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/audio/luts.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(SEQUENCER_ENABLE)), yes)
|
||||
OPT_DEFS += -DSEQUENCER_ENABLE
|
||||
MUSIC_ENABLE = yes
|
||||
SRC += $(QUANTUM_DIR)/sequencer/sequencer.c
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(MIDI_ENABLE)), yes)
|
||||
OPT_DEFS += -DMIDI_ENABLE
|
||||
MUSIC_ENABLE = yes
|
||||
@@ -114,6 +127,17 @@ else
|
||||
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
|
||||
OPT_DEFS += -DEEPROM_EMU_STM32F072xB
|
||||
OPT_DEFS += -DSTM32_EEPROM_ENABLE
|
||||
else ifeq ($(MCU_SERIES)_$(MCU_LDSCRIPT), STM32F0xx_STM32F042x6)
|
||||
|
||||
# Stack sizes: Since this chip has limited RAM capacity, the stack area needs to be reduced.
|
||||
# This ensures that the EEPROM page buffer fits into RAM
|
||||
USE_PROCESS_STACKSIZE = 0x600
|
||||
USE_EXCEPTIONS_STACKSIZE = 0x300
|
||||
|
||||
SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
|
||||
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
|
||||
OPT_DEFS += -DEEPROM_EMU_STM32F042x6
|
||||
OPT_DEFS += -DSTM32_EEPROM_ENABLE
|
||||
else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
|
||||
OPT_DEFS += -DEEPROM_DRIVER
|
||||
COMMON_VPATH += $(DRIVER_PATH)/eeprom
|
||||
@@ -144,12 +168,14 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom
|
||||
|
||||
LED_MATRIX_ENABLE ?= no
|
||||
ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
|
||||
ifeq ($(filter $(LED_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
|
||||
$(error LED_MATRIX_ENABLE="$(LED_MATRIX_ENABLE)" is not a valid matrix type)
|
||||
VALID_LED_MATRIX_TYPES := IS31FL3731 custom
|
||||
# TODO: IS31FL3733 IS31FL3737 IS31FL3741
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
|
||||
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
|
||||
$(error LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type)
|
||||
else
|
||||
BACKLIGHT_ENABLE = yes
|
||||
BACKLIGHT_DRIVER = custom
|
||||
@@ -157,65 +183,73 @@ ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
|
||||
SRC += $(QUANTUM_DIR)/led_matrix.c
|
||||
SRC += $(QUANTUM_DIR)/led_matrix_drivers.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
|
||||
OPT_DEFS += -DIS31FL3731
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3731-simple.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731)
|
||||
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3731-simple.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
endif
|
||||
|
||||
RGB_MATRIX_ENABLE ?= no
|
||||
VALID_RGB_MATRIX_TYPES := IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom
|
||||
|
||||
ifneq ($(strip $(RGB_MATRIX_ENABLE)), no)
|
||||
ifeq ($(filter $(RGB_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
|
||||
$(error RGB_MATRIX_ENABLE="$(RGB_MATRIX_ENABLE)" is not a valid matrix type)
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
|
||||
$(error "$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
|
||||
endif
|
||||
OPT_DEFS += -DRGB_MATRIX_ENABLE
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2))
|
||||
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
|
||||
OPT_DEFS += -DLIB8_ATTINY
|
||||
endif
|
||||
SRC += $(QUANTUM_DIR)/color.c
|
||||
SRC += $(QUANTUM_DIR)/rgb_matrix.c
|
||||
SRC += $(QUANTUM_DIR)/rgb_matrix_drivers.c
|
||||
CIE1931_CURVE := yes
|
||||
RGB_KEYCODES_ENABLE := yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||
RGB_MATRIX_ENABLE := IS31FL3731
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731)
|
||||
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3731.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
|
||||
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3731.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733)
|
||||
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3733.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3733)
|
||||
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3733.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737)
|
||||
OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3737.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3737)
|
||||
OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3737.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741)
|
||||
OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE
|
||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||
SRC += is31fl3741.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), WS2812)
|
||||
OPT_DEFS += -DWS2812
|
||||
WS2812_DRIVER_REQUIRED := yes
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812)
|
||||
OPT_DEFS += -DWS2812
|
||||
WS2812_DRIVER_REQUIRED := yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
|
||||
OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB
|
||||
endif
|
||||
ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
|
||||
OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes)
|
||||
OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER
|
||||
ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes)
|
||||
OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RGB_KEYCODES_ENABLE)), yes)
|
||||
@@ -239,12 +273,13 @@ ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
|
||||
VAPTH += $(SERIAL_PATH)
|
||||
endif
|
||||
|
||||
ifneq ($(strip $(VARIABLE_TRACE)),)
|
||||
VARIABLE_TRACE ?= no
|
||||
ifneq ($(strip $(VARIABLE_TRACE)),no)
|
||||
SRC += $(QUANTUM_DIR)/variable_trace.c
|
||||
OPT_DEFS += -DNUM_TRACED_VARIABLES=$(strip $(VARIABLE_TRACE))
|
||||
ifneq ($(strip $(MAX_VARIABLE_TRACE_SIZE)),)
|
||||
OPT_DEFS += -DMAX_VARIABLE_TRACE_SIZE=$(strip $(MAX_VARIABLE_TRACE_SIZE))
|
||||
endif
|
||||
ifneq ($(strip $(MAX_VARIABLE_TRACE_SIZE)),)
|
||||
OPT_DEFS += -DMAX_VARIABLE_TRACE_SIZE=$(strip $(MAX_VARIABLE_TRACE_SIZE))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LCD_ENABLE)), yes)
|
||||
@@ -256,7 +291,7 @@ ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
|
||||
BACKLIGHT_DRIVER := custom
|
||||
endif
|
||||
|
||||
VALID_BACKLIGHT_TYPES := pwm software custom
|
||||
VALID_BACKLIGHT_TYPES := pwm timer software custom
|
||||
|
||||
BACKLIGHT_ENABLE ?= no
|
||||
BACKLIGHT_DRIVER ?= pwm
|
||||
@@ -296,6 +331,12 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
|
||||
SRC += ws2812.c
|
||||
else
|
||||
SRC += ws2812_$(strip $(WS2812_DRIVER)).c
|
||||
|
||||
ifeq ($(strip $(PLATFORM)), CHIBIOS)
|
||||
ifeq ($(strip $(WS2812_DRIVER)), pwm)
|
||||
OPT_DEFS += -DSTM32_DMA_REQUIRED=TRUE
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# add extra deps
|
||||
@@ -383,9 +424,20 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Support for translating old names to new names:
|
||||
ifeq ($(strip $(DEBOUNCE_TYPE)),sym_g)
|
||||
DEBOUNCE_TYPE:=sym_defer_g
|
||||
else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pk)
|
||||
DEBOUNCE_TYPE:=sym_eager_pk
|
||||
else ifeq ($(strip $(DEBOUNCE_TYPE)),sym_pk)
|
||||
DEBOUNCE_TYPE:=sym_defer_pk
|
||||
else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pr)
|
||||
DEBOUNCE_TYPE:=sym_eager_pr
|
||||
endif
|
||||
|
||||
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
|
||||
# Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually.
|
||||
DEBOUNCE_TYPE?= sym_g
|
||||
DEBOUNCE_TYPE?= sym_defer_g
|
||||
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
|
||||
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
|
||||
endif
|
||||
@@ -403,11 +455,14 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
|
||||
# Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called.
|
||||
# Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
|
||||
ifeq ($(PLATFORM),AVR)
|
||||
QUANTUM_LIB_SRC += i2c_master.c \
|
||||
i2c_slave.c
|
||||
ifneq ($(NO_I2C),yes)
|
||||
QUANTUM_LIB_SRC += i2c_master.c \
|
||||
i2c_slave.c
|
||||
endif
|
||||
endif
|
||||
|
||||
SERIAL_DRIVER ?= bitbang
|
||||
OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||
ifeq ($(strip $(SERIAL_DRIVER)), bitbang)
|
||||
QUANTUM_LIB_SRC += serial.c
|
||||
else
|
||||
@@ -521,3 +576,19 @@ ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
|
||||
OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
|
||||
endif
|
||||
endif
|
||||
|
||||
JOYSTICK_ENABLE ?= no
|
||||
ifneq ($(strip $(JOYSTICK_ENABLE)), no)
|
||||
OPT_DEFS += -DJOYSTICK_ENABLE
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c
|
||||
SRC += $(QUANTUM_DIR)/joystick.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(JOYSTICK_ENABLE)), analog)
|
||||
OPT_DEFS += -DANALOG_JOYSTICK_ENABLE
|
||||
SRC += analog.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
|
||||
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
|
||||
endif
|
||||
|
239
docs/ChangeLog/20200530.md
Normal file
239
docs/ChangeLog/20200530.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# QMK Breaking Change - 2020 May 30 Changelog
|
||||
|
||||
Four times a year QMK runs a process for merging Breaking Changes. A Breaking Change is any change which modifies how QMK behaves in a way that is incompatible or potentially dangerous. We limit these changes to 4 times per year so that users can have confidence that updating their QMK tree will not break their keymaps.
|
||||
|
||||
The list of changes follows.
|
||||
|
||||
|
||||
## Core Changes
|
||||
|
||||
### Converting V-USB usbdrv to a submodule
|
||||
|
||||
[#8321](https://github.com/qmk/qmk_firmware/pull/8321) and [qmk_compiler#62](https://github.com/qmk/qmk_compiler/pull/62).
|
||||
|
||||
These PRs move the V-USB driver code out of the qmk_firmware repository and into a submodule pointed at https://github.com/obdev/v-usb. This will make it easier to update the codebase if needed, while applying any potential QMK-specific modifications by forking it to the QMK GitHub organization.
|
||||
|
||||
### Unify Tap Hold functions and documentation
|
||||
|
||||
[#8348](https://github.com/qmk/qmk_firmware/pull/8348)
|
||||
|
||||
Updates all of the per key tap-hold functions to pass the `keyrecord_t` structure, and include documentation changes.
|
||||
|
||||
Any remaining versions or code outside of the main repo will need to be converted:
|
||||
| Old function | New Function |
|
||||
|------------------------------------------------------|---------------------------------------------------------------------------|
|
||||
|`uint16_t get_tapping_term(uint16_t keycode)` |`uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record)` |
|
||||
|`bool get_ignore_mod_tap_interrupt(uint16_t keycode)` |`bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record)` |
|
||||
|
||||
### Python Required In The Build Process
|
||||
|
||||
[#9000](https://github.com/qmk/qmk_firmware/pull/9000)
|
||||
|
||||
This is the last release of QMK that will work without having Python 3.6 (or later) installed. If your environment is not fully setup you will get a warning instructing you to set it up.
|
||||
|
||||
After the next breaking change you will not be able to build if `bin/qmk hello` does not work.
|
||||
|
||||
### Upgrade from tinyprintf to mpaland/printf
|
||||
|
||||
[#8269](https://github.com/qmk/qmk_firmware/pull/8269)
|
||||
|
||||
- Provides debug functionality on ChibiOS/ARM that is more compliant than previous integrations.
|
||||
- Less maintenence, fewer QMK customisations, and allows QMK to sidestep previous compile and runtime issues.
|
||||
- A `make git-submodule` may be required after pulling the latest QMK Firmware code to update to the new dependency.
|
||||
|
||||
### Fixed RGB_DISABLE_AFTER_TIMEOUT to be seconds based & small internals cleanup
|
||||
|
||||
[#6480](https://github.com/qmk/qmk_firmware/pull/6480)
|
||||
|
||||
- Changes `RGB_DISABLE_AFTER_TIMEOUT` to be based on milliseconds instead of ticks.
|
||||
- Includes a code cleanup, resulting in a savings of 100 bytes, depending on features used.
|
||||
- Fixed issues with timeouts / suspending at the wrong time not turning off all LEDs in some cases.
|
||||
|
||||
The `RGB_DISABLE_AFTER_TIMEOUT` definition is now deprecated, and has been superseded by `RGB_DISABLE_TIMEOUT`. To use the new definition, rename `RGB_DISABLE_AFTER_TIMEOUT` to `RGB_DISABLE_TIMEOUT` in your `config.h` file, and multiply the value set by 1200.
|
||||
|
||||
Before: `#define RGB_DISABLE_AFTER_TIMEOUT 100`
|
||||
After: `#define RGB_DISABLE_TIMEOUT 120000`
|
||||
|
||||
### Switch to qmk forks for everything
|
||||
|
||||
[#9019](https://github.com/qmk/qmk_firmware/pull/9019)
|
||||
|
||||
Fork all QMK submodules to protect against upstream repositories disappearing.
|
||||
|
||||
### code cleanup regarding deprecated macro PLAY_NOTE_ARRAY by replacing it with PLAY_SONG
|
||||
|
||||
[#8484](https://github.com/qmk/qmk_firmware/pull/8484)
|
||||
|
||||
Removes the deprecated `PLAY_NOTE_ARRAY` macro. References to it are replaced with `PLAY_SONG`, which references the same function.
|
||||
|
||||
### fixing wrong configuration of AUDIO feature
|
||||
|
||||
[#8903](https://github.com/qmk/qmk_firmware/pull/8903) and [#8974](https://github.com/qmk/qmk_firmware/pull/8974)
|
||||
|
||||
`audio_avr.c` does not default to any pin; there has to be a #define XX_AUDIO in config.h at some level for Audio to actually work. Otherwise, the Audio code ends up cluttering the firmware, possibly breaking builds because the maximum allowed firmware size is exceeded.
|
||||
|
||||
These changes fix this by disabling Audio on keyboards that have the feature misconfigured, and therefore non-functional.
|
||||
|
||||
Also, add a compile-time error to alert the user to a missing pin-configuration (on AVR boards) when `AUDIO_ENABLE = yes` is set.
|
||||
|
||||
|
||||
## Keyboard Refactors
|
||||
|
||||
### Migrating Lily58 to use split_common
|
||||
|
||||
[#6260](https://github.com/qmk/qmk_firmware/pull/6260)
|
||||
|
||||
Modifies the default firmware for Lily58 to use the `split_common` library, instead of including and depending on its own set of libraries for the following functionality:
|
||||
|
||||
- SSD1306 display
|
||||
- i2c for OLED
|
||||
- Serial Communication
|
||||
|
||||
This allows current lily58 firmware to advance with updates to the `split_common` library, which is shared with many other split keyboards.
|
||||
|
||||
#### To migrate existing Lily58 firmware:
|
||||
|
||||
[Changes to `config.h`](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-445ac369c8717dcd6fc6fc3630836fc1):
|
||||
- Remove `#define SSD1306OLED` from config.h
|
||||
|
||||
|
||||
[Changes to `keymap.c`](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7):
|
||||
- Find/Replace each instance of `#ifdef SSD1306OLED` with `#ifdef OLED_DRIVER_ENABLE`
|
||||
- The following changes are for compatibility with the OLED driver. If you don't use the OLED driver you may safely delete [this section](https://github.com/qmk/qmk_firmware/blob/e6b9980bd45c186f7360df68c24b6e05a80c10dc/keyboards/lily58/keymaps/default/keymap.c#L144-L190)
|
||||
- Alternatively, if you did not change the OLED code from that in `default`, you may find it easier to simply copy the [relevant section](https://github.com/qmk/qmk_firmware/blob/4ac310668501ae6786c711ecc8f01f62ddaa1c0b/keyboards/lily58/keymaps/default/keymap.c#L138-L172). Otherwise, the changes you need to make are as follows (sample change [here](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7R138-R173))
|
||||
- [Remove](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7L138-L141) the block
|
||||
```c
|
||||
#ifdef SSD1306OLED
|
||||
iota_gfx_init(!has_usb()); // turns on the display
|
||||
#endif
|
||||
```
|
||||
- Within the block bounded by `#ifdef OLED_DRIVER_ENABLE` and `#endif // OLED_DRIVER_ENABLE`, add the following block to ensure that your two OLEDs are rotated correctly across the left and right sides:
|
||||
```c
|
||||
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
|
||||
if (!is_keyboard_master())
|
||||
return OLED_ROTATION_180; // flips the display 180 degrees if offhand
|
||||
return rotation;
|
||||
}
|
||||
```
|
||||
- Remove the functions `matrix_scan_user`, `matrix_update` and `iota_gfx_task_user`
|
||||
- Find/Replace `matrix_render_user(struct CharacterMatrix *matrix)` with `iota_gfx_task_user(void)`
|
||||
- Find/Replace `is_master` with `is_keyboard_master()`
|
||||
- For each instance of `matrix_write_ln(matrix, display_fn())`, rewrite it as `oled_write_ln(read_layer_state(), false);`
|
||||
- For each instance of `matrix_write(matrix, read_logo());`, replace with `oled_write(read_logo(), false);`
|
||||
|
||||
### Refactor zinc to use split_common
|
||||
|
||||
[#7114](https://github.com/qmk/qmk_firmware/pull/7114) and [#9171](https://github.com/qmk/qmk_firmware/pull/9171)
|
||||
|
||||
* Refactor to use split_common and remove split codes under the zinc/revx/
|
||||
* Add - backlight RGB LED and/or underglow RGB LED option
|
||||
* Add - continuous RGB animations feature (between L and R halves)
|
||||
* Fix - keymap files to adapt to changes
|
||||
* all authors of keymaps confirmed this PR
|
||||
* Update - documents and rules.mk
|
||||
|
||||
### Refactor of TKC1800 to use common OLED code
|
||||
|
||||
[#8472](https://github.com/qmk/qmk_firmware/pull/8472)
|
||||
|
||||
Modifies the default firmware for TKC1800 to use the in-built I2C and OLED drivers, instead of including and depending on its own set of libraries for the following functionality:
|
||||
|
||||
- SSD1306 display
|
||||
- i2c for OLED
|
||||
|
||||
This allows current TKC1800 firmware to advance with updates to those drivers, which are shared with other keyboards.
|
||||
|
||||
#### To migrate existing TKC1800 firmware:
|
||||
|
||||
[Changes to `config.h`](https://github.com/qmk/qmk_firmware/pull/8472/files#diff-d10b26e676b4a55cbb00d71955116526):
|
||||
- Remove `#define SSD1306OLED` from config.h
|
||||
|
||||
[Changes to `tkc1800.c`](https://github.com/qmk/qmk_firmware/pull/8472/files#diff-3b35bd30abe89c8110717c6972cd2cc5):
|
||||
- Add the following to avoid debug errors on HID_listen if the screen is not present
|
||||
```c
|
||||
void keyboard_pre_init_kb(void) {
|
||||
setPinInputHigh(D0);
|
||||
setPinInputHigh(D1);
|
||||
|
||||
keyboard_pre_init_user();
|
||||
}
|
||||
```
|
||||
|
||||
[Changes to `keymap.c`](https://github.com/qmk/qmk_firmware/pull/8472/files#diff-05a2a344ce27e4d045fe68520ccd4771):
|
||||
- Find/Replace each instance of `#ifdef SSD1306OLED` with `#ifdef OLED_DRIVER_ENABLE`
|
||||
- The following changes are for compatibility with the OLED driver. If you don't use the OLED driver you may safely delete [this section](https://github.com/qmk/qmk_firmware/blob/e6b9980bd45c186f7360df68c24b6e05a80c10dc/keyboards/lily58/keymaps/default/keymap.c#L144-L190)
|
||||
- [Remove](https://github.com/qmk/qmk_firmware/pull/6260/files#diff-20943ea59856e9bdf3d99ecb2eee40b7L91-L158) the block
|
||||
```c
|
||||
#ifdef SSD1306OLED
|
||||
iota_gfx_init(!has_usb()); // turns on the display
|
||||
#endif
|
||||
```
|
||||
- Within the block bounded by `#ifdef OLED_DRIVER_ENABLE` and `#endif // OLED_DRIVER_ENABLE`, add the following block to ensure that your two OLEDs are rotated correctly across the left and right sides:
|
||||
```c
|
||||
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
|
||||
if (!is_keyboard_master())
|
||||
return OLED_ROTATION_180; // flips the display 180 degrees if offhand
|
||||
return rotation;
|
||||
}
|
||||
```
|
||||
- Remove the function `iota_gfx_task_user`
|
||||
|
||||
### Split HHKB to ANSI and JP layouts and Add VIA support for each
|
||||
|
||||
[#8582](https://github.com/qmk/qmk_firmware/pull/8582)
|
||||
|
||||
- Splits the HHKB codebase into two separate folders `keyboards/hhkb/ansi` and `keyboards/hhkb/jp`.
|
||||
- Adds VIA Configurator support for both versions.
|
||||
|
||||
#### Migrating existing HHKB keymaps
|
||||
|
||||
- Remove any checks for the `HHKB_JP` definition
|
||||
- All checks for this definition have been removed, and each version uses the source that is appropriate to that version.
|
||||
- Move the directory for your keymap into the appropriate `keymaps` directory
|
||||
- `keyboards/hhkb/ansi/keymaps/` for ANSI HHKBs
|
||||
- `keyboards/hhkb/jp/keymaps/` for HHKB JPs
|
||||
- Compile with the new keyboard names
|
||||
- This PR changes the compilation instructions for the HHKB Alternate Controller. To compile firmware for this controller moving forward, use:
|
||||
- `make hhkb/ansi` for ANSI-layout HHKBs
|
||||
- `make hhkb/jp` for HHKB JP keyboards
|
||||
|
||||
|
||||
## Keyboard Moves
|
||||
|
||||
- [#8412](https://github.com/qmk/qmk_firmware/pull/8412 "Changing board names to prevent confusion") by blindassassin111
|
||||
- [#8499](https://github.com/qmk/qmk_firmware/pull/8499 "Move the Keyboardio Model01 to a keyboardio/ subdir") by algernon
|
||||
- [#8830](https://github.com/qmk/qmk_firmware/pull/8830 "Move spaceman keyboards") by Spaceman (formerly known as Rionlion100)
|
||||
- [#8537](https://github.com/qmk/qmk_firmware/pull/8537 "Organizing my keyboards (plaid, tartan, ergoinu)") by hsgw
|
||||
|
||||
Keyboards by Keyboardio, Spaceman, and hsgw move to vendor folders, while PCBs designed by blindassassin111 are renamed.
|
||||
|
||||
Old Name | New Name
|
||||
:----------------- | :-----------------
|
||||
2_milk | spaceman/2_milk
|
||||
at101_blackheart | at101_bh
|
||||
ergoinu | dm9records/ergoinu
|
||||
model01 | keyboardio/model01
|
||||
omnikey_blackheart | omnikey_bh
|
||||
pancake | spaceman/pancake
|
||||
plaid | dm9records/plaid
|
||||
tartan | dm9records/tartan
|
||||
z150_blackheart | z150_bh
|
||||
|
||||
If you own one of these PCBs, please use the new names to compile your firmware moving forward.
|
||||
|
||||
|
||||
## Keycode Migration PRs
|
||||
|
||||
[#8954](https://github.com/qmk/qmk_firmware/pull/8954 "Migrate `ACTION_LAYER_TOGGLE` to `TG()`"), [#8957](https://github.com/qmk/qmk_firmware/pull/8957 "Migrate `ACTION_MODS_ONESHOT` to `OSM()`"), [#8958](https://github.com/qmk/qmk_firmware/pull/8958 "Migrate `ACTION_DEFAULT_LAYER_SET` to `DF()`"), [#8959](https://github.com/qmk/qmk_firmware/pull/8959 "Migrate `ACTION_LAYER_MODS` to `LM()`"), [#8968](https://github.com/qmk/qmk_firmware/pull/8968 "Migrate `ACTION_MODS_TAP_KEY` to `MT()`"), [#8977](https://github.com/qmk/qmk_firmware/pull/8977 "Migrate miscellaneous `fn_actions` entries"), and [#8979](https://github.com/qmk/qmk_firmware/pull/8979 "Migrate `ACTION_MODS_KEY` to chained mod keycodes")
|
||||
|
||||
Authored by fauxpark, these pull requests remove references to deprecated TMK macros that have been superseded by native QMK keycodes.
|
||||
|
||||
Old `fn_actions` action | New QMK keycode
|
||||
:---------------------- | :--------------
|
||||
`ACTION_DEFAULT_LAYER_SET(layer)` | `DF(layer)`
|
||||
`ACTION_LAYER_MODS(layer, mod)` | `LM(layer, mod)`
|
||||
`ACTION_LAYER_ONESHOT(mod)` | `OSL(mod)`
|
||||
`ACTION_LAYER_TOGGLE(layer)` | `TG(layer)`
|
||||
`ACTION_MODS_ONESHOT(mod)` | `OSM(mod)`
|
||||
`ACTION_MODS_TAP_KEY(mod, kc)` | `MT(mod, kc)`
|
||||
`ACTION_MODS_KEY(mod, kc)`<br>e.g. `ACTION_MODS_KEY(MOD_LCTL, KC_0)` | `MOD(kc)`<br>e.g. `LCTL(KC_0)`
|
148
docs/ChangeLog/20200829.md
Normal file
148
docs/ChangeLog/20200829.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# QMK Breaking Change - 2020 Aug 29 Changelog
|
||||
|
||||
Four times a year QMK runs a process for merging Breaking Changes. A Breaking Change is any change which modifies how QMK behaves in a way that is incompatible or potentially dangerous. We limit these changes to 4 times per year so that users can have confidence that updating their QMK tree will not break their keymaps.
|
||||
|
||||
|
||||
## Changes Requiring User Action :id=changes-requiring-user-action
|
||||
|
||||
### Relocated Keyboards :id-relocated-keyboards
|
||||
|
||||
#### The Key Company project consolidation ([#9547](https://github.com/qmk/qmk_firmware/pull/9547))
|
||||
#### relocating boards by flehrad to flehrad/ folder ([#9635](https://github.com/qmk/qmk_firmware/pull/9635))
|
||||
|
||||
Keyboards released by The Key Company and keyboards designed by flehrad have moved to vendor folders. If you own any of the keyboards listed below, please use the new names to compile your firmware moving forward.
|
||||
|
||||
Old Name | New Name
|
||||
:--------------------- | :------------------
|
||||
candybar/lefty | tkc/candybar/lefty
|
||||
candybar/righty | tkc/candybar/righty
|
||||
m0lly | tkc/m0lly
|
||||
tkc1800 | tkc/tkc1800
|
||||
bigswitch | flehrad/bigswitch
|
||||
handwired/downbubble | flehrad/downbubble
|
||||
handwired/numbrero | flehrad/numbrero
|
||||
snagpad | flehrad/snagpad
|
||||
handwired/tradestation | flehrad/tradestation
|
||||
|
||||
### Updated Keyboard Codebases :id=keyboard-updates
|
||||
|
||||
#### Keebio RGB wiring update ([#7754](https://github.com/qmk/qmk_firmware/pull/7754))
|
||||
|
||||
This pull request changes the configuration for Keebio split boards to use the same RGB strip wiring for each half, which provides the following improvements:
|
||||
|
||||
* Easier wiring due to one fewer wire needed (the wire between left DOut to extra data pin) and the fact that wiring is the same for both halves.
|
||||
* RGB LEDs can be controlled by each half now instead of just master half.
|
||||
* Extra data line is freed up to allow for I2C usage instead of serial.
|
||||
|
||||
If you have customized the value of `RGBLED_SPLIT` for your keymap, you will need to undefine it using `#undef RGBLED_SPLIT` before defining it to your customized value.
|
||||
|
||||
This change affects:
|
||||
|
||||
* BFO-9000
|
||||
* Fourier
|
||||
* Iris rev2
|
||||
* Levinson, revs. 1 and 2
|
||||
* Nyquist, revs. 1 and 2
|
||||
* Quefrency rev1
|
||||
* Viterbi, revs. 1 and 2
|
||||
|
||||
### Changes to Core Functionality :id=core-updates
|
||||
|
||||
* Bigger Combo index ([#9318](https://github.com/qmk/qmk_firmware/pull/9318))
|
||||
|
||||
Allows the Combo feature to support more than 256 combos.
|
||||
|
||||
Any fork that uses `process_combo_event` needs to update the function's first argument to `uint16_t`:
|
||||
|
||||
* Old function: `void process_combo_event(uint8_t combo_index, bool pressed)`
|
||||
* New function: `void process_combo_event(uint16_t combo_index, bool pressed)`
|
||||
|
||||
|
||||
## Core Changes :id=core-changes
|
||||
|
||||
### Fixes :id=core-fixes
|
||||
|
||||
* Mousekeys: scrolling acceleration is no longer coupled to mouse movement acceleration ([#9174](https://github.com/qmk/qmk_firmware/pull/9174))
|
||||
* Keymap Extras: correctly assign Question Mark in Czech layout ([#9987](https://github.com/qmk/qmk_firmware/pull/9987))
|
||||
|
||||
### Additions and Enhancements :id=core-additions
|
||||
|
||||
* allow for WS2812 PWM to work on DMAMUX-capable devices ([#9471](https://github.com/qmk/qmk_firmware/pull/9471))
|
||||
* Newer STM32 MCUs have a DMAMUX peripheral, which allows mapping of DMAs to different DMA streams, rather than hard-defining the target streams in silicon.
|
||||
* Affects STM32L4+ devices, as well as the soon-to-be-supported-by-QMK STM32G4/H7 families.
|
||||
* Tested on F303/Proton C (ChibiOS v19, non-DMAMUX), G474 (ChibiOS v20, with DMAMUX).
|
||||
* dual-bank STM32 bootloader support ([#8778](https://github.com/qmk/qmk_firmware/pull/8778) and [#9738](https://github.com/qmk/qmk_firmware/pull/9738))
|
||||
* Adds support for STM32 dual-bank flash bootloaders, by toggling a GPIO during early init in order to charge an RC circuit attached to `BOOT0`.
|
||||
* The main rationale behind this is that dual-bank STM32 devices unconditionally execute user-mode code, regardless of whether or not the user-mode code jumps to the bootloader. If either flash bank is valid (and `BOOT0` is low), then the built-in bootloader will skip any sort of DFU.
|
||||
* This PR allows for the initialisation sequencing to charge the RC circuit based on the example circuit posted on Discord, effectively pulling `BOOT0` high before issuing the system reset. As the RC circuit takes a while to discharge, the system reset executes the ROM bootloader which subsequently sees `BOOT0` high, and starts executing the DFU routines.
|
||||
* Tested with STM32L082 (with current QMK+current ChibiOS), and STM32G474 (against ChibiOS 20.x).
|
||||
* update Space Cadet and Tap Dance features to use Custom Tapping Term when appropriate ([#6259](https://github.com/qmk/qmk_firmware/pull/6259))
|
||||
* For the Tap Dance feature, this completely removes the need for the `ACTION_TAP_DANCE_FN_ADVANCED_TIME` dance.
|
||||
* HID Joystick Interface ([#4226](https://github.com/qmk/qmk_firmware/pull/4226) and [#9949](https://github.com/qmk/qmk_firmware/pull/9949 "Fix Joystick Compile Issues"))
|
||||
* This implements a joystick feature, including a joystick_task function called from TMK, specific keycodes for joystick buttons and a USB HID interface.
|
||||
* Tested on V-USB backend and Proton C; compiles but untested on LUFA.
|
||||
* In order to test, you have to add `JOYSTICK_ENABLE = yes` to your `rules.mk` and
|
||||
```c
|
||||
#define JOYSTICK_BUTTON_COUNT 8
|
||||
#define JOYSTICK_AXES_COUNT 2
|
||||
```
|
||||
in your config.h.
|
||||
* Christmas RGB Underglow animation now fades between green and red ([#7648](https://github.com/qmk/qmk_firmware/pull/7648))
|
||||
* `RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL` has been greatly decreased; please check your animation if you have customized this value.
|
||||
* layer state now initializes on startup ([#8318](https://github.com/qmk/qmk_firmware/pull/8318))
|
||||
* This should produce more consistent behavior between the two functions and layer masks.
|
||||
* added support for HSV->RGB conversion without using CIE curve ([#9856](https://github.com/qmk/qmk_firmware/pull/9856))
|
||||
* added NOEEPROM functions for RGB Matrix ([#9487](https://github.com/qmk/qmk_firmware/pull/9487))
|
||||
* Added eeprom_helpers for toggle, mode, sethsv, speed, similar to rgblight versions.
|
||||
* Added set_speed function.
|
||||
* Added helper functions, similar to those in rgblight, in order to add NOEEPROM versions of toggle, step, hue, sat, val, and speed.
|
||||
* Minor: spelling correction for EEPROM in a debug message.
|
||||
* flashing firmware using `st-flash` utility from [STLink Tools](https://github.com/stlink-org/stlink) is now supported ([#9964](https://github.com/qmk/qmk_firmware/pull/9964))
|
||||
* add ability to dump all makefile variables for the specified target ([#8256](https://github.com/qmk/qmk_firmware/pull/8256))
|
||||
* Adds a new subtarget to builds, `dump_vars`, which allows for printing out all the variables that make knows about, after all substitutions occur.
|
||||
* Example: `make handwired/onekey/proton_c:default:dump_vars`
|
||||
* add ability to change the Auto Shift timeout in real time ([#8441](https://github.com/qmk/qmk_firmware/pull/8441))
|
||||
* added a timer implementation for backlight on ChibiOS ([#8291](https://github.com/qmk/qmk_firmware/pull/8291))
|
||||
* added a third endpoint to V-USB keyboards ([#9020](https://github.com/qmk/qmk_firmware/pull/9020))
|
||||
* added a method to read the OLED display buffer from user space ([#8777](https://github.com/qmk/qmk_firmware/pull/8777))
|
||||
* K-Type refactor ([#9864](https://github.com/qmk/qmk_firmware/pull/9864))
|
||||
* The K-Type has been refactored to use QMK's native matrix scanning routine, and now has partial support for the RGB Matrix feature.
|
||||
* Joysticks can now be used without defining analog pins ([#10169](https://github.com/qmk/qmk_firmware/pull/10169))
|
||||
|
||||
### Clean-ups and Optimizations :id=core-optimizations
|
||||
|
||||
* iWRAP protocol removed ([#9284](https://github.com/qmk/qmk_firmware/pull/9284))
|
||||
* work begun for consolidation of ChibiOS platform files ([#8327](https://github.com/qmk/qmk_firmware/pull/8327) and [#9315](https://github.com/qmk/qmk_firmware/pull/9315))
|
||||
* Start of the consolidation work to move the ChibiOS board definitions as well as the default set of configuration files for existing board definitions used by keyboards.
|
||||
* Uses `/platforms/chibios` as previously discussed on discord.
|
||||
* Consolidates the Proton C configs into the generic F303 definitions.
|
||||
* Allows for defining a default set of `chconf.h`, `halconf.h`, and `mcuconf.h` files within the platform definition, which is able to be overridden by the keyboard directly, though include path ordering.
|
||||
* Adds template `chconf.h`, `halconf.h`, `mcuconf.h`, and `board.h` that can be dropped into a keyboard directory, in order to override rather than replace the entire contents of the respective files.
|
||||
* Removed Proton C QMK board definitions, falling back to ChibiOS board definitions with QMK overrides.
|
||||
* Various tidy-ups for USB descriptor code ([#9005](https://github.com/qmk/qmk_firmware/pull/9005))
|
||||
* Renamed `keyboard_led_stats` in lufa.c and ChibiOS usb_main.c to `keyboard_led_state`, as well as `vusb_keyboard_leds`, for consistency
|
||||
* Formatted CDC and MIDI descriptors better
|
||||
* Removed `ENDPOINT_CONFIG` macro, it seems pointless and removes the need for endpoint address defines in the middle of the endpoint numbering enum
|
||||
* Fixed (possibly?) V-USB `GET_REPORT` request handling. Not sure about this one, but the existing code appears to always return an empty report - now `send_keyboard` sets this variable to the current report, matching what the LUFA code does.
|
||||
* converted `CONSUMER2BLUEFRUIT()` and `CONSUMER2RN42()` macros to static inline functions ([#9055](https://github.com/qmk/qmk_firmware/pull/9055))
|
||||
* Additional cleanups for V-USB code ([#9310](https://github.com/qmk/qmk_firmware/pull/9310))
|
||||
* Removing the UART stuff entirely, now that we have Console support. Also fixing up various other things; switching some `debug()` calls to `dprintf()`, moved `raw_hid_report` out of the way so that we can implement the shared endpoint stuff.
|
||||
* removed inclusion of `adafruit_ble.h` from `ssd1306.c` ([#9355](https://github.com/qmk/qmk_firmware/pull/9355))
|
||||
* `outputselect.c` is no longer compiled if Bluetooth is disabled ([#9356](https://github.com/qmk/qmk_firmware/pull/9356))
|
||||
* `analogRead()` deprecated in favor of `analogReadPin()` ([#9023](https://github.com/qmk/qmk_firmware/pull/9023))
|
||||
* forcibly disable NKRO on V-USB controllers ([#9054](https://github.com/qmk/qmk_firmware/pull/9054))
|
||||
* removed warning if running backlight on STM32F072 ([#10040](https://github.com/qmk/qmk_firmware/pull/10040))
|
||||
* removed unused CORTEX_VTOR_INIT rules.mk option ([#10053](https://github.com/qmk/qmk_firmware/pull/10053))
|
||||
* improved handling for enabling Link Time Optimization ([#9832](https://github.com/qmk/qmk_firmware/pull/9832))
|
||||
* streamline rules for supporting Kiibohd bootloader ([#10129](https://github.com/qmk/qmk_firmware/pull/10129))
|
||||
* Define `STM32_DMA_REQUIRED` when using DMA-based WS2812 driver on STM32 ([#10127](https://github.com/qmk/qmk_firmware/pull/10127))
|
||||
* fix DMA stream ID calculation in ws2812_pwm ([#10008](https://github.com/qmk/qmk_firmware/pull/10008))
|
||||
* remove support for Adafruit EZ Key Bluetooth controller ([#10103](https://github.com/qmk/qmk_firmware/pull/10103))
|
||||
|
||||
|
||||
## QMK Infrastructure and Internals :id=qmk-internals
|
||||
|
||||
* Attempt to fix CI for non-master branches. ([#9308](https://github.com/qmk/qmk_firmware/pull/9308))
|
||||
* Actually fetch the branch we're attempting to compare against.
|
||||
* Run `qmk cformat` on `develop` branch ([#9501](https://github.com/qmk/qmk_firmware/pull/9501))
|
||||
* minor refactor of Bluetooth API ([#9905](https://github.com/qmk/qmk_firmware/pull/9905))
|
150
docs/ChangeLog/20201128.md
Normal file
150
docs/ChangeLog/20201128.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# QMK Breaking Change - 2020 Nov 28 Changelog
|
||||
|
||||
Four times a year QMK runs a process for merging Breaking Changes. A Breaking Change is any change which modifies how QMK behaves in a way that is incompatible or potentially dangerous. We limit these changes to 4 times per year so that users can have confidence that updating their QMK tree will not break their keymaps.
|
||||
|
||||
|
||||
## Changes Requiring User Action :id=changes-requiring-user-action
|
||||
|
||||
### Relocated Keyboards :id-relocated-keyboards
|
||||
|
||||
#### Reduce Helix keyboard build variation ([#8669](https://github.com/qmk/qmk_firmware/pull/8669))
|
||||
|
||||
The build commands for the Helix keyboard are:
|
||||
|
||||
```
|
||||
make <helix_build_name>:<keymap_name>
|
||||
```
|
||||
|
||||
For `<helix_build_name>`, specify the one in the rightmost column of the table below, such as `helix`,` helix/pico`.
|
||||
|
||||
| before Oct 17 2019 | Oct 17 2019 | Mar 10 2020 | Nov 28 2020 |
|
||||
| ---------------------|-------------------------|-------------------------| ------------------------|
|
||||
| helix/rev1 | helix/rev1 | helix/rev1 | helix/rev1 |
|
||||
| helix/pico | helix/pico | helix/pico | helix/pico |
|
||||
| | helix/pico/back | helix/pico/back | helix/pico/back |
|
||||
| | helix/pico/under | helix/pico/under | helix/pico/under |
|
||||
| | | helix/pico/sc | -- |
|
||||
| | | helix/pico/sc/back | helix/pico/sc |
|
||||
| | | helix/pico/sc/under | -- |
|
||||
| helix/rev2 (=helix) | helix/rev2 (=helix) | helix/rev2 (=helix) | -- |
|
||||
| | helix/rev2/back | helix/rev2/back | -- |
|
||||
| | helix/rev2/back/oled | helix/rev2/back/oled | ( --> helix/rev2/back) |
|
||||
| | helix/rev2/oled | helix/rev2/oled | helix/rev2 (=helix) |
|
||||
| | helix/rev2/oled/back | helix/rev2/oled/back | helix/rev2/back |
|
||||
| | helix/rev2/oled/under | helix/rev2/oled/under | helix/rev2/under |
|
||||
| | | helix/rev2/sc | -- |
|
||||
| | | helix/rev2/sc/back | -- |
|
||||
| | | helix/rev2/sc/oled | -- |
|
||||
| | | helix/rev2/sc/oledback | helix/rev2/sc |
|
||||
| | | helix/rev2/sc/oledunder | -- |
|
||||
| | | helix/rev2/sc/under | -- |
|
||||
| | helix/rev2/under | helix/rev2/under | -- |
|
||||
| | helix/rev2/under/oled | helix/rev2/under/oled | ( --> helix/rev2/under) |
|
||||
|
||||
#### Update the Speedo firmware for v3.0 ([#10657](https://github.com/qmk/qmk_firmware/pull/10657))
|
||||
|
||||
The Speedo keyboard has moved to `cozykeys/speedo/v2` as the designer prepares to release the Speedo v3.0.
|
||||
|
||||
| Previous Name | New Name |
|
||||
| :------------ | :------------------------- |
|
||||
| speedo | cozykeys/speedo/v2 |
|
||||
| -- | cozykeys/speedo/v3 **new** |
|
||||
|
||||
#### Maartenwut/Maarten name change to evyd13/Evy ([#10274](https://github.com/qmk/qmk_firmware/pull/10274))
|
||||
|
||||
Maartenwut has rebranded as @evyd13, and all released Maartenwut boards have moved.
|
||||
|
||||
| Previous Name | New Name |
|
||||
| :--------------------- | :----------------- |
|
||||
| maartenwut/atom47/rev2 | evyd13/atom47/rev2 |
|
||||
| maartenwut/atom47/rev3 | evyd13/atom47/rev3 |
|
||||
| maartenwut/eon40 | evyd13/eon40 |
|
||||
| maartenwut/eon65 | evyd13/eon65 |
|
||||
| maartenwut/eon75 | evyd13/eon75 |
|
||||
| maartenwut/eon87 | evyd13/eon87 |
|
||||
| maartenwut/eon95 | evyd13/eon95 |
|
||||
| maartenwut/gh80_1800 | evyd13/gh80_1800 |
|
||||
| maartenwut/gh80_3700 | evyd13/gh80_3700 |
|
||||
| maartenwut/minitomic | evyd13/minitomic |
|
||||
| maartenwut/mx5160 | evyd13/mx5160 |
|
||||
| maartenwut/nt660 | evyd13/nt660 |
|
||||
| maartenwut/omrontkl | evyd13/omrontkl |
|
||||
| maartenwut/plain60 | evyd13/plain60 |
|
||||
| maartenwut/pockettype | evyd13/pockettype |
|
||||
| maartenwut/quackfire | evyd13/quackfire |
|
||||
| maartenwut/solheim68 | evyd13/solheim68 |
|
||||
| maartenwut/ta65 | evyd13/ta65 |
|
||||
| maartenwut/wasdat | evyd13/wasdat |
|
||||
| maartenwut/wasdat_code | evyd13/wasdat_code |
|
||||
| maartenwut/wonderland | evyd13/wonderland |
|
||||
|
||||
#### Xelus Valor and Dawn60 Refactors ([#10512](https://github.com/qmk/qmk_firmware/pull/10512), [#10584](https://github.com/qmk/qmk_firmware/pull/10584))
|
||||
|
||||
The Valor and Dawn60 keyboards by Xelus22 both now require their revisions to be specified when compiling.
|
||||
|
||||
| Previous Name | New Name |
|
||||
| :------------ | :---------------- |
|
||||
| xelus/dawn60 | xelus/dawn60/rev1 |
|
||||
| xelus/valor | xelus/valor/rev1 |
|
||||
|
||||
|
||||
### Updated Keyboard Codebases :id=keyboard-updates
|
||||
|
||||
#### AEboards EXT65 Refactor ([#10820](https://github.com/qmk/qmk_firmware/pull/10820))
|
||||
|
||||
The EXT65 codebase has been reworked so keymaps can be used with either revision.
|
||||
|
||||
|
||||
## Core Changes :id=core-changes
|
||||
|
||||
### Fixes :id=core-fixes
|
||||
|
||||
* Reconnect the USB if users wake up a computer from the keyboard to restore the USB state ([#10088](https://github.com/qmk/qmk_firmware/pull/10088))
|
||||
* Fix cursor position bug in oled_write_raw functions ([#10800](https://github.com/qmk/qmk_firmware/pull/10800))
|
||||
|
||||
### Additions and Enhancements :id=core-additions
|
||||
|
||||
* Allow MATRIX_ROWS to be greater than 32 ([#10183](https://github.com/qmk/qmk_firmware/pull/10183))
|
||||
* Add support for soft serial to ATmega32U2 ([#10204](https://github.com/qmk/qmk_firmware/pull/10204))
|
||||
* Allow direct control of MIDI velocity value ([#9940](https://github.com/qmk/qmk_firmware/pull/9940))
|
||||
* Joystick 16-bit support ([#10439](https://github.com/qmk/qmk_firmware/pull/10439))
|
||||
* Allow encoder resolutions to be set per encoder ([#10259](https://github.com/qmk/qmk_firmware/pull/10259))
|
||||
* Share button state from mousekey to pointing_device ([#10179](https://github.com/qmk/qmk_firmware/pull/10179))
|
||||
* Add advanced/efficient RGB Matrix Indicators ([#8564](https://github.com/qmk/qmk_firmware/pull/8564))
|
||||
* OLED display update interval support ([#10388](https://github.com/qmk/qmk_firmware/pull/10388))
|
||||
* Per-Key Retro Tapping ([#10622](https://github.com/qmk/qmk_firmware/pull/10622))
|
||||
* Allow backlight duty cycle limit ([#10260](https://github.com/qmk/qmk_firmware/pull/10260))
|
||||
* Add step sequencer feature ([#9703](https://github.com/qmk/qmk_firmware/pull/9703))
|
||||
* Added `add_oneshot_mods` & `del_oneshot_mods` ([#10549](https://github.com/qmk/qmk_firmware/pull/10549))
|
||||
* Add AT90USB support for serial.c ([#10706](https://github.com/qmk/qmk_firmware/pull/10706))
|
||||
* Auto shift: support repeats and early registration (#9826)
|
||||
|
||||
### Clean-ups and Optimizations :id=core-optimizations
|
||||
|
||||
* Haptic and solenoid cleanup ([#9700](https://github.com/qmk/qmk_firmware/pull/9700))
|
||||
* XD75 cleanup ([#10524](https://github.com/qmk/qmk_firmware/pull/10524))
|
||||
* Minor change to behavior allowing display updates to continue between task ticks ([#10750](https://github.com/qmk/qmk_firmware/pull/10750))
|
||||
* Change some GPIO manipulations in matrix.c to be atomic ([#10491](https://github.com/qmk/qmk_firmware/pull/10491))
|
||||
* combine repeated lines of code for ATmega32U2, ATmega16U2, ATmega328 and ATmega328P ([#10837](https://github.com/qmk/qmk_firmware/pull/10837))
|
||||
* Remove references to HD44780 ([#10735](https://github.com/qmk/qmk_firmware/pull/10735))
|
||||
|
||||
|
||||
## QMK Infrastructure and Internals :id=qmk-internals
|
||||
|
||||
* Add ability to build a subset of all keyboards based on platform. ([#10420](https://github.com/qmk/qmk_firmware/pull/10420))
|
||||
* Initialise EEPROM drivers at startup, instead of upon first execution ([#10438](https://github.com/qmk/qmk_firmware/pull/10438))
|
||||
* Make bootloader_jump weak for ChibiOS ([#10417](https://github.com/qmk/qmk_firmware/pull/10417))
|
||||
* Support for STM32 GPIOF,G,H,I,J,K ([#10206](https://github.com/qmk/qmk_firmware/pull/10206))
|
||||
* Add milc as a dependency and remove the installed milc ([#10563](https://github.com/qmk/qmk_firmware/pull/10563))
|
||||
* ChibiOS upgrade: early init conversions ([#10214](https://github.com/qmk/qmk_firmware/pull/10214))
|
||||
* ChibiOS upgrade: configuration file migrator ([#9952](https://github.com/qmk/qmk_firmware/pull/9952))
|
||||
* Add definition based on currently-selected serial driver. ([#10716](https://github.com/qmk/qmk_firmware/pull/10716))
|
||||
* Allow for modification of output RGB values when using rgblight/rgb_matrix. ([#10638](https://github.com/qmk/qmk_firmware/pull/10638))
|
||||
* Allow keyboards/keymaps to execute code at each main loop iteration ([#10530](https://github.com/qmk/qmk_firmware/pull/10530))
|
||||
* qmk cformat ([#10767](https://github.com/qmk/qmk_firmware/pull/10767))
|
||||
* Add a Make variable to easily enable DEBUG_MATRIX_SCAN_RATE on the command line ([#10824](https://github.com/qmk/qmk_firmware/pull/10824))
|
||||
* update Chibios OS USB for the OTG driver ([#8893](https://github.com/qmk/qmk_firmware/pull/8893))
|
||||
* Fixup version.h writing when using `SKIP_VERSION=yes` ([#10972](https://github.com/qmk/qmk_firmware/pull/10972), [#10974](https://github.com/qmk/qmk_firmware/pull/10974))
|
||||
* Rename ledmatrix.h to match .c file ([#7949](https://github.com/qmk/qmk_firmware/pull/7949))
|
||||
* Split RGB_MATRIX_ENABLE into _ENABLE and _DRIVER ([#10231](https://github.com/qmk/qmk_firmware/pull/10231))
|
||||
* Split LED_MATRIX_ENABLE into _ENABLE and _DRIVER ([#10840](https://github.com/qmk/qmk_firmware/pull/10840))
|
@@ -23,6 +23,7 @@
|
||||
* [Overview](api_overview.md)
|
||||
* [API Documentation](api_docs.md)
|
||||
* [Keyboard Support](reference_configurator_support.md)
|
||||
* [Adding Default Keymaps](configurator_default_keymaps.md)
|
||||
|
||||
* CLI
|
||||
* [Overview](cli.md)
|
||||
@@ -55,6 +56,7 @@
|
||||
* Simple Keycodes
|
||||
* [Full List](keycodes.md)
|
||||
* [Basic Keycodes](keycodes_basic.md)
|
||||
* [Language-Specific Keycodes](reference_keymap_extras.md)
|
||||
* [Modifier Keys](feature_advanced_keycodes.md)
|
||||
* [Quantum Keycodes](quantum_keycodes.md)
|
||||
|
||||
@@ -78,6 +80,7 @@
|
||||
* [One Shot Keys](one_shot_keys.md)
|
||||
* [Pointing Device](feature_pointing_device.md)
|
||||
* [Raw HID](feature_rawhid.md)
|
||||
* [Sequencer](feature_sequencer.md)
|
||||
* [Swap Hands](feature_swap_hands.md)
|
||||
* [Tap Dance](feature_tap_dance.md)
|
||||
* [Tap-Hold Configuration](tap_hold.md)
|
||||
@@ -102,6 +105,8 @@
|
||||
* [DIP Switch](feature_dip_switch.md)
|
||||
* [Encoders](feature_encoders.md)
|
||||
* [Haptic Feedback](feature_haptic_feedback.md)
|
||||
* [Joystick](feature_joystick.md)
|
||||
* [LED Indicators](feature_led_indicators.md)
|
||||
* [Proton C Conversion](proton_c_conversion.md)
|
||||
* [PS/2 Mouse](feature_ps2_mouse.md)
|
||||
* [Split Keyboard](feature_split_keyboard.md)
|
||||
@@ -110,10 +115,14 @@
|
||||
* [Velocikey](feature_velocikey.md)
|
||||
|
||||
* Developing QMK
|
||||
* [PR Checklist](pr_checklist.md)
|
||||
* Breaking Changes
|
||||
* [Overview](breaking_changes.md)
|
||||
* [My Pull Request Was Flagged](breaking_changes_instructions.md)
|
||||
* History
|
||||
* [2020 Nov 28](ChangeLog/20201128.md)
|
||||
* [2020 Aug 29](ChangeLog/20200829.md)
|
||||
* [2020 May 30](ChangeLog/20200530.md)
|
||||
* [2020 Feb 29](ChangeLog/20200229.md)
|
||||
* [2019 Aug 30](ChangeLog/20190830.md)
|
||||
|
||||
@@ -143,6 +152,7 @@
|
||||
|
||||
* Hardware Platform Development
|
||||
* Arm/ChibiOS
|
||||
* [Selecting an MCU](platformdev_selecting_arm_mcu.md)
|
||||
* [Early initialization](platformdev_chibios_earlyinit.md)
|
||||
|
||||
* QMK Reference
|
||||
|
@@ -22,7 +22,7 @@ Then place this include at the top of your code:
|
||||
|
||||
### AVR
|
||||
|
||||
|Channel|AT90USB64/128|ATmega16/32U4|ATmega32A|ATmega328P|
|
||||
|Channel|AT90USB64/128|ATmega16/32U4|ATmega32A|ATmega328/P|
|
||||
|-------|-------------|-------------|---------|----------|
|
||||
|0 |`F0` |`F0` |`A0` |`C0` |
|
||||
|1 |`F1` |`F1` |`A1` |`C1` |
|
||||
@@ -39,15 +39,15 @@ Then place this include at the top of your code:
|
||||
|12 | |`B5` | | |
|
||||
|13 | |`B6` | | |
|
||||
|
||||
<sup>\* The ATmega328P possesses two extra ADC channels; however, they are not present on the DIP pinout, and are not shared with GPIO pins. You can use `adc_read()` directly to gain access to these.</sup>
|
||||
<sup>\* The ATmega328/P possesses two extra ADC channels; however, they are not present on the DIP pinout, and are not shared with GPIO pins. You can use `adc_read()` directly to gain access to these.</sup>
|
||||
|
||||
### ARM
|
||||
|
||||
Note that some of these pins are doubled-up on ADCs with the same channel. This is because the pins can be used for either ADC.
|
||||
|
||||
Also note that the F0 and F3 use different numbering schemes. The F0 has a single ADC and the channels are 0-based, whereas the F3 has 4 ADCs and the channels are 1 based. This is because the F0 uses the `ADCv1` implementation of the ADC, whereas the F3 uses the `ADCv3` implementation.
|
||||
Also note that the F0 and F3 use different numbering schemes. The F0 has a single ADC and the channels are 0-indexed, whereas the F3 has 4 ADCs and the channels are 1-indexed. This is because the F0 uses the `ADCv1` implementation of the ADC, whereas the F3 uses the `ADCv3` implementation.
|
||||
|
||||
|ADC|Channel|STM32F0XX|STM32F3XX|
|
||||
|ADC|Channel|STM32F0xx|STM32F3xx|
|
||||
|---|-------|---------|---------|
|
||||
|1 |0 |`A0` | |
|
||||
|1 |1 |`A1` |`A0` |
|
||||
@@ -122,32 +122,29 @@ Also note that the F0 and F3 use different numbering schemes. The F0 has a singl
|
||||
|Function |Description |
|
||||
|----------------------------|-------------------------------------------------------------------------------------------------------------------|
|
||||
|`analogReference(mode)` |Sets the analog voltage reference source. Must be one of `ADC_REF_EXTERNAL`, `ADC_REF_POWER` or `ADC_REF_INTERNAL`.|
|
||||
|`analogRead(pin)` |Reads the value from the specified Arduino pin, eg. `4` for ADC6 on the ATmega32U4. |
|
||||
|`analogReadPin(pin)` |Reads the value from the specified QMK pin, eg. `F6` for ADC6 on the ATmega32U4. |
|
||||
|`pinToMux(pin)` |Translates a given QMK pin to a mux value. If an unsupported pin is given, returns the mux value for "0V (GND)". |
|
||||
|`analogReadPin(pin)` |Reads the value from the specified pin, eg. `F6` for ADC6 on the ATmega32U4. |
|
||||
|`pinToMux(pin)` |Translates a given pin to a mux value. If an unsupported pin is given, returns the mux value for "0V (GND)". |
|
||||
|`adc_read(mux)` |Reads the value from the ADC according to the specified mux. See your MCU's datasheet for more information. |
|
||||
|
||||
### ARM
|
||||
|
||||
Note that care was taken to match all of the functions used for AVR devices, however complications in the ARM platform prevent that from always being possible. For example, the `STM32` chips do not have assigned Arduino pins. We could use the default pin numbers, but those numbers change based on the package type of the device. For this reason, please specify your target pins with their identifiers (`A0`, `F3`, etc.). Also note that there are some variants of functions that accept the target ADC for the pin. Some pins can be used for multiple ADCs, and this specified can help you pick which ADC will be used to interact with that pin.
|
||||
|
||||
|Function |Description |
|
||||
|----------------------------|--------------------------------------------------------------------------------------------------------------------|
|
||||
|`analogReadPin(pin)` |Reads the value from the specified QMK pin, eg. `A0` for channel 0 on the STM32F0 and ADC1 channel 1 on the STM32F3. Note that if a pin can be used for multiple ADCs, it will pick the lower numbered ADC for this function. eg. `C0` will be channel 6 of ADC 1 when it could be used for ADC 2 as well.|
|
||||
|`analogReadPinAdc(pin, adc)`|Reads the value from the specified QMK pin and ADC, eg. `C0, 1` will read from channel 6, ADC 2 instead of ADC 1. Note that the ADCs are 0-indexed for this function.|
|
||||
|`pinToMux(pin)` |Translates a given QMK pin to a channel and ADC combination. If an unsupported pin is given, returns the mux value for "0V (GND)".|
|
||||
|`adc_read(mux)` |Reads the value from the ADC according to the specified pin and adc combination. See your MCU's datasheet for more information.|
|
||||
|Function |Description |
|
||||
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`analogReadPin(pin)` |Reads the value from the specified pin, eg. `A0` for channel 0 on the STM32F0 and ADC1 channel 1 on the STM32F3. Note that if a pin can be used for multiple ADCs, it will pick the lower numbered ADC for this function. eg. `C0` will be channel 6 of ADC 1 when it could be used for ADC 2 as well.|
|
||||
|`analogReadPinAdc(pin, adc)`|Reads the value from the specified pin and ADC, eg. `C0, 1` will read from channel 6, ADC 2 instead of ADC 1. Note that the ADCs are 0-indexed for this function. |
|
||||
|`pinToMux(pin)` |Translates a given pin to a channel and ADC combination. If an unsupported pin is given, returns the mux value for "0V (GND)". |
|
||||
|`adc_read(mux)` |Reads the value from the ADC according to the specified pin and ADC combination. See your MCU's datasheet for more information. |
|
||||
|
||||
## Configuration
|
||||
|
||||
## ARM
|
||||
|
||||
The ARM implementation of the ADC has a few additional options that you can override in your own keyboards and keymaps to change how it operates.
|
||||
The ARM implementation of the ADC has a few additional options that you can override in your own keyboards and keymaps to change how it operates. Please consult the corresponding `hal_adc_lld.h` in ChibiOS for your specific microcontroller for further documentation on your available options.
|
||||
|
||||
|`#define` |Type |Default |Description|
|
||||
|-------------------|------|---------------------|-----------|
|
||||
|ADC_CIRCULAR_BUFFER|`bool`|`false` |If `TRUE`, then the implementation will use a circular buffer.|
|
||||
|ADC_NUM_CHANNELS |`int` |`1` |Sets the number of channels that will be scanned as part of an ADC operation. The current implementation only supports `1`.|
|
||||
|ADC_BUFFER_DEPTH |`int` |`2` |Sets the depth of each result. Since we are only getting a 12-bit result by default, we set this to `2` bytes so we can contain our one value. This could be set to 1 if you opt for a 8-bit or lower result.|
|
||||
|ADC_SAMPLING_RATE |`int` |`ADC_SMPR_SMP_1P5` |Sets the sampling rate of the ADC. By default, it is set to the fastest setting. Please consult the corresponding `hal_adc_lld.h` in ChibiOS for your specific microcontroller for further documentation on your available options.|
|
||||
|ADC_RESOLUTION |`int` |`ADC_CFGR1_RES_12BIT`|The resolution of your result. We choose 12 bit by default, but you can opt for 12, 10, 8, or 6 bit. Please consult the corresponding `hal_adc_lld.h` in ChibiOS for your specific microcontroller for further documentation on your available options.|
|
||||
|`#define` |Type |Default |Description |
|
||||
|---------------------|------|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`ADC_CIRCULAR_BUFFER`|`bool`|`false` |If `true`, then the implementation will use a circular buffer. |
|
||||
|`ADC_NUM_CHANNELS` |`int` |`1` |Sets the number of channels that will be scanned as part of an ADC operation. The current implementation only supports `1`. |
|
||||
|`ADC_BUFFER_DEPTH` |`int` |`2` |Sets the depth of each result. Since we are only getting a 12-bit result by default, we set this to 2 bytes so we can contain our one value. This could be set to 1 if you opt for an 8-bit or lower result.|
|
||||
|`ADC_SAMPLING_RATE` |`int` |`ADC_SMPR_SMP_1P5` |Sets the sampling rate of the ADC. By default, it is set to the fastest setting. |
|
||||
|`ADC_RESOLUTION` |`int` |`ADC_CFGR1_RES_12BIT`|The resolution of your result. We choose 12 bit by default, but you can opt for 12, 10, 8, or 6 bit. |
|
||||
|
@@ -6,27 +6,30 @@ The breaking change period is when we will merge PR's that change QMK in dangero
|
||||
|
||||
## What has been included in past Breaking Changes?
|
||||
|
||||
* [2020 Nov 28](ChangeLog/20201128.md)
|
||||
* [2020 Aug 29](ChangeLog/20200829.md)
|
||||
* [2020 May 30](ChangeLog/20200530.md)
|
||||
* [2020 Feb 29](ChangeLog/20200229.md)
|
||||
* [2019 Aug 30](ChangeLog/20190830.md)
|
||||
|
||||
## When is the next Breaking Change?
|
||||
|
||||
The next Breaking Change is scheduled for May 30, 2020.
|
||||
The next Breaking Change is scheduled for February 27, 2021.
|
||||
|
||||
### Important Dates
|
||||
|
||||
* [x] 2020 Feb 29 - `future` is created. It will be rebased weekly.
|
||||
* [ ] 2020 May 2 - `future` closed to new PR's.
|
||||
* [ ] 2020 May 2 - Call for testers.
|
||||
* [ ] 2020 May 28 - `master` is locked, no PR's merged.
|
||||
* [ ] 2020 May 30 - Merge `future` to `master`.
|
||||
* [ ] 2020 May 30 - `master` is unlocked. PR's can be merged again.
|
||||
* [x] 2020 Nov 28 - `develop` is created. Each push to `master` is subsequently merged to `develop`
|
||||
* [ ] 2021 Jan 30 - `develop` closed to new PR's.
|
||||
* [ ] 2021 Jan 30 - Call for testers.
|
||||
* [ ] 2021 Feb 25 - `master` is locked, no PR's merged.
|
||||
* [ ] 2021 Feb 27 - Merge `develop` to `master`.
|
||||
* [ ] 2021 Feb 27 - `master` is unlocked. PR's can be merged again.
|
||||
|
||||
## What changes will be included?
|
||||
|
||||
To see a list of breaking change candidates you can look at the [`breaking_change` label](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Abreaking_change+is%3Apr). New changes might be added between now and when `future` is closed, and a PR with that label applied is not guaranteed to be merged.
|
||||
To see a list of breaking change candidates you can look at the [`breaking_change` label](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Abreaking_change+is%3Apr). New changes might be added between now and when `develop` is closed, and a PR with that label applied is not guaranteed to be merged.
|
||||
|
||||
If you want your breaking change to be included in this round you need to create a PR with the `breaking_change` label and have it accepted before `future` closes. After `future` closes no new breaking changes will be accepted.
|
||||
If you want your breaking change to be included in this round you need to create a PR with the `breaking_change` label and have it accepted before `develop` closes. After `develop` closes no new breaking changes will be accepted.
|
||||
|
||||
Criteria for acceptance:
|
||||
|
||||
@@ -37,41 +40,26 @@ Criteria for acceptance:
|
||||
|
||||
This section documents various processes we use when running the Breaking Changes process.
|
||||
|
||||
## Rebase `future` from `master`
|
||||
## Creating the `develop` branch
|
||||
|
||||
This is run every Friday while `future` is open.
|
||||
|
||||
Process:
|
||||
|
||||
```
|
||||
cd qmk_firmware
|
||||
git checkout master
|
||||
git pull --ff-only
|
||||
git checkout future
|
||||
git rebase master
|
||||
git push --force
|
||||
```
|
||||
|
||||
## Creating the `future` branch
|
||||
|
||||
This happens immediately after the previous `future` branch is merged.
|
||||
This happens immediately after the previous `develop` branch is merged.
|
||||
|
||||
* `qmk_firmware` git commands
|
||||
* [ ] `git checkout master`
|
||||
* [ ] `git pull --ff-only`
|
||||
* [ ] `git checkout -b future`
|
||||
* [ ] `git checkout -b develop`
|
||||
* [ ] Edit `readme.md`
|
||||
* [ ] Add a big notice at the top that this is a testing branch.
|
||||
* [ ] Include a link to this document
|
||||
* [ ] `git commit -m 'Branch point for <DATE> Breaking Change'`
|
||||
* [ ] `git tag breakpoint_<YYYY>_<MM>_<DD>`
|
||||
* [ ] `git tag <next_version>` # Prevent the breakpoint tag from confusing version incrementing
|
||||
* [ ] `git push origin future`
|
||||
* [ ] `git push origin develop`
|
||||
* [ ] `git push --tags`
|
||||
|
||||
## 4 Weeks Before Merge
|
||||
|
||||
* `future` is now closed to new PR's, only fixes for current PR's may be merged
|
||||
* `develop` is now closed to new PR's, only fixes for current PR's may be merged
|
||||
* Post call for testers
|
||||
* [ ] Discord
|
||||
* [ ] GitHub PR
|
||||
@@ -94,15 +82,15 @@ This happens immediately after the previous `future` branch is merged.
|
||||
## Day Of Merge
|
||||
|
||||
* `qmk_firmware` git commands
|
||||
* [ ] `git checkout future`
|
||||
* [ ] `git checkout develop`
|
||||
* [ ] `git pull --ff-only`
|
||||
* [ ] `git rebase origin/master`
|
||||
* [ ] Edit `readme.md`
|
||||
* [ ] Remove the notes about `future`
|
||||
* [ ] Remove the notes about `develop`
|
||||
* [ ] Roll up the ChangeLog into one file.
|
||||
* [ ] `git commit -m 'Merge point for <DATE> Breaking Change'`
|
||||
* [ ] `git push origin future`
|
||||
* [ ] `git push origin develop`
|
||||
* GitHub Actions
|
||||
* [ ] Create a PR for `future`
|
||||
* [ ] Create a PR for `develop`
|
||||
* [ ] Make sure travis comes back clean
|
||||
* [ ] Merge `future` PR
|
||||
* [ ] Merge `develop` PR
|
||||
|
@@ -27,7 +27,7 @@ If you are contributing core code, and the only reason it needs to go through br
|
||||
|
||||
We require submissions that go through the Breaking Change process to include a changelog entry. The entry should be a short summary of the changes your pull request makes – [each section here started as a changelog](ChangeLog/20190830.md "n.b. This should link to the 2019 Aug 30 Breaking Changes doc - @noroadsleft").
|
||||
|
||||
Your changelog should be located at `docs/ChangeLog/YYYYMMDD/PR####.md`, where `YYYYMMDD` is the date on which QMK's breaking change branch – usually named `future` – will be merged into the `master` branch, and `####` is the number of your pull request.
|
||||
Your changelog should be located at `docs/ChangeLog/YYYYMMDD/PR####.md`, where `YYYYMMDD` is the date on which QMK's breaking change branch – usually named `develop` – will be merged into the `master` branch, and `####` is the number of your pull request.
|
||||
|
||||
If your submission requires action on the part of users, your changelog should instruct users what action(s) must be taken, or link to a location that does so.
|
||||
|
||||
|
@@ -167,6 +167,35 @@ Creates a keymap.c from a QMK Configurator export.
|
||||
qmk json2c [-o OUTPUT] filename
|
||||
```
|
||||
|
||||
## `qmk c2json`
|
||||
|
||||
Creates a keymap.json from a keymap.c.
|
||||
**Note:** Parsing C source files is not easy, therefore this subcommand may not work your keymap. In some cases not using the C pre-processor helps.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk c2json [--no-cpp] [-o OUTPUT] filename
|
||||
```
|
||||
|
||||
## `qmk lint`
|
||||
|
||||
Checks over a keyboard and/or keymap and highlights common errors, problems, and anti-patterns.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk lint [-km KEYMAP] [-kb KEYBOARD] [--strict]
|
||||
```
|
||||
|
||||
This command is directory aware. It will automatically fill in KEYBOARD and/or KEYMAP if you are in a keyboard or keymap directory.
|
||||
|
||||
**Examples**:
|
||||
|
||||
Do a basic lint check:
|
||||
|
||||
qmk lint -kb rominronin/katana60/rev2
|
||||
|
||||
## `qmk list-keyboards`
|
||||
|
||||
This command lists all the keyboards currently defined in `qmk_firmware`
|
||||
@@ -201,6 +230,16 @@ This command is directory aware. It will automatically fill in KEYBOARD and/or K
|
||||
qmk new-keymap [-kb KEYBOARD] [-km KEYMAP]
|
||||
```
|
||||
|
||||
## `qmk clean`
|
||||
|
||||
This command cleans up the `.build` folder. If `--all` is passed, any .hex or .bin files present in the `qmk_firmware` directory will also be deleted.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk clean [-a]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Developer Commands
|
||||
@@ -247,6 +286,16 @@ This command starts a local HTTP server which you can use for browsing or improv
|
||||
qmk docs [-p PORT]
|
||||
```
|
||||
|
||||
## `qmk generate-docs`
|
||||
|
||||
This command allows you to generate QMK documentation locally. It can be uses for general browsing or improving the docs. External tools such as [serve](https://www.npmjs.com/package/serve) can be used to browse the generated files.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk generate-docs
|
||||
```
|
||||
|
||||
## `qmk kle2json`
|
||||
|
||||
This command allows you to convert from raw KLE data to QMK Configurator JSON. It accepts either an absolute file path, or a file name in the current directory. By default it will not overwrite `info.json` if it is already present. Use the `-f` or `--force` flag to overwrite.
|
||||
@@ -288,4 +337,3 @@ This command runs the python test suite. If you make changes to python code you
|
||||
```
|
||||
qmk pytest
|
||||
```
|
||||
|
||||
|
@@ -14,6 +14,7 @@ Certain MCUs which do not have native USB will use [V-USB](https://www.obdev.at/
|
||||
|
||||
* [ATmega32A](https://www.microchip.com/wwwproducts/en/ATmega32A)
|
||||
* [ATmega328P](https://www.microchip.com/wwwproducts/en/ATmega328P)
|
||||
* [ATmega328](https://www.microchip.com/wwwproducts/en/ATmega328)
|
||||
|
||||
## ARM
|
||||
|
||||
|
@@ -29,7 +29,9 @@ This level contains all of the options for that particular keymap. If you wish t
|
||||
|
||||
This is a C header file that is one of the first things included, and will persist over the whole project (if included). Lots of variables can be set here and accessed elsewhere. The `config.h` file shouldn't be including other `config.h` files, or anything besides this:
|
||||
|
||||
#include "config_common.h"
|
||||
```c
|
||||
#include "config_common.h"
|
||||
```
|
||||
|
||||
|
||||
## Hardware Options
|
||||
@@ -43,8 +45,6 @@ This is a C header file that is one of the first things included, and will persi
|
||||
* generally who/whatever brand produced the board
|
||||
* `#define PRODUCT Board`
|
||||
* the name of the keyboard
|
||||
* `#define DESCRIPTION a keyboard`
|
||||
* a short description of what the keyboard is
|
||||
* `#define MATRIX_ROWS 5`
|
||||
* the number of rows in your keyboard's matrix
|
||||
* `#define MATRIX_COLS 15`
|
||||
@@ -137,6 +137,8 @@ If you define these options you will enable the associated feature, which may in
|
||||
* `#define RETRO_TAPPING`
|
||||
* tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release
|
||||
* See [Retro Tapping](tap_hold.md#retro-tapping) for details
|
||||
* `#define RETRO_TAPPING_PER_KEY`
|
||||
* enables handling for per key `RETRO_TAPPING` settings
|
||||
* `#define TAPPING_TOGGLE 2`
|
||||
* how many taps before triggering the toggle
|
||||
* `#define PERMISSIVE_HOLD`
|
||||
@@ -197,6 +199,8 @@ If you define these options you will enable the associated feature, which may in
|
||||
* Note: Increasing the maximum will increase the firmware size and slow sync on split keyboards.
|
||||
* `#define RGBLIGHT_LAYER_BLINK`
|
||||
* Adds ability to [blink](feature_rgblight.md?id=lighting-layer-blink) a lighting layer for a specified number of milliseconds (e.g. to acknowledge an action).
|
||||
* `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF`
|
||||
* If defined, then [lighting layers](feature_rgblight?id=overriding-rgb-lighting-onoff-status) will be shown even if RGB Light is off.
|
||||
* `#define RGBLED_NUM 12`
|
||||
* number of LEDs
|
||||
* `#define RGBLIGHT_SPLIT`
|
||||
@@ -248,7 +252,10 @@ There are a few different ways to set handedness for split keyboards (listed in
|
||||
* `#define SPLIT_HAND_PIN B7`
|
||||
* For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses.
|
||||
|
||||
* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` is not defined)
|
||||
* `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>`
|
||||
* The handedness is determined by using the intersection of the keyswitches in the key matrix, which does not exist. Normally, when this intersection is shorted (level low), it is considered left. If you define `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT`, it is determined to be right when the level is low.
|
||||
|
||||
* `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` and `SPLIT_HAND_MATRIX_GRID` are not defined)
|
||||
* Reads the handedness value stored in the EEPROM after `eeprom-lefthand.eep`/`eeprom-righthand.eep` has been flashed to their respective halves.
|
||||
|
||||
* `#define MASTER_RIGHT`
|
||||
@@ -321,11 +328,9 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i
|
||||
```
|
||||
* `LAYOUTS`
|
||||
* A list of [layouts](feature_layouts.md) this keyboard supports.
|
||||
* `LINK_TIME_OPTIMIZATION_ENABLE`
|
||||
* `LTO_ENABLE`
|
||||
* Enables Link Time Optimization (LTO) when compiling the keyboard. This makes the process take longer, but it can significantly reduce the compiled size (and since the firmware is small, the added time is not noticeable).
|
||||
However, this will automatically disable the legacy TMK Macros and Functions features, as these break when LTO is enabled. It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION`. (Note: This does not affect QMK [Macros](feature_macros.md) and [Layers](feature_layers.md).)
|
||||
* `LTO_ENABLE`
|
||||
* Has the same meaning as `LINK_TIME_OPTIMIZATION_ENABLE`. You can use `LTO_ENABLE` instead of `LINK_TIME_OPTIMIZATION_ENABLE`.
|
||||
|
||||
## AVR MCU Options
|
||||
* `MCU = atmega32u4`
|
||||
@@ -370,10 +375,8 @@ Use these to enable or disable building certain features. The more you have enab
|
||||
* MIDI controls
|
||||
* `UNICODE_ENABLE`
|
||||
* Unicode
|
||||
* `BLUETOOTH_ENABLE`
|
||||
* Legacy option to Enable Bluetooth with the Adafruit EZ-Key HID. See BLUETOOTH
|
||||
* `BLUETOOTH`
|
||||
* Current options are AdafruitEzKey, AdafruitBLE, RN42
|
||||
* Current options are AdafruitBLE, RN42
|
||||
* `SPLIT_KEYBOARD`
|
||||
* Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common
|
||||
* `CUSTOM_MATRIX`
|
||||
|
193
docs/configurator_default_keymaps.md
Normal file
193
docs/configurator_default_keymaps.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Adding Default Keymaps to QMK Configurator :id=adding-default-keymaps
|
||||
|
||||
This page covers how to add a default keymap for a keyboard to QMK Configurator.
|
||||
|
||||
|
||||
## Technical Information :id=technical-information
|
||||
|
||||
QMK Configurator uses JSON as its native file format for keymaps. As much as possible, these should be kept such that they behave the same as running `make <keyboard>:default` from `qmk_firmware`.
|
||||
|
||||
Keymaps in this directory require four key-value pairs:
|
||||
|
||||
* `keyboard` (string)
|
||||
* This is the name of the keyboard, the same as would be used when running a compile job through `make` (e.g. `make 1upkeyboards/1up60rgb:default`).
|
||||
* `keymap` (string)
|
||||
* Should be set to `default`.
|
||||
* `layout` (string)
|
||||
* This is the layout macro used by the default keymap.
|
||||
* `layers` (array)
|
||||
* The keymap itself. This key should contain one array per layer, which themselves should contain the keycodes that make up that layer.
|
||||
|
||||
Additionally, most keymaps contain a `commit` key. This key is not consumed by the API that back-stops QMK Configurator, but is used by Configurator's maintainers to tell which version of a keymap was used to create the JSON keymap in this repository. The value is the SHA of the last commit to modify a board's default `keymap.c` in the `qmk_firmware` repository. The SHA is found by checking out [the `master` branch of the `qmk/qmk_firmware` repository](https://github.com/qmk/qmk_firmware/tree/master/) and running `git log -1 --pretty=oneline -- keyboards/<keyboard>/keymaps/default/keymap.c` (use `keymap.json` if the keyboard in question has this file instead), which should return something similar to:
|
||||
|
||||
```shell
|
||||
f14629ed1cd7c7ec9089604d64f29a99981558e8 Remove/migrate action_get_macro()s from default keymaps (#5625)
|
||||
```
|
||||
|
||||
In this example, `f14629ed1cd7c7ec9089604d64f29a99981558e8` is the value that should be used for `commit`.
|
||||
|
||||
|
||||
## Example :id=example
|
||||
|
||||
If one wished to add a default keymap for the H87a by Hineybush, one would run the `git log` command above against the H87a's default keymap in `qmk_firmware`:
|
||||
|
||||
```shell
|
||||
user ~/qmk_firmware (master)
|
||||
$ git log -1 --pretty=oneline master -- keyboards/hineybush/h87a/keymaps/default/keymap.c
|
||||
ef8878fba5d3786e3f9c66436da63a560cd36ac9 Hineybush h87a lock indicators (#8237)
|
||||
```
|
||||
|
||||
Now that we have the commit hash, we need the keymap (edited for readability):
|
||||
|
||||
```c
|
||||
...
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
[0] = LAYOUT_all(
|
||||
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS,
|
||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT,
|
||||
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_TRNS, KC_UP,
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||||
|
||||
[1] = LAYOUT_all(
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, BL_TOGG, BL_DEC, BL_INC,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, KC_MNXT, KC_VOLD,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
The default keymap uses the `LAYOUT_all` macro, so that will be the value of the `layout` key. Compiled to a QMK Configurator JSON keymap, our resulting file should be:
|
||||
|
||||
```json
|
||||
{
|
||||
"keyboard": "hineybush/h87a",
|
||||
"keymap": "default",
|
||||
"commit": "ef8878fba5d3786e3f9c66436da63a560cd36ac9",
|
||||
"layout": "LAYOUT_all",
|
||||
"layers": [
|
||||
[
|
||||
"KC_ESC", "KC_F1", "KC_F2", "KC_F3", "KC_F4", "KC_F5", "KC_F6", "KC_F7", "KC_F8", "KC_F9", "KC_F10", "KC_F11", "KC_F12", "KC_PSCR", "KC_SLCK", "KC_PAUS",
|
||||
"KC_GRV", "KC_1", "KC_2", "KC_3", "KC_4", "KC_5", "KC_6", "KC_7", "KC_8", "KC_9", "KC_0", "KC_MINS", "KC_EQL", "KC_BSPC", "KC_BSPC", "KC_INS", "KC_HOME", "KC_PGUP",
|
||||
"KC_TAB", "KC_Q", "KC_W", "KC_E", "KC_R", "KC_T", "KC_Y", "KC_U", "KC_I", "KC_O", "KC_P", "KC_LBRC", "KC_RBRC", "KC_BSLS", "KC_DEL", "KC_END", "KC_PGDN",
|
||||
"KC_CAPS", "KC_A", "KC_S", "KC_D", "KC_F", "KC_G", "KC_H", "KC_J", "KC_K", "KC_L", "KC_SCLN", "KC_QUOT", "KC_NUHS", "KC_ENT",
|
||||
"KC_LSFT", "KC_NUBS", "KC_Z", "KC_X", "KC_C", "KC_V", "KC_B", "KC_N", "KC_M", "KC_COMM", "KC_DOT", "KC_SLSH", "KC_RSFT", "KC_TRNS", "KC_UP",
|
||||
"KC_LCTL", "KC_LGUI", "KC_LALT", "KC_SPC", "KC_RALT", "MO(1)", "KC_RGUI", "KC_RCTL", "KC_LEFT", "KC_DOWN", "KC_RGHT"
|
||||
],
|
||||
[
|
||||
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RGB_TOG", "RGB_MOD", "RGB_HUD", "RGB_HUI", "RGB_SAD", "RGB_SAI", "RGB_VAD", "RGB_VAI", "BL_TOGG", "BL_DEC", "BL_INC",
|
||||
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_VOLU",
|
||||
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "RESET", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPLY", "KC_MNXT", "KC_VOLD",
|
||||
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
|
||||
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
|
||||
"KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS"
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The white space in the `layers` arrays have no effect on the functionality of the keymap, but are used to make these files easier for humans to read.
|
||||
|
||||
|
||||
## Caveats :id=caveats
|
||||
|
||||
### Layers can only be referenced by number :id=layer-references
|
||||
|
||||
A common QMK convention is to name layers using a series of `#define`s, or an `enum` statement:
|
||||
|
||||
```c
|
||||
enum layer_names {
|
||||
_BASE,
|
||||
_MEDIA,
|
||||
_FN
|
||||
};
|
||||
```
|
||||
|
||||
This works in C, but for Configurator, you *must* use the layer's numeric index – `MO(_FN)` would need to be `MO(2)` in the above example.
|
||||
|
||||
### No support for custom code of any kind :id=custom-code
|
||||
|
||||
Features that require adding functions to the keymap.c file, such as Tap Dance or Unicode, can not be compiled in Configurator **at all**. Even setting `TAP_DANCE_ENABLE = yes` in the `qmk_firmware` repository at the keyboard level will prevent Configurator from compiling **any** firmware for that keyboard. This is limited both by the API and the current spec of our JSON keymap format.
|
||||
|
||||
### Limited Support for Custom keycodes :id=custom-keycodes
|
||||
|
||||
There is a way to support custom keycodes: if the logic for a custom keycode is implemented at the keyboard level instead of the keymap level in qmk_firmware, that keycode *can* be used in Configurator and it *will* compile and work. Instead of using the following in your `keymap.c`:
|
||||
|
||||
```c
|
||||
enum custom_keycodes {
|
||||
MACRO_1 = SAFE_RANGE,
|
||||
MACRO_2,
|
||||
MACRO_3
|
||||
};
|
||||
...
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch(keycode) {
|
||||
case MACRO_1:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("This is macro #1.");
|
||||
}
|
||||
return false;
|
||||
case MACRO_2:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("This is macro #2.");
|
||||
}
|
||||
return false;
|
||||
case MACRO_3:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("This is macro #3.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
... add the keycode `enum` block to your keyboard's header file (`<keyboard>.h`) as follows (note that the `enum` is named `keyboard_keycodes` here):
|
||||
|
||||
```c
|
||||
enum keyboard_keycodes {
|
||||
MACRO_1 = SAFE_RANGE,
|
||||
MACRO_2,
|
||||
MACRO_3,
|
||||
NEW_SAFE_RANGE // Important!
|
||||
};
|
||||
```
|
||||
|
||||
... then the logic to your `<keyboard>.c` through `process_record_kb()`:
|
||||
|
||||
```c
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
switch(keycode) {
|
||||
case MACRO_1:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("This is macro #1.");
|
||||
}
|
||||
return false;
|
||||
case MACRO_2:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("This is macro #2.");
|
||||
}
|
||||
return false;
|
||||
case MACRO_3:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING("This is macro #3.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return process_record_user(keycode, record);
|
||||
};
|
||||
```
|
||||
|
||||
Note the call to `process_record_user()` at the end. Additionally, users of the keyboard will need to use `NEW_SAFE_RANGE` instead of `SAFE_RANGE` if they wish to add their own custom keycodes at keymap level, beyond what is provided by the keyboard.
|
||||
|
||||
|
||||
## Additional Reading :id=additional-reading
|
||||
|
||||
For QMK Configurator to support your keyboard, your keyboard must be present in the `master` branch of the `qmk_firmware` repository. For instructions on this, please see [Supporting Your Keyboard in QMK Configurator](reference_configurator_support.md).
|
@@ -57,7 +57,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_ENTER:
|
||||
// Play a tone when enter is pressed
|
||||
if (record->event.pressed) {
|
||||
PLAY_NOTE_ARRAY(tone_qwerty);
|
||||
PLAY_SONG(tone_qwerty);
|
||||
}
|
||||
return true; // Let QMK send the enter press/release events
|
||||
default:
|
||||
@@ -88,108 +88,6 @@ keyrecord_t record {
|
||||
}
|
||||
```
|
||||
|
||||
# LED Control
|
||||
|
||||
QMK provides methods to read 5 of the LEDs defined in the HID spec:
|
||||
|
||||
* Num Lock
|
||||
* Caps Lock
|
||||
* Scroll Lock
|
||||
* Compose
|
||||
* Kana
|
||||
|
||||
There are two ways to get the lock LED state:
|
||||
|
||||
* by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or
|
||||
* by calling `led_t host_keyboard_led_state()`
|
||||
|
||||
!> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called.
|
||||
|
||||
Two more deprecated functions exist that provide the LED state as a `uint8_t`:
|
||||
|
||||
* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
|
||||
* `uint8_t host_keyboard_leds()`
|
||||
|
||||
## `led_update_user()`
|
||||
|
||||
This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
|
||||
|
||||
By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
|
||||
return `false` when you would prefer not to run the code in `led_update_kb()`.
|
||||
|
||||
Some examples include:
|
||||
|
||||
- overriding the LEDs to use them for something else like layer indication
|
||||
- return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
|
||||
- play a sound when an LED turns on or off.
|
||||
- return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
|
||||
|
||||
?> Because the `led_set_*` functions return `void` instead of `bool`, they do not allow for overriding the keyboard LED control, and thus it's recommended to use `led_update_*` instead.
|
||||
|
||||
### Example `led_update_kb()` Implementation
|
||||
|
||||
```c
|
||||
bool led_update_kb(led_t led_state) {
|
||||
bool res = led_update_user(led_state);
|
||||
if(res) {
|
||||
// writePin sets the pin high for 1 and low for 0.
|
||||
// In this example the pins are inverted, setting
|
||||
// it low/0 turns it on, and high/1 turns the LED off.
|
||||
// This behavior depends on whether the LED is between the pin
|
||||
// and VCC or the pin and GND.
|
||||
writePin(B0, !led_state.num_lock);
|
||||
writePin(B1, !led_state.caps_lock);
|
||||
writePin(B2, !led_state.scroll_lock);
|
||||
writePin(B3, !led_state.compose);
|
||||
writePin(B4, !led_state.kana);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
### Example `led_update_user()` Implementation
|
||||
|
||||
This incomplete example would play a sound if Caps Lock is turned on or off. It returns `true`, because you also want the LEDs to maintain their state.
|
||||
|
||||
```c
|
||||
#ifdef AUDIO_ENABLE
|
||||
float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
|
||||
float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
|
||||
#endif
|
||||
|
||||
bool led_update_user(led_t led_state) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
static uint8_t caps_state = 0;
|
||||
if (caps_state != led_state.caps_lock) {
|
||||
led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
|
||||
caps_state = led_state.caps_lock;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### `led_update_*` Function Documentation
|
||||
|
||||
* Keyboard/Revision: `bool led_update_kb(led_t led_state)`
|
||||
* Keymap: `bool led_update_user(led_t led_state)`
|
||||
|
||||
## `host_keyboard_led_state()`
|
||||
|
||||
Call this function to get the last received LED state as a `led_t`. This is useful for reading the LED state outside `led_update_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
|
||||
|
||||
## Setting Physical LED State
|
||||
|
||||
Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
|
||||
|
||||
### Ergodox Boards
|
||||
|
||||
The Ergodox implementations provide `ergodox_right_led_1`/`2`/`3_on`/`off()` to turn individual LEDs on or off, as well as `ergodox_right_led_on`/`off(uint8_t led)` to turn them on or off by their index.
|
||||
|
||||
In addition, it is possible to specify the brightness level of all LEDs with `ergodox_led_all_set(uint8_t n)`; of individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`; or by index with `ergodox_right_led_set(uint8_t led, uint8_t n)`.
|
||||
|
||||
Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default).
|
||||
|
||||
# Keyboard Initialization Code
|
||||
|
||||
There are several steps in the keyboard initialization process. Depending on what you want to do, it will influence which function you should use.
|
||||
@@ -287,6 +185,14 @@ This function gets called at every matrix scan, which is basically as often as t
|
||||
|
||||
You should use this function if you need custom matrix scanning code. It can also be used for custom status output (such as LEDs or a display) or other functionality that you want to trigger regularly even when the user isn't typing.
|
||||
|
||||
# Keyboard housekeeping
|
||||
|
||||
* Keyboard/Revision: `void housekeeping_task_kb(void)`
|
||||
* Keymap: `void housekeeping_task_user(void)`
|
||||
|
||||
This function gets called at the end of all QMK processing, before starting the next iteration. You can safely assume that QMK has dealt with the last matrix scan at the time that these functions are invoked -- layer states have been updated, USB reports have been sent, LEDs have been updated, and displays have been drawn.
|
||||
|
||||
Similar to `matrix_scan_*`, these are called as often as the MCU can handle. To keep your board responsive, it's suggested to do as little as possible during these function calls, potentially throtting their behaviour if you do indeed require implementing something special.
|
||||
|
||||
# Keyboard Idling/Wake Code
|
||||
|
||||
@@ -319,7 +225,7 @@ This runs code every time that the layers get changed. This can be useful for l
|
||||
|
||||
### Example `layer_state_set_*` Implementation
|
||||
|
||||
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example
|
||||
This example shows how to set the [RGB Underglow](feature_rgblight.md) lights based on the layer, using the Planck as an example.
|
||||
|
||||
```c
|
||||
layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
@@ -343,6 +249,11 @@ layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
return state;
|
||||
}
|
||||
```
|
||||
|
||||
Use the `IS_LAYER_ON_STATE(state, layer)` and `IS_LAYER_OFF_STATE(state, layer)` macros to check the status of a particular layer.
|
||||
|
||||
Outside of `layer_state_set_*` functions, you can use the `IS_LAYER_ON(layer)` and `IS_LAYER_OFF(layer)` macros to check global layer state.
|
||||
|
||||
### `layer_state_set_*` Function Documentation
|
||||
|
||||
* Keyboard/Revision: `layer_state_t layer_state_set_kb(layer_state_t state)`
|
||||
@@ -438,7 +349,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_ENTER:
|
||||
// Play a tone when enter is pressed
|
||||
if (record->event.pressed) {
|
||||
PLAY_NOTE_ARRAY(tone_qwerty);
|
||||
PLAY_SONG(tone_qwerty);
|
||||
}
|
||||
return true; // Let QMK send the enter press/release events
|
||||
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
|
||||
@@ -449,7 +360,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
layer_state_set(layer_state); // then immediately update the layer color
|
||||
}
|
||||
}
|
||||
return false; break;
|
||||
return false;
|
||||
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
|
||||
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
|
||||
if (user_config.rgb_layer_change) { // only if this is enabled
|
||||
@@ -486,56 +397,3 @@ And you're done. The RGB layer indication will only work if you want it to. And
|
||||
* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)`
|
||||
|
||||
The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM.
|
||||
|
||||
# Custom Tapping Term
|
||||
|
||||
By default, the tapping term and related options (such as `IGNORE_MOD_TAP_INTERRUPT`) are defined globally, and are not configurable by key. For most users, this is perfectly fine. But in some cases, dual function keys would be greatly improved by different timeout behaviors than `LT` keys, or because some keys may be easier to hold than others. Instead of using custom key codes for each, this allows for per key configurable timeout behaviors.
|
||||
|
||||
There are two configurable options to control per-key timeout behaviors:
|
||||
|
||||
- `TAPPING_TERM_PER_KEY`
|
||||
- `IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
|
||||
|
||||
You need to add `#define` lines to your `config.h` for each feature you want.
|
||||
|
||||
```
|
||||
#define TAPPING_TERM_PER_KEY
|
||||
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
|
||||
```
|
||||
|
||||
|
||||
## Example `get_tapping_term` Implementation
|
||||
|
||||
To change the `TAPPING_TERM` based on the keycode, you'd want to add something like the following to your `keymap.c` file:
|
||||
|
||||
```c
|
||||
uint16_t get_tapping_term(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case SFT_T(KC_SPC):
|
||||
return TAPPING_TERM + 1250;
|
||||
case LT(1, KC_GRV):
|
||||
return 130;
|
||||
default:
|
||||
return TAPPING_TERM;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Example `get_ignore_mod_tap_interrupt` Implementation
|
||||
|
||||
To change the `IGNORE_MOD_TAP_INTERRUPT` value based on the keycode, you'd want to add something like the following to your `keymap.c` file:
|
||||
|
||||
```c
|
||||
bool get_ignore_mod_tap_interrupt(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case SFT_T(KC_SPC):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `get_tapping_term` / `get_ignore_mod_tap_interrupt` Function Documentation
|
||||
|
||||
Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only user level functions are useful here, so no need to mark them as such.
|
||||
|
@@ -41,7 +41,9 @@ Bevorzugst Du es lieber auf der Befehlszeile zu debuggen? Dafür eignet sich das
|
||||
|
||||
Manchmal ist es hilfreich Debug-Nachrichten innerhalb deines eigenen [Custom Codes](de/custom_quantum_functions.md) zu drucken. Das ist ziemlich einfach. Beginne damit `print.h` am Anfang deiner Datei zu inkludieren:
|
||||
|
||||
#include <print.h>
|
||||
```c
|
||||
#include "print.h"
|
||||
```
|
||||
|
||||
Danach stehen dir verschiedene Druck-Funktionen zur Verfügung:
|
||||
|
||||
|
@@ -61,4 +61,4 @@ This page describes my cool feature. You can use my cool feature to make coffee
|
||||
|KC_SUGAR||Order Sugar|
|
||||
```
|
||||
|
||||
Place your documentation into `docs/feature_<my_cool_feature>.md`, and add that file to the appropriate place in `docs/_sidebar.md`. If you have added any keycodes be sure to add them to `docs/keycodes.md` with a link back to your feature page.
|
||||
Place your documentation into `docs/feature_<my_cool_feature>.md`, and add that file to the appropriate place in `docs/_summary.md`. If you have added any keycodes be sure to add them to `docs/keycodes.md` with a link back to your feature page.
|
||||
|
@@ -4,7 +4,7 @@ QMK presents itself to the host as a regular HID keyboard device, and as such re
|
||||
|
||||
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the HalfKay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
|
||||
|
||||
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2 or WSL, the `qmk_install.sh` script will have asked if you want it to install the drivers for you.
|
||||
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2, the `qmk_install.sh` script will have already installed the drivers for you.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -23,7 +23,7 @@ Zadig will automatically detect the bootloader device. You may sometimes need to
|
||||
|
||||
!> If Zadig lists one or more devices with the `HidUsb` driver, your keyboard is probably not in bootloader mode. The arrow will be colored orange and you will be asked to confirm modifying a system driver. **Do not** proceed if this is the case!
|
||||
|
||||
If the arrow appears green, select the driver, and click **Install Driver**. The `libusb-win32` driver will usually work for AVR, and `WinUSB` for ARM, but if you still cannot flash the board, try installing a different driver from the list. For flashing a USBaspLoader device via command line with msys2, the `libusbk` driver is recommended, otherwise `libusb-win32` will work fine if you are using QMK Toolbox for flashing.
|
||||
If the arrow appears green, select the driver, and click **Install Driver**. The `libusb-win32` driver will usually work for AVR, and `WinUSB` for ARM, but if you still cannot flash the board, try installing a different driver from the list. USBAspLoader devices must use the `libusbK` driver.
|
||||
|
||||

|
||||
|
||||
|
@@ -67,7 +67,7 @@ El archivo `config.h` es donde configuras el hardware y el conjunto de caracter
|
||||
|
||||
En la parte superior de `config.h` encontrarás ajustes relacionados con USB. Estos controlan la apariencia de tu teclado en el Sistema Operativo. Si no tienes una buena razón para cambiar debes dejar el `VENDOR_ID` como `0xFEED`. Para el `PRODUCT_ID` debes seleccionar un número que todavía no esté en uso.
|
||||
|
||||
Cambia las líneas de `MANUFACTURER`, `PRODUCT`, y `DESCRIPTION` para reflejar con precisión tu teclado.
|
||||
Cambia las líneas de `MANUFACTURER` y `PRODUCT` para reflejar con precisión tu teclado.
|
||||
|
||||
```c
|
||||
#define VENDOR_ID 0xFEED
|
||||
@@ -75,7 +75,6 @@ Cambia las líneas de `MANUFACTURER`, `PRODUCT`, y `DESCRIPTION` para reflejar c
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER Tú
|
||||
#define PRODUCT mi_teclado_fantastico
|
||||
#define DESCRIPTION Un teclado personalizado
|
||||
```
|
||||
|
||||
?> Windows y macOS mostrarán el `MANUFACTURER` y `PRODUCT` en la lista de dispositivos USB. `lsusb` en Linux toma estos de la lista mantenida por el [Repositorio de ID USB](http://www.linux-usb.org/usb-ids.html) por defecto. `lsusb -v` mostrará los valores reportados por el dispositivo, y también están presentes en los registros del núcleo después de conectarlo.
|
||||
|
@@ -41,7 +41,9 @@ Para plataformas compatibles, [QMK Toolbox](https://github.com/qmk/qmk_toolbox)
|
||||
|
||||
A veces, es útil imprimir mensajes de depuración desde tu [código personalizado](custom_quantum_functions.md). Hacerlo es bastante simple. Comienza incluyendo `print.h` al principio de tu fichero:
|
||||
|
||||
#include <print.h>
|
||||
```c
|
||||
#include "print.h"
|
||||
```
|
||||
|
||||
Después de eso puedes utilzar algunas funciones print diferentes:
|
||||
|
||||
|
@@ -13,68 +13,29 @@ An example of using `sudo`, when your controller is ATMega32u4:
|
||||
|
||||
or just:
|
||||
|
||||
$ sudo make <keyboard>:<keymap>:dfu
|
||||
$ sudo make <keyboard>:<keymap>:flash
|
||||
|
||||
Note that running `make` with `sudo` is generally ***not*** a good idea, and you should use one of the former methods, if possible.
|
||||
|
||||
### Linux `udev` Rules
|
||||
On Linux, you'll need proper privileges to access the MCU. You can either use
|
||||
`sudo` when flashing firmware, or place these files in `/etc/udev/rules.d/`. Once added run the following:
|
||||
```console
|
||||
|
||||
On Linux, you'll need proper privileges to communicate with the bootloader device. You can either use `sudo` when flashing firmware (not recommended), or place [this file](https://github.com/qmk/qmk_firmware/tree/master/util/udev/50-qmk.rules) into `/etc/udev/rules.d/`.
|
||||
|
||||
Once added, run the following:
|
||||
|
||||
```
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/50-atmel-dfu.rules:**
|
||||
```
|
||||
# Atmel ATMega32U4
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", MODE:="0666"
|
||||
# Atmel USBKEY AT90USB1287
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffb", MODE:="0666"
|
||||
# Atmel ATMega32U2
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff0", MODE:="0666"
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/52-tmk-keyboard.rules:**
|
||||
```
|
||||
# tmk keyboard products https://github.com/tmk/tmk_keyboard
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
|
||||
```
|
||||
**/etc/udev/rules.d/54-input-club-keyboard.rules:**
|
||||
**Note:** With older versions of ModemManager (< 1.12), filtering only works when not in strict mode. The following commands can update that setting:
|
||||
|
||||
```
|
||||
# Input Club keyboard bootloader
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", MODE:="0666"
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/55-caterina.rules:**
|
||||
```
|
||||
# ModemManager should ignore the following devices
|
||||
ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
```
|
||||
|
||||
**Note:** ModemManager filtering only works when not in strict mode, the following commands can update that settings:
|
||||
```console
|
||||
sudo sed -i 's/--filter-policy=strict/--filter-policy=default/' /lib/systemd/system/ModemManager.service
|
||||
printf '[Service]\nExecStart=\nExecStart=/usr/sbin/ModemManager --filter-policy=default' | sudo tee /etc/systemd/system/ModemManager.service.d/policy.conf
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart ModemManager
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/56-dfu-util.rules:**
|
||||
```
|
||||
# stm32duino
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="0003", MODE:="0666"
|
||||
# Generic stm32
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666"
|
||||
```
|
||||
|
||||
**/etc/udev/rules.d/57-bootloadhid.rules:**
|
||||
```
|
||||
# bootloadHID
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", MODE:="0666"
|
||||
```
|
||||
|
||||
### Serial device is not detected in bootloader mode on Linux
|
||||
Make sure your kernel has appropriate support for your device. If your device uses USB ACM, such as
|
||||
Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices may require `USB_SERIAL` and any of its sub options.
|
||||
@@ -99,46 +60,6 @@ You can buy a really unique VID:PID here. I don't think you need this for person
|
||||
- http://www.obdev.at/products/vusb/license.html
|
||||
- http://www.mcselec.com/index.php?page=shop.product_details&flypage=shop.flypage&product_id=92&option=com_phpshop&Itemid=1
|
||||
|
||||
## BOOTLOADER_SIZE for AVR
|
||||
Note that Teensy2.0++ bootloader size is 2048byte. Some Makefiles may have wrong comment.
|
||||
|
||||
```
|
||||
# Boot Section Size in *bytes*
|
||||
# Teensy halfKay 512
|
||||
# Teensy++ halfKay 2048
|
||||
# Atmel DFU loader 4096 (TMK Alt Controller)
|
||||
# LUFA bootloader 4096
|
||||
# USBaspLoader 2048
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=2048
|
||||
```
|
||||
|
||||
## `avr-gcc: internal compiler error: Abort trap: 6 (program cc1)` on MacOS
|
||||
|
||||
This is an issue with updating on brew, causing symlinks that avr-gcc depend on getting mangled.
|
||||
|
||||
The solution is to remove and reinstall all affected modules.
|
||||
|
||||
```
|
||||
brew rm avr-gcc avr-gcc@8 dfu-programmer dfu-util gcc-arm-none-eabi arm-gcc-bin@8 avrdude qmk
|
||||
brew install qmk/qmk/qmk
|
||||
brew link --force avr-gcc@8
|
||||
brew link --force arm-gcc-bin@8
|
||||
```
|
||||
|
||||
### `avr-gcc` and LUFA
|
||||
|
||||
If you updated your `avr-gcc` and you see errors involving LUFA, for example:
|
||||
|
||||
`lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h:380:5: error: 'const' attribute on function returning 'void'`
|
||||
|
||||
For now, you need to rollback `avr-gcc` to 8 in Homebrew.
|
||||
|
||||
```
|
||||
brew uninstall --force avr-gcc
|
||||
brew install avr-gcc@8
|
||||
brew link --force avr-gcc@8
|
||||
```
|
||||
|
||||
### I just flashed my keyboard and it does nothing/keypresses don't register - it's also ARM (rev6 planck, clueboard 60, hs60v2, etc...) (Feb 2019)
|
||||
Due to how EEPROM works on ARM based chips, saved settings may no longer be valid. This affects the default layers, and *may*, under certain circumstances we are still figuring out, make the keyboard unusable. Resetting the EEPROM will correct this.
|
||||
|
||||
|
@@ -31,20 +31,6 @@ Check:
|
||||
- try using 'print' function instead of debug print. See **common/print.h**.
|
||||
- disconnect other devices with console function. See [Issue #97](https://github.com/tmk/tmk_keyboard/issues/97).
|
||||
|
||||
## Linux or UNIX Like System Requires Super User Privilege
|
||||
Just use 'sudo' to execute *hid_listen* with privilege.
|
||||
```
|
||||
$ sudo hid_listen
|
||||
```
|
||||
|
||||
Or add an *udev rule* for TMK devices with placing a file in rules directory. The directory may vary on each system.
|
||||
|
||||
File: /etc/udev/rules.d/52-tmk-keyboard.rules(in case of Ubuntu)
|
||||
```
|
||||
# tmk keyboard products https://github.com/tmk/tmk_keyboard
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
# Miscellaneous
|
||||
|
@@ -2,21 +2,24 @@
|
||||
|
||||
These allow you to combine a modifier with a keycode. When pressed, the keydown event for the modifier, then `kc` will be sent. On release, the keyup event for `kc`, then the modifier will be sent.
|
||||
|
||||
|Key |Aliases |Description |
|
||||
|----------|-------------------------------|----------------------------------------------------|
|
||||
|`LCTL(kc)`|`C(kc)` |Hold Left Control and press `kc` |
|
||||
|`LSFT(kc)`|`S(kc)` |Hold Left Shift and press `kc` |
|
||||
|`LALT(kc)`|`A(kc)`, `LOPT(kc)` |Hold Left Alt and press `kc` |
|
||||
|`LGUI(kc)`|`G(kc)`, `LCMD(kc)`, `LWIN(kc)`|Hold Left GUI and press `kc` |
|
||||
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|
||||
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|
||||
|`RALT(kc)`|`ROPT(kc)`, `ALGR(kc)` |Hold Right Alt and press `kc` |
|
||||
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|
||||
|`SGUI(kc)`|`SCMD(kc)`, `SWIN(kc)` |Hold Left Shift and GUI and press `kc` |
|
||||
|`LCA(kc)` | |Hold Left Control and Alt and press `kc` |
|
||||
|`LCAG(kc)`| |Hold Left Control, Alt and GUI and press `kc` |
|
||||
|`MEH(kc)` | |Hold Left Control, Shift and Alt and press `kc` |
|
||||
|`HYPR(kc)`| |Hold Left Control, Shift, Alt and GUI and press `kc`|
|
||||
|Key |Aliases |Description |
|
||||
|----------|-------------------------------|------------------------------------------------------|
|
||||
|`LCTL(kc)`|`C(kc)` |Hold Left Control and press `kc` |
|
||||
|`LSFT(kc)`|`S(kc)` |Hold Left Shift and press `kc` |
|
||||
|`LALT(kc)`|`A(kc)`, `LOPT(kc)` |Hold Left Alt and press `kc` |
|
||||
|`LGUI(kc)`|`G(kc)`, `LCMD(kc)`, `LWIN(kc)`|Hold Left GUI and press `kc` |
|
||||
|`RCTL(kc)`| |Hold Right Control and press `kc` |
|
||||
|`RSFT(kc)`| |Hold Right Shift and press `kc` |
|
||||
|`RALT(kc)`|`ROPT(kc)`, `ALGR(kc)` |Hold Right Alt and press `kc` |
|
||||
|`RGUI(kc)`|`RCMD(kc)`, `LWIN(kc)` |Hold Right GUI and press `kc` |
|
||||
|`SGUI(kc)`|`SCMD(kc)`, `SWIN(kc)` |Hold Left Shift and GUI and press `kc` |
|
||||
|`LCA(kc)` | |Hold Left Control and Alt and press `kc` |
|
||||
|`LSA(kc)` | |Hold Left Shift and Left Alt and press `kc` |
|
||||
|`RSA(kc)` |`SAGR(kc)` |Hold Right Shift and Right Alt (AltGr) and press `kc` |
|
||||
|`RCS(kc)` | |Hold Right Control and Right Shift and press `kc` |
|
||||
|`LCAG(kc)`| |Hold Left Control, Alt and GUI and press `kc` |
|
||||
|`MEH(kc)` | |Hold Left Control, Shift and Alt and press `kc` |
|
||||
|`HYPR(kc)`| |Hold Left Control, Shift, Alt and GUI and press `kc` |
|
||||
|
||||
You can also chain them, for example `LCTL(LALT(KC_DEL))` or `C(A(KC_DEL))` makes a key that sends Control+Alt+Delete with a single keypress.
|
||||
|
||||
|
@@ -15,25 +15,31 @@ problem.
|
||||
When you tap a key, it stays depressed for a short period of time before it is
|
||||
then released. This depressed time is a different length for everyone. Auto Shift
|
||||
defines a constant `AUTO_SHIFT_TIMEOUT` which is typically set to twice your
|
||||
normal pressed state time. When you press a key, a timer starts and then stops
|
||||
when you release the key. If the time depressed is greater than or equal to the
|
||||
`AUTO_SHIFT_TIMEOUT`, then a shifted version of the key is emitted. If the time
|
||||
is less than the `AUTO_SHIFT_TIMEOUT` time, then the normal state is emitted.
|
||||
normal pressed state time. When you press a key, a timer starts, and if you
|
||||
have not released the key after the `AUTO_SHIFT_TIMEOUT` period, then a shifted
|
||||
version of the key is emitted. If the time is less than the `AUTO_SHIFT_TIMEOUT`
|
||||
time, or you press another key, then the normal state is emitted.
|
||||
|
||||
If `AUTO_SHIFT_REPEAT` is defined, there is keyrepeat support. Holding the key
|
||||
down will repeat the shifted key, though this can be disabled with
|
||||
`AUTO_SHIFT_NO_AUTO_REPEAT`. If you want to repeat the normal key, then tap it
|
||||
once then immediately (within `TAPPING_TERM`) hold it down again (this works
|
||||
with the shifted value as well if auto-repeat is disabled).
|
||||
|
||||
## Are There Limitations to Auto Shift?
|
||||
|
||||
Yes, unfortunately.
|
||||
|
||||
1. Key repeat will cease to work. For example, before if you wanted 20 'a'
|
||||
characters, you could press and hold the 'a' key for a second or two. This no
|
||||
longer works with Auto Shift because it is timing your depressed time instead
|
||||
of emitting a depressed key state to your operating system.
|
||||
2. You will have characters that are shifted when you did not intend on shifting, and
|
||||
other characters you wanted shifted, but were not. This simply comes down to
|
||||
practice. As we get in a hurry, we think we have hit the key long enough
|
||||
for a shifted version, but we did not. On the other hand, we may think we are
|
||||
tapping the keys, but really we have held it for a little longer than
|
||||
anticipated.
|
||||
You will have characters that are shifted when you did not intend on shifting, and
|
||||
other characters you wanted shifted, but were not. This simply comes down to
|
||||
practice. As we get in a hurry, we think we have hit the key long enough for a
|
||||
shifted version, but we did not. On the other hand, we may think we are tapping
|
||||
the keys, but really we have held it for a little longer than anticipated.
|
||||
|
||||
Additionally, with keyrepeat the desired shift state can get mixed up. It will
|
||||
always 'belong' to the last key pressed. For example, keyrepeating a capital
|
||||
and then tapping something lowercase (whether or not it's an Auto Shift key)
|
||||
will result in the capital's *key* still being held, but shift not.
|
||||
|
||||
## How Do I Enable Auto Shift?
|
||||
|
||||
@@ -103,6 +109,14 @@ Do not Auto Shift numeric keys, zero through nine.
|
||||
|
||||
Do not Auto Shift alpha characters, which include A through Z.
|
||||
|
||||
### AUTO_SHIFT_REPEAT (simple define)
|
||||
|
||||
Enables keyrepeat.
|
||||
|
||||
### AUTO_SHIFT_NO_AUTO_REPEAT (simple define)
|
||||
|
||||
Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
|
||||
|
||||
## Using Auto Shift Setup
|
||||
|
||||
This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`.
|
||||
@@ -139,7 +153,7 @@ completely normal and with no intention of shifted keys.
|
||||
`KC_ASRP`. The keyboard will type by itself the value of your
|
||||
`AUTO_SHIFT_TIMEOUT`.
|
||||
7. Update `AUTO_SHIFT_TIMEOUT` in your `config.h` with the value reported.
|
||||
8. Remove `AUTO_SHIFT_SETUP` from your `config.h`.
|
||||
8. Add `AUTO_SHIFT_NO_SETUP` to your `config.h`.
|
||||
9. Remove the key bindings `KC_ASDN`, `KC_ASUP` and `KC_ASRP`.
|
||||
10. Compile and upload your new firmware.
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Backlighting
|
||||
# Backlighting :id=backlighting
|
||||
|
||||
Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
|
||||
|
||||
@@ -6,103 +6,107 @@ QMK is able to control the brightness of these LEDs by switching them on and off
|
||||
|
||||
The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
|
||||
|
||||
## Feature Configuration
|
||||
|
||||
Most keyboards have backlighting enabled by default if they support it, but if it is not working for you, check that your `rules.mk` includes the following:
|
||||
|
||||
```makefile
|
||||
BACKLIGHT_ENABLE = yes
|
||||
```
|
||||
|
||||
## Keycodes
|
||||
Once enabled the following keycodes below can be used to change the backlight level.
|
||||
## Keycodes :id=keycodes
|
||||
|
||||
|Key |Description |
|
||||
|---------|------------------------------------------|
|
||||
|`BL_TOGG`|Turn the backlight on or off |
|
||||
|`BL_STEP`|Cycle through backlight levels |
|
||||
|`BL_ON` |Set the backlight to max brightness |
|
||||
|`BL_OFF` |Turn the backlight off |
|
||||
|`BL_INC` |Increase the backlight level |
|
||||
|`BL_DEC` |Decrease the backlight level |
|
||||
|`BL_BRTG`|Toggle backlight breathing |
|
||||
Once enabled, the following keycodes below can be used to change the backlight level.
|
||||
|
||||
## Backlight Functions
|
||||
|Key |Description |
|
||||
|---------|-----------------------------------|
|
||||
|`BL_TOGG`|Turn the backlight on or off |
|
||||
|`BL_STEP`|Cycle through backlight levels |
|
||||
|`BL_ON` |Set the backlight to max brightness|
|
||||
|`BL_OFF` |Turn the backlight off |
|
||||
|`BL_INC` |Increase the backlight level |
|
||||
|`BL_DEC` |Decrease the backlight level |
|
||||
|`BL_BRTG`|Toggle backlight breathing |
|
||||
|
||||
|Function |Description |
|
||||
|----------|-----------------------------------------------------------|
|
||||
|`backlight_toggle()` |Turn the backlight on or off |
|
||||
|`backlight_enable()` |Turn the backlight on |
|
||||
|`backlight_disable()` |Turn the backlight off |
|
||||
|`backlight_step()` |Cycle through backlight levels |
|
||||
|`backlight_increase()` |Increase the backlight level |
|
||||
|`backlight_decrease()` |Decrease the backlight level |
|
||||
|`backlight_level(x)` |Sets the backlight level to specified level |
|
||||
|`get_backlight_level()` |Return the current backlight level |
|
||||
|`is_backlight_enabled()`|Return whether the backlight is currently on |
|
||||
## Functions :id=functions
|
||||
|
||||
### Backlight Breathing Functions
|
||||
These functions can be used to change the backlighting in custom code:
|
||||
|
||||
|Function |Description |
|
||||
|----------|---------------------------------------------------|
|
||||
|`breathing_toggle()` |Turn the backlight breathing on or off |
|
||||
|`breathing_enable()` |Turns on backlight breathing |
|
||||
|`breathing_disable()` |Turns off backlight breathing |
|
||||
|Function |Description |
|
||||
|------------------------|--------------------------------------------|
|
||||
|`backlight_toggle()` |Turn the backlight on or off |
|
||||
|`backlight_enable()` |Turn the backlight on |
|
||||
|`backlight_disable()` |Turn the backlight off |
|
||||
|`backlight_step()` |Cycle through backlight levels |
|
||||
|`backlight_increase()` |Increase the backlight level |
|
||||
|`backlight_decrease()` |Decrease the backlight level |
|
||||
|`backlight_level(x)` |Sets the backlight level to specified level |
|
||||
|`get_backlight_level()` |Return the current backlight level |
|
||||
|`is_backlight_enabled()`|Return whether the backlight is currently on|
|
||||
|
||||
## Driver Configuration
|
||||
If backlight breathing is enabled (see below), the following functions are also available:
|
||||
|
||||
|Function |Description |
|
||||
|---------------------|--------------------------------------|
|
||||
|`breathing_toggle()` |Turn the backlight breathing on or off|
|
||||
|`breathing_enable()` |Turns on backlight breathing |
|
||||
|`breathing_disable()`|Turns off backlight breathing |
|
||||
|
||||
## Configuration :id=configuration
|
||||
|
||||
To select which driver to use, configure your `rules.mk` with the following:
|
||||
|
||||
```makefile
|
||||
BACKLIGHT_DRIVER = software # Valid driver values are 'pwm,software,no'
|
||||
BACKLIGHT_DRIVER = software
|
||||
```
|
||||
|
||||
See below for help on individual drivers.
|
||||
Valid driver values are `pwm`, `software`, `custom` or `no`. See below for help on individual drivers.
|
||||
|
||||
## Common Driver Configuration
|
||||
To configure the backlighting, `#define` these in your `config.h`:
|
||||
|
||||
To change the behavior of the backlighting, `#define` these in your `config.h`:
|
||||
| Define | Default | Description |
|
||||
|------------------------|---------------|-------------------------------------------------------------------------------------------------------------------|
|
||||
| `BACKLIGHT_PIN` | *Not defined* | The pin that controls the LED(s) |
|
||||
| `BACKLIGHT_LEVELS` | `3` | The number of brightness levels (maximum 31 excluding off) |
|
||||
| `BACKLIGHT_CAPS_LOCK` | *Not defined* | Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
||||
| `BACKLIGHT_BREATHING` | *Not defined* | Enable backlight breathing, if supported |
|
||||
| `BREATHING_PERIOD` | `6` | The length of one backlight "breath" in seconds |
|
||||
| `BACKLIGHT_ON_STATE` | `1` | The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
|
||||
| `BACKLIGHT_LIMIT_VAL ` | `255` | The maximum duty cycle of the backlight -- `255` allows for full brightness, any lower will decrease the maximum. |
|
||||
|
||||
|Define |Default |Description |
|
||||
|---------------------|-------------|--------------------------------------------------------------------------------------|
|
||||
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|
||||
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
||||
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if supported |
|
||||
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
||||
|`BACKLIGHT_ON_STATE` |`0` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
|
||||
Unless you are designing your own keyboard, you generally should not need to change the `BACKLIGHT_PIN` or `BACKLIGHT_ON_STATE`.
|
||||
|
||||
### Backlight On State
|
||||
### Backlight On State :id=backlight-on-state
|
||||
|
||||
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
|
||||
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
|
||||
|
||||
This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
|
||||
|
||||
## AVR driver
|
||||
### AVR Driver :id=avr-driver
|
||||
|
||||
The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
|
||||
|
||||
On AVR boards, the default driver currently sniffs the configuration to pick the best scenario. The driver is configured by default, however the equivalent setting within rules.mk would be:
|
||||
```makefile
|
||||
BACKLIGHT_DRIVER = pwm
|
||||
```
|
||||
|
||||
### Caveats
|
||||
#### Caveats :id=avr-caveats
|
||||
|
||||
Hardware PWM is supported according to the following table:
|
||||
On AVR boards, QMK automatically decides which driver to use according to the following table:
|
||||
|
||||
|Backlight Pin|AT90USB64/128|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328P|
|
||||
|-------------|-------------|-------------|-------------|---------|----------|
|
||||
|`B1` | | | | |Timer 1 |
|
||||
|`B2` | | | | |Timer 1 |
|
||||
|`B5` |Timer 1 |Timer 1 | | | |
|
||||
|`B6` |Timer 1 |Timer 1 | | | |
|
||||
|`B7` |Timer 1 |Timer 1 |Timer 1 | | |
|
||||
|`C4` |Timer 3 | | | | |
|
||||
|`C5` |Timer 3 | |Timer 1 | | |
|
||||
|`C6` |Timer 3 |Timer 3 |Timer 1 | | |
|
||||
|`D4` | | | |Timer 1 | |
|
||||
|`D5` | | | |Timer 1 | |
|
||||
|Backlight Pin|AT90USB64/128|ATmega16/32U4|ATmega16/32U2|ATmega32A|ATmega328/P|
|
||||
|-------------|-------------|-------------|-------------|---------|-----------|
|
||||
|`B1` | | | | |Timer 1 |
|
||||
|`B2` | | | | |Timer 1 |
|
||||
|`B5` |Timer 1 |Timer 1 | | | |
|
||||
|`B6` |Timer 1 |Timer 1 | | | |
|
||||
|`B7` |Timer 1 |Timer 1 |Timer 1 | | |
|
||||
|`C4` |Timer 3 | | | | |
|
||||
|`C5` |Timer 3 | |Timer 1 | | |
|
||||
|`C6` |Timer 3 |Timer 3 |Timer 1 | | |
|
||||
|`D4` | | | |Timer 1 | |
|
||||
|`D5` | | | |Timer 1 | |
|
||||
|
||||
All other pins will use software PWM. If the [Audio](feature_audio.md) feature is disabled or only using one timer, the backlight PWM can be triggered by a hardware timer:
|
||||
All other pins will use timer-assisted software PWM:
|
||||
|
||||
|Audio Pin|Audio Timer|Software PWM Timer|
|
||||
|---------|-----------|------------------|
|
||||
@@ -113,44 +117,9 @@ All other pins will use software PWM. If the [Audio](feature_audio.md) feature i
|
||||
|`B6` |Timer 1 |Timer 3 |
|
||||
|`B7` |Timer 1 |Timer 3 |
|
||||
|
||||
When both timers are in use for Audio, the backlight PWM will not use a hardware timer, but will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
|
||||
When both timers are in use for Audio, the backlight PWM cannot use a hardware timer, and will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
|
||||
|
||||
### AVR Configuration
|
||||
|
||||
To change the behavior of the backlighting, `#define` these in your `config.h`:
|
||||
|
||||
|Define |Default |Description |
|
||||
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|`BACKLIGHT_PINS` |*Not defined*|experimental: see below for more information |
|
||||
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|
||||
|`BACKLIGHT_CAPS_LOCK`|*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
||||
|`BACKLIGHT_BREATHING`|*Not defined*|Enable backlight breathing, if supported |
|
||||
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
||||
|`BACKLIGHT_ON_STATE` |`1` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
|
||||
|
||||
### Backlight On State
|
||||
|
||||
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
|
||||
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
|
||||
|
||||
This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
|
||||
|
||||
### Multiple backlight pins
|
||||
|
||||
Most keyboards have only one backlight pin which control all backlight LEDs (especially if the backlight is connected to an hardware PWM pin).
|
||||
In software PWM, it is possible to define multiple backlight pins. All those pins will be turned on and off at the same time during the PWM duty cycle.
|
||||
This feature allows to set for instance the Caps Lock LED (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped LCTRL in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on.
|
||||
|
||||
To activate multiple backlight pins, you need to add something like this to your user `config.h`:
|
||||
|
||||
```c
|
||||
#define BACKLIGHT_LED_COUNT 2
|
||||
#undef BACKLIGHT_PIN
|
||||
#define BACKLIGHT_PINS { F5, B2 }
|
||||
```
|
||||
|
||||
### Hardware PWM Implementation
|
||||
#### Hardware PWM Implementation :id=hardware-pwm-implementation
|
||||
|
||||
When using the supported pins for backlighting, QMK will use a hardware timer configured to output a PWM signal. This timer will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
||||
The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the backlight pin will go low, and is pulled high again when the counter resets.
|
||||
@@ -159,7 +128,7 @@ In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus th
|
||||
The breathing effect is achieved by registering an interrupt handler for `TIMER1_OVF_vect` that is called whenever the counter resets, roughly 244 times per second.
|
||||
In this handler, the value of an incrementing counter is mapped onto a precomputed brightness curve. To turn off breathing, the interrupt handler is simply disabled, and the brightness reset to the level stored in EEPROM.
|
||||
|
||||
### Timer Assisted PWM Implementation
|
||||
#### Timer Assisted PWM Implementation :id=timer-assisted-implementation
|
||||
|
||||
When `BACKLIGHT_PIN` is not set to a hardware backlight pin, QMK will use a hardware timer configured to trigger software interrupts. This time will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
||||
When resetting to 0, the CPU will fire an OVF (overflow) interrupt that will turn the LEDs on, starting the duty cycle.
|
||||
@@ -168,81 +137,82 @@ In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus th
|
||||
|
||||
The breathing effect is the same as in the hardware PWM implementation.
|
||||
|
||||
## ARM Driver
|
||||
### ARM Driver :id=arm-configuration
|
||||
|
||||
While still in its early stages, ARM backlight support aims to eventually have feature parity with AVR. The `pwm` driver is configured by default, however the equivalent setting within `rules.mk` would be:
|
||||
|
||||
While still in its early stages, ARM backlight support aims to eventually have feature parity with AVR. The driver is configured by default, however the equivalent setting within rules.mk would be:
|
||||
```makefile
|
||||
BACKLIGHT_DRIVER = pwm
|
||||
```
|
||||
|
||||
### Caveats
|
||||
#### ChibiOS Configuration :id=arm-configuration
|
||||
|
||||
The following `#define`s apply only to ARM-based keyboards:
|
||||
|
||||
|Define |Default|Description |
|
||||
|-----------------------|-------|-----------------------------------|
|
||||
|`BACKLIGHT_PWM_DRIVER` |`PWMD4`|The PWM driver to use |
|
||||
|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
|
||||
|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use|
|
||||
|
||||
See the ST datasheet for your particular MCU to determine these values. Unless you are designing your own keyboard, you generally should not need to change them.
|
||||
|
||||
#### Caveats :id=arm-caveats
|
||||
|
||||
Currently only hardware PWM is supported, not timer assisted, and does not provide automatic configuration.
|
||||
|
||||
?> Backlight support for STMF072 has had limited testing, YMMV. If unsure, set `BACKLIGHT_ENABLE = no` in your rules.mk.
|
||||
### Software PWM Driver :id=software-pwm-driver
|
||||
|
||||
### ARM Configuration
|
||||
In this mode, PWM is "emulated" while running other keyboard tasks. It offers maximum hardware compatibility without extra platform configuration. The tradeoff is the backlight might jitter when the keyboard is busy. To enable, add this to your `rules.mk`:
|
||||
|
||||
To change the behavior of the backlighting, `#define` these in your `config.h`:
|
||||
|
||||
|Define |Default |Description |
|
||||
|------------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use, see ST datasheets for pin to PWM timer mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|`BACKLIGHT_PWM_CHANNEL` |`3` |The PWM channel to use, see ST datasheets for pin to PWM channel mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use, see ST datasheets for pin AF mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|
||||
## Software PWM Driver :id=software-pwm-driver
|
||||
|
||||
Emulation of PWM while running other keyboard tasks, it offers maximum hardware compatibility without extra platform configuration. The tradeoff is the backlight might jitter when the keyboard is busy. To enable, add this to your rules.mk:
|
||||
```makefile
|
||||
BACKLIGHT_DRIVER = software
|
||||
```
|
||||
|
||||
### Software PWM Configuration
|
||||
|
||||
To change the behavior of the backlighting, `#define` these in your `config.h`:
|
||||
|
||||
|Define |Default |Description |
|
||||
|-----------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||
|`BACKLIGHT_PINS` |*Not defined*|experimental: see below for more information |
|
||||
|
||||
### Multiple backlight pins
|
||||
#### Multiple Backlight Pins :id=multiple-backlight-pins
|
||||
|
||||
Most keyboards have only one backlight pin which control all backlight LEDs (especially if the backlight is connected to an hardware PWM pin).
|
||||
In software PWM, it is possible to define multiple backlight pins. All those pins will be turned on and off at the same time during the PWM duty cycle.
|
||||
This feature allows to set for instance the Caps Lock LED (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped LCTRL in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on.
|
||||
In software PWM, it is possible to define multiple backlight pins, which will be turned on and off at the same time during the PWM duty cycle.
|
||||
|
||||
To activate multiple backlight pins, you need to add something like this to your user `config.h`:
|
||||
This feature allows to set, for instance, the Caps Lock LED's (or any other controllable LED) brightness at the same level as the other LEDs of the backlight. This is useful if you have mapped Control in place of Caps Lock and you need the Caps Lock LED to be part of the backlight instead of being activated when Caps Lock is on, as it is usually wired to a separate pin from the backlight.
|
||||
|
||||
To activate multiple backlight pins, add something like this to your `config.h`, instead of `BACKLIGHT_PIN`:
|
||||
|
||||
```c
|
||||
#undef BACKLIGHT_PIN
|
||||
#define BACKLIGHT_PINS { F5, B2 }
|
||||
```
|
||||
|
||||
## Custom Driver
|
||||
### Custom Driver :id=custom-driver
|
||||
|
||||
To enable, add this to your rules.mk:
|
||||
If none of the above drivers apply to your board (for example, you are using a separate IC to control the backlight), you can implement a custom backlight driver using this simple API provided by QMK. To enable, add this to your `rules.mk`:
|
||||
|
||||
```makefile
|
||||
BACKLIGHT_DRIVER = custom
|
||||
```
|
||||
|
||||
When implementing the custom driver API, the provided keyboard hooks are as follows:
|
||||
Then implement any of these hooks:
|
||||
|
||||
```c
|
||||
void backlight_init_ports(void) {
|
||||
// Optional - Run on startup
|
||||
// - usually you want to configure pins here
|
||||
// Optional - runs on startup
|
||||
// Usually you want to configure pins here
|
||||
}
|
||||
void backlight_set(uint8_t level) {
|
||||
// Optional - Run on level change
|
||||
// - usually you want to respond to the new value
|
||||
// Optional - runs on level change
|
||||
// Usually you want to respond to the new value
|
||||
}
|
||||
|
||||
void backlight_task(void) {
|
||||
// Optional - Run periodically
|
||||
// - long running actions here can cause performance issues
|
||||
// Optional - runs periodically
|
||||
// Note that this is called in the main keyboard loop,
|
||||
// so long running actions here can cause performance issues
|
||||
}
|
||||
```
|
||||
|
||||
## Example Schematic
|
||||
|
||||
In this typical example, the backlight LEDs are all connected in parallel towards an N-channel MOSFET. Its gate pin is wired to one of the microcontroller's GPIO pins through a 470Ω resistor to avoid ringing.
|
||||
A pulldown resistor is also placed between the gate pin and ground to keep it at a defined state when it is not otherwise being driven by the MCU.
|
||||
The values of these resistors are not critical - see [this Electronics StackExchange question](https://electronics.stackexchange.com/q/68748) for more information.
|
||||
|
||||

|
||||
|
@@ -2,11 +2,10 @@
|
||||
|
||||
## Bluetooth Known Supported Hardware
|
||||
|
||||
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules and the Bluefruit EZ-Key, the latter of which is not produced anymore. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
|
||||
Currently Bluetooth support is limited to AVR based chips. For Bluetooth 2.1, QMK has support for RN-42 modules. For more recent BLE protocols, currently only the Adafruit Bluefruit SPI Friend is directly supported. BLE is needed to connect to iOS devices. Note iOS does not support mouse input.
|
||||
|
||||
|Board |Bluetooth Protocol |Connection Type |rules.mk |Bluetooth Chip|
|
||||
|----------------------------------------------------------------|----------------------------|----------------|---------------------------|--------------|
|
||||
|[Adafruit EZ-Key HID](https://www.adafruit.com/product/1535) |Bluetooth Classic | UART |`BLUETOOTH = AdafruitEZKey` | |
|
||||
|Roving Networks RN-42 (Sparkfun Bluesmirf) |Bluetooth Classic | UART |`BLUETOOTH = RN42` | RN-42 |
|
||||
|[Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633)|Bluetooth Low Energy | SPI |`BLUETOOTH = AdafruitBLE` | nRF51822 |
|
||||
|
||||
@@ -24,16 +23,15 @@ Currently The only bluetooth chipset supported by QMK is the Adafruit Bluefruit
|
||||
|
||||
A Bluefruit UART friend can be converted to an SPI friend, however this [requires](https://github.com/qmk/qmk_firmware/issues/2274) some reflashing and soldering directly to the MDBT40 chip.
|
||||
|
||||
## Adafruit EZ-Key hid
|
||||
This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.
|
||||
|
||||
|
||||
<!-- FIXME: Document bluetooth support more completely. -->
|
||||
## Bluetooth Rules.mk Options
|
||||
Use only one of these
|
||||
|
||||
The currently supported Bluetooth chipsets do not support [N-Key Rollover (NKRO)](reference_glossary.md#n-key-rollover-nkro), so `rules.mk` must contain `NKRO_ENABLE = no`.
|
||||
|
||||
Use only one of these to enable Bluetooth:
|
||||
* BLUETOOTH_ENABLE = yes (Legacy Option)
|
||||
* BLUETOOTH = RN42
|
||||
* BLUETOOTH = AdafruitEZKey
|
||||
* BLUETOOTH = AdafruitBLE
|
||||
|
||||
## Bluetooth Keycodes
|
||||
|
@@ -55,7 +55,7 @@ combo_t key_combos[COMBO_COUNT] = {
|
||||
[XV_PASTE] = COMBO_ACTION(paste_combo),
|
||||
};
|
||||
|
||||
void process_combo_event(uint8_t combo_index, bool pressed) {
|
||||
void process_combo_event(uint16_t combo_index, bool pressed) {
|
||||
switch(combo_index) {
|
||||
case ZC_COPY:
|
||||
if (pressed) {
|
||||
|
@@ -1,43 +1,151 @@
|
||||
# Debounce algorithm
|
||||
# Contact bounce / contact chatter
|
||||
|
||||
Mechanical switches often don't have a clean single transition between pressed and unpressed states.
|
||||
|
||||
In an ideal world, when you press a switch, you would expect the digital pin to see something like this:
|
||||
(X axis showing time
|
||||
```
|
||||
voltage +----------------------
|
||||
^ |
|
||||
| |
|
||||
| ------------------+
|
||||
----> time
|
||||
```
|
||||
|
||||
However in the real world you will actually see contact bounce, which will look like multiple 1->0 and 0->1 transitions,
|
||||
until the value finally settles.
|
||||
```
|
||||
+-+ +--+ +-------------
|
||||
| | | | |
|
||||
| | | | |
|
||||
+-----------------+ +-+ +-+
|
||||
```
|
||||
The time it takes for the switch to settle might vary with switch type, age, and even pressing technique.
|
||||
|
||||
If the device chooses not to mitigate contact bounce, then often actions that happen when the switch is pressed are repeated
|
||||
multiple times.
|
||||
|
||||
There are many ways to handle contact bounce ("Debouncing"). Some include employing additional hardware, for example an RC filter,
|
||||
while there are various ways to do debouncing in software too, often called debounce algorithms. This page discusses software
|
||||
debouncing methods available in QMK.
|
||||
|
||||
While technically not considered contact bounce/contact chatter, some switch technologies are susceptible to noise, meaning,
|
||||
while the key is not changing state, sometimes short random 0->1 or 1->0 transitions might be read by the digital circuit, for example:
|
||||
```
|
||||
+-+
|
||||
| |
|
||||
| |
|
||||
+-----------------+ +--------------------
|
||||
```
|
||||
|
||||
Many debounce methods (but not all) will also make the device resistant to noise. If you are working with a technology that is
|
||||
susceptible to noise, you must choose a debounce method that will also mitigate noise for you.
|
||||
|
||||
## Types of debounce algorithms
|
||||
|
||||
1) Unit of time: Timestamp (milliseconds) vs Cycles (scans)
|
||||
* Debounce algorithms often have a 'debounce time' parameter, that specifies the maximum settling time of the switch contacts.
|
||||
This time might be measured in various units:
|
||||
* Cycles-based debouncing waits n cycles (scans), decreasing count by one each matrix_scan
|
||||
* Timestamp-based debouncing stores the millisecond timestamp a change occurred, and does substraction to figure out time elapsed.
|
||||
* Timestamp-based debouncing is usually superior, especially in the case of noise-resistant devices because settling times of physical
|
||||
switches is specified in units of time, and should not depend on the matrix scan-rate of the keyboard.
|
||||
* Cycles-based debouncing is sometimes considered inferior, because the settling time that it is able to compensate for depends on the
|
||||
performance of the matrix scanning code. If you use cycles-based debouncing, and you significantly improve the performance of your scanning
|
||||
code, you might end up with less effective debouncing. A situation in which cycles-based debouncing might be preferable is when
|
||||
noise is present, and the scanning algorithm is slow, or variable speed. Even if your debounce algorithm is fundamentally noise-resistant,
|
||||
if the scanning is slow, and you are using a timestamp-based algorithm, you might end up making a debouncing decision based on only two
|
||||
sampled values, which will limit the noise-resistance of the algorithm.
|
||||
* Currently all built-in debounce algorithms support timestamp-based debouncing only. In the future we might
|
||||
implement cycles-based debouncing, and it will be selectable via a ```config.h``` macro.
|
||||
|
||||
2) Symmetric vs Asymmetric
|
||||
* Symmetric - apply the same debouncing algorithm, to both key-up and key-down events.
|
||||
* Recommended naming convention: ```sym_*```
|
||||
* Asymmetric - apply different debouncing algorithms to key-down and key-up events. E.g. Eager key-down, Defer key-up.
|
||||
* Recommended naming convention: ```asym_*``` followed by details of the type of algorithm in use, in order, for key-down and then key-up
|
||||
|
||||
3) Eager vs Defer
|
||||
* Eager - any key change is reported immediately. All further inputs for DEBOUNCE ms are ignored.
|
||||
* Eager algorithms are not noise-resistant.
|
||||
* Recommended naming conventions:
|
||||
* ```sym_eager_*```
|
||||
* ```asym_eager_*_*```: key-down is using eager algorithm
|
||||
* ```asym_*_eager_*```: key-up is using eager algorithm
|
||||
* Defer - wait for no changes for DEBOUNCE ms before reporting change.
|
||||
* Defer algorithms are noise-resistant
|
||||
* Recommended naming conventions:
|
||||
* ```sym_defer_*```
|
||||
* ```asym_defer_*_*```: key-down is using defer algorithm
|
||||
* ```asym_*_defer_*```: key-up is using defer algorithm
|
||||
|
||||
4) Global vs Per-Key vs Per-Row
|
||||
* Global - one timer for all keys. Any key change state affects global timer
|
||||
* Recommended naming convention: ```*_g```
|
||||
* Per-key - one timer per key
|
||||
* Recommended naming convention: ```*_pk```
|
||||
* Per-row - one timer per row
|
||||
* Recommended naming convention: ```*_pr```
|
||||
* Per-key and per-row algorithms consume more resources (in terms of performance,
|
||||
and ram usage), but fast typists might prefer them over global.
|
||||
|
||||
## Debounce algorithms supported by QMK
|
||||
|
||||
QMK supports multiple debounce algorithms through its debounce API.
|
||||
|
||||
The logic for which debounce method called is below. It checks various defines that you have set in rules.mk
|
||||
The logic for which debounce method called is below. It checks various defines that you have set in ```rules.mk```
|
||||
|
||||
```
|
||||
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
|
||||
DEBOUNCE_TYPE?= sym_g
|
||||
DEBOUNCE_TYPE?= sym_defer_g
|
||||
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
|
||||
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
|
||||
endif
|
||||
```
|
||||
|
||||
# Debounce selection
|
||||
### Debounce selection
|
||||
|
||||
| DEBOUNCE_TYPE | Description | What else is needed |
|
||||
| ------------- | --------------------------------------------------- | ----------------------------- |
|
||||
| Not defined | Use the default algorithm, currently sym_g | Nothing |
|
||||
| Not defined | Use the default algorithm, currently sym_defer_g | Nothing |
|
||||
| custom | Use your own debounce code | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions |
|
||||
| anything_else | Use another algorithm from quantum/debounce/* | Nothing |
|
||||
| Anything Else | Use another algorithm from quantum/debounce/* | Nothing |
|
||||
|
||||
**Regarding split keyboards**:
|
||||
The debounce code is compatible with split keyboards.
|
||||
|
||||
# Use your own debouncing code
|
||||
* Set ```DEBOUNCE_TYPE = custom```.
|
||||
* Add ```SRC += debounce.c```
|
||||
### Selecting an included debouncing method
|
||||
Keyboards may select one of the already implemented debounce methods, by adding to ```rules.mk``` the following line:
|
||||
```
|
||||
DEBOUNCE_TYPE = <name of algorithm>
|
||||
```
|
||||
Where name of algorithm is one of:
|
||||
* ```sym_defer_g``` - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occurred, all input changes are pushed.
|
||||
* This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant.
|
||||
* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
|
||||
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
|
||||
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
|
||||
* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
|
||||
* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
|
||||
|
||||
### A couple algorithms that could be implemented in the future:
|
||||
* ```sym_defer_pr```
|
||||
* ```sym_eager_g```
|
||||
* ```asym_eager_defer_pk```
|
||||
|
||||
### Use your own debouncing code
|
||||
You have the option to implement you own debouncing algorithm. To do this:
|
||||
* Set ```DEBOUNCE_TYPE = custom``` in ```rules.mk```.
|
||||
* Add ```SRC += debounce.c``` in ```rules.mk```
|
||||
* Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples.
|
||||
* Debouncing occurs after every raw matrix scan.
|
||||
* Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly.
|
||||
* If the algorithm might be applicable to other keyboards, please consider adding it to ```quantum/debounce```
|
||||
|
||||
# Changing between included debouncing methods
|
||||
You can either use your own code, by including your own debounce.c, or switch to another included one.
|
||||
Included debounce methods are:
|
||||
* eager_pr - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
|
||||
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
|
||||
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
|
||||
* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
|
||||
* sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occured, all input changes are pushed.
|
||||
* sym_pk - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occured on that key, the key status change is pushed.
|
||||
### Old names
|
||||
The following old names for existing algorithms will continue to be supported, however it is recommended to use the new names instead.
|
||||
|
||||
* sym_g - old name for sym_defer_g
|
||||
* eager_pk - old name for sym_eager_pk
|
||||
* sym_pk - old name for sym_defer_pk
|
||||
* eager_pr - old name for sym_eager_pr
|
||||
|
||||
|
@@ -7,9 +7,17 @@ DIP switches are supported by adding this to your `rules.mk`:
|
||||
and this to your `config.h`:
|
||||
|
||||
```c
|
||||
// Connects each switch in the dip switch to the GPIO pin of the MCU
|
||||
#define DIP_SWITCH_PINS { B14, A15, A10, B9 }
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```c
|
||||
// Connect each switch in the DIP switch to an unused intersections in the key matrix.
|
||||
#define DIP_SWITCH_MATRIX_GRID { {0,6}, {1,6}, {2,6} } // List of row and col pairs
|
||||
```
|
||||
|
||||
## Callbacks
|
||||
|
||||
The callback functions can be inserted into your `<keyboard>.c`:
|
||||
@@ -87,4 +95,10 @@ void dip_switch_update_mask_user(uint32_t state) {
|
||||
|
||||
## Hardware
|
||||
|
||||
### Connects each switch in the dip switch to the GPIO pin of the MCU
|
||||
|
||||
One side of the DIP switch should be wired directly to the pin on the MCU, and the other side to ground. It should not matter which side is connected to which, as it should be functionally the same.
|
||||
|
||||
### Connect each switch in the DIP switch to an unused intersections in the key matrix.
|
||||
|
||||
As with the keyswitch, a diode and DIP switch connect the ROW line to the COL line.
|
||||
|
@@ -18,11 +18,11 @@ That should be everything necessary.
|
||||
|
||||
To start recording the macro, press either `DYN_REC_START1` or `DYN_REC_START2`.
|
||||
|
||||
To finish the recording, press the `DYN_REC_STOP` layer button.
|
||||
To finish the recording, press the `DYN_REC_STOP` layer button. You can also press `DYN_REC_START1` or `DYN_REC_START2` again to stop the recording.
|
||||
|
||||
To replay the macro, press either `DYN_MACRO_PLAY1` or `DYN_MACRO_PLAY2`.
|
||||
|
||||
It is possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. You can disable this completly by defining `DYNAMIC_MACRO_NO_NESTING` in your `config.h` file.
|
||||
It is possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. You can disable this completely by defining `DYNAMIC_MACRO_NO_NESTING` in your `config.h` file.
|
||||
|
||||
?> For the details about the internals of the dynamic macros, please read the comments in the `process_dynamic_macro.h` and `process_dynamic_macro.c` files.
|
||||
|
||||
|
@@ -26,19 +26,26 @@ If your encoder's clockwise directions are incorrect, you can swap the A & B pad
|
||||
#define ENCODER_DIRECTION_FLIP
|
||||
```
|
||||
|
||||
Additionally, the resolution can be specified in the same file (the default & suggested is 4):
|
||||
Additionally, the resolution, which defines how many pulses the encoder registers between each detent, can be defined with:
|
||||
|
||||
```c
|
||||
#define ENCODER_RESOLUTION 4
|
||||
```
|
||||
|
||||
It can also be defined per-encoder, by instead defining:
|
||||
|
||||
```c
|
||||
#define ENCODER_RESOLUTIONS { 4, 2 }
|
||||
```
|
||||
|
||||
## Split Keyboards
|
||||
|
||||
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout for the right half like this:
|
||||
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
|
||||
|
||||
```c
|
||||
#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a }
|
||||
#define ENCODERS_PAD_B_RIGHT { encoder1b, encoder2b }
|
||||
#define ENCODER_RESOLUTIONS_RIGHT { 2, 4 }
|
||||
```
|
||||
|
||||
## Callbacks
|
||||
|
@@ -42,14 +42,21 @@ First you will need a build a circuit to drive the solenoid through a mosfet as
|
||||
[Wiring diagram provided by Adafruit](https://playground.arduino.cc/uploads/Learning/solenoid_driver.pdf)
|
||||
|
||||
|
||||
| Settings | Default | Description |
|
||||
|--------------------------|---------------|-------------------------------------------------------|
|
||||
|`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. |
|
||||
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. |
|
||||
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|
||||
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
|
||||
| Settings | Default | Description |
|
||||
|----------------------------|----------------------|-------------------------------------------------------|
|
||||
|`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. |
|
||||
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. |
|
||||
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|
||||
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
|
||||
|`SOLENOID_DWELL_STEP_SIZE` | `1` ms |The step size to use when `HPT_DWL*` keycodes are sent |
|
||||
|`SOLENOID_DEFAULT_BUZZ` | `0` (disabled) |On HPT_RST buzz is set "on" if this is "1" |
|
||||
|`SOLENOID_BUZZ_ACTUATED` | `SOLENOID_MIN_DWELL` |Actuated-time when the solenoid is in buzz mode |
|
||||
|`SOLENOID_BUZZ_NONACTUATED` | `SOLENOID_MIN_DWELL` |Non-Actuated-time when the solenoid is in buzz mode |
|
||||
|
||||
?> Dwell time is how long the "plunger" stays activated. The dwell time changes how the solenoid sounds.
|
||||
* If solenoid buzz is off, then dwell time is how long the "plunger" stays activated. The dwell time changes how the solenoid sounds.
|
||||
* If solenoid buzz is on, then dwell time sets the length of the buzz, while `SOLENOID_BUZZ_ACTUATED` and `SOLENOID_BUZZ_NONACTUATED` set the (non-)actuation times withing the buzz period.
|
||||
* With the current implementation, for any of the above time settings, the precision of these settings may be affected by how fast the keyboard is able to scan the matrix.
|
||||
Therefore, if the keyboards scanning routine is slow, it may be preferable to set `SOLENOID_DWELL_STEP_SIZE` to a value slightly smaller than the time it takes to scan the keyboard.
|
||||
|
||||
Beware that some pins may be powered during bootloader (ie. A13 on the STM32F303 chip) and will result in the solenoid kept in the on state through the whole flashing process. This may overheat and damage the solenoid. If you find that the pin the solenoid is connected to is triggering the solenoid during bootloader/DFU, select another pin.
|
||||
|
||||
|
153
docs/feature_joystick.md
Normal file
153
docs/feature_joystick.md
Normal file
@@ -0,0 +1,153 @@
|
||||
## Joystick
|
||||
|
||||
The keyboard can be made to be recognized as a joystick HID device by the operating system.
|
||||
|
||||
This is enabled by adding `JOYSTICK_ENABLE` to `rules.mk`. You can set this value to `analog`, `digital`, or `no`.
|
||||
|
||||
!> Joystick support is not currently available on V-USB devices.
|
||||
|
||||
The joystick feature provides two services:
|
||||
* reading analog input devices (eg. potentiometers)
|
||||
* sending gamepad HID reports
|
||||
|
||||
Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance)
|
||||
or send gamepad reports based on values computed by the keyboard.
|
||||
|
||||
### Analog Input
|
||||
|
||||
To use analog input you must first enable it in `rules.mk`:
|
||||
|
||||
```makefile
|
||||
JOYSTICK_ENABLE = analog
|
||||
```
|
||||
|
||||
An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider).
|
||||
It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor,
|
||||
which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter).
|
||||
Depending on which pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated,
|
||||
feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures.
|
||||
|
||||
### Configuring the Joystick
|
||||
|
||||
By default, two axes and eight buttons are defined. This can be changed in your `config.h`:
|
||||
|
||||
```c
|
||||
// Max 32
|
||||
#define JOYSTICK_BUTTON_COUNT 16
|
||||
// Max 6: X, Y, Z, Rx, Ry, Rz
|
||||
#define JOYSTICK_AXES_COUNT 3
|
||||
```
|
||||
|
||||
When defining axes for your joystick, you have to provide a definition array. You can do this from your keymap.c file.
|
||||
A joystick will either be read from an input pin that allows the use of the ADC, or can be virtual, so that its value is provided by your code.
|
||||
You have to define an array of type ''joystick_config_t'' and of proper size.
|
||||
|
||||
There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU:
|
||||
* 1 pin: your analog device is directly connected to your device GND and VCC. The only pin used is the ADC pin of your choice.
|
||||
* 2 pins: your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC.
|
||||
* 3 pins: both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards.
|
||||
|
||||
The configuration of each axis is performed using one of four macros:
|
||||
* `JOYSTICK_AXIS_VIRTUAL`: no ADC reading must be performed, that value will be provided by keyboard/keymap-level code
|
||||
* `JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH)`: a voltage will be read on the provided pin, which must be an ADC-capable pin.
|
||||
* `JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH)`: the provided `OUTPUT_PIN` will be set high before `INPUT_PIN` is read.
|
||||
* `JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH)`: the `OUTPUT_PIN` will be set high and `GROUND_PIN` will be set low before reading from `INPUT_PIN`.
|
||||
|
||||
In any case where an ADC reading takes place (when `INPUT_PIN` is provided), additional `LOW`, `REST` and `HIGH` parameters are used.
|
||||
These implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127).
|
||||
In practice, you have to provide the lowest/highest raw ADC reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted `LOW` and `HIGH` to invert the axis.
|
||||
|
||||
For instance, an axes configuration can be defined in the following way:
|
||||
|
||||
```c
|
||||
//joystick config
|
||||
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
|
||||
[0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285),
|
||||
[1] = JOYSTICK_AXIS_VIRTUAL
|
||||
};
|
||||
```
|
||||
|
||||
When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read.
|
||||
|
||||
In this example, the first axis will be read from the `A4` pin while `B0` is set high and `A7` is set low, using `analogReadPin()`, whereas the second axis will not be read.
|
||||
|
||||
In order to give a value to the second axis, you can do so in any customizable entry point: as an action, in `process_record_user()` or in `matrix_scan_user()`, or even in `joystick_task()` which is called even when no key has been pressed.
|
||||
You assign a value by writing to `joystick_status.axes[axis_index]` a signed 8-bit value (ranging from -127 to 127). Then it is necessary to assign the flag `JS_UPDATED` to `joystick_status.status` in order for an updated HID report to be sent.
|
||||
|
||||
The following example writes two axes based on keypad presses, with `KC_P5` as a precision modifier:
|
||||
|
||||
```c
|
||||
#ifdef ANALOG_JOYSTICK_ENABLE
|
||||
static uint8_t precision_val = 70;
|
||||
static uint8_t axesFlags = 0;
|
||||
enum axes {
|
||||
Precision = 1,
|
||||
Axis1High = 2,
|
||||
Axis1Low = 4,
|
||||
Axis2High = 8,
|
||||
Axis2Low = 16
|
||||
};
|
||||
#endif
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch(keycode) {
|
||||
#ifdef ANALOG_JOYSTICK_ENABLE
|
||||
// virtual joystick
|
||||
# if JOYSTICK_AXES_COUNT > 1
|
||||
case KC_P8:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis2Low;
|
||||
} else {
|
||||
axesFlags &= ~Axis2Low;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
case KC_P2:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis2High;
|
||||
} else {
|
||||
axesFlags &= ~Axis2High;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
# endif
|
||||
case KC_P4:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis1Low;
|
||||
} else {
|
||||
axesFlags &= ~Axis1Low;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
case KC_P6:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis1High;
|
||||
} else {
|
||||
axesFlags &= ~Axis1High;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
case KC_P5:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Precision;
|
||||
} else {
|
||||
axesFlags &= ~Precision;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Axis Resolution
|
||||
|
||||
By default, the resolution of each axis is 8 bit, giving a range of -127 to +127. If you need higher precision, you can increase it by defining eg. `JOYSTICK_AXES_RESOLUTION 12` in your `config.h`. The resolution must be between 8 and 16.
|
||||
|
||||
Note that the supported AVR MCUs have a 10-bit ADC, and 12-bit for most STM32 MCUs.
|
||||
|
||||
### Triggering Joystick Buttons
|
||||
|
||||
Joystick buttons are normal Quantum keycodes, defined as `JS_BUTTON0` to `JS_BUTTON31`, depending on the number of buttons you have configured.
|
||||
To trigger a joystick button, just add the corresponding keycode to your keymap.
|
@@ -19,7 +19,7 @@ These functions allow you to activate layers in various ways. Note that layers a
|
||||
|
||||
### Caveats :id=caveats
|
||||
|
||||
Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Specifically, dual function keys like `LT` and `MT` use a 16 bit keycode. 4 bits are used for the function identifier, the next 12 are divided into the parameters. Layer Tap uses 4 bits for the layer (and is why it's limited to layers 0-16, actually), while Mod Tap does the same, 4 bits for the identifier, 4 bits for which mods are used, and all of them use 8 bits for the keycode. Because of this, the keycode used is limited to `0xFF` (0-255), which are the basic keycodes only.
|
||||
Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Specifically, dual function keys like `LT` and `MT` use a 16 bit keycode. 4 bits are used for the function identifier, the next 12 are divided into the parameters. Layer Tap uses 4 bits for the layer (and is why it's limited to layers 0-15, actually), while Mod Tap does the same, 4 bits for the identifier, 4 bits for which mods are used, and all of them use 8 bits for the keycode. Because of this, the keycode used is limited to `0xFF` (0-255), which are the basic keycodes only.
|
||||
|
||||
Expanding this would be complicated, at best. Moving to a 32-bit keycode would solve a lot of this, but would double the amount of space that the keymap matrix uses. And it could potentially cause issues, too. If you need to apply modifiers to your tapped keycode, [Tap Dance](feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this.
|
||||
|
||||
@@ -74,10 +74,9 @@ There are a number of functions (and variables) related to how you can use or ma
|
||||
| [`update_tri_layer(x, y, z)`](ref_functions.md#update_tri_layerx-y-z) | Checks if layers `x` and `y` are both on, and sets `z` based on that (on if both on, otherwise off). |
|
||||
| [`update_tri_layer_state(state, x, y, z)`](ref_functions.md#update_tri_layer_statestate-x-y-z) | Does the same as `update_tri_layer(x, y, z)`, but from `layer_state_set_*` functions. |
|
||||
|
||||
In addition to the functions that you can call, there are a number of callback functions that get called every time the layer changes. This passes the layer state to the function, where it can be read or modified.
|
||||
|
||||
In additional to the functions that you can call, there are a number of callback functions that get called every time the layer changes. This passed the layer state to the function, which can be read or modified.
|
||||
|
||||
|Callbacks |Description |
|
||||
|Callback |Description |
|
||||
|-----------------------------------------------------|----------------------------------------------------------------------------------------|
|
||||
| `layer_state_set_kb(layer_state_t state)` | Callback for layer functions, for keyboard. |
|
||||
| `layer_state_set_user(layer_state_t state)` | Callback for layer functions, for users. |
|
||||
@@ -86,9 +85,9 @@ In additional to the functions that you can call, there are a number of callback
|
||||
|
||||
?> For additional details on how you can use these callbacks, check out the [Layer Change Code](custom_quantum_functions.md#layer-change-code) document.
|
||||
|
||||
|Check functions |Description |
|
||||
|-------------------------------------------|------------------------------------------------------------------------------|
|
||||
| `layer_state_cmp(cmp_layer_state, layer)` | This checks the `cmp_layer_state` to see if the specific `layer` is enabled. This is meant for use with the layer callbacks. |
|
||||
| `layer_state_is(layer)` | This checks the layer state to see if the specific `layer` is enabled. (calls `layer_state_cmp` for the global layer state). |
|
||||
It is also possible to check the state of a particular layer using the following functions and macros.
|
||||
|
||||
!> There is `IS_LAYER_ON(layer)` as well, however the `layer_state_cmp` function has some additional handling to ensure that on layer 0 that it returns the correct value. Otherwise, if you check to see if layer 0 is on, you may get an incorrect value returned.
|
||||
|Function |Description |Aliases
|
||||
|---------------------------------|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
|
||||
| `layer_state_is(layer)` | Checks if the specified `layer` is enabled globally. | `IS_LAYER_ON(layer)`, `IS_LAYER_OFF(layer)` |
|
||||
| `layer_state_cmp(state, layer)` | Checks `state` to see if the specified `layer` is enabled. Intended for use in layer callbacks. | `IS_LAYER_ON_STATE(state, layer)`, `IS_LAYER_OFF_STATE(state, layer)` |
|
||||
|
@@ -5,7 +5,7 @@ If you've ever used Vim, you know what a Leader key is. If not, you're about to
|
||||
That's what `KC_LEAD` does. Here's an example:
|
||||
|
||||
1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `KC_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else.
|
||||
2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `KC_LEAD` key. Specifically, when you press the `KC_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low. .
|
||||
2. Include the line `#define LEADER_TIMEOUT 300` in your `config.h`. This sets the timeout for the `KC_LEAD` key. Specifically, when you press the `KC_LEAD` key, you only have a certain amount of time to complete the Leader Key sequence. The `300` here sets that to 300ms, and you can increase this value to give you more time to hit the sequence. But any keys pressed during this timeout are intercepted and not sent, so you may want to keep this value low.
|
||||
* By default, this timeout is how long after pressing `KC_LEAD` to complete your entire sequence. This may be very low for some people. So you may want to increase this timeout. Optionally, you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. This allows you to maintain a low value here, but still be able to use the longer sequences. To enable this option, add `#define LEADER_PER_KEY_TIMING` to your `config.h`.
|
||||
3. Within your `matrix_scan_user` function, add something like this:
|
||||
|
||||
|
116
docs/feature_led_indicators.md
Normal file
116
docs/feature_led_indicators.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# LED Indicators
|
||||
|
||||
QMK provides methods to read 5 of the LEDs defined in the HID spec:
|
||||
|
||||
* Num Lock
|
||||
* Caps Lock
|
||||
* Scroll Lock
|
||||
* Compose
|
||||
* Kana
|
||||
|
||||
There are three ways to get the lock LED state:
|
||||
* by specifying configuration options within `config.h`
|
||||
* by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or
|
||||
* by calling `led_t host_keyboard_led_state()`
|
||||
|
||||
!> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called.
|
||||
|
||||
Two more deprecated functions exist that provide the LED state as a `uint8_t`:
|
||||
|
||||
* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
|
||||
* `uint8_t host_keyboard_leds()`
|
||||
|
||||
## Configuration Options
|
||||
|
||||
To configure the indicators, `#define` these in your `config.h`:
|
||||
|
||||
|Define |Default |Description |
|
||||
|---------------------|-------------|-------------------------------------------|
|
||||
|`LED_NUM_LOCK_PIN` |*Not defined*|The pin that controls the `Num Lock` LED |
|
||||
|`LED_CAPS_LOCK_PIN` |*Not defined*|The pin that controls the `Caps Lock` LED |
|
||||
|`LED_SCROLL_LOCK_PIN`|*Not defined*|The pin that controls the `Scroll Lock` LED|
|
||||
|`LED_COMPOSE_PIN` |*Not defined*|The pin that controls the `Compose` LED |
|
||||
|`LED_KANA_PIN` |*Not defined*|The pin that controls the `Kana` LED |
|
||||
|`LED_PIN_ON_STATE` |`1` |The state of the indicator pins when the LED is "on" - `1` for high, `0` for low|
|
||||
|
||||
Unless you are designing your own keyboard, you generally should not need to change the above config options.
|
||||
|
||||
## `led_update_*()`
|
||||
|
||||
When the configuration options do not provide enough flexibility, the API hooks provided allow custom control of the LED behavior. These functions will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
|
||||
|
||||
By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
|
||||
return `false` when you would prefer not to run the code in `led_update_kb()`.
|
||||
|
||||
Some examples include:
|
||||
|
||||
- overriding the LEDs to use them for something else like layer indication
|
||||
- return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
|
||||
- play a sound when an LED turns on or off.
|
||||
- return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
|
||||
|
||||
?> Because the `led_set_*` functions return `void` instead of `bool`, they do not allow for overriding the keyboard LED control, and thus it's recommended to use `led_update_*` instead.
|
||||
|
||||
### Example `led_update_kb()` Implementation
|
||||
|
||||
```c
|
||||
bool led_update_kb(led_t led_state) {
|
||||
bool res = led_update_user(led_state);
|
||||
if(res) {
|
||||
// writePin sets the pin high for 1 and low for 0.
|
||||
// In this example the pins are inverted, setting
|
||||
// it low/0 turns it on, and high/1 turns the LED off.
|
||||
// This behavior depends on whether the LED is between the pin
|
||||
// and VCC or the pin and GND.
|
||||
writePin(B0, !led_state.num_lock);
|
||||
writePin(B1, !led_state.caps_lock);
|
||||
writePin(B2, !led_state.scroll_lock);
|
||||
writePin(B3, !led_state.compose);
|
||||
writePin(B4, !led_state.kana);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
### Example `led_update_user()` Implementation
|
||||
|
||||
This incomplete example would play a sound if Caps Lock is turned on or off. It returns `true`, because you also want the LEDs to maintain their state.
|
||||
|
||||
```c
|
||||
#ifdef AUDIO_ENABLE
|
||||
float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
|
||||
float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
|
||||
#endif
|
||||
|
||||
bool led_update_user(led_t led_state) {
|
||||
#ifdef AUDIO_ENABLE
|
||||
static uint8_t caps_state = 0;
|
||||
if (caps_state != led_state.caps_lock) {
|
||||
led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
|
||||
caps_state = led_state.caps_lock;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### `led_update_*` Function Documentation
|
||||
|
||||
* Keyboard/Revision: `bool led_update_kb(led_t led_state)`
|
||||
* Keymap: `bool led_update_user(led_t led_state)`
|
||||
|
||||
## `host_keyboard_led_state()`
|
||||
|
||||
Call this function to get the last received LED state as a `led_t`. This is useful for reading the LED state outside `led_update_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
|
||||
|
||||
## Setting Physical LED State
|
||||
|
||||
Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
|
||||
|
||||
### Ergodox Boards
|
||||
|
||||
The Ergodox implementations provide `ergodox_right_led_1`/`2`/`3_on`/`off()` to turn individual LEDs on or off, as well as `ergodox_right_led_on`/`off(uint8_t led)` to turn them on or off by their index.
|
||||
|
||||
In addition, it is possible to specify the brightness level of all LEDs with `ergodox_led_all_set(uint8_t n)`; of individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`; or by index with `ergodox_right_led_set(uint8_t led, uint8_t n)`.
|
||||
|
||||
Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default).
|
@@ -10,7 +10,8 @@ If you want to use RGB LED's you should use the [RGB Matrix Subsystem](feature_r
|
||||
|
||||
There is basic support for addressable LED matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
|
||||
|
||||
LED_MATRIX_ENABLE = IS31FL3731
|
||||
LED_MATRIX_ENABLE = yes
|
||||
LED_MATRIX_DRIVER = IS31FL3731
|
||||
|
||||
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
|
||||
|
||||
|
@@ -6,34 +6,34 @@ Macros allow you to send multiple keystrokes when pressing just one key. QMK has
|
||||
|
||||
## The New Way: `SEND_STRING()` & `process_record_user`
|
||||
|
||||
Sometimes you just want a key to type out words or phrases. For the most common situations we've provided `SEND_STRING()`, which will type out your string (i.e. a sequence of characters) for you. All ASCII characters that are easily translated to a keycode are supported (e.g. `\n\t`).
|
||||
Sometimes you want a key to type out words or phrases. For the most common situations, we've provided `SEND_STRING()`, which will type out a string (i.e. a sequence of characters) for you. All ASCII characters that are easily translatable to a keycode are supported (e.g. `qmk 123\n\t`).
|
||||
|
||||
Here is an example `keymap.c` for a two-key keyboard:
|
||||
|
||||
```c
|
||||
enum custom_keycodes {
|
||||
QMKBEST = SAFE_RANGE,
|
||||
QMKBEST = SAFE_RANGE,
|
||||
};
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
switch (keycode) {
|
||||
case QMKBEST:
|
||||
if (record->event.pressed) {
|
||||
// when keycode QMKBEST is pressed
|
||||
SEND_STRING("QMK is the best thing ever!");
|
||||
} else {
|
||||
// when keycode QMKBEST is released
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
if (record->event.pressed) {
|
||||
// when keycode QMKBEST is pressed
|
||||
SEND_STRING("QMK is the best thing ever!");
|
||||
} else {
|
||||
// when keycode QMKBEST is released
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = {
|
||||
{QMKBEST, KC_ESC}
|
||||
}
|
||||
[0] = {
|
||||
{QMKBEST, KC_ESC},
|
||||
// ...
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -49,42 +49,45 @@ You can do that by adding another keycode and adding another case to the switch
|
||||
|
||||
```c
|
||||
enum custom_keycodes {
|
||||
QMKBEST = SAFE_RANGE,
|
||||
QMKURL,
|
||||
MY_OTHER_MACRO
|
||||
QMKBEST = SAFE_RANGE,
|
||||
QMKURL,
|
||||
MY_OTHER_MACRO,
|
||||
};
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
switch (keycode) {
|
||||
case QMKBEST:
|
||||
if (record->event.pressed) {
|
||||
// when keycode QMKBEST is pressed
|
||||
SEND_STRING("QMK is the best thing ever!");
|
||||
} else {
|
||||
// when keycode QMKBEST is released
|
||||
}
|
||||
break;
|
||||
if (record->event.pressed) {
|
||||
// when keycode QMKBEST is pressed
|
||||
SEND_STRING("QMK is the best thing ever!");
|
||||
} else {
|
||||
// when keycode QMKBEST is released
|
||||
}
|
||||
break;
|
||||
|
||||
case QMKURL:
|
||||
if (record->event.pressed) {
|
||||
// when keycode QMKURL is pressed
|
||||
SEND_STRING("https://qmk.fm/\n");
|
||||
} else {
|
||||
// when keycode QMKURL is released
|
||||
}
|
||||
break;
|
||||
if (record->event.pressed) {
|
||||
// when keycode QMKURL is pressed
|
||||
SEND_STRING("https://qmk.fm/\n");
|
||||
} else {
|
||||
// when keycode QMKURL is released
|
||||
}
|
||||
break;
|
||||
|
||||
case MY_OTHER_MACRO:
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING(SS_LCTL("ac")); // selects all and copies
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
if (record->event.pressed) {
|
||||
SEND_STRING(SS_LCTL("ac")); // selects all and copies
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = {
|
||||
{MY_CUSTOM_MACRO, MY_OTHER_MACRO}
|
||||
}
|
||||
[0] = {
|
||||
{MY_CUSTOM_MACRO, MY_OTHER_MACRO},
|
||||
// ...
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -179,7 +182,9 @@ Which would send Left Control+`a` (Left Control down, `a`, Left Control up) - no
|
||||
|
||||
By default, it assumes a US keymap with a QWERTY layout; if you want to change that (e.g. if your OS uses software Colemak), include this somewhere in your keymap:
|
||||
|
||||
#include <sendstring_colemak.h>
|
||||
```c
|
||||
#include "sendstring_colemak.h"
|
||||
```
|
||||
|
||||
### Strings in Memory
|
||||
|
||||
|
@@ -39,10 +39,11 @@ In your keymap you can use the following keycodes to map key presses to mouse ac
|
||||
|
||||
## Configuring mouse keys
|
||||
|
||||
Mouse keys supports two different modes to move the cursor:
|
||||
Mouse keys supports three different modes to move the cursor:
|
||||
|
||||
* **Accelerated (default):** Holding movement keys accelerates the cursor until it reaches its maximum speed.
|
||||
* **Constant:** Holding movement keys moves the cursor at constant speeds.
|
||||
* **Combined:** Holding movement keys accelerates the cursor until it reaches its maximum speed, but holding acceleration and movement keys simultaneously moves the cursor at constant speeds.
|
||||
|
||||
The same principle applies to scrolling.
|
||||
|
||||
@@ -120,3 +121,26 @@ Use the following settings if you want to adjust cursor movement or scrolling:
|
||||
|`MK_W_INTERVAL_1` |120 |Time between scroll steps (`KC_ACL1`) |
|
||||
|`MK_W_OFFSET_2` |1 |Scroll steps per scroll action (`KC_ACL2`) |
|
||||
|`MK_W_INTERVAL_2` |20 |Time between scroll steps (`KC_ACL2`) |
|
||||
|
||||
### Combined mode
|
||||
|
||||
This mode functions like **Accelerated** mode, however, you can hold `KC_ACL0`, `KC_ACL1` and `KC_ACL2`
|
||||
to momentarily (while held) set the cursor and scroll speeds to constant speeds. When no acceleration
|
||||
keys are held, this mode is identical to **Accelerated** mode, and can be modified using all of the
|
||||
relevant settings.
|
||||
|
||||
* **KC_ACL0:** This acceleration sets your cursor to the slowest possible speed. This is useful for very
|
||||
small and detailed movements of the cursor.
|
||||
* **KC_ACL1:** This acceleration sets your cursor to half the maximum (user defined) speed.
|
||||
* **KC_ACL2:** This acceleration sets your cursor to the maximum (computer defined) speed. This is
|
||||
useful for moving the cursor large distances without much accuracy.
|
||||
|
||||
To use constant speed mode, you must at least define `MK_COMBINED` in your keymap’s `config.h` file:
|
||||
|
||||
```c
|
||||
#define MK_COMBINED
|
||||
```
|
||||
|
||||
## Use with PS/2 Mouse and Pointing Device
|
||||
|
||||
Mouse keys button state is shared with [PS/2 mouse](feature_ps2_mouse.md) and [pointing device](feature_pointing_device.md) so mouse keys button presses can be used for clicks and drags.
|
||||
|
@@ -72,6 +72,43 @@ static void render_logo(void) {
|
||||
}
|
||||
```
|
||||
|
||||
## Buffer Read Example
|
||||
For some purposes, you may need to read the current state of the OLED display
|
||||
buffer. The `oled_read_raw` function can be used to safely read bytes from the
|
||||
buffer.
|
||||
|
||||
In this example, calling `fade_display` in the `oled_task_user` function will
|
||||
slowly fade away whatever is on the screen by turning random pixels black over
|
||||
time.
|
||||
```c
|
||||
//Setup some mask which can be or'd with bytes to turn off pixels
|
||||
const uint8_t single_bit_masks[8] = {127, 191, 223, 239, 247, 251, 253, 254};
|
||||
|
||||
static void fade_display(void) {
|
||||
//Define the reader structure
|
||||
oled_buffer_reader_t reader;
|
||||
uint8_t buff_char;
|
||||
if (random() % 30 == 0) {
|
||||
srand(timer_read());
|
||||
// Fetch a pointer for the buffer byte at index 0. The return structure
|
||||
// will have the pointer and the number of bytes remaining from this
|
||||
// index position if we want to perform a sequential read by
|
||||
// incrementing the buffer pointer
|
||||
reader = oled_read_raw(0);
|
||||
//Loop over the remaining buffer and erase pixels as we go
|
||||
for (uint16_t i = 0; i < reader.remaining_element_count; i++) {
|
||||
//Get the actual byte in the buffer by dereferencing the pointer
|
||||
buff_char = *reader.current_element;
|
||||
if (buff_char != 0) {
|
||||
oled_write_raw_byte(buff_char & single_bit_masks[rand() % 8], i);
|
||||
}
|
||||
//increment the pointer to fetch a new byte during the next loop
|
||||
reader.current_element++;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Other Examples
|
||||
|
||||
In split keyboards, it is very common to have two OLED displays that each render different content and are oriented or flipped differently. You can do this by switching which content to render by using the return value from `is_keyboard_master()` or `is_keyboard_left()` found in `split_util.h`, e.g:
|
||||
@@ -103,8 +140,8 @@ void oled_task_user(void) {
|
||||
|---------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||
|`OLED_DISPLAY_ADDRESS` |`0x3C` |The i2c address of the OLED Display |
|
||||
|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts |
|
||||
|`OLED_FONT_START` |`0` |The starting characer index for custom fonts |
|
||||
|`OLED_FONT_END` |`223` |The ending characer index for custom fonts |
|
||||
|`OLED_FONT_START` |`0` |The starting character index for custom fonts |
|
||||
|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
|
||||
|`OLED_FONT_WIDTH` |`6` |The font width |
|
||||
|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
|
||||
|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of keyboard inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|
||||
@@ -112,6 +149,8 @@ void oled_task_user(void) {
|
||||
|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
|
||||
|`OLED_IC` |`OLED_IC_SSD1306`|Set to `OLED_IC_SH1106` if you're using the SH1106 OLED controller. |
|
||||
|`OLED_COLUMN_OFFSET` |`0` |(SH1106 only.) Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC.|
|
||||
|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
|
||||
|`OLED_UPDATE_INTERVAL` |`0` |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
|
||||
|
||||
## 128x64 & Custom sized OLED Displays
|
||||
|
||||
@@ -238,6 +277,10 @@ void oled_write_P(const char *data, bool invert);
|
||||
// Remapped to call 'void oled_write_ln(const char *data, bool invert);' on ARM
|
||||
void oled_write_ln_P(const char *data, bool invert);
|
||||
|
||||
// Returns a pointer to the requested start index in the buffer plus remaining
|
||||
// buffer length as struct
|
||||
oled_buffer_reader_t oled_read_raw(uint16_t start_index);
|
||||
|
||||
// Writes a string to the buffer at current cursor position
|
||||
void oled_write_raw(const char *data, uint16_t size);
|
||||
|
||||
@@ -247,6 +290,10 @@ void oled_write_raw_byte(const char data, uint16_t index);
|
||||
// Writes a PROGMEM string to the buffer at current cursor position
|
||||
void oled_write_raw_P(const char *data, uint16_t size);
|
||||
|
||||
// Sets a specific pixel on or off
|
||||
// Coordinates start at top-left and go right and down for positive x and y
|
||||
void oled_write_pixel(uint8_t x, uint8_t y, bool on);
|
||||
|
||||
// Can be used to manually turn on the screen if it is off
|
||||
// Returns true if the screen was on or turns on
|
||||
bool oled_on(void);
|
||||
@@ -255,6 +302,16 @@ bool oled_on(void);
|
||||
// Returns true if the screen was off or turns off
|
||||
bool oled_off(void);
|
||||
|
||||
// Returns true if the oled is currently on, false if it is
|
||||
// not
|
||||
bool is_oled_on(void);
|
||||
|
||||
// Sets the brightness level of the display
|
||||
uint8_t oled_set_brightness(uint8_t level);
|
||||
|
||||
// Gets the current brightness level of the display
|
||||
uint8_t oled_get_brightness(void);
|
||||
|
||||
// Basically it's oled_render, but with timeout management and oled_task_user calling!
|
||||
void oled_task(void);
|
||||
|
||||
|
@@ -21,7 +21,11 @@ Keep in mind that a report_mouse_t (here "mouseReport") has the following proper
|
||||
* `mouseReport.h` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing horizontal scrolling (+ right, - left).
|
||||
* `mouseReport.buttons` - this is a uint8_t in which the last 5 bits are used. These bits represent the mouse button state - bit 3 is mouse button 5, and bit 7 is mouse button 1.
|
||||
|
||||
When the mouse report is sent, the x, y, v, and h values are set to 0 (this is done in "pointing_device_send()", which can be overridden to avoid this behavior). This way, button states persist, but movement will only occur once. For further customization, both `pointing_device_init` and `pointing_device_task` can be overridden.
|
||||
Once you have made the necessary changes to the mouse report, you need to send it:
|
||||
|
||||
* `pointing_device_send()` - Sends the mouse report to the host and zeroes out the report.
|
||||
|
||||
When the mouse report is sent, the x, y, v, and h values are set to 0 (this is done in `pointing_device_send()`, which can be overridden to avoid this behavior). This way, button states persist, but movement will only occur once. For further customization, both `pointing_device_init` and `pointing_device_task` can be overridden.
|
||||
|
||||
In the following example, a custom key is used to click the mouse and scroll 127 units vertically and horizontally, then undo all of that when released - because that's a totally useful function. Listen, this is an example:
|
||||
|
||||
@@ -38,6 +42,7 @@ case MS_SPECIAL:
|
||||
currentReport.buttons &= ~MOUSE_BTN1;
|
||||
}
|
||||
pointing_device_set_report(currentReport);
|
||||
pointing_device_send();
|
||||
break;
|
||||
```
|
||||
|
||||
|
@@ -294,3 +294,13 @@ To debug the mouse, add `debug_mouse = true` or enable via bootmagic.
|
||||
#define PS2_MOUSE_DEBUG_HID
|
||||
#define PS2_MOUSE_DEBUG_RAW
|
||||
```
|
||||
|
||||
### Movement Hook :id=movement-hook
|
||||
|
||||
Process mouse movement in the keymap before it is sent to the host. Example
|
||||
uses include filtering noise, adding acceleration, and automatically activating
|
||||
a layer. To use, define the following function in your keymap:
|
||||
|
||||
```c
|
||||
void ps2_mouse_moved_user(report_mouse_t *mouse_report);
|
||||
```
|
||||
|
@@ -11,7 +11,8 @@ If you want to use single color LED's you should use the [LED Matrix Subsystem](
|
||||
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
|
||||
|
||||
```makefile
|
||||
RGB_MATRIX_ENABLE = IS31FL3731
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = IS31FL3731
|
||||
```
|
||||
|
||||
Configure the hardware via your `config.h`:
|
||||
@@ -62,7 +63,8 @@ Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet]
|
||||
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`:
|
||||
|
||||
```makefile
|
||||
RGB_MATRIX_ENABLE = IS31FL3733
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = IS31FL3733
|
||||
```
|
||||
|
||||
Configure the hardware via your `config.h`:
|
||||
@@ -112,7 +114,8 @@ Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](
|
||||
There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{a,b,c} addressable LED strand. To enable it, add this to your `rules.mk`:
|
||||
|
||||
```makefile
|
||||
RGB_MATRIX_ENABLE = WS2812
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
RGB_MATRIX_DRIVER = WS2812
|
||||
```
|
||||
|
||||
Configure the hardware via your `config.h`:
|
||||
@@ -129,7 +132,7 @@ Configure the hardware via your `config.h`:
|
||||
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:
|
||||
|
||||
```c
|
||||
const led_config_t g_led_config = { {
|
||||
led_config_t g_led_config = { {
|
||||
// Key Matrix to LED Index
|
||||
{ 5, NO_LED, NO_LED, 0 },
|
||||
{ NO_LED, NO_LED, NO_LED, NO_LED },
|
||||
@@ -159,15 +162,16 @@ As mentioned earlier, the center of the keyboard by default is expected to be `{
|
||||
|
||||
## Flags :id=flags
|
||||
|
||||
|Define |Description |
|
||||
|------------------------------------|-------------------------------------------|
|
||||
|`#define HAS_FLAGS(bits, flags)` |Returns true if `bits` has all `flags` set.|
|
||||
|`#define HAS_ANY_FLAGS(bits, flags)`|Returns true if `bits` has any `flags` set.|
|
||||
|`#define LED_FLAG_NONE 0x00` |If this LED has no flags. |
|
||||
|`#define LED_FLAG_ALL 0xFF` |If this LED has all flags. |
|
||||
|`#define LED_FLAG_MODIFIER 0x01` |If the Key for this LED is a modifier. |
|
||||
|`#define LED_FLAG_UNDERGLOW 0x02` |If the LED is for underglow. |
|
||||
|`#define LED_FLAG_KEYLIGHT 0x04` |If the LED is for key backlight. |
|
||||
|Define |Value |Description |
|
||||
|----------------------------|------|-------------------------------------------------|
|
||||
|`HAS_FLAGS(bits, flags)` |*n/a* |Evaluates to `true` if `bits` has all `flags` set|
|
||||
|`HAS_ANY_FLAGS(bits, flags)`|*n/a* |Evaluates to `true` if `bits` has any `flags` set|
|
||||
|`LED_FLAG_NONE` |`0x00`|If this LED has no flags |
|
||||
|`LED_FLAG_ALL` |`0xFF`|If this LED has all flags |
|
||||
|`LED_FLAG_MODIFIER` |`0x01`|If the LED is on a modifier key |
|
||||
|`LED_FLAG_UNDERGLOW` |`0x02`|If the LED is for underglow |
|
||||
|`LED_FLAG_KEYLIGHT` |`0x04`|If the LED is for key backlight |
|
||||
|`LED_FLAG_INDICATOR` |`0x08`|If the LED is for keyboard state indication |
|
||||
|
||||
## Keycodes :id=keycodes
|
||||
|
||||
@@ -186,8 +190,16 @@ All RGB keycodes are currently shared with the RGBLIGHT system:
|
||||
|`RGB_VAD` | |Decrease value (brightness), increase value when Shift is held |
|
||||
|`RGB_SPI` | |Increase effect speed (does not support eeprom yet), decrease speed when Shift is held|
|
||||
|`RGB_SPD` | |Decrease effect speed (does not support eeprom yet), increase speed when Shift is held|
|
||||
|`RGB_MODE_PLAIN` |`RGB_M_P `|Static (no animation) mode |
|
||||
|`RGB_MODE_BREATHE` |`RGB_M_B` |Breathing animation mode |
|
||||
|`RGB_MODE_RAINBOW` |`RGB_M_R` |Full gradient scrolling left to right (uses the `RGB_MATRIX_CYCLE_LEFT_RIGHT` mode) |
|
||||
|`RGB_MODE_SWIRL` |`RGB_M_SW`|Full gradient spinning pinwheel around center of keyboard (uses `RGB_MATRIX_CYCLE_PINWHEEL` mode) |
|
||||
|
||||
* `RGB_MODE_*` keycodes will generally work, but are not currently mapped to the correct effects for the RGB Matrix system
|
||||
* `RGB_MODE_*` keycodes will generally work, but not all of the modes are currently mapped to the correct effects for the RGB Matrix system.
|
||||
|
||||
`RGB_MODE_PLAIN`, `RGB_MODE_BREATHE`, `RGB_MODE_RAINBOW`, and `RGB_MATRIX_SWIRL` are the only ones that are mapped properly. The rest don't have a direct equivalent, and are not mapped.
|
||||
|
||||
!> By default, if you have both the [RGB Light](feature_rgblight.md) and the RGB Matrix feature enabled, these keycodes will work for both features, at the same time. You can disable the keycode functionality by defining the `*_DISABLE_KEYCODES` option for the specific feature.
|
||||
|
||||
## RGB Matrix Effects :id=rgb-matrix-effects
|
||||
|
||||
@@ -374,7 +386,8 @@ These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blo
|
||||
```c
|
||||
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
|
||||
#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
|
||||
#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
|
||||
#define RGB_DISABLE_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off
|
||||
#define RGB_DISABLE_AFTER_TIMEOUT 0 // OBSOLETE: number of ticks to wait until disabling effects
|
||||
#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended
|
||||
#define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
|
||||
#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
|
||||
@@ -384,6 +397,7 @@ These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blo
|
||||
#define RGB_MATRIX_STARTUP_SAT 255 // Sets the default saturation value, if none has been set
|
||||
#define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set
|
||||
#define RGB_MATRIX_STARTUP_SPD 127 // Sets the default animation speed, if none has been set
|
||||
#define RGB_MATRIX_DISABLE_KEYCODES // disables control of rgb matrix by keycodes (must use code functions to control the feature)
|
||||
```
|
||||
|
||||
## EEPROM storage :id=eeprom-storage
|
||||
@@ -411,8 +425,8 @@ Where `28` is an unused index from `eeconfig.h`.
|
||||
|`rgb_matrix_toggle_noeeprom()` |Toggle effect range LEDs between on and off (not written to EEPROM) |
|
||||
|`rgb_matrix_enable()` |Turn effect range LEDs on, based on their previous state |
|
||||
|`rgb_matrix_enable_noeeprom()` |Turn effect range LEDs on, based on their previous state (not written to EEPROM) |
|
||||
|`rgb_matrix_disable()` |Turn effect range LEDs off |
|
||||
|`rgb_matrix_disable_noeeprom()` |Turn effect range LEDs off (not written to EEPROM) |
|
||||
|`rgb_matrix_disable()` |Turn effect range LEDs off, based on their previous state |
|
||||
|`rgb_matrix_disable_noeeprom()` |Turn effect range LEDs off, based on their previous state (not written to EEPROM) |
|
||||
|
||||
### Change Effect Mode :id=change-effect-mode
|
||||
|Function |Description |
|
||||
@@ -420,19 +434,31 @@ Where `28` is an unused index from `eeconfig.h`.
|
||||
|`rgb_matrix_mode(mode)` |Set the mode, if RGB animations are enabled |
|
||||
|`rgb_matrix_mode_noeeprom(mode)` |Set the mode, if RGB animations are enabled (not written to EEPROM) |
|
||||
|`rgb_matrix_step()` |Change the mode to the next RGB animation in the list of enabled RGB animations |
|
||||
|`rgb_matrix_step_noeeprom()` |Change the mode to the next RGB animation in the list of enabled RGB animations (not written to EEPROM) |
|
||||
|`rgb_matrix_step_reverse()` |Change the mode to the previous RGB animation in the list of enabled RGB animations |
|
||||
|`rgb_matrix_increase_speed()` |Increases the speed of the animations |
|
||||
|`rgb_matrix_decrease_speed()` |Decreases the speed of the animations |
|
||||
|`rgb_matrix_step_reverse_noeeprom()` |Change the mode to the previous RGB animation in the list of enabled RGB animations (not written to EEPROM) |
|
||||
|`rgb_matrix_increase_speed()` |Increase the speed of the animations |
|
||||
|`rgb_matrix_increase_speed_noeeprom()` |Increase the speed of the animations (not written to EEPROM) |
|
||||
|`rgb_matrix_decrease_speed()` |Decrease the speed of the animations |
|
||||
|`rgb_matrix_decrease_speed_noeeprom()` |Decrease the speed of the animations (not written to EEPROM) |
|
||||
|`rgb_matrix_set_speed(speed)` |Set the speed of the animations to the given value where `speed` is between 0 and 255 |
|
||||
|`rgb_matrix_set_speed_noeeprom(speed)` |Set the speed of the animations to the given value where `speed` is between 0 and 255 (not written to EEPROM) |
|
||||
|
||||
### Change Color :id=change-color
|
||||
|Function |Description |
|
||||
|--------------------------------------------|-------------|
|
||||
|`rgb_matrix_increase_hue()` |Increase the hue for effect range LEDs. This wraps around at maximum hue |
|
||||
|`rgb_matrix_increase_hue_noeeprom()` |Increase the hue for effect range LEDs. This wraps around at maximum hue (not written to EEPROM) |
|
||||
|`rgb_matrix_decrease_hue()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue |
|
||||
|`rgb_matrix_decrease_hue_noeeprom()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue (not written to EEPROM) |
|
||||
|`rgb_matrix_increase_sat()` |Increase the saturation for effect range LEDs. This wraps around at maximum saturation |
|
||||
|`rgb_matrix_increase_sat_noeeprom()` |Increase the saturation for effect range LEDs. This wraps around at maximum saturation (not written to EEPROM) |
|
||||
|`rgb_matrix_decrease_sat()` |Decrease the saturation for effect range LEDs. This wraps around at minimum saturation |
|
||||
|`rgb_matrix_decrease_sat_noeeprom()` |Decrease the saturation for effect range LEDs. This wraps around at minimum saturation (not written to EEPROM) |
|
||||
|`rgb_matrix_increase_val()` |Increase the value for effect range LEDs. This wraps around at maximum value |
|
||||
|`rgb_matrix_increase_val_noeeprom()` |Increase the value for effect range LEDs. This wraps around at maximum value (not written to EEPROM) |
|
||||
|`rgb_matrix_decrease_val()` |Decrease the value for effect range LEDs. This wraps around at minimum value |
|
||||
|`rgb_matrix_decrease_val_noeeprom()` |Decrease the value for effect range LEDs. This wraps around at minimum value (not written to EEPROM) |
|
||||
|`rgb_matrix_sethsv(h, s, v)` |Set LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 |
|
||||
|`rgb_matrix_sethsv_noeeprom(h, s, v)` |Set LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|
||||
|
||||
@@ -459,6 +485,14 @@ void rgb_matrix_indicators_kb(void) {
|
||||
}
|
||||
```
|
||||
|
||||
In addition, there are the advanced indicator functions. These are aimed at those with heavily customized displays, where rendering every LED per cycle is expensive. Such as some of the "drashna" layouts. This includes a special macro to help make this easier to use: `RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b)`.
|
||||
|
||||
```c
|
||||
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
|
||||
RGB_MATRIX_INDICATOR_SET_COLOR(index, red, green, blue);
|
||||
}
|
||||
```
|
||||
|
||||
### Suspended state :id=suspended-state
|
||||
To use the suspend feature, make sure that `#define RGB_DISABLE_WHEN_USB_SUSPENDED true` is added to the `config.h` file.
|
||||
|
||||
|
@@ -41,6 +41,8 @@ Changing the **Hue** cycles around the circle.<br>
|
||||
Changing the **Saturation** moves between the inner and outer sections of the wheel, affecting the intensity of the color.<br>
|
||||
Changing the **Value** sets the overall brightness.<br>
|
||||
|
||||

|
||||
|
||||
## Keycodes
|
||||
|
||||
|Key |Aliases |Description |
|
||||
@@ -64,6 +66,9 @@ Changing the **Value** sets the overall brightness.<br>
|
||||
|`RGB_MODE_GRADIENT`|`RGB_M_G` |Static gradient animation mode |
|
||||
|`RGB_MODE_RGBTEST` |`RGB_M_T` |Red, Green, Blue test animation mode |
|
||||
|
||||
!> By default, if you have both the RGB Light and the [RGB Matrix](feature_rgb_matrix.md) feature enabled, these keycodes will work for both features, at the same time. You can disable the keycode functionality by defining the `*_DISABLE_KEYCODES` option for the specific feature.
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
Your RGB lighting can be configured by placing these `#define`s in your `config.h`:
|
||||
@@ -76,6 +81,7 @@ Your RGB lighting can be configured by placing these `#define`s in your `config.
|
||||
|`RGBLIGHT_LIMIT_VAL` |`255` |The maximum brightness level |
|
||||
|`RGBLIGHT_SLEEP` |*Not defined*|If defined, the RGB lighting will be switched off when the host goes to sleep|
|
||||
|`RGBLIGHT_SPLIT` |*Not defined*|If defined, synchronization functionality for split keyboards is added|
|
||||
|`RGBLIGHT_DISABLE_KEYCODES`|*not defined*|If defined, disables the ability to control RGB Light from the keycodes. You must use code functions to control the feature|
|
||||
|
||||
## Effects and Animations
|
||||
|
||||
@@ -122,19 +128,19 @@ Use these defines to add or remove animations from the firmware. When you are ru
|
||||
|
||||
The following options are used to tweak the various animations:
|
||||
|
||||
|Define |Default |Description |
|
||||
|------------------------------------|-------------|-------------------------------------------------------------------------------------|
|
||||
|Define |Default |Description |
|
||||
|------------------------------------|-------------|-----------------------------------------------------------------------------------------------|
|
||||
|`RGBLIGHT_EFFECT_BREATHE_CENTER` |*Not defined*|If defined, used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7 |
|
||||
|`RGBLIGHT_EFFECT_BREATHE_MAX` |`255` |The maximum brightness for the breathing mode. Valid values are 1 to 255 |
|
||||
|`RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL`|`1000` |How long to wait between light changes for the "Christmas" animation, in milliseconds|
|
||||
|`RGBLIGHT_EFFECT_CHRISTMAS_STEP` |`2` |The number of LEDs to group the red/green colors by for the "Christmas" animation |
|
||||
|`RGBLIGHT_EFFECT_KNIGHT_LED_NUM` |`RGBLED_NUM` |The number of LEDs to have the "Knight" animation travel |
|
||||
|`RGBLIGHT_EFFECT_KNIGHT_LENGTH` |`3` |The number of LEDs to light up for the "Knight" animation |
|
||||
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|
||||
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
|
||||
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|
||||
|`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`75` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) |
|
||||
|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
|
||||
|`RGBLIGHT_EFFECT_BREATHE_MAX` |`255` |The maximum brightness for the breathing mode. Valid values are 1 to 255 |
|
||||
|`RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL`|`40` |How long (in milliseconds) to wait between animation steps for the "Christmas" animation |
|
||||
|`RGBLIGHT_EFFECT_CHRISTMAS_STEP` |`2` |The number of LEDs to group the red/green colors by for the "Christmas" animation |
|
||||
|`RGBLIGHT_EFFECT_KNIGHT_LED_NUM` |`RGBLED_NUM` |The number of LEDs to have the "Knight" animation travel |
|
||||
|`RGBLIGHT_EFFECT_KNIGHT_LENGTH` |`3` |The number of LEDs to light up for the "Knight" animation |
|
||||
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|
||||
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
|
||||
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|
||||
|`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`75` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) |
|
||||
|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
|
||||
|
||||
### Example Usage to Reduce Memory Footprint
|
||||
1. Remove `RGBLIGHT_ANIMATIONS` from `config.h`.
|
||||
@@ -278,6 +284,10 @@ void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
}
|
||||
```
|
||||
|
||||
### Overriding RGB Lighting on/off status
|
||||
|
||||
Normally lighting layers are not shown when RGB Lighting is disabled (e.g. with `RGB_TOG` keycode). If you would like lighting layers to work even when the RGB Lighting is otherwise off, add `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF` to your `config.h`.
|
||||
|
||||
## Functions
|
||||
|
||||
If you need to change your RGB lighting in code, for example in a macro to change the color whenever you switch layers, QMK provides a set of functions to assist you. See [`rgblight.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight.h) for the full list, but the most commonly used functions include:
|
||||
@@ -369,6 +379,17 @@ rgblight_sethsv(HSV_GREEN, 2); // led 2
|
||||
|`rgblight_sethsv(h, s, v)` |Set effect range LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 |
|
||||
|`rgblight_sethsv_noeeprom(h, s, v)` |Set effect range LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|
||||
|
||||
#### Speed functions
|
||||
|Function |Description |
|
||||
|--------------------------------------------|-------------|
|
||||
|`rgblight_increase_speed()` |Increases the animation speed |
|
||||
|`rgblight_increase_speed_noeeprom()` |Increases the animation speed (not written to EEPROM) |
|
||||
|`rgblight_decrease_speed()` |Decreases the animation speed |
|
||||
|`rgblight_decrease_speed_noeeprom()` |Decreases the animation speed (not written to EEPROM) |
|
||||
|`rgblight_set_speed()` |Sets the speed. Value is between 0 and 255 |
|
||||
|`rgblight_set_speed_noeeprom()` |Sets the speed. Value is between 0 and 255 (not written to EEPROM) |
|
||||
|
||||
|
||||
#### layer functions
|
||||
|Function |Description |
|
||||
|--------------------------------------------|-------------|
|
||||
|
88
docs/feature_sequencer.md
Normal file
88
docs/feature_sequencer.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Sequencer
|
||||
|
||||
Since QMK has experimental support for MIDI, you can now turn your keyboard into a [step sequencer](https://en.wikipedia.org/wiki/Music_sequencer#Step_sequencers)!
|
||||
|
||||
!> **IMPORTANT:** This feature is highly experimental, it has only been tested on a Planck EZ so far. Also, the scope will be limited to support the drum machine use-case to start with.
|
||||
|
||||
## Enable the step sequencer
|
||||
|
||||
Add the following line to your `rules.mk`:
|
||||
|
||||
```make
|
||||
SEQUENCER_ENABLE = yes
|
||||
```
|
||||
|
||||
By default the sequencer has 16 steps, but you can override this setting in your `config.h`:
|
||||
|
||||
```c
|
||||
#define SEQUENCER_STEPS 32
|
||||
```
|
||||
|
||||
## Tracks
|
||||
|
||||
You can program up to 8 independent tracks with the step sequencer. Select the tracks you want to edit, enable or disable some steps, and start the sequence!
|
||||
|
||||
## Resolutions
|
||||
|
||||
While the tempo defines the absolute speed at which the sequencer goes through the steps, the resolution defines the granularity of these steps (from coarser to finer).
|
||||
|
||||
|Resolution |Description |
|
||||
|---------- |----------- |
|
||||
|`SQ_RES_2` |Every other beat |
|
||||
|`SQ_RES_2T` |Every 1.5 beats |
|
||||
|`SQ_RES_4` |Every beat |
|
||||
|`SQ_RES_4T` |Three times per 2 beats|
|
||||
|`SQ_RES_8` |Twice per beat |
|
||||
|`SQ_RES_8T` |Three times per beat |
|
||||
|`SQ_RES_16` |Four times per beat |
|
||||
|`SQ_RES_16T` |Six times per beat |
|
||||
|`SQ_RES_32` |Eight times per beat |
|
||||
|
||||
## Keycodes
|
||||
|
||||
|Keycode |Description |
|
||||
|------- |----------- |
|
||||
|`SQ_ON` |Start the step sequencer |
|
||||
|`SQ_OFF` |Stop the step sequencer |
|
||||
|`SQ_TOG` |Toggle the step sequencer playback |
|
||||
|`SQ_SALL`|Enable all the steps |
|
||||
|`SQ_SCLR`|Disable all the steps |
|
||||
|`SQ_S(n)`|Toggle the step `n` |
|
||||
|`SQ_TMPD`|Decrease the tempo |
|
||||
|`SQ_TMPU`|Increase the tempo |
|
||||
|`SQ_R(n)`|Set the resolution to n |
|
||||
|`SQ_RESD`|Change to the slower resolution |
|
||||
|`SQ_RESU`|Change to the faster resolution |
|
||||
|`SQ_T(n)`|Set `n` as the only active track or deactivate all |
|
||||
|
||||
## Functions
|
||||
|
||||
|Function |Description |
|
||||
|-------- |----------- |
|
||||
|`bool is_sequencer_on(void);` |Return whether the sequencer is playing |
|
||||
|`void sequencer_toggle(void);` |Toggle the step sequencer playback |
|
||||
|`void sequencer_on(void);` |Start the step sequencer |
|
||||
|`void sequencer_off(void);` |Stop the step sequencer |
|
||||
|`bool is_sequencer_step_on(uint8_t step);` |Return whether the step is currently enabled |
|
||||
|`void sequencer_set_step(uint8_t step, bool value);` |Enable or disable the step |
|
||||
|`void sequencer_set_step_on();` |Enable the step |
|
||||
|`void sequencer_set_step_off();` |Disable the step |
|
||||
|`void sequencer_toggle_step(uint8_t step);` |Toggle the step |
|
||||
|`void sequencer_set_all_steps(bool value);` |Enable or disable all the steps |
|
||||
|`void sequencer_set_all_steps_on();` |Enable all the steps |
|
||||
|`void sequencer_set_all_steps_off();` |Disable all the steps |
|
||||
|`uint8_t sequencer_get_tempo(void);` |Return the current tempo |
|
||||
|`void sequencer_set_tempo(uint8_t tempo);` |Set the tempo to `tempo` (between 1 and 255) |
|
||||
|`void sequencer_increase_tempo(void);` |Increase the tempo |
|
||||
|`void sequencer_decrease_tempo(void);` |Decrease the tempo |
|
||||
|`sequencer_resolution_t sequencer_get_resolution(void);` |Return the current resolution |
|
||||
|`void sequencer_set_resolution(sequencer_resolution_t resolution);` |Set the resolution to `resolution` |
|
||||
|`void sequencer_increase_resolution(void);` |Change to the faster resolution |
|
||||
|`void sequencer_decrease_resolution(void);` |Change to the slower resolution |
|
||||
|`bool is_sequencer_track_active(uint8_t track);` |Return whether the track is active |
|
||||
|`void sequencer_set_track_activation(uint8_t track, bool value);` |Activate or deactivate the `track` |
|
||||
|`void sequencer_toggle_track_activation(uint8_t track);` |Toggle the `track` |
|
||||
|`void sequencer_activate_track(uint8_t track);` |Activate the `track` |
|
||||
|`void sequencer_deactivate_track(uint8_t track);` |Deactivate the `track` |
|
||||
|`void sequencer_toggle_single_active_track(uint8_t track);` |Set `track` as the only active track or deactivate all |
|
||||
|
@@ -48,11 +48,12 @@ However, USB cables, SATA cables, and even just 4 wires have been known to be us
|
||||
|
||||
### Serial Wiring
|
||||
|
||||
The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and D0 (aka PDO or pin 3) between the two Pro Micros.
|
||||
The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and D0/D1/D2/D3 (aka PD0/PD1/PD2/PD3) between the two Pro Micros.
|
||||
|
||||
?> Note that the pin used here is actually set by `SOFT_SERIAL_PIN` below.
|
||||
|
||||

|
||||
<img alt="sk-pd0-connection-mono" src="https://user-images.githubusercontent.com/2170248/92296488-28e9ad80-ef70-11ea-98be-c40cb48a0319.JPG" width="48%"/>
|
||||
<img alt="sk-pd2-connection-mono" src="https://user-images.githubusercontent.com/2170248/92296490-2d15cb00-ef70-11ea-801f-5ace313013e6.JPG" width="48%"/>
|
||||
|
||||
### I<sup>2</sup>C Wiring
|
||||
|
||||
@@ -60,7 +61,7 @@ The 4 wires of the TRRS cable need to connect GND, VCC, and SCL and SDA (aka PD0
|
||||
|
||||
The pull-up resistors may be placed on either half. If you wish to use the halves independently, it is also possible to use 4 resistors and have the pull-ups in both halves.
|
||||
|
||||

|
||||
<img alt="sk-i2c-connection-mono" src="https://user-images.githubusercontent.com/2170248/92297182-92b98580-ef77-11ea-9d7d-d6033914af43.JPG" width="50%"/>
|
||||
|
||||
## Firmware Configuration
|
||||
|
||||
@@ -90,6 +91,24 @@ You can configure the firmware to read a pin on the controller to determine hand
|
||||
|
||||
This will read the specified pin. If it's high, then the controller assumes it is the left hand, and if it's low, it's assumed to be the right side.
|
||||
|
||||
#### Handedness by Matrix Pin
|
||||
|
||||
You can configure the firmware to read key matrix pins on the controller to determine handedness. To do this, add the following to your `config.h` file:
|
||||
|
||||
```c
|
||||
#define SPLIT_HAND_MATRIX_GRID D0, F1
|
||||
```
|
||||
|
||||
The first pin is the output pin and the second is the input pin.
|
||||
|
||||
Some keyboards have unused intersections in the key matrix. This setting uses one of these unused intersections to determine the handness.
|
||||
|
||||
Normally, when a diode is connected to an intersection, it is judged to be left. If you add the following definition, it will be judged to be right.
|
||||
|
||||
```c
|
||||
#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT
|
||||
```
|
||||
|
||||
#### Handedness by EEPROM
|
||||
|
||||
This method sets the keyboard's handedness by setting a flag in the persistent storage (`EEPROM`). This is checked when the controller first starts up, and determines what half the keyboard is, and how to orient the keyboard layout.
|
||||
@@ -218,6 +237,26 @@ This sets the maximum timeout when detecting master/slave when using `SPLIT_USB_
|
||||
```
|
||||
This sets the poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
|
||||
|
||||
## Hardware Considerations and Mods
|
||||
|
||||
While most any Pro Micro can be used, micro controllers like the AVR Teensys and most (if not all) ARM boards require the Split USB Detect.
|
||||
|
||||
However, with the Teensy 2.0 and Teensy++ 2.0, there is a simple hardware mod that you can perform to add VBUS detection, so you don't need the Split USB detection option.
|
||||
|
||||
You'll only need a few things:
|
||||
|
||||
* A knife (x-acto knife, ideally)
|
||||
* A solder station or hot air station
|
||||
* An appropriate Schottky diode, such as the [PMEG2005EH](https://www.digikey.com/en/products/detail/nexperia-usa-inc/PMEG2005EH,115/1589924)
|
||||
|
||||
You'll need to cut the small trace between the 5V and center pads on the back of the Teensy.
|
||||
|
||||
Once you have done that, you will want to solder the diode from the 5V pad to the center pad.
|
||||
|
||||
You may need to use the 5V pad from the regulator block above as the pads were too small and placed too closely together to place the Schottky diode properly.
|
||||
|
||||

|
||||
|
||||
## Additional Resources
|
||||
|
||||
Nicinabox has a [very nice and detailed guide](https://github.com/nicinabox/lets-split-guide) for the Let's Split keyboard, that covers most everything you need to know, including troubleshooting information.
|
||||
|
@@ -58,7 +58,7 @@ On the display tab click 'Open stroke display'. With Plover disabled you should
|
||||
|
||||
## Interfacing with the code :id=interfacing-with-the-code
|
||||
|
||||
The steno code has three interceptible hooks. If you define these functions, they will be called at certain points in processing; if they return true, processing continues, otherwise it's assumed you handled things.
|
||||
The steno code has three interceptable hooks. If you define these functions, they will be called at certain points in processing; if they return true, processing continues, otherwise it's assumed you handled things.
|
||||
|
||||
```c
|
||||
bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]);
|
||||
|
@@ -1,31 +1,24 @@
|
||||
# Tap Dance: A Single Key Can Do 3, 5, or 100 Different Things
|
||||
|
||||
## Introduction
|
||||
## Introduction :id=introduction
|
||||
|
||||
Hit the semicolon key once, send a semicolon. Hit it twice, rapidly -- send a colon. Hit it three times, and your keyboard's LEDs do a wild dance. That's just one example of what Tap Dance can do. It's one of the nicest community-contributed features in the firmware, conceived and created by [algernon](https://github.com/algernon) in [#451](https://github.com/qmk/qmk_firmware/pull/451). Here's how algernon describes the feature:
|
||||
|
||||
With this feature one can specify keys that behave differently, based on the amount of times they have been tapped, and when interrupted, they get handled before the interrupter.
|
||||
|
||||
## Explanatory Comparison with `ACTION_FUNCTION_TAP`
|
||||
`ACTION_FUNCTION_TAP` can offer similar functionality to Tap Dance, but it's worth noting some important differences. To do this, let's explore a certain setup! We want one key to send `Space` on single-tap, but `Enter` on double-tap.
|
||||
## How to Use Tap Dance :id=how-to-use
|
||||
|
||||
With `ACTION_FUNCTION_TAP`, it is quite a rain-dance to set this up, and has the problem that when the sequence is interrupted, the interrupting key will be sent first. Thus, `SPC a` will result in `a SPC` being sent, if `SPC` and `a` are both typed within `TAPPING_TERM`. With the Tap Dance feature, that'll come out correctly as `SPC a` (even if both `SPC` and `a` are typed within the `TAPPING_TERM`.
|
||||
|
||||
To achieve this correct handling of interrupts, the implementation of Tap Dance hooks into two parts of the system: `process_record_quantum()`, and the matrix scan. These two parts are explained below, but for now the point to note is that we need the latter to be able to time out a tap sequence even when a key is not being pressed. That way, `SPC` alone will time out and register after `TAPPING_TERM` time.
|
||||
|
||||
## How to Use Tap Dance
|
||||
But enough of the generalities; lets look at how to actually use Tap Dance!
|
||||
|
||||
First, you will need `TAP_DANCE_ENABLE=yes` in your `rules.mk`, because the feature is disabled by default. This adds a little less than 1k to the firmware size.
|
||||
First, you will need `TAP_DANCE_ENABLE = yes` in your `rules.mk`, because the feature is disabled by default. This adds a little less than 1k to the firmware size.
|
||||
|
||||
Optionally, you might want to set a custom `TAPPING_TERM` time by adding something like this in you `config.h`:
|
||||
|
||||
```
|
||||
```c
|
||||
#define TAPPING_TERM 175
|
||||
```
|
||||
|
||||
The `TAPPING_TERM` time is the maximum time allowed between taps of your Tap Dance key, and is measured in milliseconds. For example, if you used the above `#define` statement and set up a Tap Dance key that sends `Space` on single-tap and `Enter` on double-tap, then this key will send `ENT` only if you tap this key twice in less than 175ms. If you tap the key, wait more than 175ms, and tap the key again you'll end up sending `SPC SPC` instead.
|
||||
The `TAPPING_TERM` time is the maximum time allowed between taps of your Tap Dance key, and is measured in milliseconds. For example, if you used the above `#define` statement and set up a Tap Dance key that sends `Space` on single-tap and `Enter` on double-tap, then this key will send `ENT` only if you tap this key twice in less than 175ms. If you tap the key, wait more than 175ms, and tap the key again you'll end up sending `SPC SPC` instead.
|
||||
|
||||
Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro, that - similar to `F()` - takes a number, which will later be used as an index into the `tap_dance_actions` array.
|
||||
Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro, that takes a number which will later be used as an index into the `tap_dance_actions` array.
|
||||
|
||||
After this, you'll want to use the `tap_dance_actions` array to specify what actions shall be taken when a tap-dance key is in action. Currently, there are five possible options:
|
||||
|
||||
@@ -35,7 +28,9 @@ After this, you'll want to use the `tap_dance_actions` array to specify what act
|
||||
* `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: Sends the `kc` keycode when tapped once, or toggles the state of `layer`. (this functions like the `TG` layer keycode).
|
||||
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
|
||||
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
|
||||
* `ACTION_TAP_DANCE_FN_ADVANCED_TIME(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn, tap_specific_tapping_term)`: This functions identically to the `ACTION_TAP_DANCE_FN_ADVANCED` function, but uses a custom tapping term for it, instead of the predefined `TAPPING_TERM`.
|
||||
* ~~`ACTION_TAP_DANCE_FN_ADVANCED_TIME(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn, tap_specific_tapping_term)`~~: This functions identically to the `ACTION_TAP_DANCE_FN_ADVANCED` function, but uses a custom tapping term for it, instead of the predefined `TAPPING_TERM`.
|
||||
* This is deprecated in favor of the Per Key Tapping Term functionality, as outlined [here](custom_quantum_functions.md#Custom_Tapping_Term). You'd want to check for the specific `TD()` macro that you want to use (such as `TD(TD_ESC_CAPS)`) instead of using this specific Tap Dance function.
|
||||
|
||||
|
||||
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
|
||||
|
||||
@@ -43,11 +38,12 @@ The first option is enough for a lot of cases, that just want dual roles. For ex
|
||||
|
||||
Similar to the first option, the second option is good for simple layer-switching cases.
|
||||
|
||||
For more complicated cases, use the third or fourth options (examples of each are listed below).
|
||||
For more complicated cases, use the third or fourth options (examples of each are listed below).
|
||||
|
||||
Finally, the fifth option is particularly useful if your non-Tap-Dance keys start behaving weirdly after adding the code for your Tap Dance keys. The likely problem is that you changed the `TAPPING_TERM` time to make your Tap Dance keys easier for you to use, and that this has changed the way your other keys handle interrupts.
|
||||
|
||||
## Implementation Details
|
||||
## Implementation Details :id=implementation
|
||||
|
||||
Well, that's the bulk of it! You should now be able to work through the examples below, and to develop your own Tap Dance functionality. But if you want a deeper understanding of what's going on behind the scenes, then read on for the explanation of how it all works!
|
||||
|
||||
The main entry point is `process_tap_dance()`, called from `process_record_quantum()`, which is run for every keypress, and our handler gets to run early. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. If it was the same, we increment the counter and reset the timer.
|
||||
@@ -58,9 +54,9 @@ Our next stop is `matrix_scan_tap_dance()`. This handles the timeout of tap-danc
|
||||
|
||||
For the sake of flexibility, tap-dance actions can be either a pair of keycodes, or a user function. The latter allows one to handle higher tap counts, or do extra things, like blink the LEDs, fiddle with the backlighting, and so on. This is accomplished by using an union, and some clever macros.
|
||||
|
||||
# Examples
|
||||
## Examples :id=examples
|
||||
|
||||
## Simple Example
|
||||
### Simple Example :id=simple-example
|
||||
|
||||
Here's a simple example for a single definition:
|
||||
|
||||
@@ -69,23 +65,26 @@ Here's a simple example for a single definition:
|
||||
3. In your `keymap.c` file, define the variables and definitions, then add to your keymap:
|
||||
|
||||
```c
|
||||
//Tap Dance Declarations
|
||||
// Tap Dance declarations
|
||||
enum {
|
||||
TD_ESC_CAPS = 0
|
||||
TD_ESC_CAPS,
|
||||
};
|
||||
|
||||
//Tap Dance Definitions
|
||||
// Tap Dance definitions
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
//Tap once for Esc, twice for Caps Lock
|
||||
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS)
|
||||
// Other declarations would go here, separated by commas, if you have them
|
||||
// Tap once for Escape, twice for Caps Lock
|
||||
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
|
||||
};
|
||||
|
||||
//In Layer declaration, add tap dance item in place of a key code
|
||||
TD(TD_ESC_CAPS)
|
||||
// Add tap dance item in place of a key code
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
// ...
|
||||
TD(TD_ESC_CAPS)
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
## Complex Examples
|
||||
### Complex Examples :id=complex-examples
|
||||
|
||||
This section details several complex tap dance examples.
|
||||
All the enums used in the examples are declared like this:
|
||||
@@ -93,104 +92,105 @@ All the enums used in the examples are declared like this:
|
||||
```c
|
||||
// Enums defined for all examples:
|
||||
enum {
|
||||
CT_SE = 0,
|
||||
CT_CLN,
|
||||
CT_EGG,
|
||||
CT_FLSH,
|
||||
X_TAP_DANCE
|
||||
CT_SE,
|
||||
CT_CLN,
|
||||
CT_EGG,
|
||||
CT_FLSH,
|
||||
X_TAP_DANCE
|
||||
};
|
||||
```
|
||||
### Example 1: Send `:` on Single Tap, `;` on Double Tap
|
||||
|
||||
#### Example 1: Send `:` on Single Tap, `;` on Double Tap :id=example-1
|
||||
|
||||
```c
|
||||
void dance_cln_finished (qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count == 1) {
|
||||
register_code (KC_RSFT);
|
||||
register_code (KC_SCLN);
|
||||
} else {
|
||||
register_code (KC_SCLN);
|
||||
}
|
||||
void dance_cln_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count == 1) {
|
||||
register_code16(KC_COLN);
|
||||
} else {
|
||||
register_code(KC_SCLN);
|
||||
}
|
||||
}
|
||||
|
||||
void dance_cln_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count == 1) {
|
||||
unregister_code (KC_RSFT);
|
||||
unregister_code (KC_SCLN);
|
||||
} else {
|
||||
unregister_code (KC_SCLN);
|
||||
}
|
||||
void dance_cln_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count == 1) {
|
||||
unregister_code16(KC_COLN);
|
||||
} else {
|
||||
unregister_code(KC_SCLN);
|
||||
}
|
||||
}
|
||||
|
||||
//All tap dance functions would go here. Only showing this one.
|
||||
// All tap dance functions would go here. Only showing this one.
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
|
||||
[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_cln_finished, dance_cln_reset),
|
||||
};
|
||||
```
|
||||
### Example 2: Send "Safety Dance!" After 100 Taps
|
||||
|
||||
#### Example 2: Send "Safety Dance!" After 100 Taps :id=example-2
|
||||
|
||||
```c
|
||||
void dance_egg (qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count >= 100) {
|
||||
SEND_STRING ("Safety dance!");
|
||||
reset_tap_dance (state);
|
||||
}
|
||||
void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count >= 100) {
|
||||
SEND_STRING("Safety dance!");
|
||||
reset_tap_dance(state);
|
||||
}
|
||||
}
|
||||
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[CT_EGG] = ACTION_TAP_DANCE_FN (dance_egg)
|
||||
[CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
|
||||
};
|
||||
```
|
||||
|
||||
### Example 3: Turn LED Lights On Then Off, One at a Time
|
||||
#### Example 3: Turn LED Lights On Then Off, One at a Time :id=example-3
|
||||
|
||||
```c
|
||||
// on each tap, light up one led, from right to left
|
||||
// on the forth tap, turn them off from right to left
|
||||
// On each tap, light up one LED, from right to left
|
||||
// On the fourth tap, turn them off from right to left
|
||||
void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
|
||||
switch (state->count) {
|
||||
case 1:
|
||||
ergodox_right_led_3_on();
|
||||
break;
|
||||
case 2:
|
||||
ergodox_right_led_2_on();
|
||||
break;
|
||||
case 3:
|
||||
ergodox_right_led_1_on();
|
||||
break;
|
||||
case 4:
|
||||
ergodox_right_led_3_off();
|
||||
_delay_ms(50);
|
||||
ergodox_right_led_2_off();
|
||||
_delay_ms(50);
|
||||
ergodox_right_led_1_off();
|
||||
}
|
||||
switch (state->count) {
|
||||
case 1:
|
||||
ergodox_right_led_3_on();
|
||||
break;
|
||||
case 2:
|
||||
ergodox_right_led_2_on();
|
||||
break;
|
||||
case 3:
|
||||
ergodox_right_led_1_on();
|
||||
break;
|
||||
case 4:
|
||||
ergodox_right_led_3_off();
|
||||
wait_ms(50);
|
||||
ergodox_right_led_2_off();
|
||||
wait_ms(50);
|
||||
ergodox_right_led_1_off();
|
||||
}
|
||||
}
|
||||
|
||||
// on the fourth tap, set the keyboard on flash state
|
||||
// On the fourth tap, set the keyboard on flash state
|
||||
void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
if (state->count >= 4) {
|
||||
reset_keyboard();
|
||||
reset_tap_dance(state);
|
||||
}
|
||||
if (state->count >= 4) {
|
||||
reset_keyboard();
|
||||
}
|
||||
}
|
||||
|
||||
// if the flash state didn't happen, then turn off LEDs, left to right
|
||||
// If the flash state didn't happen, then turn off LEDs, left to right
|
||||
void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
ergodox_right_led_1_off();
|
||||
_delay_ms(50);
|
||||
ergodox_right_led_2_off();
|
||||
_delay_ms(50);
|
||||
ergodox_right_led_3_off();
|
||||
ergodox_right_led_1_off();
|
||||
wait_ms(50);
|
||||
ergodox_right_led_2_off();
|
||||
wait_ms(50);
|
||||
ergodox_right_led_3_off();
|
||||
}
|
||||
|
||||
//All tap dances now put together. Example 3 is "CT_FLASH"
|
||||
// All tap dances now put together. Example 3 is "CT_FLASH"
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[CT_SE] = ACTION_TAP_DANCE_DOUBLE (KC_SPC, KC_ENT)
|
||||
,[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
|
||||
,[CT_EGG] = ACTION_TAP_DANCE_FN (dance_egg)
|
||||
,[CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED (dance_flsh_each, dance_flsh_finished, dance_flsh_reset)
|
||||
[CT_SE] = ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT),
|
||||
[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_cln_finished, dance_cln_reset),
|
||||
[CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
|
||||
[CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset)
|
||||
};
|
||||
```
|
||||
|
||||
### Example 4: 'Quad Function Tap-Dance'
|
||||
#### Example 4: 'Quad Function Tap-Dance' :id=example-4
|
||||
|
||||
By [DanielGGordon](https://github.com/danielggordon)
|
||||
|
||||
@@ -201,40 +201,37 @@ Below is a specific example:
|
||||
* Double Tap = Send `Escape`
|
||||
* Double Tap and Hold = Send `Alt`
|
||||
|
||||
## Setup
|
||||
|
||||
You will need a few things that can be used for 'Quad Function Tap-Dance'.
|
||||
|
||||
You'll need to add these to the top of your `keymap.c` file, before your keymap.
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
bool is_press_action;
|
||||
int state;
|
||||
bool is_press_action;
|
||||
uint8_t state;
|
||||
} tap;
|
||||
|
||||
enum {
|
||||
SINGLE_TAP = 1,
|
||||
SINGLE_HOLD = 2,
|
||||
DOUBLE_TAP = 3,
|
||||
DOUBLE_HOLD = 4,
|
||||
DOUBLE_SINGLE_TAP = 5, //send two single taps
|
||||
TRIPLE_TAP = 6,
|
||||
TRIPLE_HOLD = 7
|
||||
SINGLE_TAP = 1,
|
||||
SINGLE_HOLD,
|
||||
DOUBLE_TAP,
|
||||
DOUBLE_HOLD,
|
||||
DOUBLE_SINGLE_TAP, // Send two single taps
|
||||
TRIPLE_TAP,
|
||||
TRIPLE_HOLD
|
||||
};
|
||||
|
||||
//Tap dance enums
|
||||
// Tap dance enums
|
||||
enum {
|
||||
X_CTL = 0,
|
||||
SOME_OTHER_DANCE
|
||||
X_CTL,
|
||||
SOME_OTHER_DANCE
|
||||
};
|
||||
|
||||
int cur_dance (qk_tap_dance_state_t *state);
|
||||
|
||||
//for the x tap dance. Put it here so it can be used in any keymap
|
||||
void x_finished (qk_tap_dance_state_t *state, void *user_data);
|
||||
void x_reset (qk_tap_dance_state_t *state, void *user_data);
|
||||
uint8_t cur_dance(qk_tap_dance_state_t *state);
|
||||
|
||||
// For the x tap dance. Put it here so it can be used in any keymap
|
||||
void x_finished(qk_tap_dance_state_t *state, void *user_data);
|
||||
void x_reset(qk_tap_dance_state_t *state, void *user_data);
|
||||
```
|
||||
|
||||
Now, at the bottom of your `keymap.c` file, you'll need to add the following:
|
||||
@@ -267,65 +264,62 @@ Now, at the bottom of your `keymap.c` file, you'll need to add the following:
|
||||
* For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested
|
||||
*
|
||||
*/
|
||||
int cur_dance (qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (state->interrupted || !state->pressed) return SINGLE_TAP;
|
||||
//key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'.
|
||||
else return SINGLE_HOLD;
|
||||
}
|
||||
else if (state->count == 2) {
|
||||
/*
|
||||
* DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
|
||||
* action when hitting 'pp'. Suggested use case for this return value is when you want to send two
|
||||
* keystrokes of the key, and not the 'double tap' action/macro.
|
||||
*/
|
||||
if (state->interrupted) return DOUBLE_SINGLE_TAP;
|
||||
else if (state->pressed) return DOUBLE_HOLD;
|
||||
else return DOUBLE_TAP;
|
||||
}
|
||||
//Assumes no one is trying to type the same letter three times (at least not quickly).
|
||||
//If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
|
||||
//an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
|
||||
if (state->count == 3) {
|
||||
if (state->interrupted || !state->pressed) return TRIPLE_TAP;
|
||||
else return TRIPLE_HOLD;
|
||||
}
|
||||
else return 8; //magic number. At some point this method will expand to work for more presses
|
||||
uint8_t cur_dance(qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (state->interrupted || !state->pressed) return SINGLE_TAP;
|
||||
// Key has not been interrupted, but the key is still held. Means you want to send a 'HOLD'.
|
||||
else return SINGLE_HOLD;
|
||||
} else if (state->count == 2) {
|
||||
// DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
|
||||
// action when hitting 'pp'. Suggested use case for this return value is when you want to send two
|
||||
// keystrokes of the key, and not the 'double tap' action/macro.
|
||||
if (state->interrupted) return DOUBLE_SINGLE_TAP;
|
||||
else if (state->pressed) return DOUBLE_HOLD;
|
||||
else return DOUBLE_TAP;
|
||||
}
|
||||
|
||||
// Assumes no one is trying to type the same letter three times (at least not quickly).
|
||||
// If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
|
||||
// an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
|
||||
if (state->count == 3) {
|
||||
if (state->interrupted || !state->pressed) return TRIPLE_TAP;
|
||||
else return TRIPLE_HOLD;
|
||||
} else return 8; // Magic number. At some point this method will expand to work for more presses
|
||||
}
|
||||
|
||||
//instanalize an instance of 'tap' for the 'x' tap dance.
|
||||
// Create an instance of 'tap' for the 'x' tap dance.
|
||||
static tap xtap_state = {
|
||||
.is_press_action = true,
|
||||
.state = 0
|
||||
.is_press_action = true,
|
||||
.state = 0
|
||||
};
|
||||
|
||||
void x_finished (qk_tap_dance_state_t *state, void *user_data) {
|
||||
xtap_state.state = cur_dance(state);
|
||||
switch (xtap_state.state) {
|
||||
case SINGLE_TAP: register_code(KC_X); break;
|
||||
case SINGLE_HOLD: register_code(KC_LCTRL); break;
|
||||
case DOUBLE_TAP: register_code(KC_ESC); break;
|
||||
case DOUBLE_HOLD: register_code(KC_LALT); break;
|
||||
case DOUBLE_SINGLE_TAP: register_code(KC_X); unregister_code(KC_X); register_code(KC_X);
|
||||
//Last case is for fast typing. Assuming your key is `f`:
|
||||
//For example, when typing the word `buffer`, and you want to make sure that you send `ff` and not `Esc`.
|
||||
//In order to type `ff` when typing fast, the next character will have to be hit within the `TAPPING_TERM`, which by default is 200ms.
|
||||
}
|
||||
void x_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
xtap_state.state = cur_dance(state);
|
||||
switch (xtap_state.state) {
|
||||
case SINGLE_TAP: register_code(KC_X); break;
|
||||
case SINGLE_HOLD: register_code(KC_LCTRL); break;
|
||||
case DOUBLE_TAP: register_code(KC_ESC); break;
|
||||
case DOUBLE_HOLD: register_code(KC_LALT); break;
|
||||
// Last case is for fast typing. Assuming your key is `f`:
|
||||
// For example, when typing the word `buffer`, and you want to make sure that you send `ff` and not `Esc`.
|
||||
// In order to type `ff` when typing fast, the next character will have to be hit within the `TAPPING_TERM`, which by default is 200ms.
|
||||
case DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
|
||||
}
|
||||
}
|
||||
|
||||
void x_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||
switch (xtap_state.state) {
|
||||
case SINGLE_TAP: unregister_code(KC_X); break;
|
||||
case SINGLE_HOLD: unregister_code(KC_LCTRL); break;
|
||||
case DOUBLE_TAP: unregister_code(KC_ESC); break;
|
||||
case DOUBLE_HOLD: unregister_code(KC_LALT);
|
||||
case DOUBLE_SINGLE_TAP: unregister_code(KC_X);
|
||||
}
|
||||
xtap_state.state = 0;
|
||||
void x_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
switch (xtap_state.state) {
|
||||
case SINGLE_TAP: unregister_code(KC_X); break;
|
||||
case SINGLE_HOLD: unregister_code(KC_LCTRL); break;
|
||||
case DOUBLE_TAP: unregister_code(KC_ESC); break;
|
||||
case DOUBLE_HOLD: unregister_code(KC_LALT);
|
||||
case DOUBLE_SINGLE_TAP: unregister_code(KC_X);
|
||||
}
|
||||
xtap_state.state = 0;
|
||||
}
|
||||
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL,x_finished, x_reset)
|
||||
[X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)
|
||||
};
|
||||
```
|
||||
|
||||
@@ -335,90 +329,91 @@ If you want to implement this in your userspace, then you may want to check out
|
||||
|
||||
> In this configuration "hold" takes place **after** tap dance timeout (see `ACTION_TAP_DANCE_FN_ADVANCED_TIME`). To achieve instant hold, remove `state->interrupted` checks in conditions. As a result you may use comfortable longer tapping periods to have more time for taps and not to wait too long for holds (try starting with doubled `TAPPING_TERM`).
|
||||
|
||||
### Example 5: Using tap dance for advanced mod-tap and layer-tap keys :id=example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys
|
||||
#### Example 5: Using tap dance for advanced mod-tap and layer-tap keys :id=example-5
|
||||
|
||||
Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`.
|
||||
|
||||
Below your layers and custom keycodes, add the following:
|
||||
|
||||
```c
|
||||
// tapdance keycodes
|
||||
// Tap Dance keycodes
|
||||
enum td_keycodes {
|
||||
ALT_LP // Our example key: `LALT` when held, `(` when tapped. Add additional keycodes for each tapdance.
|
||||
ALT_LP // Our example key: `LALT` when held, `(` when tapped. Add additional keycodes for each tapdance.
|
||||
};
|
||||
|
||||
// define a type containing as many tapdance states as you need
|
||||
// Define a type containing as many tapdance states as you need
|
||||
typedef enum {
|
||||
SINGLE_TAP,
|
||||
SINGLE_HOLD,
|
||||
DOUBLE_SINGLE_TAP
|
||||
SINGLE_TAP,
|
||||
SINGLE_HOLD,
|
||||
DOUBLE_SINGLE_TAP
|
||||
} td_state_t;
|
||||
|
||||
// create a global instance of the tapdance state type
|
||||
// Create a global instance of the tapdance state type
|
||||
static td_state_t td_state;
|
||||
|
||||
// declare your tapdance functions:
|
||||
// Declare your tapdance functions:
|
||||
|
||||
// function to determine the current tapdance state
|
||||
int cur_dance (qk_tap_dance_state_t *state);
|
||||
// Function to determine the current tapdance state
|
||||
uint8_t cur_dance(qk_tap_dance_state_t *state);
|
||||
|
||||
// `finished` and `reset` functions for each tapdance keycode
|
||||
void altlp_finished (qk_tap_dance_state_t *state, void *user_data);
|
||||
void altlp_reset (qk_tap_dance_state_t *state, void *user_data);
|
||||
void altlp_finished(qk_tap_dance_state_t *state, void *user_data);
|
||||
void altlp_reset(qk_tap_dance_state_t *state, void *user_data);
|
||||
```
|
||||
|
||||
Below your `LAYOUT`, define each of the tapdance functions:
|
||||
|
||||
```c
|
||||
// determine the tapdance state to return
|
||||
int cur_dance (qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (state->interrupted || !state->pressed) { return SINGLE_TAP; }
|
||||
else { return SINGLE_HOLD; }
|
||||
}
|
||||
if (state->count == 2) { return DOUBLE_SINGLE_TAP; }
|
||||
else { return 3; } // any number higher than the maximum state value you return above
|
||||
}
|
||||
|
||||
// handle the possible states for each tapdance keycode you define:
|
||||
// Determine the tapdance state to return
|
||||
uint8_t cur_dance(qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (state->interrupted || !state->pressed) return SINGLE_TAP;
|
||||
else return SINGLE_HOLD;
|
||||
}
|
||||
|
||||
void altlp_finished (qk_tap_dance_state_t *state, void *user_data) {
|
||||
td_state = cur_dance(state);
|
||||
switch (td_state) {
|
||||
case SINGLE_TAP:
|
||||
register_code16(KC_LPRN);
|
||||
break;
|
||||
case SINGLE_HOLD:
|
||||
register_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_on(_MY_LAYER)` here
|
||||
break;
|
||||
case DOUBLE_SINGLE_TAP: // allow nesting of 2 parens `((` within tapping term
|
||||
tap_code16(KC_LPRN);
|
||||
register_code16(KC_LPRN);
|
||||
}
|
||||
if (state->count == 2) return DOUBLE_SINGLE_TAP;
|
||||
else return 3; // Any number higher than the maximum state value you return above
|
||||
}
|
||||
|
||||
void altlp_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||
switch (td_state) {
|
||||
case SINGLE_TAP:
|
||||
unregister_code16(KC_LPRN);
|
||||
break;
|
||||
case SINGLE_HOLD:
|
||||
unregister_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_off(_MY_LAYER)` here
|
||||
break;
|
||||
case DOUBLE_SINGLE_TAP:
|
||||
unregister_code16(KC_LPRN);
|
||||
}
|
||||
// Handle the possible states for each tapdance keycode you define:
|
||||
|
||||
void altlp_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
td_state = cur_dance(state);
|
||||
switch (td_state) {
|
||||
case SINGLE_TAP:
|
||||
register_code16(KC_LPRN);
|
||||
break;
|
||||
case SINGLE_HOLD:
|
||||
register_mods(MOD_BIT(KC_LALT)); // For a layer-tap key, use `layer_on(_MY_LAYER)` here
|
||||
break;
|
||||
case DOUBLE_SINGLE_TAP: // Allow nesting of 2 parens `((` within tapping term
|
||||
tap_code16(KC_LPRN);
|
||||
register_code16(KC_LPRN);
|
||||
}
|
||||
}
|
||||
|
||||
// define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions
|
||||
void altlp_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
switch (td_state) {
|
||||
case SINGLE_TAP:
|
||||
unregister_code16(KC_LPRN);
|
||||
break;
|
||||
case SINGLE_HOLD:
|
||||
unregister_mods(MOD_BIT(KC_LALT)); // For a layer-tap key, use `layer_off(_MY_LAYER)` here
|
||||
break;
|
||||
case DOUBLE_SINGLE_TAP:
|
||||
unregister_code16(KC_LPRN);
|
||||
}
|
||||
}
|
||||
|
||||
// Define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset)
|
||||
[ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset)
|
||||
};
|
||||
```
|
||||
|
||||
Wrap each tapdance keycode in `TD()` when including it in your keymap, e.g. `TD(ALT_LP)`.
|
||||
|
||||
### Example 6: Using tap dance for momentary-layer-switch and layer-toggle keys
|
||||
#### Example 6: Using tap dance for momentary-layer-switch and layer-toggle keys :id=example-6
|
||||
|
||||
Tap Dance can be used to mimic MO(layer) and TG(layer) functionality. For this example, we will set up a key to function as `KC_QUOT` on single-tap, as `MO(_MY_LAYER)` on single-hold, and `TG(_MY_LAYER)` on double-tap.
|
||||
|
||||
@@ -426,97 +421,92 @@ The first step is to include the following code towards the beginning of your `k
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
bool is_press_action;
|
||||
int state;
|
||||
bool is_press_action;
|
||||
uint8_t state;
|
||||
} tap;
|
||||
|
||||
//Define a type for as many tap dance states as you need
|
||||
// Define a type for as many tap dance states as you need
|
||||
enum {
|
||||
SINGLE_TAP = 1,
|
||||
SINGLE_HOLD = 2,
|
||||
DOUBLE_TAP = 3
|
||||
SINGLE_TAP = 1,
|
||||
SINGLE_HOLD,
|
||||
DOUBLE_TAP
|
||||
};
|
||||
|
||||
enum {
|
||||
QUOT_LAYR = 0 //Our custom tap dance key; add any other tap dance keys to this enum
|
||||
QUOT_LAYR, // Our custom tap dance key; add any other tap dance keys to this enum
|
||||
};
|
||||
|
||||
//Declare the functions to be used with your tap dance key(s)
|
||||
// Declare the functions to be used with your tap dance key(s)
|
||||
|
||||
//Function associated with all tap dances
|
||||
int cur_dance (qk_tap_dance_state_t *state);
|
||||
// Function associated with all tap dances
|
||||
uint8_t cur_dance(qk_tap_dance_state_t *state);
|
||||
|
||||
//Functions associated with individual tap dances
|
||||
void ql_finished (qk_tap_dance_state_t *state, void *user_data);
|
||||
void ql_reset (qk_tap_dance_state_t *state, void *user_data);
|
||||
// Functions associated with individual tap dances
|
||||
void ql_finished(qk_tap_dance_state_t *state, void *user_data);
|
||||
void ql_reset(qk_tap_dance_state_t *state, void *user_data);
|
||||
```
|
||||
|
||||
Towards the bottom of your `keymap.c`, include the following code:
|
||||
|
||||
```c
|
||||
//Determine the current tap dance state
|
||||
int cur_dance (qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (!state->pressed) {
|
||||
return SINGLE_TAP;
|
||||
} else {
|
||||
return SINGLE_HOLD;
|
||||
}
|
||||
} else if (state->count == 2) {
|
||||
return DOUBLE_TAP;
|
||||
}
|
||||
else return 8;
|
||||
// Determine the current tap dance state
|
||||
uint8_t cur_dance(qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (!state->pressed) return SINGLE_TAP;
|
||||
else return SINGLE_HOLD;
|
||||
} else if (state->count == 2) return DOUBLE_TAP;
|
||||
else return 8;
|
||||
}
|
||||
|
||||
//Initialize tap structure associated with example tap dance key
|
||||
// Initialize tap structure associated with example tap dance key
|
||||
static tap ql_tap_state = {
|
||||
.is_press_action = true,
|
||||
.state = 0
|
||||
.is_press_action = true,
|
||||
.state = 0
|
||||
};
|
||||
|
||||
//Functions that control what our tap dance key does
|
||||
void ql_finished (qk_tap_dance_state_t *state, void *user_data) {
|
||||
ql_tap_state.state = cur_dance(state);
|
||||
switch (ql_tap_state.state) {
|
||||
case SINGLE_TAP:
|
||||
tap_code(KC_QUOT);
|
||||
break;
|
||||
case SINGLE_HOLD:
|
||||
layer_on(_MY_LAYER);
|
||||
break;
|
||||
case DOUBLE_TAP:
|
||||
//check to see if the layer is already set
|
||||
if (layer_state_is(_MY_LAYER)) {
|
||||
//if already set, then switch it off
|
||||
// Functions that control what our tap dance key does
|
||||
void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
ql_tap_state.state = cur_dance(state);
|
||||
switch (ql_tap_state.state) {
|
||||
case SINGLE_TAP:
|
||||
tap_code(KC_QUOT);
|
||||
break;
|
||||
case SINGLE_HOLD:
|
||||
layer_on(_MY_LAYER);
|
||||
break;
|
||||
case DOUBLE_TAP:
|
||||
// Check to see if the layer is already set
|
||||
if (layer_state_is(_MY_LAYER)) {
|
||||
// If already set, then switch it off
|
||||
layer_off(_MY_LAYER);
|
||||
} else {
|
||||
// If not already set, then switch the layer on
|
||||
layer_on(_MY_LAYER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
// If the key was held down and now is released then switch off the layer
|
||||
if (ql_tap_state.state == SINGLE_HOLD) {
|
||||
layer_off(_MY_LAYER);
|
||||
} else {
|
||||
//if not already set, then switch the layer on
|
||||
layer_on(_MY_LAYER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ql_tap_state.state = 0;
|
||||
}
|
||||
|
||||
void ql_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||
//if the key was held down and now is released then switch off the layer
|
||||
if (ql_tap_state.state==SINGLE_HOLD) {
|
||||
layer_off(_MY_LAYER);
|
||||
}
|
||||
ql_tap_state.state = 0;
|
||||
}
|
||||
|
||||
//Associate our tap dance key with its functionality
|
||||
// Associate our tap dance key with its functionality
|
||||
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||
[QUOT_LAYR] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275)
|
||||
[QUOT_LAYR] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275)
|
||||
};
|
||||
```
|
||||
|
||||
The above code is similar to that used in previous examples. The one point to note is that we need to be able to check which layers are active at any time so we can toggle them if needed. To do this we use the `layer_state_is( layer )` function which returns `true` if the given `layer` is active.
|
||||
The above code is similar to that used in previous examples. The one point to note is that we need to be able to check which layers are active at any time so we can toggle them if needed. To do this we use the `layer_state_is(layer)` function which returns `true` if the given `layer` is active.
|
||||
|
||||
The use of `cur_dance()` and `ql_tap_state` mirrors the above examples.
|
||||
|
||||
The `case:SINGLE_TAP` in `ql_finished` is similar to the above examples. The `case:SINGLE_HOLD` works in conjunction with `ql_reset()` to switch to `_MY_LAYER` while the tap dance key is held, and to switch away from `_MY_LAYER` when the key is released. This mirrors the use of `MO(_MY_LAYER)`. The `case:DOUBLE_TAP` works by checking whether `_MY_LAYER` is the active layer, and toggling it on or off accordingly. This mirrors the use of `TG(_MY_LAYER)`.
|
||||
The `case:SINGLE_TAP` in `ql_finished` is similar to the above examples. The `SINGLE_HOLD` case works in conjunction with `ql_reset()` to switch to `_MY_LAYER` while the tap dance key is held, and to switch away from `_MY_LAYER` when the key is released. This mirrors the use of `MO(_MY_LAYER)`. The `DOUBLE_TAP` case works by checking whether `_MY_LAYER` is the active layer, and toggling it on or off accordingly. This mirrors the use of `TG(_MY_LAYER)`.
|
||||
|
||||
`tap_dance_actions[]` works similar to the above examples. Note that I used `ACTION_TAP_DANCE_FN_ADVANCED_TIME()` instead of `ACTION_TAP_DANCE_FN_ADVANCED()`. This is because I like my `TAPPING_TERM` to be short (~175ms) for my non-tap-dance keys but find that this is too quick for me to reliably complete tap dance actions - thus the increased time of 275ms here.
|
||||
`tap_dance_actions[]` works similar to the above examples. Note that I used `ACTION_TAP_DANCE_FN_ADVANCED_TIME()` instead of `ACTION_TAP_DANCE_FN_ADVANCED()`. This is because I like my `TAPPING_TERM` to be short (\~175ms) for my non-tap-dance keys but find that this is too quick for me to reliably complete tap dance actions - thus the increased time of 275ms here.
|
||||
|
||||
Finally, to get this tap dance key working, be sure to include `TD(QUOT_LAYR)` in your `keymaps[]`.
|
||||
|
@@ -2,11 +2,25 @@
|
||||
|
||||
Unicode characters can be input straight from your keyboard! There are some limitations, however.
|
||||
|
||||
QMK has three different methods for enabling Unicode input and defining keycodes:
|
||||
In order to enable Unicode support on your keyboard, you will need to do the following:
|
||||
|
||||
## Basic Unicode
|
||||
1. Choose one of three supported Unicode implementations: [Basic Unicode](#basic-unicode), [Unicode Map](#unicode-map), [UCIS](#ucis).
|
||||
2. Find which [input mode](#input-modes) is the best match for your operating system and setup.
|
||||
3. [Set](#setting-the-input-mode) the appropriate input mode (or modes) in your configuration.
|
||||
4. Add Unicode keycodes to your keymap.
|
||||
|
||||
This method supports Unicode code points up to `0x7FFF`. This covers characters for most modern languages, as well as symbols, but it doesn't cover emoji.
|
||||
|
||||
## 1. Methods :id=methods
|
||||
|
||||
QMK supports three different methods for enabling Unicode input and adding Unicode characters to your keymap. Each has its pros and cons in terms of flexibility and ease of use. Choose the one that best fits your use case.
|
||||
|
||||
The Basic method should be enough for most users. However, if you need a wider range of supported characters (including emoji, rare symbols etc.), you should use Unicode Map.
|
||||
|
||||
<br>
|
||||
|
||||
### 1.1. Basic Unicode :id=basic-unicode
|
||||
|
||||
The easiest to use method, albeit somewhat limited. It stores Unicode characters as keycodes in the keymap itself, so it only supports code points up to `0x7FFF`. This covers characters for most modern languages (including East Asian), as well as symbols, but it doesn't cover emoji.
|
||||
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
@@ -14,11 +28,13 @@ Add the following to your `rules.mk`:
|
||||
UNICODE_ENABLE = yes
|
||||
```
|
||||
|
||||
Then add `UC(c)` keycodes to your keymap, where _c_ is the code point (preferably in hexadecimal, up to 4 digits long). For example: `UC(0x45B)`, `UC(0x30C4)`.
|
||||
Then add `UC(c)` keycodes to your keymap, where _c_ is the code point of the desired character (preferably in hexadecimal, up to 4 digits long). For example, `UC(0x40B)` will output [Ћ](https://unicode-table.com/en/040B/), and `UC(0x30C4)` will output [ツ](https://unicode-table.com/en/30C4).
|
||||
|
||||
## Unicode Map
|
||||
<br>
|
||||
|
||||
This method supports all possible code points (up to `0x10FFFF`); however, you need to maintain a separate mapping table in your keymap file, which may contain at most 16384 entries.
|
||||
### 1.2. Unicode Map :id=unicode-map
|
||||
|
||||
In addition to standard character ranges, this method also covers emoji, ancient scripts, rare symbols etc. In fact, all possible code points (up to `0x10FFFF`) are supported. Here, Unicode characters are stored in a separate mapping table. You need to maintain a `unicode_map` array in your keymap file, which may contain at most 16384 entries.
|
||||
|
||||
Add the following to your `rules.mk`:
|
||||
|
||||
@@ -26,7 +42,7 @@ Add the following to your `rules.mk`:
|
||||
UNICODEMAP_ENABLE = yes
|
||||
```
|
||||
|
||||
Then add `X(i)` keycodes to your keymap, where _i_ is an array index into the mapping table:
|
||||
Then add `X(i)` keycodes to your keymap, where _i_ is the desired character's index in the mapping table. This can be a numeric value, but it's recommended to keep the indices in an enum and access them by name.
|
||||
|
||||
```c
|
||||
enum unicode_names {
|
||||
@@ -44,15 +60,17 @@ const uint32_t PROGMEM unicode_map[] = {
|
||||
|
||||
Then you can use `X(BANG)`, `X(SNEK)` etc. in your keymap.
|
||||
|
||||
### Lower and Upper Case
|
||||
#### Lower and Upper Case
|
||||
|
||||
Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `XP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear.
|
||||
|
||||
This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `XP()`. This helps blend Unicode keys in with regular alphas.
|
||||
|
||||
Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L40) function. This also allows you to, say, check Ctrl instead of Shift/Caps.
|
||||
Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L36) function. This also allows you to, say, check Ctrl instead of Shift/Caps.
|
||||
|
||||
## UCIS
|
||||
<br>
|
||||
|
||||
### 1.3. UCIS :id=ucis
|
||||
|
||||
This method also supports all possible code points. As with the Unicode Map method, you need to maintain a mapping table in your keymap file. However, there are no built-in keycodes for this feature — you have to create a custom keycode or function that invokes this functionality.
|
||||
|
||||
@@ -66,15 +84,18 @@ Then define a table like this in your keymap file:
|
||||
|
||||
```c
|
||||
const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
|
||||
UCIS_SYM("poop", 0x1F4A9), // 💩
|
||||
UCIS_SYM("rofl", 0x1F923), // 🤣
|
||||
UCIS_SYM("kiss", 0x1F619) // 😙
|
||||
UCIS_SYM("poop", 0x1F4A9), // 💩
|
||||
UCIS_SYM("rofl", 0x1F923), // 🤣
|
||||
UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺
|
||||
UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0), // ಠ_ಠ
|
||||
);
|
||||
```
|
||||
|
||||
To use it, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl"), and hit Space or Enter. QMK should erase the "rofl" text and insert the laughing emoji.
|
||||
By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file.
|
||||
|
||||
### Customization
|
||||
To use UCIS input, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.
|
||||
|
||||
#### Customization
|
||||
|
||||
There are several functions that you can define in your keymap to customize the functionality of this feature.
|
||||
|
||||
@@ -84,63 +105,77 @@ There are several functions that you can define in your keymap to customize the
|
||||
|
||||
You can find the default implementations of these functions in [`process_ucis.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c).
|
||||
|
||||
## Input Modes
|
||||
|
||||
## 2. Input Modes :id=input-modes
|
||||
|
||||
Unicode input in QMK works by inputting a sequence of characters to the OS, sort of like a macro. Unfortunately, the way this is done differs for each platform. Specifically, each platform requires a different combination of keys to trigger Unicode input. Therefore, a corresponding input mode has to be set in QMK.
|
||||
|
||||
The following input modes are available:
|
||||
|
||||
* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map).
|
||||
* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points).
|
||||
|
||||
To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar.
|
||||
By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with another keycode.
|
||||
By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with a different keycode.
|
||||
|
||||
!> Using the _Unicode Hex Input_ input source may disable some Option based shortcuts, such as Option + Left Arrow and Option + Right Arrow.
|
||||
!> Using the _Unicode Hex Input_ input source may disable some Option-based shortcuts, such as Option+Left and Option+Right.
|
||||
|
||||
!> `UC_OSX` is a deprecated alias of `UC_MAC` that will be removed in a future version of QMK.
|
||||
!> `UC_OSX` is a deprecated alias of `UC_MAC` that will be removed in future versions of QMK. All new keymaps should use `UC_MAC`.
|
||||
|
||||
* **`UC_LNX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points).
|
||||
|
||||
Enabled by default and works almost anywhere on IBus-enabled distros. Without IBus, this mode works under GTK apps, but rarely anywhere else.
|
||||
By default, this mode uses Ctrl+Shift+U (`LCTL(LSFT(KC_U))`) to start Unicode input, but this can be changed by defining [`UNICODE_KEY_LNX`](#input-key-configuration) with another keycode. This might be required for IBus versions ≥1.5.15, where Ctrl+Shift+U behavior is consolidated into Ctrl+Shift+E.
|
||||
By default, this mode uses Ctrl+Shift+U (`LCTL(LSFT(KC_U))`) to start Unicode input, but this can be changed by defining [`UNICODE_KEY_LNX`](#input-key-configuration) with a different keycode. This might be required for IBus versions ≥1.5.15, where Ctrl+Shift+U behavior is consolidated into Ctrl+Shift+E.
|
||||
|
||||
* **`UC_WIN`**: _(not recommended)_ Windows built-in hex numpad Unicode input. Supports code points up to `0xFFFF`.
|
||||
|
||||
To enable, create a registry key under `HKEY_CURRENT_USER\Control Panel\Input Method\EnableHexNumpad` of type `REG_SZ` called `EnableHexNumpad` and set its value to `1`. This can be done from the Command Prompt by running `reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1` with administrator privileges. Reboot afterwards.
|
||||
To enable, create a registry key under `HKEY_CURRENT_USER\Control Panel\Input Method` of type `REG_SZ` called `EnableHexNumpad` and set its value to `1`. This can be done from the Command Prompt by running `reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1` with administrator privileges. Reboot afterwards.
|
||||
This mode is not recommended because of reliability and compatibility issues; use the `UC_WINC` mode instead.
|
||||
|
||||
* **`UC_BSD`**: _(non implemented)_ Unicode input under BSD. Not implemented at this time. If you're a BSD user and want to help add support for it, please [open an issue on GitHub](https://github.com/qmk/qmk_firmware/issues).
|
||||
|
||||
* **`UC_WINC`**: Windows Unicode input using [WinCompose](https://github.com/samhocevar/wincompose). As of v0.9.0, supports code points up to `0x10FFFF` (all possible code points).
|
||||
|
||||
To enable, install the [latest release](https://github.com/samhocevar/wincompose/releases/latest). Once installed, WinCompose will automatically run on startup. Works reliably under all version of Windows supported by the app.
|
||||
By default, this mode uses right Alt (`KC_RALT`) as the Compose key, but this can be changed in the WinCompose settings and by defining [`UNICODE_KEY_WINC`](#input-key-configuration) with another keycode.
|
||||
To enable, install the [latest release](https://github.com/samhocevar/wincompose/releases/latest). Once installed, WinCompose will automatically run on startup. This mode works reliably under all version of Windows supported by the app.
|
||||
By default, this mode uses right Alt (`KC_RALT`) as the Compose key, but this can be changed in the WinCompose settings and by defining [`UNICODE_KEY_WINC`](#input-key-configuration) with a different keycode.
|
||||
|
||||
### Switching Input Modes
|
||||
|
||||
There are two ways to set the input mode for Unicode: by keycode or by function. Keep in mind that both methods write to persistent storage (EEPROM), and are loaded each time the keyboard starts. So once you've set it the first time, you don't need to set it again unless you want to change it, or you've reset the EEPROM settings.
|
||||
## 3. Setting the Input Mode :id=setting-the-input-mode
|
||||
|
||||
You can switch the input mode at any time by using one of the following keycodes. The easiest way is to add the ones you use to your keymap.
|
||||
|
||||
|Keycode |Alias |Input Mode |Description |
|
||||
|----------------------|---------|------------|--------------------------------------------------------------|
|
||||
|`UNICODE_MODE_FORWARD`|`UC_MOD` |Next in list|[Cycle](#input-mode-cycling) through selected modes |
|
||||
|`UNICODE_MODE_REVERSE`|`UC_RMOD`|Prev in list|[Cycle](#input-mode-cycling) through selected modes in reverse|
|
||||
|`UNICODE_MODE_MAC` |`UC_M_MA`|`UC_MAC` |Switch to macOS input |
|
||||
|`UNICODE_MODE_LNX` |`UC_M_LN`|`UC_LNX` |Switch to Linux input |
|
||||
|`UNICODE_MODE_WIN` |`UC_M_WI`|`UC_WIN` |Switch to Windows input |
|
||||
|`UNICODE_MODE_BSD` |`UC_M_BS`|`UC_BSD` |Switch to BSD input (not implemented) |
|
||||
|`UNICODE_MODE_WINC` |`UC_M_WC`|`UC_WINC` |Switch to Windows input using WinCompose |
|
||||
|
||||
You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UC_LNX`). Since the function only needs to be called once, it's recommended that you do it in `eeconfig_init_user()` (or a similar function). For example:
|
||||
To set your desired input mode, add the following define to your `config.h`:
|
||||
|
||||
```c
|
||||
void eeconfig_init_user(void) {
|
||||
set_unicode_input_mode(UC_LNX);
|
||||
}
|
||||
#define UNICODE_SELECTED_MODES UC_LNX
|
||||
```
|
||||
|
||||
### Audio Feedback
|
||||
This example sets the board's default input mode to `UC_LNX`. You can replace this with `UC_MAC`, `UC_WINC`, or any of the other modes listed [above](#input-modes). The board will automatically use the selected mode on startup, unless you manually switch to another mode (see [below](#keycodes)).
|
||||
|
||||
You can also select multiple input modes, which allows you to easily cycle through them using the `UC_MOD`/`UC_RMOD` keycodes.
|
||||
|
||||
```c
|
||||
#define UNICODE_SELECTED_MODES UC_MAC, UC_LNX, UC_WINC
|
||||
```
|
||||
|
||||
Note that the values are separated by commas. The board will remember the last used input mode and will continue using it on next power-up. You can disable this and force it to always start with the first mode in the list by adding `#define UNICODE_CYCLE_PERSIST false` to your `config.h`.
|
||||
|
||||
#### Keycodes
|
||||
|
||||
You can switch the input mode at any time by using the following keycodes. Adding these to your keymap allows you to quickly switch to a specific input mode, including modes not listed in `UNICODE_SELECTED_MODES`.
|
||||
|
||||
|Keycode |Alias |Input Mode |Description |
|
||||
|----------------------|---------|------------|-----------------------------------------------------------------------------|
|
||||
|`UNICODE_MODE_FORWARD`|`UC_MOD` |Next in list|Cycle through selected modes, reverse direction when Shift is held |
|
||||
|`UNICODE_MODE_REVERSE`|`UC_RMOD`|Prev in list|Cycle through selected modes in reverse, forward direction when Shift is held|
|
||||
|`UNICODE_MODE_MAC` |`UC_M_MA`|`UC_MAC` |Switch to macOS input |
|
||||
|`UNICODE_MODE_LNX` |`UC_M_LN`|`UC_LNX` |Switch to Linux input |
|
||||
|`UNICODE_MODE_WIN` |`UC_M_WI`|`UC_WIN` |Switch to Windows input |
|
||||
|`UNICODE_MODE_BSD` |`UC_M_BS`|`UC_BSD` |Switch to BSD input _(not implemented)_ |
|
||||
|`UNICODE_MODE_WINC` |`UC_M_WC`|`UC_WINC` |Switch to Windows input using WinCompose |
|
||||
|
||||
You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UC_LNX`).
|
||||
|
||||
?> Using `UNICODE_SELECTED_MODES` is preferable to calling `set_unicode_input_mode()` in `matrix_init_user()` or similar functions, since it's better integrated into the Unicode system and has the added benefit of avoiding unnecessary writes to EEPROM.
|
||||
|
||||
#### Audio Feedback
|
||||
|
||||
If you have the [Audio feature](feature_audio.md) enabled on the board, you can set melodies to be played when you press the above keys. That way you can have some audio feedback when switching input modes.
|
||||
|
||||
@@ -154,20 +189,21 @@ For instance, you can add these definitions to your `config.h` file:
|
||||
#define UNICODE_SONG_WINC UNICODE_WINDOWS
|
||||
```
|
||||
|
||||
### Additional Customization
|
||||
|
||||
## Additional Customization
|
||||
|
||||
Because Unicode is a large and versatile feature, there are a number of options you can customize to make it work better on your system.
|
||||
|
||||
#### Start and Finish Input Functions
|
||||
### Start and Finish Input Functions
|
||||
|
||||
The functions for starting and finishing Unicode input on your platform can be overridden locally. Possible uses include customizing input mode behavior if you don't use the default keys, or adding extra visual/audio feedback to Unicode input.
|
||||
|
||||
* `void unicode_input_start(void)` – This sends the initial sequence that tells your platform to enter Unicode input mode. For example, it presses Ctrl+Shift+U on Linux and holds the Option key on macOS.
|
||||
* `void unicode_input_finish(void)` – This is called to exit Unicode input mode, for example by pressing Space or releasing the Option key.
|
||||
* `void unicode_input_start(void)` – This sends the initial sequence that tells your platform to enter Unicode input mode. For example, it holds the left Alt key followed by Num+ on Windows, and presses the `UNICODE_KEY_LNX` combination (default: Ctrl+Shift+U) on Linux.
|
||||
* `void unicode_input_finish(void)` – This is called to exit Unicode input mode, for example by pressing Space or releasing the Alt key.
|
||||
|
||||
You can find the default implementations of these functions in [`process_unicode_common.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode_common.c).
|
||||
|
||||
#### Input Key Configuration
|
||||
### Input Key Configuration
|
||||
|
||||
You can customize the keys used to trigger Unicode input for macOS, Linux and WinCompose by adding corresponding defines to your `config.h`. The default values match the platforms' default settings, so you shouldn't need to change this unless Unicode input isn't working, or you want to use a different key (e.g. in order to free up left or right Alt).
|
||||
|
||||
@@ -177,54 +213,47 @@ You can customize the keys used to trigger Unicode input for macOS, Linux and Wi
|
||||
|`UNICODE_KEY_LNX` |`uint16_t`|`LCTL(LSFT(KC_U))`|`#define UNICODE_KEY_LNX LCTL(LSFT(KC_E))`|
|
||||
|`UNICODE_KEY_WINC`|`uint8_t` |`KC_RALT` |`#define UNICODE_KEY_WINC KC_RGUI` |
|
||||
|
||||
#### Input Mode Cycling
|
||||
|
||||
You can choose which input modes are available for cycling through. By default, this is disabled. If you want to enable it, limiting it to just the modes you use makes sense. Note that the values in the list are comma-delimited.
|
||||
## Sending Unicode Strings
|
||||
|
||||
```c
|
||||
#define UNICODE_SELECTED_MODES UC_MAC, UC_LNX, UC_WIN, UC_WINC
|
||||
```
|
||||
QMK provides several functions that allow you to send Unicode input to the host programmatically:
|
||||
|
||||
You can cycle through the selected modes by using the `UC_MOD`/`UC_RMOD` keycodes, or by calling `cycle_unicode_input_mode(offset)` in your code (`offset` is how many modes to move forward by, so +1 corresponds to `UC_MOD`).
|
||||
### `send_unicode_string()`
|
||||
|
||||
By default, when the keyboard boots, it will initialize the input mode to the last one you used. You can disable this and make it start with the first mode in the list every time by adding the following to your `config.h`:
|
||||
|
||||
```c
|
||||
#define UNICODE_CYCLE_PERSIST false
|
||||
```
|
||||
|
||||
!> Using `UNICODE_SELECTED_MODES` means you don't have to initially set the input mode in `matrix_init_user()` (or a similar function); the Unicode system will do that for you on startup. This has the added benefit of avoiding unnecessary writes to EEPROM.
|
||||
|
||||
## `send_unicode_string()`
|
||||
|
||||
This function is much like `send_string()` but allows you to input UTF-8 characters directly, and supports all code points (provided the selected input method also supports it). Make sure your `keymap.c` is formatted in UTF-8 encoding.
|
||||
This function is much like `send_string()`, but it allows you to input UTF-8 characters directly. It supports all code points, provided the selected input mode also supports it. Make sure your `keymap.c` file is formatted using UTF-8 encoding.
|
||||
|
||||
```c
|
||||
send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻");
|
||||
```
|
||||
|
||||
## `send_unicode_hex_string()`
|
||||
Example uses include sending Unicode strings when a key is pressed, as described in [Macros](feature_macros.md).
|
||||
|
||||
Similar to `send_unicode_string()`, but the characters are represented by their code point values in ASCII, separated by spaces. For example, the table flip above would be achieved with:
|
||||
### `send_unicode_hex_string()`
|
||||
|
||||
Similar to `send_unicode_string()`, but the characters are represented by their Unicode code points, written in hexadecimal and separated by spaces. For example, the table flip above would be achieved with:
|
||||
|
||||
```c
|
||||
send_unicode_hex_string("0028 30CE 0CA0 75CA 0CA0 0029 30CE 5F61 253B 2501 253B");
|
||||
```
|
||||
|
||||
An easy way to convert your Unicode string to this format is by using [this site](https://r12a.github.io/app-conversion/), and taking the result in the "Hex/UTF-32" section.
|
||||
An easy way to convert your Unicode string to this format is to use [this site](https://r12a.github.io/app-conversion/) and take the result in the "Hex/UTF-32" section.
|
||||
|
||||
|
||||
## Additional Language Support
|
||||
|
||||
In `quantum/keymap_extras/`, you'll see various language files - these work the same way as the alternative layout ones do. Most are defined by their two letter country/language code followed by an underscore and a 4-letter abbreviation of its name. `FR_UGRV` which will result in a `ù` when using a software-implemented AZERTY layout. It's currently difficult to send such characters in just the firmware.
|
||||
In `quantum/keymap_extras`, you'll see various language files — these work the same way as the ones for alternative layouts such as Colemak or BÉPO. When you include one of these language headers, you gain access to keycodes specific to that language / national layout. Such keycodes are defined by a 2-letter country/language code, followed by an underscore and a 4-letter abbreviation of the character to which the key corresponds. For example, including `keymap_french.h` and using `FR_UGRV` in your keymap will output `ù` when typed on a system with a native French AZERTY layout.
|
||||
|
||||
If the primary system layout you use on your machine is different from US ANSI, using these language-specific keycodes can help your QMK keymaps better match what will actually be output on the screen. However, keep in mind that these keycodes are just aliases for the corresponding default US keycodes under the hood, and that the HID protocol used by keyboards is itself inherently based on US ANSI.
|
||||
|
||||
|
||||
## International Characters on Windows
|
||||
|
||||
### AutoHotkey allows Windows users to create custom hotkeys among others.
|
||||
### AutoHotkey
|
||||
|
||||
The method does not require Unicode support in the keyboard itself but depends instead of [AutoHotkey](https://autohotkey.com) running in the background.
|
||||
The method does not require Unicode support in the keyboard itself but instead depends on [AutoHotkey](https://autohotkey.com) running in the background.
|
||||
|
||||
First you need to select a modifier combination that is not in use by any of your programs.
|
||||
CtrlAltWin is not used very widely and should therefore be perfect for this.
|
||||
Ctrl+Alt+Win is not used very widely and should therefore be perfect for this.
|
||||
There is a macro defined for a mod-tab combo `LCAG_T`.
|
||||
Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`.
|
||||
This makes the key behave like a tab key if pressed and released immediately but changes it to the modifier if used with another key.
|
||||
@@ -239,8 +268,5 @@ AutoHotkey inserts the Text right of `Send, ` when this combination is pressed.
|
||||
|
||||
### US International
|
||||
|
||||
If you enable the US International layout on the system, it will use punctuation to accent the characters.
|
||||
|
||||
For instance, typing "\`a" will result in à.
|
||||
|
||||
If you enable the US International layout on the system, it will use punctuation to accent the characters. For instance, typing "\`a" will result in à.
|
||||
You can find details on how to enable this [here](https://support.microsoft.com/en-us/help/17424/windows-change-keyboard-layout).
|
||||
|
@@ -111,7 +111,7 @@ This is ideal for when you want ensure everything compiles successfully when pre
|
||||
|
||||
## Examples
|
||||
|
||||
For a brief example, checkout [`/users/_example/`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna).
|
||||
For a brief example, checkout [`/users/_example/`](https://github.com/qmk/qmk_firmware/tree/master/users/_example).
|
||||
For a more complicated example, checkout [`/users/drashna/`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna)'s userspace.
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ If you wanted to consolidate macros and other functions into your userspace for
|
||||
|
||||
First, you'd want to go through all of your `keymap.c` files and replace `process_record_user` with `process_record_keymap` instead. This way, you can still use keyboard specific codes on those boards, and use your custom "global" keycodes as well. You'll also want to replace `SAFE_RANGE` with `NEW_SAFE_RANGE` so that you wont have any overlapping keycodes
|
||||
|
||||
Then add `#include <name.h>` to all of your keymap.c files. This allows you to use these new keycodes without having to redefine them in each keymap.
|
||||
Then add `#include "<name>.h"` to all of your keymap.c files. This allows you to use these new keycodes without having to redefine them in each keymap.
|
||||
|
||||
Once you've done that, you'll want to set the keycode definitions that you need to the `<name>.h` file. For instance:
|
||||
```c
|
||||
|
@@ -239,3 +239,4 @@ There are a number of DFU commands that you can use to flash firmware to a STM32
|
||||
* `:dfu-util-split-left` - This flashes the normal firmware, just like the default option (`:dfu-util`). However, this also configures the "Left Side" EEPROM setting for split keyboards.
|
||||
* `:dfu-util-split-right` - This flashes the normal firmware, just like the default option (`:dfu-util`). However, this also configures the "Right Side" EEPROM setting for split keyboards.
|
||||
* `:st-link-cli` - This allows you to flash the firmware via ST-LINK's CLI utility, rather than dfu-util.
|
||||
* `:st-flash` - This allows you to flash the firmware via the `st-flash` utility from [STLink Tools](https://github.com/stlink-org/stlink), rather than dfu-util.
|
||||
|
@@ -42,7 +42,9 @@ Vous préférez une solution basée sur le terminal? [hid_listen](https://www.pj
|
||||
|
||||
Parfois, il est utile d'afficher des messages de débugage depuis votre [code custom](custom_quantum_functions.md). Le faire est assez simple. Commencez par ajouter `print.h` au début de votre fichier:
|
||||
|
||||
#include <print.h>
|
||||
```c
|
||||
#include "print.h"
|
||||
```
|
||||
|
||||
Une fois fait, vous pouvez utiliser les fonctions print suivantes:
|
||||
|
||||
|
@@ -101,10 +101,6 @@ This allows you to send Unicode characters by inputting a mnemonic corresponding
|
||||
|
||||
For further details, as well as limitations, see the [Unicode page](feature_unicode.md).
|
||||
|
||||
`BLUETOOTH_ENABLE`
|
||||
|
||||
This allows you to interface with a Bluefruit EZ-key to send keycodes wirelessly. It uses the D2 and D3 pins.
|
||||
|
||||
`AUDIO_ENABLE`
|
||||
|
||||
This allows you output audio on the C6 pin (needs abstracting). See the [audio page](feature_audio.md) for more information.
|
||||
|
@@ -67,7 +67,7 @@ The `config.h` file is where you configure the hardware and feature set for your
|
||||
|
||||
At the top of the `config.h` you'll find USB related settings. These control how your keyboard appears to the Operating System. If you don't have a good reason to change you should leave the `VENDOR_ID` as `0xFEED`. For the `PRODUCT_ID` you should pick a number that is not yet in use.
|
||||
|
||||
Do change the `MANUFACTURER`, `PRODUCT`, and `DESCRIPTION` lines to accurately reflect your keyboard.
|
||||
Do change the `MANUFACTURER` and `PRODUCT` lines to accurately reflect your keyboard.
|
||||
|
||||
```c
|
||||
#define VENDOR_ID 0xFEED
|
||||
@@ -75,7 +75,6 @@ Do change the `MANUFACTURER`, `PRODUCT`, and `DESCRIPTION` lines to accurately r
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER You
|
||||
#define PRODUCT my_awesome_keyboard
|
||||
#define DESCRIPTION A custom keyboard
|
||||
```
|
||||
|
||||
?> Windows and macOS will display the `MANUFACTURER` and `PRODUCT` in the list of USB devices. `lsusb` on Linux instead takes these from the list maintained by the [USB ID Repository](http://www.linux-usb.org/usb-ids.html) by default. `lsusb -v` will show the values reported by the device, and they are also present in kernel logs after plugging it in.
|
||||
|
@@ -3,6 +3,25 @@
|
||||
Since starting, QMK has grown by leaps and bounds thanks to people like you who contribute to creating and maintaining our community keyboards. As we've grown we've discovered some patterns that work well, and ask that you conform to them to make it easier for other people to benefit from your hard work.
|
||||
|
||||
|
||||
## Use QMK Lint
|
||||
|
||||
We have provided a tool, `qmk lint`, which will let you check over your keyboard for problems. We suggest using it frequently while working on your keyboard and keymap.
|
||||
|
||||
Example passing check:
|
||||
|
||||
```
|
||||
$ qmk lint -kb rominronin/katana60/rev2
|
||||
Ψ Lint check passed!
|
||||
```
|
||||
|
||||
Example failing check:
|
||||
|
||||
```
|
||||
$ qmk lint -kb clueboard/66/rev3
|
||||
☒ Missing keyboards/clueboard/66/rev3/readme.md
|
||||
☒ Lint check failed!
|
||||
```
|
||||
|
||||
## Naming Your Keyboard/Project
|
||||
|
||||
All keyboard names are in lower case, consisting only of letters, numbers, and underscore (`_`). Names may not begin with an underscore. Forward slash (`/`) is used as a sub-folder separation character.
|
||||
@@ -192,7 +211,7 @@ When developing your keyboard, keep in mind that all warnings will be treated as
|
||||
|
||||
## Copyright Blurb
|
||||
|
||||
If you're adapting your keyboard's setup from another project, but not using the same code, but sure to update the copyright header at the top of the files to show your name, in this format:
|
||||
If you're adapting your keyboard's setup from another project, but not using the same code, be sure to update the copyright header at the top of the files to show your name, in this format:
|
||||
|
||||
Copyright 2017 Your Name <your@email.com>
|
||||
|
||||
|
@@ -81,8 +81,8 @@ STM32 MCUs allows a variety of pins to be configured as I2C pins depending on th
|
||||
|--------------------------|----------------------------------------------------------------------------------------------|---------|
|
||||
| `I2C1_SCL_BANK` | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`) to use for SCL | `GPIOB` |
|
||||
| `I2C1_SDA_BANK` | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`) to use for SDA | `GPIOB` |
|
||||
| `I2C1_SCL` | The pin number for the SCL pin (0-9) | `6` |
|
||||
| `I2C1_SDA` | The pin number for the SDA pin (0-9) | `7` |
|
||||
| `I2C1_SCL` | The pin number for the SCL pin (0-15) | `6` |
|
||||
| `I2C1_SDA` | The pin number for the SDA pin (0-15) | `7` |
|
||||
| `I2C1_BANK` (deprecated) | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`), superceded by `I2C1_SCL_BANK`, `I2C1_SDA_BANK` | `GPIOB` |
|
||||
|
||||
The ChibiOS I2C driver configuration depends on STM32 MCU:
|
||||
|
@@ -46,6 +46,7 @@
|
||||
'/unicode': '/feature_unicode',
|
||||
'/python_development': '/cli_development',
|
||||
'/getting_started_build_tools':'/newbs_getting_started',
|
||||
'/tutorial':'/newbs',
|
||||
},
|
||||
basePath: '/',
|
||||
name: 'QMK Firmware',
|
||||
|
@@ -21,3 +21,22 @@ The following functions can provide basic control of GPIOs and are found in `qua
|
||||
## Advanced Settings :id=advanced-settings
|
||||
|
||||
Each microcontroller can have multiple advanced settings regarding its GPIO. This abstraction layer does not limit the use of architecture-specific functions. Advanced users should consult the datasheet of their desired device and include any needed libraries. For AVR, the standard avr/io.h library is used; for STM32, the ChibiOS [PAL library](http://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used.
|
||||
|
||||
## Atomic Operation
|
||||
|
||||
The above functions are not always guaranteed to work atomically. Therefore, if you want to prevent interruptions in the middle of operations when using multiple combinations of the above functions, use the following `ATOMIC_BLOCK_FORCEON` macro.
|
||||
|
||||
eg.
|
||||
```c
|
||||
void some_function() {
|
||||
// some process
|
||||
ATOMIC_BLOCK_FORCEON {
|
||||
// Atomic Processing
|
||||
}
|
||||
// some process
|
||||
}
|
||||
```
|
||||
|
||||
`ATOMIC_BLOCK_FORCEON` forces interrupts to be disabled before the block is executed, without regard to whether they are enabled or disabled. Then, after the block is executed, the interrupt is enabled.
|
||||
|
||||
Note that `ATOMIC_BLOCK_FORCEON` can therefore be used if you know that interrupts are enabled before the execution of the block, or if you know that it is OK to enable interrupts at the completion of the block.
|
||||
|
@@ -141,7 +141,9 @@ To do this manually:
|
||||
|
||||
?> It's possible to use other bootloaders here in the same way, but __you need a bootloader__, otherwise you'll have to use ISP again to write new firmware to your keyboard.
|
||||
|
||||
To do this the easy way, you can flash the board using the `:production` target when compiling. This compiles the firmware, then compiles the QMK DFU bootloader, and then creates a combined image. Once this is done, you'll see three files:
|
||||
#### Create QMK DFU Bootloader and Production images
|
||||
|
||||
You can create the firmware, the QMK DFU Bootloader and the production firmware images for the board using the `:production` target when compiling. Once this is done, you'll see three files:
|
||||
* `<keyboard>_<keymap>.hex`
|
||||
* `<keyboard>_<keymap>_bootloader.hex`
|
||||
* `<keyboard>_<keymap>_production.hex`
|
||||
@@ -236,12 +238,12 @@ For Caterina on the `atmega32u4`, these are the fuse settings that you want:
|
||||
| Fuse | Setting|
|
||||
|----------|--------|
|
||||
| Low | `0xFF` |
|
||||
| High | `0xD9` |
|
||||
| Extended | `0xC3` |
|
||||
| High | `0xD8` |
|
||||
| Extended | `0xCB` |
|
||||
|
||||
To set this add `-U lfuse:w:0xFF:m -U hfuse:w:0xD8:m -U efuse:w:0xC3:m` to your command. So the final command should look something like:
|
||||
To set this add `-U lfuse:w:0xFF:m -U hfuse:w:0xD8:m -U efuse:w:0xCB:m` to your command. So the final command should look something like:
|
||||
|
||||
avrdude -c avrisp -P COM3 -p atmega32u4 -U flash:w:main.hex:i -U lfuse:w:0xFF:m -U hfuse:w:0xD8:m -U efuse:w:0xC3:m
|
||||
avrdude -c avrisp -P COM3 -p atmega32u4 -U flash:w:main.hex:i -U lfuse:w:0xFF:m -U hfuse:w:0xD8:m -U efuse:w:0xCB:m
|
||||
|
||||
|
||||
If you are using a different controller or want different configuration, you can use [this AVR Fuse Calculator](http://www.engbedded.com/fusecalc/) to find a better value for you.
|
||||
|
@@ -6,6 +6,7 @@
|
||||
* [テストとデバッグ](ja/newbs_testing_debugging.md)
|
||||
* [手助けを得る/サポート](ja/support.md)
|
||||
* [他のリソース](ja/newbs_learn_more_resources.md)
|
||||
* [シラバス](ja/syllabus.md)
|
||||
|
||||
* FAQ
|
||||
* [一般的な FAQ](ja/faq_general.md)
|
||||
@@ -33,7 +34,9 @@
|
||||
* [機能のカスタマイズ](ja/custom_quantum_functions.md)
|
||||
* [Zadig を使ったドライバのインストール](ja/driver_installation_zadig.md)
|
||||
* [キーマップの概要](ja/keymap.md)
|
||||
* [Vagrant のガイド](ja/getting_started_vagrant.md)
|
||||
* 開発環境
|
||||
* [Docker のガイド](ja/getting_started_docker.md)
|
||||
* [Vagrant のガイド](ja/getting_started_vagrant.md)
|
||||
* 書き込み
|
||||
* [書き込み](ja/flashing.md)
|
||||
* [ATmega32A の書き込み (ps2avrgb)](ja/flashing_bootloadhid.md)
|
||||
@@ -52,6 +55,7 @@
|
||||
* 単純なキーコード
|
||||
* [完全なリスト](ja/keycodes.md)
|
||||
* [基本的なキーコード](ja/keycodes_basic.md)
|
||||
* [言語固有のキーコード](ja/reference_keymap_extras.md)
|
||||
* [修飾キー](ja/feature_advanced_keycodes.md)
|
||||
* [Quantum キーコード](ja/quantum_keycodes.md)
|
||||
|
||||
@@ -72,9 +76,10 @@
|
||||
* [デバウンス API](ja/feature_debounce_type.md)
|
||||
* [キーロック](ja/feature_key_lock.md)
|
||||
* [レイヤー](ja/feature_layers.md)
|
||||
* [One Shot Keys](ja/one_shot_keys.md)
|
||||
* [ワンショットキー](ja/one_shot_keys.md)
|
||||
* [ポインティング デバイス](ja/feature_pointing_device.md)
|
||||
* [Swap Hands](ja/feature_swap_hands.md)
|
||||
* [ロー HID](ja/feature_rawhid.md)
|
||||
* [スワップハンド](ja/feature_swap_hands.md)
|
||||
* [タップダンス](ja/feature_tap_dance.md)
|
||||
* [タップホールド設定](ja/tap_hold.md)
|
||||
* [ターミナル](ja/feature_terminal.md)
|
||||
@@ -98,18 +103,21 @@
|
||||
* [DIP スイッチ](ja/feature_dip_switch.md)
|
||||
* [エンコーダ](ja/feature_encoders.md)
|
||||
* [触覚フィードバック](ja/feature_haptic_feedback.md)
|
||||
* [Proton C 規約](ja/proton_c_conversion.md)
|
||||
* [Proton C 変換](ja/proton_c_conversion.md)
|
||||
* [PS/2 マウス](ja/feature_ps2_mouse.md)
|
||||
* [分割キーボード](ja/feature_split_keyboard.md)
|
||||
* [Stenography](ja/feature_stenography.md)
|
||||
* [速記](ja/feature_stenography.md)
|
||||
* [感熱式プリンタ](ja/feature_thermal_printer.md)
|
||||
* [Velocikey](ja/feature_velocikey.md)
|
||||
|
||||
* QMK の開発
|
||||
* 破壊的な変更
|
||||
* [PR チェックリスト](ja/pr_checklist.md)
|
||||
* 互換性を破る変更/Breaking changes
|
||||
* [概要](ja/breaking_changes.md)
|
||||
* [プルリクエストにフラグが付けられた](ja/breaking_changes_instructions.md)
|
||||
* 履歴
|
||||
* [2020年8月29日](ja/ChangeLog/20200829.md)
|
||||
* [2020年5月30日](ja/ChangeLog/20200530.md)
|
||||
* [2020年2月29日](ja/ChangeLog/20200229.md)
|
||||
* [2019年8月30日](ja/ChangeLog/20190830.md)
|
||||
|
||||
@@ -124,7 +132,8 @@
|
||||
* [SPI ドライバ](ja/spi_driver.md)
|
||||
* [WS2812 ドライバ](ja/ws2812_driver.md)
|
||||
* [EEPROM ドライバ](ja/eeprom_driver.md)
|
||||
* [GPIO コントロール](ja/internals_gpio_control.md)
|
||||
* [シリアル ドライバ](ja/serial_driver.md)
|
||||
* [GPIO 制御](ja/internals_gpio_control.md)
|
||||
* [キーボード ガイドライン](ja/hardware_keyboard_guidelines.md)
|
||||
|
||||
* Python 開発
|
||||
@@ -136,6 +145,11 @@
|
||||
* [開発環境](ja/api_development_environment.md)
|
||||
* [アーキテクチャの概要](ja/api_development_overview.md)
|
||||
|
||||
* ハードウェアプラットフォーム開発
|
||||
* Arm/ChibiOS
|
||||
* [MCU の選択](ja/platformdev_selecting_arm_mcu.md)
|
||||
* [早期初期化](ja/platformdev_chibios_earlyinit.md)
|
||||
|
||||
* QMK Reference
|
||||
* [QMK への貢献](ja/contributing.md)
|
||||
* [QMK ドキュメントの翻訳](ja/translating.md)
|
||||
@@ -155,9 +169,9 @@
|
||||
|
||||
* QMK の内部詳細(作成中)
|
||||
* [定義](ja/internals_defines.md)
|
||||
* [Input Callback Reg](ja/internals_input_callback_reg.md)
|
||||
* [入力コールバック登録](ja/internals_input_callback_reg.md)
|
||||
* [Midi デバイス](ja/internals_midi_device.md)
|
||||
* [Midi デバイスのセットアップ手順](ja/internals_midi_device_setup_process.md)
|
||||
* [Midi ユーティリティ](ja/internals_midi_util.md)
|
||||
* [Send Functions](ja/internals_send_functions.md)
|
||||
* [Midi 送信関数](ja/internals_send_functions.md)
|
||||
* [Sysex Tools](ja/internals_sysex_tools.md)
|
||||
|
8
docs/ja/api_development_environment.md
Normal file
8
docs/ja/api_development_environment.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# 開発環境のセットアップ
|
||||
|
||||
<!---
|
||||
original document: 0.9.50:docs/api_development_environment.md
|
||||
git diff 0.9.50 HEAD -- docs/api_development_environment.md | cat
|
||||
-->
|
||||
|
||||
開発環境をセットアップするには、[qmk_web_stack](https://github.com/qmk/qmk_web_stack) に行ってください。
|
49
docs/ja/api_development_overview.md
Normal file
49
docs/ja/api_development_overview.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# QMK コンパイラ開発ガイド
|
||||
|
||||
<!---
|
||||
original document: 0.9.50:docs/api_development_overview.md
|
||||
git diff 0.9.50 HEAD -- docs/api_development_overview.md | cat
|
||||
-->
|
||||
|
||||
このページでは、開発者に QMK コンパイラを紹介しようと思います。コードを読まなければならないような核心となる詳細に立ち入って調べることはしません。ここで得られるものは、コードを読んで理解を深めるためのフレームワークです。
|
||||
|
||||
# 概要
|
||||
|
||||
QMK Compile API は、いくつかの可動部分からできています:
|
||||
|
||||

|
||||
|
||||
API クライアントは API サービスと排他的にやりとりをします。ここでジョブをサブミットし、状態を調べ、結果をダウンロードします。API サービスはコンパイルジョブを [Redis Queue](https://python-rq.org) に挿入し、それらのジョブの結果について RQ と S3 の両方を調べます。
|
||||
|
||||
ワーカーは RQ から新しいコンパイルジョブを取り出し、ソースとバイナリを S3 互換のストレージエンジンにアップロードします。
|
||||
|
||||
# ワーカー
|
||||
|
||||
QMK コンパイラワーカーは実際のビルド作業に責任を持ちます。ワーカーは RQ からジョブを取り出し、ジョブを完了するためにいくつかの事を行います:
|
||||
|
||||
* 新しい qmk_firmware のチェックアウトを作成する
|
||||
* 指定されたレイヤーとキーボードメタデータを使って `keymap.c` をビルドする
|
||||
* ファームウェアをビルドする
|
||||
* ソースのコピーを zip 形式で圧縮する
|
||||
* ファームウェア、ソースの zip ファイル、メタデータファイルを S3 にアップロードする
|
||||
* ジョブの状態を RQ に送信する
|
||||
|
||||
# API サービス
|
||||
|
||||
API サービスは比較的単純な Flask アプリケーションです。理解しておくべきことが幾つかあります。
|
||||
|
||||
## @app.route('/v1/compile', methods=['POST'])
|
||||
|
||||
これは API の主なエントリーポイントです。クライアントとのやりとりはここから開始されます。クライアントはキーボードを表す JSON ドキュメントを POST し、API はコンパイルジョブをサブミットする前にいくらかの(とても)基本的な検証を行います。
|
||||
|
||||
## @app.route('/v1/compile/<string:job_id>', methods=['GET'])
|
||||
|
||||
これは最もよく呼ばれるエンドポイントです。ジョブの詳細が redis から利用可能であればそれを取り出し、そうでなければ S3 からキャッシュされたジョブの詳細を取り出します。
|
||||
|
||||
## @app.route('/v1/compile/<string:job_id>/download', methods=['GET'])
|
||||
|
||||
このメソッドによりユーザはコンパイルされたファームウェアファイルをダウンロードすることができます。
|
||||
|
||||
## @app.route('/v1/compile/<string:job_id>/source', methods=['GET'])
|
||||
|
||||
このメソッドによりユーザはファームウェアのソースをダウンロードすることができます。
|
73
docs/ja/api_docs.md
Normal file
73
docs/ja/api_docs.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# QMK API
|
||||
|
||||
<!---
|
||||
original document: 0.9.50:docs/api_docs.md
|
||||
git diff 0.9.50 HEAD -- docs/api_docs.md | cat
|
||||
-->
|
||||
|
||||
このページは QMK API の使い方を説明します。もしあなたがアプリケーション開発者であれば、全ての [QMK](https://qmk.fm) キーボードのファームウェアをコンパイルするために、この API を使うことができます。
|
||||
|
||||
## 概要
|
||||
|
||||
このサービスは、カスタムキーマップをコンパイルするための非同期 API です。API に 何らかの JSON を POST し、定期的に状態をチェックし、ファームウェアのコンパイルが完了していれば、結果のファームウェアと(もし希望すれば)そのファームウェアのソースコードをダウンロードすることができます。
|
||||
|
||||
#### JSON ペイロードの例:
|
||||
|
||||
```json
|
||||
{
|
||||
"keyboard": "clueboard/66/rev2",
|
||||
"keymap": "my_awesome_keymap",
|
||||
"layout": "LAYOUT_all",
|
||||
"layers": [
|
||||
["KC_GRV","KC_1","KC_2","KC_3","KC_4","KC_5","KC_6","KC_7","KC_8","KC_9","KC_0","KC_MINS","KC_EQL","KC_GRV","KC_BSPC","KC_PGUP","KC_TAB","KC_Q","KC_W","KC_E","KC_R","KC_T","KC_Y","KC_U","KC_I","KC_O","KC_P","KC_LBRC","KC_RBRC","KC_BSLS","KC_PGDN","KC_CAPS","KC_A","KC_S","KC_D","KC_F","KC_G","KC_H","KC_J","KC_K","KC_L","KC_SCLN","KC_QUOT","KC_NUHS","KC_ENT","KC_LSFT","KC_NUBS","KC_Z","KC_X","KC_C","KC_V","KC_B","KC_N","KC_M","KC_COMM","KC_DOT","KC_SLSH","KC_RO","KC_RSFT","KC_UP","KC_LCTL","KC_LGUI","KC_LALT","KC_MHEN","KC_SPC","KC_SPC","KC_HENK","KC_RALT","KC_RCTL","MO(1)","KC_LEFT","KC_DOWN","KC_RIGHT"],
|
||||
["KC_ESC","KC_F1","KC_F2","KC_F3","KC_F4","KC_F5","KC_F6","KC_F7","KC_F8","KC_F9","KC_F10","KC_F11","KC_F12","KC_TRNS","KC_DEL","BL_STEP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","_______","KC_TRNS","KC_PSCR","KC_SLCK","KC_PAUS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_PGUP","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_LEFT","KC_PGDN","KC_RGHT"],
|
||||
["KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","RESET","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(2)","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","KC_TRNS","MO(1)","KC_TRNS","KC_TRNS","KC_TRNS"]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
ご覧のとおり、ペイロードにはファームウェアを作成および生成するために必要なキーボードの全ての側面を記述します。各レイヤーは QMK キーコードの1つのリストで、キーボードの `LAYOUT` マクロと同じ長さです。もしキーボードが複数の `LAYOUT` マクロをサポートする場合、どのマクロを使うかを指定することができます。
|
||||
|
||||
## コンパイルジョブのサブミット
|
||||
|
||||
キーマップをファームウェアにコンパイルするには、単純に JSON を `/v1/compile` エンドポイントに POST します。以下の例では、JSON ペイロードを `json_data` という名前のファイルに配置しています。
|
||||
|
||||
```
|
||||
$ curl -H "Content-Type: application/json" -X POST -d "$(< json_data)" http://api.qmk.fm/v1/compile
|
||||
{
|
||||
"enqueued": true,
|
||||
"job_id": "ea1514b3-bdfc-4a7b-9b5c-08752684f7f6"
|
||||
}
|
||||
```
|
||||
|
||||
## 状態のチェック
|
||||
|
||||
キーマップをサブミットした後で、簡単な HTTP GET 呼び出しを使って状態をチェックすることができます:
|
||||
|
||||
```
|
||||
$ curl http://api.qmk.fm/v1/compile/ea1514b3-bdfc-4a7b-9b5c-08752684f7f6
|
||||
{
|
||||
"created_at": "Sat, 19 Aug 2017 21:39:12 GMT",
|
||||
"enqueued_at": "Sat, 19 Aug 2017 21:39:12 GMT",
|
||||
"id": "f5f9b992-73b4-479b-8236-df1deb37c163",
|
||||
"status": "running",
|
||||
"result": null
|
||||
}
|
||||
```
|
||||
|
||||
これは、ジョブをキューに入れることに成功し、現在実行中であることを示しています。5つの状態がありえます:
|
||||
|
||||
* **failed**: なんらかの理由でコンパイルサービスが失敗しました。
|
||||
* **finished**: コンパイルが完了し、結果を見るには `result` をチェックする必要があります。
|
||||
* **queued**: キーマップはコンパイルサーバが利用可能になるのを待っています。
|
||||
* **running**: コンパイルが進行中で、まもなく完了するはずです。
|
||||
* **unknown**: 深刻なエラーが発生し、[バグを報告](https://github.com/qmk/qmk_compiler/issues)する必要があります。
|
||||
|
||||
## 完了した結果を検証
|
||||
|
||||
コンパイルジョブが完了したら、`result` キーをチェックします。このキーの値は幾つかの情報を含むハッシュです:
|
||||
|
||||
* `firmware_binary_url`: 書き込み可能なファームウェアの URL のリスト
|
||||
* `firmware_keymap_url`: `keymap.c` の URL のリスト
|
||||
* `firmware_source_url`: ファームウェアの完全なソースコードの URL のリスト
|
||||
* `output`: このコンパイルジョブの stdout と stderr。エラーはここで見つけることができます。
|
20
docs/ja/api_overview.md
Normal file
20
docs/ja/api_overview.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# QMK API
|
||||
|
||||
<!---
|
||||
original document: 0.9.50:docs/api_overview.md
|
||||
git diff 0.9.50 HEAD -- docs/api_overview.md | cat
|
||||
-->
|
||||
|
||||
QMK API は、Web と GUI ツールが [QMK](http://qmk.fm/) によってサポートされるキーボード用の任意のキーマップをコンパイルするために使うことができる、非同期 API を提供します。標準のキーマップテンプレートは、C コードのサポートを必要としない全ての QMK キーコードをサポートします。キーボードのメンテナは独自のカスタムテンプレートを提供して、より多くの機能を実現することができます。
|
||||
|
||||
## アプリケーション開発者
|
||||
|
||||
もしあなたがアプリケーションでこの API を使うことに興味があるアプリケーション開発者であれば、[API の使用](ja/api_docs.md) に行くべきです。
|
||||
|
||||
## キーボードのメンテナ
|
||||
|
||||
もし QMK Compiler API でのあなたのキーボードのサポートを強化したい場合は、[キーボードサポート](ja/reference_configurator_support.md) の節に行くべきです。
|
||||
|
||||
## バックエンド開発者
|
||||
|
||||
もし API 自体に取り組むことに興味がある場合は、[開発環境](ja/api_development_environment.md)のセットアップから始め、それから [API のハッキング](ja/api_development_overview.md) を調べるべきです。
|
121
docs/ja/breaking_changes.md
Normal file
121
docs/ja/breaking_changes.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Breaking changes/互換性を破る変更
|
||||
|
||||
<!---
|
||||
grep --no-filename "^[ ]*git diff" docs/ja/*.md | sh
|
||||
original document: 0.10.33:docs/breaking_changes.md
|
||||
git diff 0.10.33 HEAD -- docs/breaking_changes.md | cat
|
||||
-->
|
||||
|
||||
このドキュメントは QMK の互換性を破る変更(Breaking change) のプロセスについて説明します。
|
||||
互換性を破る変更とは、互換性がなかったり潜在的な危険が生じるように QMK の動作を変える変更を指します。
|
||||
ユーザが QMK ツリーを更新しても自分のキーマップが壊れない事を確信できるように、これらの変更を制限します。(訳注:以後、原文のまま Breaking change を用語として使用します。)
|
||||
|
||||
Breaking change ピリオドとは、危険な変更、または予想外の変更を QMK へ行なう PR をマージする時のことです。
|
||||
付随するテスト期間があるため、問題が起きることはまれか、有りえないと確信しています。
|
||||
|
||||
## 過去の Breaking change には何が含まれますか?
|
||||
|
||||
* [2020年8月29日](ja/ChangeLog/20200829.md)
|
||||
* [2020年5月30日](ja/ChangeLog/20200530.md)
|
||||
* [2020年2月29日](ja/ChangeLog/20200229.md)
|
||||
* [2019年8月30日](ja/ChangeLog/20190830.md)
|
||||
|
||||
## 次の Breaking change はいつですか?
|
||||
|
||||
次の Breaking change は2020年11月28日に予定されています。
|
||||
|
||||
### 重要な日付
|
||||
|
||||
* [x] 2020年 8月29日 - `develop` が作成されました。毎週リベースされます。
|
||||
* [ ] 2020年10月31日 - `develop` は新しいPRを取り込みません。
|
||||
* [ ] 2020年10月31日 - テスターの募集。
|
||||
* [ ] 2020年11月26日 - `master`がロックされ、PR はマージされません。
|
||||
* [ ] 2020年11月28日 - `develop` を `master` にマージします。
|
||||
* [ ] 2020年11月28日 - `master` のロックが解除されます。PR を再びマージすることができます。
|
||||
|
||||
## どのような変更が含まれますか?
|
||||
|
||||
最新の Breaking change 候補を見るには、[`breaking_change` ラベル](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+label%3Abreaking_change+is%3Apr)を参照してください。
|
||||
現在から `develop` が閉じられるまでの間に新しい変更が追加される可能性があり、そのラベルが適用された PR はマージされることは保証されていません。
|
||||
|
||||
このラウンドに、あなたの Breaking change を含めたい場合は、`breaking_change` ラベルを持つ PR を作成し、`develop` が閉じる前に承認してもらう必要があります。
|
||||
`develop` が閉じた後は、新しい Breaking change は受け付けられません。
|
||||
|
||||
受け入れの基準:
|
||||
|
||||
* PR が完了し、マージの準備ができている
|
||||
* PR が ChangeLog を持つ
|
||||
|
||||
# チェックリスト
|
||||
|
||||
ここでは、Breaking change プロセスを実行する時に使用する様々なプロセスについて説明します。
|
||||
|
||||
## `master` から `develop` をリベースします
|
||||
|
||||
これは `develop` が開いている間、毎週金曜日に実行されます。
|
||||
|
||||
プロセス:
|
||||
|
||||
```
|
||||
cd qmk_firmware
|
||||
git checkout master
|
||||
git pull --ff-only
|
||||
git checkout develop
|
||||
git rebase master
|
||||
git push --force
|
||||
```
|
||||
|
||||
## `develop` ブランチの作成
|
||||
|
||||
以前の `develop` ブランチがマージされた直後に、これが発生します。
|
||||
|
||||
* `qmk_firmware` git commands
|
||||
* [ ] `git checkout master`
|
||||
* [ ] `git pull --ff-only`
|
||||
* [ ] `git checkout -b develop`
|
||||
* [ ] Edit `readme.md`
|
||||
* [ ] これがテストブランチであることを上部に大きな通知で追加します。
|
||||
* [ ] このドキュメントへのリンクを含めます
|
||||
* [ ] `git commit -m 'Branch point for <DATE> Breaking Change'`
|
||||
* [ ] `git tag breakpoint_<YYYY>_<MM>_<DD>`
|
||||
* [ ] `git tag <next_version>` # ブレーキング ポイント タグがバージョンの増分を混乱させないようにします
|
||||
* [ ] `git push origin develop`
|
||||
* [ ] `git push --tags`
|
||||
|
||||
## マージの 4 週間前
|
||||
|
||||
* `develop` は新しい PR に対して閉じられ、現在の PR の修正のみがマージされる可能性があります。
|
||||
* テスターの呼び出しを投稿します
|
||||
* [ ] Discord
|
||||
* [ ] GitHub PR
|
||||
* [ ] https://reddit.com/r/olkb
|
||||
|
||||
## マージの 1 週間前
|
||||
|
||||
* master が < 2 日前> から <マージの日> まで閉じられることを発表します
|
||||
* [ ] Discord
|
||||
* [ ] GitHub PR
|
||||
* [ ] https://reddit.com/r/olkb
|
||||
|
||||
## マージの 2 日前
|
||||
|
||||
* master が 2 日間閉じられることを発表します
|
||||
* [ ] Discord
|
||||
* [ ] GitHub PR
|
||||
* [ ] https://reddit.com/r/olkb
|
||||
|
||||
## マージの日
|
||||
|
||||
* `qmk_firmware` git commands
|
||||
* [ ] `git checkout develop`
|
||||
* [ ] `git pull --ff-only`
|
||||
* [ ] `git rebase origin/master`
|
||||
* [ ] Edit `readme.md`
|
||||
* [ ] `develop` についてのメモを削除
|
||||
* [ ] ChangeLog を 1 つのファイルにまとめます。
|
||||
* [ ] `git commit -m 'Merge point for <DATE> Breaking Change'`
|
||||
* [ ] `git push origin develop`
|
||||
* GitHub Actions
|
||||
* [ ] `develop`の PR を作成します
|
||||
* [ ] travis がクリーンに戻ったことを確認します
|
||||
* [ ] `develop` PR をマージします
|
51
docs/ja/breaking_changes_instructions.md
Normal file
51
docs/ja/breaking_changes_instructions.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# breaking changes/互換性を破る変更: プルリクエストにフラグが付けられた
|
||||
|
||||
<!---
|
||||
grep --no-filename "^[ ]*git diff" docs/ja/*.md | sh
|
||||
original document: 0.9.0:docs/breaking_changes_instructions.md
|
||||
git diff 0.9.0 HEAD -- docs/breaking_changes_instructions.md | cat
|
||||
-->
|
||||
|
||||
QMK のメンバーがあなたのプルリクエストに返信し、あなたの提出したものは Breaking change (互換性を破る変更) であると述べている場合があります。メンバーの判断では、あなたが提案した変更は QMK やその利用者にとってより大きな影響を持つと考えられます。
|
||||
|
||||
プルリクエストにフラグが立てられる原因となるものには、以下のようなものがあります:
|
||||
|
||||
- **ユーザーのキーマップに対する編集**
|
||||
ユーザーが自分のキーマップを QMK に提出した後、しばらくしてさらに更新してプルリクエストを開いたところ、それが `qmk/qmk_firmware` リポジトリで編集されていたためにマージできなかったことに気づくことがあるかもしれません。すべてのユーザーが Git や GitHub を使いこなせるわけではないので、ユーザー自身で問題を修正できないことに気づくかもしれません。
|
||||
- **期待される動作の変更**
|
||||
QMK の動作を変更すると、既存の QMK 機能への変更を組み込んだ新しいファームウェアをフラッシュした場合、ユーザはハードウェアまたは QMK が壊れていると考え、希望する動作を復元する手段がないことに気付くことがあります。
|
||||
- **ユーザーのアクションを必要とする変更**
|
||||
変更には、ツールチェインを更新したり、Git で何らかのアクションを取るなど、ユーザーがアクションを行う必要がある場合もあります。
|
||||
- **精査が必要な変更**
|
||||
時には、投稿がプロジェクトとしての QMK に影響を与えることもあります。これは、著作権やライセンスの問題、コーディング規約、大規模な機能のオーバーホール、コミュニティによるより広範なテストを必要とする「リスクの高い」変更、あるいは全く別のものである可能性があります。
|
||||
- **エンドユーザーとのコミュニケーションを必要とする変更**
|
||||
これには、将来の非推奨化への警告、時代遅れの慣習、その他伝えなければならないが上記のカテゴリのどれかに当てはまらないものが含まれます。
|
||||
|
||||
## 何をすればいいのか?
|
||||
|
||||
提出したものが Breaking change だと判断された場合、手続きをスムーズに進めるためにできることがいくつかあります。
|
||||
|
||||
### PR を分割することを検討する
|
||||
|
||||
あなたがコアコードを投稿していて、それが Breaking change プロセスを経る必要がある唯一の理由が、あなたの変更に合わせてキーマップを更新していることである場合、古いキーマップが機能し続けるような方法であなたの機能を投稿できるかどうかを検討してください。
|
||||
そののち、Breaking change プロセスを経て古いコードを削除する別の PR を提出してください。
|
||||
|
||||
### ChangeLog エントリの提供
|
||||
|
||||
Breaking change プロセスを経て提出する際には、変更ログのエントリを含めることを我々は要請します。
|
||||
エントリーは、あなたのプルリクエストが行う変更の短い要約としてください – [ここの各セクションは changelog として開始されました](ja/ChangeLog/20190830.md "n.b. This should link to the 2019 Aug 30 Breaking Changes doc - @noroadsleft")。
|
||||
|
||||
変更ログは `docs/ChangeLog/YYYYMMDD/PR####.md` に置いてください。
|
||||
ここで、`YYYYMMDD` は QMK の breaking change ブランチ – 通常は `develop` という名称 – が `master` ブランチにマージされる日付、`####` はプルリクエストの番号です。
|
||||
|
||||
ユーザー側でのアクションを必要とする場合、あなたの変更ログは、どのようなアクションを取らなければならないかをユーザーに指示するか、そのようなアクションを指示する場所にリンクする必要があります。
|
||||
|
||||
### 変更点を文書化する
|
||||
|
||||
提出物の目的を理解し、それが必要とする可能性のある意味合いやアクションを理解することで、レビュープロセスをより簡単にすることができます。この目的のためには変更履歴で十分かもしれませんが、より広範囲の変更を行う場合には、変更履歴には不向きな詳細レベルが必要になるかもしれません。
|
||||
|
||||
あなたのプルリクエストにコメントしたり、質問やコメント、変更要求に対応したりすることは、非常にありがたいことです。
|
||||
|
||||
### 助けを求める
|
||||
|
||||
あなたの提出物にフラグが立ったことで、あなたはびっくりしてしまったかもしれません。もし、あなた自身が脅されたり、圧倒されたりしていると感じたら、私たちに知らせてください。プルリクエストにコメントするか、[Discord で QMK チームに連絡を取ってください](https://discord.gg/Uq7gcHh)。
|
@@ -1,8 +1,8 @@
|
||||
# QMK CLI :id=qmk-cli
|
||||
|
||||
<!---
|
||||
original document: 0.8.58:docs/cli.md
|
||||
git diff 0.8.58 HEAD -- docs/cli.md | cat
|
||||
original document: 0.9.19:docs/cli.md
|
||||
git diff 0.9.19 HEAD -- docs/cli.md | cat
|
||||
-->
|
||||
|
||||
## 概要 :id=overview
|
||||
@@ -11,25 +11,24 @@ QMK CLI を使用すると QMK キーボードの構築と作業が簡単にな
|
||||
|
||||
### 必要事項 :id=requirements
|
||||
|
||||
CLI は Python 3.5 以上を必要とします。我々は必要事項の数を少なくしようとしていますが、[`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt) に列挙されているパッケージもインストールする必要があります。これらは QMK CLI をインストールするときに自動的にインストールされます。
|
||||
QMK は Python 3.6 以上を必要とします。我々は必要事項の数を少なくしようとしていますが、[`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt) に列挙されているパッケージもインストールする必要があります。これらは QMK CLI をインストールするときに自動的にインストールされます。
|
||||
|
||||
### Homebrew を使ったインストール (macOS、いくつかの Linux) :id=install-using-homebrew
|
||||
|
||||
[Homebrew](https://brew.sh) をインストールしている場合は、タップして QMK をインストールすることができます:
|
||||
|
||||
```
|
||||
brew tap qmk/qmk
|
||||
brew install qmk
|
||||
brew install qmk/qmk/qmk
|
||||
export QMK_HOME='~/qmk_firmware' # オプション、`qmk_firmware` の場所を設定します
|
||||
qmk setup # これは `qmk/qmk_firmware` をクローンし、オプションでビルド環境をセットアップします
|
||||
```
|
||||
|
||||
### easy_install あるいは pip を使ってインストール :id=install-using-easy_install-or-pip
|
||||
### pip を使ってインストール :id=install-using-easy_install-or-pip
|
||||
|
||||
上のリストにあなたのシステムがない場合は、QMK を手動でインストールすることができます。最初に、python 3.5 (以降)をインストールしていて、pip をインストールしていることを確認してください。次に以下のコマンドを使って QMK をインストールします:
|
||||
上で列挙した中にあなたのシステムがない場合は、QMK を手動でインストールすることができます。最初に、python 3.6 (以降)をインストールしていて、pip をインストールしていることを確認してください。次に以下のコマンドを使って QMK をインストールします:
|
||||
|
||||
```
|
||||
pip3 install qmk
|
||||
python3 -m pip install qmk
|
||||
export QMK_HOME='~/qmk_firmware' # オプション、`qmk_firmware` の場所を設定します
|
||||
qmk setup # これは `qmk/qmk_firmware` をクローンし、オプションでビルド環境をセットアップします
|
||||
```
|
||||
|
@@ -1,48 +1,18 @@
|
||||
# QMK CLI コマンド
|
||||
|
||||
<!---
|
||||
original document: 0.8.58:docs/cli.md
|
||||
git diff 0.8.58 HEAD -- docs/cli.md | cat
|
||||
original document: 0.9.19:docs/cli_command.md
|
||||
git diff 0.9.19 HEAD -- docs/cli_command.md | cat
|
||||
-->
|
||||
|
||||
# CLI コマンド
|
||||
|
||||
## `qmk cformat`
|
||||
|
||||
このコマンドは clang-format を使って C コードを整形します。
|
||||
|
||||
引数無しで実行すると、変更された全てのコアコードを整形します。デフォルトでは `git diff` で `origin/master` をチェックし、ブランチは `-b <branch_name>` を使って変更できます。
|
||||
|
||||
`-a` で全てのコアコードを整形するか、コマンドラインでファイル名を渡して特定のファイルに対して実行します。
|
||||
|
||||
**指定したファイルに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat [file1] [file2] [...] [fileN]
|
||||
```
|
||||
|
||||
**全てのコアファイルに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat -a
|
||||
```
|
||||
|
||||
**origin/master で変更されたファイルのみに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat
|
||||
```
|
||||
|
||||
**branch_name で変更されたファイルのみに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat -b branch_name
|
||||
```
|
||||
# ユーザー用コマンド
|
||||
|
||||
## `qmk compile`
|
||||
|
||||
このコマンドにより、任意のディレクトリからファームウェアをコンパイルすることができます。<https://config.qmk.fm> からエクスポートした JSON をコンパイルするか、リポジトリ内でキーマップをコンパイルするか、現在の作業ディレクトリでキーボードをコンパイルすることができます。
|
||||
|
||||
このコマンドはディレクトリを認識します。キーボードやキーマップのディレクトリにいる場合、自動的に KEYBOARD や KEYMAP を入力します。
|
||||
|
||||
**Configurator Exports での使い方**:
|
||||
|
||||
```
|
||||
@@ -113,6 +83,8 @@ $ qmk compile -kb dz60
|
||||
このコマンドは `qmk compile` に似ていますが、ブートローダを対象にすることもできます。ブートローダはオプションで、デフォルトでは `:flash` に設定されています。
|
||||
違うブートローダを指定するには、`-bl <bootloader>` を使ってください。利用可能なブートローダの詳細については、[ファームウェアを書き込む](ja/flashing.md)を見てください。
|
||||
|
||||
このコマンドはディレクトリを認識します。キーボードやキーマップのディレクトリにいる場合、自動的に KEYBOARD や KEYMAP を入力します。
|
||||
|
||||
**Configurator Exports での使い方**:
|
||||
|
||||
```
|
||||
@@ -141,16 +113,6 @@ qmk flash -b
|
||||
qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN]
|
||||
```
|
||||
|
||||
## `qmk docs`
|
||||
|
||||
このコマンドは、ドキュメントを参照または改善するために使うことができるローカル HTTP サーバを起動します。デフォルトのポートは 8936 です。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk docs [-p PORT]
|
||||
```
|
||||
|
||||
## `qmk doctor`
|
||||
|
||||
このコマンドは環境を調査し、潜在的なビルドあるいは書き込みの問題について警告します。必要に応じてそれらの多くを修正できます。
|
||||
@@ -175,6 +137,32 @@ qmk doctor [-y] [-n]
|
||||
|
||||
qmk doctor -n
|
||||
|
||||
## `qmk info`
|
||||
|
||||
QMK のキーボードやキーマップに関する情報を表示します。キーボードに関する情報を取得したり、レイアウトを表示したり、基礎となるキーマトリックスを表示したり、JSON キーマップをきれいに印刷したりするのに使用できます。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk info [-f FORMAT] [-m] [-l] [-km KEYMAP] [-kb KEYBOARD]
|
||||
```
|
||||
|
||||
このコマンドはディレクトリを認識します。キーボードやキーマップのディレクトリにいる場合、自動的に KEYBOARD や KEYMAP を入力します。
|
||||
|
||||
**例**:
|
||||
|
||||
キーボードの基本情報を表示する:
|
||||
|
||||
qmk info -kb planck/rev5
|
||||
|
||||
キーボードのマトリクスを表示する:
|
||||
|
||||
qmk info -kb ergodox_ez -m
|
||||
|
||||
キーボードの JSON キーマップを表示する:
|
||||
|
||||
qmk info -kb clueboard/california -km default
|
||||
|
||||
## `qmk json2c`
|
||||
|
||||
QMK Configurator からエクスポートしたものから keymap.c を生成します。
|
||||
@@ -185,6 +173,86 @@ QMK Configurator からエクスポートしたものから keymap.c を生成
|
||||
qmk json2c [-o OUTPUT] filename
|
||||
```
|
||||
|
||||
## `qmk list-keyboards`
|
||||
|
||||
このコマンドは現在 `qmk_firmware` で定義されている全てのキーボードを列挙します。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk list-keyboards
|
||||
```
|
||||
|
||||
## `qmk list-keymaps`
|
||||
|
||||
このコマンドは指定されたキーボード(とリビジョン)の全てのキーマップを列挙します。
|
||||
|
||||
このコマンドはディレクトリを認識します。キーボードのディレクトリにいる場合、自動的に KEYBOARD を入力します。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk list-keymaps -kb planck/ez
|
||||
```
|
||||
|
||||
## `qmk new-keymap`
|
||||
|
||||
このコマンドは、キーボードの既存のデフォルトのキーマップに基づいて新しいキーマップを作成します。
|
||||
|
||||
このコマンドはディレクトリを認識します。キーボードやキーマップのディレクトリにいる場合、自動的に KEYBOARD や KEYMAP を入力します。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk new-keymap [-kb KEYBOARD] [-km KEYMAP]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 開発者用コマンド
|
||||
|
||||
## `qmk cformat`
|
||||
|
||||
このコマンドは clang-format を使って C コードを整形します。
|
||||
|
||||
引数無しで実行すると、変更された全てのコアコードを整形します。デフォルトでは `git diff` で `origin/master` をチェックし、ブランチは `-b <branch_name>` を使って変更できます。
|
||||
|
||||
`-a` で全てのコアコードを整形するか、コマンドラインでファイル名を渡して特定のファイルに対して実行します。
|
||||
|
||||
**指定したファイルに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat [file1] [file2] [...] [fileN]
|
||||
```
|
||||
|
||||
**全てのコアファイルに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat -a
|
||||
```
|
||||
|
||||
**origin/master で変更されたファイルのみに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat
|
||||
```
|
||||
|
||||
**branch_name で変更されたファイルのみに対する使い方**:
|
||||
|
||||
```
|
||||
qmk cformat -b branch_name
|
||||
```
|
||||
|
||||
## `qmk docs`
|
||||
|
||||
このコマンドは、ドキュメントを参照または改善するために使うことができるローカル HTTP サーバを起動します。デフォルトのポートは 8936 です。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk docs [-p PORT]
|
||||
```
|
||||
|
||||
## `qmk kle2json`
|
||||
|
||||
このコマンドにより、生の KLE データから QMK Configurator の JSON へ変換することができます。絶対パスあるいは現在のディレクトリ内のファイル名のいずれかを受け取ります。デフォルトでは、`info.json` が既に存在している場合は上書きしません。上書きするには、`-f` あるいは `--force` フラグを使ってください。
|
||||
@@ -207,36 +275,6 @@ $ qmk kle2json -f kle.txt -f
|
||||
Ψ Wrote out to info.json
|
||||
```
|
||||
|
||||
## `qmk list-keyboards`
|
||||
|
||||
このコマンドは現在 `qmk_firmware` で定義されている全てのキーボードを列挙します。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk list-keyboards
|
||||
```
|
||||
|
||||
## `qmk list-keymaps`
|
||||
|
||||
このコマンドは指定されたキーボード(とリビジョン)の全てのキーマップを列挙します。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk list-keymaps -kb planck/ez
|
||||
```
|
||||
|
||||
## `qmk new-keymap`
|
||||
|
||||
このコマンドは、キーボードの既存のデフォルトのキーマップに基づいて新しいキーマップを作成します。
|
||||
|
||||
**使用法**:
|
||||
|
||||
```
|
||||
qmk new-keymap [-kb KEYBOARD] [-km KEYMAP]
|
||||
```
|
||||
|
||||
## `qmk pyformat`
|
||||
|
||||
このコマンドは `qmk_firmware` 内の python コードを整形します。
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# QMK CLI 設定
|
||||
|
||||
<!---
|
||||
original document: d598f01cb:docs/cli_configuration.md
|
||||
git diff d598f01cb HEAD -- docs/cli_configuration.md | cat
|
||||
original document: 0.9.0:docs/cli_configuration.md
|
||||
git diff 0.9.0 HEAD -- docs/cli_configuration.md | cat
|
||||
-->
|
||||
|
||||
このドキュメントは `qmk config` がどのように動作するかを説明します。
|
||||
|
223
docs/ja/cli_development.md
Normal file
223
docs/ja/cli_development.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# QMK CLI 開発
|
||||
|
||||
<!---
|
||||
original document: 0.9.19:docs/cli_development.md
|
||||
git diff 0.9.19 HEAD -- docs/cli_development.md | cat
|
||||
-->
|
||||
|
||||
このドキュメントは、新しい `qmk` サブコマンドを書きたい開発者に役立つ情報が含まれています。
|
||||
|
||||
# 概要
|
||||
|
||||
QMK CLI は git で有名になったサブコマンドパターンを使って動作します。メインの `qmk` スクリプトは単に環境をセットアップし、実行する正しいエントリポイントを選択するためにあります。各サブコマンドは、何らかのアクションを実行しシェルのリターンコード、または None を返すエントリーポイント (`@cli.subcommand()` で修飾されます)を備えた自己完結型のモジュールです。
|
||||
|
||||
## 開発者モード:
|
||||
|
||||
キーボードを保守、あるいは QMK に貢献したい場合は、CLI の「開発者」モードを有効にすることができます:
|
||||
|
||||
`qmk config user.developer=True`
|
||||
|
||||
これにより利用可能な全てのサブコマンドが表示されます。
|
||||
**注意:** 追加で必要なものをインストールする必要があります:
|
||||
```bash
|
||||
python3 -m pip install -r requirements-dev.txt
|
||||
```
|
||||
|
||||
# サブコマンド
|
||||
|
||||
[MILC](https://github.com/clueboard/milc) は、`qmk` が引数の解析、設定、ログ、およびほかの多くの機能を処理するために使用する CLI フレームワークです。グルーコードを書くために時間を無駄にすることなく、ツールの作成に集中できます。
|
||||
|
||||
ローカル CLI 内のサブコマンドは、常に `qmk_firmware/lib/python/qmk/cli` で見つかります。
|
||||
|
||||
サブコマンドの例を見てみましょう。これは `lib/python/qmk/cli/hello.py` です:
|
||||
|
||||
```python
|
||||
"""QMK Python Hello World
|
||||
|
||||
This is an example QMK CLI script.
|
||||
"""
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.argument('-n', '--name', default='World', help='Name to greet.')
|
||||
@cli.subcommand('QMK Hello World.')
|
||||
def hello(cli):
|
||||
"""Log a friendly greeting.
|
||||
"""
|
||||
cli.log.info('Hello, %s!', cli.config.hello.name)
|
||||
```
|
||||
|
||||
最初に `milc` から `cli` をインポートします。これが、ユーザとやり取りをし、スクリプトの挙動を制御する方法です。`@cli.argument()` を使って、コマンドラインフラグ `--name` を定義します。これは、ユーザが設定できる `hello.name` (そして対応する `user.name`) という名前の設定変数も作成し、引数を指定する必要が無くなります。`cli.subcommand()` デコレータは、この関数をサブコマンドとして指定します。サブコマンドの名前は関数の名前から取られます。
|
||||
|
||||
関数の中に入ると、典型的な "Hello, World!" プログラムが見つかります。`cli.log` を使って、基礎となる [ロガーオブジェクト](https://docs.python.org/3.6/library/logging.html#logger-objects) にアクセスし、その挙動はユーザが制御できます。またユーザが指定した名前の値に `cli.config.hello.name` でアクセスします。`cli.config.hello.name` の値は、ユーザが指定した `--name` 引数を調べることで決定されます。指定されていない場合、`qmk.ini` 設定ファイルの中の値が使われ、どちらも指定されていない場合は `cli.argument()` デコレータで指定されたデフォルトが代用されます。
|
||||
|
||||
# ユーザとの対話処理
|
||||
|
||||
MILC と QMK CLI にはユーザとやり取りするための幾つかの便利なツールがあります。これらの標準ツールを使うと、テキストに色を付けて対話し易くし、ユーザはその情報をいつどのように表示および保存するかを制御することができます。
|
||||
|
||||
## テキストの表示
|
||||
|
||||
サブコマンド内でテキストを出力するための2つの主な方法があります- `cli.log` と `cli.echo()`。それらは似た方法で動作しますが、ほとんどの一般的な目的の出力には `cli.log.info()` を使うことをお勧めします。
|
||||
|
||||
特別なトークンを使用してテキストを色付けし、プログラムの出力を理解しやすくすることができます。以下の[テキストの色付け](#colorizing-text)を見てください。
|
||||
|
||||
これらの両方の方法は python の [printf 形式の文字列書式化](https://docs.python.org/3.6/library/stdtypes.html#old-string-formatting) を使った組み込みの文字列書式化をサポートします。テキスト文字列内で`%s` と `%d` のようなトークンを使い、引数で値を渡すことができます。例として、上記の Hello、World プログラムを見てください。
|
||||
|
||||
書式演算子 (`%`) を直接使わないでください、常に引数で値を渡します。
|
||||
|
||||
### ログ (`cli.log`)
|
||||
|
||||
`cli.log` オブジェクトは[ロガーオブジェクト](https://docs.python.org/3.6/library/logging.html#logger-objects)へのアクセスを与えます。ログ出力を設定し、ユーザに各ログレベルの素敵な絵文字(またはターミナルが unicode をサポートしない場合はログレベル名)を表示します。このようにして、ユーザは何か問題が発生した時に最も重要なメッセージを一目で確認することができます。
|
||||
|
||||
デフォルトのログレベルは `INFO` です。ユーザが `qmk -v <subcommand>` を実行すると、デフォルトのログレベルは `DEBUG` に設定されます。
|
||||
|
||||
| 関数 | 絵文字 |
|
||||
|----------|-------|
|
||||
| cli.log.critical | `{bg_red}{fg_white}¬_¬{style_reset_all}` |
|
||||
| cli.log.error | `{fg_red}☒{style_reset_all}` |
|
||||
| cli.log.warning | `{fg_yellow}⚠{style_reset_all}` |
|
||||
| cli.log.info | `{fg_blue}Ψ{style_reset_all}` |
|
||||
| cli.log.debug | `{fg_cyan}☐{style_reset_all}` |
|
||||
| cli.log.notset | `{style_reset_all}¯\\_(o_o)_/¯` |
|
||||
|
||||
### 出力 (`cli.echo`)
|
||||
|
||||
場合によっては単にログシステムの外部でテキストを出力する必要があります。これは、固定データを出力したり、ログに記録してはいけない何かを書きだす場合に適しています。ほとんどの場合、`cli.echo` よりも `cli.log.info()` を選ぶべきです。
|
||||
|
||||
### テキストの色付け
|
||||
|
||||
テキスト内に色トークンを含めることで、テキストの出力を色付けすることができます。情報を伝えるためではなく、強調するために色を使います。ユーザは色を無効にできることを覚えておいてください。色を無効にした場合でもサブコマンドは引き続き使えるようにしてください。
|
||||
|
||||
背景色を設定するのは、あなたがやっていることに不可欠ではない限り、通常は避けるべきです。ユーザは、ターミナルの色に関しては多くの好みを持つため、あなたは黒と白のどちらの背景に対してもうまく機能する色を選択する必要があることを覚えておいてください。
|
||||
|
||||
'fg' という接頭辞の付いた色は、前景(テキスト)色に影響します。'bg' という接頭辞の付いた色は、背景色に影響します。
|
||||
|
||||
| 色 | 背景 | 拡張背景 | 前景 | 拡張前景 |
|
||||
|-------|------------|---------------------|------------|--------------------|
|
||||
| 黒 | {bg_black} | {bg_lightblack_ex} | {fg_black} | {fg_lightblack_ex} |
|
||||
| 青 | {bg_blue} | {bg_lightblue_ex} | {fg_blue} | {fg_lightblue_ex} |
|
||||
| シアン | {bg_cyan} | {bg_lightcyan_ex} | {fg_cyan} | {fg_lightcyan_ex} |
|
||||
| 緑 | {bg_green} | {bg_lightgreen_ex} | {fg_green} | {fg_lightgreen_ex} |
|
||||
| マゼンタ | {bg_magenta} | {bg_lightmagenta_ex} | {fg_magenta} | {fg_lightmagenta_ex} |
|
||||
| 赤 | {bg_red} | {bg_lightred_ex} | {fg_red} | {fg_lightred_ex} |
|
||||
| 白 | {bg_white} | {bg_lightwhite_ex} | {fg_white} | {fg_lightwhite_ex} |
|
||||
| 黄 | {bg_yellow} | {bg_lightyellow_ex} | {fg_yellow} | {fg_lightyellow_ex} |
|
||||
|
||||
ANSI 出力の挙動を変更するために使うことができる制御シーケンスもあります。
|
||||
|
||||
| 制御シーケンス | 説明 |
|
||||
|-------------------|-------------|
|
||||
| {style_bright} | テキストを明るくする |
|
||||
| {style_dim} | テキストを暗くする |
|
||||
| {style_normal} | テキストを通常にする (`{style_bright}` または `{style_dim}` のどちらでもない) |
|
||||
| {style_reset_all} | 全てのテキストの属性をデフォルトに再設定する(これは自動的に全ての文字列の最後に自動的に追加されます。) |
|
||||
| {bg_reset} | 背景色をユーザのデフォルトに再設定します。 |
|
||||
| {fg_reset} | 背景色をユーザのデフォルトに再設定します。 |
|
||||
|
||||
# 引数と設定
|
||||
|
||||
QMK は引数の解析と設定の詳細をあなたの代わりに処理します。新しい引数を追加すると、サブコマンドの名前と引数の長い名前に基づいて設定ツリーに自動的に組み込まれます。属性形式のアクセス (`cli.config.<subcommand>.<argument>`) あるいは辞書形式のアクセス (`cli.config['<subcommand>']['<argument>']`) を使って、`cli.config` 内のこの設定にアクセスすることができます。
|
||||
|
||||
内部では、QMK は [設定ファイルのパーサ](https://docs.python.org/3/library/configparser.html) を使って設定を格納します。これにより、人間が編集可能な方法で設定を表す簡単で分かり易い方法を提供します。この設定へのアクセスをラップして、設定ファイルのパーサーが通常持たない幾つかの機能を提供しています。
|
||||
|
||||
## 設定値の読み込み
|
||||
|
||||
通常期待される全ての方法で `cli.config` とやり取りすることができます。例えば、`qmk compile` コマンドは `cli.config.compile.keyboard` からキーボード名を取得します。値がコマンドライン、環境変数あるいは設定ファイルからきたものであるかどうかを知る必要はありません。
|
||||
|
||||
繰り返しもサポートされます:
|
||||
|
||||
```
|
||||
for section in cli.config:
|
||||
for key in cli.config[section]:
|
||||
cli.log.info('%s.%s: %s', section, key, cli.config[section][key])
|
||||
```
|
||||
|
||||
## 設定値の設定
|
||||
|
||||
通常の方法で設定値を設定することができます。
|
||||
|
||||
辞書形式:
|
||||
|
||||
```
|
||||
cli.config['<section>']['<key>'] = <value>
|
||||
```
|
||||
|
||||
属性形式:
|
||||
|
||||
```
|
||||
cli.config.<section>.<key> = <value>
|
||||
```
|
||||
|
||||
## 設定値の削除
|
||||
|
||||
通常の方法で設定値を削除することができます。
|
||||
|
||||
辞書形式:
|
||||
|
||||
```
|
||||
del(cli.config['<section>']['<key>'])
|
||||
```
|
||||
|
||||
属性形式:
|
||||
|
||||
```
|
||||
del(cli.config.<section>.<key>)
|
||||
```
|
||||
|
||||
## 設定ファイルの書き方
|
||||
|
||||
設定は変更しても書き出されません。ほとんどのコマンドでこれをする必要はありません。ユーザに `qmk config` を使って設定を慎重に変更させることをお勧めします。
|
||||
|
||||
設定を書き出すために `cli.save_config()` を使うことができます。
|
||||
|
||||
## 設定からの引数の除外
|
||||
|
||||
一部の引数は設定ファイルに反映すべきではありません。これらは引数を作成する時に `arg_only=True` を追加することで除外することができます。
|
||||
|
||||
例:
|
||||
|
||||
```
|
||||
@cli.argument('-o', '--output', arg_only=True, help='File to write to')
|
||||
@cli.argument('filename', arg_only=True, help='Configurator JSON file')
|
||||
@cli.subcommand('Create a keymap.c from a QMK Configurator export.')
|
||||
def json_keymap(cli):
|
||||
pass
|
||||
```
|
||||
|
||||
`cli.args` を使ってのみこれらの引数にアクセスすることができます。例えば:
|
||||
|
||||
```
|
||||
cli.log.info('Reading from %s and writing to %s', cli.args.filename, cli.args.output)
|
||||
```
|
||||
|
||||
# テスト、リントおよびフォーマット
|
||||
|
||||
nose2、flake8 および yapf を使ってコードをテスト、リントおよびフォーマットします。これらのテストを実行するために `pytest` と `pyformat` サブコマンドを使うことができます。
|
||||
|
||||
### テストとリント
|
||||
|
||||
qmk pytest
|
||||
|
||||
### フォーマット
|
||||
|
||||
qmk pyformat
|
||||
|
||||
## フォーマットの詳細
|
||||
|
||||
[yapf](https://github.com/google/yapf) を使ってコードを自動的にフォーマットします。フォーマットの設定は `setup.cfg` の `[yapf]` セクションにあります。
|
||||
|
||||
?> ヒント- 多くのエディタは yapf をプラグインとして使って、入力したコードを自動的にフォーマットすることができます。
|
||||
|
||||
## テストの詳細
|
||||
|
||||
テストは `lib/python/qmk/tests/` にあります。このディレクトリに単体テストと統合テストの両方があります。コードの単体テストと統合テストの両方を書いてほしいですが、一方のみ書く場合は統合テストを優先してください。
|
||||
|
||||
PR にテストの包括的なセットが含まれない場合は、次のようなコメントをコードに追加して、他の人が手助けできるようにしてください:
|
||||
|
||||
# TODO(unassigned/<your_github_username>): Write <unit|integration> tests
|
||||
|
||||
[nose2](https://nose2.readthedocs.io/en/latest/getting_started.html) を使ってテストを実行します。テスト関数でできることの詳細については、nose2 のドキュメントを参照してください。
|
||||
|
||||
## リントの詳細
|
||||
|
||||
flake8 を使ってコードをリントします。PR を開く前に、コードは flake8 をパスしなければなりません。これは `qmk pytest` を実行するときにチェックされ、PR を登録したときに CI によってチェックされます。
|
63
docs/ja/coding_conventions_c.md
Normal file
63
docs/ja/coding_conventions_c.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# コーディング規約 (C)
|
||||
|
||||
<!---
|
||||
original document: 0.9.19:docs/coding_conventions_c.md
|
||||
git diff 0.9.19 HEAD -- docs/coding_conventions_c.md | cat
|
||||
-->
|
||||
|
||||
私たちのスタイルのほとんどはかなり理解しやすいですが、現時点では完全に一貫しているわけではありません。変更箇所周辺のコードのスタイルと一致させる必要がありますが、そのコードに一貫性が無い場合や不明瞭な場合は以下のガイドラインに従ってください:
|
||||
|
||||
* 4つのスペース (ソフトタブ) を使ってインデントします。
|
||||
* 修正版 One True Brace Style を使います。
|
||||
* 開き括弧: ブロックを開始する文と同じ行の最後
|
||||
* 閉じ括弧: ブロックを開始した文と同じ字下げ
|
||||
* Else If: 行の先頭に閉じ括弧を置き、次の開き括弧を同じ行の最後に置きます。
|
||||
* 省略可能な括弧: 常に括弧を付け加えます。
|
||||
* 良い: if (condition) { return false; }
|
||||
* 悪い: if (condition) return false;
|
||||
* C 形式のコメントの使用を推奨します: `/* */`
|
||||
* コメントを機能を説明するストーリーと考えて下さい。
|
||||
* 特定の決定がなされた理由を充分なコメントで説明してください。
|
||||
* 分かり切ったコメントは書かないでください。
|
||||
* 分かり切ったコメントであるか確信できない場合は、コメントを含めてください。
|
||||
* 一般的に、行を折り返さないで、必要なだけ長くすることができます。行を折り返すことを選択した場合は、76列を超えて折り返さないでください。
|
||||
* 古い形式のインクルードガード (`#ifndef THIS_FILE_H`、`#define THIS_FILE_H`、...、`#endif`) ではなく、ヘッダファイルの先頭で `#pragma once` を使います。
|
||||
* プリプロセッサ if の両方の形式を受け付けます: `#ifdef DEFINED` と `#if defined(DEFINED)`
|
||||
* どちらがいいかわからない場合は、`#if defined(DEFINED)` 形式を使ってください。
|
||||
* 複数の条件 `#if` に移行する場合を除き、既存のコードを別のスタイルに変更しないでください。
|
||||
* プリプロセッサディレクティブをインデントする方法(あるいはするかどうか)を決定する時は、以下の事に留意してください:
|
||||
* 一貫性よりも読みやすさが重要です。
|
||||
* ファイルの既存のスタイルに従ってください。ファイルのスタイルが混在している場合は、修正しようとしているセクションに適したスタイルに従ってください。
|
||||
* インデントする時は、ハッシュを行の先頭に置き、`#` と `if` の間に空白を追加します。`#` の後ろに4つスペースを入れて開始します。
|
||||
* 周りの C コードのインデントレベルに従うか、プリプロセッサのディレクティブに独自のインデントレベルを設定することができます。コードの意図を最もよく伝えるスタイルを選択してください。
|
||||
|
||||
わかりやすいように例を示します:
|
||||
|
||||
```c
|
||||
/* Enums for foo */
|
||||
enum foo_state {
|
||||
FOO_BAR,
|
||||
FOO_BAZ,
|
||||
};
|
||||
|
||||
/* Returns a value */
|
||||
int foo(void) {
|
||||
if (some_condition) {
|
||||
return FOO_BAR;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# clang-format を使った自動整形
|
||||
|
||||
[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) は LLVM の一部で、誰もが手動で整形するほど暇ではないため、コードを自動整形することができます。私たちは、上記のコーディング規約のほとんどを適用する設定ファイルを提供しています。空白と改行のみを変更するため、省略可能な括弧は自分で付け加えることを忘れないでください。
|
||||
|
||||
Windows で clang-format を入手するには [full LLVM インストーラ](http://llvm.org/builds/)を使い、Ubuntu では `sudo apt install clang-format` を使ってください。
|
||||
|
||||
コマンドラインから実行する場合、オプションとして `-style=file` を渡すと、QMK ルートディレクトリ内の .clang-format 設定ファイルを自動的に見つけます。
|
||||
|
||||
VSCode を使う場合は、標準の C/C++ プラグインが clang-format をサポートしますが、その他にも [独立した拡張機能](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat) があります。
|
||||
|
||||
幾つかのコード (LAYOUT マクロのような)が clang-format によって破壊されるため、これらのファイルで clang-format を実行しないか、整形したくないコードを `// clang-format off` と `// clang-format on` で囲みます。
|
331
docs/ja/coding_conventions_python.md
Normal file
331
docs/ja/coding_conventions_python.md
Normal file
@@ -0,0 +1,331 @@
|
||||
# コーディング規約 (Python)
|
||||
|
||||
<!---
|
||||
original document: 0.9.19:docs/coding_conventions_python.md
|
||||
git diff 0.9.19 HEAD -- docs/coding_conventions_python.md | cat
|
||||
-->
|
||||
|
||||
私たちのスタイルの大部分は PEP8 に従いますが、神経質にならないように幾つかのローカルな変更を加えています。
|
||||
|
||||
* サポートされる全てのプラットフォームとの互換性のために、Python 3.6 を対象にしています。
|
||||
* 4つのスペース (ソフトタブ) を使ってインデントします
|
||||
* 充分なコメントを書くことを推奨します
|
||||
* コメントを機能を説明するストーリーと考えて下さい
|
||||
* 特定の決定がなされた理由を充分なコメントで説明してください。
|
||||
* 分かり切ったコメントは書かないでください
|
||||
* 分かり切ったコメントであるか確信できない場合は、コメントを含めてください。
|
||||
* 全ての関数について、役に立つ docstring を必要とします。
|
||||
* 一般的に、行を折り返さないで、必要なだけ長くすることができます。行を折り返すことを選択した場合は、76列を超えて折り返さないでください。
|
||||
* 私たちの慣習の幾つかは、Python 使いでは無い人にコードベースをより身近にするために、python コミュニティに広まっているものとは競合しています。
|
||||
|
||||
# YAPF
|
||||
|
||||
コードを整形するために [yapf](https://github.com/google/yapf) を使うことができます。[setup.cfg](setup.cfg) で設定を提供しています。
|
||||
|
||||
# インポート
|
||||
|
||||
`import ...` や `from ... import ...` をいつ使うかについての厳密なルールはありません。理解しやすさと保守性が究極の目的です。
|
||||
|
||||
一般的に、コードを短く理解しやすくするためにモジュールから特定の関数とクラス名をインポートする方が望ましいです。これにより、名前が曖昧になることがあります。代わりにモジュールをインポートするようにします。互換性のあるモジュールをインポートする時を除いて、インポートする時は "as" キーワードを避けるべきです。
|
||||
|
||||
インポートは各モジュール1行にする必要があります。標準的な python ルールに従って、インポート文をシステム、サードパーティ、ローカルにグループ化します。
|
||||
|
||||
`from foo import *` を使わないでください。代わりにインポートしたいオブジェクトのリストを指定するか、モジュール全体をインポートします。
|
||||
|
||||
## インポートの例
|
||||
|
||||
良い:
|
||||
|
||||
```
|
||||
from qmk import effects
|
||||
|
||||
effects.echo()
|
||||
```
|
||||
|
||||
悪い:
|
||||
|
||||
```
|
||||
from qmk.effects import echo
|
||||
|
||||
echo() # echoがどこから来たのかが不明瞭です
|
||||
```
|
||||
|
||||
良い:
|
||||
|
||||
```
|
||||
from qmk.keymap import compile_firmware
|
||||
|
||||
compile_firmware()
|
||||
```
|
||||
|
||||
良いですが、上の方がより良いです:
|
||||
|
||||
```
|
||||
import qmk.keymap
|
||||
|
||||
qmk.keymap.compile_firmware()
|
||||
```
|
||||
|
||||
# 命令文
|
||||
|
||||
各行1文としてください。
|
||||
|
||||
可能な場合(例えば `if foo: bar`)でも、2つの文を1行にまとめないでください。
|
||||
|
||||
# 命名
|
||||
|
||||
`module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`, `function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`, `function_parameter_name`, `local_var_name`.
|
||||
|
||||
関数名、変数名 およびファイル名は説明的でなければなりません; 略語を避けます。特に、プロジェクト外の読み手に曖昧あるいは馴染みのない略語を使わず、単語内の文字を削除して略さないでください。
|
||||
|
||||
常に .py のファイル名の拡張子を使います。ダッシュを使わないでください。
|
||||
|
||||
## 避けるべき名前
|
||||
|
||||
* カウンタあるいはイテレータ以外の1文字の名前。try/except 文では例外の識別子として `e` を使うことができます。
|
||||
* パッケージ/モジュール名内のダッシュ (`-`)
|
||||
* `__double_leading_and_trailing_underscore__` (2つのアンダースコアで始まる名前と終わる名前、Python で予約済み)
|
||||
|
||||
# Docstring
|
||||
|
||||
docstring の一貫性を維持するために、以下のガイドラインを設定しました。
|
||||
|
||||
* マークダウン(Markdown)形式の使用
|
||||
* 常に少なくとも1つの改行を含む3つのダブルクォートの docstring を使ってください: `"""\n"""`
|
||||
* 最初の行は、関数が行うことの短い (70文字未満) 説明です。
|
||||
* docstring が更に必要な場合は、説明と残りの間に空白行を入れます。
|
||||
* 開始の3つのダブルクォートと同じインデントレベルでインデント行を始めます
|
||||
* 以下で説明する形式を使って全ての関数の引数について記述します
|
||||
* Args:、Returns: および Raises: が存在する場合、それらは docstring の最後の3つの要素で、それぞれ空白行で区切られなければなりません。
|
||||
|
||||
## 簡単な docstring の例
|
||||
|
||||
```
|
||||
def my_awesome_function():
|
||||
"""1970 Jan 1 00:00 UTC からの秒数を返します。
|
||||
"""
|
||||
return int(time.time())
|
||||
```
|
||||
|
||||
## 複雑な docstring の例
|
||||
|
||||
```
|
||||
def my_awesome_function():
|
||||
"""1970 Jan 1 00:00 UTC からの秒数を返します。
|
||||
|
||||
この関数は常に整数の秒数を返します。
|
||||
"""
|
||||
return int(time.time())
|
||||
```
|
||||
|
||||
## 関数の引数の docstring の例
|
||||
|
||||
```
|
||||
def my_awesome_function(start=None, offset=0):
|
||||
"""1970 Jan 1 00:00 UTC からの秒数を返します。
|
||||
|
||||
この関数は常に整数の秒数を返します。
|
||||
|
||||
|
||||
Args:
|
||||
start
|
||||
1970 Jan 1 00:00 UTC の代わりの開始時間
|
||||
|
||||
offset
|
||||
最初の引数からこの秒数が引かれた答えを返します
|
||||
|
||||
Returns:
|
||||
秒数を表す整数。
|
||||
|
||||
Raises:
|
||||
ValueError
|
||||
`start` あるいは `offset` が正の数ではない場合
|
||||
"""
|
||||
if start < 0 or offset < 0:
|
||||
raise ValueError('start and offset must be positive numbers.')
|
||||
|
||||
if not start:
|
||||
start = time.time()
|
||||
|
||||
return int(start - offset)
|
||||
```
|
||||
|
||||
# 例外
|
||||
|
||||
例外は例外的な状況を処理するために使われます。フローの制御のために使われるべきではありません。これは Python の「許しを請う」という規範からの逸脱です。例外をキャッチする場合、異常な状況を処理する必要があります。
|
||||
|
||||
何らかの理由で全ての例外のキャッチを使う場合は、cli.log を使って例外とスタックトレースを記録する必要があります。
|
||||
|
||||
try/except ブロックをできるだけ短くします。多数の try 文が必要な場合は、コードを再構成する必要があるかもしれません。
|
||||
|
||||
# タプル
|
||||
|
||||
1項目のタプルを定義する場合、タプルを使用していることが明らかになるように、常に末尾のカンマを含めます。暗黙的な1項目のタプルのアンパックに頼らないでください。明確なリストを使う方が良いです。
|
||||
|
||||
これはよく使用される printf 形式の書式文字列を使う場合に、特に重要です。
|
||||
|
||||
# リストと辞書
|
||||
|
||||
シーケンス形式と末尾のカンマとを区別するように YAPF を設定しました。末尾のカンマが省略されると、YAPF はシーケンスを1つの行として整形します。末尾のカンマがある場合、YAPF はシーケンスを1行1項目で整形します。
|
||||
|
||||
一般的に1行が短い定義になるようにすべきです。読みやすさと保守性を向上させるために、後からではなく早めに複数の行を分割してください。
|
||||
|
||||
# 括弧
|
||||
|
||||
過度な括弧は避けますが、括弧を使ってコードを理解しやすくします。タプルを明示的に返すか、あるいは数式の一部である場合を除き、return 文で括弧を使わないでください。
|
||||
|
||||
# 書式文字列
|
||||
|
||||
一般的に printf 形式の書式文字列を用います。例:
|
||||
|
||||
```
|
||||
name = 'World'
|
||||
print('Hello, %s!' % (name,))
|
||||
```
|
||||
|
||||
このスタイルはログモジュールで使われており、私たちはそれを広範囲で利用しており、一貫性を保つために他の場所でも採用しています。これは、私たちの気まぐれな読者の大部分である C プログラマにもおなじみのスタイルです。
|
||||
|
||||
付属の CLI モジュールは、パーセント (%) 演算子を使わずにこれらを使うことをサポートしています。詳細は、`cli.echo()` と様々な `cli.log` 関数 (例えば、`cli.log.info()`) を見てください。
|
||||
|
||||
# 内包表記とジェネレータ表記
|
||||
|
||||
内包表記とジェネレータの自由な使用を推奨しますが、あまりに複雑にしないでください。複雑になる場合は、理解しやすい for ループで代替します。
|
||||
|
||||
# ラムダ
|
||||
|
||||
使っても問題ありませんが、おそらく避けるべきです。内包表記とジェネレータを使えば、ラムダの必要性は以前ほど強くありません。
|
||||
|
||||
# 条件式
|
||||
|
||||
変数の割り当てでは問題ありませんが、そうでなければ避けるべきです。
|
||||
|
||||
条件式はコードに続く if 文です。例えば:
|
||||
|
||||
```
|
||||
x = 1 if cond else 2
|
||||
```
|
||||
|
||||
一般にこれらを関数の引数、シーケンス項目などとして使用することはお勧めできません。見落としやすくなります。
|
||||
|
||||
# デフォルト引数
|
||||
|
||||
推奨されていますが、値は不変オブジェクトでなければなりません。
|
||||
|
||||
デフォルト値に引数リストを指定する場合は、その場で変更できないオブジェクトを指定するように常に注意してください。可変オブジェクトを使うと変更は呼び出しの間で持続しますが、これは通常あなたの望むものではありませんそれがあなたのやろうとしていることであっても、他の人にとっては混乱するもので理解を妨げます。
|
||||
|
||||
悪い:
|
||||
|
||||
```
|
||||
def my_func(foo={}):
|
||||
pass
|
||||
```
|
||||
|
||||
良い:
|
||||
|
||||
```
|
||||
def my_func(foo=None):
|
||||
if not foo:
|
||||
foo = {}
|
||||
```
|
||||
|
||||
# プロパティ
|
||||
|
||||
getter および setter 関数の代わりにプロパティを常に使います。
|
||||
|
||||
```
|
||||
class Foo(object):
|
||||
def __init__(self):
|
||||
self._bar = None
|
||||
|
||||
@property
|
||||
def bar(self):
|
||||
return self._bar
|
||||
|
||||
@bar.setter
|
||||
def bar(self, bar):
|
||||
self._bar = bar
|
||||
```
|
||||
|
||||
# True/False の評価
|
||||
|
||||
一般的に、if 文で等価性を調べるのではなく、暗黙的な True/False 評価を行うべきです。
|
||||
|
||||
悪い:
|
||||
|
||||
```
|
||||
if foo == True:
|
||||
pass
|
||||
|
||||
if bar == False:
|
||||
pass
|
||||
```
|
||||
|
||||
良い:
|
||||
|
||||
```
|
||||
if foo:
|
||||
pass
|
||||
|
||||
if not bar:
|
||||
pass
|
||||
```
|
||||
|
||||
# デコレータ
|
||||
|
||||
適切な時に使ってください。理解に役立つ時を除き、魔法の(ように見える技巧の)使いすぎは避けるようにしてください。
|
||||
|
||||
# スレッドとマルチプロセス
|
||||
|
||||
避けるべきです。これが必要な場合は、私たちがコードをマージする前に十分な理由を述べる必要があります。
|
||||
|
||||
# 強力な機能
|
||||
|
||||
Python は非常に柔軟な言語で、独自のメタクラス、バイトコードへのアクセス、実行中コンパイル、動的な継承、オブジェクトの親の変更、インポートハック、リフレクション、システム内部の変更など、多くの素晴らしい機能を提供します。
|
||||
|
||||
これらを使わないでください。
|
||||
|
||||
パフォーマンスは私たちにとって重要な関心ごとではなく、コードのわかりやすさに関心があります。私たちは、コードベースを1日か2日しかいじっていない人が利用できるようにしたいです。これらの機能は一般的に理解のしやすさを犠牲にするため、より高速あるいはよりコンパクトなコードよりも、容易に理解できるコードの方が望ましいです。
|
||||
|
||||
一部の標準ライブラリモジュールはこれらの手法を使っており、これらのモジュールを利用しても問題ありません。ただし、それらを使う時には、読みやすさと理解のしやすさを忘れないでください。
|
||||
|
||||
# 型アノテーション付きコード
|
||||
|
||||
今のところ型アノテーションシステムを使っていないため、コードにアノテーションをつけないようにしてください。将来的にはこれを再検討する可能性があります。
|
||||
|
||||
# 関数の長さ
|
||||
|
||||
小さくて焦点のあった関数にしてください。
|
||||
|
||||
長い関数が時には適切であることを理解しているので、関数の長さには厳密な制限はありません。関数が約40行を超える場合は、プログラムの構造を損なわずに分割できるかどうかを検討してください。
|
||||
|
||||
今のところ長い関数が完全に機能するとしても、数か月でそれを変更する人が新しい挙動を追加するかもしれません。これにより見つけにくいバグが発生するかもしれません。関数を短くかつシンプルにすることで、他の人がコードを読んで修正しやすくします。
|
||||
|
||||
幾つかのコードで作業をすると、長く複雑な関数を見つけるかもしれません。既存コードを変更することを怖がらないでください: もし、難しいことが判明したり、エラーがデバッグしづらいとわかったり、いくつかの異なるコンテキストで一部を使いたいような関数を扱っている場合、関数を小さくてより扱いやすい単位に分割することを検討してください。
|
||||
|
||||
# FIXME
|
||||
|
||||
FIXME をコードに残しても構いません。なぜでしょうか?このコードを文章化しないままにするよりも、少なくとも考え抜く必要がある(あるいは混乱している)コードの一部を文章化するように奨励する方が、このコードを文章化しないままにするよりも良いです。
|
||||
|
||||
全ての FIXME は以下のように書式化されるべきです:
|
||||
|
||||
```
|
||||
FIXME(username): 何々機能が完了したらこのコードを再検討する。
|
||||
```
|
||||
|
||||
...username はあなたの GitHub のユーザ名です。
|
||||
|
||||
# テスト
|
||||
|
||||
統合テストと単体テストの組み合わせを使ってコードが可能な限りバグが無いようにします。全てのテストは `lib/python/qmk/tests/` にあります。`qmk pytest` を使って全てのテストを実行することができます。
|
||||
|
||||
これを書いている時点では、テストは全く完全なものではありません。現在のテストを見て、テストされていない状況のための新しいテストケースを書くことは、コードベースに精通し、QMK に貢献するという両方の点で素晴らしい方法です。
|
||||
|
||||
## 統合テスト
|
||||
|
||||
統合テストは `lib/python/qmk/tests/test_cli_commands.py` にあります。ここで実際に CLI コマンドが実行され、全体的な動作が検証されます。[`subprocess`](https://docs.python.org/3.6/library/subprocess.html#module-subprocess) を使って各 CLI コマンドを起動し、正しく動作するかを判断するために出力とリターンコードの組み合わせを使います。
|
||||
|
||||
## ユニットテスト
|
||||
|
||||
`lib/python/qmk/tests/` 内の他の `test_*.py` ファイルはユニットテストを含みます。`lib/python/qmk/` 内の個々の関数のテストをここに書くことができます。一般的にこれらのファイルはモジュールに基づいて名前を付けられ、ドットはアンダースコアで置き換えられます。
|
||||
|
||||
これを書いている時点では、テストのためのモックを作っていません。これを変更する手伝いをしたい場合は、[issue を開く](https://github.com/qmk/qmk_firmware/issues/new?assignees=&labels=cli%2C+python&template=other_issues.md&title=) か [Discord の #cli に参加](https://discord.gg/heQPAgy)し、そこで会話を開始してください。
|
42
docs/ja/compatible_microcontrollers.md
Normal file
42
docs/ja/compatible_microcontrollers.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 互換性のあるマイクロコントローラ
|
||||
|
||||
<!---
|
||||
original document: 0.9.19:docs/compatible_microcontrollers.md
|
||||
git diff 0.9.19 HEAD -- docs/compatible_microcontrollers.md | cat
|
||||
-->
|
||||
|
||||
QMK は十分な容量のフラッシュメモリを備えた USB 対応 AVR または ARM マイクロコントローラで実行されます - 一般的に 32kB 以上ですが、ほとんどの機能を無効にすると*ほんの* 16kB に詰め込むことができます。
|
||||
|
||||
## Atmel AVR
|
||||
|
||||
以下は、USB スタックとして [LUFA](https://www.fourwalledcubicle.com/LUFA.php) を使います:
|
||||
|
||||
* [ATmega16U2](https://www.microchip.com/wwwproducts/en/ATmega16U2) / [ATmega32U2](https://www.microchip.com/wwwproducts/en/ATmega32U2)
|
||||
* [ATmega16U4](https://www.microchip.com/wwwproducts/en/ATmega16U4) / [ATmega32U4](https://www.microchip.com/wwwproducts/en/ATmega32U4)
|
||||
* [AT90USB64](https://www.microchip.com/wwwproducts/en/AT90USB646) / [AT90USB128](https://www.microchip.com/wwwproducts/en/AT90USB1286)
|
||||
|
||||
組み込みの USB インターフェースを持たない、いくつかの MCU は代わりに [V-USB](https://www.obdev.at/products/vusb/index.html) を使います:
|
||||
|
||||
* [ATmega32A](https://www.microchip.com/wwwproducts/en/ATmega32A)
|
||||
* [ATmega328P](https://www.microchip.com/wwwproducts/en/ATmega328P)
|
||||
* [ATmega328](https://www.microchip.com/wwwproducts/en/ATmega328)
|
||||
|
||||
## ARM
|
||||
|
||||
[ChibiOS](http://www.chibios.org) がサポートする USB 付きの ARM チップを使うこともできます。ほとんどのチップには十分な容量のフラッシュメモリがあります。動作するとわかっているのは:
|
||||
|
||||
### STMicroelectronics (STM32)
|
||||
|
||||
* [STM32F0x2](https://www.st.com/en/microcontrollers-microprocessors/stm32f0x2.html)
|
||||
* [STM32F103](https://www.st.com/en/microcontrollers-microprocessors/stm32f103.html)
|
||||
* [STM32F303](https://www.st.com/en/microcontrollers-microprocessors/stm32f303.html)
|
||||
|
||||
### NXP (Kinetis)
|
||||
|
||||
* [MKL26Z64](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/kl-series-cortex-m0-plus/kinetis-kl2x-72-96-mhz-usb-ultra-low-power-microcontrollers-mcus-based-on-arm-cortex-m0-plus-core:KL2x)
|
||||
* [MK20DX128](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/k-series-cortex-m4/k2x-usb/kinetis-k20-50-mhz-full-speed-usb-mixed-signal-integration-microcontrollers-based-on-arm-cortex-m4-core:K20_50)
|
||||
* [MK20DX256](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/k-series-cortex-m4/k2x-usb/kinetis-k20-72-mhz-full-speed-usb-mixed-signal-integration-microcontrollers-mcus-based-on-arm-cortex-m4-core:K20_72)
|
||||
|
||||
## Atmel ATSAM
|
||||
|
||||
Atmel の ATSAM マイクロコントローラの一つである、[Massdrop keyboards](https://github.com/qmk/qmk_firmware/tree/master/keyboards/massdrop) で使用されている [ATSAMD51J18A](https://www.microchip.com/wwwproducts/en/ATSAMD51J18A) には限定的なサポートがあります。
|
@@ -1,8 +1,8 @@
|
||||
# QMK の設定
|
||||
|
||||
<!---
|
||||
original document: 0.8.62:docs/config_options.md
|
||||
git diff 0.8.62 HEAD -- docs/config_options.md | cat
|
||||
original document: 0.10.33:docs/config_options.md
|
||||
git diff 0.10.33 HEAD -- docs/config_options.md | cat
|
||||
-->
|
||||
|
||||
QMK はほぼ無制限に設定可能です。可能なところはいかなるところでも、やりすぎな程、ユーザーがコードサイズを犠牲にしてでも彼らのキーボードをカスタマイズをすることを許しています。ただし、このレベルの柔軟性により設定が困難になります。
|
||||
@@ -34,7 +34,9 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
|
||||
これは最初に include されるものの 1 つである C ヘッダファイルで、プロジェクト全体(もし含まれる場合)にわたって持続します。多くの変数をここで設定し、他の場所からアクセスすることができます。`config.h` ファイルでは、以下のもの以外の、他の `config.h` ファイルやその他のファイルの include をしないでください:
|
||||
|
||||
#include "config_common.h"
|
||||
```c
|
||||
#include "config_common.h"
|
||||
```
|
||||
|
||||
|
||||
## ハードウェアオプション
|
||||
@@ -48,8 +50,6 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* 一般的に、誰もしくはどのブランドがボードを作成したか
|
||||
* `#define PRODUCT Board`
|
||||
* キーボードの名前
|
||||
* `#define DESCRIPTION a keyboard`
|
||||
* キーボードの簡単な説明
|
||||
* `#define MATRIX_ROWS 5`
|
||||
* キーボードのマトリックスの行の数
|
||||
* `#define MATRIX_COLS 15`
|
||||
@@ -120,9 +120,9 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* `#define NO_ACTION_ONESHOT`
|
||||
* ワンショットモディファイアを無効にします
|
||||
* `#define NO_ACTION_MACRO`
|
||||
* 古い形式のマクロ処理を無効にします: MACRO() & action_get_macro
|
||||
* `MACRO()`、`action_get_macro()` _(非推奨)_ を使う古い形式のマクロ処理を無効にします
|
||||
* `#define NO_ACTION_FUNCTION`
|
||||
* fn_actions 配列(非推奨)からの action_function() の呼び出しを無効にします
|
||||
* `fn_actions`、`action_function()` _(非推奨)_ を使う古い形式の関数処理を無効にします
|
||||
|
||||
## 有効にできる機能
|
||||
|
||||
@@ -189,7 +189,14 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* `#define RGBLIGHT_ANIMATIONS`
|
||||
* RGB アニメーションを実行します
|
||||
* `#define RGBLIGHT_LAYERS`
|
||||
* オンとオフを切り替えることができる [ライトレイヤー](ja/feature_rgblight.md) を定義できます。現在のキーボードレイヤーまたは Caps Lock 状態を表示するのに最適です。
|
||||
* オンとオフを切り替えることができる [ライトレイヤー](ja/feature_rgblight.md?id=lighting-layers) を定義できます。現在のキーボードレイヤーまたは Caps Lock 状態を表示するのに最適です。
|
||||
* `#define RGBLIGHT_MAX_LAYERS`
|
||||
* デフォルトは8です。もしさらに [ライトレイヤー](ja/feature_rgblight.md?id=lighting-layers) が必要であれば、32まで拡張できます。
|
||||
* メモ: 最大値を大きくするとファームウェアサイズが大きくなり、分割キーボードで同期が遅くなります。
|
||||
* `#define RGBLIGHT_LAYER_BLINK`
|
||||
* 指定されたミリ秒の間、ライトレイヤーを [点滅](ja/feature_rgblight.md?id=lighting-layer-blink) する機能を追加します(例えば、アクションを確認するため)。
|
||||
* `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF`
|
||||
* 定義されている場合、RGB ライトがオフになっている場合でも [ライトレイヤー](ja/feature_rgblight?id=overriding-rgb-lighting-onoff-status) が表示されます。
|
||||
* `#define RGBLED_NUM 12`
|
||||
* LED の数
|
||||
* `#define RGBLIGHT_SPLIT`
|
||||
@@ -241,7 +248,10 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* `#define SPLIT_HAND_PIN B7`
|
||||
* high/low ピンを使って左右を決定します。low = 右手、high = 左手。`B7` を使っているピンに置き換えます。これはオプションで、`SPLIT_HAND_PIN` が未定義のままである場合、EE_HANDS メソッドまたは標準の Let's Splitが使っている MASTER_LEFT / MASTER_RIGHT 定義をまだ使うことができます。
|
||||
|
||||
* `#define EE_HANDS` (`SPLIT_HAND_PIN` が定義されていない場合のみ動作します)
|
||||
* `#define SPLIT_HAND_MATRIX_GRID <out_pin>,<in_pin>`
|
||||
* 左右はキーマトリックスのキースイッチが存在しない交点を使って決定されます。通常、この交点が短絡している(ローレベル)のときに左側と見なされます。もし `#define SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT` が定義されている場合は、ローレベルの時に右側と決定されます。
|
||||
|
||||
* `#define EE_HANDS` (`SPLIT_HAND_PIN` と `SPLIT_HAND_MATRIX_GRID` が定義されていない場合のみ動作します)
|
||||
* `eeprom-lefthand.eep`/`eeprom-righthand.eep` がそれぞれの半分に書き込まれた後で、EEPROM 内に格納されている左右の設定の値を読み込みます。
|
||||
|
||||
* `#define MASTER_RIGHT`
|
||||
@@ -314,10 +324,9 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
```
|
||||
* `LAYOUTS`
|
||||
* このキーボードがサポートする[レイアウト](ja/feature_layouts.md)のリスト
|
||||
* `LINK_TIME_OPTIMIZATION_ENABLE`
|
||||
* キーボードをコンパイルする時に、Link Time Optimization (`LTO`) を有効にします。これは処理に時間が掛かりますが、コンパイルされたサイズを大幅に減らします (そして、ファームウェアが小さいため、追加の時間は分からないくらいです)。ただし、`LTO` が有効な場合、古いマクロと関数の機能が壊れるため、自動的にこれらの機能を無効にします。これは `NO_ACTION_MACRO` と `NO_ACTION_FUNCTION` を自動的に定義することで行われます。
|
||||
* `LTO_ENABLE`
|
||||
* LINK_TIME_OPTIMIZATION_ENABLE と同じ意味です。`LINK_TIME_OPTIMIZATION_ENABLE` の代わりに `LTO_ENABLE` を使うことができます。
|
||||
* キーボードをコンパイルする時に、Link Time Optimization (LTO) を有効にします。これは処理に時間が掛かりますが、コンパイルされたサイズを大幅に減らします (そして、ファームウェアが小さいため、追加の時間は分からないくらいです)。
|
||||
ただし、LTO が有効な場合、古い TMK のマクロと関数の機能が壊れるため、自動的にこれらの機能を無効にします。これは `NO_ACTION_MACRO` と `NO_ACTION_FUNCTION` を自動的に定義することで行われます。(メモ: これは QMK の [マクロ](ja/feature_macros.md) と [レイヤー](ja/feature_layers.md) には影響を与えません。)
|
||||
|
||||
## AVR MCU オプション
|
||||
* `MCU = atmega32u4`
|
||||
@@ -362,10 +371,8 @@ QMK での全ての利用可能な設定にはデフォルトがあります。
|
||||
* MIDI 制御
|
||||
* `UNICODE_ENABLE`
|
||||
* Unicode
|
||||
* `BLUETOOTH_ENABLE`
|
||||
* Adafruit EZ-Key HID で Bluetooth を有効にするレガシーオプション。BLUETOOTH を見てください
|
||||
* `BLUETOOTH`
|
||||
* 現在のオプションは、AdafruitEzKey、AdafruitBLE、RN42
|
||||
* 現在のオプションは、AdafruitBLE、RN42
|
||||
* `SPLIT_KEYBOARD`
|
||||
* 分割キーボード (let's split や bakingpy のキーボードのようなデュアル MCU) のサポートを有効にし、quantum/split_common にある全ての必要なファイルをインクルードします
|
||||
* `CUSTOM_MATRIX`
|
||||
|
67
docs/ja/configurator_step_by_step.md
Normal file
67
docs/ja/configurator_step_by_step.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# QMK Configurator: ステップ・バイ・ステップ
|
||||
|
||||
<!---
|
||||
grep --no-filename "^[ ]*git diff" docs/ja/*.md | sh
|
||||
original document: 0.9.0:docs/configurator_step_by_step.md
|
||||
git diff 0.9.0 HEAD -- docs/configurator_step_by_step.md | cat
|
||||
-->
|
||||
|
||||
このページでは、QMK Configurator でファームウェアを構築する手順を説明します。
|
||||
|
||||
## ステップ 1: キーボードを選ぶ
|
||||
|
||||
ドロップダウンボックスをクリックして、キーマップを作成するキーボードを選択します。
|
||||
|
||||
?> **キーボードに複数のバージョンがある場合は、正しいバージョンを選択してください。**
|
||||
|
||||
大事なことなのでもう一度言います。
|
||||
|
||||
!> **正しいバージョンを選択してください!**
|
||||
|
||||
キーボードが QMK を搭載していると宣伝されていてもリストにない場合は、開発者がまだ作業中か、私たちがまだマージするきっかけがなかった可能性があります。
|
||||
アクティブな [プルリクエスト](https://github.com/qmk/qmk_firmware/pulls?q=is%3Aopen+is%3Apr+label%3Akeyboard) がない場合、[qmk_firmware](https://github.com/qmk/qmk_firmware/issues)で報告して、その特定のキーボードのサポートをリクエストします。
|
||||
製作者自身の GitHub アカウントにある QMK 搭載キーボードもあります。
|
||||
それも再確認してください。
|
||||
|
||||
## ステップ2: キーボードのレイアウトを選択する
|
||||
|
||||
作成したいと思うキーマップに最も近いレイアウトを選択します。一部のキーボードには、まだ十分なレイアウトや正しいレイアウトが定義されていません。これらは将来サポートされる予定です。
|
||||
|
||||
## ステップ3: キーマップの名前を決める
|
||||
|
||||
お好みの名前をキーマップにつけます。
|
||||
|
||||
?> コンパイル時に問題が発生した場合は、もしかすると QMK ファームウェアリポジトリに既に同じ名前が存在しているのかもしれません。名前を変更してみてください。
|
||||
|
||||
## ステップ4: キーマップを定義する
|
||||
|
||||
キーコードの入力は、3つの方法のいずれかで行います。
|
||||
|
||||
1. ドラッグ・アンド・ドロップ
|
||||
2. レイアウト上の空の場所をクリックして、希望するキーコードをクリックします
|
||||
3. レイアウト上の空の場所をクリックして、キーボードの物理キーを押します
|
||||
|
||||
?> マウスをキーの上に置くと、そのキーコードの機能の短い説明文が出ます。より詳細な説明については以下を見てください:
|
||||
|
||||
* [基本的なキーコードリファレンス](ja/keycodes_basic.md)
|
||||
* [高度なキーコードリファレンス](ja/feature_advanced_keycodes.md)
|
||||
|
||||
!> 選択したレイアウトが物理的なビルドと一致しない場合は、使用していないキーは空白のままにしておきます。どのキーが使用されているかわからない場合、例えば、バックスペースキーは1つだが `LAYOUT_all` には2つのキーがある場合は、同じキーコードを両方の場所に配置してください。
|
||||
|
||||
## ステップ5: 後日のためにキーマップを保存する
|
||||
|
||||
キーマップに満足するか、または後で作業したい場合は、`Export Keymap' ボタンを押します。
|
||||
これでキーマップがあなたのコンピュータに保存されます。
|
||||
その後、`Import Keymap` ボタンを押すことで、この .json ファイルを後で読み込むことができます。
|
||||
|
||||
!> **注意:** このファイルは、kbfirmware.com またはその他のツールに使用される .json ファイルと同じ形式ではありません。これらのツールにこの .json を使用したり、QMK Configurator でこれらのツールの .json を使用しようとすると、問題が発生します。
|
||||
|
||||
## ステップ6: ファームウェアをコンパイルする
|
||||
|
||||
緑色の `Compile` ボタンを押します。
|
||||
|
||||
コンパイルが完了すると、緑色の `Download Firmware` ボタンを押すことができます。
|
||||
|
||||
## 次のステップ: キーボードに書き込む(フラッシュする)
|
||||
|
||||
[ファームウェアを書きこむ](ja/newbs_flashing.md) を参照してください。
|
32
docs/ja/configurator_troubleshooting.md
Normal file
32
docs/ja/configurator_troubleshooting.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Configurator トラブルシューティング
|
||||
|
||||
<!---
|
||||
grep --no-filename "^[ ]*git diff" docs/ja/*.md | sh
|
||||
original document: 0.9.0:docs/configurator_troubleshooting.md
|
||||
git diff 0.9.0 HEAD -- docs/configurator_troubleshooting.md | cat
|
||||
-->
|
||||
|
||||
## 私の .json ファイルが動きません
|
||||
|
||||
.json ファイルが QMK Configurator で作ったものの場合、おめでとうございます。バグに遭遇しました。 [qmk_configurator](https://github.com/qmk/qmk_configurator/issues) で報告してください。
|
||||
|
||||
そうでない場合は、... 他の .json ファイルを使用しないようにという、上に書いた注意書きを見逃してませんか?
|
||||
|
||||
#### レイアウトに余分なスペースがありますか?どうすればいいですか?
|
||||
|
||||
もしスペースバーが3つに分かれている場合は、全てスペースバーで埋めるのが最善の方法です。バックスペースや Shift キーについても同じことができます。
|
||||
|
||||
#### キーコードってなに?
|
||||
|
||||
以下を見てください。
|
||||
|
||||
* [基本的なキーコードリファレンス](ja/keycodes_basic.md)
|
||||
* [高度なキーコードリファレンス](ja/feature_advanced_keycodes.md)
|
||||
|
||||
#### コンパイルできません
|
||||
|
||||
キーマップの他のレイヤーを再確認して、おかしなキーが存在しないことを確認してください。
|
||||
|
||||
## 問題とバグ
|
||||
|
||||
私たちは利用者の依頼やバグレポートを常に受け入れています。[qmk_configurator](https://github.com/qmk/qmk_configurator/issues) で報告してください。
|
@@ -31,7 +31,7 @@ keyboards/<keyboard>/matrix.c
|
||||
SRC += matrix.c
|
||||
```
|
||||
|
||||
## マトリックスコードの部分置き換え
|
||||
## マトリックスコードの部分置き換え :id=lite
|
||||
|
||||
カスタムマトリックスを実装する際、定型コードを書かなくてすむように、さまざまなスキャン関数のデフォルト実装を提供しています。
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
# キーボードの挙動をカスタマイズする方法
|
||||
|
||||
<!---
|
||||
original document: 0.8.62:docs/custom_quantum_functions.md
|
||||
git diff 0.8.62 HEAD -- docs/custom_quantum_functions.md | cat
|
||||
original document: 0.10.33:docs/custom_quantum_functions.md
|
||||
git diff 0.10.33 HEAD -- docs/custom_quantum_functions.md | cat
|
||||
-->
|
||||
|
||||
多くの人にとって、カスタムキーボードはボタンの押下をコンピュータに送信するだけではありません。単純なボタンの押下やマクロよりも複雑なことを実行できるようにしたいでしょう。QMK にはコードを挿入したり、機能を上書きしたり、様々な状況でキーボードの挙動をカスタマイズできるフックがあります。
|
||||
@@ -62,7 +62,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_ENTER:
|
||||
// enter が押された時に音を再生します
|
||||
if (record->event.pressed) {
|
||||
PLAY_NOTE_ARRAY(tone_qwerty);
|
||||
PLAY_SONG(tone_qwerty);
|
||||
}
|
||||
return true; // QMK に enter のプレスまたはリリースイベントを送信させます
|
||||
default:
|
||||
@@ -232,7 +232,7 @@ void keyboard_pre_init_user(void) {
|
||||
}
|
||||
```
|
||||
|
||||
### `keyboard_pre_init_*` 関数のドキュメント
|
||||
### `keyboard_pre_init_*` 関数のドキュメント :id=keyboard_pre_init_-function-documentation
|
||||
|
||||
* キーボード/リビジョン: `void keyboard_pre_init_kb(void)`
|
||||
* キーマップ: `void keyboard_pre_init_user(void)`
|
||||
@@ -346,6 +346,11 @@ layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
return state;
|
||||
}
|
||||
```
|
||||
|
||||
特定のレイヤーの状態を確認するには、 `IS_LAYER_ON_STATE(state, layer)` と `IS_LAYER_OFF_STATE(state, layer)` マクロを使います。
|
||||
|
||||
`layer_state_set_*` 関数の外では、グローバルなレイヤー状態を確認するために `IS_LAYER_ON(layer)` と `IS_LAYER_OFF(layer)` マクロを使えます。
|
||||
|
||||
### `layer_state_set_*` 関数のドキュメント
|
||||
|
||||
* キーボード/リビジョン: `layer_state_t layer_state_set_kb(layer_state_t state)`
|
||||
@@ -440,7 +445,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_ENTER:
|
||||
// enter が押された時に音を再生します
|
||||
if (record->event.pressed) {
|
||||
PLAY_NOTE_ARRAY(tone_qwerty);
|
||||
PLAY_SONG(tone_qwerty);
|
||||
}
|
||||
return true; // QMK に enter のプレスまたはリリースイベントを送信させます
|
||||
case RGB_LYR: // これにより、アンダーグローをレイヤー表示として、あるいは通常通りに使うことができます。
|
||||
@@ -451,7 +456,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
layer_state_set(layer_state); // すぐにレイヤーの色を更新します
|
||||
}
|
||||
}
|
||||
return false; break;
|
||||
return false;
|
||||
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // 任意の RGB コード に対して(quantum_keycodes.h を見てください。400行目参照)
|
||||
if (record->event.pressed) { // これはレイヤー表示を無効にします。これを変更する場合は、無効にしたいだろうため。
|
||||
if (user_config.rgb_layer_change) { // 有効な場合のみ
|
||||
@@ -488,56 +493,3 @@ void eeconfig_init_user(void) { // EEPROM がリセットされます!
|
||||
* キーマップ: `void eeconfig_init_user(void)`、`uint32_t eeconfig_read_user(void)` および `void eeconfig_update_user(uint32_t val)`
|
||||
|
||||
`val` は EEPROM に書き込みたいデータの値です。`eeconfig_read_*` 関数は EEPROM から32ビット(DWORD) 値を返します。
|
||||
|
||||
# カスタムタッピング期間
|
||||
|
||||
デフォルトでは、タッピング期間と(`IGNORE_MOD_TAP_INTERRUPT` のような)関連オプションはグローバルに設定されていて、キーでは設定することができません。ほとんどのユーザにとって、これは全然問題ありません。しかし、場合によっては、`LT` キーとは異なるタイムアウトによって、デュアルファンクションキーが大幅に改善されます。なぜなら、一部のキーは他のキーよりも押し続けやすいためです。それぞれにカスタムキーコードを使う代わりに、キーごとに設定可能なタイムアウトの挙動を設定できます。
|
||||
|
||||
キーごとのタイムアウトの挙動を制御するための2つの設定可能なオプションがあります:
|
||||
|
||||
- `TAPPING_TERM_PER_KEY`
|
||||
- `IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
|
||||
|
||||
必要な機能ごとに、`config.h` に `#define` 行を追加する必要があります。
|
||||
|
||||
```
|
||||
#define TAPPING_TERM_PER_KEY
|
||||
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
|
||||
```
|
||||
|
||||
|
||||
## `get_tapping_term` の実装例
|
||||
|
||||
キーコードに基づいて `TAPPING_TERM` を変更するには、次のようなものを `keymap.c` ファイルに追加します:
|
||||
|
||||
```c
|
||||
uint16_t get_tapping_term(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case SFT_T(KC_SPC):
|
||||
return TAPPING_TERM + 1250;
|
||||
case LT(1, KC_GRV):
|
||||
return 130;
|
||||
default:
|
||||
return TAPPING_TERM;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `get_ignore_mod_tap_interrupt` の実装例
|
||||
|
||||
キーコードに基づいて `IGNORE_MOD_TAP_INTERRUPT` の値を変更するには、次のようなものを `keymap.c` ファイルに追加します:
|
||||
|
||||
```c
|
||||
bool get_ignore_mod_tap_interrupt(uint16_t keycode) {
|
||||
switch (keycode) {
|
||||
case SFT_T(KC_SPC):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `get_tapping_term` / `get_ignore_mod_tap_interrupt` 関数のドキュメント
|
||||
|
||||
ここにある他の多くの関数とは異なり、quantum あるいはキーボードレベルの関数を持つ必要はありません (または理由さえありません)。ここではユーザレベルの関数だけが有用なため、そのようにマークする必要はありません。
|
||||
|
69
docs/ja/documentation_best_practices.md
Normal file
69
docs/ja/documentation_best_practices.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# ドキュメントベストプラクティス
|
||||
|
||||
<!---
|
||||
original document: 0.10.33:docs/documentation_best_practices.md
|
||||
git diff 0.10.33 HEAD -- docs/documentation_best_practices.md | cat
|
||||
-->
|
||||
|
||||
このページは QMK のためのドキュメントを作成する時のベストプラクティスを文章化するためのものです。これらのガイドラインに従うことで、一貫したトーンとスタイルを維持することでき、他の人が QMK をより理解しやすくすることができます。
|
||||
|
||||
# ページの開始
|
||||
|
||||
ドキュメントページは通常 H1 ヘッダで始まり、最初の段落を使ってこのページの内容を説明します。この見出しと段落は目次の次にあるため、見出しは短くして空白の無い長い文字列を避けるように気を付けてください。
|
||||
|
||||
例:
|
||||
|
||||
```
|
||||
# My Page Title
|
||||
|
||||
This page covers my super cool feature. You can use this feature to make coffee, squeeze fresh oj, and have an egg mcmuffin and hashbrowns delivered from your local macca's by drone.
|
||||
```
|
||||
|
||||
# 見出し
|
||||
|
||||
通常、ページには複数の "H1" 見出しが有るべきです。H1 と H2 見出しのみが目次に含まれるので、適切に計画してください。目次が広くなりすぎないように、H1 と H2 の見出しでは幅を広げないようにしてください。
|
||||
|
||||
# スタイル付きのヒントブロック
|
||||
|
||||
注意を引くためにテキストの周りにスタイル付きのヒントブロックを描くことができます。
|
||||
|
||||
### 重要なもの
|
||||
|
||||
```
|
||||
!> This is important
|
||||
```
|
||||
|
||||
以下のように表示されます:
|
||||
|
||||
!> This is important
|
||||
|
||||
### 一般的なヒント
|
||||
|
||||
```
|
||||
?> This is a helpful tip.
|
||||
```
|
||||
|
||||
以下のように表示されます:
|
||||
|
||||
?> This is a helpful tip.
|
||||
|
||||
|
||||
# 機能を文章化する
|
||||
|
||||
QMK のために新しい機能を作成した場合、そのドキュメントページを作成してください。長い必要は無く、機能を説明する幾つかの文と、関連するキーコードを列挙した表で十分です。以下は基本的なテンプレートです:
|
||||
|
||||
```markdown
|
||||
# My Cool Feature
|
||||
|
||||
This page describes my cool feature. You can use my cool feature to make coffee and order cream and sugar to be delivered via drone.
|
||||
|
||||
## My Cool Feature Keycodes
|
||||
|
||||
|Long Name|Short Name|Description|
|
||||
|---------|----------|-----------|
|
||||
|KC_COFFEE||Make Coffee|
|
||||
|KC_CREAM||Order Cream|
|
||||
|KC_SUGAR||Order Sugar|
|
||||
```
|
||||
|
||||
ドキュメントを `docs/feature_<my_cool_feature>.md` に配置し、そのファイルを `docs/_summary.md` の適切な場所に追加します。キーコードを追加した場合は、機能ページに戻るリンクとともに `docs/keycodes.md` に追加するようにしてください。
|
45
docs/ja/documentation_templates.md
Normal file
45
docs/ja/documentation_templates.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# ドキュメントテンプレート
|
||||
|
||||
<!---
|
||||
original document: 0.9.19:docs/documentation_templates.md
|
||||
git diff 0.9.19 HEAD -- docs/documentation_templates.md | cat
|
||||
-->
|
||||
|
||||
このページでは、新しいキーマップやキーボードを QMK に提出する際に使うべきテンプレートをまとめています。
|
||||
|
||||
## キーマップ `readme.md` テンプレート :id=keyboard-readmemd-template
|
||||
|
||||
ほとんどのキーマップには、レイアウトを表す画像があります。画像を作成するには、[Keyboard Layout Editor](http://keyboard-layout-editor.com) を使うことができます。画像は [Imgur](http://imgur.com) や別のホスティングサービスにアップロードし、プルリクエストに画像を含めないでください。
|
||||
|
||||
画像の下には、キーマップを理解してもらうための簡単な説明文を書いてください。
|
||||
|
||||
```
|
||||

|
||||
|
||||
# Default Clueboard Layout
|
||||
|
||||
This is the default layout that comes flashed on every Clueboard. For the most
|
||||
part it's a straightforward and easy to follow layout. The only unusual key is
|
||||
the key in the upper left, which sends Escape normally, but Grave when any of
|
||||
the Ctrl, Alt, or GUI modifiers are held down.
|
||||
```
|
||||
|
||||
## キーボード `readme.md` テンプレート
|
||||
|
||||
```
|
||||
# Planck
|
||||
|
||||

|
||||
|
||||
A compact 40% (12x4) ortholinear keyboard kit made and sold by OLKB and Massdrop. [More info on qmk.fm](http://qmk.fm/planck/)
|
||||
|
||||
* Keyboard Maintainer: [Jack Humbert](https://github.com/jackhumbert)
|
||||
* Hardware Supported: Planck PCB rev1, rev2, rev3, rev4, Teensy 2.0
|
||||
* Hardware Availability: [OLKB.com](https://olkb.com), [Massdrop](https://www.massdrop.com/buy/planck-mechanical-keyboard?mode=guest_open)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
make planck/rev4:default
|
||||
|
||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user