summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_summary.md7
-rw-r--r--docs/config_options.md12
-rw-r--r--docs/custom_quantum_functions.md2
-rw-r--r--docs/faq_build.md4
-rw-r--r--docs/feature_advanced_keycodes.md16
-rw-r--r--docs/feature_audio.md3
-rw-r--r--docs/feature_backlight.md25
-rw-r--r--docs/feature_bootmagic.md2
-rw-r--r--docs/feature_combo.md3
-rw-r--r--docs/feature_encoders.md2
-rw-r--r--docs/feature_oled_driver.md49
-rw-r--r--docs/feature_rgb_matrix.md50
-rw-r--r--docs/feature_rgblight.md134
-rw-r--r--docs/feature_space_cadet.md11
-rw-r--r--docs/feature_unicode.md68
-rw-r--r--docs/feature_userspace.md2
-rw-r--r--docs/features.md7
-rw-r--r--docs/getting_started_build_tools.md6
-rw-r--r--docs/getting_started_introduction.md8
-rw-r--r--docs/how_keyboards_work.md4
-rw-r--r--docs/i2c_driver.md29
-rw-r--r--docs/index.html8
-rw-r--r--docs/keycodes.md42
-rw-r--r--docs/newbs_flashing.md4
-rw-r--r--docs/quantum_keycodes.md7
-rw-r--r--docs/reference_configurator_support.md2
-rw-r--r--docs/zh-cn/_summary.md66
-rw-r--r--docs/zh-cn/contributing.md205
-rw-r--r--docs/zh-cn/custom_quantum_functions.md490
-rw-r--r--docs/zh-cn/faq.md6
-rw-r--r--docs/zh-cn/faq_build.md150
-rw-r--r--docs/zh-cn/faq_debug.md233
-rw-r--r--docs/zh-cn/faq_general.md19
-rw-r--r--docs/zh-cn/faq_keymap.md212
-rw-r--r--docs/zh-cn/getting_started_getting_help.md15
-rw-r--r--docs/zh-cn/getting_started_github.md59
-rw-r--r--docs/zh-cn/newbs.md23
-rw-r--r--docs/zh-cn/reference_glossary.md170
38 files changed, 1958 insertions, 197 deletions
diff --git a/docs/_summary.md b/docs/_summary.md
index 043943f1d8..8a40ccd7f2 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -52,18 +52,21 @@
* [Backlight](feature_backlight.md)
* [Bluetooth](feature_bluetooth.md)
* [Bootmagic](feature_bootmagic.md)
- * [Combos](feature_combo)
+ * [Combos](feature_combo.md)
* [Command](feature_command.md)
+ * [Debounce API](feature_debounce_type.md)
* [Dynamic Macros](feature_dynamic_macros.md)
* [Encoders](feature_encoders.md)
* [Grave Escape](feature_grave_esc.md)
+ * [Haptic Feedback](feature_haptic_feedback.md)
+ * [HD44780 LCD Controller](feature_hd44780.md)
* [Key Lock](feature_key_lock.md)
* [Layouts](feature_layouts.md)
* [Leader Key](feature_leader_key.md)
* [LED Matrix](feature_led_matrix.md)
* [Macros](feature_macros.md)
* [Mouse Keys](feature_mouse_keys.md)
- * [OLED Driver](feature_oled_driver)
+ * [OLED Driver](feature_oled_driver.md)
* [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys)
* [Pointing Device](feature_pointing_device.md)
* [PS/2 Mouse](feature_ps2_mouse.md)
diff --git a/docs/config_options.md b/docs/config_options.md
index 3ef00394db..eb0a441ccc 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -76,14 +76,14 @@ This is a C header file that is one of the first things included, and will persi
* `#define B7_AUDIO`
* enables audio on pin B7 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
* `#define BACKLIGHT_PIN B7`
- * pin of the backlight - B5, B6, B7 use PWM, others use softPWM
+ * pin of the backlight - `B5`, `B6`, `B7` and `C6` (and `D4` on ATmega32A) use hardware PWM, others use software implementation
* `#define BACKLIGHT_LEVELS 3`
* number of levels your backlight will have (maximum 15 excluding off)
* `#define BACKLIGHT_BREATHING`
- * enables backlight breathing (only works with backlight pins B5, B6 and B7)
+ * enables backlight breathing
* `#define BREATHING_PERIOD 6`
* the length of one backlight "breath" in seconds
-* `#define DEBOUNCING_DELAY 5`
+* `#define DEBOUNCE 5`
* the delay when reading the value of the pin (5 is default)
* `#define LOCKING_SUPPORT_ENABLE`
* mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap
@@ -93,8 +93,8 @@ This is a C header file that is one of the first things included, and will persi
* key combination that allows the use of magic commands (useful for debugging)
* `#define USB_MAX_POWER_CONSUMPTION`
* sets the maximum power (in mA) over USB for the device (default: 500)
-* `#define SCL_CLOCK 100000L`
- * sets the SCL_CLOCK speed for split keyboards. The default is `100000L` but some boards can be set to `400000L`.
+* `#define F_SCL 100000L`
+ * sets the I2C clock rate speed for keyboards using I2C. The default is `400000L`, except for keyboards using `split_common`, where the default is `100000L`.
## Features That Can Be Disabled
@@ -171,6 +171,8 @@ If you define these options you will enable the associated feature, which may in
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
* `#define TAP_CODE_DELAY 100`
* Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds.
+* `#define TAP_HOLD_CAPS_DELAY 200`
+ * Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPSLOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 200ms if not defined.
## RGB Light Configuration
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 6287b95309..7be82c650f 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -267,7 +267,7 @@ You should use this function if you need custom matrix scanning code. It can als
If the board supports it, it can be "idled", by stopping a number of functions. A good example of this is RGB lights or backlights. This can save on power consumption, or may be better behavior for your keyboard.
-This is controlled by two functions: `suspend_power_down_*` and `suspend_wakeup_init_*`, which are called when the system is board is idled and when it wakes up, respectively.
+This is controlled by two functions: `suspend_power_down_*` and `suspend_wakeup_init_*`, which are called when the system board is idled and when it wakes up, respectively.
### Example suspend_power_down_user() and suspend_wakeup_init_user() Implementation
diff --git a/docs/faq_build.md b/docs/faq_build.md
index 0c1bedd715..23d6a67021 100644
--- a/docs/faq_build.md
+++ b/docs/faq_build.md
@@ -140,8 +140,8 @@ For now, you need to rollback avr-gcc to 7 in brew.
```
brew uninstall --force avr-gcc
-brew install avr-gcc@7
-brew link --force avr-gcc@7
+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)
diff --git a/docs/feature_advanced_keycodes.md b/docs/feature_advanced_keycodes.md
index a6ddf458cc..f748ccd70c 100644
--- a/docs/feature_advanced_keycodes.md
+++ b/docs/feature_advanced_keycodes.md
@@ -256,10 +256,10 @@ If you press a Mod Tap key, tap another key (press and release) and then release
For Instance:
-- `SHFT_T(KC_A)` Down
+- `SFT_T(KC_A)` Down
- `KC_X` Down
- `KC_X` Up
-- `SHFT_T(KC_A)` Up
+- `SFT_T(KC_A)` Up
Normally, if you do all this within the `TAPPING_TERM` (default: 200ms) this will be registered as `ax` by the firmware and host system. With permissive hold enabled, this modifies how this is handled by considering the Mod Tap keys as a Mod if another key is tapped, and would registered as `X` (`SHIFT`+`x`).
@@ -279,9 +279,9 @@ Setting `Ignore Mod Tap Interrupt` requires holding both keys for the `TAPPING_
For Instance:
-- `SHFT_T(KC_A)` Down
+- `SFT_T(KC_A)` Down
- `KC_X` Down
-- `SHFT_T(KC_A)` Up
+- `SFT_T(KC_A)` Up
- `KC_X` Up
Normally, this would send `X` (`SHIFT`+`x`). With `Ignore Mod Tap Interrupt` enabled, holding both keys are required for the `TAPPING_TERM` to register the hold action. A quick tap will output `ax` in this case, while a hold on both will still output `X` (`SHIFT`+`x`).
@@ -303,11 +303,11 @@ When the user holds a key after tap, this repeats the tapped key rather to hold
Example:
-- SHFT_T(KC_A) Down
-- SHFT_T(KC_A) Up
-- SHFT_T(KC_A) Down
+- SFT_T(KC_A) Down
+- SFT_T(KC_A) Up
+- SFT_T(KC_A) Down
- wait more than tapping term...
-- SHFT_T(KC_A) Up
+- SFT_T(KC_A) Up
With default settings, `a` will be sent on the first release, then `a` will be sent on the second press allowing the computer to trigger its auto repeat function.
diff --git a/docs/feature_audio.md b/docs/feature_audio.md
index e1dd4c5a85..7511598bcf 100644
--- a/docs/feature_audio.md
+++ b/docs/feature_audio.md
@@ -175,8 +175,9 @@ You can configure the default, min and max frequencies, the stepping and built i
| `AUDIO_CLICKY_FREQ_DEFAULT` | 440.0f | Sets the default/starting audio frequency for the clicky sounds. |
| `AUDIO_CLICKY_FREQ_MIN` | 65.0f | Sets the lowest frequency (under 60f are a bit buggy). |
| `AUDIO_CLICKY_FREQ_MAX` | 1500.0f | Sets the the highest frequency. Too high may result in coworkers attacking you. |
-| `AUDIO_CLICKY_FREQ_FACTOR` | 1.18921f| Sets the stepping of UP/DOWN key codes. |
+| `AUDIO_CLICKY_FREQ_FACTOR` | 1.18921f| Sets the stepping of UP/DOWN key codes. This is a multiplicative factor. The default steps the frequency up/down by a musical minor third. |
| `AUDIO_CLICKY_FREQ_RANDOMNESS` | 0.05f | Sets a factor of randomness for the clicks, Setting this to `0f` will make each click identical, and `1.0f` will make this sound much like the 90's computer screen scrolling/typing effect. |
+| `AUDIO_CLICKY_DELAY_DURATION` | 1 | An integer note duration where 1 is 1/16th of the tempo, or a sixty-fourth note (see `quantum/audio/musical_notes.h` for implementation details). The main clicky effect will be delayed by this duration. Adjusting this to values around 6-12 will help compensate for loud switches. |
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index 048d75390d..b06db89e4d 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -34,13 +34,14 @@ Hardware PWM is only supported on certain pins of the MCU, so if the backlightin
Hardware PWM is supported according to the following table:
-| Backlight Pin | Hardware timer |
-|---------------|----------------|
-|`B5` | Timer 1 |
-|`B6` | Timer 1 |
-|`B7` | Timer 1 |
-|`C6` | Timer 3 |
-| other | Software PWM |
+| Backlight Pin | Hardware timer |
+|---------------|-------------------------|
+|`B5` | Timer 1 |
+|`B6` | Timer 1 |
+|`B7` | Timer 1 |
+|`C6` | Timer 3 |
+|`D4` | Timer 1 (ATmega32A only)|
+| other | Software PWM |
The [audio feature](feature_audio.md) also uses hardware timers. Please refer to the following table to know what hardware timer the software PWM will use depending on the audio configuration:
@@ -63,11 +64,17 @@ To change the behaviour 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_PINS` |*Not defined*|experimental: see below for more information |
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 15 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 |
+|`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 |
+
+## 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, *low*.
+Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case you must `#define BACKLIGHT_ON_STATE 1`, so that when the transistor is on, the pin is driven *high* instead.
## Multiple backlight pins
diff --git a/docs/feature_bootmagic.md b/docs/feature_bootmagic.md
index 39e4e47f4e..225189ccb7 100644
--- a/docs/feature_bootmagic.md
+++ b/docs/feature_bootmagic.md
@@ -140,7 +140,7 @@ To replace the function, all you need to do is add something like this to your c
```c
void bootmagic_lite(void) {
matrix_scan();
- wait_ms(DEBOUNCING_DELAY * 2);
+ wait_ms(DEBOUNCE * 2);
matrix_scan();
if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
diff --git a/docs/feature_combo.md b/docs/feature_combo.md
index 680adce2dc..4cb1bcda08 100644
--- a/docs/feature_combo.md
+++ b/docs/feature_combo.md
@@ -29,6 +29,7 @@ enum combos {
AB_ESC,
JK_TAB
};
+
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
@@ -44,7 +45,7 @@ For a more complicated implementation, you can use the `process_combo_event` fun
enum combo_events {
ZC_COPY,
XV_PASTE
- };
+};
const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END};
const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END};
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index dd12c91ce3..9ac97a9a16 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -38,7 +38,7 @@ or `keymap.c`:
} else {
tap_code(KC_PGUP);
}
- } else if (index == 1) { /* Second encoder
+ } else if (index == 1) { /* Second encoder */
if (clockwise) {
tap_code(KC_UP);
} else {
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index fcc19515a9..503e438288 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -2,9 +2,19 @@
## OLED Supported Hardware
-128x32 OLED modules using SSD1306 driver IC over I2C. Supported on AVR based keyboards. Possible but untested hardware includes ARM based keyboards and other sized OLED modules using SSD1306 over I2C, such as 128x64.
+OLED modules using SSD1306 or SH1106 driver ICs, communicating over I2C.
+Tested combinations:
-!> Warning: This OLED Driver currently uses the new i2c_master driver from split common code. If your split keyboard uses i2c to communication between sides this driver could cause an address conflict (serial is fine). Please contact your keyboard vendor and ask them to migrate to the latest split common code to fix this.
+| IC driver | Size | Keyboard Platform | Notes |
+|-----------|--------|-------------------|--------------------------|
+| SSD1306 | 128x32 | AVR | Primary support |
+| SSD1306 | 128x64 | AVR | Verified working |
+| SSD1306 | 128x32 | ARM | |
+| SH1106 | 128x64 | AVR | No rotation or scrolling |
+
+Hardware configurations using ARM-based microcontrollers or different sizes of OLED modules may be compatible, but are untested.
+
+!> Warning: This OLED Driver currently uses the new i2c_master driver from split common code. If your split keyboard uses I2C to communicate between sides, this driver could cause an address conflict (serial is fine). Please contact your keyboard vendor and ask them to migrate to the latest split common code to fix this. In addition, the display timeout system to reduce OLED burn-in also uses split common to detect keypresses, so you will need to implement custom timeout logic for non-split common keyboards.
## Usage
@@ -86,17 +96,17 @@ void oled_task_user(void) {
## Basic Configuration
-|Define |Default |Description |
-|-----------------------|---------------|------------------------------------------------|
-|`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` |`224` |The ending characer index for custom fonts |
-|`OLED_FONT_WIDTH` |`6` |The font width |
-|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
-|`OLED_DISABLE_TIMEOUT` |*Not defined* |Disables the built in OLED timeout feature. Useful when implementing custom timeout rules.|
-
-
+| Define | Default | Description |
+|------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------|
+| `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` | `224` | The ending characer index for custom fonts |
+| `OLED_FONT_WIDTH` | `6` | The font width |
+| `OLED_FONT_HEIGHT` | `8` | The font height (untested) |
+| `OLED_DISABLE_TIMEOUT` | *Not defined* | Disables the built in OLED timeout feature. Useful when implementing custom timeout rules. |
+| `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. |
## 128x64 & Custom sized OLED Displays
@@ -108,16 +118,19 @@ void oled_task_user(void) {
|`OLED_DISPLAY_CUSTOM` |*Not defined* |Changes the display defines for use with custom displays.<br />Requires user to implement the below defines. |
|`OLED_DISPLAY_WIDTH` |`128` |The width of the OLED display. |
|`OLED_DISPLAY_HEIGHT` |`32` |The height of the OLED display. |
-|`OLED_MATRIX_SIZE` |`512` |The local buffer size to allocate.<br />`(OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)`|
-|`OLED_BLOCK_TYPE` |`uint16_t` |The unsigned integer type to use for dirty rendering.|
-|`OLED_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.<br />`(sizeof(OLED_BLOCK_TYPE) * 8)`|
-|`OLED_BLOCK_SIZE` |`32` |The size of each block for dirty rendering<br />`(OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)`|
+|`OLED_MATRIX_SIZE` |`512` |The local buffer size to allocate.<br />`(OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)`. |
+|`OLED_BLOCK_TYPE` |`uint16_t` |The unsigned integer type to use for dirty rendering. |
+|`OLED_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.<br />`(sizeof(OLED_BLOCK_TYPE) * 8)`. |
+|`OLED_BLOCK_SIZE` |`32` |The size of each block for dirty rendering<br />`(OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)`. |
+|`OLED_COM_PINS` |`COM_PINS_SEQ` |How the SSD1306 chip maps it's memory to display.<br />Options are `COM_PINS_SEQ`, `COM_PINS_ALT`, `COM_PINS_SEQ_LR`, & `COM_PINS_ALT_LR`. |
|`OLED_SOURCE_MAP` |`{ 0, ... N }` |Precalculated source array to use for mapping source buffer to target OLED memory in 90 degree rendering. |
|`OLED_TARGET_MAP` |`{ 24, ... N }`|Precalculated target array to use for mapping source buffer to target OLED memory in 90 degree rendering. |
### 90 Degree Rotation - Technical Mumbo Jumbo
+!> Rotation is unsupported on the SH1106.
+
```C
// OLED Rotation enum values are flags
typedef enum {
@@ -249,6 +262,8 @@ uint8_t oled_max_chars(void);
uint8_t oled_max_lines(void);
```
+!> Scrolling and rotation are unsupported on the SH1106.
+
## SSD1306.h driver conversion guide
|Old API |Recommended New API |
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index 1e43414676..916fcdce03 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -30,9 +30,11 @@ Configure the hardware via your `config.h`:
#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 25
#define DRIVER_2_LED_TOTAL 24
-#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL
+#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
+!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
+
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
@@ -40,11 +42,11 @@ Define these arrays listing all the LEDs in your `<keyboard>.c`:
```C
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
+ * driver
+ * | R location
+ * | | G location
+ * | | | B location
+ * | | | | */
{0, C1_3, C2_3, C3_3},
....
}
@@ -91,11 +93,11 @@ Define these arrays listing all the LEDs in your `<keyboard>.c`:
```C
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
+ * driver
+ * | R location
+ * | | G location
+ * | | | B location
+ * | | | | */
{0, B_1, A_1, C_1},
....
}
@@ -142,14 +144,16 @@ const led_config_t g_led_config = { {
} };
```
-The first part, `// Key Matrix to LED Index`, tells the system what key this LED represents by using the key's electrical matrix row & col. The second part, `// LED Index to Physical Position` represents the LED's physical position on the keyboard. The first value, `x`, is between 0-224 (inclusive), and the second value, `y`, is between 0-64 (inclusive). This range is due to effect that calculate the center or halves for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents x, y coordinate 0, 0 and the bottom right of your keyboard represents 224, 64. Using this as a basis, you can use the following formula to calculate the physical position:
+The first part, `// Key Matrix to LED Index`, tells the system what key this LED represents by using the key's electrical matrix row & col. The second part, `// LED Index to Physical Position` represents the LED's physical `{ x, y }` position on the keyboard. The default expected range of values for `{ x, y }` is the inclusive range `{ 0..224, 0..64 }`. This default expected range is due to effects that calculate the center of the keyboard for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents `{ x, y }` coordinate `{ 0, 0 }` and the bottom right of your keyboard represents `{ 224, 64 }`. Using this as a basis, you can use the following formula to calculate the physical position:
```C
x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION
y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
```
-Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
+Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
+
+As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `#define RGB_MATRIX_CENTER { 112, 32 }` in their config.h file with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `{ x, y }` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
`// LED Index to Flag` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
@@ -192,10 +196,20 @@ enum rgb_matrix_effects {
RGB_MATRIX_ALPHAS_MODS, // Static dual hue, speed is hue for secondary hue
RGB_MATRIX_GRADIENT_UP_DOWN, // Static gradient top to bottom, speed controls how much gradient changes
RGB_MATRIX_BREATHING, // Single hue brightness cycling animation
+ RGB_MATRIX_BAND_SAT, // Single hue band fading saturation scrolling left to right
+ RGB_MATRIX_BAND_VAL, // Single hue band fading brightness scrolling left to right
+ RGB_MATRIX_BAND_PINWHEEL_SAT, // Single hue 3 blade spinning pinwheel fades saturation
+ RGB_MATRIX_BAND_PINWHEEL_VAL, // Single hue 3 blade spinning pinwheel fades brightness
+ RGB_MATRIX_BAND_SPIRAL_SAT, // Single hue spinning spiral fades saturation
+ RGB_MATRIX_BAND_SPIRAL_VAL, // Single hue spinning spiral fades brightness
RGB_MATRIX_CYCLE_ALL, // Full keyboard solid hue cycling through full gradient
RGB_MATRIX_CYCLE_LEFT_RIGHT, // Full gradient scrolling left to right
RGB_MATRIX_CYCLE_UP_DOWN, // Full gradient scrolling top to bottom
+ RGB_MATRIX_CYCLE_OUT_IN, // Full gradient scrolling out to in
+ RGB_MATRIX_CYCLE_OUT_IN_DUAL, // Full dual gradients scrolling out to in
RGB_MATRIX_RAINBOW_MOVING_CHEVRON, // Full gradent Chevron shapped scrolling left to right
+ RGB_MATRIX_CYCLE_PINWHEEL, // Full gradient spinning pinwheel around center of keyboard
+ RGB_MATRIX_CYCLE_SPIRAL, // Full gradient spinning spiral around center of keyboard
RGB_MATRIX_DUAL_BEACON, // Full gradient spinning around center of keyboard
RGB_MATRIX_RAINBOW_BEACON, // Full tighter gradient spinning around center of keyboard
RGB_MATRIX_RAINBOW_PINWHEELS, // Full dual gradients spinning two halfs of keyboard
@@ -231,11 +245,21 @@ You can disable a single effect by defining `DISABLE_[EFFECT_NAME]` in your `con
|`#define DISABLE_RGB_MATRIX_ALPHAS_MODS` |Disables `RGB_MATRIX_ALPHAS_MODS` |
|`#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN` |Disables `RGB_MATRIX_GRADIENT_UP_DOWN` |
|`#define DISABLE_RGB_MATRIX_BREATHING` |Disables `RGB_MATRIX_BREATHING` |
+|`#define DISABLE_RGB_MATRIX_BAND_SAT` |Disables `RGB_MATRIX_BAND_SAT` |
+|`#define DISABLE_RGB_MATRIX_BAND_VAL` |Disables `RGB_MATRIX_BAND_VAL` |
+|`#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT` |Disables `RGB_MATRIX_BAND_PINWHEEL_SAT` |
+|`#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL` |Disables `RGB_MATRIX_BAND_PINWHEEL_VAL` |
+|`#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT` |Disables `RGB_MATRIX_BAND_SPIRAL_SAT` |
+|`#define DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL` |Disables `RGB_MATRIX_BAND_SPIRAL_VAL` |
|`#define DISABLE_RGB_MATRIX_CYCLE_ALL` |Disables `RGB_MATRIX_CYCLE_ALL` |
|`#define DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT` |Disables `RGB_MATRIX_CYCLE_LEFT_RIGHT` |
|`#define DISABLE_RGB_MATRIX_CYCLE_UP_DOWN` |Disables `RGB_MATRIX_CYCLE_UP_DOWN` |
+|`#define DISABLE_RGB_MATRIX_CYCLE_OUT_IN` |Disables `RGB_MATRIX_CYCLE_OUT_IN` |
+|`#define DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL` |Disables `RGB_MATRIX_CYCLE_OUT_IN_DUAL` |
|`#define DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON` |Disables `RGB_MATRIX_RAINBOW_MOVING_CHEVRON` |
|`#define DISABLE_RGB_MATRIX_DUAL_BEACON` |Disables `RGB_MATRIX_DUAL_BEACON` |
+|`#define DISABLE_RGB_MATRIX_CYCLE_PINWHEEL` |Disables `RGB_MATRIX_CYCLE_PINWHEEL` |
+|`#define DISABLE_RGB_MATRIX_CYCLE_SPIRAL` |Disables `RGB_MATRIX_CYCLE_SPIRAL` |
|`#define DISABLE_RGB_MATRIX_RAINBOW_BEACON` |Disables `RGB_MATRIX_RAINBOW_BEACON` |
|`#define DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS` |Disables `RGB_MATRIX_RAINBOW_PINWHEELS` |
|`#define DISABLE_RGB_MATRIX_RAINDROPS` |Disables `RGB_MATRIX_RAINDROPS` |
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md
index 1e0ce91473..be4ddfa729 100644
--- a/docs/feature_rgblight.md
+++ b/docs/feature_rgblight.md
@@ -129,7 +129,7 @@ The following options are used to tweak the various animations:
|`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` |`360` |Range adjustment for the rainbow swirl effect to get different swirls |
+|`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 |
### Example Usage to Reduce Memory Footprint
@@ -176,44 +176,100 @@ const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
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:
-|Function |Description |
-|--------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
-|`rgblight_enable()` |Turn LEDs on, based on their previous state |
-|`rgblight_enable_noeeprom()` |Turn LEDs on, based on their previous state (not written to EEPROM) |
-|`rgblight_disable()` |Turn LEDs off |
-|`rgblight_disable_noeeprom()` |Turn LEDs off (not written to EEPROM) |
-|`rgblight_mode(x)` |Set the mode, if RGB animations are enabled |
-|`rgblight_mode_noeeprom(x)` |Set the mode, if RGB animations are enabled (not written to EEPROM) |
-|`rgblight_setrgb(r, g, b)` |Set all LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
-|`rgblight_setrgb_at(r, g, b, led)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `led` is between 0 and `RGBLED_NUM` (not written to EEPROM) |
+### Utility Functions
+|Function |Description |
+|--------------------------------------------|-------------------------------------------------------------------|
+|`sethsv(hue, sat, val, ledbuf)` |Set ledbuf to the given HSV value |
+|`sethsv_raw(hue, sat, val, ledbuf)` |Set ledbuf to the given HSV value without RGBLIGHT_LIMIT_VAL check |
+|`setrgb(r, g, b, ledbuf)` |Set ledbuf to the given RGB value where `r`/`g`/`b` |
+
+### Low level Functions
+|Function |Description |
+|--------------------------------------------|-------------------------------------------|
+|`rgblight_set()` |Flash out led buffers to LEDs |
+|`rgblight_set_clipping_range(pos, num)` |Set clipping Range. see [Clipping Range](#clipping-range) |
+
+Example:
+```c
+sethsv(HSV_WHITE, (LED_TYPE *)&led[0]); // led 0
+sethsv(HSV_RED, (LED_TYPE *)&led[1]); // led 1
+sethsv(HSV_GREEN, (LED_TYPE *)&led[2]); // led 2
+rgblight_set(); // Utility functions do not call rgblight_set() automatically, so they need to be called explicitly.
+```
+
+### Effects and Animations Functions
+#### effect range setting
+|Function |Description |
+|--------------------------------------------|------------------|
+|`rgblight_set_effect_range(pos, num)` |Set Effects Range |
+
+#### direct operation
+|Function |Description |
+|--------------------------------------------|-------------|
+|`rgblight_setrgb_at(r, g, b, index)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `index` is between 0 and `RGBLED_NUM` (not written to EEPROM) |
+|`rgblight_sethsv_at(h, s, v, index)` |Set a single LED to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `index` is between 0 and `RGBLED_NUM` (not written to EEPROM) |
|`rgblight_setrgb_range(r, g, b, start, end)`|Set a continuous range of LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
-|`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
-|`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
-|`rgblight_sethsv(h, s, v)` |Set all LEDs to the given HSV value where `h` is between 0 and 360 and `s`/`v` are between 0 and 255 |
-|`rgblight_sethsv_noeeprom(h, s, v)` |Set all LEDs to the given HSV value where `h` is between 0 and 360 and `s`/`v` are between 0 and 255 (not written to EEPROM) |
-|`rgblight_sethsv_at(h, s, v, led)` |Set a single LED to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255, and `led` is between 0 and `RGBLED_NUM` (not written to EEPROM)|
-|`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
-|`rgblight_sethsv_master(h, s, v)` |Set the LEDs on the master side to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255 (not written to EEPROM) |
-|`rgblight_sethsv_slave(h, s, v)` |Set the LEDs on the slave side to the given HSV value, where `h` is between 0 and 360, `s`/`v` are between 0 and 255 (not written to EEPROM) |
-|`rgblight_toggle()` |Toggle all LEDs between on and off |
-|`rgblight_toggle_noeeprom()` |Toggle all LEDs between on and off (not written to EEPROM) |
-|`rgblight_step()` |Change the mode to the next RGB animation in the list of enabled RGB animations |
-|`rgblight_step_noeeprom()` |Change the mode to the next RGB animation in the list of enabled RGB animations (not written to EEPROM) |
-|`rgblight_step_reverse()` |Change the mode to the previous RGB animation in the list of enabled RGB animations |
-|`rgblight_step_reverse_noeeprom()` |Change the mode to the previous RGB animation in the list of enabled RGB animations (not written to EEPROM) |
-|`rgblight_increase_hue()` |Increase the hue for all LEDs. This wraps around at maximum hue |
-|`rgblight_increase_hue_noeeprom()` |Increase the hue for all LEDs. This wraps around at maximum hue (not written to EEPROM) |
-|`rgblight_decrease_hue()` |Decrease the hue for all LEDs. This wraps around at minimum hue |
-|`rgblight_decrease_hue_noeeprom()` |Decrease the hue for all LEDs. This wraps around at minimum hue (not written to EEPROM) |
-|`rgblight_increase_sat()` |Increase the saturation for all LEDs. This wraps around at maximum saturation |
-|`rgblight_increase_sat_noeeprom()` |Increase the saturation for all LEDs. This wraps around at maximum saturation (not written to EEPROM) |
-|`rgblight_decrease_sat()` |Decrease the saturation for all LEDs. This wraps around at minimum saturation |
-|`rgblight_decrease_sat_noeeprom()` |Decrease the saturation for all LEDs. This wraps around at minimum saturation (not written to EEPROM) |
-|`rgblight_increase_val()` |Increase the value for all LEDs. This wraps around at maximum value |
-|`rgblight_increase_val_noeeprom()` |Increase the value for all LEDs. This wraps around at maximum value (not written to EEPROM) |
-|`rgblight_decrease_val()` |Decrease the value for all LEDs. This wraps around at minimum value |
-|`rgblight_decrease_val_noeeprom()` |Decrease the value for all LEDs. This wraps around at minimum value (not written to EEPROM) |
-|`rgblight_set_clipping_range(pos, num)` |Set clipping Range |
+|`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
+|`rgblight_setrgb(r, g, b)` |Set effect range LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
+|`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
+|`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
+|`rgblight_sethsv_master(h, s, v)` |Set the LEDs on the master side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
+|`rgblight_sethsv_slave(h, s, v)` |Set the LEDs on the slave side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
+
+Example:
+```c
+rgblight_sethsv(HSV_WHITE, 0); // led 0
+rgblight_sethsv(HSV_RED, 1); // led 1
+rgblight_sethsv(HSV_GREEN, 2); // led 2
+// The above functions automatically calls rgblight_set(), so there is no need to call it explicitly.
+// Note that it is inefficient to call repeatedly.
+```
+
+#### effect mode change
+|Function |Description |
+|--------------------------------------------|-------------|
+|`rgblight_mode(x)` |Set the mode, if RGB animations are enabled |
+|`rgblight_mode_noeeprom(x)` |Set the mode, if RGB animations are enabled (not written to EEPROM) |
+|`rgblight_step()` |Change the mode to the next RGB animation in the list of enabled RGB animations |
+|`rgblight_step_noeeprom()` |Change the mode to the next RGB animation in the list of enabled RGB animations (not written to EEPROM) |
+|`rgblight_step_reverse()` |Change the mode to the previous RGB animation in the list of enabled RGB animations |
+|`rgblight_step_reverse_noeeprom()` |Change the mode to the previous RGB animation in the list of enabled RGB animations (not written to EEPROM) |
+
+#### effects mode disable/enable
+|Function |Description |
+|--------------------------------------------|-------------|
+|`rgblight_toggle()` |Toggle effect range LEDs between on and off |
+|`rgblight_toggle_noeeprom()` |Toggle effect range LEDs between on and off (not written to EEPROM) |
+|`rgblight_enable()` |Turn effect range LEDs on, based on their previous state |
+|`rgblight_enable_noeeprom()` |Turn effect range LEDs on, based on their previous state (not written to EEPROM) |
+|`rgblight_disable()` |Turn effect range LEDs off |
+|`rgblight_disable_noeeprom()` |Turn effect range LEDs off (not written to EEPROM) |
+
+#### hue, sat, val change
+|Function |Description |
+|--------------------------------------------|-------------|
+|`rgblight_increase_hue()` |Increase the hue for effect range LEDs. This wraps around at maximum hue |
+|`rgblight_increase_hue_noeeprom()` |Increase the hue for effect range LEDs. This wraps around at maximum hue (not written to EEPROM) |
+|`rgblight_decrease_hue()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue |
+|`rgblight_decrease_hue_noeeprom()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue (not written to EEPROM) |
+|`rgblight_increase_sat()` |Increase the saturation for effect range LEDs. This wraps around at maximum saturation |
+|`rgblight_increase_sat_noeeprom()` |Increase the saturation for effect range LEDs. This wraps around at maximum saturation (not written to EEPROM) |
+|`rgblight_decrease_sat()` |Decrease the saturation for effect range LEDs. This wraps around at minimum saturation |
+|`rgblight_decrease_sat_noeeprom()` |Decrease the saturation for effect range LEDs. This wraps around at minimum saturation (not written to EEPROM) |
+|`rgblight_increase_val()` |Increase the value for effect range LEDs. This wraps around at maximum value |
+|`rgblight_increase_val_noeeprom()` |Increase the value for effect range LEDs. This wraps around at maximum value (not written to EEPROM) |
+|`rgblight_decrease_val()` |Decrease the value for effect range LEDs. This wraps around at minimum value |
+|`rgblight_decrease_val_noeeprom()` |Decrease the value for effect range LEDs. This wraps around at minimum value (not written to EEPROM) |
+|`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) |
+
+#### query
+|Function |Description |
+|-----------------------|-----------------|
+|`rgblight_get_mode()` |Get current mode |
+|`rgblight_get_hue()` |Get current hue |
+|`rgblight_get_sat()` |Get current sat |
+|`rgblight_get_val()` |Get current val |
## Colors
@@ -324,4 +380,6 @@ In addition to setting the Clipping Range, you can use `RGBLIGHT_LED_MAP` togeth
```
<img src="https://user-images.githubusercontent.com/2170248/55743747-119e4c00-5a6e-11e9-91e5-013203ffae8a.JPG" alt="clip mapped" width="70%"/>
+## Hardware Modification
+
If your keyboard lacks onboard underglow LEDs, you may often be able to solder on an RGB LED strip yourself. You will need to find an unused pin to wire to the data pin of your LED strip. Some keyboards may break out unused pins from the MCU to make soldering easier. The other two pins, VCC and GND, must also be connected to the appropriate power pins.
diff --git a/docs/feature_space_cadet.md b/docs/feature_space_cadet.md
index 5c375c5184..41a44627e3 100644
--- a/docs/feature_space_cadet.md
+++ b/docs/feature_space_cadet.md
@@ -20,7 +20,7 @@ Firstly, in your keymap, do one of the following:
|`KC_RCPC` |Right Control when held, `)` when tapped |
|`KC_LAPO` |Left Alt when held, `(` when tapped |
|`KC_RAPC` |Right Alt when held, `)` when tapped |
-|`KC_SFTENT`|Right Shift when held, `Enter` when tapped |
+|`KC_SFTENT`|Right Shift when held, Enter when tapped |
## Caveats
@@ -38,11 +38,12 @@ By default Space Cadet assumes a US ANSI layout, but if your layout uses differe
|----------------|-------------------------------|---------------------------------------------------------------------------------|
|`LSPO_KEYS` |`KC_LSFT, LSPO_MOD, LSPO_KEY` |Send `KC_LSFT` when held, the mod and key defined by `LSPO_MOD` and `LSPO_KEY`. |
|`RSPC_KEYS` |`KC_RSFT, RSPC_MOD, RSPC_KEY` |Send `KC_RSFT` when held, the mod and key defined by `RSPC_MOD` and `RSPC_KEY`. |
-|`LCPO_KEYS` |`KC_LCTL, KC_LCTL, KC_9` |Send `KC_LCTL` when held, the mod `KC_LCTL` with the key `KC_9` when tapped. |
-|`RCPC_KEYS` |`KC_RCTL, KC_RCTL, KC_0` |Send `KC_RCTL` when held, the mod `KC_RCTL` with the key `KC_0` when tapped. |
-|`LAPO_KEYS` |`KC_LALT, KC_LALT, KC_9` |Send `KC_LALT` when held, the mod `KC_LALT` with the key `KC_9` when tapped. |
-|`RAPC_KEYS` |`KC_RALT, KC_RALT, KC_0` |Send `KC_RALT` when held, the mod `KC_RALT` with the key `KC_0` when tapped. |
+|`LCPO_KEYS` |`KC_LCTL, KC_LSFT, KC_9` |Send `KC_LCTL` when held, the mod `KC_LSFT` with the key `KC_9` when tapped. |
+|`RCPC_KEYS` |`KC_RCTL, KC_RSFT, KC_0` |Send `KC_RCTL` when held, the mod `KC_RSFT` with the key `KC_0` when tapped. |
+|`LAPO_KEYS` |`KC_LALT, KC_LSFT, KC_9` |Send `KC_LALT` when held, the mod `KC_LSFT` with the key `KC_9` when tapped. |
+|`RAPC_KEYS` |`KC_RALT, KC_RSFT, KC_0` |Send `KC_RALT` when held, the mod `KC_RSFT` with the key `KC_0` when tapped. |
|`SFTENT_KEYS` |`KC_RSFT, KC_TRNS, SFTENT_KEY` |Send `KC_RSFT` when held, no mod with the key `SFTENT_KEY` when tapped. |
+|`SPACE_CADET_MODIFIER_CARRYOVER` |*Not defined* |Store current modifiers before the hold mod is pressed and use them with the tap mod and keycode. Useful for when you frequently release a modifier before triggering Space Cadet. |
## Obsolete Configuration
diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md
index 778cdc69cb..bd1f4fa5ae 100644
--- a/docs/feature_unicode.md
+++ b/docs/feature_unicode.md
@@ -1,28 +1,44 @@
# Unicode Support
-There are three Unicode keymap definition methods available in QMK:
+Unicode characters can be input straight from your keyboard! There are some limitations, however.
-## `UNICODE_ENABLE`
+QMK has three different methods for enabling Unicode input and defining keycodes:
-Supports Unicode up to `0x7FFF`. This covers characters for most modern languages, as well as symbols, but it doesn't cover emoji. The keycode function is `UC(c)` in the keymap, where _c_ is the code point's number (preferably hexadecimal, up to 4 digits long). For example: `UC(0x45B)`, `UC(0x30C4)`.
+## Basic Unicode
-## `UNICODEMAP_ENABLE`
+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.
-Supports Unicode up to `0x10FFFF` (all possible code points). You need to maintain a separate mapping table `const uint32_t PROGMEM unicode_map[] = {...}` in your keymap file. The keycode function is `X(i)`, where _i_ is an array index into the mapping table. The table may contain at most 16384 entries.
+Add the following to your `rules.mk`:
-You may want to have an enum to make referencing easier. So, you could add something like this to your keymap file:
+```make
+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)`.
+
+## Unicode Map
+
+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.
+
+Add the following to your `rules.mk`:
+
+```make
+UNICODEMAP_ENABLE = yes
+```
+
+Then add `X(i)` keycodes to your keymap, where _i_ is an array index into the mapping table:
```c
enum unicode_names {
- BANG,
- IRONY,
- SNEK,
+ BANG,
+ IRONY,
+ SNEK
};
const uint32_t PROGMEM unicode_map[] = {
- [BANG] = 0x203D, // 鈥
- [IRONY] = 0x2E2E, // 飧
- [SNEK] = 0x1F40D, // 馃悕
+ [BANG] = 0x203D, // 鈥
+ [IRONY] = 0x2E2E, // 飧
+ [SNEK] = 0x1F40D, // 馃悕
};
```
@@ -30,27 +46,33 @@ Then you can use `X(BANG)`, `X(SNEK)` etc. in your keymap.
### Lower and Upper Case
-Characters often come in lower and upper case pairs, for example: 氓, 脜. 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.
+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 blends Unicode keys in with regular alphas.
+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.
-## `UCIS_ENABLE`
+## 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.
-Supports Unicode up to `0x10FFFF` (all possible code points). As with `UNICODEMAP`, you need to maintain a mapping table in your keymap file. However, there are no built-in keycodes for this feature 鈥 you have to add a keycode or function that calls `qk_ucis_start()`. Once this function has been called, you can type the corresponding mnemonic for your character, then hit Space or Enter to complete it, or Esc to cancel. If the mnemonic matches an entry in your table, the typed text will automatically be erased and the corresponding Unicode character inserted.
+Add the following to your `rules.mk`:
+
+```make
+UCIS_ENABLE = yes
+```
-For instance, you could define a table like this in your keymap file:
+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("kiss", 0x1F619) // 馃槞
);
```
-To use it, call `qk_ucis_start()`, then type "rofl" and hit Enter. QMK should erase the "rofl" text and insert the laughing emoji.
+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.
### Customization
@@ -68,7 +90,7 @@ Unicode input in QMK works by inputting a sequence of characters to the OS, sort
The following input modes are available:
-* **`UC_OSX`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with `UNICODEMAP`).
+* **`UC_OSX`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map).
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_OSX`](#input-key-configuration) with another keycode.
@@ -112,7 +134,7 @@ You can also switch the input mode by calling `set_unicode_input_mode(x)` in you
```c
void eeconfig_init_user(void) {
- set_unicode_input_mode(UC_LNX);
+ set_unicode_input_mode(UC_LNX);
}
```
diff --git a/docs/feature_userspace.md b/docs/feature_userspace.md
index d82d43138d..2f119c8bde 100644
--- a/docs/feature_userspace.md
+++ b/docs/feature_userspace.md
@@ -110,7 +110,7 @@ QMK has a bunch of [functions](custom_quantum_functions.md) that have [`_quantum
However, you can actually add support for keymap version, so that you can use it in both your userspace and your keymap!
-For instance, lets looks at the `layer_state_set_user` function. Lets enable the [Tri Layer State](ref_functions.md#olkb-tri-layers) functionalitly to all of our boards, and then still have your `keymap.c` still able to use this functionality.
+For instance, let's look at the `layer_state_set_user()` function. You can enable the [Tri Layer State](ref_functions.md#olkb-tri-layers) functionality on all of your boards, while also retaining the Tri Layer functionality in your `keymap.c` files.
In your `<name.c>` file, you'd want to add this:
```c
diff --git a/docs/features.md b/docs/features.md
index cb69df35d7..f9ef51eae2 100644
--- a/docs/features.md
+++ b/docs/features.md
@@ -7,12 +7,15 @@ QMK has a staggering number of features for building your keyboard. It can take
* [Audio](feature_audio.md) - Connect a speaker to your keyboard for audio feedback, midi support, and music mode.
* [Auto Shift](feature_auto_shift.md) - Tap for the normal key, hold slightly longer for its shifted state.
* [Backlight](feature_backlight.md) - LED lighting support for your keyboard.
+* [Bluetooth](feature_bluetooth.md) - BlueTooth support for your keyboard.
* [Bootmagic](feature_bootmagic.md) - Adjust the behavior of your keyboard using hotkeys.
* [Combos](feature_combo.md) - Custom actions for multiple key holds.
* [Command](feature_command.md) - Runtime version of bootmagic (Formerly known as "Magic").
+* [Debounce API](feature_debounce_type.md) - Customization of debouncing algorithms, and the ability to add more/custom debouncing.
* [Dynamic Macros](feature_dynamic_macros.md) - Record and playback macros from the keyboard itself.
* [Encoders](feature_encoders.md) - Rotary encoders!
* [Grave Escape](feature_grave_esc.md) - Lets you use a single key for Esc and Grave.
+* [Haptic Feedback](feature_haptic_feedback.md) - Add haptic feedback drivers to your board.
* [HD44780 LCD Display](feature_hd44780.md) - Support for LCD character displays using the HD44780 standard.
* [Key Lock](feature_key_lock.md) - Lock a key in the "down" state.
* [Layouts](feature_layouts.md) - Use one keymap with any keyboard that supports your layout.
@@ -20,7 +23,8 @@ QMK has a staggering number of features for building your keyboard. It can take
* [LED Matrix](feature_led_matrix.md) - LED Matrix single color lights for per key lighting (Single Color, not RGB).
* [Macros](feature_macros.md) - Send multiple key presses when pressing only one physical key.
* [Mouse keys](feature_mouse_keys.md) - Control your mouse pointer from your keyboard.
-* [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys) - Sticky Keys, lets hit a key rather than holding it.
+* [OLED Driver](feature_oled_driver.md) - Add OLED screens to your keyboard.
+* [One Shot Keys](feature_advanced_keycodes.md#one-shot-keys) - Sticky Keys, lets you hit a key rather than holding it.
* [Pointing Device](feature_pointing_device.md) - Framework for connecting your custom pointing device to your keyboard.
* [PS2 Mouse](feature_ps2_mouse.md) - Driver for connecting a PS/2 mouse directly to your keyboard.
* [RGB Light](feature_rgblight.md) - RGB lighting for your keyboard.
@@ -33,3 +37,4 @@ QMK has a staggering number of features for building your keyboard. It can take
* [Thermal Printer](feature_thermal_printer.md) - Connect a thermal printer to your keyboard to be able to toggle on a printed log of everything you type.
* [Unicode](feature_unicode.md) - Unicode input support.
* [Userspace](feature_userspace.md) - Share code between different keymaps and keyboards.
+* [Velocikey](feature_velocikey.md) - Allows changes in RGB animation speed based on WPM/Typing speed.
diff --git a/docs/getting_started_build_tools.md b/docs/getting_started_build_tools.md
index 0e1acca66a..268cc94c38 100644
--- a/docs/getting_started_build_tools.md
+++ b/docs/getting_started_build_tools.md
@@ -62,14 +62,14 @@ If you're using [homebrew,](http://brew.sh/) you can use the following commands:
brew tap osx-cross/avr
brew tap PX4/homebrew-px4
brew update
- brew install avr-gcc@7
- brew link --force avr-gcc@7
+ brew install avr-gcc@8
+ brew link --force avr-gcc@8
brew install dfu-programmer
brew install dfu-util
brew install gcc-arm-none-eabi
brew install avrdude
-This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line. Note that the `make` and `make install` portion during the homebrew installation of `avr-gcc@7` can take over 20 minutes and exhibit high CPU usage.
+This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line. Note that the `make` and `make install` portion during the homebrew installation of `avr-gcc@8` can take over 20 minutes and exhibit high CPU usage.
## Windows with msys2 (recommended)
diff --git a/docs/getting_started_introduction.md b/docs/getting_started_introduction.md
index 3b6a488ed6..e183d77eeb 100644
--- a/docs/getting_started_introduction.md
+++ b/docs/getting_started_introduction.md
@@ -12,11 +12,17 @@ Within the folder `users` is a directory for each user. This is a place for user
### Keyboard Project Structure
-Within the folder `keyboards` and its subfolder `handwired` is a directory for each keyboard project, for example `qmk_firmware/keyboards/clueboard`. Within it you'll find the following structure:
+Within the folder `keyboards`, its subfolder `handwired` and its vendor and manufacture subdirectories e.g. `clueboard` is a directory for each keyboard project, for example `qmk_firmware/keyboards/clueboard/2x1800`. Within it, you'll find the following structure:
* `keymaps/`: Different keymaps that can be built
* `rules.mk`: The file that sets the default "make" options. Do not edit this file directly, instead use a keymap specific `rules.mk`.
* `config.h`: The file that sets the default compile time options. Do not edit this file directly, instead use a keymap specific `config.h`.
+* `info.json`: The file used for setting layout for QMK Configurator. See [Configurator Support](reference_configurator_support.md) for more information.
+* `readme.md`: A brief overview of the keyboard.
+* `<keyboardName>.h`: This file is where the keyboard layout is defined against the keyboard's switch matrix.
+* `<keyboardName>.c`: This file is where you can find custom code for the keyboard.
+
+For more information on project structure, see [QMK Keyboard Guidelines](hardware_keyboard_guidelines.md).
### Keymap Structure
diff --git a/docs/how_keyboards_work.md b/docs/how_keyboards_work.md
index 0772f055d6..5697a21872 100644
--- a/docs/how_keyboards_work.md
+++ b/docs/how_keyboards_work.md
@@ -63,10 +63,10 @@ You may wonder why a keyboard layout containing all of Unicode is not devised th
## How to (Maybe) Enter Unicode Characters
-You can have the firmware send *sequences of keys* to use the [software Unicode Input Method](https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input) of the target operating system, thus effectively entering characters independently of the layout defined in the OS.
+You can have the firmware send *sequences of keys* to use the [software Unicode Input Method](https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_input) of the target operating system, thus effectively entering characters independently of the layout defined in the OS.
Yet, it does come with multiple disadvantages:
- - Tied to a specific OS a a time (need recompilation when changing OS);
+ - Tied to a specific OS at a time (need recompilation when changing OS);
- Within a given OS, does not work in all software;
- Limited to a subset of Unicode on some systems.
diff --git a/docs/i2c_driver.md b/docs/i2c_driver.md
index bb1a2d74ff..4a47a92b11 100644
--- a/docs/i2c_driver.md
+++ b/docs/i2c_driver.md
@@ -65,11 +65,30 @@ By default the I2C1 hardware driver is assumed to be used. If another hardware d
STM32 MCUs allows a variety of pins to be configured as I2C pins depending on the hardware driver used. By default B6 and B7 are set to I2C. You can use these defines to set your i2c pins:
-| Variable | Description | Default |
-|-------------|----------------------------------------------|---------|
-| `I2C1_BANK` | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`) | `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` |
+| Variable | Description | Default |
+|--------------------------|----------------------------------------------------------------------------------------------|---------|
+| `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_BANK` (deprecated) | The bank of pins (`GPIOA`, `GPIOB`, `GPIOC`), superceded by `I2C1_SCL_BANK`, `I2C1_SDA_BANK` | `GPIOB` |
+
+STM32 MCUs allow for different timing parameters when configuring I2C. These can be modified using the following parameters, using https://www.st.com/en/embedded-software/stsw-stm32126.html as a reference:
+
+| Variable | Default |
+|-----------------------|---------|
+| `I2C1_TIMINGR_PRESC` | `15U` |
+| `I2C1_TIMINGR_SCLDEL` | `4U` |
+| `I2C1_TIMINGR_SDADEL` | `2U` |
+| `I2C1_TIMINGR_SCLH` | `15U` |
+| `I2C1_TIMINGR_SCLL` | `21U` |
+
+STM32 MCUs allow for different "alternate function" modes when configuring GPIO pins. These are required to switch the pins used to I2C mode. See the respective datasheet for the appropriate values for your MCU.
+
+| Variable | Default |
+|---------------------|---------|
+| `I2C1_SCL_PAL_MODE` | `4` |
+| `I2C1_SDA_PAL_MODE` | `4` |
You can also overload the `void i2c_init(void)` function, which has a weak attribute. If you do this the configuration variables above will not be used. Please consult the datasheet of your MCU for the available GPIO configurations. The following is an example initialization function:
diff --git a/docs/index.html b/docs/index.html
index d6fdbdbcc1..8190450728 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -5,7 +5,13 @@
<title>QMK Firmware</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+ <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+ <meta property="og:title" content="QMK Firmware Docs">
+ <meta property="og:type" content="website">
+ <meta property="og:description" content="The full documenation of the open-source firmware">
+ <meta property="og:image" content="https://i.imgur.com/svjvIrw.jpg">
+ <meta property="og:url" content="https://docs.qmk.fm">
+ <meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css" title="light">
<link rel="stylesheet" href="qmk.css" title="dark" disabled>
<link rel="stylesheet" href="sidebar.css" />
diff --git a/docs/keycodes.md b/docs/keycodes.md
index c0e6aa5c63..bd4dd61a5b 100644
--- a/docs/keycodes.md
+++ b/docs/keycodes.md
@@ -216,6 +216,11 @@ This is a reference only. Each group of keys links to the page documenting their
|`KC_GESC` |`GRAVE_ESC`|Escape when tapped, <code>&#96;</code> when pressed with Shift or GUI|
|`KC_LSPO` | |Left Shift when held, `(` when tapped |
|`KC_RSPC` | |Right Shift when held, `)` when tapped |
+|`KC_LCPO` | |Left Control when held, `(` when tapped |
+|`KC_RCPC` | |Right Control when held, `)` when tapped |
+|`KC_LAPO` | |Left Alt when held, `(` when tapped |
+|`KC_RAPC` | |Right Alt when held, `)` when tapped |
+|`KC_SFTENT` | |Right Shift when held, Enter when tapped |
|`KC_LEAD` | |The [Leader key](feature_leader_key.md) |
|`KC_LOCK` | |The [Lock key](feature_key_lock.md) |
|`FUNC(n)` |`F(n)` |Call `fn_action(n)` (deprecated) |
@@ -293,7 +298,7 @@ This is a reference only. Each group of keys links to the page documenting their
|`LM(layer, mod)`|Momentarily turn on `layer` (like MO) with `mod` active as well. Where `mod` is a mods_bit. Mods can be viewed [here](https://docs.qmk.fm/#/feature_advanced_keycodes?id=mod-tap). Example Implementation: `LM(LAYER_1, MOD_LALT)`|
|`LT(layer, kc)` |Turn on `layer` when held, `kc` when tapped |
|`TG(layer)` |Toggle `layer` on or off |
-|`TO(layer)` |Turn on `layer` when pressed |
+|`TO(layer)` |Turns on `layer` and turns off all other layers, except the default layer |
|`TT(layer)` |Normally acts like MO unless it's tapped multiple times, which toggles `layer` on |
## [Mouse Keys](feature_mouse_keys.md)
@@ -339,23 +344,24 @@ This is a reference only. Each group of keys links to the page documenting their
## [Mod-Tap Keys](feature_advanced_keycodes.md#mod-tap)
-|Key |Aliases |Description |
-|------------|-----------------------------------------------------------------|-------------------------------------------------------|
-|`LCTL_T(kc)`|`CTL_T(kc)` |Left Control when held, `kc` when tapped |
-|`LSFT_T(kc)`|`SFT_T(kc)` |Left Shift when held, `kc` when tapped |
-|`LALT_T(kc)`|`ALT_T(kc)` |Left Alt when held, `kc` when tapped |
-|`LGUI_T(kc)`|`LCMD_T(kc)`, `LWIN_T(kc)`, `GUI_T(kc)`, `CMD_T(kc)`, `WIN_T(kc)`|Left GUI when held, `kc` when tapped |
-|`RCTL_T(kc)`| |Right Control when held, `kc` when tapped |
-|`RSFT_T(kc)`| |Right Shift when held, `kc` when tapped |
-|`RALT_T(kc)`|`ALGR_T(kc)` |Right Alt when held, `kc` when tapped |
-|`RGUI_T(kc)`|`RCMD_T(kc)`, `RWIN_T(kc)` |Right GUI when held, `kc` when tapped |
-|`SGUI_T(kc)`|`SCMD_T(kc)`, `SWIN_T(kc)` |Left Shift and GUI when held, `kc` when tapped |
-|`LCA_T(kc)` | |Left Control and Alt when held, `kc` when tapped |
-|`LCAG_T(kc)`| |Left Control, Alt and GUI when held, `kc` when tapped |
-|`RCAG_T(kc)`| |Right Control, Alt and GUI when held, `kc` when tapped |
-|`C_S_T(kc)` | |Left Control and Shift when held, `kc` when tapped |
-|`MEH_T(kc)` | |Left Control, Shift and Alt when held, `kc` when tapped|
-|`HYPR_T(kc)`|`ALL_T(kc)` |Left Control, Shift, Alt and GUI when held, `kc` when tapped - more info [here](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)|
+|Key |Aliases |Description |
+|-------------|-----------------------------------------------------------------|-------------------------------------------------------|
+|`MT(mod, kc)`| |`mod` when held, `kc` when tapped |
+|`LCTL_T(kc)` |`CTL_T(kc)` |Left Control when held, `kc` when tapped |
+|`LSFT_T(kc)` |`SFT_T(kc)` |Left Shift when held, `kc` when tapped |
+|`LALT_T(kc)` |`ALT_T(kc)` |Left Alt when held, `kc` when tapped |
+|`LGUI_T(kc)` |`LCMD_T(kc)`, `LWIN_T(kc)`, `GUI_T(kc)`, `CMD_T(kc)`, `WIN_T(kc)`|Left GUI when held, `kc` when tapped |
+|`RCTL_T(kc)` | |Right Control when held, `kc` when tapped |
+|`RSFT_T(kc)` | |Right Shift when held, `kc` when tapped |
+|`RALT_T(kc)` |`ALGR_T(kc)` |Right Alt when held, `kc` when tapped |
+|`RGUI_T(kc)` |`RCMD_T(kc)`, `RWIN_T(kc)` |Right GUI when held, `kc` when tapped |
+|`SGUI_T(kc)` |`SCMD_T(kc)`, `SWIN_T(kc)` |Left Shift and GUI when held, `kc` when tapped |
+|`LCA_T(kc)` | |Left Control and Alt when held, `kc` when tapped |
+|`LCAG_T(kc)` | |Left Control, Alt and GUI when held, `kc` when tapped |
+|`RCAG_T(kc)` | |Right Control, Alt and GUI when held, `kc` when tapped |
+|`C_S_T(kc)` | |Left Control and Shift when held, `kc` when tapped |
+|`MEH_T(kc)` | |Left Control, Shift and Alt when held, `kc` when tapped|
+|`HYPR_T(kc)` |`ALL_T(kc)` |Left Control, Shift, Alt and GUI when held, `kc` when tapped - more info [here](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)|
## [RGB Lighting](feature_rgblight.md)
diff --git a/docs/newbs_flashing.md b/docs/newbs_flashing.md
index a985e5d2b2..fa0a5e2ba5 100644
--- a/docs/newbs_flashing.md
+++ b/docs/newbs_flashing.md
@@ -127,9 +127,7 @@ Once it does this, you'll want to reset the controller. It should then show out
>>> dfu-programmer atmega32u4 reset
```
-If you have any issues with this, you may need to this:
-
- sudo make <my_keyboard>:<my_keymap>:dfu
+?> If you have any issues with this - such as `dfu-programmer: no device present` - please see the [Frequently Asked Build Questions](faq_build.md).
#### DFU commands
diff --git a/docs/quantum_keycodes.md b/docs/quantum_keycodes.md
index 90192e6324..a2ba34c32d 100644
--- a/docs/quantum_keycodes.md
+++ b/docs/quantum_keycodes.md
@@ -1,6 +1,6 @@
# Quantum Keycodes
-Quantum keycodes allow for easier customisation of your keymap than the basic ones provide, without having to define custom actions.
+Quantum keycodes allow for easier customization of your keymap than the basic ones provide, without having to define custom actions.
All keycodes within quantum are numbers between `0x0000` and `0xFFFF`. Within your `keymap.c` it may look like you have functions and other special cases, but ultimately the C preprocessor will translate those into a single 4 byte integer. QMK has reserved `0x0000` through `0x00FF` for standard keycodes. These are keycodes such as `KC_A`, `KC_1`, and `KC_LCTL`, which are basic keys defined in the USB HID specification.
@@ -16,6 +16,11 @@ On this page we have documented keycodes between `0x00FF` and `0xFFFF` which are
|`KC_GESC` |`GRAVE_ESC`|Escape when tapped, <code>&#96;</code> when pressed with Shift or GUI|
|`KC_LSPO` | |Left Shift when held, `(` when tapped |
|`KC_RSPC` | |Right Shift when held, `)` when tapped |
+|`KC_LCPO` | |Left Control when held, `(` when tapped |
+|`KC_RCPC` | |Right Control when held, `)` when tapped |
+|`KC_LAPO` | |Left Alt when held, `(` when tapped |
+|`KC_RAPC` | |Right Alt when held, `)` when tapped |
+|`KC_SFTENT` | |Right Shift when held, Enter when tapped |
|`KC_LEAD` | |The [Leader key](feature_leader_key.md) |
|`KC_LOCK` | |The [Lock key](feature_key_lock.md) |
|`FUNC(n)` |`F(n)` |Call `fn_action(n)` (deprecated) |
diff --git a/docs/reference_configurator_support.md b/docs/reference_configurator_support.md
index a20a6c9adb..784c6d9f75 100644
--- a/docs/reference_configurator_support.md
+++ b/docs/reference_configurator_support.md
@@ -89,7 +89,7 @@ Once the layout is as desired, move to the Raw Data tab in KLE, and copy the con
To convert this data into our JSON, go to the [QMK KLE-JSON Converter](https://qmk.fm/converter/), paste the Raw Data into the Input field, and click the Convert button. After a moment, our JSON data will appear in the Output field. Copy the contents to a new text document, and name the document `info.json`, saving it in the same folder that contains `numpad.h`.
-Use the `keyboard_name` object to set the name of the keyboard. The `bootloader` object is deprecated, so it can be deleted. For instruction purposes, we will put each key's object on its own line. This is only to make the file more human-readable, and does not affect the Configurator's functionality.
+Use the `keyboard_name` object to set the name of the keyboard. For instruction purposes, we will put each key's object on its own line. This is only to make the file more human-readable, and does not affect the Configurator's functionality.
```json
{
diff --git a/docs/zh-cn/_summary.md b/docs/zh-cn/_summary.md
index df25a3ccd1..b0d9f1c068 100644
--- a/docs/zh-cn/_summary.md
+++ b/docs/zh-cn/_summary.md
@@ -7,27 +7,27 @@
* [瀛︿範璧勬簮](newbs_learn_more_resources.md)
* [QMK鍩虹](README.md)
- * [QMK 绠浠媇(getting_started_introduction.md)
- * [璐$尞 QMK](contributing.md)
+ * [QMK绠浠媇(getting_started_introduction.md)
+ * [鍚慟MK璐$尞](contributing.md)
* [濡備綍浣跨敤Github](getting_started_github.md)
* [鑾峰緱甯姪](getting_started_getting_help.md)
* [闂瑙g瓟](faq.md)
* [涓鑸棶棰榏(faq_general.md)
- * [鏋勫缓/缂栬瘧QMK](faq_build.md)
- * [璋冭瘯/鏁呴殰鎺掗櫎 QMK](faq_debug.md)
- * [閿洏甯冨眬](faq_keymap.md)
+ * [鏋勫缓/缂栬瘧](faq_build.md)
+ * [璋冭瘯/鏁呴殰鎺掗櫎](faq_debug.md)
+ * [閿洏鏄犲皠](faq_keymap.md)
* 璇︾粏鎸囧崡
* [瀹夎鏋勫缓宸ュ叿](getting_started_build_tools.md)
- * [娴佹氮鑰呮寚鍗梋(getting_started_vagrant.md)
+ * [vagrant鎸囧崡](getting_started_vagrant.md)
* [鏋勫缓/缂栬瘧鎸囦护](getting_started_make_guide.md)
* [鍒锋柊鍥轰欢](flashing.md)
* [瀹氬埗鍔熻兘](custom_quantum_functions.md)
- * [甯冨眬姒傝堪](keymap.md)
+ * [鏄犲皠姒傝堪](keymap.md)
* [纭欢](hardware.md)
- * [AVR 澶勭悊鍣╙(hardware_avr.md)
+ * [AVR澶勭悊鍣╙(hardware_avr.md)
* [椹卞姩](hardware_drivers.md)
* 鍙傝
@@ -35,8 +35,8 @@
* [閰嶇疆閫夐」](config_options.md)
* [閿爜](keycodes.md)
* [璁板綍鏈浣冲疄璺礭(documentation_best_practices.md)
- * [鏂囨。鎸囧崡](documentation_templates.md)
- * [璇嶆眹琛╙(reference_glossary.md)
+ * [鏂囨。妯℃澘](documentation_templates.md)
+ * [鏈琛╙(reference_glossary.md)
* [鍗曞厓娴嬭瘯](unit_testing.md)
* [鏈夌敤鐨勫姛鑳絔(ref_functions.md)
* [閰嶇疆鍣ㄦ敮鎸乚(reference_configurator_support.md)
@@ -44,35 +44,35 @@
* [鐗规(features.md)
* [鍩烘湰閿爜](keycodes_basic.md)
- * [US ANSI 鎺у埗閿甝(keycodes_us_ansi_shifted.md)
+ * [US ANSI鎺у埗鐮乚(keycodes_us_ansi_shifted.md)
* [閲忓瓙閿爜](quantum_keycodes.md)
* [楂樼骇閿爜](feature_advanced_keycodes.md)
* [闊抽](feature_audio.md)
- * [鑷姩鎺у埗](feature_auto_shift.md)
+ * [鑷姩shift](feature_auto_shift.md)
* [鑳屽厜](feature_backlight.md)
* [钃濈墮](feature_bluetooth.md)
- * [Bootmagic](feature_bootmagic.md)
+ * [鐑敼閿甝(feature_bootmagic.md)
* [缁勫悎](feature_combo)
* [鍛戒护](feature_command.md)
* [鍔ㄦ佸畯鎸囦护](feature_dynamic_macros.md)
* [缂栫爜鍣╙(feature_encoders.md)
- * [Grave Escape](feature_grave_esc.md)
- * [閿攣](feature_key_lock.md)
- * [灞俔(feature_layouts.md)
- * [寮曞閿甝(feature_leader_key.md)
- * [LED 闃靛垪](feature_led_matrix.md)
+ * [閲嶉煶鍙稥sc澶嶅悎閿甝(feature_grave_esc.md)
+ * [鑷攣閿甝(feature_key_lock.md)
+ * [甯冨眬](feature_layouts.md)
+ * [鍓嶅閿甝(feature_leader_key.md)
+ * [LED闃靛垪](feature_led_matrix.md)
* [瀹忔寚浠(feature_macros.md)
* [榧犳爣閿甝(feature_mouse_keys.md)
* [涓閿姛鑳絔(feature_advanced_keycodes.md#one-shot-keys)
* [鎸囬拡璁惧](feature_pointing_device.md)
- * [PS/2 榧犳爣](feature_ps2_mouse.md)
- * [RGB 鍏塢(feature_rgblight.md)
- * [RGB 鐭╅樀](feature_rgb_matrix.md)
+ * [PS/2榧犳爣](feature_ps2_mouse.md)
+ * [RGB鐏厜](feature_rgblight.md)
+ * [RGB鐭╅樀](feature_rgb_matrix.md)
* [绌烘牸鍊欒ˉ鎹㈡尅](feature_space_cadet_shift.md)
* [绌烘牸鍊欒ˉ鎹㈡尅鍥炶溅](feature_space_cadet_shift_enter.md)
* [閫熷綍鏈篯(feature_stenography.md)
* [鎹㈡墜](feature_swap_hands.md)
- * [韪㈣笍鑸瀅(feature_tap_dance.md)
+ * [澶氬嚮閿甝(feature_tap_dance.md)
* [缁堢](feature_terminal.md)
* [鐑晱鎵撳嵃鏈篯(feature_thermal_printer.md)
* [Unicode](feature_unicode.md)
@@ -80,16 +80,16 @@
* [閫熷害閿甝(feature_velocikey.md)
* 閽堝鍒堕犺呭拰瀹氬埗鑰
- * [椋炵嚎鎸囧崡](hand_wire.md)
- * [ISP 鍒锋柊鎸囧崡](isp_flashing_guide.md)
- * [ARM 璋冭瘯鎸囧崡](arm_debugging.md)
- * [I2C 椹卞姩](i2c_driver.md)
- * [GPIO 鎺у埗鍣╙(internals_gpio_control.md)
- * [Proton C 杞崲](proton_c_conversion.md)
+ * [鎵嬪伐杩炵嚎鎸囧崡](hand_wire.md)
+ * [ISP鍒锋柊鎸囧崡](isp_flashing_guide.md)
+ * [ARM璋冭瘯鎸囧崡](arm_debugging.md)
+ * [I2C椹卞姩](i2c_driver.md)
+ * [GPIO鎺у埗鍣╙(internals_gpio_control.md)
+ * [Proton C杞崲](proton_c_conversion.md)
* 娣卞叆浜嗚В
* [閿洏濡備綍宸ヤ綔](how_keyboards_work.md)
- * [鐞嗚В QMK](understanding_qmk.md)
+ * [鐞嗚ВQMK](understanding_qmk.md)
* 鍏朵粬璇濋
* [浣跨敤Eclipse寮鍙慟MK](other_eclipse.md)
@@ -99,8 +99,8 @@
* QMK 鍐呮瀯 (姝e湪缂栧啓)
* [瀹氫箟](internals_defines.md)
* [杈撳叆鍥炶皟瀵勫瓨鍣╙(internals_input_callback_reg.md)
- * [Midi 璁惧](internals_midi_device.md)
- * [Midi 璁惧璁剧疆杩囩▼](internals_midi_device_setup_process.md)
- * [Midi 宸ュ叿搴揮(internals_midi_util.md)
+ * [Midi璁惧](internals_midi_device.md)
+ * [Midi璁惧璁剧疆杩囩▼](internals_midi_device_setup_process.md)
+ * [Midi宸ュ叿搴揮(internals_midi_util.md)
* [鍙戦佸嚱鏁癩(internals_send_functions.md)
- * [Sysex 宸ュ叿](internals_sysex_tools.md)
+ * [Sysex宸ュ叿](internals_sysex_tools.md)
diff --git a/docs/zh-cn/contributing.md b/docs/zh-cn/contributing.md
new file mode 100644
index 0000000000..62b956b619
--- /dev/null
+++ b/docs/zh-cn/contributing.md
@@ -0,0 +1,205 @@
+# 濡備綍鍋氳础鐚
+
+馃憤馃帀 棣栧厛鎰熻阿鍚勪綅鐧惧繖涔嬩腑鎶界┖闃呰鏈枃妗o紝骞朵负鎴戜滑鏃犵濂夌尞銆傜粰鎮ㄧ偣璧炲暒锛 馃帀馃憤
+
+绗笁鏂圭殑甯姪璁㏎閰辨垚闀夸簡璁稿鍛紝Q閰变篃浠庝綘浠偅瀛﹀埌浜嗕笉灏戞柊涓滆タ銆俀閰卞笇鏈涙瘡涓涓兂甯姪鎴戠殑浜洪兘鑳藉緢鏂逛究鐨勫仛鍑烘湁鐢ㄧ殑璐$尞銆傚湪杩欓噷鎴戠粰鎽╂嫵鎿︽帉鐨勪綘浠啓浜嗕竴鐐瑰紩瀵硷紝璁╀綘浠殑浠g爜鍦ㄤ笉瀵规垜鍋氶噸澶ф敼鍔ㄧ殑鎯呭喌涓嬮兘鑳芥垚鍔熺殑琚噰绾冲摝銆
+
+* [椤圭洰姒傚喌](#椤圭洰姒傚喌)
+* [浠g爜瑙勮寖](#浠g爜瑙勮寖)
+* [涓鑸暀绋媇(#涓鑸暀绋)
+* [琛屼负瀹堝垯瀵逛簬鎴戞潵璇存湁浣曟剰涔?](#琛屼负瀹堝垯瀵逛簬鎴戞潵璇存湁浣曟剰涔?)
+
+## 杩欐枃绔犲法闀挎棤姣斾笉鎯宠鍟! 鎴戝氨鎯抽棶涓棶棰樿屽凡!
+
+鎮ㄨ鏄兂闂叧浜嶲閰辩殑闂鐨勮瘽鍙互鍦╗OLKB Subreddit](https://reddit.com/r/olkb)鎴栬呮槸[Discord](https://discord.gg/Uq7gcHh)闅忔剰闂
+
+璇疯浣:
+
+* 缁存姢Q閰辩殑灏忓彲鐖辨湁鐨勬椂鍊欏彲鑳戒細鏈夌偣蹇欙紝涓嶈兘鍙婃椂鍥炵瓟鎮ㄧ殑闂锛岃愬績绛夌瓑锛屼粬浠兘鏄緢nice鐨勪汉鍛銆
+* 缁存姢Q閰辩殑浜洪兘鏄緢鏃犵鐨勫杽鑹殑浜恒傛棤璁烘槸璐$尞浠g爜杩樻槸鍥炵瓟闂锛岄兘鏄箟鍔$殑銆傛湁鏃惰鍒颁粬浠姫鍔涘洖绛斿悇绉嶉棶棰橈紝瑙e喅鍚勭BUG锛孮閰变篃鏄緢蹇冪柤鐨勩
+* 鎮ㄥ彲浠ョ湅鐪嬩笅闈㈢殑鏁欑▼锛屽彲浠ヨ鎮ㄧ殑闂娴呮樉鏄撴噦锛屾洿瀹规槗鍥炵瓟锛
+ * https://opensource.com/life/16/10/how-ask-technical-questions
+ * http://www.catb.org/esr/faqs/smart-questions.html
+
+# 椤圭洰姒傚喌
+
+Q閰卞緢澶т竴閮ㄥ垎鏄敤C璇█缁勬垚鐨勶紝涓嶈繃鏈変竴灏忛儴鍒嗙壒鎬ф槸C++鐨勩傛庝箞璇村憿锛岄兘鏄垜鐨勪竴閮ㄥ垎锛屼袱涓垜閮界埍銆俀閰变竴鑸槸鍦ㄩ敭鐩樹笂鐨勫祵鍏ュ紡澶勭悊鍣ㄩ偅閲屽伐浣滅殑锛屽挨鍏朵笌AVR([LUFA](http://www.fourwalledcubicle.com/LUFA.php))鍜孉RM ([ChibiOS](http://www.chibios.com))涓ゅ皬鍝ュ摜鎼厤锛屽共娲讳笉绱紝鍢诲樆銆傚鏋滄偍绮鹃欰rduino鐨勮瘽鎮ㄤ細鍙戠幇寰堝鐔熸倝鐨勬蹇碉紝浣嗕篃鏈夌偣涓嶇埥锛屽洜涓烘偍浠ュ墠鐨勭粡楠屽彲鑳芥病娉曠敤鏉ュ府鍔㏎閰便
+
+<!-- 闇瑕佷慨姝: 杩欓噷鏀句簺瀛︿範C璇█鐨勮祫婧愩傚彟澶栨劅璋慨姝g殑灏忓彲鐖便傝阿璋㈡偍浜嗐-->
+
+# Q閰憋紝鎴戝湪鍝兘甯姪浣犲槥?
+
+鎮ㄨ鏄湁闂鐨勮瘽鍙互 [鎻愬嚭涓涓猧ssue](https://github.com/qmk/qmk_firmware/issues) 鎴 [鍦―iscord涓婁氦娴佷竴涓媇(https://discord.gg/Uq7gcHh).
+
+# Q閰憋紝鎴戝浣曞府鍔╀綘?
+
+鎮ㄤ互鍓嶆槸鍚︽病涓哄紑婧愯础鐚繃浠g爜锛岃屽張鎯崇煡閬撳府鍔㏎閰辨槸鎬庝箞涓鍥炰簨? 绋嶅畨鍕胯簛锛屽挶缁欐偍鎬荤粨涓涓嬶紒
+
+0. 鍏堟敞鍐屼竴涓 [GitHub](https://github.com) 璐︽埛銆
+1. 鍋氬ソ涓涓綘瑕佽础鐚殑甯冨眬锛岄偅灏辫 [鎵句竴涓綘鎯宠В鍐崇殑闂](https://github.com/qmk/qmk_firmware/issues)锛屾垨鑰 [鎵句竴涓綘鎯虫坊鍔犵殑鐗规(https://github.com/qmk/qmk_firmware/issues?q=is%3Aopen+is%3Aissue+label%3Afeature)銆
+2. 鎶婂叧鑱旂潃闂鐨勪粨搴撳垎鍙夛紙fork锛夊埌浣犵殑浠撳簱銆傝繖鏍蜂綘鍦╜浣犵殑GitHub鐢ㄦ埛鍚/qmk_firmware`灏辨湁涓涓粨搴撳浠藉暒銆
+3. 浣跨敤 `git clone https://github.com/姝ゅ娣籊itHub鐢ㄦ埛鍚/姝ゅ娣讳粨搴撳悕.git`杩欎釜鍛戒护鎶婁粨搴撳悓姝ュ埌浣犵殑鐢佃剳涓
+4. 鎮ㄨ鏄兂寮鍙戜竴涓柊鐗规х殑璇濆彲浠ュ厛鍒涘缓涓涓猧ssue鍜孮閰辩殑缁存姢鑰呰璁轰竴涓嬫偍瑕佸仛浠涔堛
+5. 浣跨敤`git checkout -b 姝ゅ鍐欏垎鏀悕瀛楋紙鍒敤姹夊瓧锛塦鍛戒护鏉ュ垱寤轰竴涓垎鏀紙branch锛夌敤浜庡紑鍙戙
+6. 瀵硅瑙e喅鐨勯棶棰樻垨瑕佹坊鍔犵殑鐗规ц繘琛岄傚綋鐨勬洿鏀广
+7. 浣跨敤 `git add 鎶婃敼鍙樼殑鏂囦欢鐨勭洰褰曞啓杩欓噷` 鍙互娣诲姞鏀瑰彉鐨勬枃浠跺唴瀹瑰埌git鐢ㄤ簬绠$悊宸ョ▼鐘舵佺殑绱㈠紩锛堝揩鐓э級閲屻
+8. 浣跨敤 `git commit -m "杩欓噷鍐欎慨鏀圭殑鐩稿叧淇℃伅"` 鏉ユ弿杩颁綘鍋氬嚭浜嗕粈涔堜慨鏀广
+9. 浣跨敤 `git push origin 姝ゅ鍐欏垎鏀悕瀛梎鏉ユ妸浣犵殑鏇存敼鍚屾鍒癎itHub搴撻噷锛堝弽姝d笉鏄墦绡悆閭d釜搴撻噷锛夈
+10. 鎻愪氦涓涓猍QMK 鍥轰欢鐨刾ull request](https://github.com/qmk/qmk_firmware/pull/new/master)銆
+11. 缁欎綘鐨刾ull request鎷熶竴涓爣棰橈紝鍖呮嫭绠鐭殑鎻忚堪鍜岄棶棰樻垨閿欒浠g爜銆傛瘮濡, 浣犲彲浠ヨ捣涓涓繖鏍风殑"Added more log outputting to resolve #4352"锛堟渶濂界敤鑻辫锛屾瘯绔烸閰辩殑涓枃涔熶笉鏄偅涔堢殑婧滐紝鏈夊彲鑳戒細鐪嬩笉鎳備腑鏂囷級銆
+12. 鍦ㄦ弿杩帮紙description锛夐噷闈㈠啓浣犲仛浜嗗摢浜涙洿鏀癸紝浣犵殑浠g爜閲岃繕瀛樺湪浠涔堥棶棰, 鎴栬呬綘鎯抽棶缁存姢鐨勫皬鍙埍浠殑闂銆備綘鐨剏our pull request鏈夌偣灏忛棶棰樻棤浼ゅぇ闆(鏈潵涔熸病鏈夊畬缇庣殑浠g爜鍢), 缁存姢鐨勫皬鍙埍浠細绔敖鍏ㄥ姏甯偍鏀硅繘鐨勶紒
+13. 缁存姢浜哄憳瀹℃煡浠g爜鍙兘闇瑕佷竴浜涙椂闂淬
+14. 缁存姢浜哄憳浼氶氱煡鎮ㄨ鏇存敼浠涔堝湴鏂癸紝鐒跺悗鎮ㄥ氨鎸夌収寤鸿鏀逛竴鏀广
+15. 棰勭鎮ㄥ悎骞舵垚鍔燂紒
+
+# 浠g爜瑙勮寖
+
+鍏跺疄涔熸病鏈変粈涔堢壒鍒弗鏍肩殑瑙勮寖鍟︼紝浣嗘槸淇楄瘽璇寸殑濂斤細娌℃湁瑙勭煩锛屼笉鎴愭柟鍦嗐傛偍鍙互鐪嬩竴涓嬫偍鐨勮鏀瑰姩鐨勪唬鐮佸懆鍥寸殑鐢婚锛岀劧鍚庝繚鎸侀槦褰€傚鏋滀綘鎰熻鍛ㄥ洿閮戒笉鐭ラ亾鏄粈涔堢墰楝艰泧绁炵殑璇濆氨鐪嬬湅涓嬮潰鐨勫缓璁細
+
+* 鎴戜滑鐢ㄨ倖(4)涓┖鏍兼潵缂╄繘(杞欢涓篃鍙互璁剧疆鍒癟ab閿)
+* 鎴戜滑浣跨敤鏀硅壇鐨1TBS(鍏佽鍗曡鏍峰紡)
+ * 宸﹀ぇ鎷彿: 鍦ㄥ紑鏀炬ц鍙ュ潡閭h鐨勬湯灏
+ * 鍙冲ぇ鎷彿: 鍜屽紑鏀炬ц鍙ュ潡绗竴涓瓧姣嶅榻
+ * Else If: 灏嗗彸澶ф嫭鍙锋斁鍦ㄨ鐨勫紑澶达紝涓嬩竴涓乏澶ф嫭鍙锋斁鍦ㄥ悓涓琛岀殑缁撳熬
+ * 鍙夊ぇ鎷彿: 鍙夊ぇ鎷彿鏄繀閫夌殑
+ * 搴旇杩欐牱: if (condition) { return false; }
+ * 涓嶅簲璇ヨ繖鏍: if (condition) return false;
+* 寤鸿浣跨敤C璇█椋庢牸鐨勬敞閲: `/* */`
+ * 鎶婃敞閲婃兂璞℃垚涓涓弿杩扮壒寰佺殑鏁呬簨
+ * 鍏呭垎浣跨敤娉ㄩ噴鏉ユ弿杩颁綘涓轰綍杩欐牱淇敼
+ * 鏈変簺鍏鐨勪笢瑗垮氨涓嶈鍐欏埌娉ㄩ噴閲岄潰浜
+ * 濡傛灉浣犱笉鐭ラ亾娉ㄩ噴鏄惁澶氫綑,鐪嬩笅闈
+* 涓鑸笉瑕佷富鍔ㄦ崲琛岋紝涓诲姩鎹㈣鐨勮瘽姣忚涓嶈瓒呰繃76鍒
+* 瑕佹妸 `#pragma once` 鏀惧埌澶存枃浠剁殑寮濮嬪摝锛屾姏寮冭佸湡鐨(`#ifndef THIS_FILE_H`, `#define THIS_FILE_H`, ..., `#endif`)鍚
+* 涓嬮潰涓ょ棰勫鐞嗗懡浠ら兘鍙互鐢: `#ifdef DEFINED` 杩樻湁 `#if defined(DEFINED)`
+ * 浠ヤ笂閭e彞瀵瑰濂冲骇涓嶆槸寰堝弸濂藉搱锛屽濂冲骇鐨勬湅鍙嬩滑灏卞埆绾犵粨浜嗭紝鐩存帴 `#if defined(DEFINED)` 銆
+ * 杩樻湁灏辨槸閫夊ソ涓绉嶉鏍煎氨涓鐩寸敤锛屼竴鐩寸敤涓鐩寸埥锛屼笉瑕佹湞涓夋毊鍥, 闄ら潪浣犺鍙樺寲鍒板閲嶆潯浠剁殑 `#if`銆
+ * `#` 鍜 `if`瑕佹尐鍦ㄤ竴璧峰摝锛屽啀璁╂湰绌烘牸鍦ㄤ腑闂村啋鍏呯數鐏场鏈┖鏍间細鐢熸皵鐨勩
+ * 浠ヤ笅鏄缉杩涜鍒:
+ * 棣栧厛鑰冭檻鍙鎬э紝寮鸿揩鐥囩殑鏈嬪弸浠绘兂瑕佷繚鎸佷唬鐮佺殑楂樹竴鑷存э紝杩欐牱鍙笉濂姐
+ * 淇濊瘉鏂囦欢宸叉湁椋庢牸涓嶅彉銆傚鏋滀唬鐮佹湰鏉ュ氨鏄潅绯呴鏍硷紝閭e氨瑙佹満琛屼簨锛岃浣犵殑淇敼鏇存湁鎰忎箟浜涖
+ * 鍏跺疄浣犱篃鍙互鍦ㄧ缉杩涚殑鏃跺欑湅鐪嬪懆鍥村叾浠栦唬鐮侊紝鐒跺悗鑼冩按妯″北锛岄澶勭悊鍛戒护鍙互鏈夎嚜宸辩殑缂╄繘椋庢牸銆
+
+鍙互鍙傜収涓嬮潰:
+
+```c
+/* foo 鐨 Enums*/
+enum foo_state {
+ FOO_BAR,
+ FOO_BAZ,
+};
+
+/* 鏈夎繑鍥炲肩殑鎯呭喌 */
+int foo(void) {
+ if (some_condition) {
+ return FOO_BAR;
+ } else {
+ return -1;
+ }
+}
+```
+
+# Clang-format鐨勮嚜鍔ㄦ牸寮忓寲
+[Clang-format](https://clang.llvm.org/docs/ClangFormat.html) 鏄疞LVM鐨勪竴閮ㄥ垎锛屽彲浠ュ府浣犺嚜鍔ㄦ牸寮忓寲浠g爜銆傛垜浠粰浣犲噯澶囧ソ浜嗕竴涓傜敤浜庝互涓婅鑼冪殑閰嶇疆鏂囦欢锛屼細甯綘璋冩暣缂╄繘鍜屾崲琛岋紝浣犲彧闇瑕佸啓濂芥嫭鍙峰氨濂姐傛湁浜嗗畠锛屼綘鍐嶄篃涓嶇敤鎷呭績璋冩暣浠g爜鏍煎紡澶楁椂锛屾病鏈夋椂闂撮櫔浼磋嚜宸憋紙铏氭瀯锛夌殑鍙︿竴鍗婁簡銆
+
+浣跨敤[LLVM 瀹屾暣瀹夎](http://llvm.org/builds/)鍙互鍦╓indows涓婂畨瑁卌lang-format, Ubuntu鐢ㄦ埛瑕佺敤`sudo apt install clang-format`銆
+
+鍛戒护琛岀殑鏈嬪弸浠, 鍔犱笂 `-style=file`閫夐」灏变細鑷姩鍦≦MK鐨勬牴鐩綍瀵绘壘.clang-format閰嶇疆鏂囦欢浜嗐
+
+VSCode鐢ㄦ埛, 鏍囧噯鐨 C/C++ 鎻掍欢灏辨敮鎸乧lang-format, 鎴栬呭彲浠ョ敤[鐙珛鎵╁睍](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat)涔熻銆
+
+鏈変簺涓滆タ(姣斿LAYOUT瀹) 浼氳clang-format鎵撲贡锛屾墍浠ラ偅浜涙枃浠跺氨鍒敤clang-format浜,杩欓噷灏辨暀鎮ㄤ竴涓皬绐嶉棬锛屽湪`// clang-format off` 鍜 `//clang-format on`涔嬮棿瑁呬笂浼氳鎼炰贡鐨勪唬鐮佸氨濂戒簡銆
+
+# 涓鑸暀绋
+
+浣犲彲浠ョ粰Q閰辩殑涓嶅悓閮ㄥ垎娣荤爾鍔犵摝锛屼絾涔熻鐢ㄤ笉鍚岀殑鏂规硶涓ヨ皑妫鏌ャ備笉璁轰綘淇敼鍝噷鏈濂借繕鏄湅鐪嬩笅杈广
+
+* 灏哖R锛坧ull request锛夊垎鎴愪竴涓釜鐨勯昏緫鍗曞厓銆 姣斿锛屼笉瑕佷竴娆″皢涓や釜鏂扮壒鎬R鍑哄幓銆傝娣诲姞鐨勭壒鎬ф帓濂介槦锛屼竴涓竴涓潵銆
+* 鎻愪氦涔嬪墠鐪嬩竴鐪硷紝`git diff --check`鐨勭┖鏍间竴瀹氳鍐欏浜
+* 纭畾浣犵殑浠g爜鑳介氳繃缂栬瘧
+ * 甯冨眬: 纭畾`make keyboard:your_new_keymap` 涓嶈繑鍥為敊璇
+ * 閿洏: 纭畾 `make keyboard:all` 涓嶈繑鍥為敊璇
+ * 鏍稿績浠g爜: 纭畾 `make all` 涓嶈繑鍥為敊璇
+* 鎻愪氦鐨勪俊鎭敖閲忔槑纭傜涓琛屽啓鐐圭畝鐭粙缁(姣忚涓嶅浜70涓嫳鏂囧瓧姣), 绗簩琛岀┖鐫,绗笁琛屽拰鍚庨潰灏辫鍐欎簺蹇呰鐨勭粏鑺備簡銆傛渶濂界敤鑻辨枃鍐欙紝姣斿:
+
+```
+Adjust the fronzlebop for the kerpleplork
+
+The kerpleplork was intermittently failing with error code 23. The root cause was the fronzlebop setting, which causes the kerpleplork to activate every N iterations.
+
+Limited experimentation on the devices I have available shows that 7 is high enough to avoid confusing the kerpleplork, but I'd like to get some feedback from people with ARM devices to be sure.
+```
+
+## 鏂囨。
+
+鎯冲府鍔㏎閰卞綋鐒舵槸鍏堢湅鏂囨。鏈绠鍗曚簡銆傛壘鍒拌繖涓枃妗e摢閲岄敊浜嗙劧鍚庢敼姝e畠瀵逛簬浣犳潵璇磋秴绾х畝鍗! 鎴戜滑涔熷鏈夊啓鏂囨。鑳藉姏鐨勪汉姹傝搐鑻ユ复锛屽鏋滀綘鏄鐨勪汉[鐐硅繖涓猐(#Q閰憋紝鎴戝湪鍝兘甯姪浣犲槥?)!
+
+鏂囨。鍛紝閮介潤闈欑殑鏀惧湪`qmk_firmware/docs` 鐩綍閲, 涔熸垨鑰呮偍鎯充负缃戦〉鍋氳础鐚殑璇濅篃鏄彲浠ョ殑鍝︺
+
+鍦ㄦ枃妗d腑闄勪唬鐮佹渚嬫椂, 鍏堣瀵熸枃妗e叾浠栧湴鏂圭殑鍛藉悕瑙勮寖銆傛瘮濡, 鎶奺nums鐨勫悕瀛楅兘鏀规垚鍍廯my_layers`鎴栬卄my_keycodes`鏉ラ槻姝㈠悕瀛椾笉涓鑷寸殑enums琚綋浣滅壒鍔℃灙姣:
+
+```c
+enum my_layers {
+ _FIRST_LAYER,
+ _SECOND_LAYER
+};
+
+enum my_keycodes {
+ FIRST_LAYER = SAFE_RANGE,
+ SECOND_LAYER
+};
+```
+
+## 甯冨眬
+
+澶у鏁癚MK鏂版墜閮戒粠鍒涘缓涓涓嚜宸辩殑甯冨眬寮濮嬨傛垜浠敖鍔涗繚璇佸竷灞瑙勮寖瀹芥澗 (姣曠珶甯冨眬鏄釜鎬х殑浣撶幇) 涓嶈繃寤鸿閬靛畧浠ヤ笅鍑嗗垯锛岃繖鏍峰彲浠ヨ鍒汉鏇村ソ鐞嗚В浣犵殑浠g爜
+
+* 鐢 [妯℃澘](documentation_templates.md)鍐欎釜`readme.md`銆
+* 鎵鏈夌殑甯冨眬PR閮戒細琚玸quash, 濡傛灉浣犳兂鐭ラ亾浣犵殑鎻愪氦鏄庝箞琚玸quash鐨勯偅浣犲氨鑷繁鏉ュ惂
+* 涓嶈鎶婃柊鐗规у拰甯冨眬涓璧稰R銆傚彲浠ュ垎鍒玃R浠栦滑
+* 甯冨眬鏂囦欢澶瑰氨涓嶈鏀綻Makefile`浜嗭紝杩欎釜鎿嶄綔閮借繃鏃跺暒
+* 鏇存柊鏂囦欢澶撮儴鐨刢opyrights(鐪媊%YOUR_NAME%`閭)
+
+## 閿洏
+
+QMK鐨勬渶缁堝綊瀹挎槸閿洏銆傛湁浜涢敭鐩樻槸绀惧尯缁存姢鐨勶紝鏈変竴浜涙槸鍒朵綔杩欎簺閿洏鐨勪汉缁存姢鐨勩俙readme.md`浼氬憡璇変綘鏄皝缁存姢浜嗚繖涓敭鐩橈紝濡傛灉浣犲鏌愪釜閿洏鏈夌枒闂紝鍙互 [鍒涘缓涓涓狪ssue](https://github.com/qmk/qmk_firmware/issues) 鏉ラ棶涓闂淮鎶よ呫
+
+鎴戜滑寤鸿浣犳寜涓嬮潰鐨勬潵鎿嶄綔:
+
+* 鐢╗妯℃澘](documentation_templates.md)鍐檂readme.md`銆
+* 鎻愪氦鏁伴噺灏介噺鍚堢悊锛屼笉鐒舵垜浠彲灏辫鎶婁綘鐨凱R缁檚quash浜嗐
+* 涓嶈鎶婃柊鐗规у拰鏂伴敭鐩樹竴璧稰R銆傚彲浠ュ垎鍒玃R浠栦滑
+* 鐢ㄧ埗鏂囦欢澶圭殑鍚嶅瓧鍛藉悕 `.c`/`.h`鏂囦欢, 姣斿`/keyboards/<kb1>/<kb2>/<kb2>.[ch]`
+* 閿洏鏂囦欢澶瑰氨涓嶈鏀綻Makefile`浜嗭紝杩欎釜鎿嶄綔閮借繃鏃跺暒
+* 鏇存柊鏂囦欢澶撮儴鐨刢opyrights(鐪媊%YOUR_NAME%`閭)
+
+## Quantum/TMK 鏍稿績
+
+鍦ㄦ偍搴熷瘽蹇橀鍦板紑鍙慟閰辨柊鐗规ф垨鑰呭府Q閰遍┍铏箣鍓嶏紝涓瀹氳纭繚浣犵殑宸ヤ綔鏄湁鎰忎箟鐨勩傜湅鐪媅浜嗚ВQMK](understanding_qmk.md)浣犱細瀵筈閰辨湁鏇存繁鐨勪簡瑙o紝杩欎釜鏂囨。灏嗗甫浣犻鐣MK鐨勭▼搴忔祦绋嬨傜幇鍦ㄤ綘搴旇鍜岀淮鎶ゅ洟瀵硅皥璋堟潵浜嗚В瀹炵幇浣犳兂娉曠殑鏈浣虫柟娉曚簡銆備竴涓嬫笭閬撻兘鍙互锛
+
+* [鍦―iscord浜ゆ祦](https://discord.gg/Uq7gcHh)
+* [寤虹珛涓涓狪ssue](https://github.com/qmk/qmk_firmware/issues/new)
+
+鏂扮壒鎬у拰BUG鐨勪慨澶嶅奖鍝嶆墍鏈夐敭鐩樸傚紑鍙戠粍涔熷湪缈讳慨QMK銆傛墍浠ワ紝鍦ㄥ疄鏂介噸澶ц繑淇箣鍓嶄竴瀹氳璁ㄨ涓涓嬨傚鏋滀綘鍦ㄦ病鏈変簨鍏堜笌缁存姢鍥㈤槦娌熼氱殑鎯呭喌涓嬫彁浜や簡涓涓狿R锛岃屼笖浣犵殑閫夋嫨涓庣淮鎶ゅ洟闃熺殑璁″垝鏂瑰悜涓嶇锛岄偅浣犲彲鑳借闈复澶ф敼浜嗐
+
+淇BUG鎴栬呭紑鍙戞柊鐗规т箣鍓嶇湅鐪嬭繖涓細
+
+* **榛樿涓嶅惎鐢** - QMK杩愯鐨勮姱鐗囧鏁板唴瀛樻湁闄愶紝鎵浠ラ瑕佽冭檻鐨勮繕搴旇鏄竷灞涓嶈琚牬鍧忥紝浜庢槸鐗规ч粯璁ゆ槸涓嶅惎鐢ㄧ殑銆備綘鍠滄浠涔堢壒鎬х殑璇濆氨鎵撳紑瀹冿紝濡傛灉浣犺寰楁湁浜涚壒鎬у簲璇ラ粯璁ゅ紑鍚垨鑰呬綘鑳藉府鍔╃缉鍑忎唬鐮侊紝閭e氨鑱旂郴缁存姢缁勫惂銆
+* **鎻愪氦涔嬪墠鍦ㄦ湰鍦扮紪璇** - 杩欎釜绠鐩村氨鏄鍠绘埛鏅撲簡锛屼絾鏄篃纭疄闇瑕佺紪璇戝晩锛 鎴戜滑鐨凾ravis绯荤粺浼氬彂鐜颁竴鍒囬棶棰橈紝浣嗘槸鑷繁缂栬瘧涓涓嬪彲瑕佹瘮鍦ㄧ嚎绛夊揩澶氫簡銆
+* **娉ㄦ剰鐗堟湰鍜岃姱鐗囧钩鍙** - 鏈夐偅涔堝嚑涓敭鐩樻湁鏀寔涓嶅悓閰嶇疆鐢氳嚦鏄笉鍚岃姱鐗囩殑鐗堟湰銆傝瘯鐫鍐欎竴涓兘AVR鍜孉RM涓や釜骞冲彴杩愯鐨勭壒鎬э紝鎴栬呭湪涓嶆敮鎸佺殑骞冲彴鑷姩绂佺敤銆
+* **瑙i噴浣犵殑鏂扮壒鎬** - 鍦╜docs/`鍐欎釜鏂囨。, 浣犲彲浠ュ垱寤烘柊鏂囨。鎴栬呭啓鍒扮幇鏈夋枃妗d腑銆傚鏋滀綘涓嶆妸瀹冭褰曚笅鏉ワ紝鍏朵粬浜哄氨鏃犳硶浠庝綘鐨勫姫鍔涗腑鑾风泭銆
+
+涔熷彲浠ョ湅鐪嬩互涓嬪缓璁細
+
+* 鎻愪氦鏁伴噺灏介噺鍚堢悊锛屼笉鐒舵垜浠彲灏辫鎶婁綘鐨凱R缁檚quash浜嗐
+* 涓嶈鎶婃柊鐗规с佸竷灞鍜岄敭鐩樹竴璧稰R銆傚彲浠ュ垎鍒玃R浠栦滑銆
+* 缁欎綘鐨勭壒鎬у啓[鍗曞厓娴嬭瘯](unit_testing.md)銆
+* 浣犵紪杈戠殑鏂囦欢椋庢牸瑕佷竴鑷达紝濡傛灉椋庢牸涓嶆槑纭垨鑰呮槸娣锋惌椋庣殑锛屼綘灏辫鍏堢湅鐪媅浠g爜瑙勮寖](#浠g爜瑙勮寖)纭鎯呭喌銆
+
+## 閲嶆瀯
+
+涓轰簡淇濇寔QMK鑴夌粶娓呮櫚锛孮閰辨墦绠楁繁鍏ヨ鍒掗噸鏋勪竴涓嬭嚜宸憋紝鐒跺悗璁╁悎浣滆呰繘琛屼慨鏀广傚鏋滀綘鏈夐噸鏋勭殑鎬濊矾鎴栧缓璁甗鍒涘缓涓涓猧ssue](https://github.com/qmk/qmk_firmware/issues), Q閰卞緢涔愭剰璁ㄨ涓涓嬫庝箞鏀硅繘涓涓嬨
+
+# 琛屼负瀹堝垯瀵逛簬鎴戞潵璇存湁浣曟剰涔?
+
+鎴戜滑鐨刐琛屼负瀹堝垯](https://github.com/qmk/qmk_firmware/blob/master/CODE_OF_CONDUCT.md) 鏄鏄庢偍鏈夎矗浠诲皧閲嶅拰绀艰矊鍦板寰呴」鐩腑鐨勬瘡涓汉锛屾棤璁轰粬浠殑韬唤濡備綍銆 濡傛灉浣犳槸鎴戜滑琛屼负鍑嗗垯鎵鎻忚堪鐨勪笉褰撹涓虹殑鍙楀鑰咃紝鎴戜滑灏嗙珯鍦ㄤ綘杩欒竟锛屽苟鎸夌収琛屼负鍑嗗垯瀵规柦鏆磋呰繘琛岄傚綋璋磋矗銆
diff --git a/docs/zh-cn/custom_quantum_functions.md b/docs/zh-cn/custom_quantum_functions.md
new file mode 100644
index 0000000000..42ceba9cac
--- /dev/null
+++ b/docs/zh-cn/custom_quantum_functions.md
@@ -0,0 +1,490 @@
+# 如何定制你键盘的功能
+
+对于很多人来说客制化键盘可不只是向你的电脑发送你按了那个件这么简单。你肯定想实现比简单按键和宏更复杂的功能。QMK有能让你注入代码的钩子, 覆盖功能, 另外,还可以自定义键盘在不同情况下的行为。
+
+本页不假定任何特殊的QMK知识,但阅读[理解QMK](understanding_qmk.md)将会在更基础的层面帮你理解发生了什么。
+
+## A Word on Core vs 键盘 vs 布局
+
+我们把qmk组织成一个层次结构:
+
+* Core (`_quantum`)
+ * Keyboard/Revision (`_kb`)
+ * Keymap (`_user`)
+
+下面描述的每一个函数都可以在定义上加一个`_kb()`或 `_user()` 后缀。 建议在键盘/修订层使用`_kb()`后缀,在布局层使用`_user()`后缀。
+
+在键盘/修订层定义函数时,`_kb()`在执行任何代码前先调用`_user()`是必要的,不然布局层函数就不要被调用。
+<!-- 翻译问题:上面那句翻译的不太好-->
+# 自定义键码
+
+到目前为止,最常见的任务是更改现有键码的行为或创建新的键码。从代码角度来看这些操作都很相似。
+
+## 定义一个新键码
+
+创建键码第一步,先枚举出它全部,也就是给键码起个名字并分配唯一数值。QMK没有直接限制最大键码值大小,而是提供了一个`SAFE_RANGE`宏。你可以在枚举时用`SAFE_RANGE`来保证你取得了唯一的键码值。
+
+
+这有枚举两个键码的例子。把这块加到`keymap.c`的话你就在布局中能用`FOO`和`BAR`了。
+
+```c
+enum my_keycodes {
+ FOO = SAFE_RANGE,
+ BAR
+};
+```
+
+## 为键码的行为编程
+
+当你覆盖一个已存在按键的行为时,或将这个行为赋给新键时,你要用`process_record_kb()`和`process_record_user()`函数。这俩函数在键处理中真实键事件被处理前被QMK调用。如果这俩函数返回`true`,QMK将会用正常的方式处理键码。这样可以很方便的扩展键码的功能而不是替换它。如果函数返回`false` QMK会跳过正常键处理,然后发送键子抬起还是按下事件就由你决定了。
+
+当某个键按下或释放时这俩函数会被调用。
+
+### process_record_user()`函数示例实现
+
+这个例子做了两个事。自定义了一个叫做`FOO`的键码的行为,并补充了在按下回车时播放音符。
+
+```c
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case FOO:
+ if (record->event.pressed) {
+ // 按下时做些什么
+ } else {
+ // 释放时做些什么
+ }
+ return false; // 跳过此键的所有进一步处理
+ case KC_ENTER:
+ // 当按下回车时播放音符
+ if (record->event.pressed) {
+ PLAY_NOTE_ARRAY(tone_qwerty);
+ }
+ return true; // 让QMK触发回车按下/释放事件
+ default:
+ return true; // 正常处理其他键码
+ }
+}
+```
+
+### `process_record_*` 函数文档
+
+* 键盘/修订: `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
+* 布局: `bool process_record_user(uint16_t keycode, keyrecord_t *record)`
+
+`keycode(键码)`参数是在布局上定义的,比如`MO(1)`, `KC_L`, 等等。 你要用 `switch...case` 块来处理这些事件。
+
+`record`参数含有实际按键的信息:
+
+```c
+keyrecord_t record {
+ keyevent_t event {
+ keypos_t key {
+ uint8_t col
+ uint8_t row
+ }
+ bool pressed
+ uint16_t time
+ }
+}
+```
+
+# LED控制
+
+qmk提供了读取HID规范包含的5个LED的方法。:
+
+* `USB_LED_NUM_LOCK`
+* `USB_LED_CAPS_LOCK`
+* `USB_LED_SCROLL_LOCK`
+* `USB_LED_COMPOSE`
+* `USB_LED_KANA`
+
+这五个常量对应于主机LED状态的位置位。
+有两种方法可以获得主机LED状态:
+
+* 通过执行 `led_set_user()`
+* 通过调用 `host_keyboard_leds()`
+
+## `led_set_user()`
+
+当5个LED中任何一个的状态需要改变时,此函数将被调用。此函数通过参数输入LED参数。
+使用`IS_LED_ON(usb_led, led_name)`和`IS_LED_OFF(usb_led, led_name)`这两个宏来检查LED状态。
+
+!> `host_keyboard_leds()`可能会在`led_set_user()`被调用前返回新值。
+
+### `led_set_user()`函数示例实现
+
+```c
+void led_set_user(uint8_t usb_led) {
+ if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
+ writePinLow(B0);
+ } else {
+ writePinHigh(B0);
+ }
+ if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
+ writePinLow(B1);
+ } else {
+ writePinHigh(B1);
+ }
+ if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
+ writePinLow(B2);
+ } else {
+ writePinHigh(B2);
+ }
+ if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) {
+ writePinLow(B3);
+ } else {
+ writePinHigh(B3);
+ }
+ if (IS_LED_ON(usb_led, USB_LED_KANA)) {
+ writePinLow(B4);
+ } else {
+ writePinHigh(B4);
+ }
+}
+```
+
+### `led_set_*`函数文档
+
+* 键盘/修订: `void led_set_kb(uint8_t usb_led)`
+* 布局: `void led_set_user(uint8_t usb_led)`
+
+## `host_keyboard_leds()`
+
+调用这个函数会返回最后收到的LED状态。这个函数在`led_set_*`之外读取LED状态时很有用,比如在[`matrix_scan_user()`](#矩阵扫描代码).
+为了便捷,你可以用`IS_HOST_LED_ON(led_name)`和`IS_HOST_LED_OFF(led_name)` 宏,而不直接调用和检查`host_keyboard_leds()`。
+
+## 设置物理LED状态
+
+一些键盘实现了为设置物理LED的状态提供了方便的方法。
+
+### Ergodox Boards
+
+Ergodox实现了提供`ergodox_right_led_1`/`2`/`3_on`/`off()`来让每个LED开或关, 也可以用 `ergodox_right_led_on`/`off(uint8_t led)` 按索引打开或关闭他们。
+
+此外,还可以使用`ergodox_led_all_set(uint8_t n)`指定所有LED的亮度级别;针对每个LED用`ergodox_right_led_1`/`2`/`3_set(uint8_t n)`;使用索引的话用`ergodox_right_led_set(uint8_t led, uint8_t n)`。
+
+Ergodox boards 同时定义了最低亮度级别`LED_BRIGHTNESS_LO`和最高亮度级别`LED_BRIGHTNESS_HI`(默认最高).
+
+# 键盘初始化代码
+
+键盘初始化过程有几个步骤。你是用那个函数取决于你想要做什么。
+
+有三个主要初始化函数,按调用顺序列出。
+
+* `keyboard_pre_init_*` - 会在大多数其他东西运行前运行。适用于哪些需要提前运行的硬件初始化。
+* `matrix_init_*` - 在固件启动过程中间被调用。此时硬件已初始化,功能尚未初始化。
+* `keyboard_post_init_*` - 在固件启动过程最后被调用。大多数情况下,你的“客制化”代码都可以放在这里。
+
+!> 对于大多数人来说`keyboard_post_init_user`是你想要调用的函数。例如, 此时你可以设置RGB灯发光。
+
+## 键盘预初始化代码
+
+这代码极早运行,甚至都在USB初始化前运行。
+
+在这之后不久矩阵就被初始化了。
+
+对于大多数用户来说,这用不到,因为它主要是用于面向硬件的初始化。
+
+但如果你有硬件初始化的话放在这里再好不过了(比如初始化LED引脚一类的).
+
+### `keyboard_pre_init_user()`函数示例实现
+
+本例中在键盘级别,设定 B0, B1, B2, B3, 和 B4 是LED引脚。
+
+```c
+void keyboard_pre_init_user(void) {
+ // 调用键盘预初始化代码
+
+ // 设置LED引脚为输出模式
+ setPinOutput(B0);
+ setPinOutput(B1);
+ setPinOutput(B2);
+ setPinOutput(B3);
+ setPinOutput(B4);
+}
+```
+
+### `keyboard_pre_init_*` 函数文档
+
+* 键盘/修订: `void keyboard_pre_init_kb(void)`
+* 布局: `void keyboard_pre_init_user(void)`
+
+## 矩阵初始化代码
+
+这将会在矩阵初始化时被调用,在某些硬件设置好后,但在一些功能被初始化前。
+
+这在你设置其他地方会用到的东西的时候会很有用,但与硬件无关,也不依赖于它的启动位置。
+
+
+### `matrix_init_*`函数文档
+
+* 键盘/修订: `void matrix_init_kb(void)`
+* 布局: `void matrix_init_user(void)`
+
+
+## 键盘后初始化代码
+
+这是键盘初始化过程中的最后一个任务。如果您想更改某些特性,这会很有用,因为此时应该对它们进行初始化。
+
+
+### `keyboard_post_init_user()`示例实现
+
+本示例在所有初始化完成后运行,配置RGB灯。
+
+```c
+void keyboard_post_init_user(void) {
+ // 调用后初始化代码
+ rgblight_enable_noeeprom(); // 使能Rgb,不保存设置
+ rgblight_sethsv_noeeprom(180, 255, 255); // 将颜色设置到蓝绿色(青色)不保存
+ rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3); // 设置快速呼吸模式不保存
+}
+```
+
+### `keyboard_post_init_*` 函数文档
+
+* 键盘/修订: `void keyboard_post_init_kb(void)`
+* 布局: `void keyboard_post_init_user(void)`
+
+# 矩阵扫描代码
+
+可能的话你要用`process_record_*()`自定义键盘,以这种方式连接到事件中,以确保代码不会对键盘产生负面的性能影响。然而,在极少数情况下,有必要进行矩阵扫描。在这些函数中要特别注意代码的性能,因为它每秒至少被调用10次。
+
+### `matrix_scan_*`示例实现
+
+这个例子被故意省略了。在hook这样一个对性能及其敏感的区域之前,您应该足够了解qmk的内部结构,以便在没有示例的情况下编写。如果你需要帮助,请[建立一个issue](https://github.com/qmk/qmk_firmware/issues/new)或[在Discord上与我们交流](https://discord.gg/Uq7gcHh).
+
+### `matrix_scan_*` 函数文档
+
+* 键盘/修订: `void matrix_scan_kb(void)`
+* 布局: `void matrix_scan_user(void)`
+
+该函数在每次矩阵扫描时被调用,这基本与MCU处理能力上限相同。在这里写代码要谨慎,因为它会运行很多次。
+
+你会在自定义矩阵扫描代码时用到这个函数。这也可以用作自定义状态输出(比如LED灯或者屏幕)或者其他即便用户不输入你也想定期运行的功能。
+
+
+# 键盘 空闲/唤醒 代码
+
+如果键盘支持就可以通过停止一大票功能来达到"空闲"。RGB灯和背光就是很好的例子。这可以节约能耗,也可能让你键盘风味更佳。
+
+用两个函数控制: `suspend_power_down_*`和`suspend_wakeup_init_*`, 分别在系统板空闲和唤醒时调用。
+
+
+### suspend_power_down_user()和suspend_wakeup_init_user()示例实现
+
+
+```c
+void suspend_power_down_user(void) {
+ rgb_matrix_set_suspend_state(true);
+}
+
+void suspend_wakeup_init_user(void) {
+ rgb_matrix_set_suspend_state(false);
+}
+```
+
+### 键盘 挂起/唤醒 函数文档
+
+* 键盘/修订: `void suspend_power_down_kb(void)` 和`void suspend_wakeup_init_user(void)`
+* 布局: `void suspend_power_down_kb(void)` 和 `void suspend_wakeup_init_user(void)`
+
+# 层改变代码
+
+每当层改变这个就运行代码。这对于层指示或自定义层处理很有用。
+
+### `layer_state_set_*` 示例实现
+
+本例使用了Planck键盘示范了如何设置 [RGB背光灯](feature_rgblight.md)使之与层对应
+
+```c
+uint32_t layer_state_set_user(uint32_t state) {
+ switch (biton32(state)) {
+ case _RAISE:
+ rgblight_setrgb (0x00, 0x00, 0xFF);
+ break;
+ case _LOWER:
+ rgblight_setrgb (0xFF, 0x00, 0x00);
+ break;
+ case _PLOVER:
+ rgblight_setrgb (0x00, 0xFF, 0x00);
+ break;
+ case _ADJUST:
+ rgblight_setrgb (0x7A, 0x00, 0xFF);
+ break;
+ default: // for any other layers, or the default layer
+ rgblight_setrgb (0x00, 0xFF, 0xFF);
+ break;
+ }
+ return state;
+}
+```
+### `layer_state_set_*` 函数文档
+
+* 键盘/修订: `uint32_t layer_state_set_kb(uint32_t state)`
+* 布局: `uint32_t layer_state_set_user(uint32_t state)`
+
+
+该`状态`是活动层的bitmask, 详见[布局概述](keymap.md#布局的层状态)
+
+
+# 掉电保存配置 (EEPROM)
+
+这会让你的配置长期的保存在键盘中。这些配置保存在你主控的EEPROM里,掉电不会消失。 设置可以用`eeconfig_read_kb`和`eeconfig_read_user`读取,可以用`eeconfig_update_kb`和`eeconfig_update_user`写入。这对于您希望能够切换的功能很有用(比如切换RGB层指示。此外,你可以用`eeconfig_init_kb`和`eeconfig_init_user`来设置EEPROM默认值。
+
+最复杂的部分可能是,有很多方法可以通过EEPROM存储和访问数据,并且并没有用哪种方法是“政治正确”的。你每个功能只有一个双字(四字节)空间。
+
+记住EEPROM是有写入寿命的。尽管写入寿命很高,但是并不是只有设置写道EEPROM中。如果你写入频繁,你的MCU寿命将会变短。
+
+* 如果您不理解这个例子,那么您可能希望避免使用这个特性,因为它相当复杂。
+
+### 示例实现
+
+本例讲解了如何添加设置,并且读写。本里使用了用户布局。这是一个复杂的函数,有很多事情要做。实际上,它使用了很多上述函数来工作!
+
+
+在你的keymap.c文件中,将以下代码添加至顶部:
+```c
+typedef union {
+ uint32_t raw;
+ struct {
+ bool rgb_layer_change :1;
+ };
+} user_config_t;
+
+user_config_t user_config;
+```
+
+以上代码建立了一个结构体,该结构体可以存储设置并可用于写入EEPROM。如此这般将无需定义变量,因为在结构体中已然定义。要记住`bool` (布尔)值使用1位, `uint8_t`使用8位, `uint16_t`使用16位。你可以混合搭配使用,但是顺序记错可能会招致麻烦,因为那会改变写入写出的值。
+
+ `layer_state_set_*`函数中使用了`rgb_layer_change`,使用了`keyboard_post_init_user`和`process_record_user`来配置一切。
+
+首先要使用`keyboard_post_init_user,你要加入`eeconfig_read_user()`来填充你刚刚创建的结构体。然后您可以立即使用这个结构来控制您的布局中的功能。就像这样:
+```c
+void keyboard_post_init_user(void) {
+ // 调用布局级别的矩阵初始化
+
+ // 从EEPROM读用户配置
+ user_config.raw = eeconfig_read_user();
+
+ // 如使能,设置默认层
+ if (user_config.rgb_layer_change) {
+ rgblight_enable_noeeprom();
+ rgblight_sethsv_noeeprom_cyan();
+ rgblight_mode_noeeprom(1);
+ }
+}
+```
+以上函数会在读EEPROM配置后立即使用该设置来设置默认层RGB颜色。"raw"的值是从你上面基于"union"创建的结构体中转换来的。
+
+```c
+uint32_t layer_state_set_user(uint32_t state) {
+ switch (biton32(state)) {
+ case _RAISE:
+ if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_magenta(); rgblight_mode_noeeprom(1); }
+ break;
+ case _LOWER:
+ if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_red(); rgblight_mode_noeeprom(1); }
+ break;
+ case _PLOVER:
+ if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_green(); rgblight_mode_noeeprom(1); }
+ break;
+ case _ADJUST:
+ if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_white(); rgblight_mode_noeeprom(1); }
+ break;
+ default: // 针对其他层或默认层
+ if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_cyan(); rgblight_mode_noeeprom(1); }
+ break;
+ }
+ return state;
+}
+```
+这样仅在值使能时会改变RGB背光灯。现在配置这个值, 为`process_record_user`创建一个新键码叫做`RGB_LYR`。我们要确保,如果使用正常的RGB代码,使用上面的示例将其关闭,请将其设置为:
+```c
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case FOO:
+ if (record->event.pressed) {
+ // 按下时做点什么
+ } else {
+ // 释放时做点什么
+ }
+ return false; // 跳过此键的进一步处理
+ case KC_ENTER:
+ // 在按下回车时播放音符
+ if (record->event.pressed) {
+ PLAY_NOTE_ARRAY(tone_qwerty);
+ }
+ return true; // 让QMK产生回车按下/释放事件
+ case RGB_LYR: // 本句让underglow作为层指示,或正常使用。
+ if (record->event.pressed) {
+ user_config.rgb_layer_change ^= 1; // 切换状态
+ eeconfig_update_user(user_config.raw); // 向EEPROM写入新状态
+ if (user_config.rgb_layer_change) { // 如果层状态被使能
+ layer_state_set(layer_state); // 那么立刻更新层颜色
+ }
+ }
+ return false; break;
+ case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // 对于所有的RGB代码 (see quantum_keycodes.h, L400 可以参考)
+ if (record->event.pressed) { //本句失能层指示,假设你改变了这个…你要把它禁用
+ if (user_config.rgb_layer_change) { // 仅当使能时
+ user_config.rgb_layer_change = false; // 失能,然后
+ eeconfig_update_user(user_config.raw); // 向EEPROM写入设置
+ }
+ }
+ return true; break;
+ default:
+ return true; // 按其他键正常
+ }
+}
+```
+最后你要加入`eeconfig_init_user`函数,所以当EEPROM重置时,可以指定默认值, 甚至自定义操作。想强制重置EEPROM,请用`EEP_RST`键码或[Bootmagic](feature_bootmagic.md)函数。比如,如果要在默认情况下设置RGB层指示,并保存默认值
+
+```c
+void eeconfig_init_user(void) { // EEPROM正被重置
+ user_config.raw = 0;
+ user_config.rgb_layer_change = true; // 我们想要默认使能
+ eeconfig_update_user(user_config.raw); // 向EEPROM写入默认值
+
+ // use the non noeeprom versions, 还要向EEPROM写入这些值
+ rgblight_enable(); // 默认使能RGB
+ rgblight_sethsv_cyan(); // 默认设置青色
+ rgblight_mode(1); // 默认设置长亮
+}
+```
+
+然后就完事了。RGB层指示会在你想让它工作时工作。这个设置会一直保存,即便你拔下键盘。如果你使用其他RGB代码,层指示将失能,现在它可以做你所想了。
+
+### 'EECONFIG' 函数文档
+
+* 键盘/修订: `void eeconfig_init_kb(void)`, `uint32_t eeconfig_read_kb(void)`和`void eeconfig_update_kb(uint32_t val)`
+* 布局: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)`和`void eeconfig_update_user(uint32_t val)`
+
+`val` 是你想写入EEPROM的值,`eeconfig_read_*`函数会从EEPROM返回一个32位(双字)的值。
+
+# 自定义击键-长按临界值(TAPPING_TERM)
+默认情况下,击键-长按临界值是全球统一的,并且不能通过键进行配置。对于大多数用户来说这很好。但是在有些情况下,对于`LT`键来说按键延时对双功能键的提升更大,可能是因为有些键比其他的键更容易按住。为了不给每个都自定义键码,本功能可以为每个键定义`TAPPING_TERM`。
+
+想使能这个功能的话, 要先在`config.h`加上`#define TAPPING_TERM_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_tapping_term` 函数文档
+
+不像这篇的其他功能,这个不需要quantum或者键盘级别的函数,只要用户级函数即可。
diff --git a/docs/zh-cn/faq.md b/docs/zh-cn/faq.md
new file mode 100644
index 0000000000..3d0b65c6fd
--- /dev/null
+++ b/docs/zh-cn/faq.md
@@ -0,0 +1,6 @@
+# 甯歌闂
+
+* [涓鑸棶棰榏(faq_general.md)
+* [鏋勫缓鍜岀紪璇慟MK](faq_build.md)
+* [QMK璋冭瘯鍜屾晠闅滄帓闄(faq_debug.md)
+* [甯冨眬闂](faq_keymap.md)
diff --git a/docs/zh-cn/faq_build.md b/docs/zh-cn/faq_build.md
new file mode 100644
index 0000000000..8fb449db30
--- /dev/null
+++ b/docs/zh-cn/faq_build.md
@@ -0,0 +1,150 @@
+# 鍏充簬鏋勫缓鐨勫父瑙侀棶棰
+
+鏈〉鎵鍐欐槸QMK鏋勫缓鐨勫父瑙侀棶棰.濡傛灉浣犺繕娌℃湁杩涜杩囩紪璇,灏辩湅涓涓媅鏋勫缓鐜鎼缓](getting_started_build_tools.md) 鍜 [make鐨勮鏄嶿(getting_started_make_guide.md).
+
+## 濡傛灉鎮ㄤ笉鑳藉湪Linux涓婄紪绋
+鎮ㄩ渶瑕侀傚綋鐨勬潈闄愭墠鑳芥搷浣滆澶囥傚浜嶭inux鐢ㄦ埛, 璇峰弬闃呬笅鏂规湁鍏砢udev`瑙勫垯鐨勮鏄庛傚鏋滄偍瀵筦udev`鏈夐棶棰橈紝瑙e喅鏂规硶鏄敤`sudo`鍛戒护銆傚鏋滄偍涓嶇啛鎮夋鍛戒护锛屼娇鐢╜man sudo`鏌ョ湅鍏舵墜鍐屾垨[鐪嬭繖涓綉椤礭(https://linux.die.net/man/8/sudo).
+
+鍦ㄤ綘鐨勪富鎺ф槸ATMega32u4鏃讹紝浠ヤ笅鏄娇鐢╜sudo`鍛戒护鐨勬牱渚嬶細
+
+ $ sudo dfu-programmer atmega32u4 erase --force
+ $ sudo dfu-programmer atmega32u4 flash your.hex
+ $ sudo dfu-programmer atmega32u4 reset
+
+鎴栧彧鐢紱
+
+ $ sudo make <keyboard>:<keymap>:dfu
+
+浣跨敤`sudo`杩愯`make`涓鑸潵璇**涓**鎺ㄨ崘锛屽鏋滃彲鑳斤紝灏介噺浣跨敤鍓嶄竴绉嶆柟娉曚箣涓銆
+
+### Linux `udev` 瑙勫垯
+鍦↙inux涓婏紝鎮ㄩ渶瑕侀傚綋鐨勬潈闄愭墠鑳借闂甅CU銆備綘涔熷彲浠ュ湪鍒锋柊鍥轰欢鏃朵娇鐢 `sudo`锛屾垨鎶婅繖浜涙枃浠舵斁鍒癭/etc/udev/rules.d/`銆
+
+**/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閿洏浜у搧 https://github.com/tmk/tmk_keyboard
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
+```
+**/etc/udev/rules.d/54-input-club-keyboard.rules:**
+
+```
+# Input Club keyboard bootloader
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", MODE:="0666"
+```
+
+### 涓茶璁惧鍦↙inux涓婃娴嬩笉鍒癰ootloader妯″紡
+纭繚鎮ㄧ殑鍐呮牳瀵规偍鐨勮澶囨湁鐩稿簲鐨勬敮鎸併 濡傛灉浣犵殑璁惧鏄 USB ACM, 姣斿Pro Micro (Atmega32u4)锛屽氨瑕佸姞涓奰CONFIG_USB_ACM=y`. 鍏朵粬璁惧鍙兘闇瑕乣USB_SERIAL` 鍙婂叾浠讳綍瀛愰夐」銆
+
+## DFU Bootloader鐨勬湭鐭ヨ澶
+
+濡傛灉鎮ㄥ湪浣跨敤Windows鏉ュ埛鏂伴敭鐩樼殑鏃跺欑鍒颁簡闂锛屾鏌ヨ澶囩鐞嗗櫒銆傚鏋滃湪閿洏澶勪簬 "bootloader妯″紡"鏃朵綘鐪嬪埌 "鏈煡璁惧"锛岃鏄庝綘鍙兘闈复璁惧闂銆
+
+閲嶆柊杩愯MSYS2涓婄殑瀹夎鑴氭湰鎴栬浼氬噾鏁堬紙姣斿鍦∕SYS2/WSL杩愯 `./util/qmk_install.sh`) 鎴栬呴噸鏂板畨瑁匭MK宸ュ叿绠变篃鍙兘浼氳В鍐充綘鐨勯棶棰樸
+
+濡傛灉浠ヤ笂鏂规硶杩樻槸鐭拡鏀荤柦锛岄偅鎮ㄥ彲鑳介渶瑕佷娇鐢╗Zadig Utility](https://zadig.akeo.ie/)銆備笅杞芥绋嬪簭, 鎵惧埌璁惧闂, 鐒跺悗閫夋嫨 `WinUSB`閫夐」, 鐒跺悗鐐瑰嚮"Reinstall driver"銆傚畬鎴愬悗鍐嶈瘯璇曞埛鏂颁綘鐨勯敭鐩樸傚樿嫢渚濈劧寰掑姵鏃犲姛锛岄偅灏卞皾璇曟墍鏈夐夐」鐩村埌濂界敤涓烘銆
+
+?> 浜嬪疄涓婃病鏈変竴涓┍鍔ㄧ殑鏈浣抽夋嫨锛屾湁浜涢夐」灏辨槸鍜屾煇浜涚郴缁熺浉杈呯浉鎴愩備絾libUSB鍜學inUSB浼间箮涔熺畻鏄繖閲岀殑鏈浣抽夋嫨浜嗐
+濡傛灉bootloader鍦ㄨ澶囧垪琛ㄤ腑娌℃湁鏄剧ず锛屼綘鍙兘瑕佷娇鑳 "List all devices"閫夐」鍦ㄩ夐」鑿滃崟涓璥Options`锛岀劧鍚庢壘鍒版湁闂鐨刡ootloader璁惧銆(璇戣呮敞锛氬湪win10涓彲鑳戒负 鏌ョ湅-鏄剧ず闅愯棌鐨勮澶)
+
+
+## WINAVR宸叉窐姹
+涓嶅啀鎺ㄨ崘浣跨敤WINAVR锛屼娇鐢ㄥ彲鑳戒細瀵艰嚧闂
+璇︽儏璇疯[TMK Issue #99](https://github.com/tmk/tmk_keyboard/issues/99).
+
+## USB VID 鍜 PID
+浣犲彲浠ュ湪缂栬緫`config.h`鏃朵娇鐢ㄤ换浣曚綘鎯崇敤鐨処D鍊笺傚疄闄呬笂锛屼娇鐢ㄤ换浣曞彲鑳芥湭浣跨敤鐨処D閮芥病鏈夐棶棰橈紝闄や簡鏈夋瀬浣庣殑涓庡叾浠栦骇鍝佸彂鐢熷啿绐佺殑鍙兘鎬с
+
+澶у鏁癚MK涓绘澘浣跨敤`0xFEED`浣滀负vendor ID銆傛偍搴旇鏌ョ湅鍏朵粬閿洏锛屼互纭繚閫夋嫨浜嗗敮涓鐨凱roduct ID銆
+
+涔熻鐪嬬湅杩欎釜銆
+https://github.com/tmk/tmk_keyboard/issues/150
+
+涓涔熷彲浠ュ湪涓嬫柟閾炬帴璐拱涓涓敮涓鐨刅ID:PID銆備笉杩囦釜浜轰娇鐢ㄤ技涔庣敤涓嶇潃杩欎釜銆
+- 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
+
+## Cortex: `cstddef: No such file or directory`
+鍦║buntu 14.04涓婄殑GCC 4.8 浼氬嚭鐜拌繖绉嶉棶棰橀渶瑕佺敤杩欎釜PPA鍗囩骇鍒4.9銆
+https://launchpad.net/~terry.guo/+archive/ubuntu/gcc-arm-embedded
+
+https://github.com/tmk/tmk_keyboard/issues/212
+https://github.com/tmk/tmk_keyboard/wiki/mbed-cortex-porting#compile-error-cstddef
+https://developer.mbed.org/forum/mbed/topic/5205/
+
+## `clock_prescale_set` and `clock_div_1` Not Available
+浣犵殑宸ュ叿閾惧お鏃т簡涓嶆敮鎸丮CU銆傛瘮濡俉inAVR 20100110灏变笉鏀寔ATMega32u2.
+
+```
+Compiling C: ../../tmk_core/protocol/lufa/lufa.c
+avr-gcc -c -mmcu=atmega32u2 -gdwarf-2 -DF_CPU=16000000UL -DINTERRUPT_CONTROL_ENDPOINT -DBOOTLOADER_SIZE=4096 -DF_USB=16000000UL -DARCH=ARCH_AVR8 -DUSB_DEVICE_ONLY -DUSE_FLASH_DESCRIPTORS -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DFIXED_NUM_CONFIGURATIONS=1 -DPROTOCOL_LUFA -DEXTRAKEY_ENABLE -DCONSOLE_ENABLE -DCOMMAND_ENABLE -DVERSION=unknown -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -fno-inline-small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-prototypes -Wa,-adhlns=obj_alps64/protocol/lufa/lufa.lst -I. -I../../tmk_core -I../../tmk_core/protocol/lufa -I../../tmk_core/protocol/lufa/LUFA-git -I../../tmk_core/common -std=gnu99 -include config.h -MMD -MP -MF .dep/obj_alps64_protocol_lufa_lufa.o.d ../../tmk_core/protocol/lufa/lufa.c -o obj_alps64/protocol/lufa/lufa.o
+../../tmk_core/protocol/lufa/lufa.c: In function 'setup_mcu':
+../../tmk_core/protocol/lufa/lufa.c:575: warning: implicit declaration of function 'clock_prescale_set'
+../../tmk_core/protocol/lufa/lufa.c:575: error: 'clock_div_1' undeclared (first use in this function)
+../../tmk_core/protocol/lufa/lufa.c:575: error: (Each undeclared identifier is reported only once
+../../tmk_core/protocol/lufa/lufa.c:575: error: for each function it appears in.)
+make: *** [obj_alps64/protocol/lufa/lufa.o] Error 1
+```
+
+
+## AVR鐨凚OOTLOADER_SIZE
+娉ㄦ剰Teensy2.0++ bootloader鐨勫ぇ灏忔槸2048瀛楄妭銆傛湁浜汳akefile娉ㄩ噴閿欎簡銆
+
+```
+# 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
+```
+
+## 鍦∕acOS涓 `avr-gcc: internal compiler error: Abort trap: 6 (program cc1)`
+杩欐槸brew鏇存柊鐨勯棶棰橈紝瀵艰嚧AVR GCC渚濊禆鐨勭鍙烽摼鎺ヨ鎹熷潖銆
+
+瑙e喅鏂规鏄Щ闄ゅ苟閲嶆柊瀹夎鎵鏈夊彈褰卞搷鐨勬ā鍧椼
+
+```
+brew rm avr-gcc
+brew rm dfu-programmer
+brew rm dfu-util
+brew rm gcc-arm-none-eabi
+brew rm avrdude
+brew install avr-gcc
+brew install dfu-programmer
+brew install dfu-util
+brew install gcc-arm-none-eabi
+brew install avrdude
+```
+
+### avr-gcc 8.1 鍜 LUFA
+
+濡傛灉浣犳妸avr-gcc鍗囩骇鍒7浠ヤ笂浣犲彲鑳戒細閬囧埌鍏充簬LUFA鐨勯棶棰樸傛瘮濡:
+
+`lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h:380:5: error: 'const' attribute on function returning 'void'`
+
+閭d綘灏遍渶瑕佸湪brew涓妸avr-gcc鍥為鍒7銆
+
+```
+brew uninstall --force avr-gcc
+brew install avr-gcc@8
+brew link --force avr-gcc@8
+```
+
+### 鎴戝埛鏂颁簡鎴戠殑閿洏浣嗘槸閿洏涓嶅伐浣/鎸夐敭娌℃湁娉ㄥ唽 - 鑰屼笖杩樻槸ARM鐨 (rev6 planck, clueboard 60, hs60v2, etc...) (Feb 2019)
+鐢变簬EEPROM鍦ㄥ熀浜嶢RM鐨勮姱鐗囦笂鐨勫伐浣滃師鐞嗭紝淇濆瓨鐨勮缃彲鑳戒笉鍐嶆湁鏁堛傝繖浼氬奖鍝嶉粯璁ゅ眰锛岃屼笖*鎴栬*鍦ㄦ煇浜涙儏鍐典笅锛屼細浣块敭鐩樹笉濂界敤锛屾垜浠粛鍦ㄨ皟鏌ヨ繖浜涙儏鍐点傞噸缃瓻EPROM灏嗚В鍐虫闂銆
+
+[Planck rev6閿洏閲嶇疆EEPROM](https://cdn.discordapp.com/attachments/473506116718952450/539284620861243409/planck_rev6_default.bin) 鏄敤浜庡己鍒堕噸缃瓻EPROM鐨勩傚埛鍏ヨ繖涓枃浠跺悗锛屽啀娆″埛鍏ユ甯稿浐浠讹紝杩欎細灏嗛敭鐩樻仮澶嶅埌_姝e父_宸ヤ綔鐘舵併
+[Preonic rev3閿洏閲嶇疆EEPROM](https://cdn.discordapp.com/attachments/473506116718952450/537849497313738762/preonic_rev3_default.bin)
+
+濡傛灉浠ヤ换浣曞舰寮忓惎鐢ㄤ簡bootmagic锛 閭d箞鎮ㄨ繕闇瑕(鐪媅Bootmagic鏂囨。](feature_bootmagic.md) 浠ュ強閿洏淇℃伅锛屼互浜嗚В濡備綍鎵ц姝ゆ搷浣滅殑璇︾粏淇℃伅).
diff --git a/docs/zh-cn/faq_debug.md b/docs/zh-cn/faq_debug.md
new file mode 100644
index 0000000000..ca8b3fd25d
--- /dev/null
+++ b/docs/zh-cn/faq_debug.md
@@ -0,0 +1,233 @@
+# 璋冭瘯鐨勫父瑙侀棶棰
+
+鏈瘒璇︾粏浠嬬粛浜嗕汉浠湪閿洏鏁呴殰鎺掗櫎鏃剁殑鍚勭甯歌闂銆
+
+# 璋冭瘯鎺у埗鍙
+
+## `hid_listen` 鏃犳硶璇嗗埆璁惧
+褰撹澶囩殑璋冭瘯鎺у埗鍙版湭灏辩华鏃讹紝鎮ㄥ皢鐪嬪埌濡備笅鍐呭锛
+
+```
+Waiting for device:.........
+```
+
+鎻掑叆璁惧鍚庯紝*hid_listen*鎵惧埌璇ヨ澶囷紝鎮ㄥ皢鏀跺埌浠ヤ笅娑堟伅锛
+
+```
+Waiting for new device:.........................
+Listening:
+```
+
+濡傛灉鎮ㄦ棤娉曡幏寰楄繖鏉♀淟istening:鈥濇秷鎭紝璇峰皾璇曞湪[Makefile]涓娇鐢 `CONSOLE_ENABLE=yes`
+
+鍦↙inux杩欐牱鐨勬搷浣滅郴缁熶笂锛屼綘鍙兘闇瑕佷竴浜涙潈闄愩
+- 浣跨敤`sudo hid_listen`
+
+## 鎺у埗鍙版病鏈夎繑鍥炴秷鎭
+妫鏌:
+- *hid_listen* 鎵惧埌浜嗕綘鐨勮澶囥傜湅鍓嶉潰銆
+- 杈撳叆**Magic**+d鎵撳紑璋冭瘯銆傝瑙乕Magic Commands](https://github.com/tmk/tmk_keyboard#magic-commands)銆
+- 璁剧疆`debug_enable=true` 锛屼竴鑸瓨鍦ㄤ簬**matrix.c**鐨刞matrix_init()`涓
+- 灏濊瘯浣跨敤'print'鍑芥暟鑰屼笉瑕佺敤璋冭瘯杈撳嚭銆傝瑙**common/print.h**銆
+- 鏂紑鍏朵粬鏈夋帶鍒跺彴鍔熻兘鐨勮澶囥 璇﹁[Issue #97](https://github.com/tmk/tmk_keyboard/issues/97)銆
+
+## Linux鎴朥NIX杩欐牱鐨勭郴缁熷浣曡姹傝秴绾х敤鎴锋潈闄
+鐢'sudo'鏉ユ墽琛*hid_listen*灏辨湁鏉冮檺浜嗐
+```
+$ sudo hid_listen
+```
+
+鎴栬呮妸涓涓枃浠舵斁鍒拌鍒欐枃浠跺す鏉ヤ负TMK璁惧娣诲姞*udev瑙勫垯*锛屼笉鍚岀郴缁熺殑鐩綍鍙兘鏈夋墍涓嶅悓銆
+
+鏂囦欢: /etc/udev/rules.d/52-tmk-keyboard.rules(鍦║buntu绯荤粺鐨勬儏鍐典笅)
+```
+# tmk keyboard products https://github.com/tmk/tmk_keyboard
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666"
+```
+
+***
+
+# 鍏朵粬
+## 瀹夊叏娉ㄦ剰浜嬮」
+
+浣犲簲璇ヤ笉鎯宠鎶婁綘鐨勯敭鐩樺彉鎴"鐮栧ご"鍚э紝灏辨槸鍙樻垚娌℃硶閲嶅啓鍥轰欢鐨勯偅绉嶃
+涓嬮潰璁茶В涓浜涘弬鏁版潵鍛婅瘔浣犱粈涔堥闄╁緢澶э紙鍏跺疄涔熶笉鏄緢澶э級銆
+
+- 鍋囧浣犻敭鐩樿〃闈㈡病鏈夎璁¢噸缃敭"RESET", 閭d綘瑕佽繘鍏ootloader鐨勮瘽灏辫鎸塒CB涓婄殑RESET浜嗐
+ 鎸塒CB涓婄殑RESET瑕佹嫥寮閿洏搴曢儴銆
+- 濡傛灉 tmk_core / common 閲岄潰鐨勬枃浠朵涪澶遍敭鐩樺彲鑳藉け鐏点
+- .hex澶ぇ鍙兘涓嶅お濂; `make dfu` 浼氬垹闄ゅ潡锛屾楠屽ぇ灏忥紙鍜?濂藉儚鍙嶄簡...锛夈
+ 涓浣嗗嚭閿欙紝鍒锋柊閿洏澶辫触鐨勮瘽灏卞洶鍦―FU鍑轰笉鍘讳簡銆
+ - 鎵浠, 瑕佺煡閬撳ぇ灏忛檺鍒躲 Planck閿洏涓.hex鏂囦欢鏈澶уぇ灏忔槸 is 7000h (鍗佽繘鍒舵槸28672)
+
+```
+Linking: .build/planck_rev4_cbbrowne.elf [OK]
+Creating load file for Flash: .build/planck_rev4_cbbrowne.hex [OK]
+
+Size after:
+ text data bss dec hex filename
+ 0 22396 0 22396 577c planck_rev4_cbbrowne.hex
+```
+
+ - 涓婇潰閭d釜鏂囦欢澶у皬鏄 22396/577ch锛屾瘮28672/7000h灏
+ - 褰撲綘鏈変竴涓悎閫傜殑.hex鏂囦欢鏃讹紝浣犲氨瑕侀噸璇曞姞杞介偅涓簡
+ - 鎮ㄥ湪閿洏Makefile涓殑鏌愪簺閫夐」鍙兘娑堣楅澶栧唴瀛橈紱娉ㄦ剰浠ヤ笅杩欏嚑涓
+ BOOTMAGIC_ENABLE, MOUSEKEY_ENABLE, EXTRAKEY_ENABLE, CONSOLE_ENABLE, API_SYSEX_ENABLE
+- DFU 宸ュ叿/涓/鍙互鍐欏叆bootloader (unless you throw in extra fruit salad of options),
+ 鎵浠ヨ繕鏄湁鐐瑰嵄闄╃殑
+- EEPROM澶ф鏈100000娆″惊鐜鍛姐備笉瑕佹绘槸棰戠箒閲嶅啓鍥轰欢锛汦EPROM浼氱帺鍧忕殑銆
+## 鍏ㄩ敭鏃犲啿涓嶅ソ鐢
+棣栧厛浣犺鍦**Makefile**鐢ㄥ涓嬪懡浠ょ紪璇戝浐浠禶NKRO_ENABLE`銆
+
+鍏ㄩ敭鏃犲啿杩樹笉濂界敤鐨勮瘽璇曠潃鐢╜Magic` **N** 鍛戒护(榛樿鏄痐LShift+RShift+N`)銆傝繖涓懡浠や細鍦**鍏ㄩ敭鏃犲啿**鍜**鍏敭鏃犲啿**涔嬮棿涓存椂鍒囨崲銆傛湁浜涙儏鍐**鍏ㄩ敭鏃犲啿**涓嶅ソ鐢ㄤ綘灏遍渶瑕佷娇鐢**鍏敭鏃犲啿**妯″紡锛屽挨鍏舵槸鍦˙IOS涓
+
+濡傛灉浣犵殑鍥轰欢浣跨敤`BOOTMAGIC_ENABLE`缂栬瘧鐨勪綘瑕佺敤`BootMagic` **N** 鍛戒护(榛樿`Space+N`)鎵撳紑寮鍏炽傝繖涓缃繚瀛樺湪EEPROM涓苟淇濆瓨鍦ㄧ數婧愬惊鐜腑銆
+<!--缈昏瘧闂锛氫笂闈㈣繖鍙ョ炕璇戠殑涓嶈创鍒 -->
+
+https://github.com/tmk/tmk_keyboard#boot-magic-configuration---virtual-dip-switch
+
+
+## 鎸囩偣鏉嗛渶瑕佸浣嶇數璺(PS/2 榧犳爣鏀寔)
+濡傛灉娌℃湁澶嶄綅鐢佃矾锛岀敱浜庣‖浠跺垵濮嬪寲涓嶆纭紝鎮ㄥ皢寰楀埌涓嶄竴鑷寸殑缁撴灉銆傛煡鐪婽PM754澶嶄綅鐢佃矾銆
+
+- http://geekhack.org/index.php?topic=50176.msg1127447#msg1127447
+- http://www.mikrocontroller.net/attachment/52583/tpm754.pdf
+
+
+## 鐭╅樀涓嶅彲璇16浠ヤ笂鐨勫垪
+褰撳垪瓒呰繃16鏃禰matrix.h]鐨刞read_cols()`涓紝鐢╜1UL<<16`鑰屼笉瑕佺敤`1<<16`銆
+
+鍦–璇█涓璥1` 鏄竴涓猍int] 绫诲瀷鐨刐16 bit]鍊硷紝鍦ˋVR涓綘涓嶈兘宸︾Щ澶т簬15娆°傚鏋滀綘浣跨敤`1<<16`鐨勮瘽浼氬緱鍒版剰澶栫殑闆躲備綘瑕佺敤 [unsigned long]绫诲瀷锛屾瘮濡俙1UL`銆
+
+http://deskthority.net/workshop-f7/rebuilding-and-redesigning-a-classic-thinkpad-keyboard-t6181-60.html#p146279
+
+
+## Bootloader璺宠浆涓嶅ソ鐢
+鍦**Makefile**涓纭厤缃**Makefile**澶у皬銆傚鏋滃垎鍖哄ぇ灏忎笉姝g‘锛屽紩瀵煎姞杞界▼搴忓彲鑳芥棤娉曚粠**Magic command**鍜**Boot Magic**鍔犺浇銆
+```
+# bootloader瀛楄妭鏁帮細
+# Atmel DFU loader(ATmega32U4) 4096
+# Atmel DFU loader(AT90USB128) 8192
+# LUFA bootloader(ATmega32U4) 4096
+# Arduino Caterina(ATmega32U4) 4096
+# USBaspLoader(ATmega***) 2048
+# Teensy halfKay(ATmega32U4) 512
+# Teensy++ halfKay(AT90USB128) 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+```
+AVR寮曞澶у皬鏄氳繃**BOOTSZ**鐔斾笣浣嶆潵璁剧疆鐨勩傛煡闃呬綘鍗曠墖鏈虹殑datasheet銆
+璁颁綇锛宒atasheet鐢ㄧ殑鏄**Word**(2瀛楄妭)琛ㄧず澶у皬鍜屽湴鍧锛孴MK鐢ㄧ殑鏄**Byte**銆
+
+AVR寮曞閮ㄥ垎浣嶄簬闂瓨鐨勬湯灏撅紝濡備笅鎵绀猴紙Application鏄簲鐢ㄥ尯锛孊ootloader鏄紩瀵煎尯锛夈
+```
+byte Atmel/LUFA(ATMega32u4) byte Atmel(AT90SUB1286)
+0x0000 +---------------+ 0x00000 +---------------+
+ | | | |
+ | | | |
+ | Application | | Application |
+ | | | |
+ = = = =
+ | | 32KB-4KB | | 128KB-8KB
+0x6000 +---------------+ 0x1E000 +---------------+
+ | Bootloader | 4KB | Bootloader | 8KB
+0x7FFF +---------------+ 0x1FFFF +---------------+
+
+
+byte Teensy(ATMega32u4) byte Teensy++(AT90SUB1286)
+0x0000 +---------------+ 0x00000 +---------------+
+ | | | |
+ | | | |
+ | Application | | Application |
+ | | | |
+ = = = =
+ | | 32KB-512B | | 128KB-2KB
+0x7E00 +---------------+ 0x1FC00 +---------------+
+ | Bootloader | 512B | Bootloader | 2KB
+0x7FFF +---------------+ 0x1FFFF +---------------+
+```
+
+璇︽儏璇疯涓嬫柟issue銆
+https://github.com/tmk/tmk_keyboard/issues/179
+
+濡傛灉浣犱娇鐢═eensyUSB, 鏈変竴涓猍宸茬煡bug](https://github.com/qmk/qmk_firmware/issues/164)纭欢閲嶇疆鎸夐挳闃绘杞欢瀹氫箟閲嶇疆閿伐浣溿傞噸鏂版彃鎷旈敭鐩樺氨濂戒簡銆
+
+## 鐗规畩棰濆閿笉璧蜂綔鐢(绯荤粺锛岄煶棰戞帶鍒堕敭)
+浣犺鍦╜rules.mk`瀹氫箟`EXTRAKEY_ENABLE`鍦≦MK涓娇鐢ㄥ畠浠
+
+```
+EXTRAKEY_ENABLE = yes # 闊抽鎺у埗鍜岀郴缁熸帶鍒
+```
+
+## 鐫$湢鍞ら啋涓嶅ソ鐢
+
+鍦╓indows鏌ョ湅璁惧绠$悊鍣ㄤ腑璇ラ敭鐩樿澶囧睘鎬т腑鐢垫簮绠$悊閫夐」鍗′腑鐨刞鍏佽姝よ澶囧敜閱掕绠楁満(O)`鏄惁鍕鹃夈傚悓鏃剁湅涓鐪糂IOS璁剧疆銆
+
+鍦ㄤ富鏈虹潯鐪犳椂鎸変笅浠讳綍閿兘鍙互鍞ら啋浜嗐
+
+## 浣跨敤Arduino?
+
+**娉ㄦ剰Arduino鐨勯拡鑴氬悕瀛楀拰涓绘帶鑺墖鐨勪笉涓鏍枫** 姣斿, Arduino鐨刞D0`骞朵笉鏄痐PD0`銆傝嚜宸辩敤鍘熺悊鍥炬崑涓涓嬬數璺
+
+- http://arduino.cc/en/uploads/Main/arduino-leonardo-schematic_3b.pdf
+- http://arduino.cc/en/uploads/Main/arduino-micro-schematic.pdf
+
+Arduino Leonardo鍜宮icro浣跨敤**ATMega32U4**锛岃鑺墖TMK鍙敤锛屼絾Arduino鐨刡ootloader浼氬鑷撮棶棰樸
+
+
+## 鍦║SB AVR浣跨敤PF4-7閽堣剼?
+浣犺缃綅MCUCR瀵勫瓨鍣↗TD浣嶆潵灏哖F4-7璁剧疆涓篏PIO銆傝繖浜涢拡鑴氶粯璁ゆ槸JTAG鍔熻兘銆 鍍廇TMega*U* or AT90USB*杩欐牱鐨凪CU浼氬彈褰卞搷銆
+
+濡傛灉鏄敤Teensy鐨勮瘽灏变笉闇瑕佷簡銆俆ennsy鑷甫JTAGEN浣嶆湭缂栫▼鏉ュけ鑳借鍔熻兘銆
+<!--缈昏瘧闂锛氫笂鍙ュ彲鑳芥湁閿欙紝鍘熸枃涓猴細Teensy is shipped with JTAGEN fuse bit unprogrammed to disable the function. -->
+浠g爜濡備笅銆
+```
+ // F鎺ュ彛JTAG澶辫兘銆傚湪鍥涗釜鍛ㄦ湡鍐呭啓鍏ヤ袱娆TD浣嶃
+ MCUCR |= (1<<JTD);
+ MCUCR |= (1<<JTD);
+```
+https://github.com/tmk/tmk_keyboard/blob/master/keyboard/hbkb/matrix.c#L67
+
+闃呰ATMega32U4鐨刣atasheet涓殑**26.5.1 MCU Control Register 鈥 MCUCR**銆
+
+
+## 涓洪攣瀹氶敭娣诲姞鎸囩ず鐏
+浣犺鑷埗CapsLock, ScrollLock 鍜 NumLock鎸囩ず鐏紵瑙佷笅鏂囥
+
+http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478-120.html#p191560
+
+## 涓篈rduino Micro/Leonardo缂栫▼
+鎸変笅閲嶇疆閿劧鍚庡湪8绉掑唴杩愯涓嬫柟杩欐牱鐨勫懡浠ゃ
+
+```
+avrdude -patmega32u4 -cavr109 -b57600 -Uflash:w:adb_usb.hex -P/dev/ttyACM0
+```
+
+璁惧鍚嶇О鍥犵郴缁熻屽紓銆
+
+http://arduino.cc/en/Main/ArduinoBoardMicro
+https://geekhack.org/index.php?topic=14290.msg1563867#msg1563867
+
+
+## USB 3 鍏煎鎬
+鎹紶璇存湁浜涗汉鐢║SB3鎺ュ彛浼氭湁闂锛岀敤USB2鐨勮瘯璇曘
+
+
+## Mac 鍏煎鎬
+### OS X 10.11 鍜岄泦绾垮櫒
+https://geekhack.org/index.php?topic=14290.msg1884034#msg1884034
+
+
+## 瀵逛簬BIOS (UEFI)/鎭㈠(鐫$湢鍜屽敜閱)/閲嶆柊鍚姩 鏈夐棶棰
+鏈変汉璇翠粬浠殑閿洏鍦˙IOS涓紝鎴栬鏄仮澶(鐫$湢鍜屽敜閱)鍚庝笉宸ヤ綔.
+
+鎴鑷崇洰鍓嶏紝鍏舵牴鏈師鍥犳湭鐭ワ紝涓嶆帓闄や笌鏌愪簺鏋勫缓閫夐」鏈夊叧銆傝瘯鐫鍦∕akefile涓け鑳絗CONSOLE_ENABLE`, `NKRO_ENABLE`, `SLEEP_LED_ENABLE`杩欐牱鐨勯夐」锛屼篃璇曡瘯鍏朵粬鐨勩
+
+https://github.com/tmk/tmk_keyboard/issues/266
+https://geekhack.org/index.php?topic=41989.msg1967778#msg1967778
+
+
+
+## FLIP 涓嶅伐浣
+### `AtLibUsbDfu.dll` 鏈壘鍒
+浠庤澶囩鐞嗗櫒涓垹闄ゅ綋鍓嶉┍鍔ㄧ▼搴忓苟鍦ㄨ澶囩鐞嗗櫒閲嶆柊瀹夎涓涓狥LIP鎻愪緵鐨勭▼搴忋
+http://imgur.com/a/bnwzy
diff --git a/docs/zh-cn/faq_general.md b/docs/zh-cn/faq_general.md
new file mode 100644
index 0000000000..4949acb8c9
--- /dev/null
+++ b/docs/zh-cn/faq_general.md
@@ -0,0 +1,19 @@
+# 常见问题
+
+## QMK是什么?
+
+[QMK](https://github.com/qmk), 是量子机械键盘(Quantum Mechanical Keyboard)的缩写,是一群开源爱好者为定制键盘开发的工具。我们从[QMK固件](https://github.com/qmk/qmk_firmware)开始,这是[TMK](https://github.com/tmk/tmk_keyboard)的魔改分叉。
+
+### 为什么叫量子(Quantum)?
+
+<!-- 待修复 译者吐槽:文档作者竟然也不知道为啥。。。 -->
+
+## QMK和TMK有什么区别?
+
+TMK最初由[Jun Wako](https://github.com/tmk)设计和执行。QMK始于[Jack Humbert](https://github.com/jackhumbert)为Planck键盘创建的TMK分叉。一段时间后,Jack的分叉就和TMK相去甚远了,于是在2015年,Jack决定改名QMK。
+
+从技术观点来讲,QMK是TMK添加一些新功能而成的。尤其是QMK扩展了可用的键码,使高级功能进一步丰富比如 `S()`, `LCTL()`, 和 `MO()`。全部键码见[键码](keycodes.md).
+
+从工程的社区管理来讲TMK自己维护了所有官方支持的键盘,只有很小一部分社区支持。独立社区维护已存在分叉或为其他键盘创建的分叉。默认支持很少的键码,所以用户通常不会与他人分享布局。QMK鼓励通过集中管理仓库分享布局和键盘,我们会采纳所有符合质量标准的PR。这就极大的保证了社区维护,同时QMK小组也会在必要时给予帮助。
+
+这两种方法都有其优点和缺点,并且代码在有意义时在TMK和QMK之间自由流动。
diff --git a/docs/zh-cn/faq_keymap.md b/docs/zh-cn/faq_keymap.md
new file mode 100644
index 0000000000..ee8e3c06bf
--- /dev/null
+++ b/docs/zh-cn/faq_keymap.md
@@ -0,0 +1,212 @@
+# 甯冨眬甯歌闂
+
+鏈〉鏈〉鍖呭惈浜轰滑缁忓父閬囧埌鐨勫叧浜庡竷灞鐨勯棶棰樸傚鏋滀綘瑙夊緱娌′粈涔堥棶棰橈紝璇峰厛鐪媅甯冨眬姒傝](keymap.md)銆
+
+## 鎴戣兘鐢ㄤ粈涔堥敭鐮?
+鐪媅閿爜](keycodes.md)浣犲彲浠ユ壘鍒颁綘鑳界敤鐨勯敭鐮佺储寮曘傚彲浠ョ殑璇濊繖浜涢摼鎺ュ彲浠ヨ繛鎺ュ埌鏇村箍娉涚殑鏂囨。銆
+
+閿爜瀹為檯涓婂畾涔夊湪[common/keycode.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/keycode.h).
+
+## 榛樿鐨勯敭鐮佷粈涔堟牱?
+
+涓栫晫涓婃湁涓夌鏍囧噯閿洏璁捐锛屽垎鍒槸锛欰NSI, ISO, and JIS. 涓昏鏄寳缇庣敤ANSI(璇戣呮敞锛氫腑鍥藉緢澶氶敭鐩樹娇鐢ㄨ繖涓), 娆ф床鍜岄潪娲蹭富瑕佷娇鐢↖SO锛屾棩鏈娇鐢↗IS銆傛湭鎻愬強鐨勫尯鍩熼氬父浣跨敤ANSI鎴朓SO銆備笌杩欎簺璁捐瀵瑰簲鐨勯敭浠g爜濡備笅鎵绀猴細
+
+<!-- 璇ュ浘鐗囩殑鏉ユ簮: http://www.keyboard-layout-editor.com/#/gists/bf431647d1001cff5eff20ae55621e9a -->
+![閿洏璁捐鍥綸(https://i.imgur.com/5wsh5wM.png)
+
+## 鎴戞湁涓浜涢敭鍙樻垚浜嗗叾浠栧姛鑳芥垨鑰呬笉宸ヤ綔浜
+
+QMK鏈変袱涓姛鑳斤紝Bootmagic鍜屽懡浠よ锛屽畠鍏佽鎮ㄥ湪杩愯涓洿鏀归敭鐩樼殑琛屼负銆傝鍔熻兘鍖呮嫭浣嗕笉浠呴檺浜, 浜ゆ崲Ctrl/Caps锛屽叧闂晫闈紝浜ゆ崲Alt/Gui锛屼氦鎹 Backspace/Backslash锛岀鐢ㄦ墍鏈夐敭锛屼互鍙婂叾浠栫殑琛屼负鏀瑰彉銆
+
+蹇熻В鍐虫柟娉曟槸鎻掑叆閿洏鏃舵寜浣廯Space`+`Backspace`銆傝鎿嶄綔灏嗛噸缃凡淇濆瓨璁剧疆锛岃杩欎簺閿洖澶嶅垵濮嬪姛鑳姐傝繖鎷涗笉濂界敤鐨勮瘽鍙傞槄涓嬫柟锛
+
+* [Bootmagic](feature_bootmagic.md)
+* [鍛戒护](feature_command.md)
+
+## 鑿滃崟閿笉濂界敤
+
+鐜板湪澶у鏁伴敭鐩 `KC_RGUI`鍜宍KC_RCTL`涓棿鐨勯敭瀛愬彨鍋歚KC_APP`銆傝繖鏄洜涓哄湪杩欎釜閿瓙鍙戞槑涔嬪墠鐩稿叧鏍囧噯閲屽氨宸茬粡鏈夐敭鍙仛`MENU(鑿滃崟)`浜嗭紝鎵浠ュ井杞彨浠朻APP(搴旂敤)`閿
+
+## `KC_SYSREQ` 涓嶅伐浣
+浣跨敤鎶撳睆鐨勯敭鐮(`KC_PSCREEN`鎴朻KC_PSCR`)鑰屼笉鐢╜KC_SYSREQ`銆傜粍鍚堥敭'Alt + Print Screen'浼氳褰撲綔'System request'銆
+
+瑙乕issue #168](https://github.com/tmk/tmk_keyboard/issues/168)鍜
+* http://en.wikipedia.org/wiki/Magic_SysRq_key
+* http://en.wikipedia.org/wiki/System_request
+
+## 鐢垫簮閿笉宸ヤ綔
+
+杩欐湁鐐硅浜哄洶鎯,QMK鏈変袱涓"Power(鐢垫簮)"閿爜: `KC_POWER` 鍦ㄩ敭鐩/灏忛敭鐩樼殑HID浣跨敤椤甸潰涓紝`KC_SYSTEM_POWER` (鎴栬呭彨`KC_PWR`)鍦ㄧ敤鎴烽〉銆
+
+鍓嶈呭彧鑳借macOS璇嗗埆锛屼絾鏄悗鑰咃紝鍗砢KC_SLEP`鍜宍KC_WAKE`涓夊ぇ涓昏鎿嶄綔绯荤粺鍏ㄩ兘鏀寔锛屾墍浠ユ帹鑽愪娇鐢ㄨ繖涓や釜銆俉indows涓嬭繖浜涢敭绔嬪嵆鐢熸晥锛宮acOS瑕侀暱鎸夌洿鍒板脊鍑哄璇濇銆
+
+## 鑷姩澶у皬鍐欓攣瀹
+鍙互瑙e喅'the'闂(姝e父搴斾负The)銆傛垜缁忓父鍦ㄨ緭鍏'The'鏃朵笉鎱庤緭鍏ヤ簡'the'鎴栬'THe'銆傝嚜鍔ㄥぇ灏忓啓閿佸畾鍙互淇姝ょ被闂銆傝瑙佷笅鏂归摼鎺ャ
+https://github.com/tmk/tmk_keyboard/issues/67
+
+## 淇敼 閿/灞 鍗′綇
+闄ら潪姝g‘閰嶇疆灞傚垏鎹紝鍚﹀垯淇敼閿垨灞傚彲鑳戒細鍗′綇銆
+瀵逛簬淇敼閿拰鍥惧眰鎿嶄綔锛屽繀椤绘妸`KC_TRANS`鏀惧埌鐩爣灞傜殑鐩稿悓浣嶇疆锛岀敤浜庢敞閿淇敼閿垨鍦ㄩ噴鏀句簨浠舵椂杩斿洖鍒颁笂涓灞傘
+* https://github.com/tmk/tmk_core/blob/master/doc/keymap.md#31-momentary-switching
+* http://geekhack.org/index.php?topic=57008.msg1492604#msg1492604
+* https://github.com/tmk/tmk_keyboard/issues/248
+
+
+## 鏈烘鑷攣寮鍏虫敮鎸丮echanical Lock Switch Support
+
+鏈姛鑳界敤浜*鏈烘鑷攣寮鍏*姣斿[this Alps one](http://deskthority.net/wiki/Alps_SKCL_Lock)銆備綘鍙互閫氳繃鍚慲config.h`娣诲姞浠ヤ笅瀹忔潵浣胯兘璇ュ姛鑳斤細
+
+```
+#define LOCKING_SUPPORT_ENABLE
+#define LOCKING_RESYNC_ENABLE
+```
+
+鍦ㄤ娇鑳借鍔熻兘鍚庯紝瑕佸湪閿洏涓娇鐢╜KC_LCAP`, `KC_LNUM` 鍜 `KC_LSCR`杩欎笁涓敭鐮併
+
+杩滃彜鏈烘閿洏鍋跺皵浼氭湁鑷攣鏈烘寮鍏筹紝鐜板湪鍑犱箮娌℃湁浜嗐***澶у鏁版儏鍐典笅浣犱笉闇瑕佷娇鐢ㄨ鍔熻兘锛屼笖瑕佷娇鐢╜KC_CAPS`, `KC_NLCK`鍜宍KC_SLCK`杩欎笁涓敭鐮併***
+
+## 杈撳叆ASCII涔嬪鐨勭壒娈婂瓧绗︽瘮濡侰茅dille '脟'
+娌℃湁鍦ㄦ墍鏈夌郴缁熶腑杈撳叆杩欎釜鐨勯氱敤鏂规硶銆備綘瑕佸畾涔夐拡瀵逛綘鐨勭壒瀹氭搷浣滅郴缁熸垨甯冨眬鐨**瀹**銆
+
+姣斿鐪嬭繖涓**瀹**浠g爜鐨勬枃绔犮
+
+http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478-120.html#p195620
+<!--缈昏瘧闂锛氫笅鏂圭淮鍩虹櫨绉戦摼鎺ュ簲鍏ㄩ儴鏇挎崲涓轰腑鏂囬摼鎺ワ紝鏆傛湭鎵惧埌鍏ㄩ儴-->
+鍦**Windows**涓婏紝鍙互鐢╜AltGr`閿垨**Alt鐮**銆
+* http://en.wikipedia.org/wiki/AltGr_key
+* https://zh.wikipedia.org/wiki/Alt%E7%A0%81
+
+鍦**Mac OS**瀹氫箟`Option`閿粍鍚堛
+* https://zh.wikipedia.org/wiki/Option%E9%94%AE#%E6%9B%BF%E4%BB%A3%E9%94%AE%E7%9B%98%E8%BE%93%E5%85%A5
+
+鍦**Xorg**鍙互鏀圭敤`compose`閿
+* http://en.wikipedia.org/wiki/Compose_key
+
+涓嬫柟閾炬帴鏌ョ湅**Unicode**杈撳叆銆
+* http://en.wikipedia.org/wiki/Unicode_input
+
+## macOS涓婄殑`Fn`
+
+涓嶅儚澶у鏁癋N閿紝鑻规灉涓婇偅涓湁鑷繁鐨勯敭鐮...鍛冿紝鍩烘湰涓婄畻鍚с 浠栧彇缂斾簡鍩烘湰6閿棤鍐睭ID鎶ュ憡鐨勭鍏釜閿爜 -- 鎵浠ヨ嫻鏋滈敭鐩樺叾瀹炴槸5閿棤鍐茬殑銆
+
+鎶鏈笂璇碤MK鍙互鍙戦佽繖涓敭銆備絾鏄紝杩欐牱鍋氶渶瑕佷慨鏀规姤鍛婃牸寮忎互娣诲姞FN閿殑鐘舵併傝繖杩樹笉鏄渶绯熺硶鐨勶紝浣犵殑閿洏鐨刅ID鍜孭ID鍜岀湡鐨勮嫻鏋滈敭鐩樹笉涓鏍风殑璇濊繕涓嶄細琚瘑鍒
+QMK瀹樻柟鏀寔杩欎釜浼氳寰嬪笀鍑界殑锛屾墍浠ュ氨褰撴垜娌¤杩囥
+
+璇﹁[issue#2179](https://github.com/qmk/qmk_firmware/issues/2179)銆
+
+
+## Mac OSX鐨勫獟浣撴帶鍒堕敭
+#### KC_MNXT 鍜 KC_MPRV 鍦∕ac涓婁笉濂界敤
+浣跨敤 `KC_MFFD`(`KC_MEDIA_FAST_FORWARD`) 鍜 `KC_MRWD`(`KC_MEDIA_REWIND`)锛屼笉瑕佺敤 `KC_MNXT` 鍜 `KC_MPRV`.
+璇﹁ https://github.com/tmk/tmk_keyboard/issues/195
+
+
+## Mac OSX涓敮鎸侀偅浜涢敭?
+浣犲彲浠ヤ粠姝ゆ簮鐮佷腑鑾风煡鍦∣SX涓敮鎸佸摢浜涢敭鐮
+
+`usb_2_adb_keymap` 闃靛垪鏄犲皠 閿洏/灏忛敭鐩 椤电敤浜嶢DB鎵弿鐮(OSX鍐呴儴閿爜).
+
+https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-606.1.7/IOHIDFamily/Cosmo_USB2ADB.c
+
+`IOHIDConsumer::dispatchConsumerEvent`浼氬鐞嗙敤鎴烽〉闈㈢敤娉曘
+<!--缈昏瘧闂锛氫笂闈㈤偅涓ゅ彞缈昏瘧鐨勪笉濂-> handles Consumer page usages. -->
+https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-606.1.7/IOHIDFamily/IOHIDConsumer.cpp
+
+
+## Mac OSX涓殑JIS閿
+宀涘浗鐗瑰埆閿瘮濡俙鐒″鎻(Muhenkan)`, `澶夋彌(Henkan)`, `銇层倝銇屻仾(hiragana)`OSX鏄笉鏄埆鐨勩俌ou can use **Seil** to enable those keys, try following options.
+<!--缈昏瘧闂锛氫互涓娾滃矝鍥界壒鍒敭鈥濇病鏈変换浣曞湴鍩熸瑙嗙殑鎰忔 -->
+* 鍦ㄧ數鑴戦敭鐩樹笂浣胯兘NFER閿
+* 鍦ㄧ數鑴戦敭鐩樹笂浣胯兘XFER閿
+* 鍦ㄧ數鑴戦敭鐩樹笂浣胯兘KATAKAN閿
+
+https://pqrs.org/osx/karabiner/seil.html
+
+
+## RN-42钃濈墮妯″潡涓嶬arabiner涓嶈兘鏈夋晥鍗忓悓宸ヤ綔
+Karabiner - Mac OSX鐨勬敼閿蒋浠 - 榛樿RN-42妯″潡鏄笉浼氳鍝嶅簲鐨勩傛兂瑕並arabiner鍜屼綘鐨勯敭鐩樺崗鍚屽伐浣滀綘瑕佷娇鑳芥閫夐」锛
+https://github.com/tekezo/Karabiner/issues/403#issuecomment-102559237
+
+姝ら棶棰樿瑙佷笅鏂归摼鎺ャ
+https://github.com/tmk/tmk_keyboard/issues/213
+https://github.com/tekezo/Karabiner/issues/403
+
+
+## Esc 鍜 <code>&#96;</code> 鍙屽姛鑳介敭
+
+璇疯[Grave Escape](feature_grave_esc.md)鍔熻兘銆
+
+## 鍙充晶鍙岃鑹蹭慨鏀归敭(璇稿Shift銆丄lt绛夋湁淇敼鍏朵粬閿綔鐢ㄧ殑閿)鍙樼澶撮敭
+鍙充晶淇敼閿崟鍑绘椂浼氬彉涓虹澶撮敭锛岄暱鎸夊氨杩樻槸淇敼閿傚湪TMK涓弻瑙掕壊閿О涔嬩负**TAP**.
+```
+
+#include "keymap_common.h"
+
+
+/* 鐢═MK鍙岃鑹查敭鍔熻兘瀹炵幇鍙充晶淇敼閿敼绠ご閿
+ *
+ * https://github.com/tmk/tmk_core/blob/master/doc/keymap.md#213-modifier-with-tap-keydual-role
+ * https://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys
+ */
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: qwerty */
+ [0] = LAYOUT( \
+ ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, NUHS,BSPC, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
+ LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \
+ LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH,FN0, ESC, \
+ FN4, LGUI,LALT, SPC, APP, FN2, FN1, FN3),
+ [1] = LAYOUT( \
+ GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS,TRNS, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,\
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN5, TRNS, \
+ TRNS,TRNS,TRNS, TRNS, TRNS,FN7, FN6, FN8),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_UP),
+ [1] = ACTION_MODS_TAP_KEY(MOD_RGUI, KC_DOWN),
+ [2] = ACTION_MODS_TAP_KEY(MOD_RALT, KC_LEFT),
+ [3] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_RIGHT),
+ [4] = ACTION_LAYER_MOMENTARY(1),
+ [5] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_PGUP),
+ [6] = ACTION_MODS_TAP_KEY(MOD_RGUI, KC_PGDN),
+ [7] = ACTION_MODS_TAP_KEY(MOD_RALT, KC_HOME),
+ [8] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_END),
+};
+
+```
+
+鍙岃鑹查敭璇存槑: https://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys
+
+
+## Mac OSX鐨勫脊鍑洪敭
+`KC_EJCT` 閿爜鍦∣SX鍙互浣跨敤 https://github.com/tmk/tmk_keyboard/issues/250
+浼间箮Windows10浼氬拷鐣ヨ閿爜锛孡inux/Xorg鍙互璇嗗埆璇ラ敭鐮佷絾榛樿涓嶆槧灏勩
+
+鐩墠灏氫笉娓呮濡備綍鍦ㄧ湡姝g殑鑻规灉閿洏鎸夊嚭寮瑰嚭閿侶HKB浣跨敤`F20`鐢ㄤ簬寮瑰嚭閿(`Fn+f`)锛岃鍔熻兘鍦∕AC妯″紡鏈夋晥浣嗕笉淇濊瘉涓庤嫻鏋滃脊鍑洪敭鐮佺浉绗︺
+
+
+## `action_util.c`涓殑 `weak_mods`鍜宍real_mods`鏄粈涔
+___寰呮敼鍠刜__
+
+real_mods 鐢ㄤ簬淇濆瓨瀹為檯(鐗╃悊)淇敼閿殑瀹為檯鐘舵併
+weak_mods 鐢ㄤ簬淇濆瓨铏氭嫙鎴栦复鏃朵慨鏀归敭锛屽畠灏嗕笉浼氬奖鍝嶅疄闄呬慨鏀归敭銆
+
+浠ユ寜涓嬪乏渚hift閿劧鍚庤緭鍏CTION_MODS_KEY(LSHIFT, KC_A)涓轰緥锛
+
+鍦╳eak_mods鏃讹紝
+* (1) 鎸変笅涓嶆姮璧峰乏Shift: real_mods |= MOD_BIT(LSHIFT)
+* (2) 鎸 ACTION_MODS_KEY(LSHIFT, KC_A): weak_mods |= MOD_BIT(LSHIFT)
+* (3) 鎶捣 ACTION_MODS_KEY(LSHIFT, KC_A): weak_mods &= ~MOD_BIT(LSHIFT)
+real_mods 杩樻槸淇濇寔鍦ㄤ慨鏀圭姸鎬併
+
+鍦ㄦ病鏈墂eak_mods鏃讹紝
+* (1) 鎸変笅涓嶆姮璧峰乏Shift: real_mods |= MOD_BIT(LSHIFT)
+* (2) 鎸 ACTION_MODS_KEY(LSHIFT, KC_A): real_mods |= MOD_BIT(LSHIFT)
+* (3) 鎶捣 ACTION_MODS_KEY(LSHIFT, KC_A): real_mods &= ~MOD_BIT(LSHIFT)
+姝ゆ椂real_mods澶卞幓鈥樺疄闄呭乏Shift鈥欑殑鐘舵併
+
+weak_mods鍜宺eal_mods鐜板凡鍏ㄩ儴鍔犲叆閿洏鏁版嵁鍖呭彂閫佽豹鍗庡椁愩
+https://github.com/tmk/tmk_core/blob/master/common/action_util.c#L57
diff --git a/docs/zh-cn/getting_started_getting_help.md b/docs/zh-cn/getting_started_getting_help.md
new file mode 100644
index 0000000000..cf770a7708
--- /dev/null
+++ b/docs/zh-cn/getting_started_getting_help.md
@@ -0,0 +1,15 @@
+# 鑾峰緱甯姪
+
+鏈夊緢澶氭柟娉曟潵鑾峰緱鍏充簬QMK鐨勫府鍔.
+
+## 瀹炴椂鑱婂ぉ
+
+浣犲彲浠ュ湪鎴戜滑鐨勪富瑕乕Discord鏈嶅姟鍣╙(https://discord.gg/Uq7gcHh)鎵惧埌QMK鐨勫紑鍙戣呭拰鐢ㄦ埛銆傛湁寰堝璁ㄨ鍥轰欢鐨勪笉鍚岄閬, 宸ュ叿绠(Toolbox), 纭欢,閰嶇疆宸ュ叿(configurator).
+
+## OLKB Subreddit
+
+QMK鐨勫畼鏂硅鍧涙槸[/r/olkb](https://reddit.com/r/olkb) 鍦╗reddit.com](https://reddit.com)涓.
+
+## Github鐨処ssue
+
+浣犲彲浠ュ湪GitHub涓 [鎻愬嚭issue](https://github.com/qmk/qmk_firmware/issues).褰撴偍鐨勯棶棰橀渶瑕侀暱鏈熻璁烘垨璋冭瘯鏃讹紝杩欏挨鍏舵柟渚裤
diff --git a/docs/zh-cn/getting_started_github.md b/docs/zh-cn/getting_started_github.md
new file mode 100644
index 0000000000..0400eea643
--- /dev/null
+++ b/docs/zh-cn/getting_started_github.md
@@ -0,0 +1,59 @@
+# 濡備綍鍦≦MK涓娇鐢℅ithub
+
+Github can be a little tricky to those that aren't familiar with it - this guide will walk through each step of forking, cloning, and submitting a pull request with QMK.
+
+?> 鏈暀绋嬪亣璁炬偍宸插畨瑁匞itHub锛屽苟涓旀偍鍠滄浣跨敤鍛戒护琛屽伐浣溿
+
+棣栧厛 [Github涓婄殑QMK椤甸潰](https://github.com/qmk/qmk_firmware), 鎮ㄨ兘鐪嬪埌鍙充笂鏂规湁涓寜閽啓鐫"Fork":
+
+![浠嶨ithub涓婂垎鍙塢(http://i.imgur.com/8Toomz4.jpg)
+
+濡傛灉浣犳槸鏌愮粍缁囨垚鍛橈紝浣犲皢闇瑕侀夋嫨鍒嗗弶鍒板摢涓处鎴枫備竴鑸儏鍐典笅, 浣犳槸鎯宠鍒嗗弶鍒颁綘鐨勭浜鸿处鎴蜂笅銆傚綋浣犲畬鎴愬垎鍙 (鏈夋椂闇瑕佺瓑涓浼), 鐐瑰嚮"Clone or Download" 鎸夐挳:
+
+!浠嶨ithub涓嬭浇](http://i.imgur.com/N1NYcSz.jpg)
+
+浣犺閫夋嫨 "HTTPS", 鐒跺悗閫夋嫨閾炬帴澶嶅埗:
+
+![HTTPS閾炬帴](http://i.imgur.com/eGO0ohO.jpg)
+
+鐒跺悗锛屽湪鍛戒护琛岃緭鍏git clone `锛岀劧鍚庣矘璐翠綘鐨勯摼鎺:
+
+```
+user@computer:~$ git clone https://github.com/whoeveryouare/qmk_firmware.git
+Cloning into 'qmk_firmware'...
+remote: Counting objects: 46625, done.
+remote: Compressing objects: 100% (2/2), done.
+remote: Total 46625 (delta 0), reused 0 (delta 0), pack-reused 46623
+Receiving objects: 100% (46625/46625), 84.47 MiB | 3.14 MiB/s, done.
+Resolving deltas: 100% (29362/29362), done.
+Checking out files: 100% (2799/2799), done.
+```
+
+鐜板湪浣犳湰鍦拌绠楁満鏈塓MK鐨勫垎鍙変簡,浣犲彲浠ユ坊鍔犱綘鐨勫竷灞浜, 涓轰綘鐨勯敭鐩樼紪璇戝苟鍒锋柊鍥轰欢鍚с傚鏋滀綘瑙夊緱浣犵殑淇敼寰堜笉閿, 浣犲彲浠ユ坊鍔,鎻愪氦,鐒跺悗鎯充綘鐨勫垎鍙夋帹鍑猴紙pull锛変綘鐨勬敼鍙橈紝鍍忚繖鏍:
+
+```
+user@computer:~$ git add .
+user@computer:~$ git commit -m "adding my keymap"
+[master cccb1608] adding my keymap
+ 1 file changed, 1 insertion(+)
+ create mode 100644 keyboards/planck/keymaps/mine/keymap.c
+user@computer:~$ git push
+Counting objects: 1, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (1/1), done.
+Writing objects: 100% (1/1), 1.64 KiB | 0 bytes/s, done.
+Total 1 (delta 1), reused 0 (delta 0)
+remote: Resolving deltas: 100% (1/1), completed with 1 local objects.
+To https://github.com/whoeveryouare/qmk_firmware.git
+ + 20043e64...7da94ac5 master -> master
+```
+
+鐜板湪浣犵殑鏀瑰姩宸茬粡鍦ㄤ綘Github涓婄殑鍒嗘敮涓簡 - 濡傛灉浣犲洖鍒拌繖 (`https://github.com/浣犵殑GitHub璐︽埛鍚/qmk_firmware`) ,浣犲彲浠ョ偣鍑讳笅鏂规墍绀烘寜閽垱寤 "New Pull Request":
+
+![鏂扮殑 Pull Request](http://i.imgur.com/DxMHpJ8.jpg)
+
+鐜板湪浣犲彲浠ョ湅鍒颁綘鎵鍋氱殑涓鍒 - 濡傛灉鐪嬭捣鏉ヤ笉閿, 灏卞彲浠ョ偣鍑 "Create Pull Request"瀹氱ǹ浜:
+
+![鍒涘缓Pull Request](http://i.imgur.com/Ojydlaj.jpg)
+
+鎻愪氦鍚,鎴戜滑浼氬紑璺熶綘璇翠綘鐨勬敼鍔,瑕佹眰鎮ㄨ繘琛屾洿鏀, 骞舵渶缁堟帴鍙楁偍鐨勬洿鏀!鎰熻阿鎮ㄤ负QMK鍋氱殑璐$尞 :)
diff --git a/docs/zh-cn/newbs.md b/docs/zh-cn/newbs.md
new file mode 100644
index 0000000000..8c36b0d24b
--- /dev/null
+++ b/docs/zh-cn/newbs.md
@@ -0,0 +1,23 @@
+# QMK鑿滈笩鏁欑▼
+
+QMK鏄负浣犳満姊扮‖鐩樿璁$殑鐨勪竴涓己澶х殑寮婧愬浐浠躲備娇鐢≦MK鍙互寰堢畝鍗曠殑璁╀綘鐨勫畾鍒堕敭鐩樺彉寰楀己澶с傜湅瀹岃繖绡囨枃绔狅紝鏃犺浣犳槸鑿滈笩杩樻槸澶т浆锛岄兘鍙互椤哄埄鐨勪娇鐢≦MK鏉ュ畾鍒堕敭鐩樸
+
+浣犳槸鍚︿负涓嶇煡閬撲綘鐨勯敭鐩樿兘涓嶈兘杩愯QMK鑰岃嫤鎭? 濡傛灉浣犵殑鏈烘閿洏鏄綘鑷繁鍋氱殑锛岄偅涔堣繖鎶婇敭鐩樹竴鑸彲浠ヨ繍琛孮MK銆傛垜浠彁渚涗簡[涓澶у爢鑷埗閿洏](http://qmk.fm/keyboards/), 鎵浠ュ嵆渚夸綘鐨勯敭鐩樹笉鑳借繍琛孮MK浣犱篃寰堝鏄撹兘鎵惧埌婊¤冻浣犻渶姹傜殑閿洏銆
+
+## 姒傝
+
+杩欎釜鏁欑▼鏈7涓富瑕侀儴鍒嗭細
+
+* [鏂版墜涓婅矾](newbs_getting_started.md)
+* [鐢ㄥ懡浠よ鏋勫缓浣犵殑绗竴涓浐浠禲(newbs_building_firmware.md)
+* [鐢ㄥ湪绾跨晫闈㈡瀯寤轰綘鐨勭涓涓浐浠禲(newbs_building_firmware_configurator.md)
+* [鍒锋柊鍥轰欢](newbs_flashing.md)
+* [娴嬭瘯鍜岃皟璇昡(newbs_testing_debugging.md)
+* [Git鏈浣冲疄璺礭(newbs_best_practices.md)
+* [鍏朵粬瀛︿範璧勬簮](newbs_learn_more_resources.md)
+
+杩欎唤鏁欑▼鏃ㄥ湪甯姪娌℃湁鍥轰欢鏋勫缓缁忛獙鐨勪汉锛屼篃鏄牴鎹鐩殑鍋氬嚭閫夋嫨鍜屽缓璁傝繖浜涚▼搴忔湁寰堝鏇夸唬鏂规硶锛屽ぇ閮ㄥ垎鏇夸唬鎴戜滑閮芥敮鎸併傚鏋滀綘瀵瑰畬鎴愪竴涓换鍔℃湁鐤戦棶锛屽彲浠鍚戞垜浠姹傚府鍔(getting_started_getting_help.md).
+
+## 鍏朵粬璧勬簮
+
+* [Thomas Baart鐨 QMK鍩虹鍗氬](https://thomasbaart.nl/category/mechanical-keyboards/firmware/qmk/qmk-basics/) 鈥 杩欐槸涓涓敤鎴峰垱寤虹殑鍗氬锛屾兜鐩栦簡涓烘柊鎵嬪噯澶囩殑浣跨敤QMK鐨勫熀纭鐭ヨ瘑銆
diff --git a/docs/zh-cn/reference_glossary.md b/docs/zh-cn/reference_glossary.md
new file mode 100644
index 0000000000..7b9adcc2a7
--- /dev/null
+++ b/docs/zh-cn/reference_glossary.md
@@ -0,0 +1,170 @@
+# QMK鏈琛
+
+## ARM
+澶氬鍏徃鐢熶骇鐨32浣嶅崟鐗囨満绯诲垪锛屼緥濡侫tmel, Cypress, Kinetis, NXP, ST, 鍜 TI绛夊叕鍙搞
+
+## AVR
+[Atmel](http://www.microchip.com/)鍏徃鐨勫崟鐗囨満绯诲垪銆 AVR鏄疶MK鐨勫垵濮嬫敮鎸佸钩鍙般
+
+## AZERTY
+Fran莽ais (娉曞浗)鏍囧噯閿洏甯冨眬銆傜敤閿洏鐨勫墠鍏釜瀛楁瘝鍛藉悕銆
+
+## Backlight(鑳屽厜)
+閿洏涓婄収鏄庣殑閫氱О銆傝儗鍏夐氬父鏄竴缁凩ED鐏紝閫氳繃閿附鎴栬呮寜杞村彂鍏夛紝浣嗕篃涓嶆绘槸杩欐牱銆
+
+## Bluetooth(钃濈墮)
+涓绉嶇煭璺濈鐐瑰鐐规棤绾垮崗璁傝澶氬鏃犵嚎閿洏浣跨敤姝ゅ崗璁
+
+## Bootloader(寮曞鍔犺浇绋嬪簭)
+涓绉嶅啓鍒颁綘鍗曠墖鏈虹殑淇濇姢鍖虹殑鐗规畩鐨勭▼搴忥紝璇ョ▼搴忓彲浠ヤ娇鍗曠墖鏈哄崌绾ц嚜宸辩殑鍥轰欢锛岄氬父鏄氳繃USB鏉ュ崌绾с
+
+## Bootmagic(鐑敼閿)
+鍏佽鍚勭閿洏琛屼负鍔ㄦ佸彉鍖栫殑鍔熻兘锛屽浜ゆ崲鎴栫鐢ㄥ父鐢ㄩ敭銆
+
+## C
+涓绉嶉傜敤浜庣郴缁熶唬鐮佺殑浣庣骇缂栫▼璇█銆傚ぇ澶氭暟qmk浠g爜鏄敤C缂栧啓鐨勩
+
+## Colemak
+涓绉嶆祦琛岀殑閿洏甯冨眬銆
+
+## Compile(缂栬瘧)
+鎶婁汉鍙鐨勪唬鐮佽浆鎹㈡垚浣犵殑鍗曠墖鏈哄彲浠ヨ繍琛岀殑鏈哄櫒浠g爜鐨勮繃绋嬨
+
+## Dvorak
+涓涓敱August Dvorak鍗氬+鍦20涓栫邯30骞翠唬鍒涘缓鐨勫竷灞銆侱vorak绠鍖栭敭鐩(Dvorak Simplified Keyboard)鐨勭缉鍐欍
+
+## Dynamic Macro(鍔ㄦ佸畯)
+涓绉嶈褰曞湪閿洏涓婄殑瀹忥紝褰撻敭鐩樻嫈鍑烘垨璁$畻鏈洪噸鏂板惎鍔ㄦ椂锛屽畯灏嗕涪澶便
+
+* [鍔ㄦ佸畯鏂囨。](feature_dynamic_macros.md)
+
+## Eclipse
+鏄竴绉嶅彈C璇█寮鍙戣呰拷鎹х殑闆嗘垚寮鍙戠幆澧(IDE)銆
+
+* [Eclipse瀹夎璇存槑](eclipse.md)
+
+## Firmware(鍥轰欢)
+鐢ㄦ潵鎺у埗鍗曠墖鏈虹殑杞欢銆
+
+## FLIP
+鐖辩壒姊呭皵(Atmel)鎻愪緵鐨凙VR鍣ㄤ欢鍒峰啓杞欢銆傛垜浠竴鑸帹鑽 [QMK鍒峰啓宸ュ叿](https://github.com/qmk/qmk_flasher)锛屼絾鏄浜庝竴浜涢珮绾х敤渚嬶紝闇瑕丗LIP銆
+
+## git
+鍛戒护琛岀増鏈帶鍒惰蒋浠
+
+## GitHub
+璐熻矗澶у鏁癚MK椤圭洰鐨勭綉绔欍傚畠鏄疓it銆侀棶棰樿窡韪拰鍏朵粬甯姪鎴戜滑杩愯qmk鐨勫姛鑳界殑闆嗘垚骞冲彴銆
+
+## ISP(鍦ㄧ郴缁熺紪绋)
+鍦ㄧ郴缁熺紪绋(In-system programming), 浣跨敤澶栭儴纭欢鍜孞TAG绠¤剼瀵笰VR鑺墖杩涜缂栫▼鐨勪竴绉嶆柟娉曘
+
+## hid_listen
+浠庨敭鐩樻帴鏀惰皟璇曟秷鎭殑鎺ュ彛銆 鎮ㄥ彲浠ヤ娇鐢╗QMK Flasher](https://github.com/qmk/qmk_flasher)鎴朳PJRC's hid_listen](https://www.pjrc.com/teensy/hid_listen.html)鏌ョ湅杩欎簺娑堟伅
+
+## Keycode(閿爜)
+琛ㄧず鐗瑰畾閿殑2瀛楄妭鏁版嵁銆俙0x00`-`0xFF`鐢ㄤ簬[鍩烘湰閿爜](keycodes_basic.md)鑰宍0x100`-`0xFFFF`鐢ㄤ簬[閲忓瓙閿爜](quantum_keycodes.md).
+
+## Key Down
+涓涓敭鎸変笅灏氭湭鎶捣鏃惰Е鍙戠殑浜嬩欢銆
+
+## Key Up
+涓涓敭鎶捣鏃惰Е鍙戠殑浜嬩欢銆
+
+## Keymap(閿槧灏)
+鏄犲皠鍒扮墿鐞嗛敭鐩樺竷灞鐨勪竴缁勯敭鐮侊紝鍦ㄦ寜閿拰鎸夐敭閲婃斁鏃惰繘琛屽鐞嗐傛湁鏃剁炕璇戜负甯冨眬锛屾剰涓鸿蒋浠朵笂琛ㄧず鐨勫竷灞锛屽嵆鏄犲皠銆
+
+## Layer(灞)
+涓轰簡璁╀竴涓敭瀹炵幇澶氫釜鍔熻兘鐨勬娊璞$粨鏋勩傛渶楂樻椿鍔ㄥ眰鏈夐檺銆
+
+## Leader Key(鍓嶅閿佽缃彍鍗曢敭)
+鏈姛鑳藉厑璁告偍鐐瑰嚮鍓嶅閿紝鐒跺悗鎸夐『搴忔寜1-3涓敭瀛愭潵婵娲绘寜閿垨鍏朵粬閲忓瓙鍔熻兘銆
+
+* [鍓嶅閿枃妗(feature_leader_key.md)
+
+## LED
+鍙戝厜浜屾瀬绠★紝閿洏涓婃渶甯哥敤鐨勬寚绀虹伅瑁呯疆銆
+
+## Make
+鐢ㄤ簬缂栬瘧鎵鏈夋簮鏂囦欢鐨勮蒋浠跺寘銆傚彲浠ヤ娇鐢╜make`鍛戒护鍜屽叾浠栧弬鏁版潵缂栬瘧浣犵殑鍥轰欢銆
+
+## Matrix(鐭╅樀)
+涓绉嶇敱鍒楀拰琛岀粍鎴愮殑鎺ョ嚎妯″紡锛屼娇鍗曠墖鏈鸿兘澶熺敤杈冨皯鐨勫紩鑴氭娴嬫寜閿傜煩闃甸氬父鍖呭惈浜屾瀬绠★紝浠ヨ揪鍒板叏閿棤鍐层
+
+## Macro(瀹)
+鏈姛鑳藉彲浠ュ湪鏁插嚮鍗曚釜閿悗鍙戦佸涓寜閿簨浠(hid鎶ュ憡)銆
+
+* [瀹忔枃妗(feature_macros.md)
+
+## MCU(鍗曠墖鏈恒佸井鎺у埗鍗曞厓)
+寰帶鍒跺崟鍏冿紝閿洏鐨勫鐞嗗櫒銆
+
+## Modifier(淇敼閿佷慨楗伴敭銆佸姛鑳介敭)
+鎸変綇璇ラ敭灏嗕細鏀瑰彉鍏朵粬閿殑鍔熻兘锛屼慨楗伴敭鍖呮嫭 Ctrl, Alt, 鍜 Shift銆
+
+## Mousekeys(榧犳爣閿)
+鏈姛鑳藉湪鎮ㄦ暡鍑婚敭鐩樻椂浼氭帶鍒堕紶鏍囧厜鏍囥
+
+* [榧犳爣閿枃妗(feature_mouse_keys.md)
+
+## N-Key Rollover (NKRO銆佸叏閿棤鍐)
+涓绉嶆湳璇紝閫傜敤浜庤兘澶熷悓鏃舵姤鍛婁换鎰忔暟閲忔寜閿殑閿洏銆
+
+## Oneshot Modifier(绮樻粸閿)
+涓绉嶈兘璁╀綘鐨勫姛鑳介敭涓鐩翠繚鎸佹寜涓嬶紝鐩村埌浣犳寜涓嬪叾浠栭敭鐨勫姛鑳姐傚畠鍙仛绮樻粸閿垨鍙仛绮樿繛閿紝璇ュ姛鑳界敱杞欢瀹炵幇鑰岄潪鏈烘缁撴瀯銆
+
+## ProMicro
+涓绉嶄綆鎴愭湰AVR寮鍙戞澘銆傝繖绉嶆澘瀛愬緢瀹规槗鍦ㄨ喘鐗╃綉绔欐壘鍒(浠锋牸涓嶅埌20RMB)锛屼絾鏄嵁璇村埛鍐檖ro micro鏈夌偣浠や汉鎶撶媯銆
+
+## Pull Request(鎷夎姹傘丳R)
+鍚慟MK璇锋眰鎻愪氦浠g爜銆傛垜浠紦鍔辨墍鏈夌敤鎴锋彁浜や綘浠嚜宸辩殑閿洏鐨勪唬鐮併
+
+## QWERTY
+鏍囧噯鑻辨枃閿洏锛岄氬父涔熺敤浜庡叾浠栬瑷锛屼緥濡備腑鏂囥傛槸鐢ㄩ敭鐩樺墠6涓瓧姣嶅懡鍚嶇殑銆
+
+## QWERTZ
+鏍囧噯Deutsche(寰疯)閿洏甯冨眬銆備娇鐢ㄥ墠6涓瓧姣嶆槑鍚嶃
+
+## Rollover(鍏佽缈昏浆銆佹棤鍐插舰寮)
+璇ユ湳璇〃绀哄湪涓涓敭宸叉寜涓嬫椂鎸変笅鍙︿竴涓敭銆傚舰寮忓寘鎷2KRO(鍙岄敭鏃犲啿),6KRO(6閿棤鍐),鍜孨KRO(鍏ㄩ敭鏃犲啿)锛屾棤鍐茶〃绀哄彲鍚屾椂鎸変笅鑰屼笉浜х敓鍐茬獊鐨勯敭鐨勬暟閲忋
+
+## Scancode(鎵弿鐮)
+HID鎶ュ憡涓殑涓涓1瀛楄妭鐨勬暟瀛楋紝琛ㄧず涓涓敭瀛愩傝繖浜涙暟瀛楀湪涓嬪垪鏂囨。涓璠HID Usage Tables](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf)璇ユ枃妗e彂甯冧簬[USB-IF](http://www.usb.org/)銆
+
+## Space Cadet閿洏鐨剆hift閿
+涓绉嶇壒浣跨殑shift璁剧疆锛岃兘璁╀綘閫氳繃鏁插嚮宸︽垨鍙硈hift涓娆℃垨澶氭閿叆涓嶅悓鐨勬嫭鍙枫
+
+* [Space Cadet閿洏鏂囨。](feature_space_cadet.md)
+
+## Tap(鏁插嚮銆佸崟鍑)
+鎸変笅骞堕噴鏀句竴涓敭銆傚湪鏌愪簺鎯呭喌涓嬫偍闇瑕佸尯鍒嗛敭鎸変笅鍜岄敭鎶捣锛屼絾鏄崟鍑绘妸涓や釜浜嬩欢閮藉寘鎷簡銆
+
+## Tap Dance(澶氬嚮閿)
+鏈姛鑳藉厑璁稿悜鍚屼竴涓敭瀛愬垎閰嶅涓敭鐮侊紝骞舵牴鎹寜閿鏁板尯鍒嗐
+
+* [澶氬嚮閿枃妗(feature_tap_dance.md)
+
+## Teensy
+涓绉嶄綆鎴愭湰AVR寮鍙戞澘<!--璇戣呭悙妲斤細鎴戞庝箞鎰熻鎴愭湰涓嶄綆銆傚ソ鍚э紝鎴戠┓銆 -->锛岄氬父鐢ㄤ簬鎵嬪伐杩炵嚎閿洏銆傝繖涓猼eensy鏄湁鐐瑰皬璐典絾鏄痟alfkay bootloader浼氳瀹冨埛鍐欏崄鍒嗙畝鍗曪紝鎵浠ヤ篃寰堝父鐢ㄣ
+
+## Underlight(鑳屽厜)
+鐢ㄤ簬鐓т寒鐢佃矾鏉垮簳闈㈢殑LED鐨勬荤О銆傝繖浜汱ED閫氬父浠庡嵃鍒风數璺澘鐨勫簳閮ㄥ悜閿洏鎵鍦ㄧ殑琛ㄩ潰鍙戝厜銆
+
+## Unicode
+鍦ㄨ緝澶х殑璁$畻鏈轰笘鐣屼腑锛孶nicode鏄竴缁勭紪鐮佹柟妗堬紝鐢ㄤ簬琛ㄧず浠讳綍璇█涓殑瀛楃銆 涓巕mk鐩稿叧鐨勬槸锛屽畠鎰忓懗鐫浣跨敤鍚勭鎿嶄綔绯荤粺鏂规鏉ュ彂閫乁nicode浠g爜鐐癸紝鑰屼笉鏄壂鎻忕爜銆
+
+* [Unicode鏂囨。](feature_unicode.md)
+
+## Unit Testing(鍗曞厓娴嬭瘯)
+閽堝qmk鐨勮嚜鍔ㄨ繍琛屾祴璇曟鏋躲傚崟鍏冩祴璇曞府鍔╂垜浠‘淇℃垜浠殑鏇存敼涓嶄細鐮村潖浠讳綍涓滆タ銆
+
+* [鍗曞厓娴嬭瘯鏂囨。](unit_testing.md)
+
+## USB
+閫氱敤涓茶鎬荤嚎锛岄敭鐩樻渶甯歌鐨勬湁绾挎帴鍙c
+
+## USB 涓绘満 (鎴栫畝鏄撲富鏈)
+USB璇告毃甯備綘鐨勭數鑴戯紝鎴栬呬綘鐨勯敭鐩樻墍鎻掔殑浠讳綍璁惧銆
+
+# 骞舵病鏈夋壘鍒颁綘鎯虫壘鍒扮殑鏈?
+
+[寤虹珛涓涓猧ssue](https://github.com/qmk/qmk_firmware/issues) 锛屾兂濂戒綘鐨勯棶棰橈紝鎴栬浣犳墍闂殑鏈灏变細娣诲姞鍒拌繖閲屻傚垱寤轰竴涓狿R甯垜浠坊鍔犻渶瑕佹坊鍔犵殑鏈褰撶劧鍧犲惣浜:)