diff options
| author | Joel Challis <git@zvecr.com> | 2025-11-06 18:36:07 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-06 18:36:07 +0000 |
| commit | 01d81b95508f8411490467fe785b84d73495bdb9 (patch) | |
| tree | 971bc16a9049795fad6f4ed6c2e931e340e586dd | |
| parent | a00177d172878cfed3245881695d414be18bce1c (diff) | |
Rework converter docs (#18314)
| -rw-r--r-- | docs/feature_converters.md | 348 | ||||
| -rw-r--r-- | docs/public/pin_compatible_elite_c.svg | 61 | ||||
| -rw-r--r-- | docs/public/pin_compatible_promicro.svg | 61 |
3 files changed, 369 insertions, 101 deletions
diff --git a/docs/feature_converters.md b/docs/feature_converters.md index 06cc7b3a11..4e0a23752c 100644 --- a/docs/feature_converters.md +++ b/docs/feature_converters.md | |||
| @@ -2,8 +2,22 @@ | |||
| 2 | 2 | ||
| 3 | This page documents the automated process for converting keyboards to use drop-in replacement controllers. This process is designed to be easy to use and can be completed in a few simple steps. | 3 | This page documents the automated process for converting keyboards to use drop-in replacement controllers. This process is designed to be easy to use and can be completed in a few simple steps. |
| 4 | 4 | ||
| 5 | You can generate the firmware by appending `-e CONVERT_TO=<target>` to your compile/flash command. For example: | ||
| 6 | |||
| 7 | ```sh | ||
| 8 | qmk flash -c -kb keebio/bdn9/rev1 -km default -e CONVERT_TO=proton_c | ||
| 9 | ``` | ||
| 10 | |||
| 11 | You can also configure this within your [keymap](#keymap) to accomplish the same thing. | ||
| 12 | |||
| 13 | ::: tip | ||
| 14 | If you get build errors, you will need to convert the keyboard's code to be [compatible](#keyboard-req) with the converter feature, or provide additional [keymap](#keymap-add) configuration. | ||
| 15 | ::: | ||
| 16 | |||
| 5 | ## Supported Converters | 17 | ## Supported Converters |
| 6 | 18 | ||
| 19 | Each converter category is broken down by its declared `pin compatibility`. This ensures that only valid combinations are attempted. | ||
| 20 | |||
| 7 | The following converters are available at this time: | 21 | The following converters are available at this time: |
| 8 | 22 | ||
| 9 | | From | To | | 23 | | From | To | |
| @@ -28,86 +42,56 @@ The following converters are available at this time: | |||
| 28 | | `elite_c` | `helios` | | 42 | | `elite_c` | `helios` | |
| 29 | | `elite_c` | `liatris` | | 43 | | `elite_c` | `liatris` | |
| 30 | 44 | ||
| 45 | ## Configuration | ||
| 31 | 46 | ||
| 32 | ## Overview | 47 | Configuring a converter to use can be done by adding one of the following lines to your keymaps's configuration: |
| 33 | 48 | ||
| 34 | Each converter category is broken down by its declared `pin compatibility`. This ensures that only valid combinations are attempted. You can generate the firmware by appending `-e CONVERT_TO=<target>` to your compile/flash command. For example: | 49 | :::::tabs |
| 35 | 50 | ||
| 36 | ```sh | 51 | ==== keymap.json |
| 37 | qmk flash -c -kb keebio/bdn9/rev1 -km default -e CONVERT_TO=proton_c | ||
| 38 | ``` | ||
| 39 | |||
| 40 | You can also add the same `CONVERT_TO=<target>` to your keymap's `rules.mk`, which will accomplish the same thing. | ||
| 41 | |||
| 42 | ::: tip | ||
| 43 | If you get errors about `PORTB/DDRB`, etc not being defined, you'll need to convert the keyboard's code to use the [GPIO Controls](drivers/gpio) that will work for both ARM and AVR. This shouldn't affect the AVR builds at all. | ||
| 44 | ::: | ||
| 45 | 52 | ||
| 46 | ### Conditional Configuration | 53 | ```json [keymap.json] |
| 47 | 54 | { | |
| 48 | Once a converter is enabled, it exposes the `CONVERT_TO_<target_uppercase>` flag that you can use in your code with `#ifdef`s, For example: | 55 | "version": 1, |
| 49 | 56 | "keyboard": "keebio/bdn9/rev1", | |
| 50 | ```c | 57 | "keymap": "keebio_bdn9_rev1_layout_2025-05-20", |
| 51 | #ifdef CONVERT_TO_PROTON_C | 58 | "converter": "proton_c", // [!code focus] |
| 52 | // Proton C code | 59 | "layout": "LAYOUT", |
| 53 | #else | 60 | } |
| 54 | // Pro Micro code | ||
| 55 | #endif | ||
| 56 | ``` | 61 | ``` |
| 57 | 62 | ||
| 58 | ### Pin Compatibility | 63 | ==== rules.mk |
| 59 | |||
| 60 | To ensure compatibility, provide validation, and enable future workflows, a keyboard should declare its `pin compatibility`. For legacy reasons, this is currently assumed to be `promicro`. The following pin compatibility interfaces are currently defined: | ||
| 61 | |||
| 62 | | Pin Compatibility | Notes | | ||
| 63 | |-------------------|-----------------------------------| | ||
| 64 | | `promicro` | Includes RX/TX LEDs | | ||
| 65 | | `elite_c` | Includes bottom row pins, no LEDs | | ||
| 66 | |||
| 67 | To declare the base for conversions, add this line to your keyboard's `rules.mk`: | ||
| 68 | 64 | ||
| 69 | ```makefile | 65 | ```makefile |
| 70 | PIN_COMPATIBLE = elite_c | 66 | CONVERT_TO = proton_c |
| 71 | ``` | 67 | ``` |
| 72 | 68 | ||
| 73 | ## Pro Micro | 69 | ::::: |
| 74 | 70 | ||
| 75 | If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.com/products/12640) (or compatible board), the supported alternative controllers are: | 71 | ::: tip |
| 76 | 72 | If you get build errors, you will need to convert the keyboard's code to be [compatible](#keyboard-req) with the converter feature, or provide additional [keymap](#keymap-add) configuration. | |
| 77 | | Device | Target | | 73 | ::: |
| 78 | |------------------------------------------------------------------------------------------|-------------------| | 74 | |
| 79 | | [Proton C](https://qmk.fm/proton-c/) | `proton_c` | | 75 | ## Pro Micro Converters |
| 80 | | [Adafruit KB2040](https://learn.adafruit.com/adafruit-kb2040) | `kb2040` | | 76 | |
| 81 | | [SparkFun Pro Micro - RP2040](https://www.sparkfun.com/products/18288) | `sparkfun_pm2040` | | 77 | If a board currently supported by QMK uses a [Pro Micro](https://www.sparkfun.com/products/12640) (or compatible board), the supported alternative controllers are: |
| 82 | | [Blok](https://boardsource.xyz/store/628b95b494dfa308a6581622) | `blok` | | 78 | |
| 83 | | [Bit-C PRO](https://nullbits.co/bit-c-pro) | `bit_c_pro` | | 79 | | Device | Target | CLI Argument | `rules.mk` | Condition | |
| 84 | | [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` | | 80 | |------------------------------------------------------------------------------------------|-------------------|---------------------------------|------------------------------|-------------------------------------| |
| 85 | | [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` | | 81 | | [Proton C](https://qmk.fm/proton-c/) | `proton_c` | `-e CONVERT_TO=proton_c` | `CONVERT_TO=proton_c` | `#ifdef CONVERT_TO_PROTON_C` | |
| 86 | | [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` | | 82 | | [Adafruit KB2040](https://learn.adafruit.com/adafruit-kb2040) | `kb2040` | `-e CONVERT_TO=kb2040` | `CONVERT_TO=kb2040` | `#ifdef CONVERT_TO_KB2040` | |
| 87 | | [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` | | 83 | | [SparkFun Pro Micro - RP2040](https://www.sparkfun.com/products/18288) | `sparkfun_pm2040` | `-e CONVERT_TO=sparkfun_pm2040` | `CONVERT_TO=sparkfun_pm2040` | `#ifdef CONVERT_TO_SPARKFUN_PM2040` | |
| 88 | | [Liatris](https://splitkb.com/products/liatris) | `liatris` | | 84 | | [Blok](https://boardsource.xyz/store/628b95b494dfa308a6581622) | `blok` | `-e CONVERT_TO=blok` | `CONVERT_TO=blok` | `#ifdef CONVERT_TO_BLOK` | |
| 89 | | [Imera](https://splitkb.com/products/imera) | `imera` | | 85 | | [Bit-C PRO](https://nullbits.co/bit-c-pro) | `bit_c_pro` | `-e CONVERT_TO=bit_c_pro` | `CONVERT_TO=bit_c_pro` | `#ifdef CONVERT_TO_BIT_C_PRO` | |
| 90 | | [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` | | 86 | | [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` | |
| 91 | | [Svlinky](https://github.com/sadekbaroudi/svlinky) | `svlinky` | | 87 | | [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` | `-e CONVERT_TO=bonsai_c4` | `CONVERT_TO=bonsai_c4` | `#ifdef CONVERT_TO_BONSAI_C4` | |
| 92 | 88 | | [RP2040 Community Edition](#rp2040_ce) | `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` | | |
| 93 | Converter summary: | 89 | | [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` | |
| 94 | 90 | | [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` | | |
| 95 | | Target | Argument | `rules.mk` | Condition | | 91 | | [Liatris](https://splitkb.com/products/liatris) | `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` | |
| 96 | |-------------------|---------------------------------|------------------------------|-------------------------------------| | 92 | | [Imera](https://splitkb.com/products/imera) | `imera` | `-e CONVERT_TO=imera` | `CONVERT_TO=imera` | `#ifdef CONVERT_TO_IMERA` | |
| 97 | | `proton_c` | `-e CONVERT_TO=proton_c` | `CONVERT_TO=proton_c` | `#ifdef CONVERT_TO_PROTON_C` | | 93 | | [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` | |
| 98 | | `kb2040` | `-e CONVERT_TO=kb2040` | `CONVERT_TO=kb2040` | `#ifdef CONVERT_TO_KB2040` | | 94 | | [Svlinky](https://github.com/sadekbaroudi/svlinky) | `svlinky` | `-e CONVERT_TO=svlinky` | `CONVERT_TO=svlinky` | `#ifdef CONVERT_TO_SVLINKY` | |
| 99 | | `sparkfun_pm2040` | `-e CONVERT_TO=sparkfun_pm2040` | `CONVERT_TO=sparkfun_pm2040` | `#ifdef CONVERT_TO_SPARKFUN_PM2040` | | ||
| 100 | | `blok` | `-e CONVERT_TO=blok` | `CONVERT_TO=blok` | `#ifdef CONVERT_TO_BLOK` | | ||
| 101 | | `bit_c_pro` | `-e CONVERT_TO=bit_c_pro` | `CONVERT_TO=bit_c_pro` | `#ifdef CONVERT_TO_BIT_C_PRO` | | ||
| 102 | | `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` | | ||
| 103 | | `bonsai_c4` | `-e CONVERT_TO=bonsai_c4` | `CONVERT_TO=bonsai_c4` | `#ifdef CONVERT_TO_BONSAI_C4` | | ||
| 104 | | `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` | | ||
| 105 | | `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` | | ||
| 106 | | `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` | | ||
| 107 | | `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` | | ||
| 108 | | `imera` | `-e CONVERT_TO=imera` | `CONVERT_TO=imera` | `#ifdef CONVERT_TO_IMERA` | | ||
| 109 | | `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` | | ||
| 110 | | `svlinky` | `-e CONVERT_TO=svlinky` | `CONVERT_TO=svlinky` | `#ifdef CONVERT_TO_SVLINKY` | | ||
| 111 | 95 | ||
| 112 | ### Proton C {#proton_c} | 96 | ### Proton C {#proton_c} |
| 113 | 97 | ||
| @@ -119,26 +103,26 @@ The Proton C only has one on-board LED (C13), and by default, the TXLED (D5) is | |||
| 119 | 103 | ||
| 120 | The following defaults are based on what has been implemented for STM32 boards. | 104 | The following defaults are based on what has been implemented for STM32 boards. |
| 121 | 105 | ||
| 122 | | Feature | Notes | | 106 | | Feature | Notes | |
| 123 | |----------------------------------------------|------------------------------------------------------------------------------------------------------------------| | 107 | |--------------------------------------------|----------------------------------------------------------------------------------------------------------------| |
| 124 | | [Audio](features/audio) | Enabled | | 108 | | [Audio](features/audio) | Enabled | |
| 125 | | [RGB Lighting](features/rgblight) | Disabled | | 109 | | [RGB Lighting](features/rgblight) | Disabled | |
| 126 | | [Backlight](features/backlight) | Forces [task driven PWM](features/backlight#software-pwm-driver) until ARM can provide automatic configuration | | 110 | | [Backlight](features/backlight) | Forces [task driven PWM](features/backlight#software-pwm-driver) until ARM can provide automatic configuration | |
| 127 | | USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) | | 111 | | USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) | |
| 128 | | [Split keyboards](features/split_keyboard) | Partial - heavily dependent on enabled features | | 112 | | [Split keyboards](features/split_keyboard) | Partial - heavily dependent on enabled features | |
| 129 | 113 | ||
| 130 | ### Adafruit KB2040 {#kb2040} | 114 | ### Adafruit KB2040 {#kb2040} |
| 131 | 115 | ||
| 132 | The following defaults are based on what has been implemented for [RP2040](platformdev_rp2040) boards. | 116 | The following defaults are based on what has been implemented for [RP2040](platformdev_rp2040) boards. |
| 133 | 117 | ||
| 134 | | Feature | Notes | | 118 | | Feature | Notes | |
| 135 | |----------------------------------------------|------------------------------------------------------------------------------------------------------------------| | 119 | |--------------------------------------------|----------------------------------------------------------------------------------------------------------------| |
| 136 | | [RGB Lighting](features/rgblight) | Enabled via `PIO` vendor driver | | 120 | | [RGB Lighting](features/rgblight) | Enabled via `PIO` vendor driver | |
| 137 | | [Backlight](features/backlight) | Forces [task driven PWM](features/backlight#software-pwm-driver) until ARM can provide automatic configuration | | 121 | | [Backlight](features/backlight) | Forces [task driven PWM](features/backlight#software-pwm-driver) until ARM can provide automatic configuration | |
| 138 | | USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) | | 122 | | USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) | |
| 139 | | [Split keyboards](features/split_keyboard) | Partial via `PIO` vendor driver - heavily dependent on enabled features | | 123 | | [Split keyboards](features/split_keyboard) | Partial via `PIO` vendor driver - heavily dependent on enabled features | |
| 140 | 124 | ||
| 141 | ### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi {#sparkfun_pm2040 } | 125 | ### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi {#sparkfun_pm2040} |
| 142 | 126 | ||
| 143 | Feature set is identical to [Adafruit KB2040](#kb2040). | 127 | Feature set is identical to [Adafruit KB2040](#kb2040). |
| 144 | 128 | ||
| @@ -177,31 +161,193 @@ Feature set is identical to [Adafruit KB2040](#kb2040). VBUS detection is enable | |||
| 177 | 161 | ||
| 178 | Feature set is a pro micro equivalent of the [RP2040 Community Edition](#rp2040_ce), except that two of the analog GPIO have been replaced with digital only GPIO. These two were moved to the FPC connector to support the [VIK specification](https://github.com/sadekbaroudi/vik). This means that if you are expecting analog support on all 4 pins as provided on a RP2040 Community Edition pinout, you will not have that. Please see the [Svlinky github page](https://github.com/sadekbaroudi/svlinky) for more details. | 162 | Feature set is a pro micro equivalent of the [RP2040 Community Edition](#rp2040_ce), except that two of the analog GPIO have been replaced with digital only GPIO. These two were moved to the FPC connector to support the [VIK specification](https://github.com/sadekbaroudi/vik). This means that if you are expecting analog support on all 4 pins as provided on a RP2040 Community Edition pinout, you will not have that. Please see the [Svlinky github page](https://github.com/sadekbaroudi/svlinky) for more details. |
| 179 | 163 | ||
| 180 | ## Elite-C | 164 | ## Elite-C Converters |
| 181 | |||
| 182 | If a board currently supported in QMK uses an [Elite-C](https://keeb.io/products/elite-c-low-profile-version-usb-c-pro-micro-replacement-atmega32u4), the supported alternative controllers are: | ||
| 183 | 165 | ||
| 184 | | Device | Target | | 166 | If a board currently supported by QMK uses an [Elite-C](https://keeb.io/products/elite-c-low-profile-version-usb-c-pro-micro-replacement-atmega32u4), the supported alternative controllers are: |
| 185 | |----------------------------------------------------------------------------------|-------------------| | ||
| 186 | | [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` | | ||
| 187 | | [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` | | ||
| 188 | | [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` | | ||
| 189 | | [Liatris](https://splitkb.com/products/liatris) | `liatris` | | ||
| 190 | 167 | ||
| 191 | Converter summary: | 168 | | Device | Target | CLI Argument | `rules.mk` | Condition | |
| 169 | |----------------------------------------------------------------------------------|-------------|---------------------------|------------------------|-------------------------------| | ||
| 170 | | [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` | | ||
| 171 | | [RP2040 Community Edition](#rp2040_ce_elite) | `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` | | ||
| 172 | | [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` | | ||
| 173 | | [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` | | ||
| 174 | | [Liatris](https://splitkb.com/products/liatris) | `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` | | ||
| 192 | 175 | ||
| 193 | | Target | Argument | `rules.mk` | Condition | | 176 | ### STeMCell {#stemcell_elite} |
| 194 | |-------------------|---------------------------------|------------------------------|-------------------------------------| | ||
| 195 | | `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` | | ||
| 196 | | `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` | | ||
| 197 | | `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` | | ||
| 198 | | `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` | | ||
| 199 | | `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` | | ||
| 200 | |||
| 201 | ### STeMCell {#stemcell}_elite | ||
| 202 | 177 | ||
| 203 | Identical to [Pro Micro - STeMCell](#stemcell) with support for the additional bottom row of pins. | 178 | Identical to [Pro Micro - STeMCell](#stemcell) with support for the additional bottom row of pins. |
| 204 | 179 | ||
| 205 | ### RP2040 Community Edition {#rp2040_ce_elite} | 180 | ### RP2040 Community Edition {#rp2040_ce_elite} |
| 206 | 181 | ||
| 207 | Identical to [Pro Micro - RP2040 Community Edition](#rp2040_ce) with support for the additional bottom row of pins. | 182 | Identical to [Pro Micro - RP2040 Community Edition](#rp2040_ce) with support for the additional bottom row of pins. |
| 183 | |||
| 184 | ## Advanced Topics | ||
| 185 | |||
| 186 | ### Keyboard Configuration | ||
| 187 | |||
| 188 | To configure a keyboard to allow the converter feature, add the following line to your keyboard's `.json` configuration: | ||
| 189 | |||
| 190 | ```json [keyboard.json] | ||
| 191 | { | ||
| 192 | "maintainer": "QMK", | ||
| 193 | "development_board": "promicro", // [!code focus] | ||
| 194 | "diode_direction": "COL2ROW", | ||
| 195 | } | ||
| 196 | ``` | ||
| 197 | |||
| 198 | See the [pin compatibility](#pin_compatible) for more information. | ||
| 199 | |||
| 200 | #### Additional Requirements {#keyboard-req} | ||
| 201 | |||
| 202 | Keyboards must use the platform agnostic abstractions provided by QMK. This includes: | ||
| 203 | |||
| 204 | * Use of [GPIO Controls](drivers/gpio). | ||
| 205 | |||
| 206 | ### Additional Keymap Configuration {#keymap-add} | ||
| 207 | |||
| 208 | While effort has been made to make converters as compatible as possible, sometimes additional platform specific configuration is required. | ||
| 209 | |||
| 210 | For example, enabling hardware peripherals by adding a keymap level `mcuconf.h` with something like the following: | ||
| 211 | ```c | ||
| 212 | #pragma once | ||
| 213 | |||
| 214 | #include_next <mcuconf.h> | ||
| 215 | |||
| 216 | #undef RP_SIO_USE_UART0 | ||
| 217 | #define RP_SIO_USE_UART0 TRUE | ||
| 218 | ``` | ||
| 219 | |||
| 220 | You can find details on how to configure drivers on their respective pages. | ||
| 221 | |||
| 222 | Alternatively, you may have to disable incompatible features. For example: | ||
| 223 | |||
| 224 | :::::tabs | ||
| 225 | |||
| 226 | ==== keymap.json | ||
| 227 | |||
| 228 | ```json [keymap.json] | ||
| 229 | { | ||
| 230 | "version": 1, | ||
| 231 | "keyboard": "keebio/bdn9/rev1", | ||
| 232 | "keymap": "keebio_bdn9_rev1_layout_2025-05-20", | ||
| 233 | "converter": "proton_c", | ||
| 234 | "config": { // [!code focus] | ||
| 235 | "features": { // [!code focus] | ||
| 236 | "audio": false // [!code focus] | ||
| 237 | } | ||
| 238 | } | ||
| 239 | "layout": "LAYOUT", | ||
| 240 | } | ||
| 241 | ``` | ||
| 242 | |||
| 243 | ==== rules.mk | ||
| 244 | |||
| 245 | ```makefile | ||
| 246 | AUDIO_ENABLE = no | ||
| 247 | ``` | ||
| 248 | |||
| 249 | ::::: | ||
| 250 | |||
| 251 | ### Conditional Configuration | ||
| 252 | |||
| 253 | Once a converter is enabled, it exposes the `CONVERT_TO_<target_uppercase>` flag that you can use in your code with `#ifdef`s, For example: | ||
| 254 | |||
| 255 | ```c | ||
| 256 | #ifdef CONVERT_TO_PROTON_C | ||
| 257 | // Proton C code | ||
| 258 | #else | ||
| 259 | // Pro Micro code | ||
| 260 | #endif | ||
| 261 | ``` | ||
| 262 | |||
| 263 | ### Pin Compatibility {#pin_compatible} | ||
| 264 | |||
| 265 | To ensure compatibility, provide validation, and power future workflows, a keyboard should declare its `pin compatibility`. This ensures that only valid combinations are attempted. | ||
| 266 | |||
| 267 | ::: tip Note | ||
| 268 | This will already be configured for you if are using the `promicro` development board preset. | ||
| 269 | ::: | ||
| 270 | |||
| 271 | To declare the base interface for conversions, add the following line to your keyboard's configuration: | ||
| 272 | |||
| 273 | ```json [keyboard.json] | ||
| 274 | { | ||
| 275 | "maintainer": "QMK", | ||
| 276 | "development_board": "elite_c", // [!code focus] | ||
| 277 | "pin_compatible": "elite_c", // [!code focus] | ||
| 278 | "diode_direction": "COL2ROW", | ||
| 279 | } | ||
| 280 | ``` | ||
| 281 | |||
| 282 | The above example, configures a keyboard for a default of `elite_c` while allowing any of the `elite_c` converter targets. | ||
| 283 | |||
| 284 | The framework then allows mapping of pins from `<PIN_COMPATIBLE>` to converter `<target>`. | ||
| 285 | |||
| 286 | ::: warning | ||
| 287 | Mapped pins should adhere strictly to the defined interface, any extras present on the hardware should be ignored. | ||
| 288 | ::: | ||
| 289 | |||
| 290 | #### Available Pin Compatibility | ||
| 291 | |||
| 292 | :::::tabs | ||
| 293 | |||
| 294 | ==== promicro | ||
| 295 | |||
| 296 |  | ||
| 297 | |||
| 298 | <!-- ```svgbob | ||
| 299 | pins | ||
| 300 | .-------------. LEDs | ||
| 301 | | | _|_ _|_ | ||
| 302 | D3 -+-O | \ /B0 \ /D5 | ||
| 303 | D2 -+-O | -+- -+- | ||
| 304 | | | | | | ||
| 305 | | | | ||
| 306 | D1 -+-O O-+- F4 | ||
| 307 | D0 -+-O O-+- F5 | ||
| 308 | D4 -+-O O-+- F6 | ||
| 309 | C6 -+-O O-+- F7 | ||
| 310 | D7 -+-O O-+- B1 | ||
| 311 | E6 -+-O O-+- B3 | ||
| 312 | B4 -+-O O-+- B2 | ||
| 313 | B5 -+-O O-+- B6 | ||
| 314 | | | | ||
| 315 | '---+-+-+-+-+---' | ||
| 316 | ``` --> | ||
| 317 | |||
| 318 | ::: info Notes: | ||
| 319 | Includes LEDs - these may be mapped to unused/unavailable pins when not present. | ||
| 320 | ::: | ||
| 321 | |||
| 322 | ==== elite_c | ||
| 323 | |||
| 324 |  | ||
| 325 | |||
| 326 | <!-- ```svgbob | ||
| 327 | pins | ||
| 328 | .-------------. | ||
| 329 | | | | ||
| 330 | D3 -+-O | | ||
| 331 | D2 -+-O | | ||
| 332 | | | | ||
| 333 | | | | ||
| 334 | D1 -+-O O-+- F4 | ||
| 335 | D0 -+-O O-+- F5 | ||
| 336 | D4 -+-O O-+- F6 | ||
| 337 | C6 -+-O O-+- F7 | ||
| 338 | D7 -+-O O-+- B1 | ||
| 339 | E6 -+-O O-+- B3 | ||
| 340 | B4 -+-O O-+- B2 | ||
| 341 | B5 -+-O O O O O O O-+- B6 | ||
| 342 | | | | | | | | | ||
| 343 | '---+-+-+-+-+---' | ||
| 344 | + + + + + | ||
| 345 | B D C F F | ||
| 346 | 7 5 7 1 0 | ||
| 347 | ``` --> | ||
| 348 | |||
| 349 | ::: info Notes: | ||
| 350 | Includes bottom row pins, no LEDs. | ||
| 351 | ::: | ||
| 352 | |||
| 353 | ::::: | ||
diff --git a/docs/public/pin_compatible_elite_c.svg b/docs/public/pin_compatible_elite_c.svg new file mode 100644 index 0000000000..cb54d9dfe4 --- /dev/null +++ b/docs/public/pin_compatible_elite_c.svg | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="208" height="352" class="svgbob"><style>.svgbob line, .svgbob path, .svgbob circle, .svgbob rect, .svgbob polygon { | ||
| 2 | stroke: black; | ||
| 3 | stroke-width: 2; | ||
| 4 | stroke-opacity: 1; | ||
| 5 | fill-opacity: 1; | ||
| 6 | stroke-linecap: round; | ||
| 7 | stroke-linejoin: miter; | ||
| 8 | } | ||
| 9 | .svgbob text { | ||
| 10 | white-space: pre; | ||
| 11 | fill: black; | ||
| 12 | font-family: Iosevka Fixed, monospace; | ||
| 13 | font-size: 14px; | ||
| 14 | } | ||
| 15 | .svgbob rect.backdrop { | ||
| 16 | stroke: none; | ||
| 17 | fill: white; | ||
| 18 | } | ||
| 19 | .svgbob .broken { | ||
| 20 | stroke-dasharray: 8; | ||
| 21 | } | ||
| 22 | .svgbob .filled { | ||
| 23 | fill: black; | ||
| 24 | } | ||
| 25 | .svgbob .bg_filled { | ||
| 26 | fill: white; | ||
| 27 | stroke-width: 1; | ||
| 28 | } | ||
| 29 | .svgbob .nofill { | ||
| 30 | fill: white; | ||
| 31 | } | ||
| 32 | .svgbob .end_marked_arrow { | ||
| 33 | marker-end: url(#arrow); | ||
| 34 | } | ||
| 35 | .svgbob .start_marked_arrow { | ||
| 36 | marker-start: url(#arrow); | ||
| 37 | } | ||
| 38 | .svgbob .end_marked_diamond { | ||
| 39 | marker-end: url(#diamond); | ||
| 40 | } | ||
| 41 | .svgbob .start_marked_diamond { | ||
| 42 | marker-start: url(#diamond); | ||
| 43 | } | ||
| 44 | .svgbob .end_marked_circle { | ||
| 45 | marker-end: url(#circle); | ||
| 46 | } | ||
| 47 | .svgbob .start_marked_circle { | ||
| 48 | marker-start: url(#circle); | ||
| 49 | } | ||
| 50 | .svgbob .end_marked_open_circle { | ||
| 51 | marker-end: url(#open_circle); | ||
| 52 | } | ||
| 53 | .svgbob .start_marked_open_circle { | ||
| 54 | marker-start: url(#open_circle); | ||
| 55 | } | ||
| 56 | .svgbob .end_marked_big_open_circle { | ||
| 57 | marker-end: url(#big_open_circle); | ||
| 58 | } | ||
| 59 | .svgbob .start_marked_big_open_circle { | ||
| 60 | marker-start: url(#big_open_circle); | ||
| 61 | }<!--separator--></style><defs><marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><polygon points="0,0 0,4 4,2 0,0"></polygon></marker><marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><polygon points="0,2 2,0 4,2 2,4 0,2"></polygon></marker><marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><circle cx="4" cy="4" r="2" class="filled"></circle></marker><marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><circle cx="4" cy="4" r="2" class="bg_filled"></circle></marker><marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><circle cx="4" cy="4" r="3" class="bg_filled"></circle></marker></defs><rect class="backdrop" x="0" y="0" width="208" height="352"></rect><text x="82" y="28" >pins</text><line x1="24" y1="72" x2="52" y2="72" class="solid end_marked_big_open_circle"></line><line x1="24" y1="88" x2="52" y2="88" class="solid end_marked_big_open_circle"></line><line x1="24" y1="136" x2="52" y2="136" class="solid end_marked_big_open_circle"></line><line x1="160" y1="136" x2="148" y2="136" class="solid end_marked_big_open_circle"></line><line x1="160" y1="136" x2="176" y2="136" class="solid"></line><line x1="24" y1="152" x2="52" y2="152" class="solid end_marked_big_open_circle"></line><line x1="160" y1="152" x2="148" y2="152" class="solid end_marked_big_open_circle"></line><line x1="160" y1="152" x2="176" y2="152" class="solid"></line><line x1="24" y1="168" x2="52" y2="168" class="solid end_marked_big_open_circle"></line><line x1="160" y1="168" x2="148" y2="168" class="solid end_marked_big_open_circle"></line><line x1="160" y1="168" x2="176" y2="168" class="solid"></line><line x1="24" y1="184" x2="52" y2="184" class="solid end_marked_big_open_circle"></line><line x1="160" y1="184" x2="148" y2="184" class="solid end_marked_big_open_circle"></line><line x1="160" y1="184" x2="176" y2="184" class="solid"></line><line x1="24" y1="200" x2="52" y2="200" class="solid end_marked_big_open_circle"></line><line x1="160" y1="200" x2="148" y2="200" class="solid end_marked_big_open_circle"></line><line x1="160" y1="200" x2="176" y2="200" class="solid"></line><line x1="24" y1="216" x2="52" y2="216" class="solid end_marked_big_open_circle"></line><line x1="160" y1="216" x2="148" y2="216" class="solid end_marked_big_open_circle"></line><line x1="160" y1="216" x2="176" y2="216" class="solid"></line><line x1="24" y1="232" x2="52" y2="232" class="solid end_marked_big_open_circle"></line><line x1="160" y1="232" x2="148" y2="232" class="solid end_marked_big_open_circle"></line><line x1="160" y1="232" x2="176" y2="232" class="solid"></line><line x1="24" y1="248" x2="52" y2="248" class="solid end_marked_big_open_circle"></line><line x1="68" y1="252" x2="68" y2="248" class="solid end_marked_big_open_circle"></line><line x1="84" y1="252" x2="84" y2="248" class="solid end_marked_big_open_circle"></line><line x1="100" y1="252" x2="100" y2="248" class="solid end_marked_big_open_circle"></line><line x1="116" y1="252" x2="116" y2="248" class="solid end_marked_big_open_circle"></line><line x1="132" y1="252" x2="132" y2="248" class="solid end_marked_big_open_circle"></line><line x1="160" y1="248" x2="148" y2="248" class="solid end_marked_big_open_circle"></line><line x1="160" y1="248" x2="176" y2="248" class="solid"></line><line x1="68" y1="256" x2="68" y2="296" class="solid"></line><line x1="84" y1="256" x2="84" y2="296" class="solid"></line><line x1="100" y1="256" x2="100" y2="296" class="solid"></line><line x1="116" y1="256" x2="116" y2="296" class="solid"></line><line x1="132" y1="256" x2="132" y2="296" class="solid"></line><text x="66" y="316" >B</text><text x="82" y="316" >D</text><text x="98" y="316" >C</text><text x="114" y="316" >F</text><text x="130" y="316" >F</text><text x="66" y="332" >7</text><text x="82" y="332" >5</text><text x="98" y="332" >7</text><text x="114" y="332" >1</text><text x="130" y="332" >0</text><text x="2" y="76" >D3</text><text x="2" y="92" >D2</text><text x="2" y="140" >D1</text><text x="2" y="156" >D0</text><text x="2" y="172" >D4</text><text x="2" y="188" >C6</text><text x="2" y="204" >D7</text><text x="2" y="220" >E6</text><text x="2" y="236" >B4</text><text x="2" y="252" >B5</text><text x="186" y="140" >F4</text><text x="186" y="156" >F5</text><text x="186" y="172" >F6</text><text x="186" y="188" >F7</text><text x="186" y="204" >B1</text><text x="186" y="220" >B3</text><text x="186" y="236" >B2</text><text x="186" y="252" >B6</text><g><path d="M 44,40 A 8,8 0,0,0 36,48" class="nofill"></path><line x1="44" y1="40" x2="156" y2="40" class="solid"></line><path d="M 156,40 A 8,8 0,0,1 164,48" class="nofill"></path><line x1="36" y1="48" x2="36" y2="276" class="solid"></line><line x1="164" y1="48" x2="164" y2="276" class="solid"></line><path d="M 36,276 A 4,4 0,0,0 40,280" class="nofill"></path><line x1="40" y1="280" x2="160" y2="280" class="solid"></line><path d="M 164,276 A 4,4 0,0,1 160,280" class="nofill"></path></g></svg> \ No newline at end of file | ||
diff --git a/docs/public/pin_compatible_promicro.svg b/docs/public/pin_compatible_promicro.svg new file mode 100644 index 0000000000..044b265a57 --- /dev/null +++ b/docs/public/pin_compatible_promicro.svg | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | <svg xmlns="http://www.w3.org/2000/svg" width="344" height="288" class="svgbob"><style>.svgbob line, .svgbob path, .svgbob circle, .svgbob rect, .svgbob polygon { | ||
| 2 | stroke: black; | ||
| 3 | stroke-width: 2; | ||
| 4 | stroke-opacity: 1; | ||
| 5 | fill-opacity: 1; | ||
| 6 | stroke-linecap: round; | ||
| 7 | stroke-linejoin: miter; | ||
| 8 | } | ||
| 9 | .svgbob text { | ||
| 10 | white-space: pre; | ||
| 11 | fill: black; | ||
| 12 | font-family: Iosevka Fixed, monospace; | ||
| 13 | font-size: 14px; | ||
| 14 | } | ||
| 15 | .svgbob rect.backdrop { | ||
| 16 | stroke: none; | ||
| 17 | fill: white; | ||
| 18 | } | ||
| 19 | .svgbob .broken { | ||
| 20 | stroke-dasharray: 8; | ||
| 21 | } | ||
| 22 | .svgbob .filled { | ||
| 23 | fill: black; | ||
| 24 | } | ||
| 25 | .svgbob .bg_filled { | ||
| 26 | fill: white; | ||
| 27 | stroke-width: 1; | ||
| 28 | } | ||
| 29 | .svgbob .nofill { | ||
| 30 | fill: white; | ||
| 31 | } | ||
| 32 | .svgbob .end_marked_arrow { | ||
| 33 | marker-end: url(#arrow); | ||
| 34 | } | ||
| 35 | .svgbob .start_marked_arrow { | ||
| 36 | marker-start: url(#arrow); | ||
| 37 | } | ||
| 38 | .svgbob .end_marked_diamond { | ||
| 39 | marker-end: url(#diamond); | ||
| 40 | } | ||
| 41 | .svgbob .start_marked_diamond { | ||
| 42 | marker-start: url(#diamond); | ||
| 43 | } | ||
| 44 | .svgbob .end_marked_circle { | ||
| 45 | marker-end: url(#circle); | ||
| 46 | } | ||
| 47 | .svgbob .start_marked_circle { | ||
| 48 | marker-start: url(#circle); | ||
| 49 | } | ||
| 50 | .svgbob .end_marked_open_circle { | ||
| 51 | marker-end: url(#open_circle); | ||
| 52 | } | ||
| 53 | .svgbob .start_marked_open_circle { | ||
| 54 | marker-start: url(#open_circle); | ||
| 55 | } | ||
| 56 | .svgbob .end_marked_big_open_circle { | ||
| 57 | marker-end: url(#big_open_circle); | ||
| 58 | } | ||
| 59 | .svgbob .start_marked_big_open_circle { | ||
| 60 | marker-start: url(#big_open_circle); | ||
| 61 | }<!--separator--></style><defs><marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><polygon points="0,0 0,4 4,2 0,0"></polygon></marker><marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><polygon points="0,2 2,0 4,2 2,4 0,2"></polygon></marker><marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><circle cx="4" cy="4" r="2" class="filled"></circle></marker><marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><circle cx="4" cy="4" r="2" class="bg_filled"></circle></marker><marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><circle cx="4" cy="4" r="3" class="bg_filled"></circle></marker></defs><rect class="backdrop" x="0" y="0" width="344" height="288"></rect><text x="82" y="12" >pins</text><line x1="24" y1="56" x2="52" y2="56" class="solid end_marked_big_open_circle"></line><line x1="24" y1="72" x2="52" y2="72" class="solid end_marked_big_open_circle"></line><line x1="24" y1="120" x2="52" y2="120" class="solid end_marked_big_open_circle"></line><line x1="160" y1="120" x2="148" y2="120" class="solid end_marked_big_open_circle"></line><line x1="160" y1="120" x2="176" y2="120" class="solid"></line><line x1="24" y1="136" x2="52" y2="136" class="solid end_marked_big_open_circle"></line><line x1="160" y1="136" x2="148" y2="136" class="solid end_marked_big_open_circle"></line><line x1="160" y1="136" x2="176" y2="136" class="solid"></line><line x1="24" y1="152" x2="52" y2="152" class="solid end_marked_big_open_circle"></line><line x1="160" y1="152" x2="148" y2="152" class="solid end_marked_big_open_circle"></line><line x1="160" y1="152" x2="176" y2="152" class="solid"></line><line x1="24" y1="168" x2="52" y2="168" class="solid end_marked_big_open_circle"></line><line x1="160" y1="168" x2="148" y2="168" class="solid end_marked_big_open_circle"></line><line x1="160" y1="168" x2="176" y2="168" class="solid"></line><line x1="24" y1="184" x2="52" y2="184" class="solid end_marked_big_open_circle"></line><line x1="160" y1="184" x2="148" y2="184" class="solid end_marked_big_open_circle"></line><line x1="160" y1="184" x2="176" y2="184" class="solid"></line><line x1="24" y1="200" x2="52" y2="200" class="solid end_marked_big_open_circle"></line><line x1="160" y1="200" x2="148" y2="200" class="solid end_marked_big_open_circle"></line><line x1="160" y1="200" x2="176" y2="200" class="solid"></line><line x1="24" y1="216" x2="52" y2="216" class="solid end_marked_big_open_circle"></line><line x1="160" y1="216" x2="148" y2="216" class="solid end_marked_big_open_circle"></line><line x1="160" y1="216" x2="176" y2="216" class="solid"></line><line x1="24" y1="232" x2="52" y2="232" class="solid end_marked_big_open_circle"></line><line x1="160" y1="232" x2="148" y2="232" class="solid end_marked_big_open_circle"></line><line x1="160" y1="232" x2="176" y2="232" class="solid"></line><text x="250" y="28" >LEDs</text><text x="242" y="60" >B0</text><text x="322" y="60" >D5</text><text x="2" y="60" >D3</text><text x="2" y="76" >D2</text><text x="2" y="124" >D1</text><text x="2" y="140" >D0</text><text x="2" y="156" >D4</text><text x="2" y="172" >C6</text><text x="2" y="188" >D7</text><text x="2" y="204" >E6</text><text x="2" y="220" >B4</text><text x="2" y="236" >B5</text><text x="186" y="124" >F4</text><text x="186" y="140" >F5</text><text x="186" y="156" >F6</text><text x="186" y="172" >F7</text><text x="186" y="188" >B1</text><text x="186" y="204" >B3</text><text x="186" y="220" >B2</text><text x="186" y="236" >B6</text><g><path d="M 44,24 A 8,8 0,0,0 36,32" class="nofill"></path><line x1="44" y1="24" x2="156" y2="24" class="solid"></line><path d="M 156,24 A 8,8 0,0,1 164,32" class="nofill"></path><line x1="36" y1="32" x2="36" y2="260" class="solid"></line><line x1="164" y1="32" x2="164" y2="260" class="solid"></line><path d="M 36,260 A 4,4 0,0,0 40,264" class="nofill"></path><line x1="40" y1="264" x2="160" y2="264" class="solid"></line><path d="M 164,260 A 4,4 0,0,1 160,264" class="nofill"></path></g><g><line x1="216" y1="48" x2="240" y2="48" class="solid"></line><line x1="228" y1="32" x2="228" y2="48" class="solid"></line><line x1="216" y1="48" x2="228" y2="72" class="solid"></line><line x1="240" y1="48" x2="228" y2="72" class="solid"></line><line x1="216" y1="72" x2="240" y2="72" class="solid"></line><line x1="228" y1="72" x2="228" y2="96" class="solid"></line></g><g><line x1="296" y1="48" x2="320" y2="48" class="solid"></line><line x1="308" y1="32" x2="308" y2="48" class="solid"></line><line x1="296" y1="48" x2="308" y2="72" class="solid"></line><line x1="320" y1="48" x2="308" y2="72" class="solid"></line><line x1="296" y1="72" x2="320" y2="72" class="solid"></line><line x1="308" y1="72" x2="308" y2="96" class="solid"></line></g></svg> \ No newline at end of file | ||
