Merge branch 'qmk:master' into master

This commit is contained in:
Jacky 2024-08-27 10:10:47 +08:00 committed by GitHub
commit 70ae2a1992
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7159 changed files with 21332 additions and 165930 deletions

View File

@ -1,7 +1,7 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: QMK Discord - name: QMK Discord
url: https://discord.gg/Uq7gcHh url: https://discord.gg/qmk
about: Ask questions, discuss issues and features. Chill. about: Ask questions, discuss issues and features. Chill.
- name: OLKB Subreddit - name: OLKB Subreddit
url: https://www.reddit.com/r/olkb url: https://www.reddit.com/r/olkb

16
.github/labeler.yml vendored
View File

@ -11,15 +11,15 @@ core:
- Makefile - Makefile
- '*.mk' - '*.mk'
dependencies: dependencies:
- all: - changed-files:
- changed-files: - all-globs-to-any-file:
- any-glob-to-any-file: lib/** - lib/**
- all-globs-to-all-files: '!lib/python/**' - '!lib/python/**'
keyboard: keyboard:
- all: - changed-files:
- changed-files: - all-globs-to-any-file:
- any-glob-to-any-file: keyboards/** - keyboards/**
- all-globs-to-all-files: '!keyboards/**/keymaps/**' - '!keyboards/**/keymaps/**'
keymap: keymap:
- changed-files: - changed-files:
- any-glob-to-any-file: - any-glob-to-any-file:

View File

@ -35,7 +35,7 @@ jobs:
- name: Get changed files - name: Get changed files
id: file_changes id: file_changes
uses: tj-actions/changed-files@v44 uses: tj-actions/changed-files@v45
with: with:
use_rest_api: true use_rest_api: true

View File

@ -27,7 +27,7 @@ jobs:
- name: Get changed files - name: Get changed files
id: file_changes id: file_changes
uses: tj-actions/changed-files@v44 uses: tj-actions/changed-files@v45
with: with:
use_rest_api: true use_rest_api: true

1
.gitignore vendored
View File

@ -118,4 +118,5 @@ compile_commands.json
# VIA(L) files that don't belong in QMK repo # VIA(L) files that don't belong in QMK repo
via*.json via*.json
/keyboards/**/keymaps/via/*
/keyboards/**/keymaps/vial/* /keyboards/**/keymaps/vial/*

View File

@ -34,10 +34,13 @@ ifeq ($(strip $(DUMP_CI_METADATA)),yes)
endif endif
# Force expansion # Force expansion
TARGET := $(TARGET) override TARGET := $(TARGET)
ifneq ($(FORCE_LAYOUT),) ifneq ($(FORCE_LAYOUT),)
TARGET := $(TARGET)_$(FORCE_LAYOUT) override TARGET := $(TARGET)_$(FORCE_LAYOUT)
endif
ifneq ($(CONVERT_TO),)
override TARGET := $(TARGET)_$(CONVERT_TO)
endif endif
# Object files and generated keymap directory # Object files and generated keymap directory
@ -58,9 +61,6 @@ ifdef SKIP_GIT
VERSION_H_FLAGS += --skip-git VERSION_H_FLAGS += --skip-git
endif endif
# Generate the board's version.h file.
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(INTERMEDIATE_OUTPUT)/src/version.h)
# Determine which subfolders exist. # Determine which subfolders exist.
KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD) KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD)
KEYBOARD_FOLDER_PATH_2 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_1))) KEYBOARD_FOLDER_PATH_2 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_1)))
@ -212,12 +212,20 @@ $(INTERMEDIATE_OUTPUT)/src/config.h: $(KEYMAP_JSON)
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON)) $(eval CMD=$(QMK_BIN) generate-config-h --quiet --output $(KEYMAP_H) $(KEYMAP_JSON))
@$(BUILD_CMD) @$(BUILD_CMD)
generated-files: $(INTERMEDIATE_OUTPUT)/src/config.h $(INTERMEDIATE_OUTPUT)/src/keymap.c $(INTERMEDIATE_OUTPUT)/src/keymap.h: $(KEYMAP_JSON)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-keymap-h --quiet --output $(INTERMEDIATE_OUTPUT)/src/keymap.h $(KEYMAP_JSON))
@$(BUILD_CMD)
generated-files: $(INTERMEDIATE_OUTPUT)/src/config.h $(INTERMEDIATE_OUTPUT)/src/keymap.c $(INTERMEDIATE_OUTPUT)/src/keymap.h
endif endif
include $(BUILDDEFS_PATH)/converters.mk include $(BUILDDEFS_PATH)/converters.mk
# Generate the board's version.h file.
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(INTERMEDIATE_OUTPUT)/src/version.h)
MCU_ORIG := $(MCU) MCU_ORIG := $(MCU)
include $(wildcard $(PLATFORM_PATH)/*/mcu_selection.mk) include $(wildcard $(PLATFORM_PATH)/*/mcu_selection.mk)

View File

@ -47,7 +47,8 @@ PLATFORM:=TEST
PLATFORM_KEY:=test PLATFORM_KEY:=test
BOOTLOADER_TYPE:=none BOOTLOADER_TYPE:=none
ifeq ($(strip $(DEBUG)), 1) DEBUG ?= 0
ifneq ($(strip $(DEBUG)), 0)
CONSOLE_ENABLE = yes CONSOLE_ENABLE = yes
endif endif

View File

@ -282,18 +282,17 @@ ifneq ($(strip $(WEAR_LEVELING_DRIVER)),none)
endif endif
endif endif
VALID_FLASH_DRIVER_TYPES := spi VALID_FLASH_DRIVER_TYPES := spi custom
FLASH_DRIVER ?= none FLASH_DRIVER ?= none
ifneq ($(strip $(FLASH_DRIVER)), none) ifneq ($(strip $(FLASH_DRIVER)), none)
ifeq ($(filter $(FLASH_DRIVER),$(VALID_FLASH_DRIVER_TYPES)),) ifeq ($(filter $(FLASH_DRIVER),$(VALID_FLASH_DRIVER_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid FLASH_DRIVER,FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid flash driver) $(call CATASTROPHIC_ERROR,Invalid FLASH_DRIVER,FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid flash driver)
else else
OPT_DEFS += -DFLASH_ENABLE OPT_DEFS += -DFLASH_ENABLE -DFLASH_DRIVER -DFLASH_DRIVER_$(strip $(shell echo $(FLASH_DRIVER) | tr '[:lower:]' '[:upper:]'))
COMMON_VPATH += $(DRIVER_PATH)/flash
ifeq ($(strip $(FLASH_DRIVER)),spi) ifeq ($(strip $(FLASH_DRIVER)),spi)
SPI_DRIVER_REQUIRED = yes
OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI
COMMON_VPATH += $(DRIVER_PATH)/flash
SRC += flash_spi.c SRC += flash_spi.c
SPI_DRIVER_REQUIRED = yes
endif endif
endif endif
endif endif

View File

@ -32,9 +32,6 @@ ifneq ($(CONVERT_TO),)
PLATFORM_KEY = $(shell echo $(CONVERTER) | cut -d "/" -f2) PLATFORM_KEY = $(shell echo $(CONVERTER) | cut -d "/" -f2)
# force setting as value can be from environment
override TARGET := $(TARGET)_$(CONVERT_TO)
# Configure any defaults # Configure any defaults
OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]') OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]')
OPT_DEFS += -DCONVERTER_TARGET=\"$(CONVERT_TO)\" OPT_DEFS += -DCONVERTER_TARGET=\"$(CONVERT_TO)\"

View File

@ -0,0 +1,616 @@
{
"aliases": {
/*
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ │ ۱ │ ۲ │ ۳ │ ۴ │ ۵ │ ۶ │ ۷ │ ۸ │ ۹ │ ۰ │ - │ = │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ ض │ ص │ ث │ ق │ ف │ غ │ ع │ ه │ خ │ ح │ ج │ چ │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ ش │ س │ ی │ ب │ ل │ ا │ ت │ ن │ م │ ک │ گ │ \ │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ < │ ظ │ ط │ ز │ ر │ ذ │ د │ پ │ و │ . │ / │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"KC_GRV": {
"key": "FA_ZWJ",
"label": "(zero-width joiner)",
}
"KC_1": {
"key": "FA_1A",
"label": "۱",
}
"KC_2": {
"key": "FA_2A",
"label": "۲",
}
"KC_3": {
"key": "FA_3A",
"label": "۳",
}
"KC_4": {
"key": "FA_4A",
"label": "۴",
}
"KC_5": {
"key": "FA_5A",
"label": "۵",
}
"KC_6": {
"key": "FA_6A",
"label": "۶",
}
"KC_7": {
"key": "FA_7A",
"label": "۷",
}
"KC_8": {
"key": "FA_8A",
"label": "۸",
}
"KC_9": {
"key": "FA_9A",
"label": "۹",
}
"KC_0": {
"key": "FA_0A",
"label": "۰",
}
"KC_MINS": {
"key": "FA_MINS",
"label": "-",
}
"KC_EQL": {
"key": "FA_EQL",
"label": "=",
}
"KC_Q": {
"key": "FA_ZAD",
"label": "ض",
}
"KC_W": {
"key": "FA_SAD",
"label": "ص",
}
"KC_E": {
"key": "FA_SE",
"label": "ث",
}
"KC_R": {
"key": "FA_QAF",
"label": "ق",
}
"KC_T": {
"key": "FA_FE",
"label": "ف",
}
"KC_Y": {
"key": "FA_GHYN",
"label": "غ",
}
"KC_U": {
"key": "FA_EYN",
"label": "ع",
}
"KC_I": {
"key": "FA_HE",
"label": "ه",
}
"KC_O": {
"key": "FA_KHE",
"label": "خ",
}
"KC_P": {
"key": "FA_HEJ",
"label": "ح",
}
"KC_LBRC": {
"key": "FA_JIM",
"label": "ج",
}
"KC_RBRC": {
"key": "FA_CHE",
"label": "چ",
}
"KC_A": {
"key": "FA_SHIN",
"label": "ش",
}
"KC_S": {
"key": "FA_SIN",
"label": "س",
}
"KC_D": {
"key": "FA_YE",
"label": "ی",
}
"KC_F": {
"key": "FA_BE",
"label": "ب",
}
"KC_G": {
"key": "FA_LAM",
"label": "ل",
}
"KC_H": {
"key": "FA_ALEF",
"label": "ا",
}
"KC_J": {
"key": "FA_TE",
"label": "ت",
}
"KC_K": {
"key": "FA_NOON",
"label": "ن",
}
"KC_L": {
"key": "FA_MIM",
"label": "م",
}
"KC_SCLN": {
"key": "FA_KAF",
"label": "ک",
}
"KC_QUOT": {
"key": "FA_GAF",
"label": "گ",
}
"KC_BSLS": {
"key": "FA_BSLS",
"label": "\\",
}
"KC_LT": {
"key": "FA_LT",
"label": "<",
}
"KC_Z": {
"key": "FA_ZA",
"label": "ظ",
}
"KC_X": {
"key": "FA_TA",
"label": "ط",
}
"KC_C": {
"key": "FA_ZE",
"label": "ز",
}
"KC_V": {
"key": "FA_RE",
"label": "ر",
}
"KC_B": {
"key": "FA_ZAL",
"label": "ذ",
}
"KC_N": {
"key": "FA_DAL",
"label": "د",
}
"KC_M": {
"key": "FA_PE",
"label": "پ",
}
"KC_COMM": {
"key": "FA_WAW",
"label": "و",
}
"KC_DOT": {
"key": "FA_DOT",
"label": ".",
}
"KC_SLSH": {
"key": "FA_SLSH",
"label": "/",
}
"KC_SPC": {
"key": "FA_SPC",
"label": " ",
}
/* Shifted symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ ÷ │ ! │ ٬ │ ٫ │ ﷼ │ ٪ │ × │ ، │ * │ ) │ ( │ ـ │ + │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ ْ │ ٌ │ ٍ │ ً │ ُ │ ِ │ َ │ ّ │ ] │ [ │ } │ { │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ ؤ │ ئ │ ي │ إ │ أ │ آ │ ة │ » │ « │ : │ ؛ │ | │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ > │ ك │ ٓ │ ژ │ ٰ │ │ ٔ │ ء │ │ │ ؟ │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"S(FA_ZWJ)": {
"key": "FA_DIV",
"label": "÷",
}
"S(FA_1A)": {
"key": "FA_EXLM",
"label": "!",
}
"S(FA_2A)": {
"key": "FA_THS",
"label": "٬",
}
"S(FA_3A)": {
"key": "FA_DECS",
"label": "٫",
}
"S(FA_4A)": {
"key": "FA_RIAL",
"label": "﷼",
}
"S(FA_5A)": {
"key": "FA_PRCA",
"label": "٪",
}
"S(FA_6A)": {
"key": "FA_MUL",
"label": "×",
}
"S(FA_7A)": {
"key": "FA_COMA",
"label": "،",
}
"S(FA_8A)": {
"key": "FA_ASTR",
"label": "*",
}
"S(FA_9A)": {
"key": "FA_RPRN",
"label": ")",
}
"S(FA_0A)": {
"key": "FA_LPRN",
"label": "(",
}
"S(FA_MINS)": {
"key": "FA_TATW",
"label": "ـ",
}
"S(FA_EQL)": {
"key": "FA_PLUS",
"label": "+",
}
"S(FA_ZAD)": {
"key": "FA_SUK",
"label": "ْ",
}
"S(FA_SAD)": {
"key": "FA_DMTN",
"label": "ٌ",
}
"S(FA_SE)": {
"key": "FA_KSTN",
"label": "ٍ",
}
"S(FA_QAF)": {
"key": "FA_FTHN",
"label": "ً",
}
"S(FA_FE)": {
"key": "FA_DMM",
"label": "ُ",
}
"S(FA_GHYN)": {
"key": "FA_KAS",
"label": "ِ",
}
"S(FA_EYN)": {
"key": "FA_FAT",
"label": "َ",
}
"S(FA_HE)": {
"key": "FA_TSDD",
"label": "",
}
"S(FA_KHE)": {
"key": "FA_RBRC",
"label": "]",
}
"S(FA_HEJ)": {
"key": "FA_LBRC",
"label": "[",
}
"S(FA_JIM)": {
"key": "FA_RCBR",
"label": "}",
}
"S(FA_CHE)": {
"key": "FA_LCBR",
"label": "{",
}
"S(FA_SHIN)": {
"key": "FA_HMZV",
"label": "ؤ",
}
"S(FA_SIN)": {
"key": "FA_HMZY",
"label": "ئ",
}
"S(FA_YE)": {
"key": "FA_YEA",
"label": "ي",
}
"S(FA_BE)": {
"key": "FA_HMZU",
"label": "إ",
}
"S(FA_LAM)": {
"key": "FA_HMZO",
"label": "أ",
}
"S(FA_ALEF)": {
"key": "FA_MALF",
"label": "آ",
}
"S(FA_TE)": {
"key": "FA_TEHM",
"label": "ة",
}
"S(FA_NOON)": {
"key": "FA_RQOT",
"label": "»",
}
"S(FA_MIM)": {
"key": "FA_LQOT",
"label": "«",
}
"S(FA_KAF)": {
"key": "FA_COLN",
"label": ":",
}
"S(FA_GAF)": {
"key": "FA_SCLA",
"label": "؛",
}
"S(FA_LT)": {
"key": "FA_GT",
"label": ">",
}
"S(FA_ZA)": {
"key": "FA_KAFA",
"label": "ك",
}
"S(FA_TA)": {
"key": "FA_MADO",
"label": "ٓ",
}
"S(FA_ZE)": {
"key": "FA_JEH",
"label": "ژ",
}
"S(FA_RE)": {
"key": "FA_SUPA",
"label": "ٰ",
}
"S(FA_ZAL)": {
"key": "FA_ZWNJ",
"label": "(zero-width non-joiner)",
}
"S(FA_DAL)": {
"key": "FA_HMZA",
"label": "ٔ",
}
"S(FA_PE)": {
"key": "FA_HMZ",
"label": "ء",
}
"S(FA_SLSH)": {
"key": "FA_QSA",
"label": "؟",
}
/* AltGr symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ ~ │ ` │ @ │ # │ $ │ % │ ^ │ & │ • │ │ │ _ │ │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ ° │ │ € │ │ │ │ │ │ │ │ │ │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ │ │ ى │ │ │ ٱ │ │ ﴿ │ ; │ " │ │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ | │ │ │ │ ٖ │ │ ٕ │ … │ , │ ' │ ? │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"ALGR(FA_ZWJ)": {
"key": "FA_TILD",
"label": "~",
}
"ALGR(FA_1A)": {
"key": "FA_GRV",
"label": "`",
}
"ALGR(FA_2A)": {
"key": "FA_AT",
"label": "@",
}
"ALGR(FA_3A)": {
"key": "FA_HASH",
"label": "#",
}
"ALGR(FA_4A)": {
"key": "FA_DLR",
"label": "$",
}
"ALGR(FA_5A)": {
"key": "FA_PERC",
"label": "%",
}
"ALGR(FA_6A)": {
"key": "FA_CIRC",
"label": "^",
}
"ALGR(FA_7A)": {
"key": "FA_AMPR",
"label": "&",
}
"ALGR(FA_8A)": {
"key": "FA_BULT",
"label": "•",
}
"ALGR(FA_9A)": {
"key": "FA_LRM",
"label": "(left-to-right mark)",
}
"ALGR(FA_0A)": {
"key": "FA_RLM",
"label": "(right-to-left mark)",
}
"ALGR(FA_MINS)": {
"key": "FA_UNDS",
"label": "_",
}
"ALGR(FA_EQL)": {
"key": "FA_DMNS",
"label": " (dead)",
}
"ALGR(FA_ZAD)": {
"key": "FA_DEG",
"label": "°",
}
"ALGR(FA_SE)": {
"key": "FA_EURO",
"label": "€",
}
"ALGR(FA_HE)": {
"key": "FA_LRO",
"label": "(left-to-right override)",
}
"ALGR(FA_KHE)": {
"key": "FA_RLO",
"label": "(right-to-left override)",
}
"ALGR(FA_HEJ)": {
"key": "FA_PDF",
"label": "(pop directional formatting)",
}
"ALGR(FA_JIM)": {
"key": "FA_LRE",
"label": "(left-to-right embedding)",
}
"ALGR(FA_CHE)": {
"key": "FA_RLE",
"label": "(right-to-left embedding)",
}
"ALGR(FA_YE)": {
"key": "FA_ALFM",
"label": "ى",
}
"ALGR(FA_ALEF)": {
"key": "FA_ALFW",
"label": "ٱ",
}
"ALGR(FA_NOON)": {
"key": "FA_LORP",
"label": "",
}
"ALGR(FA_MIM)": {
"key": "FA_RORP",
"label": "﴿",
}
"ALGR(FA_KAF)": {
"key": "FA_SCLN",
"label": ";",
}
"ALGR(FA_GAF)": {
"key": "FA_DQT",
"label": "\"",
}
"ALGR(FA_BSLS)": {
"key": "FA_MINA",
"label": "-",
}
"ALGR(FA_ZA)": {
"key": "FA_PIPE",
"label": "|",
}
"ALGR(FA_RA)": {
"key": "FA_SUBA",
"label": "ٖ",
}
"ALGR(FA_DAL)": {
"key": "FA_HMZB",
"label": "ء",
}
"ALGR(FA_PE)": {
"key": "FA_ELLP",
"label": "…",
}
"ALGR(FA_WAW)": {
"key": "FA_COMM",
"label": ",",
}
"ALGR(FA_DOT)": {
"key": "FA_QUOT",
"label": "'",
}
"ALGR(FA_SLSH)": {
"key": "FA_QUES",
"label": "?",
}
/* Shift+AltGr symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
* │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ │ │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
* │ │ ¦ │ │ │ │ │ │ │ │ │ │ │ │
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
* │ │ │ │ │ │ │ │ │
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
*/
"S(ALGR(FA_1A))": {
"key": "FA_1",
"label": "1",
}
"S(ALGR(FA_2A))": {
"key": "FA_2",
"label": "2",
}
"S(ALGR(FA_3A))": {
"key": "FA_3",
"label": "3",
}
"S(ALGR(FA_4A))": {
"key": "FA_4",
"label": "4",
}
"S(ALGR(FA_5A))": {
"key": "FA_5",
"label": "5",
}
"S(ALGR(FA_6A))": {
"key": "FA_6",
"label": "6",
}
"S(ALGR(FA_7A))": {
"key": "FA_7",
"label": "7",
}
"S(ALGR(FA_8A))": {
"key": "FA_8",
"label": "8",
}
"S(ALGR(FA_9A))": {
"key": "FA_9",
"label": "9",
}
"S(ALGR(FA_0A))": {
"key": "FA_0",
"label": "0",
}
"S(ALGR(FA_LT))": {
"key": "FA_BRKP",
"label": "¦",
}
"S(ALGR(FA_SPC))": {
"key": "FA_NNBS",
"label": "(narrow non-breaking space)",
}
}
}

View File

@ -0,0 +1,175 @@
{
"keycodes": {
"0x00CD": {
"group": "mouse",
"key": "QK_MOUSE_CURSOR_UP",
"label": "Mouse cursor up",
"aliases": [
"!reset!",
"MS_UP"
]
},
"0x00CE": {
"group": "mouse",
"key": "QK_MOUSE_CURSOR_DOWN",
"label": "Mouse cursor down",
"aliases": [
"!reset!",
"MS_DOWN"
]
},
"0x00CF": {
"group": "mouse",
"key": "QK_MOUSE_CURSOR_LEFT",
"label": "Mouse cursor left",
"aliases": [
"!reset!",
"MS_LEFT"
]
},
"0x00D0": {
"group": "mouse",
"key": "QK_MOUSE_CURSOR_RIGHT",
"label": "Mouse cursor right",
"aliases": [
"!reset!",
"MS_RGHT"
]
},
"0x00D1": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_1",
"label": "Mouse button 1",
"aliases": [
"!reset!",
"MS_BTN1"
]
},
"0x00D2": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_2",
"label": "Mouse button 2",
"aliases": [
"!reset!",
"MS_BTN2"
]
},
"0x00D3": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_3",
"label": "Mouse button 3",
"aliases": [
"!reset!",
"MS_BTN3"
]
},
"0x00D4": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_4",
"label": "Mouse button 4",
"aliases": [
"!reset!",
"MS_BTN4"
]
},
"0x00D5": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_5",
"label": "Mouse button 5",
"aliases": [
"!reset!",
"MS_BTN5"
]
},
"0x00D6": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_6",
"label": "Mouse button 6",
"aliases": [
"!reset!",
"MS_BTN6"
]
},
"0x00D7": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_7",
"label": "Mouse button 7",
"aliases": [
"!reset!",
"MS_BTN7"
]
},
"0x00D8": {
"group": "mouse",
"key": "QK_MOUSE_BUTTON_8",
"label": "Mouse button 8",
"aliases": [
"!reset!",
"MS_BTN8"
]
},
"0x00D9": {
"group": "mouse",
"key": "QK_MOUSE_WHEEL_UP",
"label": "Mouse wheel up",
"aliases": [
"!reset!",
"MS_WHLU"
]
},
"0x00DA": {
"group": "mouse",
"key": "QK_MOUSE_WHEEL_DOWN",
"label": "Mouse wheel down",
"aliases": [
"!reset!",
"MS_WHLD"
]
},
"0x00DB": {
"group": "mouse",
"key": "QK_MOUSE_WHEEL_LEFT",
"label": "Mouse wheel left",
"aliases": [
"!reset!",
"MS_WHLL"
]
},
"0x00DC": {
"group": "mouse",
"key": "QK_MOUSE_WHEEL_RIGHT",
"label": "Mouse wheel right",
"aliases": [
"!reset!",
"MS_WHLR"
]
},
"0x00DD": {
"group": "mouse",
"key": "QK_MOUSE_ACCELERATION_0",
"label": "Set mouse acceleration to 0",
"aliases": [
"!reset!",
"MS_ACL0"
]
},
"0x00DE": {
"group": "mouse",
"key": "QK_MOUSE_ACCELERATION_1",
"label": "Set mouse acceleration to 1",
"aliases": [
"!reset!",
"MS_ACL1"
]
},
"0x00DF": {
"group": "mouse",
"key": "QK_MOUSE_ACCELERATION_2",
"label": "Set mouse acceleration to 2",
"aliases": [
"!reset!",
"MS_ACL2"
]
}
}
}

View File

@ -72,6 +72,11 @@
"LED_KANA_PIN": {"info_key": "indicators.kana"}, "LED_KANA_PIN": {"info_key": "indicators.kana"},
"LED_PIN_ON_STATE": {"info_key": "indicators.on_state", "value_type": "int"}, "LED_PIN_ON_STATE": {"info_key": "indicators.on_state", "value_type": "int"},
// Joystick
"JOYSTICK_AXIS_COUNT": {"info_key": "joystick.axis_count", "value_type": "int"},
"JOYSTICK_AXIS_RESOLUTION": {"info_key": "joystick.axis_resolution", "value_type": "int"},
"JOYSTICK_BUTTON_COUNT": {"info_key": "joystick.button_count", "value_type": "int"},
// Leader Key // Leader Key
"LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "flag"}, "LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "flag"},
"LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "flag"}, "LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "flag"},
@ -171,7 +176,7 @@
"SECURE_UNLOCK_TIMEOUT": {"info_key": "secure.unlock_timeout", "value_type": "int"}, "SECURE_UNLOCK_TIMEOUT": {"info_key": "secure.unlock_timeout", "value_type": "int"},
// Split Keyboard // Split Keyboard
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"}, "SOFT_SERIAL_PIN": {"info_key": "split.serial.pin"},
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"}, "SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
"SPLIT_HAND_MATRIX_GRID": {"info_key": "split.handedness.matrix_grid", "value_type": "array", "to_c": false}, "SPLIT_HAND_MATRIX_GRID": {"info_key": "split.handedness.matrix_grid", "value_type": "array", "to_c": false},
"SPLIT_HAND_PIN": {"info_key": "split.handedness.pin"}, "SPLIT_HAND_PIN": {"info_key": "split.handedness.pin"},

View File

@ -25,6 +25,8 @@
"ENCODER_DRIVER": {"info_key": "encoder.driver"}, "ENCODER_DRIVER": {"info_key": "encoder.driver"},
"FIRMWARE_FORMAT": {"info_key": "build.firmware_format"}, "FIRMWARE_FORMAT": {"info_key": "build.firmware_format"},
"HAPTIC_DRIVER": {"info_key": "haptic.driver"}, "HAPTIC_DRIVER": {"info_key": "haptic.driver"},
"JOYSTICK_DRIVER": {"info_key": "joystick.driver"},
"JOYSTICK_ENABLE": {"info_key": "joystick.enabled", "value_type": "bool"},
"KEYBOARD_SHARED_EP": {"info_key": "usb.shared_endpoint.keyboard", "value_type": "bool"}, "KEYBOARD_SHARED_EP": {"info_key": "usb.shared_endpoint.keyboard", "value_type": "bool"},
"LAYOUTS": {"info_key": "community_layouts", "value_type": "list"}, "LAYOUTS": {"info_key": "community_layouts", "value_type": "list"},
"LED_MATRIX_DRIVER": {"info_key": "led_matrix.driver"}, "LED_MATRIX_DRIVER": {"info_key": "led_matrix.driver"},
@ -41,6 +43,7 @@
"RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"}, "RGB_MATRIX_DRIVER": {"info_key": "rgb_matrix.driver"},
"RGBLIGHT_DRIVER": {"info_key": "rgblight.driver"}, "RGBLIGHT_DRIVER": {"info_key": "rgblight.driver"},
"SECURE_ENABLE": {"info_key": "secure.enabled", "value_type": "bool"}, "SECURE_ENABLE": {"info_key": "secure.enabled", "value_type": "bool"},
"SERIAL_DRIVER": {"info_key": "split.serial.driver"},
"SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"}, "SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"},
"SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false}, "SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false},
"STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"}, "STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"},

View File

@ -563,6 +563,15 @@
"plain60": { "plain60": {
"target": "evyd13/plain60" "target": "evyd13/plain60"
}, },
"planck/ez": {
"target": "zsa/planck_ez/base"
},
"planck/ez/base": {
"target": "zsa/planck_ez/base"
},
"planck/ez/glow": {
"target": "zsa/planck_ez/glow"
},
"ploopyco/trackball": { "ploopyco/trackball": {
"target": "ploopyco/trackball/rev1_005" "target": "ploopyco/trackball/rev1_005"
}, },
@ -1060,7 +1069,7 @@
"target": "lyso1/lefishe" "target": "lyso1/lefishe"
}, },
"lets_split_eh/eh": { "lets_split_eh/eh": {
"target": "maple_computing/lets_split_eh/eh" "target": "maple_computing/lets_split_eh"
}, },
"ls_60": { "ls_60": {
"target": "weirdo/ls_60" "target": "weirdo/ls_60"
@ -1080,6 +1089,9 @@
"macro1": { "macro1": {
"target": "laneware/macro1" "target": "laneware/macro1"
}, },
"maple_computing/lets_split_eh/eh": {
"target": "maple_computing/lets_split_eh"
},
"massdrop/thekey": { "massdrop/thekey": {
"target": "drop/thekey/v1" "target": "drop/thekey/v1"
}, },
@ -1137,6 +1149,12 @@
"mt980": { "mt980": {
"target": "mt/mt980" "target": "mt/mt980"
}, },
"mt/ncr80/hotswap": {
"target": "mt/ncr80/r2/hotswap"
},
"mt/ncr80/solder": {
"target": "mt/ncr80/r2/solder"
},
"nafuda": { "nafuda": {
"target": "salicylic_acid3/nafuda" "target": "salicylic_acid3/nafuda"
}, },
@ -1525,5 +1543,8 @@
}, },
"kprepublic/jj50": { "kprepublic/jj50": {
"target": "kprepublic/jj50/rev1" "target": "kprepublic/jj50/rev1"
},
"dnworks/9973": {
"target": "dnworks/tkl87"
} }
} }

View File

@ -16,12 +16,6 @@
"type": "object", "type": "object",
"additionalProperties": {"type": "boolean"} "additionalProperties": {"type": "boolean"}
}, },
"build_target": {
"oneOf": [
{"$ref": "#/keyboard_keymap_tuple"},
{"$ref": "#/json_file_path"}
]
},
"filename": { "filename": {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
@ -53,6 +47,19 @@
{"$ref": "#/keyboard"}, {"$ref": "#/keyboard"},
{"$ref": "#/filename"} {"$ref": "#/filename"}
], ],
"minItems": 2,
"maxItems": 2,
"unevaluatedItems": false
},
"keyboard_keymap_env": {
"type": "array",
"prefixItems": [
{"$ref": "#/keyboard"},
{"$ref": "#/filename"},
{"$ref": "#/kvp_object"}
],
"minItems": 3,
"maxItems": 3,
"unevaluatedItems": false "unevaluatedItems": false
}, },
"keycode": { "keycode": {
@ -87,6 +94,10 @@
"maxLength": 7, "maxLength": 7,
"pattern": "^[A-Z][A-Zs_0-9]*$" "pattern": "^[A-Z][A-Zs_0-9]*$"
}, },
"kvp_object": {
"type": "object",
"additionalProperties": {"type": "string"}
},
"layout_macro": { "layout_macro": {
"oneOf": [ "oneOf": [
{ {

View File

@ -1 +0,0 @@
false

View File

@ -342,6 +342,36 @@
"on_state": {"$ref": "qmk.definitions.v1#/bit"} "on_state": {"$ref": "qmk.definitions.v1#/bit"}
} }
}, },
"joystick": {
"type": "object",
"properties": {
"enabled": {"type": "boolean"},
"driver": {"type": "string"},
"button_count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"axis_resolution": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"axes": {
"type": "object",
"propertyNames": {"enum": ["x", "y", "z", "rx", "ry", "rz"]}
"additionalProperties": {
"oneOf": [
{
"type": "object",
"properties": {
"input_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"low": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"rest": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"high": {"$ref": "qmk.definitions.v1#/unsigned_int"}
}
},
{
"type": "string",
"enum": ["virtual"]
}
]
}
}
}
},
"keycodes": {"$ref": "qmk.definitions.v1#/keycode_decl_array"}, "keycodes": {"$ref": "qmk.definitions.v1#/keycode_decl_array"},
"layout_aliases": { "layout_aliases": {
"type": "object", "type": "object",
@ -793,12 +823,26 @@
} }
} }
}, },
"soft_serial_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}, "soft_serial_pin": {
"$ref": "qmk.definitions.v1#/mcu_pin",
"$comment": "Deprecated: use split.serial.pin instead"
},
"soft_serial_speed": { "soft_serial_speed": {
"type": "integer", "type": "integer",
"minimum": 0, "minimum": 0,
"maximum": 5 "maximum": 5
}, },
"serial": {
"type": "object",
"additionalProperties": false,
"properties": {
"driver": {
"type": "string",
"enum": ["bitbang", "usart", "vendor"]
},
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
}
},
"transport": { "transport": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,

View File

@ -1 +0,0 @@
true

View File

@ -3,6 +3,14 @@
"$id": "qmk.user_repo.v1", "$id": "qmk.user_repo.v1",
"title": "User Repository Information", "title": "User Repository Information",
"type": "object", "type": "object",
"definitions": {
"build_target": {
"oneOf": [
{"$ref": "qmk.definitions.v1#/keyboard_keymap_tuple"},
{"$ref": "qmk.definitions.v1#/json_file_path"}
]
},
},
"required": [ "required": [
"userspace_version", "userspace_version",
"build_targets" "build_targets"
@ -15,7 +23,7 @@
"build_targets": { "build_targets": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "qmk.definitions.v1#/build_target" "$ref": "#/definitions/build_target"
} }
} }
} }

View File

@ -0,0 +1,31 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema#",
"$id": "qmk.user_repo.v1_1",
"title": "User Repository Information",
"type": "object",
"definitions": {
"build_target": {
"oneOf": [
{"$ref": "qmk.definitions.v1#/keyboard_keymap_tuple"},
{"$ref": "qmk.definitions.v1#/keyboard_keymap_env"},
{"$ref": "qmk.definitions.v1#/json_file_path"}
]
},
},
"required": [
"userspace_version",
"build_targets"
],
"properties": {
"userspace_version": {
"type": "string",
"enum": ["1.1"]
},
"build_targets": {
"type": "array",
"items": {
"$ref": "#/definitions/build_target"
}
}
}
}

198
docs/ChangeLog/20240825.md Normal file
View File

