summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_summary.md1
-rw-r--r--docs/breaking_changes.md4
-rw-r--r--docs/chibios_upgrade_instructions.md56
-rw-r--r--docs/cli_commands.md2
-rw-r--r--docs/compatible_microcontrollers.md2
-rw-r--r--docs/config_options.md29
-rw-r--r--docs/custom_quantum_functions.md8
-rw-r--r--docs/eeprom_driver.md3
-rw-r--r--docs/feature_debounce_type.md4
-rw-r--r--docs/feature_dip_switch.md16
-rw-r--r--docs/feature_haptic_feedback.md26
-rw-r--r--docs/feature_oled_driver.md4
-rw-r--r--docs/feature_rgb_matrix.md116
-rw-r--r--docs/feature_rgblight.md47
-rw-r--r--docs/feature_split_keyboard.md122
-rw-r--r--docs/feature_st7565.md274
-rw-r--r--docs/ja/compatible_microcontrollers.md2
-rw-r--r--docs/ja/feature_dip_switch.md16
-rw-r--r--docs/serial_driver.md15
19 files changed, 665 insertions, 82 deletions
diff --git a/docs/_summary.md b/docs/_summary.md
index 9798ef5127..4141e01e77 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -93,6 +93,7 @@
* Hardware Features
* Displays
* [HD44780 LCD Controller](feature_hd44780.md)
+ * [ST7565 LCD Driver](feature_st7565.md)
* [OLED Driver](feature_oled_driver.md)
* Lighting
* [Backlight](feature_backlight.md)
diff --git a/docs/breaking_changes.md b/docs/breaking_changes.md
index b0d56a81bd..a1a56bd457 100644
--- a/docs/breaking_changes.md
+++ b/docs/breaking_changes.md
@@ -100,3 +100,7 @@ This happens immediately after the previous `develop` branch is merged.
* [ ] `git pull --ff-only`
* [ ] `git merge --no-ff develop`
* [ ] `git push upstream master`
+
+## Post-merge operations
+
+* (Optional) [update ChibiOS + ChibiOS-Contrib on `develop`](chibios_upgrade_instructions.md)
diff --git a/docs/chibios_upgrade_instructions.md b/docs/chibios_upgrade_instructions.md
new file mode 100644
index 0000000000..40c2faafcf
--- /dev/null
+++ b/docs/chibios_upgrade_instructions.md
@@ -0,0 +1,56 @@
+# ChibiOS Upgrade Procedure
+
+ChibiOS and ChibiOS-Contrib need to be updated in tandem -- the latter has a branch tied to the ChibiOS version in use and should not be mixed with different versions.
+
+## Getting ChibiOS
+
+* `svn` Initialisation:
+ * Only needed to be done once
+ * You might need to separately install `git-svn` package in your OS's package manager
+ * `git svn init --stdlayout --prefix='svn/' http://svn.osdn.net/svnroot/chibios/`
+ * `git remote add qmk git@github.com:qmk/ChibiOS.git`
+* Updating:
+ * `git svn fetch`
+ * First time around this will take several hours
+ * Subsequent updates will be incremental only
+* Tagging example (work out which version first!):
+ * `git tag -a ver20.3.3 -m ver20.3.3 svn/tags/ver20.3.3`
+ * `git push qmk ver20.3.3`
+ * `git tag -a breaking_YYYY_qN -m breaking_YYYY_qN svn/tags/ver20.3.3`
+ * `git push qmk breaking_YYYY_qN`
+
+## Getting ChibiOS-Contrib
+
+* `git` Initialisation:
+ * `git clone git@github.com:qmk/ChibiOS-Contrib`
+ * `git remote add upstream https://github.com/ChibiOS/ChibiOS-Contrib`
+ * `git checkout -b chibios-20.3.x upstream/chibios-20.3.x`
+* Updating:
+ * `git fetch --all --tags --prune`
+ * `git checkout chibios-20.3.x`
+ * `git pull --ff-only`
+ * `git push origin chibios-20.3.x`
+ * `git tag -a breaking_YYYY_qN -m breaking_YYYY_qN chibios-20.3.x`
+ * `git push origin breaking_YYYY_qN`
+
+## Updating submodules
+
+* Update the submodules
+ * `cd $QMK_FIRMWARE`
+ * `git checkout develop`
+ * `git pull --ff-only`
+ * `git checkout -b chibios-version-bump`
+ * `cd lib/chibios`
+ * `git fetch --all --tags --prune`
+ * `git checkout breaking_YYYY_qN`
+ * `cd ../chibios-contrib`
+ * `git fetch --all --tags --prune`
+ * `git checkout breaking_YYYY_qN`
+* Build everything
+ * `cd $QMK_FIRMWARE`
+ * `qmk multibuild -j4`
+ * Make sure there are no errors
+* Push to the repo
+ * `git commit -am 'Update ChibiOS to XXXXXXXXX'`
+ * `git push --set-upstream origin chibios-version-bump`
+* Make a PR to qmk_firmware with the new branch \ No newline at end of file
diff --git a/docs/cli_commands.md b/docs/cli_commands.md
index 581342093a..e30593daa9 100644
--- a/docs/cli_commands.md
+++ b/docs/cli_commands.md
@@ -368,7 +368,7 @@ qmk generate-docs
## `qmk generate-rgb-breathe-table`
-This command generates a lookup table (LUT) header file for the [RGB Lighting](feature_rgblight.md) feature's breathing animation. Place this file in your keyboard or keymap directory as `rgblight_breathe_table.h` to override the default LUT in `quantum/`.
+This command generates a lookup table (LUT) header file for the [RGB Lighting](feature_rgblight.md) feature's breathing animation. Place this file in your keyboard or keymap directory as `rgblight_breathe_table.h` to override the default LUT in `quantum/rgblight/`.
**Usage**:
diff --git a/docs/compatible_microcontrollers.md b/docs/compatible_microcontrollers.md
index 0f5b140de0..865b29feec 100644
--- a/docs/compatible_microcontrollers.md
+++ b/docs/compatible_microcontrollers.md
@@ -31,6 +31,8 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
* [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.html)
+ * [STM32L412](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
+ * [STM32L422](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L433](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x3.html)
* [STM32L443](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x3.html)
diff --git a/docs/config_options.md b/docs/config_options.md
index d0f0b316e0..980195ac68 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -51,8 +51,10 @@ This is a C header file that is one of the first things included, and will persi
* the number of columns in your keyboard's matrix
* `#define MATRIX_ROW_PINS { D0, D5, B5, B6 }`
* pins of the rows, from top to bottom
+ * may be omitted by the keyboard designer if matrix reads are handled in an alternate manner. See [low-level matrix overrides](custom_quantum_functions.md?id=low-level-matrix-overrides) for more information.
* `#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }`
* pins of the columns, from left to right
+ * may be omitted by the keyboard designer if matrix reads are handled in an alternate manner. See [low-level matrix overrides](custom_quantum_functions.md?id=low-level-matrix-overrides) for more information.
* `#define MATRIX_IO_DELAY 30`
* the delay in microseconds when between changing matrix pin state and reading values
* `#define UNUSED_PINS { D1, D2, D3, B1, B2, B3 }`
@@ -272,7 +274,7 @@ There are a few different ways to set handedness for split keyboards (listed in
### Other Options
* `#define USE_I2C`
- * For using I2C instead of Serial (defaults to serial)
+ * For using I2C instead of Serial (default is serial; serial transport is supported on ARM -- I2C is AVR-only)
* `#define SOFT_SERIAL_PIN D0`
* When using serial, define this. `D0` or `D1`,`D2`,`D3`,`E6`.
@@ -280,6 +282,7 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define MATRIX_ROW_PINS_RIGHT { <row pins> }`
* `#define MATRIX_COL_PINS_RIGHT { <col pins> }`
* If you want to specify a different pinout for the right half than the left half, you can define `MATRIX_ROW_PINS_RIGHT`/`MATRIX_COL_PINS_RIGHT`. Currently, the size of `MATRIX_ROW_PINS` must be the same as `MATRIX_ROW_PINS_RIGHT` and likewise for the definition of columns.
+ * may be omitted by the keyboard designer if matrix reads are handled in an alternate manner. See [low-level matrix overrides](custom_quantum_functions.md?id=low-level-matrix-overrides) for more information.
* `#define DIRECT_PINS_RIGHT { { F1, F0, B0, C7 }, { F4, F5, F6, F7 } }`
* If you want to specify a different direct pinout for the right half than the left half, you can define `DIRECT_PINS_RIGHT`. Currently, the size of `DIRECT_PINS` must be the same as `DIRECT_PINS_RIGHT`.
@@ -300,7 +303,7 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define SPLIT_USB_DETECT`
* Detect (with timeout) USB connection when delegating master/slave
* Default behavior for ARM
- * Required for AVR Teensy
+ * Required for AVR Teensy (without hardware mods)
* `#define SPLIT_USB_TIMEOUT 2000`
* Maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT`
@@ -308,6 +311,28 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define SPLIT_USB_TIMEOUT_POLL 10`
* Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
+* `#define FORCED_SYNC_THROTTLE_MS 100`
+ * Deadline for synchronizing data from master to slave when using the QMK-provided split transport.
+
+* `#define SPLIT_TRANSPORT_MIRROR`
+ * Mirrors the master-side matrix on the slave when using the QMK-provided split transport.
+
+* `#define SPLIT_LAYER_STATE_ENABLE`
+ * Ensures the current layer state is available on the slave when using the QMK-provided split transport.
+
+* `#define SPLIT_LED_STATE_ENABLE`
+ * Ensures the current host indicator state (caps/num/scroll) is available on the slave when using the QMK-provided split transport.
+
+* `#define SPLIT_MODS_ENABLE`
+ * Ensures the current modifier state (normal, weak, and oneshot) is available on the slave when using the QMK-provided split transport.
+
+* `#define SPLIT_WPM_ENABLE`
+ * Ensures the current WPM is available on the slave when using the QMK-provided split transport.
+
+* `#define SPLIT_TRANSACTION_IDS_KB .....`
+* `#define SPLIT_TRANSACTION_IDS_USER .....`
+ * Allows for custom data sync with the slave when using the QMK-provided split transport. See [custom data sync between sides](feature_split_keyboard.md#custom-data-sync) for more information.
+
# The `rules.mk` File
This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 694b421e79..30c637bb49 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -144,6 +144,14 @@ This is useful for setting up stuff that you may need elsewhere, but isn't hardw
* Keyboard/Revision: `void matrix_init_kb(void)`
* Keymap: `void matrix_init_user(void)`
+### Low-level Matrix Overrides Function Documentation :id=low-level-matrix-overrides
+
+* GPIO pin initialisation: `void matrix_init_pins(void)`
+ * This needs to perform the low-level initialisation of all row and column pins. By default this will initialise the input/output state of each of the GPIO pins listed in `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`, based on whether or not the keyboard is set up for `ROW2COL`, `COL2ROW`, or `DIRECT_PINS`. Should the keyboard designer override this function, no initialisation of pin state will occur within QMK itself, instead deferring to the keyboard's override.
+* `COL2ROW`-based row reads: `void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)`
+* `ROW2COL`-based column reads: `void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)`
+* `DIRECT_PINS`-based reads: `void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)`
+ * These three functions need to perform the low-level retrieval of matrix state of relevant input pins, based on the matrix type. Only one of the functions should be implemented, if needed. By default this will iterate through `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`, configuring the inputs and outputs based on whether or not the keyboard is set up for `ROW2COL`, `COL2ROW`, or `DIRECT_PINS`. Should the keyboard designer override this function, no manipulation of matrix GPIO pin state will occur within QMK itself, instead deferring to the keyboard's override.
## Keyboard Post Initialization code
diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md
index e2c262546d..6dcf10c04d 100644
--- a/docs/eeprom_driver.md
+++ b/docs/eeprom_driver.md
@@ -31,6 +31,9 @@ Currently QMK supports 24xx-series chips over I2C. As such, requires a working i
`#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32
`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2
`#define EXTERNAL_EEPROM_WRITE_TIME` | Write cycle time of the EEPROM, as specified in the datasheet | 5
+`#define EXTERNAL_EEPROM_WP_PIN` | If defined the WP pin will be toggled appropriately when writing to the EEPROM. | _none_
+
+Some I2C EEPROM manufacturers explicitly recommend against hardcoding the WP pin to ground. This is in order to protect the eeprom memory content during power-up/power-down/brown-out conditions at low voltage where the eeprom is still operational, but the i2c master output might be unpredictable. If a WP pin is configured, then having an external pull-up on the WP pin is recommended.
Default values and extended descriptions can be found in `drivers/eeprom/eeprom_i2c.h`.
diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md
index 3ad74224c1..306185fe83 100644
--- a/docs/feature_debounce_type.md
+++ b/docs/feature_debounce_type.md
@@ -121,16 +121,16 @@ DEBOUNCE_TYPE = <name of algorithm>
Where name of algorithm is one of:
* ```sym_defer_g``` - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occurred, all input changes are pushed.
* This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant.
-* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
+* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
+* ```asym_eager_defer_pk``` - debouncing per key. On a key-down state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key-up status change is pushed.
### A couple algorithms that could be implemented in the future:
* ```sym_defer_pr```
* ```sym_eager_g```
-* ```asym_eager_defer_pk```
### Use your own debouncing code
You have the option to implement you own debouncing algorithm. To do this:
diff --git a/docs/feature_dip_switch.md b/docs/feature_dip_switch.md
index 15e449c4c4..5e8c19bfa7 100644
--- a/docs/feature_dip_switch.md
+++ b/docs/feature_dip_switch.md
@@ -23,8 +23,9 @@ or
The callback functions can be inserted into your `<keyboard>.c`:
```c
-void dip_switch_update_kb(uint8_t index, bool active) {
- dip_switch_update_user(index, active);
+bool dip_switch_update_kb(uint8_t index, bool active) {
+ if !(dip_switch_update_user(index, active)) { return false; }
+ return true;
}
```
@@ -32,7 +33,7 @@ void dip_switch_update_kb(uint8_t index, bool active) {
or `keymap.c`:
```c
-void dip_switch_update_user(uint8_t index, bool active) {
+bool dip_switch_update_user(uint8_t index, bool active) {
switch (index) {
case 0:
if(active) { audio_on(); } else { audio_off(); }
@@ -57,6 +58,7 @@ void dip_switch_update_user(uint8_t index, bool active) {
}
break;
}
+ return true;
}
```
@@ -64,8 +66,9 @@ Additionally, we support bit mask functions which allow for more complex handlin
```c
-void dip_switch_update_mask_kb(uint32_t state) {
- dip_switch_update_mask_user(state);
+bool dip_switch_update_mask_kb(uint32_t state) {
+ if (!dip_switch_update_mask_user(state)) { return false; }
+ return true;
}
```
@@ -73,7 +76,7 @@ void dip_switch_update_mask_kb(uint32_t state) {
or `keymap.c`:
```c
-void dip_switch_update_mask_user(uint32_t state) {
+bool dip_switch_update_mask_user(uint32_t state) {
if (state & (1UL<<0) && state & (1UL<<1)) {
layer_on(_ADJUST); // C on esc
} else {
@@ -89,6 +92,7 @@ void dip_switch_update_mask_user(uint32_t state) {
} else {
layer_off(_TEST_B);
}
+ return true;
}
```
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
index a092e784c7..469c9c7981 100644
--- a/docs/feature_haptic_feedback.md
+++ b/docs/feature_haptic_feedback.md
@@ -162,4 +162,28 @@ This will set what sequence HPT_RST will set as the active mode. If not defined,
### DRV2605L Continuous Haptic Mode
-This mode sets continuous haptic feedback with the option to increase or decrease strength.
+This mode sets continuous haptic feedback with the option to increase or decrease strength.
+
+## Haptic Key Exclusion
+The Haptic Exclusion is implemented as `__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record)` in haptic.c. This allows a re-definition at the required level with the specific requirement / exclusion.
+
+### NO_HAPTIC_MOD
+With the entry of `#define NO_HAPTIC_MOD` in config.h, modifiers from Left Control to Right GUI will not trigger a feedback. This also includes modifiers in a Mod Tap configuration.
+
+### NO_HAPTIC_FN
+With the entry of `#define NO_HAPTIC_FN` in config.h, layer keys will not rigger a feedback.
+
+### NO_HAPTIC_ALPHA
+With the entry of `#define NO_HAPTIC_ALPHA` in config.h, none of the alpha keys (A ... Z) will trigger a feedback.
+
+### NO_HAPTIC_PUNCTUATION
+With the entry of `#define NO_HAPTIC_PUNCTUATION` in config.h, none of the following keys will trigger a feedback: Enter, ESC, Backspace, Space, Minus, Equal, Left Bracket, Right Bracket, Backslash, Non-US Hash, Semicolon, Quote, Grave, Comma, Slash, Dot, Non-US Backslash.
+
+### NO_HAPTIC_LOCKKEYS
+With the entry of `#define NO_HAPTIC_LOCKKEYS` in config.h, none of the following keys will trigger a feedback: Caps Lock, Scroll Lock, Num Lock.
+
+### NO_HAPTIC_NAV
+With the entry of `#define NO_HAPTIC_NAV` in config.h, none of the following keys will trigger a feedback: Print Screen, Pause, Insert, Delete, Page Down, Page Up, Left Arrow, Up Arrow, Right Arrow, Down Arrow, End, Home.
+
+### NO_HAPTIC_NUMERIC
+With the entry of `#define NO_HAPTIC_NUMERIC` in config.h, none of the following keys between 0 and 9 (KC_1 ... KC_0) will trigger a feedback. \ No newline at end of file
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index f3b659b1bc..c90aabb9c6 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -346,6 +346,10 @@ bool oled_scroll_left(void);
// Returns true if the screen was not scrolling or stops scrolling
bool oled_scroll_off(void);
+// Inverts the display
+// Returns true if the screen was or is inverted
+bool oled_invert(bool invert);
+
// Returns the maximum number of characters that will fit on a line
uint8_t oled_max_chars(void);
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index 08d5c9c4c6..be763ee025 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -171,7 +171,7 @@ Currently only a single drivers is supported, but it would be trivial to support
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -228,6 +228,75 @@ Configure the hardware via your `config.h`:
```
---
+### AW20216 :id=aw20216
+There is basic support for addressable RGB matrix lighting with the SPI AW20216 RGB controller. To enable it, add this to your `rules.mk`:
+
+```makefile
+RGB_MATRIX_ENABLE = yes
+RGB_MATRIX_DRIVER = AW20216
+```
+
+You can use up to 2 AW20216 IC's. Do not specify `DRIVER_<N>_xxx` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `DRIVER_1_CS` | (Required) MCU pin connected to first RGB driver chip select line | B13 |
+| `DRIVER_2_CS` | (Optional) MCU pin connected to second RGB driver chip select line | |
+| `DRIVER_1_EN` | (Required) MCU pin connected to first RGB driver hardware enable line | C13 |
+| `DRIVER_2_EN` | (Optional) MCU pin connected to second RGB driver hardware enable line | |
+| `DRIVER_1_LED_TOTAL` | (Required) How many RGB lights are connected to first RGB driver | |
+| `DRIVER_2_LED_TOTAL` | (Optional) How many RGB lights are connected to second RGB driver | |
+| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
+| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
+| `AW_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
+| `AW_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
+| `AW_SPI_DIVISOR` | (Optional) Clock divisor for SPI communication (powers of 2, smaller numbers means faster communication, should not be less than 4) | 4 |
+
+Here is an example using 2 drivers.
+
+```c
+#define DRIVER_1_CS B13
+#define DRIVER_2_CS B14
+// Hardware enable lines may be connected to the same pin
+#define DRIVER_1_EN C13
+#define DRIVER_2_EN C13
+
+#define DRIVER_COUNT 2
+#define DRIVER_1_LED_TOTAL 66
+#define DRIVER_2_LED_TOTAL 32
+#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`.
+
+Define these arrays listing all the LEDs in your `<keyboard>.c`:
+
+```c
+const aw_led g_aw_leds[DRIVER_LED_TOTAL] = {
+/* Each AW20216 channel is controlled by a register at some offset between 0x00
+ * and 0xD7 inclusive.
+ * See drivers/awinic/aw20216.h for the mapping between register offsets and
+ * driver pin locations.
+ * driver
+ * | R location
+ * | | G location
+ * | | | B location
+ * | | | | */
+ { 0, CS1_SW1, CS2_SW1, CS3_SW1 },
+ { 0, CS4_SW1, CS5_SW1, CS6_SW1 },
+ { 0, CS7_SW1, CS8_SW1, CS9_SW1 },
+ { 0, CS10_SW1, CS11_SW1, CS12_SW1 },
+ { 0, CS13_SW1, CS14_SW1, CS15_SW1 },
+ ...
+ { 1, CS1_SW1, CS2_SW1, CS3_SW1 },
+ { 1, CS13_SW1, CS14_SW1, CS15_SW1 },
+ { 1, CS16_SW1, CS17_SW1, CS18_SW1 },
+ { 1, CS4_SW2, CS5_SW2, CS6_SW2 },
+ ...
+};
+```
+
+---
## Common Configuration :id=common-configuration
@@ -485,28 +554,29 @@ For inspiration and examples, check out the built-in effects under `quantum/rgb_
These are shorthands to popular colors. The `RGB` ones can be passed to the `setrgb` functions, while the `HSV` ones to the `sethsv` functions.
-|RGB |HSV |
-|-------------------|-------------------|
-|`RGB_WHITE` |`HSV_WHITE` |
-|`RGB_RED` |`HSV_RED` |
-|`RGB_CORAL` |`HSV_CORAL` |
-|`RGB_ORANGE` |`HSV_ORANGE` |
-|`RGB_GOLDENROD` |`HSV_GOLDENROD` |
-|`RGB_GOLD` |`HSV_GOLD` |
-|`RGB_YELLOW` |`HSV_YELLOW` |
-|`RGB_CHARTREUSE` |`HSV_CHARTREUSE` |
-|`RGB_GREEN` |`HSV_GREEN` |
-|`RGB_SPRINGGREEN` |`HSV_SPRINGGREEN` |
-|`RGB_TURQUOISE` |`HSV_TURQUOISE` |
-|`RGB_TEAL` |`HSV_TEAL` |
-|`RGB_CYAN` |`HSV_CYAN` |
-|`RGB_AZURE` |`HSV_AZURE` |
-|`RGB_BLUE` |`HSV_BLUE` |
-|`RGB_PURPLE` |`HSV_PURPLE` |
-|`RGB_MAGENTA` |`HSV_MAGENTA` |
-|`RGB_PINK` |`HSV_PINK` |
-
-These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight_list.h). Feel free to add to this list!
+|RGB |HSV |
+|---------------------|---------------------|
+|`RGB_AZURE` |`HSV_AZURE` |
+|`RGB_BLACK`/`RGB_OFF`|`HSV_BLACK`/`HSV_OFF`|
+|`RGB_BLUE` |`HSV_BLUE` |
+|`RGB_CHARTREUSE` |`HSV_CHARTREUSE` |
+|`RGB_CORAL` |`HSV_CORAL` |
+|`RGB_CYAN` |`HSV_CYAN` |
+|`RGB_GOLD` |`HSV_GOLD` |
+|`RGB_GOLDENROD` |`HSV_GOLDENROD` |
+|`RGB_GREEN` |`HSV_GREEN` |
+|`RGB_MAGENTA` |`HSV_MAGENTA` |
+|`RGB_ORANGE` |`HSV_ORANGE` |
+|`RGB_PINK` |`HSV_PINK` |
+|`RGB_PURPLE` |`HSV_PURPLE` |
+|`RGB_RED` |`HSV_RED` |
+|`RGB_SPRINGGREEN` |`HSV_SPRINGGREEN` |
+|`RGB_TEAL` |`HSV_TEAL` |
+|`RGB_TURQUOISE` |`HSV_TURQUOISE` |
+|`RGB_WHITE` |`HSV_WHITE` |
+|`RGB_YELLOW` |`HSV_YELLOW` |
+
+These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/color.h). Feel free to add to this list!
## Additional `config.h` Options :id=additional-configh-options
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md
index 994a014a28..d323dee4f7 100644
--- a/docs/feature_rgblight.md
+++ b/docs/feature_rgblight.md
@@ -119,7 +119,7 @@ if `RGBLIGHT_EFFECT_xxxx` or `RGBLIGHT_ANIMATIONS` is defined, you also have a n
Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration.
-Note: For versions older than 0.6.117, The mode numbers were written directly. In `quantum/rgblight.h` there is a contrast table between the old mode number and the current symbol.
+Note: For versions older than 0.6.117, The mode numbers were written directly. In `quantum/rgblight/rgblight.h` there is a contrast table between the old mode number and the current symbol.
### Effect and Animation Toggles
@@ -328,7 +328,7 @@ Normally lighting layers are not shown when RGB Lighting is disabled (e.g. with
## Functions
-If you need to change your RGB lighting in code, for example in a macro to change the color whenever you switch layers, QMK provides a set of functions to assist you. See [`rgblight.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight.h) for the full list, but the most commonly used functions include:
+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/rgblight.h) for the full list, but the most commonly used functions include:
### Utility Functions
|Function |Description |
@@ -449,26 +449,27 @@ rgblight_sethsv_at(HSV_GREEN, 2); // led 2
These are shorthands to popular colors. The `RGB` ones can be passed to the `setrgb` functions, while the `HSV` ones to the `sethsv` functions.
-|RGB |HSV |
-|-------------------|-------------------|
-|`RGB_WHITE` |`HSV_WHITE` |
-|`RGB_RED` |`HSV_RED` |
-|`RGB_CORAL` |`HSV_CORAL` |
-|`RGB_ORANGE` |`HSV_ORANGE` |
-|`RGB_GOLDENROD` |`HSV_GOLDENROD` |
-|`RGB_GOLD` |`HSV_GOLD` |
-|`RGB_YELLOW` |`HSV_YELLOW` |
-|`RGB_CHARTREUSE` |`HSV_CHARTREUSE` |
-|`RGB_GREEN` |`HSV_GREEN` |
-|`RGB_SPRINGGREEN` |`HSV_SPRINGGREEN` |
-|`RGB_TURQUOISE` |`HSV_TURQUOISE` |
-|`RGB_TEAL` |`HSV_TEAL` |
-|`RGB_CYAN` |`HSV_CYAN` |
-|`RGB_AZURE` |`HSV_AZURE` |
-|`RGB_BLUE` |`HSV_BLUE` |
-|`RGB_PURPLE` |`HSV_PURPLE` |
-|`RGB_MAGENTA` |`HSV_MAGENTA` |
-|`RGB_PINK` |`HSV_PINK` |
+|RGB |HSV |
+|---------------------|---------------------|
+|`RGB_AZURE` |`HSV_AZURE` |
+|`RGB_BLACK`/`RGB_OFF`|`HSV_BLACK`/`HSV_OFF`|
+|`RGB_BLUE` |`HSV_BLUE` |
+|`RGB_CHARTREUSE` |`HSV_CHARTREUSE` |
+|`RGB_CORAL` |`HSV_CORAL` |
+|`RGB_CYAN` |`HSV_CYAN` |
+|`RGB_GOLD` |`HSV_GOLD` |
+|`RGB_GOLDENROD` |`HSV_GOLDENROD` |
+|`RGB_GREEN` |`HSV_GREEN` |
+|`RGB_MAGENTA` |`HSV_MAGENTA` |
+|`RGB_ORANGE` |`HSV_ORANGE` |
+|`RGB_PINK` |`HSV_PINK` |
+|`RGB_PURPLE` |`HSV_PURPLE` |
+|`RGB_RED` |`HSV_RED` |
+|`RGB_SPRINGGREEN` |`HSV_SPRINGGREEN` |
+|`RGB_TEAL` |`HSV_TEAL` |
+|`RGB_TURQUOISE` |`HSV_TURQUOISE` |
+|`RGB_WHITE` |`HSV_WHITE` |
+|`RGB_YELLOW` |`HSV_YELLOW` |
```c
rgblight_setrgb(RGB_ORANGE);
@@ -477,7 +478,7 @@ rgblight_setrgb_at(RGB_GOLD, 3);
rgblight_sethsv_range(HSV_WHITE, 0, 6);
```
-These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight_list.h). Feel free to add to this list!
+These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/color.h). Feel free to add to this list!
## Changing the order of the LEDs
diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md
index 4ebf585f5c..428d581cab 100644
--- a/docs/feature_split_keyboard.md
+++ b/docs/feature_split_keyboard.md
@@ -8,8 +8,7 @@ QMK Firmware has a generic implementation that is usable by any board, as well a
For this, we will mostly be talking about the generic implementation used by the Let's Split and other keyboards.
-!> ARM is not yet fully supported for Split Keyboards and has many limitations. Progress is being made, but we have not yet reached 100% feature parity.
-
+!> ARM split supports most QMK subsystems when using the 'serial' and 'serial_usart' drivers. I2C slave is currently unsupported.
## Compatibility Overview
@@ -90,7 +89,13 @@ You can configure the firmware to read a pin on the controller to determine hand
#define SPLIT_HAND_PIN B7
```
-This will read the specified pin. If it's high, then the controller assumes it is the left hand, and if it's low, it's assumed to be the right side.
+This will read the specified pin. By default, if it's high, then the controller assumes it is the left hand, and if it's low, it's assumed to be the right side.
+
+This behaviour can be flipped by adding this to you `config.h` file:
+
+```c
+#define SPLIT_HAND_PIN_LOW_IS_LEFT
+```
#### Handedness by Matrix Pin
@@ -169,7 +174,7 @@ Because not every split keyboard is identical, there are a number of additional
#define USE_I2C
```
-This enables I<sup>2</sup>C support for split keyboards. This isn't strictly for communication, but can be used for OLED or other I<sup>2</sup>C-based devices.
+This configures the use of I<sup>2</sup>C support for split keyboard transport (AVR only).
```c
#define SOFT_SERIAL_PIN D0
@@ -193,20 +198,115 @@ If you're having issues with serial communication, you can change this value, as
* **`5`**: about 20kbps
```c
-#define SPLIT_MODS_ENABLE
+#define FORCED_SYNC_THROTTLE_MS 100
```
-This enables transmitting modifier state (normal, weak and oneshot) to the non
-primary side of the split keyboard. This adds a few bytes of data to the split
-communication protocol and may impact the matrix scan speed when enabled.
-The purpose of this feature is to support cosmetic use of modifer state (e.g.
-displaying status on an OLED screen).
+This sets the maximum number of milliseconds before forcing a synchronization of data from master to slave. Under normal circumstances this sync occurs whenever the data _changes_, for safety a data transfer occurs after this number of milliseconds if no change has been detected since the last sync.
```c
#define SPLIT_TRANSPORT_MIRROR
```
-This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. This adds a few bytes of data to the split communication protocol and may impact the matrix scan speed when enabled. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to Keypresses).
+This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to keypresses). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
+
+```c
+#define SPLIT_LAYER_STATE_ENABLE
+```
+
+This enables syncing of the layer state between both halves of the split keyboard. The main purpose of this feature is to enable support for use of things like OLED display of the currently active layer. This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
+
+```c
+#define SPLIT_LED_STATE_ENABLE
+```
+
+This enables syncing of the Host LED status (caps lock, num lock, etc) between both halves of the split keyboard. The main purpose of this feature is to enable support for use of things like OLED display of the Host LED status. This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
+
+```c
+#define SPLIT_MODS_ENABLE
+```
+
+This enables transmitting modifier state (normal, weak and oneshot) to the non primary side of the split keyboard. The purpose of this feature is to support cosmetic use of modifer state (e.g. displaying status on an OLED screen). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
+
+```c
+#define SPLIT_WPM_ENABLE
+```
+
+This enables transmitting the current WPM to the slave side of the split keyboard. The purpose of this feature is to support cosmetic use of WPM (e.g. displaying the current value on an OLED screen). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
+
+### Custom data sync between sides :id=custom-data-sync
+
+QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
+
+To leverage this, a keyboard or user/keymap can define a comma-separated list of _transaction IDs_:
+
+```c
+// for keyboard-level data sync:
+#define SPLIT_TRANSACTION_IDS_KB KEYBOARD_SYNC_A, KEYBOARD_SYNC_B
+// or, for user:
+#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_A, USER_SYNC_B, USER_SYNC_C
+```
+
+These _transaction IDs_ then need a slave-side handler function to be registered with the split transport, for example:
+
+```c
+typedef struct _master_to_slave_t {
+ int m2s_data;
+} master_to_slave_t;
+
+typedef struct _slave_to_master_t {
+ int s2m_data;
+} slave_to_master_t;
+
+void user_sync_a_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
+ const master_to_slave_t *m2s = (const master_to_slave_t*)in_data;
+ slave_to_master_t *s2m = (slave_to_master_t*)out_data;
+ s2m->s2m_data = m2s->m2s_data + 5; // whatever comes in, add 5 so it can be sent back
+}
+
+void keyboard_post_init_user(void) {
+ transaction_register_rpc(USER_SYNC_A, user_sync_a_slave_handler);
+}
+```
+
+The master side can then invoke the slave-side handler - for normal keyboard functionality to be minimally affected, any keyboard- or user-level code attempting to sync data should be throttled:
+
+```c
+void housekeeping_task_user(void) {
+ if (is_keyboard_master()) {
+ // Interact with slave every 500ms
+ static uint32_t last_sync = 0;
+ if (timer_elapsed32(last_sync) > 500) {
+ master_to_slave_t m2s = {6};
+ slave_to_master_t s2m = {0};
+ if(transaction_rpc_exec(USER_SYNC_A, sizeof(m2s), &m2s, sizeof(s2m), &s2m)) {
+ last_sync = timer_read32();
+ dprintf("Slave value: %d\n", s2m.s2m_data); // this will now be 11, as the slave adds 5
+ } else {
+ dprint("Slave sync failed!\n");
+ }
+ }
+ }
+}
+```
+
+!> It is recommended that any data sync between halves happens during the master side's _housekeeping task_. This ensures timely retries should failures occur.
+
+If only one-way data transfer is needed, helper methods are provided:
+
+```c
+bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
+bool transaction_rpc_send(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer);
+bool transaction_rpc_recv(int8_t transaction_id, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
+```
+
+By default, the inbound and outbound data is limited to a maximum of 32 bytes each. The sizes can be altered if required:
+
+```c
+// Master to slave:
+#define RPC_M2S_BUFFER_SIZE 48
+// Slave to master:
+#define RPC_S2M_BUFFER_SIZE 48
+```
### Hardware Configuration Options
diff --git a/docs/feature_st7565.md b/docs/feature_st7565.md
new file mode 100644
index 0000000000..de3e44d8e9
--- /dev/null
+++ b/docs/feature_st7565.md
@@ -0,0 +1,274 @@
+# ST7565 LCD Driver
+
+## Supported Hardware
+
+LCD modules using ST7565 driver IC, communicating over SPI.
+
+|Module |IC |Size |Notes |
+|------------------------------|-------|------|----------------------------------------------------------|
+|Newhaven Display NHD-C12832A1Z|ST7565R|128x32|Used by Ergodox Infinity; primary consumer of this feature|
+|Zolentech ZLE12864B |ST7565P|128x64|Requires contrast adjustment |
+
+## Usage
+
+To enable the feature, there are three steps. First, when compiling your keyboard, you'll need to add the following to your `rules.mk`:
+
+```make
+ST7565_ENABLE = yes
+```
+
+Then in your `keymap.c` file, implement the ST7565 task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`:
+
+```c
+#ifdef ST7565_ENABLE
+void st7565_task_user(void) {
+ // Host Keyboard Layer Status
+ st7565_write_P(PSTR("Layer: "), false);
+
+ switch (get_highest_layer(layer_state)) {
+ case _QWERTY:
+ st7565_write_P(PSTR("Default\n"), false);
+ break;
+ case _FN:
+ st7565_write_P(PSTR("FN\n"), false);
+ break;
+ case _ADJ:
+ st7565_write_P(PSTR("ADJ\n"), false);
+ break;
+ default:
+ // Or use the write_ln shortcut over adding '\n' to the end of your string
+ st7565_write_ln_P(PSTR("Undefined"), false);
+ }
+
+ // Host Keyboard LED Status
+ led_t led_state = host_keyboard_led_state();
+ st7565_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false);
+ st7565_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false);
+ st7565_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false);
+}
+#endif
+```
+
+## Logo Example
+
+In the default font, certain ranges of characters are reserved for a QMK logo. To render this logo to the screen, use the following code example:
+
+```c
+static void render_logo(void) {
+ static const char PROGMEM qmk_logo[] = {
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00
+ };
+
+ st7565_write_P(qmk_logo, false);
+}
+```
+
+## Buffer Read Example
+For some purposes, you may need to read the current state of the display buffer. The `st7565_read_raw` function can be used to safely read bytes from the buffer.
+
+In this example, calling `fade_display` in the `st7565_task_user` function will slowly fade away whatever is on the screen by turning random pixels off over time.
+```c
+//Setup some mask which can be or'd with bytes to turn off pixels
+const uint8_t single_bit_masks[8] = {127, 191, 223, 239, 247, 251, 253, 254};
+
+static void fade_display(void) {
+ //Define the reader structure
+ display_buffer_reader_t reader;
+ uint8_t buff_char;
+ if (random() % 30 == 0) {
+ srand(timer_read());
+ // Fetch a pointer for the buffer byte at index 0. The return structure
+ // will have the pointer and the number of bytes remaining from this
+ // index position if we want to perform a sequential read by
+ // incrementing the buffer pointer
+ reader = st7565_read_raw(0);
+ //Loop over the remaining buffer and erase pixels as we go
+ for (uint16_t i = 0; i < reader.remaining_element_count; i++) {
+ //Get the actual byte in the buffer by dereferencing the pointer
+ buff_char = *reader.current_element;
+ if (buff_char != 0) {
+ st7565_write_raw_byte(buff_char & single_bit_masks[rand() % 8], i);
+ }
+ //increment the pointer to fetch a new byte during the next loop
+ reader.current_element++;
+ }
+ }
+}
+```
+
+## Other Examples
+
+In split keyboards, it is very common to have two displays that each render different content and are oriented or flipped differently. You can do this by switching which content to render by using the return value from `is_keyboard_master()` or `is_keyboard_left()` found in `split_util.h`, e.g:
+
+```c
+#ifdef ST7565_ENABLE
+display_rotation_t st7565_init_user(display_rotation_t rotation) {
+ if (!is_keyboard_master()) {
+ return DISPLAY_ROTATION_180; // flips the display 180 degrees if offhand
+ }
+
+ return rotation;
+}
+
+void st7565_task_user(void) {
+ if (is_keyboard_master()) {
+ render_status(); // Renders the current keyboard state (layer, lock, caps, scroll, etc)
+ } else {
+ render_logo(); // Renders a static logo
+ }
+}
+#endif
+```
+
+## Basic Configuration
+
+|Define |Default |Description |
+|------------------------|--------------|-----------------------------------------------------------------------------------------------------|
+|`ST7565_A0_PIN` |*Not defined* |(Required) The GPIO connected to the display's A0 (data/command) pin |
+|`ST7565_RST_PIN` |*Not defined* |(Required) The GPIO connected to the display's reset pin |
+|`ST7565_SS_PIN` |*Not defined* |(Required) The GPIO connected to the display's slave select pin |
+|`ST7565_SPI_CLK_DIVISOR`|`4` |The SPI clock divisor to use |
+|`ST7565_FONT_H` |`"glcdfont.c"`|The font code file to use for custom fonts |
+|`ST7565_FONT_START` |`0` |The starting character index for custom fonts |
+|`ST7565_FONT_END` |`223` |The ending character index for custom fonts |
+|`ST7565_FONT_WIDTH` |`6` |The font width |
+|`ST7565_FONT_HEIGHT` |`8` |The font height (untested) |
+|`ST7565_TIMEOUT` |`60000` |Turns off the screen after 60000ms of keyboard inactivity. Helps reduce burn-in. Set to 0 to disable.|
+|`ST7565_COLUMN_OFFSET` |`0` |Shift output to the right this many pixels. |
+|`ST7565_CONTRAST` |`32` |The default contrast level of the display, from 0 to 255. |
+|`ST7565_UPDATE_INTERVAL`|`0` |Set the time interval for updating the display in ms. This will improve the matrix scan rate. |
+
+## Custom sized displays
+
+The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind.
+
+|Define |Default |Description |
+|-----------------------|----------|-----------------------------------------------------------------------------------------------------------|
+|`ST7565_DISPLAY_WIDTH` |`128` |The width of the display. |
+|`ST7565_DISPLAY_HEIGHT`|`32` |The height of the display. |
+|`ST7565_MATRIX_SIZE` |`512` |The local buffer size to allocate.<br>`(ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH)`. |
+|`ST7565_BLOCK_TYPE` |`uint16_t`|The unsigned integer type to use for dirty rendering. |
+|`ST7565_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.<br>`(sizeof(ST7565_BLOCK_TYPE) * 8)`.|
+|`ST7565_BLOCK_SIZE` |`32` |The size of each block for dirty rendering<br>`(ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)`. |
+
+## API
+
+```c
+// Rotation enum values are flags
+typedef enum {
+ DISPLAY_ROTATION_0,
+ DISPLAY_ROTATION_180
+} display_rotation_t;
+
+// Initialize the display, rotating the rendered output based on the define passed in.
+// Returns true if the was initialized successfully
+bool st7565_init(display_rotation_t rotation);
+
+// Called at the start of st7565_init, weak function overridable by the user
+// rotation - the value passed into st7565_init
+// Return new display_rotation_t if you want to override default rotation
+display_rotation_t st7565_init_user(display_rotation_t rotation);
+
+// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
+void st7565_clear(void);
+
+// Renders the dirty chunks of the buffer to display
+void st7565_render(void);
+
+// Moves cursor to character position indicated by column and line, wraps if out of bounds
+// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions
+void st7565_set_cursor(uint8_t col, uint8_t line);
+
+// Advances the cursor to the next page, writing ' ' if true
+// Wraps to the begining when out of bounds
+void st7565_advance_page(bool clearPageRemainder);
+
+// Moves the cursor forward 1 character length
+// Advance page if there is not enough room for the next character
+// Wraps to the begining when out of bounds
+void st7565_advance_char(void);
+
+// Writes a single character to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Main handler that writes character data to the display buffer
+void st7565_write_char(const char data, bool invert);
+
+// Writes a string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+void st7565_write(const char *data, bool invert);
+
+// Writes a string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
+void st7565_write_ln(const char *data, bool invert);
+
+// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
+// Useful for moving the screen in preparation for new drawing
+void st7565_pan(bool left);
+
+// Returns a pointer to the requested start index in the buffer plus remaining
+// buffer length as struct
+display_buffer_reader_t st7565_read_raw(uint16_t start_index);
+
+// Writes a string to the buffer at current cursor position
+void st7565_write_raw(const char *data, uint16_t size);
+
+// Writes a single byte into the buffer at the specified index
+void st7565_write_raw_byte(const char data, uint16_t index);
+
+// Sets a specific pixel on or off
+// Coordinates start at top-left and go right and down for positive x and y
+void st7565_write_pixel(uint8_t x, uint8_t y, bool on);
+
+// Writes a PROGMEM string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM
+void st7565_write_P(const char *data, bool invert);
+
+// Writes a PROGMEM string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
+// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM
+void st7565_write_ln_P(const char *data, bool invert);
+
+// Writes a PROGMEM string to the buffer at current cursor position
+void st7565_write_raw_P(const char *data, uint16_t size);
+
+// Can be used to manually turn on the screen if it is off
+// Returns true if the screen was on or turns on
+bool st7565_on(void);
+
+// Called when st7565_on() turns on the screen, weak function overridable by the user
+// Not called if the screen is already on
+void st7565_on_user(void);
+
+// Can be used to manually turn off the screen if it is on
+// Returns true if the screen was off or turns off
+bool st7565_off(void);
+
+// Called when st7565_off() turns off the screen, weak function overridable by the user
+// Not called if the screen is already off
+void st7565_off_user(void);
+
+// Returns true if the screen is currently on, false if it is
+// not
+bool st7565_is_on(void);
+
+// Basically it's st7565_render, but with timeout management and st7565_task_user calling!
+void st7565_task(void);
+
+// Called at the start of st7565_task, weak function overridable by the user
+void st7565_task_user(void);
+
+// Inverts the display
+// Returns true if the screen was or is inverted
+bool st7565_invert(bool invert);
+
+// Returns the maximum number of characters that will fit on a line
+uint8_t st7565_max_chars(void);
+
+// Returns the maximum number of lines that will fit on the display
+uint8_t st7565_max_lines(void);
+```
diff --git a/docs/ja/compatible_microcontrollers.md b/docs/ja/compatible_microcontrollers.md
index b675b038d2..761a4cda46 100644
--- a/docs/ja/compatible_microcontrollers.md
+++ b/docs/ja/compatible_microcontrollers.md
@@ -36,6 +36,8 @@ QMK は十分な容量のフラッシュメモリを備えた USB 対応 AVR ま
* [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.html)
+* [STM32L412](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
+* [STM32L422](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x2.html)
* [STM32L433](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x3.html)
* [STM32L443](https://www.st.com/en/microcontrollers-microprocessors/stm32l4x3.html)
diff --git a/docs/ja/feature_dip_switch.md b/docs/ja/feature_dip_switch.md
index a0f6aeb003..a5436779f1 100644
--- a/docs/ja/feature_dip_switch.md
+++ b/docs/ja/feature_dip_switch.md
@@ -28,8 +28,9 @@ DIP スイッチは、以下を `rules.mk` に追加することでサポート
コールバック関数を `<keyboard>.c` に記述することができます:
```c
-void dip_switch_update_kb(uint8_t index, bool active) {
- dip_switch_update_user(index, active);
+bool dip_switch_update_kb(uint8_t index, bool active) {
+ if !(dip_switch_update_user(index, active)) { return false; }
+ return true;
}
```
@@ -37,7 +38,7 @@ void dip_switch_update_kb(uint8_t index, bool active) {
あるいは `keymap.c` に記述することもできます:
```c
-void dip_switch_update_user(uint8_t index, bool active) {
+bool dip_switch_update_user(uint8_t index, bool active) {
switch (index) {
case 0:
if(active) { audio_on(); } else { audio_off(); }
@@ -62,6 +63,7 @@ void dip_switch_update_user(uint8_t index, bool active) {
}
break;
}
+ return true;
}
```
@@ -69,8 +71,9 @@ void dip_switch_update_user(uint8_t index, bool active) {
```c
-void dip_switch_update_mask_kb(uint32_t state) {
- dip_switch_update_mask_user(state);
+bool dip_switch_update_mask_kb(uint32_t state) {
+ if (!dip_switch_update_mask_user(state)) { return false; }
+ return true;
}
```
@@ -78,7 +81,7 @@ void dip_switch_update_mask_kb(uint32_t state) {
あるいは `keymap.c` に記述することもできます:
```c
-void dip_switch_update_mask_user(uint32_t state) {
+bool dip_switch_update_mask_user(uint32_t state) {
if (state & (1UL<<0) && state & (1UL<<1)) {
layer_on(_ADJUST); // C on esc
} else {
@@ -94,6 +97,7 @@ void dip_switch_update_mask_user(uint32_t state) {
} else {
layer_off(_TEST_B);
}
+ return true;
}
```
diff --git a/docs/serial_driver.md b/docs/serial_driver.md
index 359fc59551..ed989b0a15 100644
--- a/docs/serial_driver.md
+++ b/docs/serial_driver.md
@@ -73,7 +73,7 @@ You must also enable the ChibiOS `SERIAL` feature:
Do note that the configuration required is for the `SERIAL` peripheral, not the `UART` peripheral.
### USART Full-duplex
-Targeting STM32 boards where communication is offloaded to a USART hardware device. The advantage over bitbang is that this provides fast and accurate timings. USART Full-Duplex requires two conductors **without** pull-up resistors instead of one conductor with a pull-up resistor unlike the Half-duplex driver, but it is more efficent as it uses DMA transfers, which can result in even faster transmission speeds.
+Targeting STM32 boards where communication is offloaded to a USART hardware device. The advantage over bitbang is that this provides fast and accurate timings. USART Full-Duplex requires two conductors **without** pull-up resistors instead of one conductor with a pull-up resistor unlike the Half-duplex driver. Due to its internal design it is more efficent, which can result in even faster transmission speeds.
#### Pin configuration
@@ -86,12 +86,13 @@ Please note that `TX` of the master half has to be connected with the `RX` pin o
To use the driver, add this to your rules.mk:
```make
-SERIAL_DRIVER = usart_duplex
+SERIAL_DRIVER = usart
```
Next configure the hardware via your config.h:
```c
+#define SERIAL_USART_FULL_DUPLEX // Enable full duplex operation mode.
#define SERIAL_USART_TX_PIN B6 // USART TX pin
#define SERIAL_USART_RX_PIN B7 // USART RX pin
//#define USART1_REMAP // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
@@ -104,17 +105,17 @@ Next configure the hardware via your config.h:
// 3: 57600 baud
// 4: 38400 baud
// 5: 19200 baud
-#define SERIAL_USART_DRIVER UARTD1 // USART driver of TX and RX pin. default: UARTD1
+#define SERIAL_USART_DRIVER SD1 // USART driver of TX and RX pin. default: SD1
#define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
#define SERIAL_USART_RX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
#define SERIAL_USART_TIMEOUT 100 // USART driver timeout. default 100
```
-You must also enable the ChibiOS `UART` with blocking api feature:
-* In your board's halconf.h: `#define HAL_USE_UART TRUE` and `#define UART_USE_WAIT TRUE`
-* In your board's mcuconf.h: `#define STM32_UART_USE_USARTn TRUE` (where 'n' matches the peripheral number of your selected USART on the MCU)
+You must also enable the ChibiOS `SERIAL` feature:
+* In your board's halconf.h: `#define HAL_USE_SERIAL TRUE`
+* In your board's mcuconf.h: `#define STM32_SERIAL_USE_USARTn TRUE` (where 'n' matches the peripheral number of your selected USART on the MCU)
-Do note that the configuration required is for the `UART` peripheral, not the `SERIAL` peripheral.
+Do note that the configuration required is for the `SERIAL` peripheral, not the `UART` peripheral.
#### Pins for USART Peripherals with Alternate Functions for selected STM32 MCUs