summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_summary.md1
-rw-r--r--docs/config_options.md9
-rw-r--r--docs/feature_caps_word.md20
-rw-r--r--docs/feature_converters.md8
-rw-r--r--docs/feature_dynamic_macros.md2
-rw-r--r--docs/feature_encoders.md16
-rw-r--r--docs/feature_layers.md48
-rw-r--r--docs/feature_led_matrix.md8
-rw-r--r--docs/feature_oled_driver.md119
-rw-r--r--docs/feature_pointing_device.md26
-rw-r--r--docs/feature_rgb_matrix.md100
-rw-r--r--docs/feature_rgblight.md13
-rw-r--r--docs/feature_split_keyboard.md6
-rw-r--r--docs/feature_stenography.md2
-rw-r--r--docs/feature_swap_hands.md11
-rw-r--r--docs/getting_started_vagrant.md56
-rw-r--r--docs/ja/_summary.md1
-rw-r--r--docs/ja/config_options.md3
-rw-r--r--docs/ja/feature_dynamic_macros.md2
-rw-r--r--docs/ja/feature_stenography.md2
-rw-r--r--docs/ja/getting_started_vagrant.md61
-rw-r--r--docs/ja/tap_hold.md28
-rw-r--r--docs/mod_tap.md2
-rw-r--r--docs/newbs_building_firmware_workflow.md2
-rw-r--r--docs/quantum_painter.md24
-rw-r--r--docs/squeezing_avr.md1
-rw-r--r--docs/tap_hold.md89
-rw-r--r--docs/understanding_qmk.md2
-rw-r--r--docs/ws2812_driver.md8
-rw-r--r--docs/zh-cn/_summary.md3
-rw-r--r--docs/zh-cn/getting_started_vagrant.md61
-rw-r--r--docs/zh-cn/mod_tap.md2
32 files changed, 339 insertions, 397 deletions
diff --git a/docs/_summary.md b/docs/_summary.md
index 01808bd675..ce579cb071 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -41,7 +41,6 @@
* [Keymap Overview](keymap.md)
* Development Environments
* [Docker Guide](getting_started_docker.md)
- * [Vagrant Guide](getting_started_vagrant.md)
* Flashing
* [Flashing](flashing.md)
* [Flashing ATmega32A (ps2avrgb)](flashing_bootloadhid.md)
diff --git a/docs/config_options.md b/docs/config_options.md
index 5bfb7c5d58..5ea71d993e 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -150,7 +150,7 @@ If you define these options you will enable the associated feature, which may in
* `#define TAPPING_TERM_PER_KEY`
* enables handling for per key `TAPPING_TERM` settings
* `#define RETRO_TAPPING`
- * tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release
+ * tap anyway, even after `TAPPING_TERM`, if there was no other key interruption between press and release
* See [Retro Tapping](tap_hold.md#retro-tapping) for details
* `#define RETRO_TAPPING_PER_KEY`
* enables handling for per key `RETRO_TAPPING` settings
@@ -161,9 +161,6 @@ If you define these options you will enable the associated feature, which may in
* See [Permissive Hold](tap_hold.md#permissive-hold) for details
* `#define PERMISSIVE_HOLD_PER_KEY`
* enabled handling for per key `PERMISSIVE_HOLD` settings
-* `#define IGNORE_MOD_TAP_INTERRUPT`
- * makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys.
- * See [Ignore Mod Tap Interrupt](tap_hold.md#ignore-mod-tap-interrupt) for details
* `#define QUICK_TAP_TERM 100`
* tap-then-hold timing to use a dual role key to repeat keycode
* See [Quick Tap Term](tap_hold.md#quick-tap-term)
@@ -217,7 +214,7 @@ If you define these options you will enable the associated feature, which may in
## RGB Light Configuration
-* `#define RGB_DI_PIN D7`
+* `#define WS2812_DI_PIN D7`
* pin the DI on the WS2812 is hooked-up to
* `#define RGBLIGHT_LAYERS`
* Lets you define [lighting layers](feature_rgblight.md?id=lighting-layers) that can be toggled on or off. Great for showing the current keyboard layer or caps lock state.
@@ -233,7 +230,7 @@ If you define these options you will enable the associated feature, which may in
* `#define RGBLIGHT_SPLIT`
* Needed if both halves of the board have RGB LEDs wired directly to the RGB output pin on the controllers instead of passing the output of the left half to the input of the right half
* `#define RGBLED_SPLIT { 6, 6 }`
- * number of LEDs connected that are directly wired to `RGB_DI_PIN` on each half of a split keyboard
+ * number of LEDs connected that are directly wired to the RGB pin on each half of a split keyboard
* First value indicates number of LEDs for left half, second value is for the right half
* When RGBLED_SPLIT is defined, RGBLIGHT_SPLIT is implicitly defined.
* `#define RGBLIGHT_HUE_STEP 12`
diff --git a/docs/feature_caps_word.md b/docs/feature_caps_word.md
index c58d1a56e2..7f726b059d 100644
--- a/docs/feature_caps_word.md
+++ b/docs/feature_caps_word.md
@@ -90,6 +90,26 @@ by defining `IS_COMMAND()` in config.h:
## Customizing Caps Word :id=customizing-caps-word
+### Invert on shift :id=invert-on-shift
+
+By default, Caps Word turns off when Shift keys are pressed, considering them as
+word-breaking. Alternatively with the `CAPS_WORD_INVERT_ON_SHIFT` option,
+pressing the Shift key continues Caps Word and inverts the shift state. This
+is convenient for uncapitalizing one or a few letters within a word, for
+example with Caps Word on, typing "D, B, Shift+A, Shift+A, S" produces "DBaaS",
+or typing "P, D, F, Shift+S" produces "PDFs".
+
+Enable it by adding in config.h
+
+```c
+#define CAPS_WORD_INVERT_ON_SHIFT
+```
+
+This option works with regular Shift keys `KC_LSFT` and `KC_RSFT`, mod-tap Shift
+keys, and one-shot Shift keys. Note that while Caps Word is on, one-shot Shift
+keys behave like regular Shift keys, and have effect only while they are held.
+
+
### Idle timeout :id=idle-timeout
Caps Word turns off automatically if no keys are pressed for
diff --git a/docs/feature_converters.md b/docs/feature_converters.md
index ec1f3915ee..b1abfa373a 100644
--- a/docs/feature_converters.md
+++ b/docs/feature_converters.md
@@ -20,11 +20,13 @@ Currently the following converters are available:
| `promicro` | `rp2040_ce` |
| `promicro` | `elite_pi` |
| `promicro` | `helios` |
+| `promicro` | `liatris` |
| `promicro` | `michi` |
| `elite_c` | `stemcell` |
| `elite_c` | `rp2040_ce` |
| `elite_c` | `elite_pi` |
| `elite_c` | `helios` |
+| `elite_c` | `liatris` |
See below for more in depth information on each converter.
@@ -87,6 +89,7 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
| [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
+| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` |
Converter summary:
@@ -103,6 +106,7 @@ Converter summary:
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
+| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` |
### Proton C :id=proton_c
@@ -167,7 +171,7 @@ The Bonsai C4 only has one on-board LED (B2), and by default, both the Pro Micro
#define B0 PAL_LINE(GPIOA, 9)
```
-### RP2040 Community Edition - Elite-Pi and Helios :id=rp2040_ce
+### RP2040 Community Edition - Elite-Pi, Helios, and Liatris :id=rp2040_ce
Feature set currently identical to [Adafruit KB2040](#kb2040).
@@ -184,6 +188,7 @@ If a board currently supported in QMK uses an [Elite-C](https://keeb.io/products
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
+| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
Converter summary:
@@ -193,6 +198,7 @@ Converter summary:
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
+| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
### STeMCell :id=stemcell_elite
diff --git a/docs/feature_dynamic_macros.md b/docs/feature_dynamic_macros.md
index f5a6952b6b..8ab1bad61c 100644
--- a/docs/feature_dynamic_macros.md
+++ b/docs/feature_dynamic_macros.md
@@ -59,7 +59,7 @@ There are a number of hooks that you can use to add custom functionality and fee
Note, that direction indicates which macro it is, with `1` being Macro 1, `-1` being Macro 2, and 0 being no macro.
-* `dynamic_macro_record_start_user(void)` - Triggered when you start recording a macro.
+* `dynamic_macro_record_start_user(int8_t direction)` - Triggered when you start recording a macro.
* `dynamic_macro_play_user(int8_t direction)` - Triggered when you play back a macro.
* `dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record)` - Triggered on each keypress while recording a macro.
* `dynamic_macro_record_end_user(int8_t direction)` - Triggered when the macro recording is stopped.
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index 1c521a4eff..891baeefa1 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -81,7 +81,7 @@ Your `keymap.c` will then need an encoder mapping defined (for four layers and t
```c
#if defined(ENCODER_MAP_ENABLE)
-const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
+const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[_BASE] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[_LOWER] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_SAD, RGB_SAI) },
[_RAISE] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(RGB_SPD, RGB_SPI) },
@@ -102,9 +102,9 @@ Using encoder mapping pumps events through the normal QMK keycode processing pip
## Callbacks
-When not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
+?> [**Default Behaviour**](https://github.com/qmk/qmk_firmware/blob/master/quantum/encoder.c#L79-#L98): all encoders installed will function as volume up (`KC_VOLU`) on clockwise rotation and volume down (`KC_VOLD`) on counter-clockwise rotation. If you do not wish to override this, no further configuration is necessary.
-?> Those who are adding new keyboard support where encoders are enabled at the keyboard level should include basic encoder functionality at the keyboard level (`<keyboard>.c`) using the `encoder_update_kb()` function, that way it works for QMK Configuator users and exists in general.
+If you would like the alter the default behaviour, and are not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
```c
bool encoder_update_kb(uint8_t index, bool clockwise) {
@@ -113,9 +113,9 @@ bool encoder_update_kb(uint8_t index, bool clockwise) {
}
if (index == 0) { /* First encoder */
if (clockwise) {
- tap_code_delay(KC_VOLU, 10);
+ tap_code(KC_PGDN);
} else {
- tap_code_delay(KC_VOLD, 10);
+ tap_code(KC_PGUP);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
@@ -134,9 +134,9 @@ or `keymap.c`:
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) { /* First encoder */
if (clockwise) {
- tap_code_delay(KC_VOLU, 10);
+ tap_code(KC_PGDN);
} else {
- tap_code_delay(KC_VOLD, 10);
+ tap_code(KC_PGUP);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
@@ -149,7 +149,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
}
```
-!> If you return `true` in the keymap level `_user` function, it will allow the keyboard level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
+!> If you return `true` in the keymap level `_user` function, it will allow the keyboard/core level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
## Hardware
diff --git a/docs/feature_layers.md b/docs/feature_layers.md
index f8cb53eda4..8503603ffe 100644
--- a/docs/feature_layers.md
+++ b/docs/feature_layers.md
@@ -127,6 +127,54 @@ layer_state_t layer_state_set_user(layer_state_t state) {
}
```
+### Example: Keycode to cycle through layers
+
+This example shows how to implement a custom keycode to cycle through a range of layers.
+
+```c
+// Define the keycode, `QK_USER` avoids collisions with existing keycodes
+enum keycodes {
+ KC_CYCLE_LAYERS = QK_USER,
+};
+
+// 1st layer on the cycle
+#define LAYER_CYCLE_START 0
+// Last layer on the cycle
+#define LAYER_CYCLE_END 4
+
+// Add the behaviour of this new keycode
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case KC_CYCLE_LAYERS:
+ // Our logic will happen on presses, nothing is done on releases
+ if (!record->event.pressed) {
+ // We've already handled the keycode (doing nothing), let QMK know so no further code is run unnecessarily
+ return false;
+ }
+
+ uint8_t current_layer = get_highest_layer(layer_state);
+
+ // Check if we are within the range, if not quit
+ if (curent_layer > LAYER_CYCLE_END || current_layer < LAYER_CYCLE_START) {
+ return false;
+ }
+
+ uint8_t next_layer = current_layer + 1;
+ if (next_layer > LAYER_CYCLE_END) {
+ next_layer = LAYER_CYCLE_START;
+ }
+ layer_move(next_layer);
+ return false;
+
+ // Process other keycodes normally
+ default:
+ return true;
+ }
+}
+
+// Place `KC_CYCLE_LAYERS` as a keycode in your keymap
+```
+
Use the `IS_LAYER_ON_STATE(state, layer)` and `IS_LAYER_OFF_STATE(state, layer)` macros to check the status of a particular layer.
Outside of `layer_state_set_*` functions, you can use the `IS_LAYER_ON(layer)` and `IS_LAYER_OFF(layer)` macros to check global layer state.
diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
index 1cde9b66e1..bc86099f1f 100644
--- a/docs/feature_led_matrix.md
+++ b/docs/feature_led_matrix.md
@@ -378,13 +378,7 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
## EEPROM storage :id=eeprom-storage
-The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time), but could be configured to use its own 32bit address with:
-
-```c
-#define EECONFIG_LED_MATRIX (uint32_t *)28
-```
-
-Where `28` is an unused index from `eeconfig.h`.
+The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time).
### Direct Operation :id=direct-operation
|Function |Description |
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index dea9cb8074..a62294b23a 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -2,15 +2,18 @@
## Supported Hardware
-OLED modules using SSD1306 or SH1106 driver ICs, communicating over I2C.
+OLED modules using SSD1306, SH1106 or SH1107 driver ICs, communicating over I2C or SPI.
Tested combinations:
-|IC |Size |Platform|Notes |
-|---------|------|--------|------------------------|
-|SSD1306 |128x32|AVR |Primary support |
-|SSD1306 |128x64|AVR |Verified working |
-|SSD1306 |128x32|Arm | |
-|SH1106 |128x64|AVR |No rotation or scrolling|
+|IC |Size |Platform|Notes |
+|---------|-------|--------|------------------------|
+|SSD1306 |128x32 |AVR |Primary support |
+|SSD1306 |128x64 |AVR |Verified working |
+|SSD1306 |128x32 |Arm | |
+|SH1106 |128x64 |AVR |No scrolling |
+|SH1107 |64x128 |AVR |No scrolling |
+|SH1107 |64x128 |Arm |No scrolling |
+|SH1107 |128x128|Arm |No scrolling |
Hardware configurations using Arm-based microcontrollers or different sizes of OLED modules may be compatible, but are untested.
@@ -23,15 +26,26 @@ OLED_ENABLE = yes
```
## OLED type
-|OLED Driver |Supported Device |
-|-------------------|---------------------------|
-|SSD1306 (default) |For both SSD1306 and SH1106|
+
+|OLED Driver |Supported Device |
+|-------------------|------------------------------------|
+|SSD1306 (default) |For both SSD1306, SH1106, and SH1107|
e.g.
```make
OLED_DRIVER = SSD1306
```
+|OLED Transport | |
+|---------------|------------------------------------------------|
+|i2c (default) | Uses I2C for communication with the OLED panel |
+|spi | Uses SPI for communication with the OLED panel |
+
+e.g.
+```make
+OLED_TRANSPORT = i2c
+```
+
Then in your `keymap.c` file, implement the OLED task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`:
```c
@@ -159,32 +173,57 @@ These configuration options should be placed in `config.h`. Example:
#define OLED_BRIGHTNESS 128
```
+|Define |Default |Description |
+|---------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------|
+|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
+|`OLED_COLUMN_OFFSET` |`0` |Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC. |
+|`OLED_DISPLAY_CLOCK` |`0x80` |Set the display clock divide ratio/oscillator frequency. |
+|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts |
+|`OLED_FONT_START` |`0` |The starting character index for custom fonts |
+|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
+|`OLED_FONT_WIDTH` |`6` |The font width |
+|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
+|`OLED_IC` |`OLED_IC_SSD1306` |Set to `OLED_IC_SH1106` or `OLED_IC_SH1107` if the corresponding controller chip is used. |
+|`OLED_FADE_OUT` |*Not defined* |Enables fade out animation. Use together with `OLED_TIMEOUT`. |
+|`OLED_FADE_OUT_INTERVAL` |`0` |The speed of fade out animation, from 0 to 15. Larger values are slower. |
+|`OLED_SCROLL_TIMEOUT` |`0` |Scrolls the OLED screen after 0ms of OLED inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
+|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
+|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
+|`OLED_UPDATE_INTERVAL` |`0` (`50` for split keyboards) |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
+|`OLED_UPDATE_PROCESS_LIMIT'|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
+
+### I2C 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 character index for custom fonts |
-|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
-|`OLED_FONT_WIDTH` |`6` |The font width |
-|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
-|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
-|`OLED_FADE_OUT` |*Not defined* |Enables fade out animation. Use together with `OLED_TIMEOUT`. |
-|`OLED_FADE_OUT_INTERVAL` |`0` |The speed of fade out animation, from 0 to 15. Larger values are slower. |
-|`OLED_SCROLL_TIMEOUT` |`0` |Scrolls the OLED screen after 0ms of OLED inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
-|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
-|`OLED_IC` |`OLED_IC_SSD1306`|Set to `OLED_IC_SH1106` if you're using the SH1106 OLED controller. |
-|`OLED_COLUMN_OFFSET` |`0` |(SH1106 only.) Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC.|
-|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
-|`OLED_UPDATE_INTERVAL` |`0` |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
-
- ## 128x64 & Custom sized OLED Displays
-
- The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind. We have added a define, `OLED_DISPLAY_128X64`, to switch all the values to be used in a 128x64 display, as well as added a custom define, `OLED_DISPLAY_CUSTOM`, that allows you to provide the necessary values to the driver.
+
+### SPI Configuration
+
+|Define |Default |Description |
+|---------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------|
+|`OLED_DC_PIN` | Required |The pin used for the DC connection of the OLED Display. |
+|`OLED_CS_PIN` | Required |The pin used for the CS connection of the OLED Display. |
+|`OLED_RST_PIN` | *Not defined* |The pin used for the RST connection of the OLED Display (may be left undefined if the RST pin is not connected). |
+|`OLED_SPI_MODE` |`3` (default) |The SPI Mode for the OLED Display (not typically changed). |
+|`OLED_SPI_DIVISOR` |`2` (default) |The SPI Multiplier to use for the OLED Display. |
+
+## 128x64 & Custom sized OLED Displays
+
+ The default display size for this feature is 128x32, and the defaults are set with that in mind. However, there are a number of additional presets for common sizes that we have added. You can define one of these values to use the presets. If your display doesn't match one of these presets, you can define `OLED_DISPLAY_CUSTOM` to manually specify all of the values.
+
+|Define |Default |Description |
+|----------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------|
+|`OLED_DISPLAY_128X64` |*Not defined* |Changes the display defines for use with 128x64 displays. |
+|`OLED_DISPLAY_64X32` |*Not defined* |Changes the display defines for use with 64x32 displays. |
+|`OLED_DISPLAY_64X48` |*Not defined* |Changes the display defines for use with 64x48 displays. |
+|`OLED_DISPLAY_64X128` |*Not defined* |Changes the display defines for use with 64x128 displays. |
+|`OLED_DISPLAY_128X128`|*Not defined* |Changes the display defines for use with 128x128 displays. |
+|`OLED_DISPLAY_CUSTOM` |*Not defined* |Changes the display defines for use with custom displays.<br>Requires user to implement the below defines. |
+
+!> 64x128 and 128x128 displays default to the SH1107 IC type, as these heights are not supported by the other IC types.
|Define |Default |Description |
-|---------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------|
-|`OLED_DISPLAY_128X64`|*Not defined* |Changes the display defines for use with 128x64 displays. |
-|`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)`. |
@@ -192,14 +231,13 @@ These configuration options should be placed in `config.h`. Example:
|`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_COM_PIN_COUNT` |*Not defined* |Number of COM pins supported by the controller.<br>If not defined, the value appropriate for the defined `OLED_IC` is used. |
+|`OLED_COM_PIN_OFFSET`|`0` |Number of the first COM pin used by the OLED matrix. |
|`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 {
@@ -210,7 +248,7 @@ typedef enum {
} oled_rotation_t;
```
-OLED displays driven by SSD1306 drivers only natively support in hardware 0 degree and 180 degree rendering. This feature is done in software and not free. Using this feature will increase the time to calculate what data to send over i2c to the OLED. If you are strapped for cycles, this can cause keycodes to not register. In testing however, the rendering time on an ATmega32U4 board only went from 2ms to 5ms and keycodes not registering was only noticed once we hit 15ms.
+OLED displays driven by SSD1306, SH1106 or SH1107 drivers only natively support in hardware 0 degree and 180 degree rendering. This feature is done in software and not free. Using this feature will increase the time to calculate what data to send over i2c to the OLED. If you are strapped for cycles, this can cause keycodes to not register. In testing however, the rendering time on an ATmega32U4 board only went from 2ms to 5ms and keycodes not registering was only noticed once we hit 15ms.
90 degree rotation is achieved by using bitwise operations to rotate each 8 block of memory and uses two precalculated arrays to remap buffer memory to OLED memory. The memory map defines are precalculated for remap performance and are calculated based on the display height, width, and block size. For example, in the 128x32 implementation with a `uint8_t` block type, we have a 64 byte block size. This gives us eight 8 byte blocks that need to be rotated and rendered. The OLED renders horizontally two 8 byte blocks before moving down a page, e.g:
@@ -232,6 +270,8 @@ However the local buffer is stored as if it was Height x Width display instead o
So those precalculated arrays just index the memory offsets in the order in which each one iterates its data.
+Rotation on SH1106 and SH1107 is noticeably less efficient than on SSD1306, because these controllers do not support the “horizontal addressing mode”, which allows transferring the data for the whole rotated block at once; instead, separate address setup commands for every page in the block are required. The screen refresh time for SH1107 is therefore about 45% higher than for a same size screen with SSD1306 when using STM32 MCUs (on AVR the slowdown is about 20%, because the code which actually rotates the bitmap consumes more time).
+
## OLED API
```c
@@ -253,6 +293,11 @@ bool oled_init(oled_rotation_t rotation);
oled_rotation_t oled_init_kb(oled_rotation_t rotation);
oled_rotation_t oled_init_user(oled_rotation_t rotation);
+// Send commands/data to screen
+bool oled_send_cmd(const uint8_t *data, uint16_t size);
+bool oled_send_cmd_P(const uint8_t *data, uint16_t size);
+bool oled_send_data(const uint8_t *data, uint16_t size);
+
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
void oled_clear(void);
@@ -386,7 +431,9 @@ uint8_t oled_max_chars(void);
uint8_t oled_max_lines(void);
```
-!> Scrolling and rotation are unsupported on the SH1106.
+!> Scrolling is unsupported on the SH1106 and SH1107.
+
+!> Scrolling does not work properly on the SSD1306 if the display width is smaller than 128.
## SSD1306.h Driver Conversion Guide
diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md
index 4da5d64a1a..909eff826d 100644
--- a/docs/feature_pointing_device.md
+++ b/docs/feature_pointing_device.md
@@ -197,6 +197,24 @@ The Pimoroni Trackball module is a I2C based breakout board with an RGB enable t
| `PIMORONI_TRACKBALL_DEBOUNCE_