@ -0,0 +1,198 @@
# QMK Breaking Changes - 2024 August 25 Changelog
## Notable Features
August 2024 brings another maintenance release of QMK. Almost all PRs this cycle were to do with cleanup or re-organization of existing features and code.
One key item is that there are no longer any `via`-enabled keymaps in the QMK repository -- these have all transitioned to an [External Userspace](../newbs_external_userspace) repository under the VIA team's control. Going forward, all PRs to `qmk_firmware` must not contain `via` keymaps; these should instead be redirected to the [VIA QMK Userspace](https://github.com/the-via/qmk_userspace_via) repository.
## Changes Requiring User Action
### Updated Keyboard Codebases
One note with updated keyboard names -- historical keyboard names are still considered valid when using [External Userspace](../newbs_external_userspace) for builds. If you're already using External Userspace, you do not need to move your keymap inside your repository.
| Old Keyboard Name | New Keyboard Name |
|----------------------------------|-------------------------------|
| dnworks/9973 | dnworks/tkl87 |
| maple_computing/lets_split_eh/eh | maple_computing/lets_split_eh |
| planck/ez/base | zsa/planck_ez/base |
### SparkFun Pro Micro RP2040 converter renamed ([#24192](https://github.com/qmk/qmk_firmware/pull/24192))
The converter for the SparkFun Pro Micro RP2040 has been renamed.
| Old | New |
|-------------------|-------------------|
| `promicro_rp2040` | `sparkfun_rp2040` |
This change was made to avoid confusion between the clones named ProMicro RP2040 and the SparkFun Pro Micro RP2040. The clones should be using the `rp2040_ce` option.
### Key Override `keymap.c` signature change ([#24120](https://github.com/qmk/qmk_firmware/pull/24120))
Changes were made to key overrides in order to hook them into the keymap introspection system.
If you're using key overrides, your `keymap.c` will need a change to the signature of your list of key overrides, as well as removing the `NULL` terminator.
For example, you'll need to change existing code from (note the highlighted lines):
```c{1,4-5}
const key_override_t **key_overrides = (const key_override_t *[]){
&my_override_1,
&my_override_2,
NULL
};
```
to:
```c{1,4}
const key_override_t *key_overrides[] = {
&my_override_1,
&my_override_2,
};
```
### ADNS9800 and PMW33xx firmware upload now opt-in ([#24001](https://github.com/qmk/qmk_firmware/pull/24001))
Due to ambiguity with licensing compatibility, QMK has made the firmware ROM uploads for the ADNS9800 and PMW33xx lines of pointing device sensors temporarily opt-in with the view to removing them. Historically they were included by default, but as of this PR this is now no longer the case.
Please get in touch with the QMK team if your sensor no longer functions without the firmware upload -- so far we've tested each device type and they still seem to function without a new firmware, but this has not been a 100% exhaustive validation.
To re-enable firmware upload for your own builds, add the following to your keymap's `config.h`:
| Sensor | Define |
|----------|--------------------------------|
| ADNS9800 | `#define ADNS9800_UPLOAD_SROM` |
| PMW33xx | `#define PMW33XX_UPLOAD_SROM` |
:::info Note
If no issues arise during this current breaking changes cycle, these sensor firmware ROMs will be removed from QMK entirely.
:::
## Deprecation Notices
In line with the [notice period](../support_deprecation_policy#how-much-advance-notice-will-be-given), deprecation notices for larger items are listed here.
### Migration of VIA keymaps to VIA team control
Last breaking changes cycle, the QMK team informed that [`via` keymaps are moving](./20240526#migration-of-via-keymaps-to-via-team-control) to the control of the VIA team. As of this merge, any `via`-enabled keymaps should now be PR'ed to the [VIA QMK Userspace](https://github.com/the-via/qmk_userspace_via) repository.
Any existing or newly-opened PRs against `qmk_firmware` will now be asked to remove any `via`-enabled keymaps from their submissions.
### ADNS9800 and PMW33xx sensor firmware ROM removal
As mentioned above, there's license compatibility issues between QMK and the firmware blobs historically uploaded for the ADNS9800 and PMW33xx sensors. This notice is to inform users that these firmware blobs will almost certainly be removed from QMK in the next breaking changes merge.
As previously noted this does not seem to have any detrimental effect to any of those devices, as they seem to include firmware on-chip without requiring one to be uploaded. Please get in touch with the QMK team on Discord if your sensor is no longer functional.
## Full changelist
Core:
* EEPROM: Don't erase if we don't have to. Adding eeprom_driver_format abstraction. ([#18332](https://github.com/qmk/qmk_firmware/pull/18332))
* Generate keymap dd keycodes to header ([#20273](https://github.com/qmk/qmk_firmware/pull/20273))
* [wear_leveling] efl updates ([#22489](https://github.com/qmk/qmk_firmware/pull/22489))
* GC9xxx LCD family drivers (GC9107 and GC9A01) ([#23091](https://github.com/qmk/qmk_firmware/pull/23091))
* [build_test] set CONSOLE_ENABLE=yes if DEBUG > 0 ([#23097](https://github.com/qmk/qmk_firmware/pull/23097))
* Enhance overlapping mouse keys control ([#23341](https://github.com/qmk/qmk_firmware/pull/23341))
* APA102: API rework ([#23355](https://github.com/qmk/qmk_firmware/pull/23355))
* [WIP] Adds bus acquire/release semantics to SPI start/stop. ([#23439](https://github.com/qmk/qmk_firmware/pull/23439))
* add farsi keymap extras ([#23650](https://github.com/qmk/qmk_firmware/pull/23650))
* Update atomic GPIO macros in keyboard custom matrix ([#23796](https://github.com/qmk/qmk_firmware/pull/23796))
* Check LED flags for Pixel Fractal effect ([#23881](https://github.com/qmk/qmk_firmware/pull/23881))
* Add STM32F405RG ld script for tinyuf2 ([#23885](https://github.com/qmk/qmk_firmware/pull/23885))
* SPI flash API cleanup, add async erase capability. ([#23894](https://github.com/qmk/qmk_firmware/pull/23894))
* Add process_keycode handlers for new RGB Matrix and Underglow keycodes ([#23896](https://github.com/qmk/qmk_firmware/pull/23896))
* Decouple VIA from STM32 L0/L1 EEPROM implementation ([#23901](https://github.com/qmk/qmk_firmware/pull/23901))
* Normalise mouse keycodes ([#23975](https://github.com/qmk/qmk_firmware/pull/23975))
* Remove deprecated `led_set_user` ([#23979](https://github.com/qmk/qmk_firmware/pull/23979))
* Change ADNS9800 and PMW33XX SROM uploads to opt in. ([#24001](https://github.com/qmk/qmk_firmware/pull/24001))
* Rename encoder pins defines ([#24003](https://github.com/qmk/qmk_firmware/pull/24003))
* Change suspend condition check order on ChibiOS ([#24020](https://github.com/qmk/qmk_firmware/pull/24020))
* Tap dance introspection ([#24049](https://github.com/qmk/qmk_firmware/pull/24049))
* Allow overriding `get_hardware_id()`. ([#24051](https://github.com/qmk/qmk_firmware/pull/24051))
* Align LUFA suspend logic ([#24055](https://github.com/qmk/qmk_firmware/pull/24055))
* Add support for key override introspection. ([#24120](https://github.com/qmk/qmk_firmware/pull/24120))
* Dynamic macro callbacks ([#24142](https://github.com/qmk/qmk_firmware/pull/24142))
* Rename promicro_rp2040 converter to sparkfun_pm2040 ([#24192](https://github.com/qmk/qmk_firmware/pull/24192))
* Refactor starlight RGB matrix effects ([#24202](https://github.com/qmk/qmk_firmware/pull/24202))
* Refactor riverflow RGB matrix loop ([#24203](https://github.com/qmk/qmk_firmware/pull/24203))
CLI:
* Remove handling of keyboard level keymap templates ([#24234](https://github.com/qmk/qmk_firmware/pull/24234))
* Small tweaks to keymap generation ([#24240](https://github.com/qmk/qmk_firmware/pull/24240))
Keyboards:
* refactor: keyboard/ncr80/r2 ([#22670](https://github.com/qmk/qmk_firmware/pull/22670))
* Implement data driven joysticks ([#22947](https://github.com/qmk/qmk_firmware/pull/22947))
* Whitefacemountain Ampersand ([#23437](https://github.com/qmk/qmk_firmware/pull/23437))
* Add TRKeyboard TRK1 keyboard ([#23642](https://github.com/qmk/qmk_firmware/pull/23642))
* Rename dnworks/9973 to dnworks/tkl87 ([#23692](https://github.com/qmk/qmk_firmware/pull/23692))
* Update Underglow keycodes ([#23765](https://github.com/qmk/qmk_firmware/pull/23765))
* Add boardsource/the_q ([#23782](https://github.com/qmk/qmk_firmware/pull/23782))
* BastardKB: remove legacy board `tbk` ([#23818](https://github.com/qmk/qmk_firmware/pull/23818))
* Update ZSA Moonlander ([#23911](https://github.com/qmk/qmk_firmware/pull/23911))
* Move Planck EZ to ZSA vendor folder ([#23917](https://github.com/qmk/qmk_firmware/pull/23917))
* Migrate SPLIT_HAND_PIN to json ([#23924](https://github.com/qmk/qmk_firmware/pull/23924))
* Migrate SERIAL_DRIVER to json ([#23925](https://github.com/qmk/qmk_firmware/pull/23925))
* Migrate RGB Matrix layout for two boards ([#23963](https://github.com/qmk/qmk_firmware/pull/23963))
* Migrate `led_update_kb` implementations to DD ([#23980](https://github.com/qmk/qmk_firmware/pull/23980))
* Migrate `led_update_kb` implementations to DD ([#23981](https://github.com/qmk/qmk_firmware/pull/23981))
* Migrate `led_update_kb` implementations to DD ([#23983](https://github.com/qmk/qmk_firmware/pull/23983))
* Migrate `led_update_kb` implementations to DD ([#23985](https://github.com/qmk/qmk_firmware/pull/23985))
* Relocate m256wh VIA logic ([#24006](https://github.com/qmk/qmk_firmware/pull/24006))
* Relocate winry315 VIA logic ([#24008](https://github.com/qmk/qmk_firmware/pull/24008))
* Relocate m256ws VIA logic ([#24009](https://github.com/qmk/qmk_firmware/pull/24009))
* `atreus`: misc cleanups ([#24010](https://github.com/qmk/qmk_firmware/pull/24010))
* Relocate work_louder VIA logic ([#24011](https://github.com/qmk/qmk_firmware/pull/24011))
* Relocate xelus/pachi/rgb/rev2 VIA logic ([#24016](https://github.com/qmk/qmk_firmware/pull/24016))
* Remove custom keycodes from nullbitsco/snap ([#24017](https://github.com/qmk/qmk_firmware/pull/24017))
* added bear_face/v3 ([#24032](https://github.com/qmk/qmk_firmware/pull/24032))
* Remove DEFAULT_FOLDER from maple_computing/lets_split_eh ([#24054](https://github.com/qmk/qmk_firmware/pull/24054))
* refactor bear_face/v1, v2 ([#24060](https://github.com/qmk/qmk_firmware/pull/24060))
* Convert `eeconfig_init_kb` implementations to config ([#24087](https://github.com/qmk/qmk_firmware/pull/24087))
* Remove broken keymap from keebio/iris ([#24094](https://github.com/qmk/qmk_firmware/pull/24094))
* Move LED Matrix LED config to data driven ([#24122](https://github.com/qmk/qmk_firmware/pull/24122))
* Move split.soft_serial_pin to split.serial.pin ([#24127](https://github.com/qmk/qmk_firmware/pull/24127))
* Remove pointless `RGB_MATRIX_LED_COUNT`s ([#24133](https://github.com/qmk/qmk_firmware/pull/24133))
* `hs60/v1`: separate into ANSI and ISO revisions ([#24136](https://github.com/qmk/qmk_firmware/pull/24136))
* Migrate half-duplex `SERIAL_USART_TX_PIN` to DD ([#24143](https://github.com/qmk/qmk_firmware/pull/24143))
* Migrate split.soft_serial_pin to split.serial.pin O-Z ([#24146](https://github.com/qmk/qmk_firmware/pull/24146))
* Migrate split.soft_serial_pin to split.serial.pin 0-H ([#24155](https://github.com/qmk/qmk_firmware/pull/24155))
* Remove instances of MASTER_LEFT. ([#24163](https://github.com/qmk/qmk_firmware/pull/24163))
* Rename EC Type-K ([#24180](https://github.com/qmk/qmk_firmware/pull/24180))
* Migrate split.soft_serial_pin to split.serial.pin H-O ([#24185](https://github.com/qmk/qmk_firmware/pull/24185))
* Remove split.transport.protocol=serial ([#24191](https://github.com/qmk/qmk_firmware/pull/24191))
* Refactor use of `matrix_scan_kb` ([#24200](https://github.com/qmk/qmk_firmware/pull/24200))
* Eliminate use of `#include "../default/keymap.c"`. ([#24215](https://github.com/qmk/qmk_firmware/pull/24215))
* Remove keyboard level `QK_BOOT` implementations ([#24231](https://github.com/qmk/qmk_firmware/pull/24231))
* Remove `handwired/pytest/has_template` ([#24232](https://github.com/qmk/qmk_firmware/pull/24232))
* Refactor opendeck/32 ([#24233](https://github.com/qmk/qmk_firmware/pull/24233))
* Refactor printedpad ([#24236](https://github.com/qmk/qmk_firmware/pull/24236))
* Refactor orthocode ([#24237](https://github.com/qmk/qmk_firmware/pull/24237))
* Remove unnecessary RGB Matrix shutdown hooks ([#24238](https://github.com/qmk/qmk_firmware/pull/24238))
* Remove all via-enabled keymaps, including `via`. ([#24322](https://github.com/qmk/qmk_firmware/pull/24322))
Keyboard fixes:
* Fix dogtag/info.json ([#23520](https://github.com/qmk/qmk_firmware/pull/23520))
* splitkb/kyria: remove `CONVERT_TO` at keyboard level ([#23857](https://github.com/qmk/qmk_firmware/pull/23857))
* Fixup mt/mt84 ([#23883](https://github.com/qmk/qmk_firmware/pull/23883))
* Fix for encoders and support ENCODER_MAP_ENABLE on Planck rev7 ([#23967](https://github.com/qmk/qmk_firmware/pull/23967))
* `handwired/swiftrax/bumblebee`: fix layout name ([#24064](https://github.com/qmk/qmk_firmware/pull/24064))
* Fixup boardsource/the_q RGB matrix coordinates ([#24086](https://github.com/qmk/qmk_firmware/pull/24086))
* Various fixes for keyboards not implementing callbacks correctly ([#24092](https://github.com/qmk/qmk_firmware/pull/24092))
* Various fixes for keyboards not implementing callbacks correctly ([#24116](https://github.com/qmk/qmk_firmware/pull/24116))
* Remove duplicate calls to `housekeeping_task_user` ([#24201](https://github.com/qmk/qmk_firmware/pull/24201))
* Fixup `handwired/dactyl_minidox` ([#24253](https://github.com/qmk/qmk_firmware/pull/24253))
* Fix build failure on zsa/moonlander with DYNAMIC_MACRO_ENABLE ([#24316](https://github.com/qmk/qmk_firmware/pull/24316))
Others:
* LED drivers: extract documentation from LED/RGB Matrix pages ([#23630](https://github.com/qmk/qmk_firmware/pull/23630))
* Implement data driven serial driver ([#23923](https://github.com/qmk/qmk_firmware/pull/23923))
* Remove skipped schema files ([#23987](https://github.com/qmk/qmk_firmware/pull/23987))
* Update RGBLight (Underglow) keycode names ([#23999](https://github.com/qmk/qmk_firmware/pull/23999))
Bugs:
* Fix NKRO and Mouse Emulation on arm_atsam ([#23945](https://github.com/qmk/qmk_firmware/pull/23945))
* Force `dump_lines()` to always use Unix line endings ([#23954](https://github.com/qmk/qmk_firmware/pull/23954))
* Fixup home link. ([#24068](https://github.com/qmk/qmk_firmware/pull/24068))

View File

@ -204,7 +204,7 @@
{ "text": "My Pull Request Was Flagged", "link": "/breaking_changes_instructions" }, { "text": "My Pull Request Was Flagged", "link": "/breaking_changes_instructions" },
{ {
"text": "Most Recent ChangeLog", "text": "Most Recent ChangeLog",
"link": "/ChangeLog/20240526" "link": "/ChangeLog/20240825"
}, },
{ "text": "Past Breaking Changes", "link": "/breaking_changes_history" }, { "text": "Past Breaking Changes", "link": "/breaking_changes_history" },
{ "text": "Deprecation Policy", "link": "/support_deprecation_policy" } { "text": "Deprecation Policy", "link": "/support_deprecation_policy" }

View File

@ -10,25 +10,25 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
## What has been included in past Breaking Changes? ## What has been included in past Breaking Changes?
* [2024 Aug 25](ChangeLog/20240825)
* [2024 May 26](ChangeLog/20240526) * [2024 May 26](ChangeLog/20240526)
* [2024 Feb 25](ChangeLog/20240225) * [2024 Feb 25](ChangeLog/20240225)
* [2023 Nov 26](ChangeLog/20231126)
* [Older Breaking Changes](breaking_changes_history) * [Older Breaking Changes](breaking_changes_history)
## When is the next Breaking Change? ## When is the next Breaking Change?
The next Breaking Change is scheduled for August 25, 2024. The next Breaking Change is scheduled for November 24, 2024.
### Important Dates ### Important Dates
* 2024 May 26 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions. * 2024 Aug 25 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2024 Jul 28 - `develop` closed to new PRs. * 2024 Oct 27 - `develop` closed to new PRs.
* 2024 Jul 28 - Call for testers. * 2024 Oct 27 - Call for testers.
* 2024 Aug 4 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes * 2024 Nov 10 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2024 Aug 18 - `develop` is locked, only critical bugfix PRs merged. * 2024 Nov 17 - `develop` is locked, only critical bugfix PRs merged.
* 2024 Aug 22 - `master` is locked, no PRs merged. * 2024 Nov 22 - `master` is locked, no PRs merged.
* 2024 Aug 25 - Merge `develop` to `master`. * 2024 Nov 24 - Merge `develop` to `master`.
* 2024 Aug 25 - `master` is unlocked. PRs can be merged again. * 2024 Nov 24 - `master` is unlocked. PRs can be merged again.
## What changes will be included? ## What changes will be included?
@ -48,7 +48,7 @@ Criteria for acceptance:
Strongly suggested: Strongly suggested:
* The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20240526`. * The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20241124`.
* This should be in Markdown format, with a name in the format `PR12345.md`, substituting the digits for your PRs ID. * This should be in Markdown format, with a name in the format `PR12345.md`, substituting the digits for your PRs ID.
* One strong recommendation that the ChangeLog document matches the PR description on GitHub, so as to ensure traceability. * One strong recommendation that the ChangeLog document matches the PR description on GitHub, so as to ensure traceability.

View File

@ -2,6 +2,7 @@
This page links to all previous changelogs from the QMK Breaking Changes process. This page links to all previous changelogs from the QMK Breaking Changes process.
* [2024 Aug 25](ChangeLog/20240825) - version 0.26.0
* [2024 May 26](ChangeLog/20240526) - version 0.25.0 * [2024 May 26](ChangeLog/20240526) - version 0.25.0
* [2024 Feb 25](ChangeLog/20240225) - version 0.24.0 * [2024 Feb 25](ChangeLog/20240225) - version 0.24.0
* [2023 Nov 26](ChangeLog/20231126) - version 0.23.0 * [2023 Nov 26](ChangeLog/20231126) - version 0.23.0

View File

@ -31,4 +31,4 @@ Commenting on your pull request and being responsive to questions, comments, and
### Ask for Help ### Ask for Help
Having your submission flagged may have caught you off guard. If you find yourself intimidated or overwhelmed, let us know. Comment on your pull request, or [reach out to the QMK team on Discord](https://discord.gg/Uq7gcHh). Having your submission flagged may have caught you off guard. If you find yourself intimidated or overwhelmed, let us know. Comment on your pull request, or [reach out to the QMK team on Discord](https://discord.gg/qmk).

View File

@ -11,7 +11,7 @@ Third-party contributions help us grow and improve QMK. We want to make the pull
## I Don't Want to Read This Whole Thing! I Just Have a Question! ## I Don't Want to Read This Whole Thing! I Just Have a Question!
If you'd like to ask questions about QMK you can do so on the [OLKB Subreddit](https://reddit.com/r/olkb) or on [Discord](https://discord.gg/Uq7gcHh). If you'd like to ask questions about QMK you can do so on the [OLKB Subreddit](https://reddit.com/r/olkb) or on [Discord](https://discord.gg/qmk).
Please keep these things in mind: Please keep these things in mind:
@ -29,7 +29,7 @@ QMK is largely written in C, with specific features and parts written in C++. It
# Where Can I Go for Help? # Where Can I Go for Help?
If you need help you can [open an issue](https://github.com/qmk/qmk_firmware/issues) or [chat on Discord](https://discord.gg/Uq7gcHh). If you need help you can [open an issue](https://github.com/qmk/qmk_firmware/issues) or [chat on Discord](https://discord.gg/qmk).
# How Do I Make a Contribution? # How Do I Make a Contribution?
@ -128,7 +128,7 @@ We also ask that you follow these guidelines:
Before you put a lot of work into building your new feature you should make sure you are implementing it in the best way. You can get a basic understanding of QMK by reading [Understanding QMK](understanding_qmk), which will take you on a tour of the QMK program flow. From here you should talk to us to get a sense of the best way to implement your idea. There are two main ways to do this: Before you put a lot of work into building your new feature you should make sure you are implementing it in the best way. You can get a basic understanding of QMK by reading [Understanding QMK](understanding_qmk), which will take you on a tour of the QMK program flow. From here you should talk to us to get a sense of the best way to implement your idea. There are two main ways to do this:
* [Chat on Discord](https://discord.gg/Uq7gcHh) * [Chat on Discord](https://discord.gg/qmk)
* [Open an Issue](https://github.com/qmk/qmk_firmware/issues/new) * [Open an Issue](https://github.com/qmk/qmk_firmware/issues/new)
Feature and Bug Fix PRs affect all keyboards. We are also in the process of restructuring QMK. For this reason it is especially important for significant changes to be discussed before implementation has happened. If you open a PR without talking to us first please be prepared to do some significant rework if your choices do not mesh well with our planned direction. Feature and Bug Fix PRs affect all keyboards. We are also in the process of restructuring QMK. For this reason it is especially important for significant changes to be discussed before implementation has happened. If you open a PR without talking to us first please be prepared to do some significant rework if your choices do not mesh well with our planned direction.

View File

@ -184,7 +184,7 @@ Whenever possible you should customize your keyboard by using `process_record_*(
### Example `matrix_scan_*` Implementation ### Example `matrix_scan_*` Implementation
This example has been deliberately omitted. You should understand enough about QMK internals to write this without an example before hooking into such a performance sensitive area. If you need help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) or [chat with us on Discord](https://discord.gg/Uq7gcHh). This example has been deliberately omitted. You should understand enough about QMK internals to write this without an example before hooking into such a performance sensitive area. If you need help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) or [chat with us on Discord](https://discord.gg/qmk).
### `matrix_scan_*` Function Documentation ### `matrix_scan_*` Function Documentation

View File

@ -26,20 +26,51 @@ Add the following to your `config.h`:
## API {#api} ## API {#api}
### `void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds)` ### `void apa102_init(void)` {#api-apa102-init}
Send RGB data to the APA102 LED chain. Initialize the LED driver. This function should be called first.
#### Arguments {#api-apa102-setleds-arguments}
- `rgb_led_t *start_led`
A pointer to the LED array.
- `uint16_t num_leds`
The length of the LED array.
--- ---
### `void apa102_set_brightness(uint8_t brightness)` ### `void apa102_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue)` {#api-apa102-set-color}
Set the color of a single LED. This function does not immediately update the LEDs; call `apa102_flush()` after you are finished.
#### Arguments {#api-apa102-set-color-arguments}
- `uint16_t index`
The LED index in the APA102 chain.
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void apa102_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-apa102-set-color-all}
Set the color of all LEDs.
#### Arguments {#api-apa102-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void apa102_flush(void)` {#api-apa102-flush}
Flush the PWM values to the LED chain.
---
### `void apa102_set_brightness(uint8_t brightness)` {#api-apa102-set-brightness}
Set the global brightness. Set the global brightness.

133
docs/drivers/aw20216s.md Normal file
View File

@ -0,0 +1,133 @@
# AW20216S Driver {#aw20216s-driver}
SPI 18x12 LED matrix driver by Awinic. Supports a maximum of four drivers, each controlling up to 216 single-color LEDs, or 72 RGB LEDs.
[AW20216S Datasheet](https://doc.awinic.com/doc/20230609wm/b6a9c70b-e1bd-495b-925f-bcbed3fc2620.pdf)
## Usage {#usage}
The AW20216S driver code is automatically included if you are using the [RGB Matrix](../features/rgb_matrix) feature with the `aw20216s` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led
SRC += aw20216s.c
SPI_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|-----------------------------|-------------|-------------------------------------------------------------|
|`AW20216S_CS_PIN_1` |*Not defined*|The GPIO pin connected to the first driver's Chip Select pin |
|`AW20216S_CS_PIN_2` |*Not defined*|The GPIO pin connected to the second driver's Chip Select pin|
|`AW20216S_EN_PIN` |*Not defined*|The GPIO pin connected to the drivers' Enable pins |
|`AW20216S_SPI_MODE` |`0` |The SPI mode to use |
|`AW20216S_SPI_DIVISOR` |`4` |The SPI divisor to use |
|`AW20216S_SCALING_MAX` |`150` |The scaling value |
|`AW20216S_GLOBAL_CURRENT_MAX`|`150` |The global current control value |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. To adjust it, add the following to your `config.h`:
```c
#define AW20216S_GLOBAL_CURRENT_MAX 150
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure SPI](spi#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the first LED index on driver 0 has its red channel on `SW1_CS1`, green on `SW1_CS2` and blue on `SW1_CS3`.
These values correspond to the matrix locations as shown in the datasheet on page 16, figure 16.
## API {#api}
### `struct aw20216s_led_t` {#api-aw20216s-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-aw20216s-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel.
- `uint8_t g`
The output PWM register address for the LED's green channel.
- `uint8_t b`
The output PWM register address for the LED's blue channel.
---
### `void aw20216s_init(pin_t cs_pin)` {#api-aw20216s-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-aw20216s-init-arguments}
- `pin_t cs_pin`
The GPIO connected to the Chip Select pin of the LED driver to initialize.
---
### `void aw20216s_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-aw20216s-set-color}
Set the color of a single LED. This function does not immediately update the LEDs; call `aw20216s_update_pwm_buffers()` after you are finished.
#### Arguments {#api-aw20216s-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_aw20216s_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void aw20216s_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-aw20216s-set-color-all}
Set the color of all LEDs.
#### Arguments {#api-aw20216s-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void aw20216s_update_pwm_buffers(pin_t cs_pin, uint8_t index)` {#api-aw20216s-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-aw20216s-update-pwm-buffers-arguments}
- `pin_t cs_pin`
The GPIO connected to the Chip Select pin of the driver.
- `uint8_t index`
The index of the driver.

View File

@ -119,13 +119,14 @@ This driver performs writes to the embedded flash storage embedded in the MCU. I
Configurable options in your keyboard's `config.h`: Configurable options in your keyboard's `config.h`:
`config.h` override | Default | Description `config.h` override | Default | Description
-----------------------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`#define WEAR_LEVELING_EFL_FIRST_SECTOR` | _unset_ | The first sector on the MCU to use. By default this is not defined and calculated at runtime based on the MCU. However, different flash sizes on MCUs may require custom configuration. `#define WEAR_LEVELING_EFL_FIRST_SECTOR` | _unset_ | The first sector on the MCU to use. By default this is not defined and calculated at runtime based on the MCU. However, different flash sizes on MCUs may require custom configuration.
`#define WEAR_LEVELING_EFL_FLASH_SIZE` | _unset_ | Allows overriding the flash size available for use for wear-leveling. Under normal circumstances this is automatically calculated and should not need to be overridden. Specifying a size larger than the amount actually available in flash will usually prevent the MCU from booting. `#define WEAR_LEVELING_EFL_FLASH_SIZE` | _unset_ | Allows overriding the flash size available for use for wear-leveling. Under normal circumstances this is automatically calculated and should not need to be overridden. Specifying a size larger than the amount actually available in flash will usually prevent the MCU from booting.
`#define WEAR_LEVELING_LOGICAL_SIZE` | `(backing_size/2)` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM. `#define WEAR_LEVELING_EFL_OMIT_LAST_SECTOR_COUNT` | `0` | Number of sectors to omit at the end of the flash. These sectors will not be allocated to the driver and the usable flash block will be offset, but keeping the set flash size. Useful on devices with bootloaders requiring a check flag at the end of flash to be present in order to confirm a valid, bootable firmware.
`#define WEAR_LEVELING_BACKING_SIZE` | `2048` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size. `#define WEAR_LEVELING_LOGICAL_SIZE` | `(backing_size/2)` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
`#define BACKING_STORE_WRITE_SIZE` | _automatic_ | The byte width of the underlying write used on the MCU, and is usually automatically determined from the selected MCU family. If an error occurs in the auto-detection, you'll need to consult the MCU's datasheet and determine this value, specifying it directly. `#define WEAR_LEVELING_BACKING_SIZE` | `2048` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size.
`#define BACKING_STORE_WRITE_SIZE` | _automatic_ | The byte width of the underlying write used on the MCU, and is usually automatically determined from the selected MCU family. If an error occurs in the auto-detection, you'll need to consult the MCU's datasheet and determine this value, specifying it directly.
::: warning ::: warning
If your MCU does not boot after swapping to the EFL wear-leveling driver, it's likely that the flash size is incorrectly detected, usually as an MCU with larger flash and may require overriding. If your MCU does not boot after swapping to the EFL wear-leveling driver, it's likely that the flash size is incorrectly detected, usually as an MCU with larger flash and may require overriding.

194
docs/drivers/is31fl3218.md Normal file
View File

@ -0,0 +1,194 @@
# IS31FL3218 Driver {#is31fl3218-driver}
I²C LED driver by Lumissil. Supports up to 18 single-color LEDs, or 6 RGB LEDs.
[IS31FL3218 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3218_DS.pdf)
## Usage {#usage}
The IS31FL3218 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3218` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3218-mono.c # For single-color
SRC += is31fl3218.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|-------------|---------------------------------------------------|
|`IS31FL3218_SDB_PIN` |*Not defined*|The GPIO pin connected to the driver's shutdown pin|
|`IS31FL3218_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3218_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
### I²C Addressing {#i2c-addressing}
The IS31FL3218's 7-bit I²C address is `0x54`, available as `IS31FL3218_I2C_ADDRESS`.
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT] = {
/* R G B */
{OUT1, OUT2, OUT3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index all have their anodes connected to `VCC`, and their cathodes on the `OUT1`, `OUT2` and `OUT3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT] = {
/* V */
{OUT1},
// etc...
};
```
## API {#api}
### `struct is31fl3218_led_t` {#api-is31fl3218-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3218-led-t-members}
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3218_init(void)` {#api-is31fl3218-init}
Initialize the LED driver. This function should be called first.
---
### `void is31fl3218_write_register(uint8_t reg, uint8_t data)` {#api-is31fl3218-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3218-write-register-arguments}
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3218_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3218-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3218_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3218-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3218_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3218_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3218-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3218-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3218_set_value(int index, uint8_t value)` {#api-is31fl3218-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3218_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3218-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3218_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3218_set_value_all(uint8_t value)` {#api-is31fl3218-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3218-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3218_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3218-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3218_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3218-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3218_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3218_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3218-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3218_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3218-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3218_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3218_update_pwm_buffers(void)` {#api-is31fl3218-update-pwm-buffers}
Flush the PWM values to the LED driver.
---
### `void is31fl3218_update_led_control_registers(void)` {#api-is31fl3218-update-led-control-registers}
Flush the LED control register values to the LED driver.

228
docs/drivers/is31fl3236.md Normal file
View File

@ -0,0 +1,228 @@
# IS31FL3236 Driver {#is31fl3236-driver}
I²C LED driver by Lumissil. Supports a maximum of four drivers, each controlling up to 36 single-color LEDs, or 12 RGB LEDs.
[IS31FL3236 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3236_DS.pdf)
## Usage {#usage}
The IS31FL3236 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3236` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3236-mono.c # For single-color
SRC += is31fl3236.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|-------------|----------------------------------------------------|
|`IS31FL3236_SDB_PIN` |*Not defined*|The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3236_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3236_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3236_I2C_ADDRESS_1` |*Not defined*|The I²C address of driver 0 |
|`IS31FL3236_I2C_ADDRESS_2` |*Not defined*|The I²C address of driver 1 |
|`IS31FL3236_I2C_ADDRESS_3` |*Not defined*|The I²C address of driver 2 |
|`IS31FL3236_I2C_ADDRESS_4` |*Not defined*|The I²C address of driver 3 |
### I²C Addressing {#i2c-addressing}
The IS31FL3236 has four possible 7-bit I²C addresses, depending on how the `AD` pin is connected.
To configure this, set the `IS31FL3236_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|----------------------------|------|
|`IS31FL3236_I2C_ADDRESS_GND`|`0x3C`|
|`IS31FL3236_I2C_ADDRESS_SCL`|`0x3D`|
|`IS31FL3236_I2C_ADDRESS_SDA`|`0x3E`|
|`IS31FL3236_I2C_ADDRESS_VCC`|`0x3F`|
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3236_led_t PROGMEM g_is31fl3236_leds[IS31FL3236_LED_COUNT] = {
/* Driver
| R G B */
{0, OUT1, OUT2, OUT3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to `VCC`, and their cathodes on the `OUT1`, `OUT2` and `OUT3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3236_led_t PROGMEM g_is31fl3236_leds[IS31FL3236_LED_COUNT] = {
/* Driver
| V */
{0, OUT1},
// etc...
};
```
## API {#api}
### `struct is31fl3236_led_t` {#api-is31fl3236-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3236-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3236_init(uint8_t index)` {#api-is31fl3236-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3236-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3236_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3236-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3236-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3236_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3236-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3236_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3236-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3236_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3236_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3236-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3236-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3236_set_value(int index, uint8_t value)` {#api-is31fl3236-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3236_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3236-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3236_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3236_set_value_all(uint8_t value)` {#api-is31fl3236-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3236-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3236_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3236-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3236_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3236-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3236_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3236_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3236-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3236_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3236-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3236_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3236_update_pwm_buffers(uint8_t index)` {#api-is31fl3236-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3236-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3236_update_led_control_registers(uint8_t index)` {#api-is31fl3236-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-is31fl3236-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

300
docs/drivers/is31fl3729.md Normal file
View File

@ -0,0 +1,300 @@
# IS31FL3729 Driver {#is31fl3729-driver}
I²C 16x8/15x9 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 135 single-color LEDs, or 45 RGB LEDs.
[IS31FL3729 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3729_DS.pdf)
## Usage {#usage}
The IS31FL3729 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3729` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3729-mono.c # For single-color
SRC += is31fl3729.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|--------------------------------------|----------------------------------------------------|
|`IS31FL3729_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3729_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3729_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3729_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3729_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3729_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3729_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3729_PWM_FREQUENCY` |`IS31FL3729_PWM_FREQUENCY_32K_HZ` |The PWM frequency of the LEDs |
|`IS31FL3729_SW_PULLDOWN` |`IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF`|The `SWx` pullup resistor value |
|`IS31FL3729_CS_PULLUP` |`IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF` |The `CSx` pulldown resistor value |
|`IS31FL3729_GLOBAL_CURRENT` |`0x40` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3729 has four possible 7-bit I²C addresses, depending on how the `AD` pin is connected.
To configure this, set the `IS31FL3729_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|----------------------------|------|
|`IS31FL3729_I2C_ADDRESS_GND`|`0x34`|
|`IS31FL3729_I2C_ADDRESS_SCL`|`0x35`|
|`IS31FL3729_I2C_ADDRESS_SDA`|`0x36`|
|`IS31FL3729_I2C_ADDRESS_VCC`|`0x37`|
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted by adding the following to your `config.h`:
```c
#define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ
```
Valid values are:
|Define |Frequency |
|----------------------------------|----------------|
|`IS31FL3729_PWM_FREQUENCY_55K_HZ` |55 kHz |
|`IS31FL3729_PWM_FREQUENCY_32K_HZ` |32 kHz (default)|
|`IS31FL3729_PWM_FREQUENCY_4K_HZ` |4 kHz |
|`IS31FL3729_PWM_FREQUENCY_2K_HZ` |2 kHz |
|`IS31FL3729_PWM_FREQUENCY_1K_HZ` |1 kHz |
|`IS31FL3729_PWM_FREQUENCY_500_HZ` |500 Hz |
|`IS31FL3729_PWM_FREQUENCY_250_HZ` |250 Hz |
|`IS31FL3729_PWM_FREQUENCY_80K_HZ` |80 kHz |
### De-Ghosting {#de-ghosting}
These settings control the pulldown and pullup resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 18) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3729_SW_PULLDOWN IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF
#define IS31FL3729_CS_PULLUP IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF
```
Valid values for `IS31FL3729_SW_PULLDOWN` are:
|Define |Resistance |
|---------------------------------------|------------------------------|
|`IS31FL3729_SW_PULLDOWN_0_OHM` |None |
|`IS31FL3729_SW_PULLDOWN_0K5_OHM_SW_OFF`|0.5 kΩ in SWy off time |
|`IS31FL3729_SW_PULLDOWN_1K_OHM_SW_OFF` |1 kΩ in SWy off time |
|`IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF` |2 kΩ in SWy off time (default)|
|`IS31FL3729_SW_PULLDOWN_1K_OHM` |1 kΩ |
|`IS31FL3729_SW_PULLDOWN_2K_OHM` |2 kΩ |
|`IS31FL3729_SW_PULLDOWN_4K_OHM` |4 kΩ |
|`IS31FL3729_SW_PULLDOWN_8K_OHM` |8 kΩ |
Valid values for `IS31FL3729_CS_PULLUP` are:
|Define |Resistance |
|-------------------------------------|------------------------------|
|`IS31FL3729_CS_PULLUP_0_OHM` |None |
|`IS31FL3729_CS_PULLUP_0K5_OHM_CS_OFF`|0.5 kΩ in CSx off time |
|`IS31FL3729_CS_PULLUP_1K_OHM_CS_OFF` |1 kΩ in CSx off time |
|`IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF` |2 kΩ in CSx off time (default)|
|`IS31FL3729_CS_PULLUP_1K_OHM` |1 kΩ |
|`IS31FL3729_CS_PULLUP_2K_OHM` |2 kΩ |
|`IS31FL3729_CS_PULLUP_4K_OHM` |4 kΩ |
|`IS31FL3729_CS_PULLUP_8K_OHM` |8 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. By default, the value is 64, but if you need to adjust it, add the following to your `config.h`:
```c
#define IS31FL3729_GLOBAL_CURRENT 0x40
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to the `SW1` pin, and their cathodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 12, figure 9.
## API {#api}
### `struct is31fl3729_led_t` {#api-is31fl3729-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3729-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3729_init(uint8_t index)` {#api-is31fl3729-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3729-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3729-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3729-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3729_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3729-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3729_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3729-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3729_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3729_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3729-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3729-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3729_set_value(int index, uint8_t value)` {#api-is31fl3729-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3729_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3729-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3729_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3729_set_value_all(uint8_t value)` {#api-is31fl3729-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3729-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3729_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3729-set-scaling-register-rgb}
Configure the scaling registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3729_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3729-set-scaling-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3729_leds` array).
- `uint8_t red`
The scaling value for the red channel.
- `uint8_t green`
The scaling value for the green channel.
- `uint8_t blue`
The scaling value for the blue channel.
---
### `void is31fl3729_set_scaling_register(uint8_t index, uint8_t value)` {#api-is31fl3729-set-scaling-register-mono}
Configure the scaling registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3729_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3729-set-scaling-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3729_leds` array).
- `uint8_t value`
The scaling value for the LED.
---
### `void is31fl3729_update_pwm_buffers(uint8_t index)` {#api-is31fl3729-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3729-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3729_update_scaling_registers(uint8_t index)` {#api-is31fl3729-update-scaling-registers}
Flush the scaling register values to the LED driver.
#### Arguments {#api-is31fl3729-update-scaling-registers-arguments}
- `uint8_t index`
The driver index.

254
docs/drivers/is31fl3731.md Normal file
View File

@ -0,0 +1,254 @@
# IS31FL3731 Driver {#is31fl3731-driver}
I²C Charlieplexed 16x9 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 144 single-color LEDs, or 48 RGB LEDs.
[IS31FL3731 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf)
## Usage {#usage}
The IS31FL3731 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3731` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731-mono.c # For single-color
SRC += is31fl3731.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|-------------|----------------------------------------------------|
|`IS31FL3731_SDB_PIN` |*Not defined*|The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3731_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3731_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3731_I2C_ADDRESS_1` |*Not defined*|The I²C address of driver 0 |
|`IS31FL3731_I2C_ADDRESS_2` |*Not defined*|The I²C address of driver 1 |
|`IS31FL3731_I2C_ADDRESS_3` |*Not defined*|The I²C address of driver 2 |
|`IS31FL3731_I2C_ADDRESS_4` |*Not defined*|The I²C address of driver 3 |
|`IS31FL3731_DEGHOST` |*Not defined*|Enable ghost image prevention |
### I²C Addressing {#i2c-addressing}
The IS31FL3731 has four possible 7-bit I²C addresses, depending on how the `AD` pin is connected.
To configure this, set the `IS31FL3731_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|----------------------------|------|
|`IS31FL3731_I2C_ADDRESS_GND`|`0x74`|
|`IS31FL3731_I2C_ADDRESS_SCL`|`0x75`|
|`IS31FL3731_I2C_ADDRESS_SDA`|`0x76`|
|`IS31FL3731_I2C_ADDRESS_VCC`|`0x77`|
### De-Ghosting {#de-ghosting}
This setting enables the de-ghosting feature on the IS31FL3731. See this [Application Note](https://www.lumissil.com/assets/pdf/core/IS31FL3731_AN.pdf) (p. 15) for more information.
To enable, add the following to your `config.h`:
```c
#define IS31FL3731_DEGHOST
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Driver
* | R G B */
{0, C1_1, C1_2, C1_3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their cathodes connected to the `CA1` pin, and their anodes on the `CA2`, `CA3` and `CA4` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Driver
* | V */
{0, C1_1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 11, figure 8.
## API {#api}
### `struct is31fl3731_led_t` {#api-is31fl3731-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3731-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3731_init(uint8_t index)` {#api-is31fl3731-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3731-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3731_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3731-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3731-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3731_select_page(uint8_t index, uint8_t page)` {#api-is31fl3731-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3731-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3731-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3731_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3731-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3731_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3731_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3731-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3731-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3731_set_value(int index, uint8_t value)` {#api-is31fl3731-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3731_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3731-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3731_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3731_set_value_all(uint8_t value)` {#api-is31fl3731-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3731-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3731_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3731-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3731_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3731-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3731_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3731_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3731-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3731_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3731-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3731_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3731_update_pwm_buffers(uint8_t index)` {#api-is31fl3731-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3731-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3731_update_led_control_registers(uint8_t index)` {#api-is31fl3731-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-is31fl3731-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

338
docs/drivers/is31fl3733.md Normal file
View File

@ -0,0 +1,338 @@
# IS31FL3733 Driver {#is31fl3733-driver}
I²C 12x16 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 192 single-color LEDs, or 64 RGB LEDs.
[IS31FL3733 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3733_DS.pdf)
## Usage {#usage}
The IS31FL3733 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3733` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3733-mono.c # For single-color
SRC += is31fl3733.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|---------------------------------|----------------------------------------------------|
|`IS31FL3733_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3733_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3733_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3733_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3733_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3733_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3733_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3733_SYNC_1` |`IS31FL3733_SYNC_NONE` |The sync configuration for driver 0 |
|`IS31FL3733_SYNC_2` |`IS31FL3733_SYNC_NONE` |The sync configuration for driver 1 |
|`IS31FL3733_SYNC_3` |`IS31FL3733_SYNC_NONE` |The sync configuration for driver 2 |
|`IS31FL3733_SYNC_4` |`IS31FL3733_SYNC_NONE` |The sync configuration for driver 3 |
|`IS31FL3733_PWM_FREQUENCY` |`IS31FL3733_PWM_FREQUENCY_8K4_HZ`|The PWM frequency of the LEDs (IS31FL3733B only) |
|`IS31FL3733_SW_PULLUP` |`IS31FL3733_PUR_0_OHM` |The `SWx` pullup resistor value |
|`IS31FL3733_CS_PULLDOWN` |`IS31FL3733_PDR_0_OHM` |The `CSx` pulldown resistor value |
|`IS31FL3733_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3733 has 16 possible 7-bit I²C addresses, depending on how the `ADDR1` and `ADDR2` pins are connected.
To configure this, set the `IS31FL3733_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|--------------------------------|------|
|`IS31FL3733_I2C_ADDRESS_GND_GND`|`0x50`|
|`IS31FL3733_I2C_ADDRESS_GND_SCL`|`0x51`|
|`IS31FL3733_I2C_ADDRESS_GND_SDA`|`0x52`|
|`IS31FL3733_I2C_ADDRESS_GND_VCC`|`0x53`|
|`IS31FL3733_I2C_ADDRESS_SCL_GND`|`0x54`|
|`IS31FL3733_I2C_ADDRESS_SCL_SCL`|`0x55`|
|`IS31FL3733_I2C_ADDRESS_SCL_SDA`|`0x56`|
|`IS31FL3733_I2C_ADDRESS_SCL_VCC`|`0x57`|
|`IS31FL3733_I2C_ADDRESS_SDA_GND`|`0x58`|
|`IS31FL3733_I2C_ADDRESS_SDA_SCL`|`0x59`|
|`IS31FL3733_I2C_ADDRESS_SDA_SDA`|`0x5A`|
|`IS31FL3733_I2C_ADDRESS_SDA_VCC`|`0x5B`|
|`IS31FL3733_I2C_ADDRESS_VCC_GND`|`0x5C`|
|`IS31FL3733_I2C_ADDRESS_VCC_SCL`|`0x5D`|
|`IS31FL3733_I2C_ADDRESS_VCC_SDA`|`0x5E`|
|`IS31FL3733_I2C_ADDRESS_VCC_VCC`|`0x5F`|
### Multi-Driver Synchronization {#multi-driver-synchronization}
Multiple IS31FL3733 drivers can be synchronized by connecting the `SYNC` pins together. One driver must be designated as the "master", and the others configured as "slave".
To do this, set the `IS31FL3733_SYNC_n` defines accordingly in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|------------------------|---------------------------|
|`IS31FL3733_SYNC_NONE` |No synchronization |
|`IS31FL3733_SYNC_MASTER`|Driver configured as master|
|`IS31FL3733_SYNC_SLAVE` |Driver configured as slave |
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted (for IS31FL3733B only) by adding the following to your `config.h`:
```c
#define IS31FL3733_PWM_FREQUENCY IS31FL3733_PWM_FREQUENCY_8K4_HZ
```
Valid values are:
|Define |Frequency |
|----------------------------------|-----------------|
|`IS31FL3733_PWM_FREQUENCY_8K4_HZ` |8.4 kHz (default)|
|`IS31FL3733_PWM_FREQUENCY_4K2_HZ` |4.2 kHz |
|`IS31FL3733_PWM_FREQUENCY_26K7_HZ`|26.7 kHz |
|`IS31FL3733_PWM_FREQUENCY_2K1_HZ` |2.1 kHz |
|`IS31FL3733_PWM_FREQUENCY_1K05_HZ`|1.05 kHz |
### De-Ghosting {#de-ghosting}
These settings control the pullup and pulldown resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 23) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3733_SW_PULLUP IS31FL3733_PUR_0_OHM
#define IS31FL3733_CS_PULLDOWN IS31FL3733_PUR_0_OHM
```
Valid values for `IS31FL3733_SW_PULLUP` are:
|Define |Resistance |
|------------------------|--------------|
|`IS31FL3733_PUR_0_OHM` |None (default)|
|`IS31FL3733_PUR_0K5_OHM`|0.5 kΩ |
|`IS31FL3733_PUR_1K_OHM` |1 kΩ |
|`IS31FL3733_PUR_2K_OHM` |2 kΩ |
|`IS31FL3733_PUR_4K_OHM` |4 kΩ |
|`IS31FL3733_PUR_8K_OHM` |8 kΩ |
|`IS31FL3733_PUR_16K_OHM`|16 kΩ |
|`IS31FL3733_PUR_32K_OHM`|32 kΩ |
Valid values for `IS31FL3733_CS_PULLDOWN` are:
|Define |Resistance |
|------------------------|--------------|
|`IS31FL3733_PDR_0_OHM` |None (default)|
|`IS31FL3733_PDR_0K5_OHM`|0.5 kΩ |
|`IS31FL3733_PDR_1K_OHM` |1 kΩ |
|`IS31FL3733_PDR_2K_OHM` |2 kΩ |
|`IS31FL3733_PDR_4K_OHM` |4 kΩ |
|`IS31FL3733_PDR_8K_OHM` |8 kΩ |
|`IS31FL3733_PDR_16K_OHM`|16 kΩ |
|`IS31FL3733_PDR_32K_OHM`|32 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3733_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their cathodes connected to the `SW1` pin, and their anodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 15, figure 9.
## API {#api}
### `struct is31fl3733_led_t` {#api-is31fl3733-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3733-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3733_init(uint8_t index)` {#api-is31fl3733-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3733-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3733_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3733-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3733-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3733_select_page(uint8_t index, uint8_t page)` {#api-is31fl3733-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3733-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3733-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3733_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3733-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3733_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3733-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3733-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3733_set_value(int index, uint8_t value)` {#api-is31fl3733-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3733_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3733-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3733_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3733_set_value_all(uint8_t value)` {#api-is31fl3733-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3733-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3733_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3733-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3733_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3733-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3733_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3733_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3733-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3733_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3733-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3733_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3733_update_pwm_buffers(uint8_t index)` {#api-is31fl3733-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3733-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3733_update_led_control_registers(uint8_t index)` {#api-is31fl3733-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-is31fl3733-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

322
docs/drivers/is31fl3736.md Normal file
View File

@ -0,0 +1,322 @@
# IS31FL3736 Driver {#is31fl3736-driver}
I²C 12x8 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 96 single-color LEDs, or 32 RGB LEDs.
[IS31FL3736 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3736_DS.pdf)
## Usage {#usage}
The IS31FL3736 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3736` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3736-mono.c # For single-color
SRC += is31fl3736.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|---------------------------------|----------------------------------------------------|
|`IS31FL3736_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3736_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3736_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3736_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3736_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3736_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3736_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3736_PWM_FREQUENCY` |`IS31FL3736_PWM_FREQUENCY_8K4_HZ`|The PWM frequency of the LEDs (IS31FL3736B only) |
|`IS31FL3736_SW_PULLUP` |`IS31FL3736_PUR_0_OHM` |The `SWx` pullup resistor value |
|`IS31FL3736_CS_PULLDOWN` |`IS31FL3736_PDR_0_OHM` |The `CSx` pulldown resistor value |
|`IS31FL3736_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3736 has 16 possible 7-bit I²C addresses, depending on how the `ADDR1` and `ADDR2` pins are connected.
To configure this, set the `IS31FL3736_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|--------------------------------|------|
|`IS31FL3736_I2C_ADDRESS_GND_GND`|`0x50`|
|`IS31FL3736_I2C_ADDRESS_GND_SCL`|`0x51`|
|`IS31FL3736_I2C_ADDRESS_GND_SDA`|`0x52`|
|`IS31FL3736_I2C_ADDRESS_GND_VCC`|`0x53`|
|`IS31FL3736_I2C_ADDRESS_SCL_GND`|`0x54`|
|`IS31FL3736_I2C_ADDRESS_SCL_SCL`|`0x55`|
|`IS31FL3736_I2C_ADDRESS_SCL_SDA`|`0x56`|
|`IS31FL3736_I2C_ADDRESS_SCL_VCC`|`0x57`|
|`IS31FL3736_I2C_ADDRESS_SDA_GND`|`0x58`|
|`IS31FL3736_I2C_ADDRESS_SDA_SCL`|`0x59`|
|`IS31FL3736_I2C_ADDRESS_SDA_SDA`|`0x5A`|
|`IS31FL3736_I2C_ADDRESS_SDA_VCC`|`0x5B`|
|`IS31FL3736_I2C_ADDRESS_VCC_GND`|`0x5C`|
|`IS31FL3736_I2C_ADDRESS_VCC_SCL`|`0x5D`|
|`IS31FL3736_I2C_ADDRESS_VCC_SDA`|`0x5E`|
|`IS31FL3736_I2C_ADDRESS_VCC_VCC`|`0x5F`|
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted (for IS31FL3736B only) by adding the following to your `config.h`:
```c
#define IS31FL3736_PWM_FREQUENCY IS31FL3736_PWM_FREQUENCY_8K4_HZ
```
Valid values are:
|Define |Frequency |
|----------------------------------|-----------------|
|`IS31FL3736_PWM_FREQUENCY_8K4_HZ` |8.4 kHz (default)|
|`IS31FL3736_PWM_FREQUENCY_4K2_HZ` |4.2 kHz |
|`IS31FL3736_PWM_FREQUENCY_26K7_HZ`|26.7 kHz |
|`IS31FL3736_PWM_FREQUENCY_2K1_HZ` |2.1 kHz |
|`IS31FL3736_PWM_FREQUENCY_1K05_HZ`|1.05 kHz |
### De-Ghosting {#de-ghosting}
These settings control the pullup and pulldown resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 25) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3736_SW_PULLUP IS31FL3736_PUR_0_OHM
#define IS31FL3736_CS_PULLDOWN IS31FL3736_PDR_0_OHM
```
Valid values for `IS31FL3736_SW_PULLUP` are:
|Define |Resistance |
|------------------------|--------------|
|`IS31FL3736_PUR_0_OHM` |None (default)|
|`IS31FL3736_PUR_0K5_OHM`|0.5 kΩ |
|`IS31FL3736_PUR_1K_OHM` |1 kΩ |
|`IS31FL3736_PUR_2K_OHM` |2 kΩ |
|`IS31FL3736_PUR_4K_OHM` |4 kΩ |
|`IS31FL3736_PUR_8K_OHM` |8 kΩ |
|`IS31FL3736_PUR_16K_OHM`|16 kΩ |
|`IS31FL3736_PUR_32K_OHM`|32 kΩ |
Valid values for `IS31FL3736_CS_PULLDOWN` are:
|Define |Resistance |
|------------------------|--------------|
|`IS31FL3736_PDR_0_OHM` |None (default)|
|`IS31FL3736_PDR_0K5_OHM`|0.5 kΩ |
|`IS31FL3736_PDR_1K_OHM` |1 kΩ |
|`IS31FL3736_PDR_2K_OHM` |2 kΩ |
|`IS31FL3736_PDR_4K_OHM` |4 kΩ |
|`IS31FL3736_PDR_8K_OHM` |8 kΩ |
|`IS31FL3736_PDR_16K_OHM`|16 kΩ |
|`IS31FL3736_PDR_32K_OHM`|32 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3736_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their cathodes connected to the `SW1` pin, and their anodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 16, figure 9.
## API {#api}
### `struct is31fl3736_led_t` {#api-is31fl3736-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3736-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3736_init(uint8_t index)` {#api-is31fl3736-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3736-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3736_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3736-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3736-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3736_select_page(uint8_t index, uint8_t page)` {#api-is31fl3736-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3736-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3736-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3736_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3736-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3736_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3736_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3736-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3736-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3736_set_value(int index, uint8_t value)` {#api-is31fl3736-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3736_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3736-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3736_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3736_set_value_all(uint8_t value)` {#api-is31fl3736-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3736-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3736_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3736-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3736_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3736-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3736_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3736_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3736-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3736_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3736-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3736_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3736_update_pwm_buffers(uint8_t index)` {#api-is31fl3736-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3736-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3736_update_led_control_registers(uint8_t index)` {#api-is31fl3736-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-is31fl3736-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

310
docs/drivers/is31fl3737.md Normal file
View File

@ -0,0 +1,310 @@
# IS31FL3737 Driver {#is31fl3737-driver}
I²C 12x12 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 144 single-color LEDs, or 48 RGB LEDs.
[IS31FL3737 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3737_DS.pdf)
## Usage {#usage}
The IS31FL3737 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3737` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3737-mono.c # For single-color
SRC += is31fl3737.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|---------------------------------|----------------------------------------------------|
|`IS31FL3737_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3737_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3737_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3737_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3737_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3737_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3737_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3737_PWM_FREQUENCY` |`IS31FL3737_PWM_FREQUENCY_8K4_HZ`|The PWM frequency of the LEDs (IS31FL3737B only) |
|`IS31FL3737_SW_PULLUP` |`IS31FL3737_PUR_0_OHM` |The `SWx` pullup resistor value |
|`IS31FL3737_CS_PULLDOWN` |`IS31FL3737_PDR_0_OHM` |The `CSx` pulldown resistor value |
|`IS31FL3737_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3737 has four possible 7-bit I²C addresses, depending on how the `ADDR` pin is connected.
To configure this, set the `IS31FL3737_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|----------------------------|------|
|`IS31FL3737_I2C_ADDRESS_GND`|`0x50`|
|`IS31FL3737_I2C_ADDRESS_SCL`|`0x55`|
|`IS31FL3737_I2C_ADDRESS_SDA`|`0x5A`|
|`IS31FL3737_I2C_ADDRESS_VCC`|`0x5F`|
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted (for IS31FL3737B only) by adding the following to your `config.h`:
```c
#define IS31FL3737_PWM_FREQUENCY IS31FL3737_PWM_FREQUENCY_8K4_HZ
```
Valid values are:
|Define |Frequency |
|----------------------------------|-----------------|
|`IS31FL3737_PWM_FREQUENCY_8K4_HZ` |8.4 kHz (default)|
|`IS31FL3737_PWM_FREQUENCY_4K2_HZ` |4.2 kHz |
|`IS31FL3737_PWM_FREQUENCY_26K7_HZ`|26.7 kHz |
|`IS31FL3737_PWM_FREQUENCY_2K1_HZ` |2.1 kHz |
|`IS31FL3737_PWM_FREQUENCY_1K05_HZ`|1.05 kHz |
### De-Ghosting {#de-ghosting}
These settings control the pullup and pulldown resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 23) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3737_SW_PULLUP IS31FL3737_PUR_0_OHM
#define IS31FL3737_CS_PULLDOWN IS31FL3737_PDR_0_OHM
```
Valid values for `IS31FL3737_SW_PULLUP` are:
|Define |Resistance |
|------------------------|--------------|
|`IS31FL3737_PUR_0_OHM` |None (default)|
|`IS31FL3737_PUR_0K5_OHM`|0.5 kΩ |
|`IS31FL3737_PUR_1K_OHM` |1 kΩ |
|`IS31FL3737_PUR_2K_OHM` |2 kΩ |
|`IS31FL3737_PUR_4K_OHM` |4 kΩ |
|`IS31FL3737_PUR_8K_OHM` |8 kΩ |
|`IS31FL3737_PUR_16K_OHM`|16 kΩ |
|`IS31FL3737_PUR_32K_OHM`|32 kΩ |
Valid values for `IS31FL3737_CS_PULLDOWN` are:
|Define |Resistance |
|------------------------|--------------|
|`IS31FL3737_PDR_0_OHM` |None (default)|
|`IS31FL3737_PDR_0K5_OHM`|0.5 kΩ |
|`IS31FL3737_PDR_1K_OHM` |1 kΩ |
|`IS31FL3737_PDR_2K_OHM` |2 kΩ |
|`IS31FL3737_PDR_4K_OHM` |4 kΩ |
|`IS31FL3737_PDR_8K_OHM` |8 kΩ |
|`IS31FL3737_PDR_16K_OHM`|16 kΩ |
|`IS31FL3737_PDR_32K_OHM`|32 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3737_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their cathodes connected to the `SW1` pin, and their anodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 15, figure 9.
## API {#api}
### `struct is31fl3737_led_t` {#api-is31fl3737-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3737-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3737_init(uint8_t index)` {#api-is31fl3737-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3737-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3737_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3737-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3737-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3737_select_page(uint8_t index, uint8_t page)` {#api-is31fl3737-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3737-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3737-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3737_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3737-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3737_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3737-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3737-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3737_set_value(int index, uint8_t value)` {#api-is31fl3737-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3737_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3737-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3737_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3737_set_value_all(uint8_t value)` {#api-is31fl3737-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3737-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3737_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3737-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3737_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3737-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3737_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3737_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3737-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3737_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3737-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3737_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3737_update_pwm_buffers(uint8_t index)` {#api-is31fl3737-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3737-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3737_update_led_control_registers(uint8_t index)` {#api-is31fl3737-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-is31fl3737-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

310
docs/drivers/is31fl3741.md Normal file
View File

@ -0,0 +1,310 @@
# IS31FL3741 Driver {#is31fl3741-driver}
I²C 39x9 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 351 single-color LEDs, or 117 RGB LEDs.
[IS31FL3741A Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3741A_DS.pdf)
## Usage {#usage}
The IS31FL3741 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3741` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3741-mono.c # For single-color
SRC += is31fl3741.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|---------------------------------|----------------------------------------------------|
|`IS31FL3741_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3741_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3741_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3741_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3741_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3741_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3741_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3741_CONFIGURATION` |`1` |The value of the configuration register |
|`IS31FL3741_PWM_FREQUENCY` |`IS31FL3741_PWM_FREQUENCY_29K_HZ`|The PWM frequency of the LEDs (IS31FL3741A only) |
|`IS31FL3741_SW_PULLUP` |`IS31FL3741_PUR_32K_OHM` |The `SWx` pullup resistor value |
|`IS31FL3741_CS_PULLDOWN` |`IS31FL3741_PDR_32K_OHM` |The `CSx` pulldown resistor value |
|`IS31FL3741_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3741 has four possible 7-bit I²C addresses, depending on how the `ADDR` pin is connected.
To configure this, set the `IS31FL3741_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|----------------------------|------|
|`IS31FL3741_I2C_ADDRESS_GND`|`0x30`|
|`IS31FL3741_I2C_ADDRESS_SCL`|`0x31`|
|`IS31FL3741_I2C_ADDRESS_SDA`|`0x32`|
|`IS31FL3741_I2C_ADDRESS_VCC`|`0x33`|
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted (for IS31FL3741A only) by adding the following to your `config.h`:
```c
#define IS31FL3741_PWM_FREQUENCY IS31FL3741_PWM_FREQUENCY_29K_HZ
```
Valid values are:
|Define |Frequency |
|---------------------------------|----------------|
|`IS31FL3741_PWM_FREQUENCY_29K_HZ`|29 kHz (default)|
|`IS31FL3741_PWM_FREQUENCY_3K6_HZ`|3.6 kHz |
|`IS31FL3741_PWM_FREQUENCY_1K8_HZ`|1.8 kHz |
|`IS31FL3741_PWM_FREQUENCY_900_HZ`|900 Hz |
### De-Ghosting {#de-ghosting}
These settings control the pullup and pulldown resistor values on the `CSx` and `SWy` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 18) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3741_SW_PULLUP IS31FL3741_PUR_32K_OHM
#define IS31FL3741_CS_PULLDOWN IS31FL3741_PDR_32K_OHM
```
Valid values for `IS31FL3741_SW_PULLUP` are:
|Define |Resistance |
|------------------------|---------------|
|`IS31FL3741_PUR_0_OHM` |None |
|`IS31FL3741_PUR_0K5_OHM`|0.5 kΩ |
|`IS31FL3741_PUR_1K_OHM` |1 kΩ |
|`IS31FL3741_PUR_2K_OHM` |2 kΩ |
|`IS31FL3741_PUR_4K_OHM` |4 kΩ |
|`IS31FL3741_PUR_8K_OHM` |8 kΩ |
|`IS31FL3741_PUR_16K_OHM`|16 kΩ |
|`IS31FL3741_PUR_32K_OHM`|32 kΩ (default)|
Valid values for `IS31FL3741_CS_PULLDOWN` are:
|Define |Resistance |
|------------------------|---------------|
|`IS31FL3741_PDR_0_OHM` |None |
|`IS31FL3741_PDR_0K5_OHM`|0.5 kΩ |
|`IS31FL3741_PDR_1K_OHM` |1 kΩ |
|`IS31FL3741_PDR_2K_OHM` |2 kΩ |
|`IS31FL3741_PDR_4K_OHM` |4 kΩ |
|`IS31FL3741_PDR_8K_OHM` |8 kΩ |
|`IS31FL3741_PDR_16K_OHM`|16 kΩ |
|`IS31FL3741_PDR_32K_OHM`|32 kΩ (default)|
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3741_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to the `SW1` pin, and their cathodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 12, figure 8.
## API {#api}
### `struct is31fl3741_led_t` {#api-is31fl3741-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3741-led-t-members}
- `uint32_t driver`
The driver index of the LED, from 0 to 3.
- `uint32_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint32_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint32_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint32_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3741_init(uint8_t index)` {#api-is31fl3741-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3741-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3741_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3741-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3741-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3741_select_page(uint8_t index, uint8_t page)` {#api-is31fl3741-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3741-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3741-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3741_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3741-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3741_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3741_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3741-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3741-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3741_set_value(int index, uint8_t value)` {#api-is31fl3741-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3741_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3741-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3741_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3741_set_value_all(uint8_t value)` {#api-is31fl3741-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3741-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3741_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-is31fl3741-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3741_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3741-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3741_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void is31fl3741_set_led_control_register(uint8_t index, bool value)` {#api-is31fl3741-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3741_update_led_control_registers()` after you are finished.
#### Arguments {#api-is31fl3741-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3741_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void is31fl3741_update_pwm_buffers(uint8_t index)` {#api-is31fl3741-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3741-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3741_update_led_control_registers(uint8_t index)` {#api-is31fl3741-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-is31fl3741-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

310
docs/drivers/is31fl3742a.md Normal file
View File

@ -0,0 +1,310 @@
# IS31FL3742A Driver {#is31fl3742a-driver}
I²C 30x6 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 180 single-color LEDs, or 60 RGB LEDs.
[IS31FL3742A Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf)
## Usage {#usage}
The IS31FL3742A driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3742a` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3742a-mono.c # For single-color
SRC += is31fl3742a.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|-----------------------------|----------------------------------|----------------------------------------------------|
|`IS31FL3742A_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3742A_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3742A_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3742A_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3742A_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3742A_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3742A_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3742A_CONFIGURATION` |`0x31` |The value of the configuration register |
|`IS31FL3742A_PWM_FREQUENCY` |`IS31FL3742A_PWM_FREQUENCY_29K_HZ`|The PWM frequency of the LEDs |
|`IS31FL3742A_SW_PULLDOWN` |`IS31FL3742A_PDR_8K_OHM` |The `SWx` pulldown resistor value |
|`IS31FL3742A_CS_PULLUP` |`IS31FL3742A_PUR_8K_OHM` |The `CSx` pullup resistor value |
|`IS31FL3742A_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3742A has four possible 7-bit I²C addresses, depending on how the `ADDR` pin is connected.
To configure this, set the `IS31FL3742A_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|-----------------------------|------|
|`IS31FL3742A_I2C_ADDRESS_GND`|`0x30`|
|`IS31FL3742A_I2C_ADDRESS_SCL`|`0x31`|
|`IS31FL3742A_I2C_ADDRESS_SDA`|`0x32`|
|`IS31FL3742A_I2C_ADDRESS_VCC`|`0x33`|
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted by adding the following to your `config.h`:
```c
#define IS31FL3742A_PWM_FREQUENCY IS31FL3742A_PWM_FREQUENCY_29K_HZ
```
Valid values are:
|Define |Frequency |
|----------------------------------|----------------|
|`IS31FL3742A_PWM_FREQUENCY_29K_HZ`|29 kHz (default)|
|`IS31FL3742A_PWM_FREQUENCY_3K6_HZ`|3.6 kHz |
|`IS31FL3742A_PWM_FREQUENCY_1K8_HZ`|1.8 kHz |
|`IS31FL3742A_PWM_FREQUENCY_900_HZ`|900 Hz |
### De-Ghosting {#de-ghosting}
These settings control the pulldown and pullup resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 23) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3742A_SW_PULLDOWN IS31FL3742A_PDR_8K_OHM
#define IS31FL3742A_CS_PULLUP IS31FL3742A_PUR_8K_OHM
```
Valid values for `IS31FL3742A_SW_PULLDOWN` are:
|Define |Resistance |
|-------------------------|--------------|
|`IS31FL3742A_PDR_0_OHM` |None |
|`IS31FL3742A_PDR_0K5_OHM`|0.5 kΩ |
|`IS31FL3742A_PDR_1K_OHM` |1 kΩ |
|`IS31FL3742A_PDR_2K_OHM` |2 kΩ |
|`IS31FL3742A_PDR_4K_OHM` |4 kΩ |
|`IS31FL3742A_PDR_8K_OHM` |8 kΩ (default)|
|`IS31FL3742A_PDR_16K_OHM`|16 kΩ |
|`IS31FL3742A_PDR_32K_OHM`|32 kΩ |
Valid values for `IS31FL3742A_CS_PULLUP` are:
|Define |Resistance |
|-------------------------|--------------|
|`IS31FL3742A_PUR_0_OHM` |None |
|`IS31FL3742A_PUR_0K5_OHM`|0.5 kΩ |
|`IS31FL3742A_PUR_1K_OHM` |1 kΩ |
|`IS31FL3742A_PUR_2K_OHM` |2 kΩ |
|`IS31FL3742A_PUR_4K_OHM` |4 kΩ |
|`IS31FL3742A_PUR_8K_OHM` |8 kΩ (default)|
|`IS31FL3742A_PUR_16K_OHM`|16 kΩ |
|`IS31FL3742A_PUR_32K_OHM`|32 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSx` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3742A_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3742a_led_t PROGMEM g_is31fl3742a_leds[IS31FL3742A_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to the `SW1` pin, and their cathodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3742a_led_t PROGMEM g_is31fl3742a_leds[IS31FL3742A_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 12, figure 8.
## API {#api}
### `struct is31fl3742a_led_t` {#api-is31fl3742a-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3742a-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3742a_init(uint8_t index)` {#api-is31fl3742a-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3742a-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3742a_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3742a-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3742a-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3742a_select_page(uint8_t index, uint8_t page)` {#api-is31fl3742a-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3742a-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3742a_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3742a-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3742a_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3742a-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3742a_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3742a_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3742a-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3742a-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3742a_set_value(int index, uint8_t value)` {#api-is31fl3742a-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3742a_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3742a-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3742a_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3742a_set_value_all(uint8_t value)` {#api-is31fl3742a-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3742a-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3742a_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3742a-set-scaling-register-rgb}
Configure the scaling registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3742a_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3742a-set-scaling-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3742a_leds` array).
- `uint8_t red`
The scaling value for the red channel.
- `uint8_t green`
The scaling value for the green channel.
- `uint8_t blue`
The scaling value for the blue channel.
---
### `void is31fl3742a_set_scaling_register(uint8_t index, uint8_t value)` {#api-is31fl3742a-set-scaling-register-mono}
Configure the scaling register for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3742a_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3742a-set-scaling-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3742a_leds` array).
- `uint8_t value`
The scaling value for the LED.
---
### `void is31fl3742a_update_pwm_buffers(uint8_t index)` {#api-is31fl3742a-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3742a-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3742a_update_scaling_registers(uint8_t index)` {#api-is31fl3742a-update-scaling-registers}
Flush the scaling register values to the LED driver.
#### Arguments {#api-is31fl3742a-update-scaling-registers-arguments}
- `uint8_t index`
The driver index.

320
docs/drivers/is31fl3743a.md Normal file
View File

@ -0,0 +1,320 @@
# IS31FL3743A Driver {#is31fl3743a-driver}
I²C 18x11 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 198 single-color LEDs, or 66 RGB LEDs.
[IS31FL3743A Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf)
## Usage {#usage}
The IS31FL3743A driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3743a` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3743a-mono.c # For single-color
SRC += is31fl3743a.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|-----------------------------|-------------------------------|----------------------------------------------------|
|`IS31FL3743A_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3743A_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3743A_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3743A_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3743A_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3743A_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3743A_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3743A_SYNC_1` |`IS31FL3743A_SYNC_NONE` |The sync configuration for driver 0 |
|`IS31FL3743A_SYNC_2` |`IS31FL3743A_SYNC_NONE` |The sync configuration for driver 1 |
|`IS31FL3743A_SYNC_3` |`IS31FL3743A_SYNC_NONE` |The sync configuration for driver 2 |
|`IS31FL3743A_SYNC_4` |`IS31FL3743A_SYNC_NONE` |The sync configuration for driver 3 |
|`IS31FL3743A_CONFIGURATION` |`0x01` |The value of the configuration register |
|`IS31FL3743A_SW_PULLDOWN` |`IS31FL3743A_PDR_2K_OHM_SW_OFF`|The `SWx` pulldown resistor value |
|`IS31FL3743A_CS_PULLUP` |`IS31FL3743A_PUR_2K_OHM_CS_OFF`|The `CSx` pullup resistor value |
|`IS31FL3743A_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3743A has 16 possible 7-bit I²C addresses, depending on how the `ADDR1` and `ADDR2` pins are connected.
To configure this, set the `IS31FL3743A_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|---------------------------------|------|
|`IS31FL3743A_I2C_ADDRESS_GND_GND`|`0x20`|
|`IS31FL3743A_I2C_ADDRESS_GND_SCL`|`0x21`|
|`IS31FL3743A_I2C_ADDRESS_GND_SDA`|`0x22`|
|`IS31FL3743A_I2C_ADDRESS_GND_VCC`|`0x23`|
|`IS31FL3743A_I2C_ADDRESS_SCL_GND`|`0x24`|
|`IS31FL3743A_I2C_ADDRESS_SCL_SCL`|`0x25`|
|`IS31FL3743A_I2C_ADDRESS_SCL_SDA`|`0x26`|
|`IS31FL3743A_I2C_ADDRESS_SCL_VCC`|`0x27`|
|`IS31FL3743A_I2C_ADDRESS_SDA_GND`|`0x28`|
|`IS31FL3743A_I2C_ADDRESS_SDA_SCL`|`0x29`|
|`IS31FL3743A_I2C_ADDRESS_SDA_SDA`|`0x2A`|
|`IS31FL3743A_I2C_ADDRESS_SDA_VCC`|`0x2B`|
|`IS31FL3743A_I2C_ADDRESS_VCC_GND`|`0x2C`|
|`IS31FL3743A_I2C_ADDRESS_VCC_SCL`|`0x2D`|
|`IS31FL3743A_I2C_ADDRESS_VCC_SDA`|`0x2E`|
|`IS31FL3743A_I2C_ADDRESS_VCC_VCC`|`0x2F`|
### Multi-Driver Synchronization {#multi-driver-synchronization}
Multiple IS31FL3743A drivers can be synchronized by connecting the `SYNC` pins together. One driver must be designated as the "master", and the others configured as "slave".
To do this, set the `IS31FL3743A_SYNC_n` defines accordingly in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|-------------------------|---------------------------|
|`IS31FL3743A_SYNC_NONE` |No synchronization |
|`IS31FL3743A_SYNC_MASTER`|Driver configured as master|
|`IS31FL3743A_SYNC_SLAVE` |Driver configured as slave |
### De-Ghosting {#de-ghosting}
These settings control the pulldown and pullup resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 23) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3743A_SW_PULLDOWN IS31FL3743A_PDR_2K_OHM_SW_OFF
#define IS31FL3743A_CS_PULLUP IS31FL3743A_PUR_2K_OHM_CS_OFF
```
Valid values for `IS31FL3743A_SW_PULLDOWN` are:
|Define |Resistance |
|--------------------------------|------------------------------|
|`IS31FL3743A_PDR_0_OHM` |None (default) |
|`IS31FL3743A_PDR_0K5_OHM_SW_OFF`|0.5 kΩ in SWx off time |
|`IS31FL3743A_PDR_1K_OHM_SW_OFF` |1 kΩ in SWx off time |
|`IS31FL3743A_PDR_2K_OHM_SW_OFF` |2 kΩ in SWx off time (default)|
|`IS31FL3743A_PDR_1K_OHM` |1 kΩ |
|`IS31FL3743A_PDR_2K_OHM` |2 kΩ |
|`IS31FL3743A_PDR_4K_OHM` |4 kΩ |
|`IS31FL3743A_PDR_8K_OHM` |8 kΩ |
Valid values for `IS31FL3743A_CS_PULLUP` are:
|Define |Resistance |
|--------------------------------|------------------------------|
|`IS31FL3743A_PUR_0_OHM` |None (default) |
|`IS31FL3743A_PUR_0K5_OHM_CS_OFF`|0.5 kΩ in CSy off time |
|`IS31FL3743A_PUR_1K_OHM_CS_OFF` |1 kΩ in CSy off time |
|`IS31FL3743A_PUR_2K_OHM_CS_OFF` |2 kΩ in CSy off time (default)|
|`IS31FL3743A_PUR_1K_OHM` |1 kΩ |
|`IS31FL3743A_PUR_2K_OHM` |2 kΩ |
|`IS31FL3743A_PUR_4K_OHM` |4 kΩ |
|`IS31FL3743A_PUR_8K_OHM` |8 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSy` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3743A_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3743a_led_t PROGMEM g_is31fl3743a_leds[IS31FL3743A_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to the `SW1` pin, and their cathodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3743a_led_t PROGMEM g_is31fl3743a_leds[IS31FL3743A_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 12, figure 8.
## API {#api}
### `struct is31fl3743a_led_t` {#api-is31fl3743a-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3743a-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3743a_init(uint8_t index)` {#api-is31fl3743a-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3743a-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3743a_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3743a-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3743a-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3743a_select_page(uint8_t index, uint8_t page)` {#api-is31fl3743a-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3743a-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3743a_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3743a-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3743a_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3743a-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3743a_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3743a_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3743a-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3743a-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3743a_set_value(int index, uint8_t value)` {#api-is31fl3743a-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3743a_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3743a-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3743a_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3743a_set_value_all(uint8_t value)` {#api-is31fl3743a-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3743a-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3743a_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3743a-set-scaling-register-rgb}
Configure the scaling registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3743a_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3743a-set-scaling-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3743a_leds` array).
- `uint8_t red`
The scaling value for the red channel.
- `uint8_t green`
The scaling value for the green channel.
- `uint8_t blue`
The scaling value for the blue channel.
---
### `void is31fl3743a_set_scaling_register(uint8_t index, uint8_t value)` {#api-is31fl3743a-set-scaling-register-mono}
Configure the scaling register for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3743a_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3743a-set-scaling-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3743a_leds` array).
- `uint8_t value`
The scaling value for the LED.
---
### `void is31fl3743a_update_pwm_buffers(uint8_t index)` {#api-is31fl3743a-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3743a-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3743a_update_scaling_registers(uint8_t index)` {#api-is31fl3743a-update-scaling-registers}
Flush the scaling register values to the LED driver.
#### Arguments {#api-is31fl3743a-update-scaling-registers-arguments}
- `uint8_t index`
The driver index.

320
docs/drivers/is31fl3745.md Normal file
View File

@ -0,0 +1,320 @@
# IS31FL3745 Driver {#is31fl3745-driver}
I²C 18x8 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 144 single-color LEDs, or 48 RGB LEDs.
[IS31FL3745 Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf)
## Usage {#usage}
The IS31FL3745 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3745` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3745-mono.c # For single-color
SRC += is31fl3745.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|------------------------------|----------------------------------------------------|
|`IS31FL3745_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3745_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3745_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3745_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3745_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3745_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3745_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3745_SYNC_1` |`IS31FL3745_SYNC_NONE` |The sync configuration for driver 0 |
|`IS31FL3745_SYNC_2` |`IS31FL3745_SYNC_NONE` |The sync configuration for driver 1 |
|`IS31FL3745_SYNC_3` |`IS31FL3745_SYNC_NONE` |The sync configuration for driver 2 |
|`IS31FL3745_SYNC_4` |`IS31FL3745_SYNC_NONE` |The sync configuration for driver 3 |
|`IS31FL3745_CONFIGURATION` |`0x31` |The value of the configuration register |
|`IS31FL3745_SW_PULLDOWN` |`IS31FL3745_PDR_2K_OHM_SW_OFF`|The `SWx` pulldown resistor value |
|`IS31FL3745_CS_PULLUP` |`IS31FL3745_PUR_2K_OHM_CS_OFF`|The `CSx` pullup resistor value |
|`IS31FL3745_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3745 has 16 possible 7-bit I²C addresses, depending on how the `ADDR1` and `ADDR2` pins are connected.
To configure this, set the `IS31FL3745_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|--------------------------------|------|
|`IS31FL3745_I2C_ADDRESS_GND_GND`|`0x20`|
|`IS31FL3745_I2C_ADDRESS_GND_SCL`|`0x21`|
|`IS31FL3745_I2C_ADDRESS_GND_SDA`|`0x22`|
|`IS31FL3745_I2C_ADDRESS_GND_VCC`|`0x23`|
|`IS31FL3745_I2C_ADDRESS_SCL_GND`|`0x24`|
|`IS31FL3745_I2C_ADDRESS_SCL_SCL`|`0x25`|
|`IS31FL3745_I2C_ADDRESS_SCL_SDA`|`0x26`|
|`IS31FL3745_I2C_ADDRESS_SCL_VCC`|`0x27`|
|`IS31FL3745_I2C_ADDRESS_SDA_GND`|`0x28`|
|`IS31FL3745_I2C_ADDRESS_SDA_SCL`|`0x29`|
|`IS31FL3745_I2C_ADDRESS_SDA_SDA`|`0x2A`|
|`IS31FL3745_I2C_ADDRESS_SDA_VCC`|`0x2B`|
|`IS31FL3745_I2C_ADDRESS_VCC_GND`|`0x2C`|
|`IS31FL3745_I2C_ADDRESS_VCC_SCL`|`0x2D`|
|`IS31FL3745_I2C_ADDRESS_VCC_SDA`|`0x2E`|
|`IS31FL3745_I2C_ADDRESS_VCC_VCC`|`0x2F`|
### Multi-Driver Synchronization {#multi-driver-synchronization}
Multiple IS31FL3745 drivers can be synchronized by connecting the `SYNC` pins together. One driver must be designated as the "master", and the others configured as "slave".
To do this, set the `IS31FL3745_SYNC_n` defines accordingly in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|------------------------|---------------------------|
|`IS31FL3745_SYNC_NONE` |No synchronization |
|`IS31FL3745_SYNC_MASTER`|Driver configured as master|
|`IS31FL3745_SYNC_SLAVE` |Driver configured as slave |
### De-Ghosting {#de-ghosting}
These settings control the pulldown and pullup resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 23) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3745_SW_PULLDOWN IS31FL3745_PDR_2K_OHM_SW_OFF
#define IS31FL3745_CS_PULLUP IS31FL3745_PUR_2K_OHM_CS_OFF
```
Valid values for `IS31FL3745_SW_PULLDOWN` are:
|Define |Resistance |
|-------------------------------|------------------------------|
|`IS31FL3745_PDR_0_OHM` |None (default) |
|`IS31FL3745_PDR_0K5_OHM_SW_OFF`|0.5 kΩ in SWx off time |
|`IS31FL3745_PDR_1K_OHM_SW_OFF` |1 kΩ in SWx off time |
|`IS31FL3745_PDR_2K_OHM_SW_OFF` |2 kΩ in SWx off time (default)|
|`IS31FL3745_PDR_1K_OHM` |1 kΩ |
|`IS31FL3745_PDR_2K_OHM` |2 kΩ |
|`IS31FL3745_PDR_4K_OHM` |4 kΩ |
|`IS31FL3745_PDR_8K_OHM` |8 kΩ |
Valid values for `IS31FL3745_CS_PULLUP` are:
|Define |Resistance |
|-------------------------------|------------------------------|
|`IS31FL3745_PUR_0_OHM` |None (default) |
|`IS31FL3745_PUR_0K5_OHM_CS_OFF`|0.5 kΩ in CSy off time |
|`IS31FL3745_PUR_1K_OHM_CS_OFF` |1 kΩ in CSy off time |
|`IS31FL3745_PUR_2K_OHM_CS_OFF` |2 kΩ in CSy off time (default)|
|`IS31FL3745_PUR_1K_OHM` |1 kΩ |
|`IS31FL3745_PUR_2K_OHM` |2 kΩ |
|`IS31FL3745_PUR_4K_OHM` |4 kΩ |
|`IS31FL3745_PUR_8K_OHM` |8 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSy` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3745_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3745_led_t PROGMEM g_is31fl3745_leds[IS31FL3745_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to the `SW1` pin, and their cathodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3745_led_t PROGMEM g_is31fl3745_leds[IS31FL3745_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 12, figure 9.
## API {#api}
### `struct is31fl3745_led_t` {#api-is31fl3745-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3745-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3745_init(uint8_t index)` {#api-is31fl3745-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3745-init-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3745_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3745-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3745-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3745_select_page(uint8_t index, uint8_t page)` {#api-is31fl3745-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3745-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3745_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3745-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3745_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3745-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3745_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3745_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3745-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3745-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3745_set_value(int index, uint8_t value)` {#api-is31fl3745-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3745_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3745-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3745_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3745_set_value_all(uint8_t value)` {#api-is31fl3745-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3745-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3745_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3745-set-scaling-register-rgb}
Configure the scaling registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3745_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3745-set-scaling-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3745_leds` array).
- `uint8_t red`
The scaling value for the red channel.
- `uint8_t green`
The scaling value for the green channel.
- `uint8_t blue`
The scaling value for the blue channel.
---
### `void is31fl3745_set_scaling_register(uint8_t index, uint8_t value)` {#api-is31fl3745-set-scaling-register-mono}
Configure the scaling register for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3745_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3745-set-scaling-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3745_leds` array).
- `uint8_t value`
The scaling value for the LED.
---
### `void is31fl3745_update_pwm_buffers(uint8_t index)` {#api-is31fl3745-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3745-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3745_update_scaling_registers(uint8_t index)` {#api-is31fl3745-update-scaling-registers}
Flush the scaling register values to the LED driver.
#### Arguments {#api-is31fl3745-update-scaling-registers-arguments}
- `uint8_t index`
The driver index.

327
docs/drivers/is31fl3746a.md Normal file
View File

@ -0,0 +1,327 @@
# IS31FL3746A Driver {#is31fl3746a-driver}
I²C 18x4 LED matrix driver by Lumissil. Supports a maximum of four drivers, each controlling up to 72 single-color LEDs, or 24 RGB LEDs.
[IS31FL3746A Datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf)
## Usage {#usage}
The IS31FL3746A driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `is31fl3746a` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3746a-mono.c # For single-color
SRC += is31fl3746a.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|-----------------------------|----------------------------------|----------------------------------------------------|
|`IS31FL3746A_SDB_PIN` |*Not defined* |The GPIO pin connected to the drivers' shutdown pins|
|`IS31FL3746A_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`IS31FL3746A_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`IS31FL3746A_I2C_ADDRESS_1` |*Not defined* |The I²C address of driver 0 |
|`IS31FL3746A_I2C_ADDRESS_2` |*Not defined* |The I²C address of driver 1 |
|`IS31FL3746A_I2C_ADDRESS_3` |*Not defined* |The I²C address of driver 2 |
|`IS31FL3746A_I2C_ADDRESS_4` |*Not defined* |The I²C address of driver 3 |
|`IS31FL3746A_CONFIGURATION` |`0x01` |The value of the configuration register |
|`IS31FL3746A_PWM_FREQUENCY` |`IS31FL3746A_PWM_FREQUENCY_29K_HZ`|The PWM frequency of the LEDs |
|`IS31FL3746A_SW_PULLDOWN` |`IS31FL3746A_PDR_2K_OHM_SW_OFF` |The `SWx` pulldown resistor value |
|`IS31FL3746A_CS_PULLUP` |`IS31FL3746A_PUR_2K_OHM_CS_OFF` |The `CSx` pullup resistor value |
|`IS31FL3746A_GLOBAL_CURRENT` |`0xFF` |The global current control value |
### I²C Addressing {#i2c-addressing}
The IS31FL3746A has 16 possible 7-bit I²C addresses, depending on how the `ADDR1` and `ADDR2` pins are connected.
To configure this, set the `IS31FL3746A_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|---------------------------------|------|
|`IS31FL3746A_I2C_ADDRESS_GND_GND`|`0x60`|
|`IS31FL3746A_I2C_ADDRESS_GND_SCL`|`0x61`|
|`IS31FL3746A_I2C_ADDRESS_GND_SDA`|`0x62`|
|`IS31FL3746A_I2C_ADDRESS_GND_VCC`|`0x63`|
|`IS31FL3746A_I2C_ADDRESS_SCL_GND`|`0x64`|
|`IS31FL3746A_I2C_ADDRESS_SCL_SCL`|`0x65`|
|`IS31FL3746A_I2C_ADDRESS_SCL_SDA`|`0x66`|
|`IS31FL3746A_I2C_ADDRESS_SCL_VCC`|`0x67`|
|`IS31FL3746A_I2C_ADDRESS_SDA_GND`|`0x68`|
|`IS31FL3746A_I2C_ADDRESS_SDA_SCL`|`0x69`|
|`IS31FL3746A_I2C_ADDRESS_SDA_SDA`|`0x6A`|
|`IS31FL3746A_I2C_ADDRESS_SDA_VCC`|`0x6B`|
|`IS31FL3746A_I2C_ADDRESS_VCC_GND`|`0x6C`|
|`IS31FL3746A_I2C_ADDRESS_VCC_SCL`|`0x6D`|
|`IS31FL3746A_I2C_ADDRESS_VCC_SDA`|`0x6E`|
|`IS31FL3746A_I2C_ADDRESS_VCC_VCC`|`0x6F`|
### PWM Frequency {#pwm-frequency}
The PWM frequency can be adjusted by adding the following to your `config.h`:
```c
#define IS31FL3746A_PWM_FREQUENCY IS31FL3746A_PWM_FREQUENCY_29K_HZ
```
Valid values are:
|Define |Frequency |
|-----------------------------------|----------------|
|`IS31FL3746A_PWM_FREQUENCY_29K_HZ` |29 kHz (default)|
|`IS31FL3746A_PWM_FREQUENCY_14K5_HZ`|14.5 kHz |
|`IS31FL3746A_PWM_FREQUENCY_7K25_HZ`|7.25 kHz |
|`IS31FL3746A_PWM_FREQUENCY_3K63_HZ`|3.63 kHz |
|`IS31FL3746A_PWM_FREQUENCY_1K81_HZ`|1.81 kHz |
|`IS31FL3746A_PWM_FREQUENCY_906_HZ` |906 Hz |
|`IS31FL3746A_PWM_FREQUENCY_453_HZ` |453 Hz |
### De-Ghosting {#de-ghosting}
These settings control the pulldown and pullup resistor values on the `SWy` and `CSx` pins respectively, for the purposes of eliminating ghosting. Refer to the datasheet (p. 23) for more information on how and why this occurs.
To adjust the resistor values, add the following to your `config.h`:
```c
#define IS31FL3746A_SW_PULLDOWN IS31FL3746A_PDR_2K_OHM_SW_OFF
#define IS31FL3746A_CS_PULLUP IS31FL3746A_PUR_2K_OHM_CS_OFF
```
Valid values for `IS31FL3746A_SW_PULLDOWN` are:
|Define |Resistance |
|--------------------------------|------------------------------|
|`IS31FL3746A_PDR_0_OHM` |None |
|`IS31FL3746A_PDR_0K5_OHM_SW_OFF`|0.5 kΩ in SWx off time |
|`IS31FL3746A_PDR_1K_OHM_SW_OFF` |1 kΩ in SWx off time |
|`IS31FL3746A_PDR_2K_OHM_SW_OFF` |2 kΩ in SWx off time (default)|
|`IS31FL3746A_PDR_1K_OHM` |1 kΩ |
|`IS31FL3746A_PDR_2K_OHM` |2 kΩ |
|`IS31FL3746A_PDR_4K_OHM` |4 kΩ |
|`IS31FL3746A_PDR_8K_OHM` |8 kΩ |
Valid values for `IS31FL3746A_CS_PULLUP` are:
|Define |Resistance |
|--------------------------------|------------------------------|
|`IS31FL3746A_PUR_0_OHM` |None (default) |
|`IS31FL3746A_PUR_0K5_OHM_CS_OFF`|0.5 kΩ in CSy off time |
|`IS31FL3746A_PUR_1K_OHM_CS_OFF` |1 kΩ in CSy off time |
|`IS31FL3746A_PUR_2K_OHM_CS_OFF` |2 kΩ in CSy off time (default)|
|`IS31FL3746A_PUR_1K_OHM` |1 kΩ |
|`IS31FL3746A_PUR_2K_OHM` |2 kΩ |
|`IS31FL3746A_PUR_4K_OHM` |4 kΩ |
|`IS31FL3746A_PUR_8K_OHM` |8 kΩ |
### Global Current Control {#global-current-control}
This setting controls the current sunk by the `CSy` pins, from 0 to 255. By default, the value is the maximum (255), but if you need to lower it, add the following to your `config.h`:
```c
#define IS31FL3746A_GLOBAL_CURRENT 0xFF
```
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const is31fl3746a_led_t PROGMEM g_is31fl3746a_leds[IS31FL3746A_LED_COUNT] = {
/* Driver
* | R G B */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their anodes connected to the `SW1` pin, and their cathodes on the `CS1`, `CS2` and `CS3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const is31fl3746a_led_t PROGMEM g_is31fl3746a_leds[IS31FL3746A_LED_COUNT] = {
/* Driver
* | V */
{0, SW1_CS1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 13, figure 8.
## API {#api}
### `struct is31fl3746a_led_t` {#api-is31fl3746a-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-is31fl3746a-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void is31fl3746a_init(uint8_t index)` {#api-is31fl3746a-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-is31fl3746a-init-arguments}
- `uint8_t index`
The driver index.
- `uint8_t sync`
Sync configuration of the LED driver.
---
### `void is31fl3746a_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-is31fl3746a-write-register}
Set the value of the given register.
#### Arguments {#api-is31fl3746a-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void is31fl3746a_select_page(uint8_t index, uint8_t page)` {#api-is31fl3746a-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-is31fl3746a-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void is31fl3746a_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3746a-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3746a_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3746a-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3746a_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3746a_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3746a-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-is31fl3746a-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void is31fl3746a_set_value(int index, uint8_t value)` {#api-is31fl3746a-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3746a_update_pwm_buffers()` after you are finished.
#### Arguments {#api-is31fl3746a-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_is31fl3746a_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3746a_set_value_all(uint8_t value)` {#api-is31fl3746a-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-is31fl3746a-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void is31fl3746a_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)` {#api-is31fl3746a-set-scaling-register-rgb}
Configure the scaling registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `is31fl3746a_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3746a-set-scaling-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3746a_leds` array).
- `uint8_t red`
The scaling value for the red channel.
- `uint8_t green`
The scaling value for the green channel.
- `uint8_t blue`
The scaling value for the blue channel.
---
### `void is31fl3746a_set_scaling_register(uint8_t index, uint8_t value)` {#api-is31fl3746a-set-scaling-register-mono}
Configure the scaling register for a single LED (single-color driver only). This function does not immediately update the LEDs; call `is31fl3746a_update_scaling_registers()` after you are finished.
#### Arguments {#api-is31fl3746a-set-scaling-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_is31fl3746a_leds` array).
- `uint8_t value`
The scaling value for the LED.
---
### `void is31fl3746a_update_pwm_buffers(uint8_t index)` {#api-is31fl3746a-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-is31fl3746a-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void is31fl3746a_update_scaling_registers(uint8_t index)` {#api-is31fl3746a-update-scaling-registers}
Flush the scaling register values to the LED driver.
#### Arguments {#api-is31fl3746a-update-scaling-registers-arguments}
- `uint8_t index`
The driver index.

245
docs/drivers/snled27351.md Normal file
View File

@ -0,0 +1,245 @@
# SNLED27351 Driver {#snled27351-driver}
I²C 16x12 LED matrix driver by Sonix. Supports a maximum of four drivers, each controlling up to 192 single-color LEDs, or 64 RGB LEDs.
A slightly modified version of this IC is also known as "CKLED2001".
[SNLED27351 Datasheet](https://www.sonix.com.tw/files/1/D235860C0C037C28E050007F01001CBE)
## Usage {#usage}
The SNLED27351 driver code is automatically included if you are using the [LED Matrix](../features/led_matrix) or [RGB Matrix](../features/rgb_matrix) feature with the `snled27351` driver set, and you would use those APIs instead.
However, if you need to use the driver standalone, add this to your `rules.mk`:
```make
COMMON_VPATH += $(DRIVER_PATH)/led
SRC += snled27351-mono.c # For single-color
SRC += snled27351.c # For RGB
I2C_DRIVER_REQUIRED = yes
```
## Basic Configuration {#basic-configuration}
Add the following to your `config.h`:
|Define |Default |Description |
|----------------------------|-------------|----------------------------------------------------|
|`SNLED27351_SDB_PIN` |*Not defined*|The GPIO pin connected to the drivers' shutdown pins|
|`SNLED27351_I2C_TIMEOUT` |`100` |The I²C timeout in milliseconds |
|`SNLED27351_I2C_PERSISTENCE`|`0` |The number of times to retry I²C transmissions |
|`SNLED27351_I2C_ADDRESS_1` |*Not defined*|The I²C address of driver 0 |
|`SNLED27351_I2C_ADDRESS_2` |*Not defined*|The I²C address of driver 1 |
|`SNLED27351_I2C_ADDRESS_3` |*Not defined*|The I²C address of driver 2 |
|`SNLED27351_I2C_ADDRESS_4` |*Not defined*|The I²C address of driver 3 |
### I²C Addressing {#i2c-addressing}
The SNLED27351 has four possible 7-bit I²C addresses, depending on how the `ADDR` pin is connected.
To configure this, set the `SNLED27351_I2C_ADDRESS_n` defines to one of the following in your `config.h`, where *n* denotes the driver index:
|Define |Value |
|------------------------------|------|
|`SNLED27351_I2C_ADDRESS_GND` |`0x74`|
|`SNLED27351_I2C_ADDRESS_SCL` |`0x75`|
|`SNLED27351_I2C_ADDRESS_SDA` |`0x76`|
|`SNLED27351_I2C_ADDRESS_VDDIO`|`0x77`|
## ARM/ChibiOS Configuration {#arm-configuration}
Depending on the ChibiOS board configuration, you may need to [enable and configure I²C](i2c#arm-configuration) at the keyboard level.
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
```c
const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {
/* Driver
* | R G B */
{0, CB1_CA1, CB1_CA2, CB1_CA3},
// etc...
};
```
In this example, the red, green and blue channels for the first LED index on driver 0 all have their cathodes connected to the `CB1` pin, and their anodes on the `CA1`, `CA2` and `CA3` pins respectively.
For the single-color driver, the principle is the same, but there is only one channel:
```c
const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {
/* Driver
* | V */
{0, CB1_CA1},
// etc...
};
```
These values correspond to the register indices as shown in the datasheet on page 13.
## API {#api}
### `struct snled27351_led_t` {#api-snled27351-led-t}
Contains the PWM register addresses for a single RGB LED.
#### Members {#api-snled27351-led-t-members}
- `uint8_t driver`
The driver index of the LED, from 0 to 3.
- `uint8_t r`
The output PWM register address for the LED's red channel (RGB driver only).
- `uint8_t g`
The output PWM register address for the LED's green channel (RGB driver only).
- `uint8_t b`
The output PWM register address for the LED's blue channel (RGB driver only).
- `uint8_t v`
The output PWM register address for the LED (single-color driver only).
---
### `void snled27351_init(uint8_t index)` {#api-snled27351-init}
Initialize the LED driver. This function should be called first.
#### Arguments {#api-snled27351-init-arguments}
- `uint8_t index`
The driver index.
---
### `void snled27351_write_register(uint8_t index, uint8_t reg, uint8_t data)` {#api-snled27351-write-register}
Set the value of the given register.
#### Arguments {#api-snled27351-write-register-arguments}
- `uint8_t index`
The driver index.
- `uint8_t reg`
The register address.
- `uint8_t data`
The value to set.
---
### `void snled27351_select_page(uint8_t index, uint8_t page)` {#api-snled27351-select-page}
Change the current page for configuring the LED driver.
#### Arguments {#api-snled27351-select-page-arguments}
- `uint8_t index`
The driver index.
- `uint8_t page`
The page number to select.
---
### `void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-snled27351-set-color}
Set the color of a single LED (RGB driver only). This function does not immediately update the LEDs; call `snled27351_update_pwm_buffers()` after you are finished.
#### Arguments {#api-snled27351-set-color-arguments}
- `int index`
The LED index (ie. the index into the `g_snled27351_leds` array).
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void snled27351_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-snled27351-set-color-all}
Set the color of all LEDs (RGB driver only).
#### Arguments {#api-snled27351-set-color-all-arguments}
- `uint8_t red`
The red value to set.
- `uint8_t green`
The green value to set.
- `uint8_t blue`
The blue value to set.
---
### `void snled27351_set_value(int index, uint8_t value)` {#api-snled27351-set-value}
Set the brightness of a single LED (single-color driver only). This function does not immediately update the LEDs; call `snled27351_update_pwm_buffers()` after you are finished.
#### Arguments {#api-snled27351-set-value-arguments}
- `int index`
The LED index (ie. the index into the `g_snled27351_leds` array).
- `uint8_t value`
The brightness value to set.
---
### `void snled27351_set_value_all(uint8_t value)` {#api-snled27351-set-value-all}
Set the brightness of all LEDs (single-color driver only).
#### Arguments {#api-snled27351-set-value-all-arguments}
- `uint8_t value`
The brightness value to set.
---
### `void snled27351_set_led_control_register(uint8_t index, bool red, bool green, bool blue)` {#api-snled27351-set-led-control-register-rgb}
Configure the LED control registers for a single LED (RGB driver only). This function does not immediately update the LEDs; call `snled27351_update_led_control_registers()` after you are finished.
#### Arguments {#api-snled27351-set-led-control-register-rgb-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_snled27351_leds` array).
- `bool red`
Enable or disable the red channel.
- `bool green`
Enable or disable the green channel.
- `bool blue`
Enable or disable the blue channel.
---
### `void snled27351_set_led_control_register(uint8_t index, bool value)` {#api-snled27351-set-led-control-register-mono}
Configure the LED control registers for a single LED (single-color driver only). This function does not immediately update the LEDs; call `snled27351_update_led_control_registers()` after you are finished.
#### Arguments {#api-snled27351-set-led-control-register-mono-arguments}
- `uint8_t index`
The LED index (ie. the index into the `g_snled27351_leds` array).
- `bool value`
Enable or disable the LED.
---
### `void snled27351_update_pwm_buffers(uint8_t index)` {#api-snled27351-update-pwm-buffers}
Flush the PWM values to the LED driver.
#### Arguments {#api-snled27351-update-pwm-buffers-arguments}
- `uint8_t index`
The driver index.
---
### `void snled27351_update_led_control_registers(uint8_t index)` {#api-snled27351-update-led-control-registers}
Flush the LED control register values to the LED driver.
#### Arguments {#api-snled27351-update-led-control-registers-arguments}
- `uint8_t index`
The driver index.

View File

@ -40,7 +40,7 @@ That's amazing! We would love to assist you with that!
In fact, we have a [whole page](https://qmk.fm/powered/) dedicated to adding QMK Branding to your page and keyboard. This covers pretty much everything you need (knowledge and images) to officially support QMK. In fact, we have a [whole page](https://qmk.fm/powered/) dedicated to adding QMK Branding to your page and keyboard. This covers pretty much everything you need (knowledge and images) to officially support QMK.
If you have any questions about this, open an issue or head to [Discord](https://discord.gg/Uq7gcHh). If you have any questions about this, open an issue or head to [Discord](https://discord.gg/qmk).
## What Differences Are There Between QMK and TMK? ## What Differences Are There Between QMK and TMK?

View File

@ -10,7 +10,7 @@ The following converters are available at this time:
|------------|-------------------| |------------|-------------------|
| `promicro` | `proton_c` | | `promicro` | `proton_c` |
| `promicro` | `kb2040` | | `promicro` | `kb2040` |
| `promicro` | `promicro_rp2040` | | `promicro` | `sparkfun_pm2040` |
| `promicro` | `blok` | | `promicro` | `blok` |
| `promicro` | `bit_c_pro` | | `promicro` | `bit_c_pro` |
| `promicro` | `stemcell` | | `promicro` | `stemcell` |
@ -77,7 +77,7 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
|------------------------------------------------------------------------------------------|-------------------| |------------------------------------------------------------------------------------------|-------------------|
| [Proton C](https://qmk.fm/proton-c/) | `proton_c` | | [Proton C](https://qmk.fm/proton-c/) | `proton_c` |
| [Adafruit KB2040](https://learn.adafruit.com/adafruit-kb2040) | `kb2040` | | [Adafruit KB2040](https://learn.adafruit.com/adafruit-kb2040) | `kb2040` |
| [SparkFun Pro Micro - RP2040](https://www.sparkfun.com/products/18288) | `promicro_rp2040` | | [SparkFun Pro Micro - RP2040](https://www.sparkfun.com/products/18288) | `sparkfun_pm2040` |
| [Blok](https://boardsource.xyz/store/628b95b494dfa308a6581622) | `blok` | | [Blok](https://boardsource.xyz/store/628b95b494dfa308a6581622) | `blok` |
| [Bit-C PRO](https://nullbits.co/bit-c-pro) | `bit_c_pro` | | [Bit-C PRO](https://nullbits.co/bit-c-pro) | `bit_c_pro` |
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` | | [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
@ -94,7 +94,7 @@ Converter summary:
|-------------------|---------------------------------|------------------------------|-------------------------------------| |-------------------|---------------------------------|------------------------------|-------------------------------------|
| `proton_c` | `-e CONVERT_TO=proton_c` | `CONVERT_TO=proton_c` | `#ifdef CONVERT_TO_PROTON_C` | | `proton_c` | `-e CONVERT_TO=proton_c` | `CONVERT_TO=proton_c` | `#ifdef CONVERT_TO_PROTON_C` |
| `kb2040` | `-e CONVERT_TO=kb2040` | `CONVERT_TO=kb2040` | `#ifdef CONVERT_TO_KB2040` | | `kb2040` | `-e CONVERT_TO=kb2040` | `CONVERT_TO=kb2040` | `#ifdef CONVERT_TO_KB2040` |
| `promicro_rp2040` | `-e CONVERT_TO=promicro_rp2040` | `CONVERT_TO=promicro_rp2040` | `#ifdef CONVERT_TO_PROMICRO_RP2040` | | `sparkfun_pm2040` | `-e CONVERT_TO=sparkfun_pm2040` | `CONVERT_TO=sparkfun_pm2040` | `#ifdef CONVERT_TO_SPARKFUN_PM2040` |
| `blok` | `-e CONVERT_TO=blok` | `CONVERT_TO=blok` | `#ifdef CONVERT_TO_BLOK` | | `blok` | `-e CONVERT_TO=blok` | `CONVERT_TO=blok` | `#ifdef CONVERT_TO_BLOK` |
| `bit_c_pro` | `-e CONVERT_TO=bit_c_pro` | `CONVERT_TO=bit_c_pro` | `#ifdef CONVERT_TO_BIT_C_PRO` | | `bit_c_pro` | `-e CONVERT_TO=bit_c_pro` | `CONVERT_TO=bit_c_pro` | `#ifdef CONVERT_TO_BIT_C_PRO` |
| `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` | | `stemcell` | `-e CONVERT_TO=stemcell` | `CONVERT_TO=stemcell` | `#ifdef CONVERT_TO_STEMCELL` |
@ -135,7 +135,7 @@ The following defaults are based on what has been implemented for [RP2040](platf
| USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) | | USB Host (e.g. USB-USB converter) | Not supported (USB host code is AVR specific and is not currently supported on ARM) |
| [Split keyboards](features/split_keyboard) | Partial via `PIO` vendor driver - heavily dependent on enabled features | | [Split keyboards](features/split_keyboard) | Partial via `PIO` vendor driver - heavily dependent on enabled features |
### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi {#promicro_rp2040 } ### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi {#sparkfun_pm2040 }
Feature set is identical to [Adafruit KB2040](#kb2040). Feature set is identical to [Adafruit KB2040](#kb2040).

View File

@ -9,15 +9,15 @@ ENCODER_ENABLE = yes
and this to your `config.h`: and this to your `config.h`:
```c ```c
#define ENCODERS_PAD_A { B12 } #define ENCODER_A_PINS { B12 }
#define ENCODERS_PAD_B { B13 } #define ENCODER_B_PINS { B13 }
``` ```
Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.: Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.:
```c ```c
#define ENCODERS_PAD_A { encoder1a, encoder2a } #define ENCODER_A_PINS { encoder1a, encoder2a }
#define ENCODERS_PAD_B { encoder1b, encoder2b } #define ENCODER_B_PINS { encoder1b, encoder2b }
``` ```
If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. They can also be flipped with a define: If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. They can also be flipped with a define:
@ -49,8 +49,8 @@ For 4× encoders you also can assign default position if encoder skips pulses wh
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this: If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
```c ```c
#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a } #define ENCODER_A_PINS_RIGHT { encoder1a, encoder2a }
#define ENCODERS_PAD_B_RIGHT { encoder1b, encoder2b } #define ENCODER_B_PINS_RIGHT { encoder1b, encoder2b }
#define ENCODER_RESOLUTIONS_RIGHT { 2, 4 } #define ENCODER_RESOLUTIONS_RIGHT { 2, 4 }
``` ```
@ -59,11 +59,11 @@ If the `_RIGHT` definitions aren't specified in your `config.h`, then the non-`_
Additionally, if one side does not have an encoder, you can specify `{}` for the pins/resolution -- for example, a split keyboard with only a right-side encoder: Additionally, if one side does not have an encoder, you can specify `{}` for the pins/resolution -- for example, a split keyboard with only a right-side encoder:
```c ```c
#define ENCODERS_PAD_A { } #define ENCODER_A_PINS { }
#define ENCODERS_PAD_B { } #define ENCODER_B_PINS { }
#define ENCODER_RESOLUTIONS { } #define ENCODER_RESOLUTIONS { }
#define ENCODERS_PAD_A_RIGHT { B12 } #define ENCODER_A_PINS_RIGHT { B12 }
#define ENCODERS_PAD_B_RIGHT { B13 } #define ENCODER_B_PINS_RIGHT { B13 }
#define ENCODER_RESOLUTIONS_RIGHT { 4 } #define ENCODER_RESOLUTIONS_RIGHT { 4 }
``` ```
@ -84,10 +84,10 @@ Your `keymap.c` will then need an encoder mapping defined (for four layers and t
```c ```c
#if defined(ENCODER_MAP_ENABLE) #if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = { const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, [0] = { ENCODER_CCW_CW(MS_WHLU, MS_WHLD), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(UG_HUED, UG_HUEU), ENCODER_CCW_CW(UG_SATD, UG_SATU) }, [1] = { ENCODER_CCW_CW(UG_HUED, UG_HUEU), ENCODER_CCW_CW(UG_SATD, UG_SATU) },
[2] = { ENCODER_CCW_CW(UG_VALD, UG_VALU), ENCODER_CCW_CW(UG_SPDD, UG_SPDU) }, [2] = { ENCODER_CCW_CW(UG_VALD, UG_VALU), ENCODER_CCW_CW(UG_SPDD, UG_SPDU) },
[3] = { ENCODER_CCW_CW(UG_PREV, UG_NEXT), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) }, [3] = { ENCODER_CCW_CW(UG_PREV, UG_NEXT), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) },
}; };
#endif #endif
``` ```
@ -174,13 +174,13 @@ Multiple encoders may share pins so long as each encoder has a distinct pair of
For example you can support two encoders using only 3 pins like this For example you can support two encoders using only 3 pins like this
``` ```
#define ENCODERS_PAD_A { B1, B1 } #define ENCODER_A_PINS { B1, B1 }
#define ENCODERS_PAD_B { B2, B3 } #define ENCODER_B_PINS { B2, B3 }
``` ```
You could even support three encoders using only three pins (one per encoder) however in this configuration, rotating two encoders which share pins simultaneously will often generate incorrect output. For example: You could even support three encoders using only three pins (one per encoder) however in this configuration, rotating two encoders which share pins simultaneously will often generate incorrect output. For example:
``` ```
#define ENCODERS_PAD_A { B1, B1, B2 } #define ENCODER_A_PINS { B1, B1, B2 }
#define ENCODERS_PAD_B { B2, B3, B3 } #define ENCODER_B_PINS { B2, B3, B3 }
``` ```
Here rotating Encoder 0 `B1 B2` and Encoder 1 `B1 B3` could be interpreted as rotating Encoder 2 `B2 B3` or `B3 B2` depending on the timing. This may still be a useful configuration depending on your use case Here rotating Encoder 0 `B1 B2` and Encoder 1 `B1 B3` could be interpreted as rotating Encoder 2 `B2 B3` or `B3 B2` depending on the timing. This may still be a useful configuration depending on your use case

View File

@ -14,7 +14,7 @@ You can use key overrides in a similar way to momentary layer/fn keys to activat
To enable this feature, you need to add `KEY_OVERRIDE_ENABLE = yes` to your `rules.mk`. To enable this feature, you need to add `KEY_OVERRIDE_ENABLE = yes` to your `rules.mk`.
Then, in your `keymap.c` file, you'll need to define the array `key_overrides`, which defines all key overrides to be used. Each override is a value of type `key_override_t`. The array `key_overrides` is `NULL`-terminated and contains pointers to `key_override_t` values (`const key_override_t **`). Then, in your `keymap.c` file, you'll need to define the array `key_overrides`, which defines all key overrides to be used. Each override is a value of type `key_override_t`. The array `key_overrides`contains pointers to `key_override_t` values (`const key_override_t **`).
## Creating Key Overrides {#creating-key-overrides} ## Creating Key Overrides {#creating-key-overrides}
@ -42,9 +42,8 @@ This shows how the mentioned example of sending `delete` when `shift` + `backspa
const key_override_t delete_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_BSPC, KC_DEL); const key_override_t delete_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_BSPC, KC_DEL);
// This globally defines all key overrides to be used // This globally defines all key overrides to be used
const key_override_t **key_overrides = (const key_override_t *[]){ const key_override_t *key_overrides[] = {
&delete_key_override, &delete_key_override
NULL // Null terminate the array of overrides!
}; };
``` ```
@ -91,14 +90,13 @@ const key_override_t brightness_up_override = ko_make_with_layers_negmods_and_op
const key_override_t brightness_down_override = ko_make_basic(MOD_MASK_CSA, KC_MPLY, KC_BRID); const key_override_t brightness_down_override = ko_make_basic(MOD_MASK_CSA, KC_MPLY, KC_BRID);
// This globally defines all key overrides to be used // This globally defines all key overrides to be used
const key_override_t **key_overrides = (const key_override_t *[]){ const key_override_t *key_overrides[] = {
&next_track_override, &next_track_override,
&prev_track_override, &prev_track_override,
&vol_up_override, &vol_up_override,
&vol_down_override, &vol_down_override,
&brightness_up_override, &brightness_up_override,
&brightness_down_override, &brightness_down_override
NULL
}; };
``` ```
@ -112,10 +110,9 @@ const key_override_t tilde_esc_override = ko_make_basic(MOD_MASK_SHIFT, KC_ESC,
// GUI + esc = ` // GUI + esc = `
const key_override_t grave_esc_override = ko_make_basic(MOD_MASK_GUI, KC_ESC, KC_GRV); const key_override_t grave_esc_override = ko_make_basic(MOD_MASK_GUI, KC_ESC, KC_GRV);
const key_override_t **key_overrides = (const key_override_t *[]){ const key_override_t *key_overrides[] = {
&tilde_esc_override, &tilde_esc_override,
&grave_esc_override, &grave_esc_override
NULL
}; };
``` ```

View File

@ -21,9 +21,8 @@ There are three ways to get the lock LED state:
The `host_keyboard_led_state()` may reflect an updated state before `led_update_user()` is called. The `host_keyboard_led_state()` may reflect an updated state before `led_update_user()` is called.
::: :::
Two deprecated functions that provide the LED state as `uint8_t`: Deprecated functions that provide the LED state as `uint8_t`:
* `uint8_t led_set_user(uint8_t usb_led)`
* `uint8_t host_keyboard_leds()` * `uint8_t host_keyboard_leds()`
## Configuration Options ## Configuration Options
@ -50,10 +49,6 @@ When the configuration options do not provide enough flexibility, the following
Both receives LED state as a struct parameter. Returning `true` in `led_update_user()` will allow the keyboard level code in `led_update_kb()` to run as well. Returning `false` will override the keyboard level code, depending on how the keyboard level function is set up. Both receives LED state as a struct parameter. Returning `true` in `led_update_user()` will allow the keyboard level code in `led_update_kb()` to run as well. Returning `false` will override the keyboard level code, depending on how the keyboard level function is set up.
::: tip
This boolean return type of `led_update_user` allows for overriding keyboard LED controls, and is thus recommended over the void `led_set_user` function.
:::
### Example of keyboard LED update implementation ### Example of keyboard LED update implementation
This is a template indicator function that can be implemented on keyboard level code: This is a template indicator function that can be implemented on keyboard level code:

View File

@ -4,176 +4,32 @@ This feature allows you to use LED matrices driven by external drivers. It hooks
If you want to use RGB LED's you should use the [RGB Matrix Subsystem](rgb_matrix) instead. If you want to use RGB LED's you should use the [RGB Matrix Subsystem](rgb_matrix) instead.
## Driver configuration {#driver-configuration} ## Driver Configuration {#driver-configuration}
---
### IS31FL3731 {#is31fl3731}
There is basic support for addressable LED matrix lighting with the I2C IS31FL3731 LED controller. To enable it, add this to your `rules.mk`: LED Matrix is an abstraction layer on top of an underlying LED driver API. The list of supported LED drivers is below; see the respective documentation for information on how to configure the driver.
|Driver |Max LEDs|
|-------------------------------------|--------|
|[IS31FL3218](../drivers/is31fl3218) |18 |
|[IS31FL3236](../drivers/is31fl3236) |36 |
|[IS31FL3729](../drivers/is31fl3729) |135 |
|[IS31FL3731](../drivers/is31fl3731) |144 |
|[IS31FL3733](../drivers/is31fl3733) |192 |
|[IS31FL3736](../drivers/is31fl3736) |96 |
|[IS31FL3737](../drivers/is31fl3737) |144 |
|[IS31FL3741](../drivers/is31fl3741) |351 |
|[IS31FL3742A](../drivers/is31fl3742a)|180 |
|[IS31FL3743A](../drivers/is31fl3743a)|198 |
|[IS31FL3745](../drivers/is31fl3745) |144 |
|[IS31FL3746A](../drivers/is31fl3746a)|72 |
|[SNLED27351](../drivers/snled27351) |192 |
To assign the LED Matrix driver, add the following to your `rules.mk`, for example:
```make ```make
LED_MATRIX_ENABLE = yes LED_MATRIX_DRIVER = is31fl3218
LED_MATRIX_DRIVER = is31fl3731
``` ```
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
| `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first LED driver | |
| `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second LED driver | |
| `IS31FL3731_I2C_ADDRESS_3` | (Optional) Address for the third LED driver | |
| `IS31FL3731_I2C_ADDRESS_4` | (Optional) Address for the fourth LED driver | |
Here is an example using 2 drivers.
```c
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 AD <-> GND
// 01 AD <-> SCL
// 10 AD <-> SDA
// 11 AD <-> VCC
// ADDR represents A1:A0 of the 7-bit address.
// The result is: 0b11101(ADDR)
#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
#define LED_DRIVER_1_LED_TOTAL 25
#define LED_DRIVER_2_LED_TOTAL 24
#define LED_MATRIX_LED_COUNT (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `LED_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)` will give very different results than `rand() % LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL`.
:::
For split keyboards using `LED_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `IS31FL3731_I2C_ADDRESS_1` for one and `IS31FL3731_I2C_ADDRESS_2` for the other one. Then, in `g_is31fl3731_leds`, fill out the correct driver index (0 or 1). If using one address, use `IS31FL3731_I2C_ADDRESS_1` for both, and use index 0 for `g_is31fl3731_leds`.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
* | | */
{ 0, C1_1 },
{ 0, C1_15 },
// ...
}
```
Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731-mono.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ).
---
### IS31FLCOMMON {#is31flcommon}
There is basic support for addressable LED matrix lighting with a selection of I2C ISSI Lumissil LED controllers through a shared common driver. To enable it, add this to your `rules.mk`:
```makefile
LED_MATRIX_ENABLE = yes
LED_MATRIX_DRIVER = <driver name>
```
Where `<driver name>` is the applicable LED driver chip as below
| Driver Name | Data Sheet | Capability |
|-------------|------------|------------|
| `IS31FL3742A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf) | 180 LED, 30x6 Matrix |
| `IS31FL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 198 LED, 18x11 Matrix |
| `IS31FL3745` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf) | 144 LED, 18x8 Matrix |
| `IS31FL3746A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf) | 72 LED, 18x4 Matrix |
You can use between 1 and 4 IC's. Do not specify `DRIVER_ADDR_<N>` define for IC's if not present on your keyboard. The `DRIVER_ADDR_1` default assumes that all Address pins on the controller have been connected to GND. Drivers that have SYNC functionality have the default settings to disable if 1 driver. If more than 1 drivers then `DRIVER_ADDR_1` will be set to Master and the remaiing ones set to Slave.
Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Optional) Address for the first LED driver | |
| `DRIVER_ADDR_<N>` | (Required) Address for the additional LED drivers | |
| `ISSI_SSR_<N>` | (Optional) Configuration for the Spread Spectrum Register | |
| `ISSI_CONFIGURATION` | (Optional) Configuration for the Configuration Register | |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `ISSI_PULLDOWNUP` | (Optional) Configuration for the Pull Up & Pull Down Register | |
| `ISSI_TEMP` | (Optional) Configuration for the Tempature Register | |
| `ISSI_PWM_ENABLE` | (Optional) Configuration for the PWM Enable Register | |
| `ISSI_PWM_SET` | (Optional) Configuration for the PWM Setting Register | |
| `ISSI_SCAL_LED ` | (Optional) Configuration for the LEDs Scaling Registers | 0xFF |
| `ISSI_MANUAL_SCALING` | (Optional) If you wish to configure the Scaling Registers manually | |
Defaults
| Variable | IS31FL3742A | IS31FL3743A | IS31FL3745 | IS31FL3746 |
|----------|-------------|-------------|------------|------------|
| `DRIVER_ADDR_1` | 0b0110000 | 0b0100000 | 0b0100000 | 0b1100000 |
| `ISSI_SSR_1` | 0x00 | 0x00 / 0x60 | 0x00 / 0xC0 | 0x00 |
| `ISSI_SSR_<2-4>` | 0x00 | 0x40 | 0x80 | 0x00 |
| `ISSI_CONFIGURATION` | 0x31 | 0x01 | 0x31 | 0x01 |
| `ISSI_PULLDOWNUP` | 0x55 | 0x33 | 0x33 | 0x33 |
| `ISSI_TEMP` | N/A | 0x00 | 0x00 | 0x00 |
| `ISSI_PWM_ENABLE` | N/A | N/A | N/A | 0x00 |
| `ISSI_PWM_SET` | 0x00 | N/A | N/A | 0x00 |
Here is an example using 2 drivers.
```c
#define DRIVER_ADDR_2 0b0100001
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42
#define LED_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `LED_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
:::
Currently only 4 drivers are supported, but it would be trivial to support for more. Note that using a combination of different drivers is not supported. All drivers must be of the same model.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | LED address
* | | */
{ 0, SW1_CS1 },
{ 0, SW1_CS2 },
// ...
}
```
Where `CSx_SWx` is the location of the LED in the matrix defined by the datasheet. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now).
`ISSI_MANUAL_SCALING` is used to override the Scaling for individual LED's. By default they will be set as per `ISSI_SCAL_LED`. In `config.h` set how many LED's you want to manually set scaling for.
Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
/* LED Index
* | Scaling
* | | */
{5, 120},
{9, 120},
....
}
```
Where LED Index is the position of the LED in the `g_is31_leds` array. The `scaling` value between 0 and 255 to be written to the Scaling Register.
---
## Common Configuration {#common-configuration} ## Common Configuration {#common-configuration}
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example: From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:

View File

@ -18,27 +18,27 @@ MOUSEKEY_ENABLE = yes
In your keymap you can use the following keycodes to map key presses to mouse actions: In your keymap you can use the following keycodes to map key presses to mouse actions:
|Key |Aliases |Description | |Key |Aliases |Description |
|----------------|---------|-----------------| |-------------------------|---------|---------------------------|
|`KC_MS_UP` |`KC_MS_U`|Move cursor up | |`QK_MOUSE_CURSOR_UP` |`MS_UP` |Mouse cursor up |
|`KC_MS_DOWN` |`KC_MS_D`|Move cursor down | |`QK_MOUSE_CURSOR_DOWN` |`MS_DOWN`|Mouse cursor down |
|`KC_MS_LEFT` |`KC_MS_L`|Move cursor left | |`QK_MOUSE_CURSOR_LEFT` |`MS_LEFT`|Mouse cursor left |
|`KC_MS_RIGHT` |`KC_MS_R`|Move cursor right| |`QK_MOUSE_CURSOR_RIGHT` |`MS_RGHT`|Mouse cursor right |
|`KC_MS_BTN1` |`KC_BTN1`|Press button 1 | |`QK_MOUSE_BUTTON_1` |`MS_BTN1`|Mouse button 1 |
|`KC_MS_BTN2` |`KC_BTN2`|Press button 2 | |`QK_MOUSE_BUTTON_2` |`MS_BTN2`|Mouse button 2 |
|`KC_MS_BTN3` |`KC_BTN3`|Press button 3 | |`QK_MOUSE_BUTTON_3` |`MS_BTN3`|Mouse button 3 |
|`KC_MS_BTN4` |`KC_BTN4`|Press button 4 | |`QK_MOUSE_BUTTON_4` |`MS_BTN4`|Mouse button 4 |
|`KC_MS_BTN5` |`KC_BTN5`|Press button 5 | |`QK_MOUSE_BUTTON_5` |`MS_BTN5`|Mouse button 5 |
|`KC_MS_BTN6` |`KC_BTN6`|Press button 6 | |`QK_MOUSE_BUTTON_6` |`MS_BTN6`|Mouse button 6 |
|`KC_MS_BTN7` |`KC_BTN7`|Press button 7 | |`QK_MOUSE_BUTTON_7` |`MS_BTN7`|Mouse button 7 |
|`KC_MS_BTN8` |`KC_BTN8`|Press button 8 | |`QK_MOUSE_BUTTON_8` |`MS_BTN8`|Mouse button 8 |
|`KC_MS_WH_UP` |`KC_WH_U`|Move wheel up | |`QK_MOUSE_WHEEL_UP` |`MS_WHLU`|Mouse wheel up |
|`KC_MS_WH_DOWN` |`KC_WH_D`|Move wheel down | |`QK_MOUSE_WHEEL_DOWN` |`MS_WHLD`|Mouse wheel down |
|`KC_MS_WH_LEFT` |`KC_WH_L`|Move wheel left | |`QK_MOUSE_WHEEL_LEFT` |`MS_WHLL`|Mouse wheel left |
|`KC_MS_WH_RIGHT`|`KC_WH_R`|Move wheel right | |`QK_MOUSE_WHEEL_RIGHT` |`MS_WHLR`|Mouse wheel right |
|`KC_MS_ACCEL0` |`KC_ACL0`|Set speed to 0 | |`QK_MOUSE_ACCELERATION_0`|`MS_ACL0`|Set mouse acceleration to 0|
|`KC_MS_ACCEL1` |`KC_ACL1`|Set speed to 1 | |`QK_MOUSE_ACCELERATION_1`|`MS_ACL1`|Set mouse acceleration to 1|
|`KC_MS_ACCEL2` |`KC_ACL2`|Set speed to 2 | |`QK_MOUSE_ACCELERATION_2`|`MS_ACL2`|Set mouse acceleration to 2|
## Configuring mouse keys ## Configuring mouse keys
@ -106,17 +106,17 @@ Tips:
### Constant mode ### Constant mode
In this mode you can define multiple different speeds for both the cursor and the mouse wheel. There is no acceleration. `KC_ACL0`, `KC_ACL1` and `KC_ACL2` change the cursor and scroll speed to their respective setting. In this mode you can define multiple different speeds for both the cursor and the mouse wheel. There is no acceleration. `MS_ACL0`, `MS_ACL1` and `MS_ACL2` change the cursor and scroll speed to their respective setting.
You can choose whether speed selection is momentary or tap-to-select: You can choose whether speed selection is momentary or tap-to-select:
* **Momentary:** The chosen speed is only active while you hold the respective key. When the key is raised, mouse keys returns to the unmodified speed. * **Momentary:** The chosen speed is only active while you hold the respective key. When the key is raised, mouse keys returns to the unmodified speed.
* **Tap-to-select:** The chosen speed is activated when you press the respective key and remains active even after the key has been raised. The default speed is that of `KC_ACL1`. There is no unmodified speed. * **Tap-to-select:** The chosen speed is activated when you press the respective key and remains active even after the key has been raised. The default speed is that of `MS_ACL1`. There is no unmodified speed.
The default speeds from slowest to fastest are as follows: The default speeds from slowest to fastest are as follows:
* **Momentary:** `KC_ACL0` < `KC_ACL1` < *unmodified* < `KC_ACL2` * **Momentary:** `MS_ACL0` < `MS_ACL1` < *unmodified* < `MS_ACL2`
* **Tap-to-select:** `KC_ACL0` < `KC_ACL1` < `KC_ACL2` * **Tap-to-select:** `MS_ACL0` < `MS_ACL1` < `MS_ACL2`
To use constant speed mode, you must at least define `MK_3_SPEED` in your keymaps `config.h` file: To use constant speed mode, you must at least define `MK_3_SPEED` in your keymaps `config.h` file:
@ -138,32 +138,32 @@ Use the following settings if you want to adjust cursor movement or scrolling:
|`MK_MOMENTARY_ACCEL` |*Not defined*|Enable momentary speed selection | |`MK_MOMENTARY_ACCEL` |*Not defined*|Enable momentary speed selection |
|`MK_C_OFFSET_UNMOD` |16 |Cursor offset per movement (unmodified) | |`MK_C_OFFSET_UNMOD` |16 |Cursor offset per movement (unmodified) |
|`MK_C_INTERVAL_UNMOD`|16 |Time between cursor movements (unmodified) | |`MK_C_INTERVAL_UNMOD`|16 |Time between cursor movements (unmodified) |
|`MK_C_OFFSET_0` |1 |Cursor offset per movement (`KC_ACL0`) | |`MK_C_OFFSET_0` |1 |Cursor offset per movement (`MS_ACL0`) |
|`MK_C_INTERVAL_0` |32 |Time between cursor movements (`KC_ACL0`) | |`MK_C_INTERVAL_0` |32 |Time between cursor movements (`MS_ACL0`) |
|`MK_C_OFFSET_1` |4 |Cursor offset per movement (`KC_ACL1`) | |`MK_C_OFFSET_1` |4 |Cursor offset per movement (`MS_ACL1`) |
|`MK_C_INTERVAL_1` |16 |Time between cursor movements (`KC_ACL1`) | |`MK_C_INTERVAL_1` |16 |Time between cursor movements (`MS_ACL1`) |
|`MK_C_OFFSET_2` |32 |Cursor offset per movement (`KC_ACL2`) | |`MK_C_OFFSET_2` |32 |Cursor offset per movement (`MS_ACL2`) |
|`MK_C_INTERVAL_2` |16 |Time between cursor movements (`KC_ACL2`) | |`MK_C_INTERVAL_2` |16 |Time between cursor movements (`MS_ACL2`) |
|`MK_W_OFFSET_UNMOD` |1 |Scroll steps per scroll action (unmodified)| |`MK_W_OFFSET_UNMOD` |1 |Scroll steps per scroll action (unmodified)|
|`MK_W_INTERVAL_UNMOD`|40 |Time between scroll steps (unmodified) | |`MK_W_INTERVAL_UNMOD`|40 |Time between scroll steps (unmodified) |
|`MK_W_OFFSET_0` |1 |Scroll steps per scroll action (`KC_ACL0`) | |`MK_W_OFFSET_0` |1 |Scroll steps per scroll action (`MS_ACL0`) |
|`MK_W_INTERVAL_0` |360 |Time between scroll steps (`KC_ACL0`) | |`MK_W_INTERVAL_0` |360 |Time between scroll steps (`MS_ACL0`) |
|`MK_W_OFFSET_1` |1 |Scroll steps per scroll action (`KC_ACL1`) | |`MK_W_OFFSET_1` |1 |Scroll steps per scroll action (`MS_ACL1`) |
|`MK_W_INTERVAL_1` |120 |Time between scroll steps (`KC_ACL1`) | |`MK_W_INTERVAL_1` |120 |Time between scroll steps (`MS_ACL1`) |
|`MK_W_OFFSET_2` |1 |Scroll steps per scroll action (`KC_ACL2`) | |`MK_W_OFFSET_2` |1 |Scroll steps per scroll action (`MS_ACL2`) |
|`MK_W_INTERVAL_2` |20 |Time between scroll steps (`KC_ACL2`) | |`MK_W_INTERVAL_2` |20 |Time between scroll steps (`MS_ACL2`) |
### Combined mode ### Combined mode
This mode functions like **Accelerated** mode, however, you can hold `KC_ACL0`, `KC_ACL1` and `KC_ACL2` This mode functions like **Accelerated** mode, however, you can hold `MS_ACL0`, `MS_ACL1` and `MS_ACL2`
to momentarily (while held) set the cursor and scroll speeds to constant speeds. When no acceleration to momentarily (while held) set the cursor and scroll speeds to constant speeds. When no acceleration
keys are held, this mode is identical to **Accelerated** mode, and can be modified using all of the keys are held, this mode is identical to **Accelerated** mode, and can be modified using all of the
relevant settings. relevant settings.
* **KC_ACL0:** This acceleration sets your cursor to the slowest possible speed. This is useful for very * **MS_ACL0:** This acceleration sets your cursor to the slowest possible speed. This is useful for very
small and detailed movements of the cursor. small and detailed movements of the cursor.
* **KC_ACL1:** This acceleration sets your cursor to half the maximum (user defined) speed. * **MS_ACL1:** This acceleration sets your cursor to half the maximum (user defined) speed.
* **KC_ACL2:** This acceleration sets your cursor to the maximum (computer defined) speed. This is * **MS_ACL2:** This acceleration sets your cursor to the maximum (computer defined) speed. This is
useful for moving the cursor large distances without much accuracy. useful for moving the cursor large distances without much accuracy.
To use combined speed mode, you must at least define `MK_COMBINED` in your keymaps `config.h` file: To use combined speed mode, you must at least define `MK_COMBINED` in your keymaps `config.h` file:
@ -203,6 +203,19 @@ Tips:
* Keep `MOUSEKEY_MOVE_DELTA` at 1. This allows precise movements before the gliding effect starts. * Keep `MOUSEKEY_MOVE_DELTA` at 1. This allows precise movements before the gliding effect starts.
* Mouse wheel options are the same as the default accelerated mode, and do not use inertia. * Mouse wheel options are the same as the default accelerated mode, and do not use inertia.
### Overlapping mouse key control
When additional overlapping mouse key is pressed, the mouse cursor will continue in a new direction with the same acceleration. The following settings can be used to reset the acceleration with new overlapping keys for more precise control if desired:
|Define |Default |Description |
|------------------------------|----------------------|-----------------------------------------------------------------------|
|`MOUSEKEY_OVERLAP_RESET` |undefined |Enables overlapping mouse key control |
|`MOUSEKEY_OVERLAP_MOVE_DELTA` |`MOUSEKEY_MOVE_DELTA` |Step size of reset movement acceleration |
|`MOUSEKEY_OVERLAP_WHEEL_DELTA`|`MOUSEKEY_WHEEL_DELTA`|Step size of reset mouse wheel acceleration |
|`MOUSEKEY_OVERLAP_INTERVAL` |`MOUSEKEY_INTERVAL` |Reset time between cursor movements in milliseconds (Kinetic mode only)|
?> This feature will not be applied on Inertial mode
## Use with PS/2 Mouse and Pointing Device ## Use with PS/2 Mouse and Pointing Device
Mouse keys button state is shared with [PS/2 mouse](ps2_mouse) and [pointing device](pointing_device) so mouse keys button presses can be used for clicks and drags. Mouse keys button state is shared with [PS/2 mouse](ps2_mouse) and [pointing device](pointing_device) so mouse keys button presses can be used for clicks and drags.

View File

@ -60,10 +60,10 @@ with mods, like Ctrl + Left &harr; Ctrl + Right Arrow.
|`KC_UP` &harr; `KC_DOWN` | Up &harr; Down Arrow | |`KC_UP` &harr; `KC_DOWN` | Up &harr; Down Arrow |
|`KC_HOME` &harr; `KC_END` | Home &harr; End | |`KC_HOME` &harr; `KC_END` | Home &harr; End |
|`KC_PGUP` &harr; `KC_PGDN` | Page Up &harr; Page Down | |`KC_PGUP` &harr; `KC_PGDN` | Page Up &harr; Page Down |
|`KC_MS_L` &harr; `KC_MS_R` | Mouse Cursor Left &harr; Right | |`MS_LEFT` &harr; `MS_RGHT` | Mouse Cursor Left &harr; Right |
|`KC_MS_U` &harr; `KC_MS_D` | Mouse Cursor Up &harr; Down | |`MS_UP` &harr; `MS_DOWN` | Mouse Cursor Up &harr; Down |
|`KC_WH_L` &harr; `KC_WH_R` | Mouse Wheel Left &harr; Right | |`MS_WHLL` &harr; `MS_WHLR` | Mouse Wheel Left &harr; Right |
|`KC_WH_U` &harr; `KC_WH_D` | Mouse Wheel Up &harr; Down | |`MS_WHLU` &harr; `MS_WHLD` | Mouse Wheel Up &harr; Down |
**Misc** **Misc**

View File

@ -4,543 +4,35 @@ This feature allows you to use RGB LED matrices driven by external drivers. It h
If you want to use single color LED's you should use the [LED Matrix Subsystem](led_matrix) instead. If you want to use single color LED's you should use the [LED Matrix Subsystem](led_matrix) instead.
## Driver configuration {#driver-configuration} ## Driver Configuration {#driver-configuration}
---
### IS31FL3731 {#is31fl3731}
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`: RGB Matrix is an abstraction layer on top of an underlying LED driver API. The list of supported LED drivers is below; see the respective documentation for information on how to configure the driver.
|Driver |Max LEDs|
|-------------------------------------|--------|
|[APA102](../drivers/apa102) |? |
|[AW20216S](../drivers/aw20216s) |72 |
|[IS31FL3218](../drivers/is31fl3218) |6 |
|[IS31FL3236](../drivers/is31fl3236) |12 |
|[IS31FL3729](../drivers/is31fl3729) |45 |
|[IS31FL3731](../drivers/is31fl3731) |48 |
|[IS31FL3733](../drivers/is31fl3733) |64 |
|[IS31FL3736](../drivers/is31fl3736) |32 |
|[IS31FL3737](../drivers/is31fl3737) |48 |
|[IS31FL3741](../drivers/is31fl3741) |117 |
|[IS31FL3742A](../drivers/is31fl3742a)|60 |
|[IS31FL3743A](../drivers/is31fl3743a)|66 |
|[IS31FL3745](../drivers/is31fl3745) |48 |
|[IS31FL3746A](../drivers/is31fl3746a)|24 |
|[SNLED27351](../drivers/snled27351) |64 |
|[WS2812](../drivers/ws2812) |? |
To assign the RGB Matrix driver, add the following to your `rules.mk`, for example:
```make ```make
RGB_MATRIX_ENABLE = yes RGB_MATRIX_DRIVER = is31fl3218
RGB_MATRIX_DRIVER = is31fl3731
``` ```
You can use between 1 and 4 IS31FL3731 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `IS31FL3731_DEGHOST` | (Optional) Set this define to enable de-ghosting by halving Vcc during blanking time | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `IS31FL3731_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `IS31FL3731_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
Here is an example using 2 drivers.
```c
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 AD <-> GND
// 01 AD <-> SCL
// 10 AD <-> SDA
// 11 AD <-> VCC
// ADDR represents A1:A0 of the 7-bit address.
// The result is: 0b11101(ADDR)
#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
#define DRIVER_1_LED_TOTAL 25
#define DRIVER_2_LED_TOTAL 24
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` 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`.
:::
For split keyboards using `RGB_MATRIX_SPLIT` with an LED driver, you can either have the same driver address or different driver addresses. If using different addresses, use `IS31FL3731_I2C_ADDRESS_1` for one and `IS31FL3731_I2C_ADDRESS_2` for the other one. Then, in `g_is31fl3731_leds`, fill out the correct driver index (0 or 1). If using one address, use `IS31FL3731_I2C_ADDRESS_1` for both, and use index 0 for `g_is31fl3731_leds`.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, C1_3, C2_3, C3_3},
....
}
```
Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3`).
---
### IS31FL3733 {#is31fl3733}
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = is31fl3733
```
You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `IS31FL3733_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `IS31FL3733_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `IS31FL3733_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 |
| `IS31FL3733_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `IS31FL3733_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `IS31FL3733_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `IS31FL3733_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `IS31FL3733_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `IS31FL3733_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `IS31FL3733_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
| `IS31FL3733_SYNC_1` | (Optional) Sync configuration for the first RGB driver | 0 |
| `IS31FL3733_SYNC_2` | (Optional) Sync configuration for the second RGB driver | 0 |
| `IS31FL3733_SYNC_3` | (Optional) Sync configuration for the third RGB driver | 0 |
| `IS31FL3733_SYNC_4` | (Optional) Sync configuration for the fourth RGB driver | 0 |
The IS31FL3733 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`IS31FL3733_SWPULLUP`/`IS31FL3733_CSPULLUP` are given the value of `IS31FL3733_PUR_0R`), the values that can be set to enable de-ghosting are as follows:
| `IS31FL3733_SWPULLUP/IS31FL3733_CSPULLUP` | Description |
|----------------------|-------------|
| `IS31FL3733_PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
| `IS31FL3733_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3733_PUR_3KR` | The 3k Ohm resistor used at all times |
| `IS31FL3733_PUR_4KR` | The 4k Ohm resistor used at all times |
| `IS31FL3733_PUR_8KR` | The 8k Ohm resistor used at all times |
| `IS31FL3733_PUR_16KR` | The 16k Ohm resistor used at all times |
| `IS31FL3733_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
```c
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 ADDRn <-> GND
// 01 ADDRn <-> SCL
// 10 ADDRn <-> SDA
// 11 ADDRn <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b101(ADDR2)(ADDR1)
#define IS31FL3733_I2C_ADDRESS_1 IS31FL3733_I2C_ADDRESS_GND_GND
#define IS31FL3733_I2C_ADDRESS_2 IS31FL3733_I2C_ADDRESS_GND_VCC
#define DRIVER_1_LED_TOTAL 58
#define DRIVER_2_LED_TOTAL 10
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
:::
Currently only 4 drivers are supported, but it would be trivial to support all 8 combinations.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
....
}
```
Where `SWx_CSy` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/led/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now).
---
### IS31FL3736 {#is31fl3736}
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3736 RGB controller. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = is31fl3736
```
You can use between 1 and 4 IS31FL3736 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard.
Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `IS31FL3736_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `IS31FL3736_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `IS31FL3736_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 |
| `IS31FL3736_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `IS31FL3736_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `IS31FL3736_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `IS31FL3736_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `IS31FL3736_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `IS31FL3736_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `IS31FL3736_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
The IS31FL3736 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`IS31FL3736_SWPULLUP`/`IS31FL3736_CSPULLUP` are given the value of `IS31FL3736_PUR_0R`), the values that can be set to enable de-ghosting are as follows:
| `IS31FL3736_SWPULLUP/IS31FL3736_CSPULLUP` | Description |
|----------------------|-------------|
| `IS31FL3736_PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
| `IS31FL3736_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3736_PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3736_PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3736_PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3736_PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
| `IS31FL3736_PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
| `IS31FL3736_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
```c
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 ADDRn <-> GND
// 01 ADDRn <-> SCL
// 10 ADDRn <-> SDA
// 11 ADDRn <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b101(ADDR2)(ADDR1)
#define IS31FL3736_I2C_ADDRESS_1 IS31FL3736_I2C_ADDRESS_GND_GND
#define IS31FL3736_I2C_ADDRESS_2 IS31FL3736_I2C_ADDRESS_GND_SCL
#define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 32
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` 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 is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
....
}
```
### IS31FL3737 {#is31fl3737}
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3737 RGB controller. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = is31fl3737
```
You can use between 1 and 4 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard.
Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `IS31FL3737_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `IS31FL3737_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `IS31FL3737_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3737B only | 0 |
| `IS31FL3737_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `IS31FL3737_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `IS31FL3737_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `IS31FL3737_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
| `IS31FL3737_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
| `IS31FL3737_I2C_ADDRESS_3` | (Optional) Address for the third RGB driver | |
| `IS31FL3737_I2C_ADDRESS_4` | (Optional) Address for the fourth RGB driver | |
The IS31FL3737 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`IS31FL3737_SWPULLUP`/`IS31FL3737_CSPULLUP` are given the value of `IS31FL3737_PUR_0R`), the values that can be set to enable de-ghosting are as follows:
| `IS31FL3737_SWPULLUP/IS31FL3737_CSPULLUP` | Description |
|----------------------|-------------|
| `IS31FL3737_PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
| `IS31FL3737_PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3737_PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3737_PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3737_PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
| `IS31FL3737_PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
| `IS31FL3737_PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
| `IS31FL3737_PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
```c
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 0000 ADDR <-> GND
// 0101 ADDR <-> SCL
// 1010 ADDR <-> SDA
// 1111 ADDR <-> VCC
// ADDR represents A3:A0 of the 7-bit address.
// The result is: 0b101(ADDR)
#define IS31FL3737_I2C_ADDRESS_1 IS31FL3737_I2C_ADDRESS_GND
#define IS31FL3737_I2C_ADDRESS_2 IS31FL3737_I2C_ADDRESS_SCL
#define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 36
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` 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 is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
....
}
```
Where `SWx_CSy` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/led/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1`, `2`, or `3` for now).
---
### IS31FLCOMMON {#is31flcommon}
There is basic support for addressable RGB matrix lighting with a selection of I2C ISSI Lumissil RGB controllers through a shared common driver. To enable it, add this to your `rules.mk`:
```makefile
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = <driver name>
```
Where `<driver name>` is the applicable LED driver chip as below
| Driver Name | Data Sheet | Capability |
|-------------|------------|------------|
| `IS31FL3742A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3742A_DS.pdf) | 60 RGB, 30x6 Matrix |
| `IS31FL3743A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3743A_DS.pdf) | 66 RGB, 18x11 Matrix |
| `IS31FL3745` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3745_DS.pdf) | 48 RGB, 18x8 Matrix |
| `IS31FL3746A` | [datasheet](https://www.lumissil.com/assets/pdf/core/IS31FL3746A_DS.pdf) | 24 RGB, 18x4 Matrix |
You can use between 1 and 4 IC's. Do not specify `DRIVER_ADDR_<N>` define for IC's if not present on your keyboard. The `DRIVER_ADDR_1` default assumes that all Address pins on the controller have been connected to GND. Drivers that have SYNC functionality have the default settings to disable if 1 driver. If more than 1 drivers then `DRIVER_ADDR_1` will be set to Master and the remaining ones set to Slave.
Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Optional) Address for the first RGB driver | |
| `DRIVER_ADDR_<N>` | (Required) Address for the additional RGB drivers | |
| `ISSI_SSR_<N>` | (Optional) Configuration for the Spread Spectrum Register | |
| `ISSI_CONFIGURATION` | (Optional) Configuration for the Configuration Register | |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `ISSI_PULLDOWNUP` | (Optional) Configuration for the Pull Up & Pull Down Register | |
| `ISSI_TEMP` | (Optional) Configuration for the Temperature Register | |
| `ISSI_PWM_ENABLE` | (Optional) Configuration for the PWM Enable Register | |
| `ISSI_PWM_SET` | (Optional) Configuration for the PWM Setting Register | |
| `ISSI_SCAL_RED` | (Optional) Configuration for the RED LEDs in Scaling Registers | 0xFF |
| `ISSI_SCAL_BLUE` | (Optional) Configuration for the BLUE LEDs in Scaling Registers | 0xFF |
| `ISSI_SCAL_GREEN` | (Optional) Configuration for the GREEN LEDs in Scaling Registers | 0xFF |
| `ISSI_MANUAL_SCALING` | (Optional) If you wish to configure the Scaling Registers manually | |
Defaults
| Variable | IS31FL3742A | IS31FL3743A | IS31FL3745 | IS31FL3746 |
|----------|-------------|-------------|------------|------------|
| `DRIVER_ADDR_1` | 0b0110000 | 0b0100000 | 0b0100000 | 0b1100000 |
| `ISSI_SSR_1` | 0x00 | 0x00 / 0x60 | 0x00 / 0xC0 | 0x00 |
| `ISSI_SSR_<2-4>` | 0x00 | 0x40 | 0x80 | 0x00 |
| `ISSI_CONFIGURATION` | 0x31 | 0x01 | 0x31 | 0x01 |
| `ISSI_PULLDOWNUP` | 0x55 | 0x33 | 0x33 | 0x33 |
| `ISSI_TEMP` | N/A | 0x00 | 0x00 | 0x00 |
| `ISSI_PWM_ENABLE` | N/A | N/A | N/A | 0x00 |
| `ISSI_PWM_SET` | 0x00 | N/A | N/A | 0x00 |
Here is an example using 2 drivers.
```c
#define DRIVER_ADDR_2 0b0100001
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 42
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
:::
Currently only 4 drivers are supported, but it would be trivial to support for more. Note that using a combination of different drivers is not supported. All drivers must be of the same model.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, SW1_CS1, SW1_CS2, SW1_CS3},
....
}
```
Where `CSx_SWx` is the location of the LED in the matrix defined by the datasheet. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now).
`ISSI_MANUAL_SCALING` is used to override the Scaling for individual LED's. By default they will be set as per `ISSI_SCAL_<colour>`. In `config.h` set how many LED's you want to manually set scaling for.
Eg `#define ISSI_MANUAL_SCALING 3`
Then Define the array listing all the LEDs you want to override in your `<keyboard>.c`:
```c
const is31_led PROGMEM g_is31_scaling[ISSI_MANUAL_SCALING] = {
/* LED Index
* | R scaling
* | | G scaling
* | | | B scaling
* | | | | */
{5, 120, 155, 167},
{9, 120, 155, 167},
....
}
```
Where LED Index is the position of the LED in the `g_is31_leds` array. The `scaling` value between 0 and 255 to be written to the Scaling Register.
---
### WS2812 {#ws2812}
There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{a,b,c} addressable LED strand. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = ws2812
```
Configure the hardware via your `config.h`:
```c
// The pin connected to the data pin of the LEDs
#define WS2812_DI_PIN D7
// The number of LEDs connected
#define RGB_MATRIX_LED_COUNT 70
```
::: tip
There are additional configuration options for ARM controllers that offer increased performance over the default bitbang driver. Please see [WS2812 Driver](../drivers/ws2812) for more information.
:::
---
### APA102 {#apa102}
There is basic support for APA102 based addressable LED strands. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = apa102
```
Configure the hardware via your `config.h`:
```c
// The pin connected to the data pin of the LEDs
#define APA102_DI_PIN D7
// The pin connected to the clock pin of the LEDs
#define APA102_CI_PIN D6
// The number of LEDs connected
#define RGB_MATRIX_LED_COUNT 70
```
---
### AW20216S {#aw20216s}
There is basic support for addressable RGB matrix lighting with the SPI AW20216S RGB controller. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = aw20216s
```
You can use up to 2 AW20216S 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 |
|----------|-------------|---------|
| `AW20216S_CS_PIN_1` | (Required) MCU pin connected to first RGB driver chip select line | B13 |
| `AW20216S_CS_PIN_2` | (Optional) MCU pin connected to second RGB driver chip select line | |
| `AW20216S_EN_PIN_1` | (Required) MCU pin connected to first RGB driver hardware enable line | C13 |
| `AW20216S_EN_PIN_2` | (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 | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `AW20216S_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
| `AW20216S_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
| `AW20216S_SPI_MODE` | (Optional) Mode for SPI communication (0-3, defines polarity and phase of the clock) | 3 |
| `AW20216S_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 AW20216S_CS_PIN_1 B13
#define AW20216S_CS_PIN_2 B14
// Hardware enable lines may be connected to the same pin
#define AW20216S_EN_PIN_1 C13
#define AW20216S_EN_PIN_2 C13
#define DRIVER_1_LED_TOTAL 66
#define DRIVER_2_LED_TOTAL 32
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
::: warning
Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` 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 aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
/* Each AW20216S channel is controlled by a register at some offset between 0x00
* and 0xD7 inclusive.
* See drivers/led/aw20216s.h for the mapping between register offsets and
* driver pin locations.
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{ 0, SW1_CS1, SW1_CS2, SW1_CS3 },
{ 0, SW1_CS4, SW1_CS5, SW1_CS6 },
{ 0, SW1_CS7, SW1_CS8, SW1_CS9 },
{ 0, SW1_CS10, SW1_CS11, SW1_CS12 },
{ 0, SW1_CS13, SW1_CS14, SW1_CS15 },
...
{ 1, SW1_CS1, SW1_CS2, SW1_CS3 },
{ 1, SW1_CS13, SW1_CS14, SW1_CS15 },
{ 1, SW1_CS16, SW1_CS17, SW1_CS18 },
{ 1, SW2_CS4, SW2_CS5, SW2_CS6 },
...
};
```
---
## Common Configuration {#common-configuration} ## Common Configuration {#common-configuration}
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example: From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:

View File

@ -417,8 +417,8 @@ This allows you to specify a different set of pins for the matrix on the right s
This allows you to specify a different set of direct pins for the right side. This allows you to specify a different set of direct pins for the right side.
```c ```c
#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a } #define ENCODER_A_PINS_RIGHT { encoder1a, encoder2a }
#define ENCODERS_PAD_B_RIGHT { encoder1b, encoder2b } #define ENCODER_B_PINS_RIGHT { encoder1b, encoder2b }
``` ```
This allows you to specify a different set of encoder pins for the right side. This allows you to specify a different set of encoder pins for the right side.

View File

@ -273,12 +273,12 @@ Now, at the bottom of your `keymap.c` file, you'll need to add the following:
* How to figure out tap dance state: interrupted and pressed. * How to figure out tap dance state: interrupted and pressed.
* *
* Interrupted: If the state of a dance is "interrupted", that means that another key has been hit * Interrupted: If the state of a dance is "interrupted", that means that another key has been hit
* under the tapping term. This is typically indicitive that you are trying to "tap" the key. * under the tapping term. This is typically indicative that you are trying to "tap" the key.
* *
* Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term * Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term
* has ended, but the key is still being pressed down. This generally means the key is being "held". * has ended, but the key is still being pressed down. This generally means the key is being "held".
* *
* One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold" * One thing that is currently not possible with qmk software in regards to tap dance is to mimic the "permissive hold"
* feature. In general, advanced tap dances do not work well if they are used with commonly typed letters. * feature. In general, advanced tap dances do not work well if they are used with commonly typed letters.
* For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters. * For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters.
* *
@ -290,7 +290,7 @@ Now, at the bottom of your `keymap.c` file, you'll need to add the following:
* Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or * Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or
* in a web form. So 'tab' would be a poor choice for a tap dance. * in a web form. So 'tab' would be a poor choice for a tap dance.
* Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the * Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the
* letter 'p', the word 'pepper' would be quite frustating to type. * letter 'p', the word 'pepper' would be quite frustrating to type.
* *
* For the third point, there does exist the 'TD_DOUBLE_SINGLE_TAP', however this is not fully tested * For the third point, there does exist the 'TD_DOUBLE_SINGLE_TAP', however this is not fully tested
* *

View File

@ -231,7 +231,7 @@ Once you have confirmed that the keyboard is working, if you have used a seperat
If you found this fullfilling you could experiment by adding additional features such as [in switch LEDs](https://geekhack.org/index.php?topic=94258.0), [in switch RGB](https://www.reddit.com/r/MechanicalKeyboards/comments/5s1l5u/photoskeyboard_science_i_made_a_handwired_rgb/), [RGB underglow](https://medium.com/@DavidNZ/hand-wired-custom-keyboard-cdd14429c7b3#.7a1ovebsk) or even an [OLED display!](https://www.reddit.com/r/olkb/comments/5zy7og/adding_ssd1306_oled_display_to_your_build/) If you found this fullfilling you could experiment by adding additional features such as [in switch LEDs](https://geekhack.org/index.php?topic=94258.0), [in switch RGB](https://www.reddit.com/r/MechanicalKeyboards/comments/5s1l5u/photoskeyboard_science_i_made_a_handwired_rgb/), [RGB underglow](https://medium.com/@DavidNZ/hand-wired-custom-keyboard-cdd14429c7b3#.7a1ovebsk) or even an [OLED display!](https://www.reddit.com/r/olkb/comments/5zy7og/adding_ssd1306_oled_display_to_your_build/)
There are a lot of possibilities inside the firmware - explore [docs.qmk.fm](https://docs.qmk.fm) for a full feature list, and dive into the different keyboards to see how people use all of them. You can always stop by [the OLKB subreddit](https://reddit.com/r/olkb) or [QMK Discord](https://discord.gg/Uq7gcHh) for help! There are a lot of possibilities inside the firmware - explore [docs.qmk.fm](https://docs.qmk.fm) for a full feature list, and dive into the different keyboards to see how people use all of them. You can always stop by [the OLKB subreddit](https://reddit.com/r/olkb) or [QMK Discord](https://discord.gg/qmk) for help!
## Links to Other Guides ## Links to Other Guides

View File

@ -32,7 +32,7 @@ There are a lot of ways you can contribute to the QMK Community. The easiest way
* Help people out on our forums and chat rooms: * Help people out on our forums and chat rooms:
* [/r/olkb](https://www.reddit.com/r/olkb/) * [/r/olkb](https://www.reddit.com/r/olkb/)
* [Discord Server](https://discord.gg/Uq7gcHh) * [Discord Server](https://discord.gg/qmk)
* Contribute to our documentation by clicking "Edit This Page" at the bottom * Contribute to our documentation by clicking "Edit This Page" at the bottom
* [Report a bug](https://github.com/qmk/qmk_firmware/issues/new/choose) * [Report a bug](https://github.com/qmk/qmk_firmware/issues/new/choose)
* [Open a Pull Request](contributing) * [Open a Pull Request](contributing)

View File

@ -611,24 +611,27 @@ See also: [MIDI](features/midi)
See also: [Mouse Keys](features/mouse_keys) See also: [Mouse Keys](features/mouse_keys)
|Key |Aliases |Description | |Key |Aliases |Description |
|----------------|---------|---------------------------| |-------------------------|---------|---------------------------|
|`KC_MS_UP` |`KC_MS_U`|Mouse Cursor Up | |`QK_MOUSE_CURSOR_UP` |`MS_UP` |Mouse cursor up |
|`KC_MS_DOWN` |`KC_MS_D`|Mouse Cursor Down | |`QK_MOUSE_CURSOR_DOWN` |`MS_DOWN`|Mouse cursor down |
|`KC_MS_LEFT` |`KC_MS_L`|Mouse Cursor Left | |`QK_MOUSE_CURSOR_LEFT` |`MS_LEFT`|Mouse cursor left |
|`KC_MS_RIGHT` |`KC_MS_R`|Mouse Cursor Right | |`QK_MOUSE_CURSOR_RIGHT` |`MS_RGHT`|Mouse cursor right |
|`KC_MS_BTN1` |`KC_BTN1`|Mouse Button 1 | |`QK_MOUSE_BUTTON_1` |`MS_BTN1`|Mouse button 1 |
|`KC_MS_BTN2` |`KC_BTN2`|Mouse Button 2 | |`QK_MOUSE_BUTTON_2` |`MS_BTN2`|Mouse button 2 |
|`KC_MS_BTN3` |`KC_BTN3`|Mouse Button 3 | |`QK_MOUSE_BUTTON_3` |`MS_BTN3`|Mouse button 3 |
|`KC_MS_BTN4` |`KC_BTN4`|Mouse Button 4 | |`QK_MOUSE_BUTTON_4` |`MS_BTN4`|Mouse button 4 |
|`KC_MS_BTN5` |`KC_BTN5`|Mouse Button 5 | |`QK_MOUSE_BUTTON_5` |`MS_BTN5`|Mouse button 5 |
|`KC_MS_WH_UP` |`KC_WH_U`|Mouse Wheel Up | |`QK_MOUSE_BUTTON_6` |`MS_BTN6`|Mouse button 6 |
|`KC_MS_WH_DOWN` |`KC_WH_D`|Mouse Wheel Down | |`QK_MOUSE_BUTTON_7` |`MS_BTN7`|Mouse button 7 |
|`KC_MS_WH_LEFT` |`KC_WH_L`|Mouse Wheel Left | |`QK_MOUSE_BUTTON_8` |`MS_BTN8`|Mouse button 8 |
|`KC_MS_WH_RIGHT`|`KC_WH_R`|Mouse Wheel Right | |`QK_MOUSE_WHEEL_UP` |`MS_WHLU`|Mouse wheel up |
|`KC_MS_ACCEL0` |`KC_ACL0`|Set mouse acceleration to 0| |`QK_MOUSE_WHEEL_DOWN` |`MS_WHLD`|Mouse wheel down |
|`KC_MS_ACCEL1` |`KC_ACL1`|Set mouse acceleration to 1| |`QK_MOUSE_WHEEL_LEFT` |`MS_WHLL`|Mouse wheel left |
|`KC_MS_ACCEL2` |`KC_ACL2`|Set mouse acceleration to 2| |`QK_MOUSE_WHEEL_RIGHT` |`MS_WHLR`|Mouse wheel right |
|`QK_MOUSE_ACCELERATION_0`|`MS_ACL0`|Set mouse acceleration to 0|
|`QK_MOUSE_ACCELERATION_1`|`MS_ACL1`|Set mouse acceleration to 1|
|`QK_MOUSE_ACCELERATION_2`|`MS_ACL2`|Set mouse acceleration to 2|
## Modifiers {#modifiers} ## Modifiers {#modifiers}

View File

@ -15,7 +15,7 @@ Different keyboards have different ways to enter this special mode. If your PCB
* Press the physical `RESET` button, usually located on the underside of the PCB * Press the physical `RESET` button, usually located on the underside of the PCB
* Locate header pins on the PCB labeled `RESET` and `GND`, and short them together while plugging your PCB in * Locate header pins on the PCB labeled `RESET` and `GND`, and short them together while plugging your PCB in
If you've attempted all of the above to no avail, and the main chip on the board says `STM32` or `RP2-B1` on it, this may be a bit more complicated. Generally your best bet is to ask on [Discord](https://discord.gg/Uq7gcHh) for assistance. It's likely some photos of the board will be asked for -- if you can get them ready beforehand it'll help move things along! If you've attempted all of the above to no avail, and the main chip on the board says `STM32` or `RP2-B1` on it, this may be a bit more complicated. Generally your best bet is to ask on [Discord](https://discord.gg/qmk) for assistance. It's likely some photos of the board will be asked for -- if you can get them ready beforehand it'll help move things along!
Otherwise, you should see a message in yellow, similar to this in QMK Toolbox: Otherwise, you should see a message in yellow, similar to this in QMK Toolbox:
@ -129,4 +129,4 @@ Congrats! Your custom firmware has been programmed to your keyboard and you're r
With a little bit of luck everything will work perfectly, but if not there are steps that will help you figure out what's wrong. With a little bit of luck everything will work perfectly, but if not there are steps that will help you figure out what's wrong.
Testing your keyboard is usually pretty straightforward. Press every single key and make sure it sends the keys you expect. You can use [QMK Configurator](https://config.qmk.fm/#/test/)'s test mode to check your keyboard, even if it doesn't run QMK. Testing your keyboard is usually pretty straightforward. Press every single key and make sure it sends the keys you expect. You can use [QMK Configurator](https://config.qmk.fm/#/test/)'s test mode to check your keyboard, even if it doesn't run QMK.
Still not working? Browse the FAQ topics for more information, or [chat with us on Discord](https://discord.gg/Uq7gcHh). Still not working? Browse the FAQ topics for more information, or [chat with us on Discord](https://discord.gg/qmk).

View File

@ -149,7 +149,7 @@ Next is configuring Layout Macro(s). These define the physical arrangement of ke
In the above example, In the above example,
* `LAYOUT_ortho_4x4` defines the name of the layout macro * `LAYOUT_ortho_4x4` defines the name of the layout macro
* It must conform to the [layout guidelines](hardware_keyboard_guidelines#ltkeyboard_namehgt) * It must conform to the [layout guidelines](hardware_keyboard_guidelines#keyboard-name-h)
* `"matrix": [0, 0]` defines the electrical position * `"matrix": [0, 0]` defines the electrical position
::: tip ::: tip

View File

@ -2,7 +2,7 @@
This is a non-exhaustive checklist of what the QMK Collaborators will be checking when reviewing submitted PRs. This is a non-exhaustive checklist of what the QMK Collaborators will be checking when reviewing submitted PRs.
If there are any inconsistencies with these recommendations, you're best off [creating an issue](https://github.com/qmk/qmk_firmware/issues/new) against this document, or getting in touch with a QMK Collaborator on [Discord](https://discord.gg/Uq7gcHh). If there are any inconsistencies with these recommendations, you're best off [creating an issue](https://github.com/qmk/qmk_firmware/issues/new) against this document, or getting in touch with a QMK Collaborator on [Discord](https://discord.gg/qmk).
## Requirements for all PRs ## Requirements for all PRs
@ -44,12 +44,14 @@ If there are any inconsistencies with these recommendations, you're best off [cr
Note that personal keymap submissions will no longer be accepted. This section applies to manufacturer-supported keymaps. Please see this [issue](https://github.com/qmk/qmk_firmware/issues/22724) for more information. Note that personal keymap submissions will no longer be accepted. This section applies to manufacturer-supported keymaps. Please see this [issue](https://github.com/qmk/qmk_firmware/issues/22724) for more information.
::: :::
- PRs for vendor specific keymaps will be permitted. The naming convention for these should be `default_${vendor}`, `via_${vendor}` i.e. `via_clueboard`. - PRs for vendor specific keymaps will be permitted. The naming convention for these should be `default_${vendor}` i.e. `default_clueboard`.
- vendor specific keymaps do not necessarily need to be "vanilla" and can be more richly featured than `default` or `via` stock keymaps. - vendor specific keymaps do not necessarily need to be "vanilla" and can be more richly featured than `default` stock keymaps.
- `#include QMK_KEYBOARD_H` preferred to including specific board files - `#include QMK_KEYBOARD_H` preferred to including specific board files
- prefer layer enums to #defines - prefer layer enums to #defines
- custom keycode enums must have first entry = `QK_USER` - custom keycode enums must have first entry = `QK_USER`
- some care with spacing (e.g., alignment on commas or first char of keycodes) makes for a much nicer-looking keymap. Spaces are preferred to tabs - some care with spacing (e.g., alignment on commas or first char of keycodes) makes for a much nicer-looking keymap. Spaces are preferred to tabs
- keymaps should not enable VIA
- keymaps targeting VIA support should be submitted to the [VIA QMK Userspace](https://github.com/the-via/qmk_userspace_via) repository
## Keyboard PRs ## Keyboard PRs
@ -136,12 +138,12 @@ https://github.com/qmk/qmk_firmware/pulls?q=is%3Apr+is%3Aclosed+label%3Akeyboard
- `keymaps/default/keymap.c` - `keymaps/default/keymap.c`
- `QMKBEST`/`QMKURL` example macros removed - `QMKBEST`/`QMKURL` example macros removed
- if using `MO(1)` and `MO(2)` keycodes together to access a third layer, the [Tri Layer](features/tri_layer) feature should be used, rather than manually implementing this using `layer_on/off()` and `update_tri_layer()` functions in the keymap's `process_record_user()`. - if using `MO(1)` and `MO(2)` keycodes together to access a third layer, the [Tri Layer](features/tri_layer) feature should be used, rather than manually implementing this using `layer_on/off()` and `update_tri_layer()` functions in the keymap's `process_record_user()`.
- default (and via) keymaps should be "pristine" - default keymaps should be "pristine"
- bare minimum to be used as a "clean slate" for another user to develop their own user-specific keymap - bare minimum to be used as a "clean slate" for another user to develop their own user-specific keymap
- what does pristine mean? no custom keycodes. no advanced features like tap dance or macros. basic mod taps and home row mods would be acceptable where their use is necessary - what does pristine mean? no custom keycodes. no advanced features like tap dance or macros. basic mod taps and home row mods would be acceptable where their use is necessary
- standard layouts preferred in these keymaps, if possible - standard layouts preferred in these keymaps, if possible
- should use [encoder map feature](features/encoders#encoder-map), rather than `encoder_update_user()` - should use [encoder map feature](features/encoders#encoder-map), rather than `encoder_update_user()`
- default keymap should not enable VIA -- the VIA integration documentation requires a keymap called `via` - default keymap should not enable VIA -- keymaps targeting VIA support should be submitted to the [VIA QMK Userspace](https://github.com/the-via/qmk_userspace_via) repository
- submitters can add an example (or bells-and-whistles) keymap showcasing capabilities in the same PR but it shouldn't be embedded in the 'default' keymap - submitters can add an example (or bells-and-whistles) keymap showcasing capabilities in the same PR but it shouldn't be embedded in the 'default' keymap
- submitters can also have a "manufacturer-matching" keymap that mirrors existing functionality of the commercial product, if porting an existing board - submitters can also have a "manufacturer-matching" keymap that mirrors existing functionality of the commercial product, if porting an existing board
- Do not include VIA json files in the PR. These do not belong in the QMK repository as they are not used by QMK firmware -- they belong in the [VIA Keyboard Repo](https://github.com/the-via/keyboards) - Do not include VIA json files in the PR. These do not belong in the QMK repository as they are not used by QMK firmware -- they belong in the [VIA Keyboard Repo](https://github.com/the-via/keyboards)
@ -174,7 +176,7 @@ Also, specific to ChibiOS:
- all core PRs must now target `develop` branch, which will subsequently be merged back to `master` on the breaking changes timeline - all core PRs must now target `develop` branch, which will subsequently be merged back to `master` on the breaking changes timeline
- as indicated above, the smallest set of changes to core components should be included in each PR - as indicated above, the smallest set of changes to core components should be included in each PR
- PRs containing multiple areas of change will be asked to be split up and raised separately - PRs containing multiple areas of change will be asked to be split up and raised separately
- keyboard and keymap changes should only be included if they affect base keyboard builds, or the default-like `default`, `via`, `default_????` keymaps etc. - keyboard and keymap changes should only be included if they affect base keyboard builds, or the default-like `default`, `default_????` keymaps etc.
- keymap modifications for anything other than the default-like keymaps **should not be included in the initial PR** in order to simplify the review process - keymap modifications for anything other than the default-like keymaps **should not be included in the initial PR** in order to simplify the review process
- the core PR submitter should submit a followup PR affecting other keymaps after initial PR merge - the core PR submitter should submit a followup PR affecting other keymaps after initial PR merge
- large-scale refactoring or consolidation PRs that affect other keymaps (such as renaming keycodes) should always be raised separately - large-scale refactoring or consolidation PRs that affect other keymaps (such as renaming keycodes) should always be raised separately

View File

@ -732,8 +732,12 @@ Configures the [Split Keyboard](features/split_keyboard) feature.
* `matrix_pins` * `matrix_pins`
* `right` * `right`
* See [Matrix](#matrix) config. * See [Matrix](#matrix) config.
* `soft_serial_pin` * `serial`
* The GPIO pin to use (`serial` transport protocol only). * `driver`
* The driver to use. Must be one of `bitbang`, `usart`, `vendor`.
* Default: `"bitbang"`
* `pin`
* The GPIO pin to use for transmit and receive.
* `soft_serial_speed` * `soft_serial_speed`
* The protocol speed, from `0` to `5` (`serial` transport protocol only). * The protocol speed, from `0` to `5` (`serial` transport protocol only).
* Default: `1` * Default: `1`

View File

@ -33,6 +33,7 @@ These headers are located in [`quantum/keymap_extras/`](https://github.com/qmk/q
|English (US International) |`keymap_us_international.h` |`sendstring_us_international.h` | |English (US International) |`keymap_us_international.h` |`sendstring_us_international.h` |
|English (US International, Linux)|`keymap_us_international_linux.h`| | |English (US International, Linux)|`keymap_us_international_linux.h`| |
|Estonian |`keymap_estonian.h` |`sendstring_estonian.h` | |Estonian |`keymap_estonian.h` |`sendstring_estonian.h` |
|Farsi |`keymap_farsi.h` | |
|Finnish |`keymap_finnish.h` |`sendstring_finnish.h` | |Finnish |`keymap_finnish.h` |`sendstring_finnish.h` |
|French |`keymap_french.h` |`sendstring_french.h` | |French |`keymap_french.h` |`sendstring_french.h` |
|French (AFNOR) |`keymap_french_afnor.h` |`sendstring_french_afnor.h` | |French (AFNOR) |`keymap_french_afnor.h` |`sendstring_french_afnor.h` |

View File

@ -6,7 +6,7 @@ Please read our [Code of Conduct](https://qmk.fm/coc/) before participating in a
## Realtime Chat ## Realtime Chat
If you need help with something, the best place to get quick support is going to be on our [Discord Server](https://discord.gg/Uq7gcHh). There is usually somebody online, and there are a bunch of very helpful people there. If you need help with something, the best place to get quick support is going to be on our [Discord Server](https://discord.gg/qmk). There is usually somebody online, and there are a bunch of very helpful people there.
## OLKB Subreddit ## OLKB Subreddit

View File

@ -23,6 +23,17 @@ void eeprom_driver_init(void) {
/* Any initialisation code */ /* Any initialisation code */
} }
void eeprom_driver_format(bool erase) {
/* If erase=false, then only do the absolute minimum initialisation necessary
to make sure that the eeprom driver is usable. It doesn't need to guarantee
that the content of the eeprom is reset to any particular value. For many
eeprom drivers this may be a no-op.
If erase=true, then in addition to making sure the eeprom driver is in a
usable state, also make sure that it is erased.
*/
}
void eeprom_driver_erase(void) { void eeprom_driver_erase(void) {
/* Wipe out the EEPROM, setting values to zero */ /* Wipe out the EEPROM, setting values to zero */
} }

View File

@ -77,3 +77,9 @@ void eeprom_update_dword(uint32_t *addr, uint32_t value) {
eeprom_write_dword(addr, value); eeprom_write_dword(addr, value);
} }
} }
void eeprom_driver_format(bool erase) __attribute__((weak));
void eeprom_driver_format(bool erase) {
(void)erase; /* The default implementation assumes that the eeprom must be erased in order to be usable. */
eeprom_driver_erase();
}

View File

@ -16,7 +16,9 @@
#pragma once #pragma once
#include <stdbool.h>
#include "eeprom.h" #include "eeprom.h"
void eeprom_driver_init(void); void eeprom_driver_init(void);
void eeprom_driver_format(bool erase);
void eeprom_driver_erase(void); void eeprom_driver_erase(void);

View File

@ -36,6 +36,7 @@
#include "wait.h" #include "wait.h"
#include "i2c_master.h" #include "i2c_master.h"
#include "eeprom.h" #include "eeprom.h"
#include "eeprom_driver.h"
#include "eeprom_i2c.h" #include "eeprom_i2c.h"
// #define DEBUG_EEPROM_OUTPUT // #define DEBUG_EEPROM_OUTPUT
@ -62,6 +63,13 @@ void eeprom_driver_init(void) {
#endif #endif
} }
void eeprom_driver_format(bool erase) {
/* i2c eeproms do not need to be formatted before use */
if (erase) {
eeprom_driver_erase();
}
}
void eeprom_driver_erase(void) { void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
uint32_t start = timer_read32(); uint32_t start = timer_read32();

View File

@ -35,6 +35,7 @@
#include "timer.h" #include "timer.h"
#include "spi_master.h" #include "spi_master.h"
#include "eeprom.h" #include "eeprom.h"
#include "eeprom_driver.h"
#include "eeprom_spi.h" #include "eeprom_spi.h"
#define CMD_WREN 6 #define CMD_WREN 6
@ -92,6 +93,13 @@ void eeprom_driver_init(void) {
spi_init(); spi_init();
} }
void eeprom_driver_format(bool erase) {
/* spi eeproms do not need to be formatted before use */
if (erase) {
eeprom_driver_erase();
}
}
void eeprom_driver_erase(void) { void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
uint32_t start = timer_read32(); uint32_t start = timer_read32();

View File

@ -30,8 +30,13 @@ size_t clamp_length(intptr_t offset, size_t len) {
return len; return len;
} }
void eeprom_driver_init(void) { void eeprom_driver_init(void) {}
eeprom_driver_erase();
void eeprom_driver_format(bool erase) {
/* The transient eeprom driver doesn't necessarily need to be formatted before use, and it always starts up filled with zeros, due to placement in the .bss section */
if (erase) {
eeprom_driver_erase();
}
} }
void eeprom_driver_erase(void) { void eeprom_driver_erase(void) {

View File

@ -10,6 +10,12 @@ void eeprom_driver_init(void) {
wear_leveling_init(); wear_leveling_init();
} }
void eeprom_driver_format(bool erase) {
/* wear leveling requires the write log data structures to be erased before use. */
(void)erase;
eeprom_driver_erase();
}
void eeprom_driver_erase(void) { void eeprom_driver_erase(void) {
wear_leveling_erase(); wear_leveling_erase();
} }

View File

@ -22,7 +22,7 @@
#endif #endif
#undef ENCODER_DEFAULT_PIN_API_IMPL #undef ENCODER_DEFAULT_PIN_API_IMPL
#if defined(ENCODERS_PAD_A) && defined(ENCODERS_PAD_B) #if defined(ENCODER_A_PINS) && defined(ENCODER_B_PINS)
// Inform the quadrature driver that it needs to implement pin init/read functions // Inform the quadrature driver that it needs to implement pin init/read functions
# define ENCODER_DEFAULT_PIN_API_IMPL # define ENCODER_DEFAULT_PIN_API_IMPL
#endif #endif
@ -34,8 +34,8 @@ __attribute__((weak)) uint8_t encoder_quadrature_read_pin(uint8_t index, bool pa
#ifdef ENCODER_DEFAULT_PIN_API_IMPL #ifdef ENCODER_DEFAULT_PIN_API_IMPL
static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_A; static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODER_A_PINS;
static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_B; static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODER_B_PINS;
__attribute__((weak)) void encoder_wait_pullup_charge(void) { __attribute__((weak)) void encoder_wait_pullup_charge(void) {
wait_us(100); wait_us(100);
@ -123,25 +123,25 @@ void encoder_driver_init(void) {
// here, but it's the simplest solution. // here, but it's the simplest solution.
memset(encoder_state, 0, sizeof(encoder_state)); memset(encoder_state, 0, sizeof(encoder_state));
memset(encoder_pulses, 0, sizeof(encoder_pulses)); memset(encoder_pulses, 0, sizeof(encoder_pulses));
const pin_t encoders_pad_a_left[] = ENCODERS_PAD_A; const pin_t encoders_pad_a_left[] = ENCODER_A_PINS;
const pin_t encoders_pad_b_left[] = ENCODERS_PAD_B; const pin_t encoders_pad_b_left[] = ENCODER_B_PINS;
for (uint8_t i = 0; i < thisCount; i++) { for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_left[i]; encoders_pad_a[i] = encoders_pad_a_left[i];
encoders_pad_b[i] = encoders_pad_b_left[i]; encoders_pad_b[i] = encoders_pad_b_left[i];
} }
#endif #endif
#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) #if defined(SPLIT_KEYBOARD) && defined(ENCODER_A_PINS_RIGHT) && defined(ENCODER_B_PINS_RIGHT)
// Re-initialise the pads if it's the right-hand side // Re-initialise the pads if it's the right-hand side
if (!isLeftHand) { if (!isLeftHand) {
const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; const pin_t encoders_pad_a_right[] = ENCODER_A_PINS_RIGHT;
const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; const pin_t encoders_pad_b_right[] = ENCODER_B_PINS_RIGHT;
for (uint8_t i = 0; i < thisCount; i++) { for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_right[i]; encoders_pad_a[i] = encoders_pad_a_right[i];
encoders_pad_b[i] = encoders_pad_b_right[i]; encoders_pad_b[i] = encoders_pad_b_right[i];
} }
} }
#endif // defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) #endif // defined(SPLIT_KEYBOARD) && defined(ENCODER_A_PINS_RIGHT) && defined(ENCODER_B_PINS_RIGHT)
// Encoder resolutions is defined differently in config.h, so concatenate // Encoder resolutions is defined differently in config.h, so concatenate
#if defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS) #if defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS)

126
drivers/flash/flash.h Normal file
View File

@ -0,0 +1,126 @@
// Copyright 2024 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
/**
* @brief The status of a flash operation.
*/
enum {
FLASH_STATUS_SUCCESS = 0, //< The operation completed successfully.
FLASH_STATUS_ERROR = -1, //< An error occurred during the operation.
FLASH_STATUS_TIMEOUT = -2, //< The operation timed out.
FLASH_STATUS_BAD_ADDRESS = -3, //< The address is out of bounds.
FLASH_STATUS_BUSY = -4, //< The flash is busy.
};
/**
* @brief The status of a flash operation.
*/
typedef int16_t flash_status_t;
/**
* @brief Initializes the flash driver.
*
* This function initializes the flash driver and prepares it for use.
* It should be called before any other flash-related functions are used.
*/
void flash_init(void);
/**
* @brief Checks if the flash is busy.
*
* This function checks if the flash is currently busy with an operation.
*
* @return FLASH_STATUS_SUCCESS if the flash is not busy, FLASH_STATUS_BUSY if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_is_busy(void);
/**
* @brief Initiates a chip erase operation.
*
* This function does not wait for the flash to become ready.
*
* @return FLASH_STATUS_SUCCESS if the erase command was successfully sent, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_begin_erase_chip(void);
/**
* @brief Waits for the chip erase operation to complete.
*
* This function waits for the chip erase operation to complete.
*
* @return FLASH_STATUS_SUCCESS if the chip erase operation completed successfully, FLASH_STATUS_TIMEOUT if the flash was still busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_wait_erase_chip(void);
/**
* @brief Erases the entire flash memory chip.
*
* This function initiates an erase operation to erase the entire flash memory chip.
* It waits for the operation to complete.
*
* @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_erase_chip(void);
/**
* @brief Erases a block of flash memory.
*
* This function initiates an erase operation to erase a block of flash memory.
* It waits for the operation to complete.
*
* @param addr The address of the block to erase.
*
* @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_erase_block(uint32_t addr);
/**
* @brief Erases a sector of flash memory.
*
* This function initiates an erase operation to erase a sector of flash memory.
* It waits for the operation to complete.
*
* @param addr The address of the sector to erase.
*
* @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_erase_sector(uint32_t addr);
/**
* @brief Reads a range of flash memory.
*
* This function reads a range of flash memory into a buffer.
*
* @param addr The address of the range to read.
* @param buf A pointer to the buffer to read the range into.
* @param len The length of the range to read.
*
* @return FLASH_STATUS_SUCCESS if the range was successfully read, FLASH_STATUS_BAD_ADDRESS if the address is out of bounds, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_read_range(uint32_t addr, void *buf, size_t len);
/**
* @brief Writes a range of flash memory.
*
* This function writes a range of flash memory from a buffer.
*
* @param addr The address of the range to write.
* @param buf A pointer to the buffer to write to the range.
* @param len The length of the range to write.
*
* @return FLASH_STATUS_SUCCESS if the range was successfully written, FLASH_STATUS_BAD_ADDRESS if the address is out of bounds, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
*/
flash_status_t flash_write_range(uint32_t addr, const void *buf, size_t len);
#ifdef __cplusplus
}
#endif

View File

@ -1,22 +1,10 @@
/* // Copyright 2021 Westberry Technology (ChangZhou) Corp., Ltd
Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd // Copyright 2024 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> #include <string.h>
#include "flash.h"
#include "util.h" #include "util.h"
#include "wait.h" #include "wait.h"
#include "debug.h" #include "debug.h"
@ -69,33 +57,43 @@ static bool spi_flash_start(void) {
return spi_start(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN, EXTERNAL_FLASH_SPI_LSBFIRST, EXTERNAL_FLASH_SPI_MODE, EXTERNAL_FLASH_SPI_CLOCK_DIVISOR); return spi_start(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN, EXTERNAL_FLASH_SPI_LSBFIRST, EXTERNAL_FLASH_SPI_MODE, EXTERNAL_FLASH_SPI_CLOCK_DIVISOR);
} }
static flash_status_t spi_flash_wait_while_busy(void) { static flash_status_t spi_flash_wait_while_busy_multiplier(int multiplier) {
uint32_t deadline = timer_read32() + EXTERNAL_FLASH_SPI_TIMEOUT;
flash_status_t response = FLASH_STATUS_SUCCESS; flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t retval; uint32_t deadline = timer_read32() + ((EXTERNAL_FLASH_SPI_TIMEOUT)*multiplier);
do { do {
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash wait while busy]\n");
return FLASH_STATUS_ERROR;
}
spi_write(FLASH_CMD_RDSR);
retval = (uint8_t)spi_read();
spi_stop();
if (timer_read32() >= deadline) { if (timer_read32() >= deadline) {
response = FLASH_STATUS_TIMEOUT; response = FLASH_STATUS_TIMEOUT;
break; break;
} }
} while (retval & FLASH_FLAG_WIP);
response = flash_is_busy();
} while (response == FLASH_STATUS_BUSY);
return response; return response;
} }
static flash_status_t spi_flash_wait_while_busy(void) {
return spi_flash_wait_while_busy_multiplier(1);
}
flash_status_t flash_is_busy(void) {
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash wait while busy]\n");
return FLASH_STATUS_ERROR;
}
spi_write(FLASH_CMD_RDSR);
spi_status_t status = spi_read();
spi_stop();
if (status < 0) {
return status;
}
uint8_t sr = (uint8_t)status;
return (sr & FLASH_FLAG_WIP) ? FLASH_STATUS_BUSY : FLASH_STATUS_SUCCESS;
}
static flash_status_t spi_flash_write_enable(void) { static flash_status_t spi_flash_write_enable(void) {
bool res = spi_flash_start(); bool res = spi_flash_start();
if (!res) { if (!res) {
@ -104,7 +102,6 @@ static flash_status_t spi_flash_write_enable(void) {
} }
spi_write(FLASH_CMD_WREN); spi_write(FLASH_CMD_WREN);
spi_stop(); spi_stop();
return FLASH_STATUS_SUCCESS; return FLASH_STATUS_SUCCESS;
@ -118,7 +115,6 @@ static flash_status_t spi_flash_write_disable(void) {
} }
spi_write(FLASH_CMD_WRDI); spi_write(FLASH_CMD_WRDI);
spi_stop(); spi_stop();
return FLASH_STATUS_SUCCESS; return FLASH_STATUS_SUCCESS;
@ -166,7 +162,7 @@ void flash_init(void) {
spi_init(); spi_init();
} }
flash_status_t flash_erase_chip(void) { flash_status_t flash_begin_erase_chip(void) {
flash_status_t response = FLASH_STATUS_SUCCESS; flash_status_t response = FLASH_STATUS_SUCCESS;
/* Wait for the write-in-progress bit to be cleared. */ /* Wait for the write-in-progress bit to be cleared. */
@ -191,17 +187,28 @@ flash_status_t flash_erase_chip(void) {
} }
spi_write(FLASH_CMD_CE); spi_write(FLASH_CMD_CE);
spi_stop(); spi_stop();
return FLASH_STATUS_SUCCESS;
}
/* Wait for the write-in-progress bit to be cleared.*/ flash_status_t flash_wait_erase_chip(void) {
response = spi_flash_wait_while_busy(); flash_status_t response = spi_flash_wait_while_busy_multiplier(250); // Chip erase can take a long time, wait 250x the usual timeout
if (response != FLASH_STATUS_SUCCESS) { if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase chip]\n"); dprint("Failed to check WIP flag! [spi flash erase chip]\n");
return response; return response;
} }
return response; return response;
} }
flash_status_t flash_erase_chip(void) {
flash_status_t response = flash_begin_erase_chip();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to begin erase chip! [spi flash erase chip]\n");
return response;
}
return flash_wait_erase_chip();
}
flash_status_t flash_erase_sector(uint32_t addr) { flash_status_t flash_erase_sector(uint32_t addr) {
flash_status_t response = FLASH_STATUS_SUCCESS; flash_status_t response = FLASH_STATUS_SUCCESS;
@ -282,7 +289,7 @@ flash_status_t flash_erase_block(uint32_t addr) {
return response; return response;
} }
flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len) { flash_status_t flash_read_range(uint32_t addr, void *buf, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS; flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t * read_buf = (uint8_t *)buf; uint8_t * read_buf = (uint8_t *)buf;
@ -313,7 +320,7 @@ flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len) {
return response; return response;
} }
flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len) { flash_status_t flash_write_range(uint32_t addr, const void *buf, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS; flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t * write_buf = (uint8_t *)buf; uint8_t * write_buf = (uint8_t *)buf;

View File

@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once #pragma once
#include "flash.h"
/* All the following default configurations are based on MX25L4006E Nor FLASH. */ /* All the following default configurations are based on MX25L4006E Nor FLASH. */
/* /*
@ -105,32 +107,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
The page count of the FLASH, calculated by total FLASH size and page size. The page count of the FLASH, calculated by total FLASH size and page size.
*/ */
#define EXTERNAL_FLASH_PAGE_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_PAGE_SIZE)) #define EXTERNAL_FLASH_PAGE_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_PAGE_SIZE))
typedef int16_t flash_status_t;
#define FLASH_STATUS_SUCCESS (0)
#define FLASH_STATUS_ERROR (-1)
#define FLASH_STATUS_TIMEOUT (-2)
#define FLASH_STATUS_BAD_ADDRESS (-3)
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void flash_init(void);
flash_status_t flash_erase_chip(void);
flash_status_t flash_erase_block(uint32_t addr);
flash_status_t flash_erase_sector(uint32_t addr);
flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len);
flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len);
#ifdef __cplusplus
}
#endif

View File

@ -53,7 +53,8 @@
io_wait; \ io_wait; \
} while (0) } while (0)
uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS; rgb_led_t apa102_leds[APA102_LED_COUNT];
uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS;
static void apa102_send_byte(uint8_t byte) { static void apa102_send_byte(uint8_t byte) {
APA102_SEND_BIT(byte, 7); APA102_SEND_BIT(byte, 7);
@ -121,14 +122,24 @@ void apa102_init(void) {
gpio_set_pin_output(APA102_CI_PIN); gpio_set_pin_output(APA102_CI_PIN);
} }
void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds) { void apa102_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue) {
rgb_led_t *end = start_led + num_leds; apa102_leds[index].r = red;
apa102_leds[index].g = green;
apa102_leds[index].b = blue;
}
apa102_start_frame(); void apa102_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
for (rgb_led_t *led = start_led; led < end; led++) { for (uint16_t i = 0; i < APA102_LED_COUNT; i++) {
apa102_send_frame(led->r, led->g, led->b, apa102_led_brightness); apa102_set_color(i, red, green, blue);
} }
apa102_end_frame(num_leds); }
void apa102_flush(void) {
apa102_start_frame();
for (uint8_t i = 0; i < APA102_LED_COUNT; i++) {
apa102_send_frame(apa102_leds[i].r, apa102_leds[i].g, apa102_leds[i].b, apa102_led_brightness);
}
apa102_end_frame(APA102_LED_COUNT);
} }
void apa102_set_brightness(uint8_t brightness) { void apa102_set_brightness(uint8_t brightness) {

View File

@ -32,17 +32,8 @@
#define APA102_MAX_BRIGHTNESS 31 #define APA102_MAX_BRIGHTNESS 31
void apa102_init(void); void apa102_init(void);
void apa102_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue);
/* User Interface void apa102_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
* void apa102_flush(void);
* Input:
* start_led: An array of GRB data describing the LED colors
* num_leds: The number of LEDs to write
*
* The functions will perform the following actions:
* - Set the data-out pin as output
* - Send out the LED data
*/
void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds);
void apa102_set_brightness(uint8_t brightness); void apa102_set_brightness(uint8_t brightness);

View File

@ -1,157 +0,0 @@
// Copyright 2021 Paul Cotter (@gr1mr3aver)
// Copyright 2023 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_gc9a01.h"
#include "qp_gc9a01_opcodes.h"
#include "qp_tft_panel.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver storage
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tft_panel_dc_reset_painter_device_t gc9a01_drivers[GC9A01_NUM_DEVICES] = {0};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
__attribute__((weak)) bool qp_gc9a01_init(painter_device_t device, painter_rotation_t rotation) {
// A lot of these "unknown" opcodes are sourced from other OSS projects and are seemingly required for this display to function.
// clang-format off
const uint8_t gc9a01_init_sequence[] = {
// Command, Delay, N, Data[N]
GC9A01_SET_INTER_REG_ENABLE2, 0, 0,
0xEB, 0, 1, 0x14,
GC9A01_SET_INTER_REG_ENABLE1, 0, 0,
GC9A01_SET_INTER_REG_ENABLE2, 0, 0,
0xEB, 0, 1, 0x14,
0x84, 0, 1, 0x40,
0x85, 0, 1, 0xFF,
0x86, 0, 1, 0xFF,
0x87, 0, 1, 0xFF,
0x88, 0, 1, 0x0A,
0x89, 0, 1, 0x21,
0x8a, 0, 1, 0x00,
0x8b, 0, 1, 0x80,
0x8c, 0, 1, 0x01,
0x8d, 0, 1, 0x01,
0x8e, 0, 1, 0xFF,
0x8f, 0, 1, 0xFF,
GC9A01_SET_FUNCTION_CTL, 0, 2, 0x00, 0x20,
GC9A01_SET_PIX_FMT, 0, 1, 0x55,
0x90, 0, 4, 0x08, 0x08, 0x08, 0x08,
0xBD, 0, 1, 0x06,
0xBC, 0, 1, 0x00,
0xFF, 0, 3, 0x60, 0x01, 0x04,
GC9A01_SET_POWER_CTL_2, 0, 1, 0x13,
GC9A01_SET_POWER_CTL_3, 0, 1, 0x13,
GC9A01_SET_POWER_CTL_4, 0, 1, 0x22,
0xBE, 0, 1, 0x11,
0xE1, 0, 2, 0x10, 0x0E,
0xDF, 0, 3, 0x21, 0x0C, 0x02,
GC9A01_SET_GAMMA1, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
GC9A01_SET_GAMMA2, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
GC9A01_SET_GAMMA3, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
GC9A01_SET_GAMMA4, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
0xED, 0, 2, 0x1B, 0x0B,
0xAE, 0, 1, 0x77,
0xCD, 0, 1, 0x63,
0x70, 0, 9, 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03,
GC9A01_SET_FRAME_RATE, 0, 1, 0x34,
0x62, 0, 12, 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70,
0x63, 0, 12, 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70,
0x64, 0, 7, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07,
0x66, 0, 10, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00,
0x67, 0, 10, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98,
0x74, 0, 7, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00,
0x98, 0, 2, 0x3E, 0x07,
GC9A01_CMD_TEARING_OFF, 0, 0,
GC9A01_CMD_INVERT_OFF, 0, 0,
GC9A01_CMD_SLEEP_OFF, 120, 0,
GC9A01_CMD_DISPLAY_ON, 20, 0
};
// clang-format on
// clang-format on
qp_comms_bulk_command_sequence(device, gc9a01_init_sequence, sizeof(gc9a01_init_sequence));
// Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
const uint8_t madctl[] = {
[QP_ROTATION_0] = GC9A01_MADCTL_BGR,
[QP_ROTATION_90] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MX | GC9A01_MADCTL_MV,
[QP_ROTATION_180] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MX | GC9A01_MADCTL_MY,
[QP_ROTATION_270] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MV | GC9A01_MADCTL_MY,
};
qp_comms_command_databyte(device, GC9A01_SET_MEM_ACS_CTL, madctl[rotation]);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver vtable
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const tft_panel_dc_reset_painter_driver_vtable_t gc9a01_driver_vtable = {
.base =
{
.init = qp_gc9a01_init,
.power = qp_tft_panel_power,
.clear = qp_tft_panel_clear,
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
.palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
.append_pixels = qp_tft_panel_append_pixels_rgb565,
.append_pixdata = qp_tft_panel_append_pixdata,
},
.num_window_bytes = 2,
.swap_window_coords = false,
.opcodes =
{
.display_on = GC9A01_CMD_DISPLAY_ON,
.display_off = GC9A01_CMD_DISPLAY_OFF,
.set_column_address = GC9A01_SET_COL_ADDR,
.set_row_address = GC9A01_SET_PAGE_ADDR,
.enable_writes = GC9A01_SET_MEM,
},
};
#ifdef QUANTUM_PAINTER_GC9A01_SPI_ENABLE
// Factory function for creating a handle to the ILI9341 device
painter_device_t qp_gc9a01_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
for (uint32_t i = 0; i < GC9A01_NUM_DEVICES; ++i) {
tft_panel_dc_reset_painter_device_t *driver = &gc9a01_drivers[i];
if (!driver->base.driver_vtable) {
driver->base.driver_vtable = (const painter_driver_vtable_t *)&gc9a01_driver_vtable;
driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable;
driver->base.native_bits_per_pixel = 16; // RGB565
driver->base.panel_width = panel_width;
driver->base.panel_height = panel_height;
driver->base.rotation = QP_ROTATION_0;
driver->base.offset_x = 0;
driver->base.offset_y = 0;
// SPI and other pin configuration
driver->base.comms_config = &driver->spi_dc_reset_config;
driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
driver->spi_dc_reset_config.spi_config.divisor = spi_divisor;
driver->spi_dc_reset_config.spi_config.lsb_first = false;
driver->spi_dc_reset_config.spi_config.mode = spi_mode;
driver->spi_dc_reset_config.dc_pin = dc_pin;
driver->spi_dc_reset_config.reset_pin = reset_pin;
driver->spi_dc_reset_config.command_params_uses_command_pin = false;
if (!qp_internal_register_device((painter_device_t)driver)) {
memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t));
return NULL;
}
return (painter_device_t)driver;
}
}
return NULL;
}
#endif // QUANTUM_PAINTER_GC9A01_SPI_ENABLE

View File

@ -1,77 +0,0 @@
// Copyright 2021 Paul Cotter (@gr1mr3aver)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter GC9A01 command opcodes
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Level 1 command opcodes
#define GC9A01_GET_ID_INFO 0x04 // Get ID information
#define GC9A01_GET_STATUS 0x09 // Get status
#define GC9A01_CMD_SLEEP_ON 0x10 // Enter sleep mode
#define GC9A01_CMD_SLEEP_OFF 0x11 // Exit sleep mode
#define GC9A01_CMD_PARTIAL_ON 0x12 // Enter partial mode
#define GC9A01_CMD_PARTIAL_OFF 0x13 // Exit partial mode
#define GC9A01_CMD_INVERT_ON 0x20 // Enter inverted mode
#define GC9A01_CMD_INVERT_OFF 0x21 // Exit inverted mode
#define GC9A01_CMD_DISPLAY_OFF 0x28 // Disable display
#define GC9A01_CMD_DISPLAY_ON 0x29 // Enable display
#define GC9A01_SET_COL_ADDR 0x2A // Set column address
#define GC9A01_SET_PAGE_ADDR 0x2B // Set page address
#define GC9A01_SET_MEM 0x2C // Set memory
#define GC9A01_SET_PARTIAL_AREA 0x30 // Set partial area
#define GC9A01_SET_VSCROLL 0x33 // Set vertical scroll def
#define GC9A01_CMD_TEARING_ON 0x34 // Tearing line enabled
#define GC9A01_CMD_TEARING_OFF 0x35 // Tearing line disabled
#define GC9A01_SET_MEM_ACS_CTL 0x36 // Set mem access ctl
#define GC9A01_SET_VSCROLL_ADDR 0x37 // Set vscroll start addr
#define GC9A01_CMD_IDLE_OFF 0x38 // Exit idle mode
#define GC9A01_CMD_IDLE_ON 0x39 // Enter idle mode
#define GC9A01_SET_PIX_FMT 0x3A // Set pixel format
#define GC9A01_SET_MEM_CONT 0x3C // Set memory continue
#define GC9A01_SET_TEAR_SCANLINE 0x44 // Set tearing scanline
#define GC9A01_GET_TEAR_SCANLINE 0x45 // Get tearing scanline
#define GC9A01_SET_BRIGHTNESS 0x51 // Set brightness
#define GC9A01_SET_DISPLAY_CTL 0x53 // Set display ctl
#define GC9A01_GET_ID1 0xDA // Get ID1
#define GC9A01_GET_ID2 0xDB // Get ID2
#define GC9A01_GET_ID3 0xDC // Get ID3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Level 2 command opcodes
#define GC9A01_SET_RGB_IF_SIG_CTL 0xB0 // RGB IF signal ctl
#define GC9A01_SET_BLANKING_PORCH_CTL 0xB5 // Set blanking porch ctl
#define GC9A01_SET_FUNCTION_CTL 0xB6 // Set function ctl
#define GC9A01_SET_TEARING_EFFECT 0xBA // Set backlight ctl 3
#define GC9A01_SET_IF_CTL 0xF6 // Set interface control
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Level 3 command opcodes
#define GC9A01_SET_FRAME_RATE 0xE8 // Set frame rate
#define GC9A01_SET_SPI_2DATA 0xE9 // Set frame rate
#define GC9A01_SET_POWER_CTL_1 0xC1 // Set power ctl 1
#define GC9A01_SET_POWER_CTL_2 0xC3 // Set power ctl 2
#define GC9A01_SET_POWER_CTL_3 0xC4 // Set power ctl 3
#define GC9A01_SET_POWER_CTL_4 0xC9 // Set power ctl 4
#define GC9A01_SET_POWER_CTL_7 0xA7 // Set power ctl 7
#define GC9A01_SET_INTER_REG_ENABLE1 0xFE // Enable Inter Register 1
#define GC9A01_SET_INTER_REG_ENABLE2 0xEF // Enable Inter Register 2
#define GC9A01_SET_GAMMA1 0xF0 //
#define GC9A01_SET_GAMMA2 0xF1
#define GC9A01_SET_GAMMA3 0xF2
#define GC9A01_SET_GAMMA4 0xF3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MADCTL Flags
#define GC9A01_MADCTL_MY 0b10000000
#define GC9A01_MADCTL_MX 0b01000000
#define GC9A01_MADCTL_MV 0b00100000
#define GC9A01_MADCTL_ML 0b00010000
#define GC9A01_MADCTL_RGB 0b00000000
#define GC9A01_MADCTL_BGR 0b00001000
#define GC9A01_MADCTL_MH 0b00000100

View File

@ -0,0 +1,114 @@
// Copyright 2024 Fernando Birra
// SPDX-License-Identifier: GPL-2.0-or-later
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_gc9107.h"
#include "qp_gc9xxx_opcodes.h"
#include "qp_gc9107_opcodes.h"
#include "qp_tft_panel.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver storage
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tft_panel_dc_reset_painter_device_t gc9107_drivers[GC9107_NUM_DEVICES] = {0};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
__attribute__((weak)) bool qp_gc9107_init(painter_device_t device, painter_rotation_t rotation) {
// A lot of these "unknown" opcodes are sourced from other OSS projects and are seemingly required for this display to function.
// clang-format off
const uint8_t gc9107_init_sequence[] = {
GC9XXX_SET_INTER_REG_ENABLE1, 5, 0,
GC9XXX_SET_INTER_REG_ENABLE2, 5, 0,
GC9107_SET_FUNCTION_CTL6, 0, 1, GC9107_ALLOW_SET_COMPLEMENT_RGB | 0x08 | GC9107_ALLOW_SET_FRAMERATE,
GC9107_SET_COMPLEMENT_RGB, 0, 1, GC9107_COMPLEMENT_WITH_LSB,
0xAB, 0, 1, 0x0E,
GC9107_SET_FRAME_RATE, 0, 1, 0x19,
GC9XXX_SET_PIXEL_FORMAT, 0, 1, GC9107_PIXEL_FORMAT_16_BPP_IFPF,
GC9XXX_CMD_SLEEP_OFF, 120, 0,
GC9XXX_CMD_DISPLAY_ON, 20, 0
};
// clang-format on
qp_comms_bulk_command_sequence(device, gc9107_init_sequence, sizeof(gc9107_init_sequence));
// Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
const uint8_t madctl[] = {
[QP_ROTATION_0] = GC9XXX_MADCTL_BGR,
[QP_ROTATION_90] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MV,
[QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY,
[QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY,
};
qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver vtable
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const tft_panel_dc_reset_painter_driver_vtable_t gc9107_driver_vtable = {
.base =
{
.init = qp_gc9107_init,
.power = qp_tft_panel_power,
.clear = qp_tft_panel_clear,
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
.palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
.append_pixels = qp_tft_panel_append_pixels_rgb565,
.append_pixdata = qp_tft_panel_append_pixdata,
},
.num_window_bytes = 2,
.swap_window_coords = false,
.opcodes =
{
.display_on = GC9XXX_CMD_DISPLAY_ON,
.display_off = GC9XXX_CMD_DISPLAY_OFF,
.set_column_address = GC9XXX_SET_COL_ADDR,
.set_row_address = GC9XXX_SET_ROW_ADDR,
.enable_writes = GC9XXX_SET_MEM,
},
};
#ifdef QUANTUM_PAINTER_GC9107_SPI_ENABLE
// Factory function for creating a handle to the GC9107 device
painter_device_t qp_gc9107_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
for (uint32_t i = 0; i < GC9107_NUM_DEVICES; ++i) {
tft_panel_dc_reset_painter_device_t *driver = &gc9107_drivers[i];
if (!driver->base.driver_vtable) {
driver->base.driver_vtable = (const painter_driver_vtable_t *)&gc9107_driver_vtable;
driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable;
driver->base.native_bits_per_pixel = 16; // RGB565
driver->base.panel_width = panel_width;
driver->base.panel_height = panel_height;
driver->base.rotation = QP_ROTATION_0;
driver->base.offset_x = 2;
driver->base.offset_y = 1;
// SPI and other pin configuration
driver->base.comms_config = &driver->spi_dc_reset_config;
driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
driver->spi_dc_reset_config.spi_config.divisor = spi_divisor;
driver->spi_dc_reset_config.spi_config.lsb_first = false;
driver->spi_dc_reset_config.spi_config.mode = spi_mode;
driver->spi_dc_reset_config.dc_pin = dc_pin;
driver->spi_dc_reset_config.reset_pin = reset_pin;
driver->spi_dc_reset_config.command_params_uses_command_pin = false;
if (!qp_internal_register_device((painter_device_t)driver)) {
memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t));
return NULL;
}
return (painter_device_t)driver;
}
}
return NULL;
}
#endif // QUANTUM_PAINTER_GC9107_SPI_ENABLE

View File

@ -0,0 +1,37 @@
// Copyright 2024 Fernando Birra (@gr1mr3aver)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "gpio.h"
#include "qp_internal.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter GC9107 configurables (add to your keyboard's config.h)
#ifndef GC9107_NUM_DEVICES
/**
* @def This controls the maximum number of GC9107 devices that Quantum Painter can communicate with at any one time.
* Increasing this number allows for multiple displays to be used.
*/
# define GC9107_NUM_DEVICES 1
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter GC9107 device factories
#ifdef QUANTUM_PAINTER_GC9107_SPI_ENABLE
/**
* Factory method for an GC9107 SPI LCD device.
*
* @param panel_width[in] the width of the display panel
* @param panel_height[in] the height of the display panel
* @param chip_select_pin[in] the GPIO pin used for SPI chip select
* @param dc_pin[in] the GPIO pin used for D/C control
* @param reset_pin[in] the GPIO pin used for RST
* @param spi_divisor[in] the SPI divisor to use when communicating with the display
* @param spi_mode[in] the SPI mode to use when communicating with the display
* @return the device handle used with all drawing routines in Quantum Painter
*/
painter_device_t qp_gc9107_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
#endif // QUANTUM_PAINTER_GC9107_SPI_ENABLE

View File

@ -0,0 +1,135 @@
// Copyright 2024 Fernando Birra
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter GC9107 command opcodes
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define GC9107_GET_POWER_MODE 0x0A // Get power mode
#define GC9107_GET_MADCTL 0x0B // Get MADCTL
#define GC9107_GET_PIXEL_FMT 0x0C // Get pixel format
#define GC9107_GET_IMAGE_FMT 0x0D // Get image format
#define GC9107_GET_SIGNAL_MODE 0x0E // Get signal mode
#define GC9107_GET_DIAG_RESULT 0x0F // Get self-diagnostic results
#define GC9107_SET_FRAME_RATE 0xA8 // Set frame rate
#define GC9107_SET_COMPLEMENT_RGB 0xAC // Set complement Principle RGB
#define GC9107_SET_BLANK_PORCH 0xAD // Set blank porch control, 0;front_porch[6:0],0;back_porch[6:0]
#define GC9107_SET_FUNCTION_CTL1 0xB1 // Set access to AVDD_VCL_CLK and VGH_VGL_CLK commands
#define GC9107_SET_FUNCTION_CTL2 0xB2 // Set access to VGH, VGH control commands
#define GC9107_SET_FUNCTION_CTL3 0xB3 // Set access to Gamma control commands
#define GC9107_SET_DISPLAY_INVERSION 0xB4 // Set Display Inversion control
#define GC9107_SET_FUNCTION_CTL6 0xB6 // Set access to commands SET_FRAME_RATE, SET_COMPLEMENT_RGB and SET_BLANK_PORCH
#define GC9107_SET_CUSTOM_ID_INFO 0xD3 // Set customized display id information
#define GC9107_AVDD_VCL_CLK 0xE3 // AVDD_CLK
#define GC9107_SET_VGH 0xE8 // Set VGH
#define GC9107_SET_VGL 0xE9 // Set VGL
#define GC9107_SET_VGH_VGL_CLK 0xEA // Set VGH and VGL clock divisors
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GC9107 Parameter constants
// Parameter values for
// GC9107_SET_PIXEL_FORMAT
#define GC9107_PIXEL_FORMAT_12_BPP_IFPF (0b001 << 0) // 12 bits per pixel
#define GC9107_PIXEL_FORMAT_16_BPP_IFPF (0b101 << 0) // 16 bits per pixel
#define GC9107_PIXEL_FORMAT_18_BPP_IFPB (0b110 << 0) // 18 bits per pixel
// Parameter values for
// GC9107_SET_COMPLEMENT_RGB
#define GC9107_COMPLEMENT_WITH_0 0x00 // R0 <- B0 <- 0, except if data is FFh
#define GC9107_COMPLEMENT_WITH_1 0x40 // R0 <- B0 <- 1, except if data is 00h
#define GC9107_COMPLEMENT_WITH_MSB 0x80 // R0 <- R5, B0 <- B5
#define GC9107_COMPLEMENT_WITH_LSB 0xC0 // R0 <- B0 <- G0
// Parameter masks for
// GC9107_SET_FUNCTION_CTL1
#define GC9107_ALLOW_AVDD_VCL_CLK 0b00001000 // Allow AVDD_VCL_CLK command
// Parameter masks for
// GC9107_SET_FUNCTION_CTL2
#define GC9107_ALLOW_SET_VGH 0b00000001 // Allow GC9107_SET_VGH
#define GC9107_ALLOW_SET_VGL 0b00000010 // Allow GC9107_SET_VGL
#define GC9107_ALLOW_SET_VGH_VGL_CLK 0b00000100 // Allow GC9107_SET_VGH_VGL_CLK
// Parameter masks for
// GC9107_SET_FUNCTION_CTL3
#define GC9107_ALLOW_SET_GAMMA1 0b00000001 // Allow GC9107_SET_GAMMA1
#define GC9107_ALLOW_SET_GAMMA2 0b00000010 // Allow GC9107_SET_GAMMA2
// Parameter mask for
// GC9107_SET_FUNCTION_CTL6
#define GC9107_ALLOW_SET_FRAMERATE 0b000000001 // Allow GC9107_SET_FRAME_RATE
#define GC9107_ALLOW_SET_COMPLEMENT_RGB 0b000010000 // Allow GC9107_SET_COMPLEMENT_RGB
#define GC9107_ALLOW_SET_BLANK_PORCH 0b000100000 // Allow GFC9107_SET_BLANK_PORCH
// Parameter values for
// AVDD_CLK_AD part (Most significant nibble)
#define GC9107_AVDD_CLK_AD_2T 0x00
#define GC9107_AVDD_CLK_AD_3T 0x10
#define GC9107_AVDD_CLK_AD_4T 0x20
#define GC9107_AVDD_CLK_AD_5T 0x30
#define GC9107_AVDD_CLK_AD_6T 0x40
#define GC9107_AVDD_CLK_AD_7T 0x50
#define GC9107_AVDD_CLK_AD_8T 0x60
#define GC9107_AVDD_CLK_AD_9T 0x70
// Parameter values for
// VCL_CLK_AD part (Least significant nibble)
#define GC9107_VCL_CLK_AD_2T 0x00
#define GC9107_VCL_CLK_AD_3T 0x01
#define GC9107_VCL_CLK_AD_4T 0x02
#define GC9107_VCL_CLK_AD_5T 0x03
#define GC9107_VCL_CLK_AD_6T 0x04
#define GC9107_VCL_CLK_AD_7T 0x05
#define GC9107_VCL_CLK_AD_8T 0x06
#define GC9107_VCL_CLK_AD_9T 0x07
// Parameter values for
// GC9107_SET_VGH
#define GC9107_VGH_P100 0x20 // +10 V
#define GC9107_VGH_P110 0x21 // +11 V
#define GC9107_VGH_P120 0x22 // +12 V
#define GC9107_VGH_P130 0x23 // +13 V
#define GC9107_VGH_P140 0x24 // +14 V
#define GC9107_VGH_P150 0x25 // +15 V
// Parameter values for
// GC9107_SET_VGL
#define VGL_N_075 0x40 // -7.5 V
#define VGL_N_085 0x41 // -8.5 V
#define VGL_N_095 0x42 // -9.5 V
#define VGL_N_100 0x43 // -10.0 V
#define VGL_N_105 0x44 // -10.5 V
#define VGL_N_110 0x45 // -11.0 V
#define VGL_N_120 0x46 // -12.0 V
#define VGL_N_130 0x47 // -13.0 V
// Parameter masks for
// GC9107_SET_VGH_VGL_CLK (VGH Divisor)
#define GC9107_VGH_CLK_DIV_2 0x00 // Clock divisor = 2 -> 6.0 Mhz
#define GC9107_VGH_CLK_DIV_3 0x10 // Clock divisor = 3 -> 4.0 Mhz
#define GC9107_VGH_CLK_DIV_4 0x20 // Clock divisor = 4 -> 3.0 Mhz
#define GC9107_VGH_CLK_DIV_5 0x30 // Clock divisor = 5 -> 2.4 Mhz
#define GC9107_VGH_CLK_DIV_6 0x40 // Clock divisor = 6 -> 2.0 Mhz
#define GC9107_VGH_CLK_DIV_7 0x50 // Clock divisor = 7 -> 1.7 Mhz
#define GC9107_VGH_CLK_DIV_8 0x60 // Clock divisor = 8 -> 1.5 Mhz
#define GC9107_VGH_CLK_DIV_9 0x70 // Clock divisor = 9 -> 1.3 Mhz
#define GC9107_VGH_CLK_DIV_10 0x80 // Clock divisor = 10 -> 1.2 Mhz
#define GC9107_VGH_CLK_DIV_12 0x90 // Clock divisor = 12 -> 1.0 Mhz
#define GC9107_VGH_CLK_DIV_15 0xA0 // Clock divisor = 15 -> 0.8 Mhz
#define GC9107_VGH_CLK_DIV_20 0xB0 // Clock divisor = 20 -> 0.6 Mhz
#define GC9107_VGH_CLK_DIV_24 0xC0 // Clock divisor = 24 -> 0.5 Mhz
#define GC9107_VGH_CLK_DIV_30 0xD0 // Clock divisor = 30 -> 0.4 Mhz
#define GC9107_VGH_CLK_DIV_40 0xE0 // Clock divisor = 40 -> 0.3 Mhz
#define GC9107_VGH_CLK_DIV_60 0xE0 // Clock divisor = 40 -> 0.2 Mhz
// Parameter masks for
// GC9107_SET_VGH_VGL_CLK (VGL Divisor)
#define GC9107_VGL_CLK_DIV_2 0x00 // Clock divisor = 2 -> 6.0 Mhz
#define GC9107_VGL_CLK_DIV_3 0x01 // Clock divisor = 3 -> 4.0 Mhz
#define GC9107_VGL_CLK_DIV_4 0x02 // Clock divisor = 4 -> 3.0 Mhz
#define GC9107_VGL_CLK_DIV_5 0x03 // Clock divisor = 5 -> 2.4 Mhz
#define GC9107_VGL_CLK_DIV_6 0x04 // Clock divisor = 6 -> 2.0 Mhz
#define GC9107_VGL_CLK_DIV_7 0x05 // Clock divisor = 7 -> 1.7 Mhz
#define GC9107_VGL_CLK_DIV_8 0x06 // Clock divisor = 8 -> 1.5 Mhz
#define GC9107_VGL_CLK_DIV_9 0x07 // Clock divisor = 9 -> 1.3 Mhz
#define GC9107_VGL_CLK_DIV_10 0x08 // Clock divisor = 10 -> 1.2 Mhz
#define GC9107_VGL_CLK_DIV_12 0x09 // Clock divisor = 12 -> 1.0 Mhz
#define GC9107_VGL_CLK_DIV_15 0x0A // Clock divisor = 15 -> 0.8 Mhz
#define GC9107_VGL_CLK_DIV_20 0x0B // Clock divisor = 20 -> 0.6 Mhz
#define GC9107_VGL_CLK_DIV_24 0x0C // Clock divisor = 24 -> 0.5 Mhz
#define GC9107_VGL_CLK_DIV_30 0x0D // Clock divisor = 30 -> 0.4 Mhz
#define GC9107_VGL_CLK_DIV_40 0x0E // Clock divisor = 40 -> 0.3 Mhz
#define GC9107_VGL_CLK_DIV_60 0x0E // Clock divisor = 40 -> 0.2 Mhz

View File

@ -0,0 +1,127 @@
// Copyright 2021 Paul Cotter (@gr1mr3aver)
// Copyright 2023 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_gc9a01.h"
#include "qp_gc9xxx_opcodes.h"
#include "qp_gc9a01_opcodes.h"
#include "qp_tft_panel.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver storage
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tft_panel_dc_reset_painter_device_t gc9a01_drivers[GC9A01_NUM_DEVICES] = {0};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
__attribute__((weak)) bool qp_gc9a01_init(painter_device_t device, painter_rotation_t rotation) {
// A lot of these "unknown" opcodes are sourced from other OSS projects and are seemingly required for this display to function.
// clang-format off
const uint8_t gc9a01_init_sequence[] = {
// Command, Delay, N, Data[N]
GC9XXX_SET_INTER_REG_ENABLE1, 0, 0,
GC9XXX_SET_INTER_REG_ENABLE2, 0, 0,
0x84, 0, 1, 0x40,
GC9A01_SET_FUNCTION_CTL, 0, 3, 0x00, GC9A01_SOURCE_OUTPUT_SCAN_DIRECTION_S360_TO_S1 | GC9A01_GATE_OUTPUT_SCAN_DIRECTION_G1_TO_G32, GC9A01_LCD_DRIVE_LINE_240, // Only works if the previous command is present (undocumented)
GC9A01_SET_POWER_CTL_2, 0, 1, 0x20,
GC9A01_SET_POWER_CTL_3, 0, 1, 0x20,
GC9A01_SET_POWER_CTL_4, 0, 1, 0x22,
GC9XXX_SET_GAMMA1, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
GC9XXX_SET_GAMMA2, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
GC9A01_SET_GAMMA3, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
GC9A01_SET_GAMMA4, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
0x66, 0, 10, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00,
0x67, 0, 10, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98,
GC9XXX_CMD_TEARING_ON, 0, 0,
GC9XXX_SET_PIXEL_FORMAT, 0, 1, GC9A01_PIXEL_FORMAT_16_BPP_DBI,
GC9XXX_CMD_INVERT_ON, 0, 0,
GC9XXX_CMD_SLEEP_OFF, 120, 0,
GC9XXX_CMD_DISPLAY_ON, 20, 0
};
// clang-format on
qp_comms_bulk_command_sequence(device, gc9a01_init_sequence, sizeof(gc9a01_init_sequence));
// Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
const uint8_t madctl[] = {
[QP_ROTATION_0] = GC9XXX_MADCTL_BGR,
[QP_ROTATION_90] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MV,
[QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY,
[QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY,
};
qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver vtable
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const tft_panel_dc_reset_painter_driver_vtable_t gc9a01_driver_vtable = {
.base =
{
.init = qp_gc9a01_init,
.power = qp_tft_panel_power,
.clear = qp_tft_panel_clear,
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
.palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
.append_pixels = qp_tft_panel_append_pixels_rgb565,
.append_pixdata = qp_tft_panel_append_pixdata,
},
.num_window_bytes = 2,
.swap_window_coords = false,
.opcodes =
{
.display_on = GC9XXX_CMD_DISPLAY_ON,
.display_off = GC9XXX_CMD_DISPLAY_OFF,
.set_column_address = GC9XXX_SET_COL_ADDR,
.set_row_address = GC9XXX_SET_ROW_ADDR,
.enable_writes = GC9XXX_SET_MEM,
},
};
#ifdef QUANTUM_PAINTER_GC9A01_SPI_ENABLE
// Factory function for creating a handle to the ILI9341 device
painter_device_t qp_gc9a01_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
for (uint32_t i = 0; i < GC9A01_NUM_DEVICES; ++i) {
tft_panel_dc_reset_painter_device_t *driver = &gc9a01_drivers[i];
if (!driver->base.driver_vtable) {
driver->base.driver_vtable = (const painter_driver_vtable_t *)&gc9a01_driver_vtable;
driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable;
driver->base.native_bits_per_pixel = 16; // RGB565
driver->base.panel_width = panel_width;
driver->base.panel_height = panel_height;
driver->base.rotation = QP_ROTATION_0;
driver->base.offset_x = 0;
driver->base.offset_y = 0;
// SPI and other pin configuration
driver->base.comms_config = &driver->spi_dc_reset_config;
driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
driver->spi_dc_reset_config.spi_config.divisor = spi_divisor;
driver->spi_dc_reset_config.spi_config.lsb_first = false;
driver->spi_dc_reset_config.spi_config.mode = spi_mode;
driver->spi_dc_reset_config.dc_pin = dc_pin;
driver->spi_dc_reset_config.reset_pin = reset_pin;
driver->spi_dc_reset_config.command_params_uses_command_pin = false;
if (!qp_internal_register_device((painter_device_t)driver)) {
memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t));
return NULL;
}
return (painter_device_t)driver;
}
}
return NULL;
}
#endif // QUANTUM_PAINTER_GC9A01_SPI_ENABLE

View File

@ -0,0 +1,104 @@
// Copyright 2021 Paul Cotter (@gr1mr3aver)
// Copyright 2024 Fernando Birra
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter GC9A01 command opcodes
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define GC9A01_SET_MEM_CONT 0x3C // Set memory continue
#define GC9A01_SET_BRIGHTNESS 0x51 // Set brightness
#define GC9A01_SET_DISPLAY_CTL 0x53 // Set display ctl
#define GC9A01_SET_RGB_IF_SIG_CTL 0xB0 // RGB IF signal ctl
#define GC9A01_SET_BLANKING_PORCH_CTL 0xB5 // Set blanking porch ctl
#define GC9A01_SET_FUNCTION_CTL 0xB6 // Set function ctl
#define GC9A01_SET_TEARING_EFFECT 0xBA // Set tering effect control
#define GC9A01_SET_POWER_CTL_7 0xA7 // Set power ctl 7
#define GC9A01_SET_POWER_CTL_1 0xC1 // Set power ctl 1
#define GC9A01_SET_POWER_CTL_2 0xC3 // Set power ctl 2
#define GC9A01_SET_POWER_CTL_3 0xC4 // Set power ctl 3
#define GC9A01_SET_POWER_CTL_4 0xC9 // Set power ctl 4
#define GC9A01_SET_FRAME_RATE 0xE8 // Set frame rate
#define GC9A01_SET_SPI_2DATA 0xE9 // Set frame rate
#define GC9A01_SET_GAMMA3 0xF2 // Set gamma 3
#define GC9A01_SET_GAMMA4 0xF3 // Set gamma 4
#define GC9A01_SET_IF_CTL 0xF6 // Set interface control
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GC9A01 MADCTL Flags
#define GC9A01_MADCTL_MH 0b00000100
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GC9A01 Parameter constants
// Parameter values for
// GC9A01_SET_PIXEL_FORMAT
#define GC9A01_PIXEL_FORMAT_12_BPP_DBI (0b011 << 0) // 12 bits/pixel MCU interface format
#define GC9A01_PIXEL_FORMAT_16_BPP_DBI (0b101 << 0) // 16 bits/pixel MCU interface format
#define GC9A01_PIXEL_FORMAT_18_BPP_DBI (0b110 << 0) // 18 bits/pixel MCU interface format
#define GC9A01_PIXEL_FORMAT_16_BPP_DPI (0b101 << 4) // 16 bits/pixel RGB interface format
#define GC9A01_PIXEL_FORMAT_18_BPP_DPI (0b110 << 4) // 18 bits/pixel RGB interface format
// Parameter values for
// GC9A01_SET_FUNCTION_CTL (2nd parameter)
#define GC9A01_SOURCE_OUTPUT_SCAN_DIRECTION_S1_TO_S360 0b00000000
#define GC9A01_SOURCE_OUTPUT_SCAN_DIRECTION_S360_TO_S1 0b00100000
#define GC9A01_GATE_OUTPUT_SCAN_DIRECTION_G1_TO_G32 0b00000000
#define GC9A01_GATE_OUTPUT_SCAN_DIRECTION_G32_TO_G1 0b01000000
#define GC9A01_SCAN_MODE_INTER 0x10
// Parameter values for
// GC9A01_SET_FUNCTION_CTL (3rd parameter)
#define GC9A01_LCD_DRIVE_LINE_16 0x01
#define GC9A01_LCD_DRIVE_LINE_24 0x02
#define GC9A01_LCD_DRIVE_LINE_32 0x03
#define GC9A01_LCD_DRIVE_LINE_40 0x04
#define GC9A01_LCD_DRIVE_LINE_48 0x05
#define GC9A01_LCD_DRIVE_LINE_56 0x06
#define GC9A01_LCD_DRIVE_LINE_64 0x07
#define GC9A01_LCD_DRIVE_LINE_72 0x08
#define GC9A01_LCD_DRIVE_LINE_80 0x09
#define GC9A01_LCD_DRIVE_LINE_88 0x0A
#define GC9A01_LCD_DRIVE_LINE_96 0x0B
#define GC9A01_LCD_DRIVE_LINE_104 0x0C
#define GC9A01_LCD_DRIVE_LINE_112 0x0D
#define GC9A01_LCD_DRIVE_LINE_120 0x0E
#define GC9A01_LCD_DRIVE_LINE_128 0x0F
#define GC9A01_LCD_DRIVE_LINE_136 0x10
#define GC9A01_LCD_DRIVE_LINE_144 0x11
#define GC9A01_LCD_DRIVE_LINE_152 0x12
#define GC9A01_LCD_DRIVE_LINE_160 0x13
#define GC9A01_LCD_DRIVE_LINE_168 0x14
#define GC9A01_LCD_DRIVE_LINE_176 0x15
#define GC9A01_LCD_DRIVE_LINE_184 0x16
#define GC9A01_LCD_DRIVE_LINE_192 0x17
#define GC9A01_LCD_DRIVE_LINE_200 0x18
#define GC9A01_LCD_DRIVE_LINE_208 0x19
#define GC9A01_LCD_DRIVE_LINE_216 0x1A
#define GC9A01_LCD_DRIVE_LINE_224 0x1B
#define GC9A01_LCD_DRIVE_LINE_232 0x1C
#define GC9A01_LCD_DRIVE_LINE_240 0x1D
// Parameter values for
// GC9A01_SET_DISPLAY_CTL
#define GC9A01_BRIGHTNESS_CONTROL_ON 0b00100000
#define GC9A01_DIMMING_ON 0b00001000
#define GC9A01_BACKLIGHT_ON 0b00000100
#define GC9A01_BRIGHTNESS_CONTROL_OFF 0b00000000
#define GC9A01_DIMMING_OFF 0b00000000
#define GC9A01_BACKLIGHT_OFF 0b00000000
// Parameter values for
// GC9A01_SET_IF_CTL
#define GC9A01_DISPLAY_MODE_INTERNAL_CLOCK 0b00000000
#define GC9A01_DISPLAY_MODE_RGB_INTERFACE 0b00000100
#define GC9A01_DISPLAY_MODE_VSYNC_INTERFACE 0b00001000
#define GC9A01_DSISPLAY_MODE_DISABLED 0b00001100
#define GC0A01_GRAM_INTERFACE_VSYNC 0b00000000
#define GC9A01_GRAM_INTERFACE_RGB 0b00000010
#define GC9A01_RGB_INTERFACE_MODE_1_TRANSFER 0b00000000
#define GC9A01_RGB_INTERFACE_MODE_3_TRANSFER 0b00000001

View File

@ -0,0 +1,55 @@
// Copyright 2021 Paul Cotter (@gr1mr3aver)
// Copyright 2024 Fernando Birra
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter GC9xxx command opcodes
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define GC9XXX_GET_ID_INFO 0x04 // Get ID information
#define GC9XXX_GET_STATUS 0x09 // Get status
#define GC9XXX_CMD_SLEEP_ON 0x10 // Enter sleep mode
#define GC9XXX_CMD_SLEEP_OFF 0x11 // Exit sleep mode
#define GC9XXX_CMD_PARTIAL_ON 0x12 // Enter partial mode
#define GC9XXX_CMD_PARTIAL_OFF 0x13 // Exit partial mode
#define GC9XXX_CMD_INVERT_OFF 0x20 // Exit inverted mode
#define GC9XXX_CMD_INVERT_ON 0x21 // Enter inverted mode
#define GC9XXX_CMD_DISPLAY_OFF 0x28 // Disable display
#define GC9XXX_CMD_DISPLAY_ON 0x29 // Enable display
#define GC9XXX_SET_COL_ADDR 0x2A // Set column address (MSB(StartCol),LSB(StartCol),MSB(EndCol),LSB(EndCol)
#define GC9XXX_SET_ROW_ADDR 0x2B // Set row address (MSB(StartRow),LSB(StartRow),MSB(EndRow),LSB(EndRow)
#define GC9XXX_SET_MEM 0x2C // Set (write) memory
#define GC9XXX_SET_PARTIAL_AREA 0x30 // Set partial area (MSB(StartRow),LSB(StartRow),MSB(EndRow),LSB(EndRow)
#define GC9XXX_SET_VSCROLL 0x33 // Set vertical scroll MSB(TFA),LSB(TFA),MSB(VSA),LSB(VSA)+ GC9107 extra param: MSB(BFA),LSB(BFA)
#define GC9XXX_CMD_TEARING_OFF 0x34 // Tearing effect line OFF
#define GC9XXX_CMD_TEARING_ON 0x35 // Tearing effect line ON
#define GC9XXX_SET_MEM_ACS_CTL 0x36 // Set mem access ctl
#define GC9XXX_SET_VSCROLL_ADDR 0x37 // Set vscroll start addr
#define GC9XXX_CMD_IDLE_OFF 0x38 // Exit idle mode
#define GC9XXX_CMD_IDLE_ON 0x39 // Enter idle mode
#define GC9XXX_SET_PIXEL_FORMAT 0x3A // Set pixel format
#define GC9XXX_SET_TEAR_SCANLINE 0x44 // Set tearing scanline (Scanline = LS bit of Param 1 (GC9A01) + Param 2(GC9XXX))
#define GC9XXX_GET_TEAR_SCANLINE 0x45 // Get tearing scanline (Scanline = LS bit of Param 1 (GC9A01) + Param 2(GC9XXX))
#define GC9XXX_GET_ID1 0xDA // Get ID1
#define GC9XXX_GET_ID2 0xDB // Get ID2
#define GC9XXX_GET_ID3 0xDC // Get ID3
#define GC9XXX_SET_INTER_REG_ENABLE1 0xFE // Enable Inter Register 1
#define GC9XXX_SET_INTER_REG_ENABLE2 0xEF // Enable Inter Register 2
#define GC9XXX_SET_GAMMA1 0xF0 // Set gamma 1
#define GC9XXX_SET_GAMMA2 0xF1 // Set gamma 2
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MADCTL Flags
#define GC9XXX_MADCTL_MY 0b10000000 // Mirror Y (row address order)
#define GC9XXX_MADCTL_MX 0b01000000 // Mirror X (column address order)
#define GC9XXX_MADCTL_MV 0b00100000 // Vertical Refresh Order (bottom to top)
#define GC9XXX_MADCTL_ML 0b00010000
#define GC9XXX_MADCTL_BGR 0b00001000
#define GC9XXX_MADCTL_RGB 0b00000000
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GC9XXX Parameter constants

View File

@ -115,6 +115,7 @@ void adns9800_init(void) {
adns9800_read(REG_Delta_Y_L); adns9800_read(REG_Delta_Y_L);
adns9800_read(REG_Delta_Y_H); adns9800_read(REG_Delta_Y_H);
#ifdef ADNS9800_UPLOAD_SROM
// upload firmware // upload firmware
// 3k firmware mode // 3k firmware mode
@ -145,6 +146,16 @@ void adns9800_init(void) {
spi_stop(); spi_stop();
wait_ms(10); wait_ms(10);
#else
// write reset value to REG_Configuration_IV
adns9800_write(REG_Configuration_IV, 0x0);
// write reset value to REG_SROM_Enable
adns9800_write(REG_SROM_Enable, 0x0);
// wait a frame
wait_ms(10);
#endif
// enable laser // enable laser
uint8_t laser_ctrl0 = adns9800_read(REG_LASER_CTRL0); uint8_t laser_ctrl0 = adns9800_read(REG_LASER_CTRL0);

View File

@ -28,7 +28,7 @@ typedef struct {
# ifndef CIRQUE_PINNACLE_TAPPING_TERM # ifndef CIRQUE_PINNACLE_TAPPING_TERM
# include "action.h" # include "action.h"
# include "action_tapping.h" # include "action_tapping.h"
# define CIRQUE_PINNACLE_TAPPING_TERM GET_TAPPING_TERM(KC_BTN1, &(keyrecord_t){}) # define CIRQUE_PINNACLE_TAPPING_TERM GET_TAPPING_TERM(QK_MOUSE_BUTTON_1, &(keyrecord_t){})
# endif # endif
# ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE # ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE
# define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8) # define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8)

View File

@ -154,10 +154,12 @@ bool pmw33xx_init(uint8_t sensor) {
pmw33xx_read(sensor, REG_Delta_Y_L); pmw33xx_read(sensor, REG_Delta_Y_L);
pmw33xx_read(sensor, REG_Delta_Y_H); pmw33xx_read(sensor, REG_Delta_Y_H);
#ifdef PMW33XX_UPLOAD_SROM
if (!pmw33xx_upload_firmware(sensor)) { if (!pmw33xx_upload_firmware(sensor)) {
pd_dprintf("PMW33XX (%d): firmware upload failed!\n", sensor); pd_dprintf("PMW33XX (%d): firmware upload failed!\n", sensor);
return false; return false;
} }
#endif
spi_stop(); spi_stop();
@ -200,7 +202,7 @@ pmw33xx_report_t pmw33xx_read_burst(uint8_t sensor) {
spi_write(REG_Motion_Burst); spi_write(REG_Motion_Burst);
wait_us(35); // waits for tSRAD_MOTBR wait_us(35); // waits for tSRAD_MOTBR
spi_receive((uint8_t*)&report, sizeof(report)); spi_receive((uint8_t *)&report, sizeof(report));
// panic recovery, sometimes burst mode works weird. // panic recovery, sometimes burst mode works weird.
if (report.motion.w & 0b111) { if (report.motion.w & 0b111) {

View File

@ -58,7 +58,7 @@ bool backing_store_read(uint32_t address, backing_store_int_t *value) {
bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) { bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
bs_dprintf("Read "); bs_dprintf("Read ");
uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address; uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
flash_status_t status = flash_read_block(offset, values, sizeof(backing_store_int_t) * item_count); flash_status_t status = flash_read_range(offset, values, sizeof(backing_store_int_t) * item_count);
if (status == FLASH_STATUS_SUCCESS) { if (status == FLASH_STATUS_SUCCESS) {
for (size_t i = 0; i < item_count; ++i) { for (size_t i = 0; i < item_count; ++i) {
values[i] = ~values[i]; values[i] = ~values[i];
@ -88,7 +88,7 @@ bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, siz
} }
// Write out the block // Write out the block
if (flash_write_block(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) { if (flash_write_range(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
return false; return false;
} }

View File

@ -1,22 +0,0 @@
/* Copyright 2021 Vinam Arora <vinam@posteo.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#define DYNAMIC_KEYMAP_LAYER_COUNT 7
/* This is 4 by default. ProMicro's memory doesn't seem to be able to
* support more than 7 dynamic keymap layers
*/

View File

@ -1,146 +0,0 @@
/* Copyright 2020 Vinam Arora <vinam@posteo.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
// 4 layers, because that is what VIA can support by default
enum zero_sixty_layers {
_QWERTY,
_LOWER,
_RAISE,
_ADJUST,
_EMPTY1, // Just to initialize dynamic layers in VIA
_EMPTY2,
_EMPTY3,
};
#define LOWER MO(_LOWER)
#define RAISE MO(_RAISE)
#define ADJUST MO(_ADJUST)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Qwerty
* ,-----------------------------------------------------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | Tab | Q | W | E | R | T | Y | U | I | O | P | Del |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | Esc | A | S | D | F | G | H | J | K | L | ; | " |
* |------+------+------+------+------+------|------+------+------+------+------+------|
* | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | Caps | Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
* `-----------------------------------------------------------------------------------'
*/
[_QWERTY] = LAYOUT_ortho_5x12(
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL,
KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
KC_CAPS, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT
),
/* Lower
* ,-----------------------------------------------------------------------------------.
* | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Del |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
* |------+------+------+------+------+------|------+------+------+------+------+------|
* | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | | | | | | | Next | Vol- | Vol+ | Play |
* `-----------------------------------------------------------------------------------'
*/
[_LOWER] = LAYOUT_ortho_5x12(
KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC,
KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL,
KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),KC_HOME, KC_END, _______,
_______, _______, _______, _______, _______, _______, _______, ADJUST, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY
),
/* Raise
* ,-----------------------------------------------------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Del |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
* |------+------+------+------+------+------|------+------+------+------+------+------|
* | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | | | | | | | Next | Vol- | Vol+ | Play |
* `-----------------------------------------------------------------------------------'
*/
[_RAISE] = LAYOUT_ortho_5x12(
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,
_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______,
_______, _______, _______, _______, ADJUST, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY
),
/* Adjust
* ,-----------------------------------------------------------------------------------.
* | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | Reset| | | | | | | | | | Del |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | | | | | | | | | | | | |
* |------+------+------+------+------+------|------+------+------+------+------+------|
* | | | | | | | | | | | | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | | | | | | | | | | |
* `-----------------------------------------------------------------------------------'
*/
[_ADJUST] = LAYOUT_ortho_5x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
_______, QK_BOOT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
/* Transparent layers, only to initialize VIA's dynamic layers */
[_EMPTY1] = LAYOUT_ortho_5x12(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[_EMPTY2] = LAYOUT_ortho_5x12(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[_EMPTY3] = LAYOUT_ortho_5x12(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
};

View File

@ -1,2 +0,0 @@
VIA_ENABLE = yes
MOUSEKEY_ENABLE = yes

View File

@ -1,48 +0,0 @@
/* Copyright 2021 0xC7
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_60_ansi(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_APP, KC_RCTL
),
[1] = LAYOUT_60_ansi(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL,
KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SCRL, KC_PAUS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_HOME, KC_PGUP, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_DEL, KC_END, KC_PGDN, KC_TRNS,
KC_TRNS, KC_TRNS, QK_LOCK, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, C(A(KC_DEL))
),
[2] = LAYOUT_60_ansi(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[3] = LAYOUT_60_ansi(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
)
};

View File

@ -1 +0,0 @@
VIA_ENABLE = yes

View File

@ -1,27 +0,0 @@
/*
Copyright 2021 0xCB - Conor Burns
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "quantum.h"
void eeconfig_init_kb(void) {
#ifdef BACKLIGHT_ENABLE
backlight_enable();
backlight_level(5);
#endif
eeconfig_update_kb(0);
eeconfig_init_user();
}

View File

@ -9,6 +9,9 @@
"device_version": "0.0.1" "device_version": "0.0.1"
}, },
"backlight": { "backlight": {
"default": {
"brightness": 5
},
"pin": "B5", "pin": "B5",
"levels": 7, "levels": 7,
"breathing": true "breathing": true

View File

@ -35,9 +35,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, TO(2) _______, _______, TO(2)
), ),
[_RGB] = LAYOUT( [_RGB] = LAYOUT(
RGB_HUI, RGB_HUD, RGB_MOD, UG_HUEU, UG_HUED, UG_NEXT,
RGB_SAI, RGB_SAD, TO(1), UG_SATU, UG_SATD, TO(1),
RGB_SPI, RGB_SPD, TO(3) UG_SPDU, UG_SPDD, TO(3)
), ),
[_BLED] = LAYOUT( [_BLED] = LAYOUT(
BL_STEP, BL_BRTG, BL_TOGG, BL_STEP, BL_BRTG, BL_TOGG,

View File

@ -1,186 +0,0 @@
/*
Copyright 2021 0xCB - Conor Burns
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
// clang-format off
enum layer_names {
_HOME,
_MISC,
_RGB,
_BLED
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_HOME] = LAYOUT(
KC_MPRV, KC_MNXT, KC_MPLY,
KC_PGUP, KC_PGDN, TO(3),
KC_HOME, KC_END, TO(1)
),
[_MISC] = LAYOUT(
_______, _______, _______,
_______, _______, TO(0),
_______, _______, TO(2)
),
[_RGB] = LAYOUT(
RGB_HUI, RGB_HUD, RGB_MOD,
RGB_SAI, RGB_SAD, TO(1),
RGB_SPI, RGB_SPD, TO(3)
),
[_BLED] = LAYOUT(
BL_STEP, BL_BRTG, BL_TOGG,
BL_ON, BL_OFF, TO(2),
BL_UP, BL_DOWN, TO(0)
)
};
// clang-format on
/* rotary encoder (SW3) - add more else if blocks for more granular layer control */
#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
if (IS_LAYER_ON(_RGB)) {
#ifdef RGBLIGHT_ENABLE
if (clockwise) {
rgblight_increase_val();
} else {
rgblight_decrease_val();
}
#endif
} else if (IS_LAYER_ON(_BLED)) {
if (clockwise) {
backlight_increase();
} else {
backlight_decrease();
}
} else {
if (clockwise) {
tap_code(KC_VOLU);
} else {
tap_code(KC_VOLD);
}
}
return true;
}
#endif
/* oled stuff :) */
#ifdef OLED_ENABLE
uint16_t startup_timer;
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
startup_timer = timer_read();
return rotation;
}
static void render_logo(void) {
static const char PROGMEM raw_logo[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 64,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 1, 2, 4, 2, 1, 1, 1, 1, 1, 1,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 0, 0, 0, 0, 0, 0,128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5,248, 5, 2, 0, 0, 0, 0, 0, 0,128,192,192,224,224,112,120, 56, 63, 28, 14, 14, 14,254, 14, 14, 30, 28, 63, 56,120,112,224,224,192,128, 0, 0, 0, 0, 0, 0, 0, 2, 5,248, 5, 2, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,160, 19,162, 66, 66, 66, 66, 66, 66, 66,255,255,255, 0, 0, 0,252,254,254,192,192,192,192,255, 0, 0, 0, 62, 62, 60, 60, 0, 0, 1,255,255,255, 66, 66, 66, 66, 66, 66, 66,162, 19,160, 64, 0,
0, 0, 0,128, 64, 64, 64,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,192, 64, 64,192,128, 0, 0,192, 64, 64,192,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 64,192, 0, 0, 0, 0, 0,128,192, 64, 64,192,128, 0, 0,128,192, 64, 64,192,128, 0, 0, 64, 64, 64, 64, 64,192, 0, 0, 0, 0, 0,249, 8, 8, 8, 8, 8, 8, 8, 8,127,255,255,192,128,128, 15, 31, 31, 1, 1, 1, 1,255, 0, 0, 0, 30, 30, 14, 14,128,192,192,255,255,127, 8, 8, 8, 8, 8, 8, 8, 8,249, 0, 0, 0,
0, 0, 31, 49, 64, 78, 64, 49, 31, 0, 0, 97, 22, 8, 22, 97, 0, 0, 31, 49, 96, 64, 64, 96, 32, 0, 0,127, 68, 68,100, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 64,127, 64, 64, 0, 0, 0, 32,100, 68, 68,110, 59, 0, 0, 32,100, 68, 68,110, 59, 0, 0, 0, 0, 0,126, 3, 1, 0, 0, 0, 8, 20, 35, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 7, 7, 15,254, 30, 28, 28, 28,255, 28, 28, 28, 30,254, 15, 7, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 10, 17, 10, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 40, 68, 40, 16, 16, 16, 16, 16, 16, 31, 0, 0, 16, 40, 71, 40, 16, 0, 0, 31, 16, 16, 16, 16, 16, 16, 40, 68, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
oled_write_raw_P(raw_logo, sizeof(raw_logo));
}
static void render_logo_font(void) {
static const char PROGMEM qmk_logo[] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4,
0x88, 0x89, 0x8A, 0x8B, 0x8A, 0x8B, 0x8C, 0x8D, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
0xA8, 0xA9, 0xAA, 0xAB, 0xAA, 0xAB, 0xAC, 0xAD, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0x00
};
oled_write_P(qmk_logo, false);
}
/* Shows the name of the current layer and locks for the host (CAPS etc.) */
static void render_info(void) {
oled_write_P(PSTR("Layer: "), false);
switch (get_highest_layer(layer_state)) {
case _HOME:
oled_write_ln_P(PSTR("HOME"), false);
break;
case _MISC:
oled_write_ln_P(PSTR("MISC"), false);
break;
case _RGB:
oled_write_ln_P(PSTR("RGB"), false);
break;
case _BLED:
oled_write_ln_P(PSTR("Backlight"), false);
break;
default:
oled_write_ln_P(PSTR("Undefined"), false);
}
led_t led_state = host_keyboard_led_state();
oled_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false);
oled_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false);
oled_write_ln_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false);
}
static void render_rgbled_status(void) {
char string[4];
if (RGBLIGHT_MODES > 1 && rgblight_is_enabled() && get_highest_layer(layer_state) == _RGB) {
uint16_t m = rgblight_get_mode();
string[3] = '\0';
string[2] = '0' + m % 10;
string[1] = ( m /= 10) % 10 ? '0' + (m) % 10 : (m / 10) % 10 ? '0' : ' ';
string[0] = m / 10 ? '0' + m / 10 : ' ';
oled_write_P(PSTR("Conf:"), false);
oled_write(string, false);
uint16_t h = rgblight_get_hue()/RGBLIGHT_HUE_STEP;
string[3] = '\0';
string[2] = '0' + h % 10;
string[1] = ( h /= 10) % 10 ? '0' + (h) % 10 : (h / 10) % 10 ? '0' : ' ';
string[0] = h / 10 ? '0' + h / 10 : ' ';
oled_write_P(PSTR(","), false);
oled_write(string, false);
uint16_t s = rgblight_get_sat()/RGBLIGHT_SAT_STEP;
string[3] = '\0';
string[2] = '0' + s % 10;
string[1] = ( s /= 10) % 10 ? '0' + (s) % 10 : (s / 10) % 10 ? '0' : ' ';
string[0] = s / 10 ? '0' + s / 10 : ' ';
oled_write_P(PSTR(","), false);
oled_write(string, false);
uint16_t v = rgblight_get_val()/RGBLIGHT_VAL_STEP;
string[3] = '\0';
string[2] = '0' + v % 10;
string[1] = ( v /= 10) % 10 ? '0' + (v) % 10 : (v / 10) % 10 ? '0' : ' ';
string[0] = v / 10 ? '0' + v / 10 : ' ';
oled_write_P(PSTR(","), false);
oled_write(string, false);
oled_write_ln_P(PSTR("\n MOD HUE SAT VAR"), false);
} else {
oled_write_ln_P(PSTR("\n"), false);
}
}
bool oled_task_user(void) {
static bool finished_timer = false;
if (!finished_timer && (timer_elapsed(startup_timer) < 1000)) {
render_logo();
} else {
if (!finished_timer) {
oled_clear();
finished_timer = true;
}
render_info();
render_rgbled_status();
render_logo_font();
}
return false;
}
#endif

View File

@ -1 +0,0 @@
VIA_ENABLE = yes

Some files were not shown because too many files have changed in this diff Show More