Merge upstream

This commit is contained in:
elpekenin 2024-03-10 11:18:36 +01:00
commit 04cad9732c
1634 changed files with 32864 additions and 68913 deletions

View File

@ -4,39 +4,39 @@
root = true root = true
[*] [*]
end_of_line = lf
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
# We recommend you to keep these unchanged
charset = utf-8 charset = utf-8
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[{*.yaml,*.yml}] # To match GitHub Actions formatting
indent_size = 2
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
indent_size = 4
[{qmk,*.py}] [{Makefile,*.mk}]
charset = utf-8
max_line_length = 200
# Make these match what we have in .gitattributes
[*.mk]
end_of_line = lf
indent_style = tab indent_style = tab
[Makefile] # Don't override anything in `lib/`...
end_of_line = lf
indent_style = tab
[*.sh]
end_of_line = lf
# The gitattributes file will handle the line endings conversion properly according to the operating system settings for other files
# We don't have gitattributes properly for these
# So if the user have for example core.autocrlf set to true
# the line endings would be wrong.
[lib/**] [lib/**]
indent_style = unset
indent_size = unset
tab_width = unset
end_of_line = unset end_of_line = unset
charset = unset
spelling_language = unset
trim_trailing_whitespace = unset
insert_final_newline = unset
# ...except QMK's `lib/python`.
[{*.py,lib/python/**.py}]
end_of_line = lf
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 200

View File

@ -36,6 +36,8 @@ jobs:
- name: Get changed files - name: Get changed files
id: file_changes id: file_changes
uses: tj-actions/changed-files@v42 uses: tj-actions/changed-files@v42
with:
use_rest_api: true
- name: Run qmk formatters - name: Run qmk formatters
shell: 'bash {0}' shell: 'bash {0}'

View File

@ -47,7 +47,7 @@ jobs:
git config user.email 'hello@qmk.fm' git config user.email 'hello@qmk.fm'
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v5 uses: peter-evans/create-pull-request@v6
if: ${{ github.repository == 'qmk/qmk_firmware'}} if: ${{ github.repository == 'qmk/qmk_firmware'}}
with: with:
token: ${{ secrets.QMK_BOT_TOKEN }} token: ${{ secrets.QMK_BOT_TOKEN }}

View File

@ -28,6 +28,8 @@ jobs:
- name: Get changed files - name: Get changed files
id: file_changes id: file_changes
uses: tj-actions/changed-files@v42 uses: tj-actions/changed-files@v42
with:
use_rest_api: true
- name: Print info - name: Print info
run: | run: |
@ -62,10 +64,12 @@ jobs:
qmk format-text ${{ steps.file_changes.outputs.all_changed_files}} || true qmk format-text ${{ steps.file_changes.outputs.all_changed_files}} || true
for file in ${{ steps.file_changes.outputs.all_changed_files}}; do for file in ${{ steps.file_changes.outputs.all_changed_files}}; do
if ! git diff --quiet $file; then if [[ -f $file ]]; then
echo "File '${file}' Requires Formatting" if ! git diff --quiet $file; then
echo "::error file=${file}::Requires Formatting" echo "File '${file}' Requires Formatting"
exit_code=$(($exit_code + 1)) echo "::error file=${file}::Requires Formatting"
exit_code=$(($exit_code + 1))
fi
fi fi
done done

View File

@ -34,7 +34,7 @@ jobs:
git config user.email 'hello@qmk.fm' git config user.email 'hello@qmk.fm'
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v5 uses: peter-evans/create-pull-request@v6
if: ${{ github.repository == 'qmk/qmk_firmware'}} if: ${{ github.repository == 'qmk/qmk_firmware'}}
with: with:
token: ${{ secrets.QMK_BOT_TOKEN }} token: ${{ secrets.QMK_BOT_TOKEN }}

View File

@ -32,4 +32,4 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: pip3 install -r requirements-dev.txt run: pip3 install -r requirements-dev.txt
- name: Run tests - name: Run tests
run: make test:all run: qmk test-c

1
.gitignore vendored
View File

@ -37,6 +37,7 @@ quantum/version.h
# DD config at wrong location # DD config at wrong location
/keyboards/**/keymaps/*/info.json /keyboards/**/keymaps/*/info.json
/keyboards/**/keymaps/*/keyboard.json
# Old-style QMK Makefiles # Old-style QMK Makefiles
/keyboards/**/Makefile /keyboards/**/Makefile

View File

@ -119,7 +119,7 @@ MAIN_KEYMAP_PATH_3 := $(KEYBOARD_PATH_3)/keymaps/$(KEYMAP)
MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP) MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP)
MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP) MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
# Pull in rules from info.json # Pull in rules from DD keyboard config
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_rules.mk) INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_rules.mk)
include $(INFO_RULES_MK) include $(INFO_RULES_MK)
@ -221,7 +221,7 @@ include $(BUILDDEFS_PATH)/converters.mk
MCU_ORIG := $(MCU) MCU_ORIG := $(MCU)
include $(wildcard $(PLATFORM_PATH)/*/mcu_selection.mk) include $(wildcard $(PLATFORM_PATH)/*/mcu_selection.mk)
# PLATFORM_KEY should be detected in info.json via key 'processor' (or rules.mk 'MCU') # PLATFORM_KEY should be detected in DD keyboard config via key 'processor' (or rules.mk 'MCU')
ifeq ($(PLATFORM_KEY),) ifeq ($(PLATFORM_KEY),)
$(call CATASTROPHIC_ERROR,Platform not defined) $(call CATASTROPHIC_ERROR,Platform not defined)
endif endif
@ -335,38 +335,54 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","")
POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h
endif endif
# Pull in stuff from info.json # Create dependencies on DD keyboard config - structure validated elsewhere
INFO_JSON_FILES := DD_CONFIG_FILES :=
ifneq ("$(wildcard $(KEYBOARD_PATH_1)/info.json)","") ifneq ("$(wildcard $(KEYBOARD_PATH_1)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_1)/info.json DD_CONFIG_FILES += $(KEYBOARD_PATH_1)/info.json
endif endif
ifneq ("$(wildcard $(KEYBOARD_PATH_2)/info.json)","") ifneq ("$(wildcard $(KEYBOARD_PATH_2)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_2)/info.json DD_CONFIG_FILES += $(KEYBOARD_PATH_2)/info.json
endif endif
ifneq ("$(wildcard $(KEYBOARD_PATH_3)/info.json)","") ifneq ("$(wildcard $(KEYBOARD_PATH_3)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_3)/info.json DD_CONFIG_FILES += $(KEYBOARD_PATH_3)/info.json
endif endif
ifneq ("$(wildcard $(KEYBOARD_PATH_4)/info.json)","") ifneq ("$(wildcard $(KEYBOARD_PATH_4)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_4)/info.json DD_CONFIG_FILES += $(KEYBOARD_PATH_4)/info.json
endif endif
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","") ifneq ("$(wildcard $(KEYBOARD_PATH_5)/info.json)","")
INFO_JSON_FILES += $(KEYBOARD_PATH_5)/info.json DD_CONFIG_FILES += $(KEYBOARD_PATH_5)/info.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_1)/keyboard.json)","")
DD_CONFIG_FILES += $(KEYBOARD_PATH_1)/keyboard.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_2)/keyboard.json)","")
DD_CONFIG_FILES += $(KEYBOARD_PATH_2)/keyboard.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_3)/keyboard.json)","")
DD_CONFIG_FILES += $(KEYBOARD_PATH_3)/keyboard.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_4)/keyboard.json)","")
DD_CONFIG_FILES += $(KEYBOARD_PATH_4)/keyboard.json
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/keyboard.json)","")
DD_CONFIG_FILES += $(KEYBOARD_PATH_5)/keyboard.json
endif endif
CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c
$(INTERMEDIATE_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES) $(INTERMEDIATE_OUTPUT)/src/info_config.h: $(DD_CONFIG_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_config.h) $(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/info_config.h)
@$(BUILD_CMD) @$(BUILD_CMD)
$(INTERMEDIATE_OUTPUT)/src/default_keyboard.c: $(INFO_JSON_FILES) $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c: $(DD_CONFIG_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-keyboard-c --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c) $(eval CMD=$(QMK_BIN) generate-keyboard-c --quiet --keyboard $(KEYBOARD) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c)
@$(BUILD_CMD) @$(BUILD_CMD)
$(INTERMEDIATE_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES) $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h: $(DD_CONFIG_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --include $(FOUND_KEYBOARD_H) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h) $(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --include $(FOUND_KEYBOARD_H) --output $(INTERMEDIATE_OUTPUT)/src/default_keyboard.h)
@$(BUILD_CMD) @$(BUILD_CMD)

View File

@ -886,9 +886,24 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
endif endif
endif endif
ENCODER_ENABLE ?= no
ENCODER_DRIVER ?= quadrature
VALID_ENCODER_DRIVER_TYPES := quadrature custom
ifeq ($(strip $(ENCODER_ENABLE)), yes) ifeq ($(strip $(ENCODER_ENABLE)), yes)
ifeq ($(filter $(ENCODER_DRIVER),$(VALID_ENCODER_DRIVER_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid ENCODER_DRIVER,ENCODER_DRIVER="$(ENCODER_DRIVER)" is not a valid encoder driver)
endif
SRC += $(QUANTUM_DIR)/encoder.c SRC += $(QUANTUM_DIR)/encoder.c
OPT_DEFS += -DENCODER_ENABLE OPT_DEFS += -DENCODER_ENABLE
OPT_DEFS += -DENCODER_DRIVER_$(strip $(shell echo $(ENCODER_DRIVER) | tr '[:lower:]' '[:upper:]'))
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/encoder
COMMON_VPATH += $(DRIVER_PATH)/encoder
ifneq ($(strip $(ENCODER_DRIVER)), custom)
SRC += encoder_$(strip $(ENCODER_DRIVER)).c
endif
ifeq ($(strip $(ENCODER_MAP_ENABLE)), yes) ifeq ($(strip $(ENCODER_MAP_ENABLE)), yes)
OPT_DEFS += -DENCODER_MAP_ENABLE OPT_DEFS += -DENCODER_MAP_ENABLE
endif endif
@ -945,6 +960,15 @@ ifeq ($(strip $(SPI_DRIVER_REQUIRED)), yes)
endif endif
ifeq ($(strip $(UART_DRIVER_REQUIRED)), yes) ifeq ($(strip $(UART_DRIVER_REQUIRED)), yes)
OPT_DEFS += -DHAL_USE_SERIAL=TRUE ifeq ($(strip $(PLATFORM)), CHIBIOS)
QUANTUM_LIB_SRC += uart.c ifneq ($(filter $(MCU_SERIES),RP2040),)
OPT_DEFS += -DHAL_USE_SIO=TRUE
QUANTUM_LIB_SRC += uart_sio.c
else
OPT_DEFS += -DHAL_USE_SERIAL=TRUE
QUANTUM_LIB_SRC += uart_serial.c
endif
else
QUANTUM_LIB_SRC += uart.c
endif
endif endif

View File

@ -19,6 +19,8 @@
// Audio // Audio
"AUDIO_DEFAULT_ON": {"info_key": "audio.default.on", "value_type": "bool"}, "AUDIO_DEFAULT_ON": {"info_key": "audio.default.on", "value_type": "bool"},
"AUDIO_DEFAULT_CLICKY_ON": {"info_key": "audio.default.clicky", "value_type": "bool"}, "AUDIO_DEFAULT_CLICKY_ON": {"info_key": "audio.default.clicky", "value_type": "bool"},
"AUDIO_POWER_CONTROL_PIN": {"info_key": "audio.power_control.pin"},
"AUDIO_POWER_CONTROL_PIN_ON_STATE": {"info_key": "audio.power_control.on_state", "value_type": "int" },
"AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "flag"}, "AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "flag"},
"SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "flag"}, "SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "flag"},
@ -36,10 +38,10 @@
"BACKLIGHT_DEFAULT_LEVEL": {"info_key": "backlight.default.brightness", "value_type": "int"}, "BACKLIGHT_DEFAULT_LEVEL": {"info_key": "backlight.default.brightness", "value_type": "int"},
// Bootmagic // Bootmagic
"BOOTMAGIC_LITE_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"}, "BOOTMAGIC_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"},
"BOOTMAGIC_LITE_COLUMN_RIGHT": {"info_key": "split.bootmagic.matrix.1", "value_type": "int"}, "BOOTMAGIC_COLUMN_RIGHT": {"info_key": "split.bootmagic.matrix.1", "value_type": "int"},
"BOOTMAGIC_LITE_ROW": {"info_key": "bootmagic.matrix.0", "value_type": "int"}, "BOOTMAGIC_ROW": {"info_key": "bootmagic.matrix.0", "value_type": "int"},
"BOOTMAGIC_LITE_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"}, "BOOTMAGIC_ROW_RIGHT": {"info_key": "split.bootmagic.matrix.0", "value_type": "int"},
// Caps Word // Caps Word
"BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "flag"}, "BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "flag"},

View File

@ -21,6 +21,7 @@
"DEBOUNCE_TYPE": {"info_key": "build.debounce_type"}, "DEBOUNCE_TYPE": {"info_key": "build.debounce_type"},
"EEPROM_DRIVER": {"info_key": "eeprom.driver"}, "EEPROM_DRIVER": {"info_key": "eeprom.driver"},
"ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"}, "ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"},
"ENCODER_DRIVER": {"info_key": "encoder.driver"},
"FIRMWARE_FORMAT": {"info_key": "build.firmware_format"}, "FIRMWARE_FORMAT": {"info_key": "build.firmware_format"},
"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"},

View File

@ -185,6 +185,9 @@
"eek": { "eek": {
"target": "eek/silk_down" "target": "eek/silk_down"
}, },
"epoch80": {
"target": "kbdfans/epoch80"
},
"era/klein": { "era/klein": {
"target": "era/sirind/klein_sd" "target": "era/sirind/klein_sd"
}, },
@ -311,6 +314,9 @@
"jj50": { "jj50": {
"target": "kprepublic/jj50" "target": "kprepublic/jj50"
}, },
"jm60": {
"target": "kbdfans/jm60"
},
"jones": { "jones": {
"target": "jones/v03_1" "target": "jones/v03_1"
}, },

View File

@ -6,6 +6,10 @@
"encoder_config": { "encoder_config": {
"type": "object", "type": "object",
"properties": { "properties": {
"driver": {
"type": "string",
"enum": ["custom", "quadrature"]
},
"rotary": { "rotary": {
"type": "array", "type": "array",
"items": { "items": {
@ -24,14 +28,12 @@
"dip_switch_config": { "dip_switch_config": {
"type": "object", "type": "object",
"properties": { "properties": {
"pins": { "pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
"$ref": "qmk.definitions.v1#/mcu_pin_array"
}
} }
}, }
}, },
"type": "object", "type": "object",
"not": { "required": [ "vendorId", "productId" ] }, // reject via keys... "not": {"required": ["vendorId", "productId"]}, // reject via keys...
"properties": { "properties": {
"keyboard_name": {"$ref": "qmk.definitions.v1#/text_identifier"}, "keyboard_name": {"$ref": "qmk.definitions.v1#/text_identifier"},
"keyboard_folder": {"$ref": "qmk.definitions.v1#/keyboard"}, "keyboard_folder": {"$ref": "qmk.definitions.v1#/keyboard"},
@ -133,6 +135,14 @@
}, },
"macro_beep": {"type": "boolean"}, "macro_beep": {"type": "boolean"},
"pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}, "pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"power_control": {
"type": "object",
"additionalProperties": false,
"properties": {
"on_state": {"$ref": "qmk.definitions.v1#/bit"},
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
}
},
"voices": {"type": "boolean"} "voices": {"type": "boolean"}
} }
}, },
@ -142,7 +152,7 @@
"properties": { "properties": {
"driver": { "driver": {
"type": "string", "type": "string",
"enum": ["pwm", "software", "timer", "custom"] "enum": ["custom", "pwm", "software", "timer"]
}, },
"default": { "default": {
"type": "object", "type": "object",
@ -314,8 +324,8 @@
}, },
"features": { "features": {
"$ref": "qmk.definitions.v1#/boolean_array", "$ref": "qmk.definitions.v1#/boolean_array",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" }, "propertyNames": {"$ref": "qmk.definitions.v1#/snake_case"},
"not": { "required": [ "lto" ] } "not": {"required": ["lto"]}
}, },
"indicators": { "indicators": {
"type": "object", "type": "object",
@ -340,15 +350,9 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"filename": { "filename": {"type": "string"},
"type": "string" "c_macro": {"type": "boolean"},
}, "json_layout": {"type": "boolean"},
"c_macro": {
"type": "boolean"
},
"json_layout": {
"type": "boolean"
},
"layout": { "layout": {
"type": "array", "type": "array",
"items": { "items": {
@ -431,10 +435,8 @@
"properties": { "properties": {
"animations": { "animations": {
"type": "object", "type": "object",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" } "propertyNames": {"$ref": "qmk.definitions.v1#/snake_case"},
"additionalProperties": { "additionalProperties": {"type": "boolean"}
"type": "boolean"
}
}, },
"default": { "default": {
"type": "object", "type": "object",
@ -446,7 +448,24 @@
"speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"} "speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
} }
}, },
"driver": {"type": "string"}, "driver": {
"type": "string",
"enum": [
"custom",
"is31fl3218",
"is31fl3729",
"is31fl3731",
"is31fl3733",
"is31fl3736",
"is31fl3737",
"is31fl3741",
"is31fl3742a",
"is31fl3743a",
"is31fl3745",
"is31fl3746a",
"snled27351"
]
},
"center_point": { "center_point": {
"type": "array", "type": "array",
"minItems": 2, "minItems": 2,
@ -495,10 +514,8 @@
"properties": { "properties": {
"animations": { "animations": {
"type": "object", "type": "object",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" } "propertyNames": {"$ref": "qmk.definitions.v1#/snake_case"},
"additionalProperties": { "additionalProperties": {"type": "boolean"}
"type": "boolean"
}
}, },
"default": { "default": {
"type": "object", "type": "object",
@ -512,7 +529,26 @@
"speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"} "speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
} }
}, },
"driver": {"type": "string"}, "driver": {
"type": "string",
"enum": [
"aw20216s",
"custom",
"is31fl3218",
"is31fl3729",
"is31fl3731",
"is31fl3733",
"is31fl3736",
"is31fl3737",
"is31fl3741",
"is31fl3742a",
"is31fl3743a",
"is31fl3745",
"is31fl3746a",
"snled27351",
"ws2812"
]
},
"center_point": { "center_point": {
"type": "array", "type": "array",
"minItems": 2, "minItems": 2,
@ -564,10 +600,8 @@
"properties": { "properties": {
"animations": { "animations": {
"type": "object", "type": "object",
"propertyNames": { "$ref": "qmk.definitions.v1#/snake_case" } "propertyNames": {"$ref": "qmk.definitions.v1#/snake_case"},
"additionalProperties": { "additionalProperties": {"type": "boolean"}
"type": "boolean"
}
}, },
"brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"default": { "default": {
@ -770,7 +804,7 @@
"st7565": {"type": "boolean"}, "st7565": {"type": "boolean"},
"wpm": {"type": "boolean"} "wpm": {"type": "boolean"}
} }
} },
"watchdog": {"type": "boolean"}, "watchdog": {"type": "boolean"},
"watchdog_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}, "watchdog_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"sync_matrix_state": { "sync_matrix_state": {

View File

@ -1,20 +0,0 @@
// Copyright %YEAR% %REAL_NAME% (@%USER_NAME%)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT

367
docs/ChangeLog/20240225.md Normal file
View File

@ -0,0 +1,367 @@
# QMK Breaking Changes - 2024 February 25 Changelog
## Notable Features :id=notable-features
_0.24.0_ is mainly a maintenance release of QMK Firmware -- as per last few breaking changes cycles, there have been a lot of behind-the-scenes changes, mainly:
* continued purge of user keymaps
* migration of RGB matrix configuration into `info.json` files
* standardisation of `LAYOUT` naming
* keyboard relocations
* addressing technical debt
## Changes Requiring User Action :id=changes-requiring-user-action
### Windows Driver Changes ([QMK Toolbox 0.3.0 Release](https://github.com/qmk/qmk_toolbox/releases/tag/0.3.0))
Flashing keyboards that target `atmel-dfu` or `qmk-dfu` on Windows using `qmk flash` or QMK Toolbox have traditionally used _libusb_ for access to the DFU USB device. Since QMK Toolbox 0.3.0, this has changed to WinUSB.
If you update QMK Toolbox or update QMK MSYS, you may find that flashing Atmel DFU keyboards no longer functions as intended. If you strike such issues when flashing new firmware, you will need to replace the _libusb_ driver with _WinUSB_ using Zadig. You can follow the [Recovering from Installation to Wrong Device](driver_installation_zadig.md#recovering-from-installation-to-wrong-device) instructions to replace the driver associated with the Atmel DFU bootloader, skipping the section about removal as Zadig will safely replace the driver instead. Please ensure your keyboard is in bootloader mode and has _libusb_ as the existing driver before attempting to use Zadig to replace the driver. If instead you see _HidUsb_ you're not in bootloader mode and should not continue with driver replacement.
### Updated Keyboard Codebases :id=updated-keyboard-codebases
One note with updated keyboard names -- historical keyboard names are still considered valid when using [External Userspace](newbs_external_userspace.md) 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 |
|-------------------------|---------------------------------|
| enter67 | kezewa/enter67 |
| enter80 | kezewa/enter80 |
| epoch80 | kbdfans/epoch80 |
| eu_isolation | p3d/eu_isolation |
| flygone60/rev3 | shandoncodes/flygone60/rev3 |
| hub16 | joshajohnson/hub16 |
| hub20 | joshajohnson/hub20 |
| jm60 | kbdfans/jm60 |
| kira75 | kira/kira75 |
| kira80 | kira/kira80 |
| kmac | kbdmania/kmac |
| kmac_pad | kbdmania/kmac_pad |
| kudox/columner | kumaokobo/kudox/columner |
| kudox/rev1 | kumaokobo/kudox/rev1 |
| kudox/rev2 | kumaokobo/kudox/rev2 |
| kudox/rev3 | kumaokobo/kudox/rev3 |
| kudox_full/rev1 | kumaokobo/kudox_full/rev1 |
| kudox_game | kumaokobo/kudox_game |
| kudox_game/rev1 | kumaokobo/kudox_game/rev1 |
| kudox_game/rev2 | kumaokobo/kudox_game/rev2 |
| laser_ninja/pumpkin_pad | laser_ninja/pumpkinpad |
| late9/rev1 | rookiebwoy/late9/rev1 |
| lefty | smoll/lefty |
| lefty/rev1 | smoll/lefty/rev1 |
| lefty/rev2 | smoll/lefty/rev2 |
| lpad | laneware/lpad |
| lw67 | laneware/lw67 |
| lw75 | laneware/lw75 |
| macro1 | laneware/macro1 |
| macro3 | handwired/macro3 |
| miniaxe | kagizaraya/miniaxe |
| mino/hotswap | shandoncodes/mino/hotswap |
| mino_plus/hotswap | shandoncodes/mino_plus/hotswap |
| mino_plus/soldered | shandoncodes/mino_plus/soldered |
| mnk1800s | monokei/mnk1800s |
| mnk50 | monokei/mnk50 |
| mnk75 | monokei/mnk75 |
| moonlander | zsa/moonlander |
| neopad/rev1 | rookiebwoy/neopad/rev1 |
| pico/65keys | kumaokobo/pico/65keys |
| pico/70keys | kumaokobo/pico/70keys |
| pw88 | smoll/pw88 |
| q4z | p3d/q4z |
| raindrop | laneware/raindrop |
| redox_w | redox/wireless |
| riot_pad | shandoncodes/riot_pad |
| spacey | p3d/spacey |
| synapse | p3d/synapse |
| tw40 | p3d/tw40 |
| w1_at | geonworks/w1_at |
| z12 | zigotica/z12 |
| z34 | zigotica/z34 |
## Notable core changes :id=notable-core
### Renaming Arduino-style GPIO pin functions ([#23085](https://github.com/qmk/qmk_firmware/pull/23085), [#23093](https://github.com/qmk/qmk_firmware/pull/23093)) :id=gpio-rename
QMK has long used Arduino-style GPIO naming conventions. This has been confusing for users, as over time they've had new variations added, as well as users mistakenly thinking that QMK supports the rest of the Arduino ecosystem.
The decision was made to rename the GPIO manipulation functions with ones matching QMK Firmware's code styling.
| Old | New |
|------------------------------|---------------------------------------|
| `setPinInput(pin)` | `gpio_set_pin_input(pin)` |
| `setPinInputHigh(pin)` | `gpio_set_pin_input_high(pin)` |
| `setPinInputLow(pin)` | `gpio_set_pin_input_low(pin)` |
| `setPinOutput(pin)` | `gpio_set_pin_output(pin)` |
| `setPinOutputPushPull(pin)` | `gpio_set_pin_output_push_pull(pin)` |
| `setPinOutputOpenDrain(pin)` | `gpio_set_pin_output_open_drain(pin)` |
| `writePinHigh(pin)` | `gpio_write_pin_high(pin)` |
| `writePinLow(pin)` | `gpio_write_pin_low(pin)` |
| `writePin(pin, level)` | `gpio_write_pin(pin, level)` |
| `readPin(pin)` | `gpio_read_pin(pin)` |
| `togglePin(pin)` | `gpio_toggle_pin(pin)` |
### I2C driver API Changes ([#22905](https://github.com/qmk/qmk_firmware/pull/22905))
Much like the GPIO refactoring, I2C APIs were also updated to conform to QMK naming standards. This is largely irrelevant to people using subsystem abstractions such as touchpads or RGB lighting, and only affects people manually communicating with other peripherals.
| Old API | New API |
|--------------------|--------------------------|
| `i2c_readReg()` | `i2c_read_register()` |
| `i2c_readReg16()` | `i2c_read_register16()` |
| `i2c_writeReg()` | `i2c_write_register()` |
| `i2c_writeReg16()` | `i2c_write_register16()` |
### Renaming _Bootmagic Lite_ => _Bootmagic_ ([#22970](https://github.com/qmk/qmk_firmware/pull/22970), [#22979](https://github.com/qmk/qmk_firmware/pull/22979)) :id=bootmagic-rename
Bootmagic "Lite" had no real meaning once the historical Bootmagic "Full" was deprecated and removed. Any references to _Bootmagic Lite_ should now just refer to _Bootmagic_. We hope we got the majority of the code and the documentation, so if you find any more, let us know!
### Threshold for automatic mouse layer activation ([#21398](https://github.com/qmk/qmk_firmware/pull/21398)) :id=auto-mouse-layer
In some cases, accidental automatic activation of the mouse layer made it difficult to continue typing, such as when brushing across a trackball. `AUTO_MOUSE_THRESHOLD` is now a configurable option in `config.h` which allows for specifying what the movement threshold is before automatically activating the mouse layer.
### DIP Switch Mapping ([#22543](https://github.com/qmk/qmk_firmware/pull/22543)) :id=dip-switch-map
Much like Encoder Mapping, DIP Switch Mapping allows for specifying a table of actions to execute when a DIP switch state changes. See the [DIP Switch Documentation](feature_dip_switch.md#dip-switch-map) for more information.
```c
#if defined(DIP_SWITCH_MAP_ENABLE)
const uint16_t PROGMEM dip_switch_map[NUM_DIP_SWITCHES][NUM_DIP_STATES] = {
DIP_SWITCH_OFF_ON(DF(0), DF(1)),
DIP_SWITCH_OFF_ON(EC_NORM, EC_SWAP)
};
#endif
```
### Quantum Painter updates ([#18521](https://github.com/qmk/qmk_firmware/pull/18521), [#20645](https://github.com/qmk/qmk_firmware/pull/20645), [#22358](https://github.com/qmk/qmk_firmware/pull/22358)) :id=qp-updates
Quantum Painter picked up support for the following:
* ILI9486 displays
* SSD1306 displays, including smaller OLEDs
* Native panel pixel format support for fonts
Quantum Painter now supports the majority of common OLED panels supported by the basic OLED driver, so if you're using an ARM-based board you may find Quantum Painter a much more feature-rich API in comparison.
## Full changelist :id=full-changelist
Core:
* [Driver] ILI9486 on Quantum Painter ([#18521](https://github.com/qmk/qmk_firmware/pull/18521))
* Insert delay between shifted chars in send_string_with_delay ([#19280](https://github.com/qmk/qmk_firmware/pull/19280))
* [QP] Native palette support for fonts ([#20645](https://github.com/qmk/qmk_firmware/pull/20645))
* I2C driver cleanup ([#21273](https://github.com/qmk/qmk_firmware/pull/21273))
* Add option for auto mouse movement threshold ([#21398](https://github.com/qmk/qmk_firmware/pull/21398))
* Add Canadian French input locale ([#21456](https://github.com/qmk/qmk_firmware/pull/21456))
* Add encoder abstraction. ([#21548](https://github.com/qmk/qmk_firmware/pull/21548))
* Converted RGB matrix to use last_input_activity_elapsed(). ([#21687](https://github.com/qmk/qmk_firmware/pull/21687))
* Ignore space cadet key release when caps word is active ([#21721](https://github.com/qmk/qmk_firmware/pull/21721))
* Add OS detection callbacks ([#21777](https://github.com/qmk/qmk_firmware/pull/21777))
* joystick weights ([#21883](https://github.com/qmk/qmk_firmware/pull/21883))
* Add RGB matrix & LED Matrix support for IS31FL3729 ([#21944](https://github.com/qmk/qmk_firmware/pull/21944))
* dac_additive: Decouple the buffer length from the waveform length ([#22276](https://github.com/qmk/qmk_firmware/pull/22276))
* Add missing rgb matrix default parameters ([#22281](https://github.com/qmk/qmk_firmware/pull/22281))
* Remove console out endpoint ([#22304](https://github.com/qmk/qmk_firmware/pull/22304))
* Add ADC support STM32L4xx and STM32G4xx series MCUs ([#22341](https://github.com/qmk/qmk_firmware/pull/22341))
* Add QP support for smaller OLED displays and SSD1306 ([#22358](https://github.com/qmk/qmk_firmware/pull/22358))
* Add Imera converter ([#22419](https://github.com/qmk/qmk_firmware/pull/22419))
* LED drivers: refactor page selection ([#22518](https://github.com/qmk/qmk_firmware/pull/22518))
* Rework RGBLight driver system ([#22529](https://github.com/qmk/qmk_firmware/pull/22529))
* Add `APA102_LED_COUNT` define ([#22530](https://github.com/qmk/qmk_firmware/pull/22530))
* Add latam spanish headers ([#22542](https://github.com/qmk/qmk_firmware/pull/22542))
* Keymap introspection for Dip Switches ([#22543](https://github.com/qmk/qmk_firmware/pull/22543))
* Add basic presence check for cirque trackpad. ([#22546](https://github.com/qmk/qmk_firmware/pull/22546))
* Rename `RGBLED_NUM` -> `RGBLIGHT_LED_COUNT` ([#22570](https://github.com/qmk/qmk_firmware/pull/22570))
* LED drivers: change "TWI" to "I2C" ([#22617](https://github.com/qmk/qmk_firmware/pull/22617))
* LED drivers: extract IS31FL3742A from IS31COMMON ([#22620](https://github.com/qmk/qmk_firmware/pull/22620))
* Align Dip Switch feature ([#22625](https://github.com/qmk/qmk_firmware/pull/22625))
* LED/RGB Matrix: add header for drivers ([#22628](https://github.com/qmk/qmk_firmware/pull/22628))
* LED drivers: extract IS31FL3743A from IS31COMMON ([#22635](https://github.com/qmk/qmk_firmware/pull/22635))
* LED drivers: extract IS31FL3745 from IS31COMMON ([#22636](https://github.com/qmk/qmk_firmware/pull/22636))
* LED drivers: extract IS31FL3746A from IS31COMMON ([#22637](https://github.com/qmk/qmk_firmware/pull/22637))
* Update keyboard LED driver configs ([#22638](https://github.com/qmk/qmk_firmware/pull/22638))
* Solid reactive: improve fading effect ([#22656](https://github.com/qmk/qmk_firmware/pull/22656))
* Remove redundant RGB/LED matrix eeconfig init ([#22673](https://github.com/qmk/qmk_firmware/pull/22673))
* Remove redundant rgblight eeconfig init ([#22674](https://github.com/qmk/qmk_firmware/pull/22674))
* Remove redundant steno eeconfig init ([#22680](https://github.com/qmk/qmk_firmware/pull/22680))
* Rename `LED_DISABLE_WHEN_USB_SUSPENDED` -> `LED_MATRIX_SLEEP` ([#22681](https://github.com/qmk/qmk_firmware/pull/22681))
* Rename `RGB_DISABLE_WHEN_USB_SUSPENDED` -> `RGB_MATRIX_SLEEP` ([#22682](https://github.com/qmk/qmk_firmware/pull/22682))
* Align VUSB suspend protocol logic ([#22688](https://github.com/qmk/qmk_firmware/pull/22688))
* [Audio] Enable Complementary output for PWM Hardware driver ([#22726](https://github.com/qmk/qmk_firmware/pull/22726))
* Remove redundant audio eeconfig init ([#22736](https://github.com/qmk/qmk_firmware/pull/22736))
* Align location of tap dance keycode ([#22742](https://github.com/qmk/qmk_firmware/pull/22742))
* Align `SPLIT_HAND_MATRIX_GRID` left/right logic with `SPLIT_HAND_PIN` ([#22775](https://github.com/qmk/qmk_firmware/pull/22775))
* [CI] Regenerate Files ([#22795](https://github.com/qmk/qmk_firmware/pull/22795))
* Remove IS31FLCOMMON code ([#22800](https://github.com/qmk/qmk_firmware/pull/22800))
* Cirque reachable calibration aide ([#22803](https://github.com/qmk/qmk_firmware/pull/22803))
* LED drivers: rename "simple" to "mono" ([#22814](https://github.com/qmk/qmk_firmware/pull/22814))
* is31fl3733: change `write_register()` return type to `void` ([#22824](https://github.com/qmk/qmk_firmware/pull/22824))
* snled27351: change `write_register()` return type to `void` ([#22825](https://github.com/qmk/qmk_firmware/pull/22825))
* apa102: cleanups ([#22826](https://github.com/qmk/qmk_firmware/pull/22826))
* Remove PWM advanced check for WS2812 driver ([#22830](https://github.com/qmk/qmk_firmware/pull/22830))
* Allow ChibiOS `SIO` driver for `UART` driver ([#22839](https://github.com/qmk/qmk_firmware/pull/22839))
* LED drivers: more formatting ([#22865](https://github.com/qmk/qmk_firmware/pull/22865))
* LED drivers: change `write_pwm_buffer()` return type to `void` ([#22869](https://github.com/qmk/qmk_firmware/pull/22869))
* [CI] Regenerate Files ([#22872](https://github.com/qmk/qmk_firmware/pull/22872))
* LED drivers: switch to i2c_writeReg() ([#22878](https://github.com/qmk/qmk_firmware/pull/22878))
* LED drivers: remove `write_pwm_buffer()` from public API ([#22884](https://github.com/qmk/qmk_firmware/pull/22884))
* i2c: rename read/write register functions ([#22905](https://github.com/qmk/qmk_firmware/pull/22905))
* LED drivers: update I2C API usage ([#22951](https://github.com/qmk/qmk_firmware/pull/22951))
* LED drivers: create structs to hold PWM/scaling buffers ([#22955](https://github.com/qmk/qmk_firmware/pull/22955))
* Migrate and remove deprecated debug utils ([#22961](https://github.com/qmk/qmk_firmware/pull/22961))
* Remove call to removed i2c function in azoteq driver ([#22966](https://github.com/qmk/qmk_firmware/pull/22966))
* Tidy up print/debug logging headers ([#22969](https://github.com/qmk/qmk_firmware/pull/22969))
* Begin removal of bootmagic lite terminology ([#22970](https://github.com/qmk/qmk_firmware/pull/22970))
* LED drivers: place I2C addresses into an array ([#22975](https://github.com/qmk/qmk_firmware/pull/22975))
* Removal of bootmagic lite terminology ([#22979](https://github.com/qmk/qmk_firmware/pull/22979))
* Init pins for Analog Joystick sensor ([#22985](https://github.com/qmk/qmk_firmware/pull/22985))
* Workaround for G431 eeprom emulation ([#23002](https://github.com/qmk/qmk_firmware/pull/23002))
* is31fl3741: split PWM and scaling buffers ([#23049](https://github.com/qmk/qmk_firmware/pull/23049))
* LED drivers: update PWM register defines for `g_<driver>_leds` ([#23052](https://github.com/qmk/qmk_firmware/pull/23052))
* LED drivers: add support for shutdown pin ([#23058](https://github.com/qmk/qmk_firmware/pull/23058))
* AW20216S: combine EN pin defines ([#23067](https://github.com/qmk/qmk_firmware/pull/23067))
* Update naming convention for GPIO control macros ([#23085](https://github.com/qmk/qmk_firmware/pull/23085))
* Update GPIO macro usages in core ([#23093](https://github.com/qmk/qmk_firmware/pull/23093))
* OS Detection - Entire file should not be wrapped with ifdef ([#23108](https://github.com/qmk/qmk_firmware/pull/23108))
* IS31FL3729 updates ([#23109](https://github.com/qmk/qmk_firmware/pull/23109))
* Nix shell updates (Nixpkgs 2024-02-23, QMK CLI 1.1.5) ([#23143](https://github.com/qmk/qmk_firmware/pull/23143))
CLI:
* [Refactor] `qmk find` ([#21096](https://github.com/qmk/qmk_firmware/pull/21096))
* [Refactor] Break `QGFImageFile`'s `_save` function into smaller pieces ([#21124](https://github.com/qmk/qmk_firmware/pull/21124))
* [Enhancement] Prepare for `SyntaxWarning` ([#22562](https://github.com/qmk/qmk_firmware/pull/22562))
* Flag invalid keyboard features during lint ([#22832](https://github.com/qmk/qmk_firmware/pull/22832))
Submodule updates:
* chore(chibios-contrib): sync with chibios-21.11.x ([#22560](https://github.com/qmk/qmk_firmware/pull/22560))
Keyboards:
* Move `redox_w` into `redox` ([#21448](https://github.com/qmk/qmk_firmware/pull/21448))
* null ST110R2.1 (SaikouType) basic support with layouts ([#21623](https://github.com/qmk/qmk_firmware/pull/21623))
* New keyboard addition: Orthograph ([#21770](https://github.com/qmk/qmk_firmware/pull/21770))
* Add Olly JF Rev.2 ([#21775](https://github.com/qmk/qmk_firmware/pull/21775))
* Cleanup Satisfaction75 Firmware and add new revisions ([#22082](https://github.com/qmk/qmk_firmware/pull/22082))
* Migrate dynamic_keymap.layer_count < 4 where requried ([#22091](https://github.com/qmk/qmk_firmware/pull/22091))
* Bastard Keyboards: Add support for Dilemma v2 (3x5+3) ([#22185](https://github.com/qmk/qmk_firmware/pull/22185))
* Karn: correct layout data ([#22201](https://github.com/qmk/qmk_firmware/pull/22201))
* zk3mod : added OLED ([#22303](https://github.com/qmk/qmk_firmware/pull/22303))
* Adds support for the Iron180 V2 PCBs ([#22314](https://github.com/qmk/qmk_firmware/pull/22314))
* Add 5x13 and 6x13 ortho community layouts ([#22315](https://github.com/qmk/qmk_firmware/pull/22315))
* Cipulot refactoring ([#22368](https://github.com/qmk/qmk_firmware/pull/22368))
* Remove era/klein ([#22384](https://github.com/qmk/qmk_firmware/pull/22384))
* consolidate firmware folder in smoll parent folder ([#22401](https://github.com/qmk/qmk_firmware/pull/22401))
* `keycapsss/plaid_pad`: switch to encoder map ([#22474](https://github.com/qmk/qmk_firmware/pull/22474))
* Add EE-AT and move W1-AT under geonworks ([#22526](https://github.com/qmk/qmk_firmware/pull/22526))
* refactor: projectcain/vault35 ([#22558](https://github.com/qmk/qmk_firmware/pull/22558))
* Update Q5 ([#22575](https://github.com/qmk/qmk_firmware/pull/22575))
* Update Q7 ([#22577](https://github.com/qmk/qmk_firmware/pull/22577))
* Update Q8 ([#22578](https://github.com/qmk/qmk_firmware/pull/22578))
* Update Q9 ([#22579](https://github.com/qmk/qmk_firmware/pull/22579))
* Remove "empty" files ([#22603](https://github.com/qmk/qmk_firmware/pull/22603))
* Rename Pumpkin Pad to Pumkinpad ([#22651](https://github.com/qmk/qmk_firmware/pull/22651))
* Noodlepad Additions and Updates ([#22701](https://github.com/qmk/qmk_firmware/pull/22701))
* Refactor: move miniaxe into kagizaraya ([#22708](https://github.com/qmk/qmk_firmware/pull/22708))
* Refactor: move keyboards into zigotica folder ([#22709](https://github.com/qmk/qmk_firmware/pull/22709))
* Refactor: move keyboards into laneware folder ([#22710](https://github.com/qmk/qmk_firmware/pull/22710))
* Refactor: move keyboards into kezewa ([#22712](https://github.com/qmk/qmk_firmware/pull/22712))
* Refactor: move keyboards into kbdmania folder ([#22714](https://github.com/qmk/qmk_firmware/pull/22714))
* Refactor: move keyboards into monokei folder ([#22715](https://github.com/qmk/qmk_firmware/pull/22715))
* Refactor: move keyboards into kumaokobo ([#22719](https://github.com/qmk/qmk_firmware/pull/22719))
* Updating NCC1701KB and adding via support ([#22721](https://github.com/qmk/qmk_firmware/pull/22721))
* Move Moonlander to ZSA folder ([#22740](https://github.com/qmk/qmk_firmware/pull/22740))
* Refactor: group shandoncodes keyboards ([#22743](https://github.com/qmk/qmk_firmware/pull/22743))
* Refactor: group rookiebwoy keyboards ([#22745](https://github.com/qmk/qmk_firmware/pull/22745))
* Default folder correction for kumaokobo ([#22750](https://github.com/qmk/qmk_firmware/pull/22750))
* Default folder correction for rookiebwoy ([#22753](https://github.com/qmk/qmk_firmware/pull/22753))
* Refactor: move macro3 into handwired folder ([#22759](https://github.com/qmk/qmk_firmware/pull/22759))
* Refactor: group kira keyboards ([#22760](https://github.com/qmk/qmk_firmware/pull/22760))
* Refactor: group hub keyboards ([#22762](https://github.com/qmk/qmk_firmware/pull/22762))
* Refactor: move p3d keyboards ([#22763](https://github.com/qmk/qmk_firmware/pull/22763))
* Refactor: group kbdfans keyboards ([#22764](https://github.com/qmk/qmk_firmware/pull/22764))
* Remove incorrect use of WS2812_PIO_USE_PIO1 ([#22771](https://github.com/qmk/qmk_firmware/pull/22771))
* Migrate LED Matrix config to info.json ([#22792](https://github.com/qmk/qmk_firmware/pull/22792))
* Migrate RGB Matrix config to info.json - [0-9] ([#22797](https://github.com/qmk/qmk_firmware/pull/22797))
* Migrate RGB Matrix config to info.json - A ([#22798](https://github.com/qmk/qmk_firmware/pull/22798))
* Late9 keymaps update, added VIA support ([#22801](https://github.com/qmk/qmk_firmware/pull/22801))
* Migrate RGB Matrix config to info.json - B ([#22806](https://github.com/qmk/qmk_firmware/pull/22806))
* Migrate RGB Matrix config to info.json - C ([#22807](https://github.com/qmk/qmk_firmware/pull/22807))
* Migrate RGB Matrix config to info.json - EF ([#22808](https://github.com/qmk/qmk_firmware/pull/22808))
* Migrate RGB Matrix config to info.json - D ([#22811](https://github.com/qmk/qmk_firmware/pull/22811))
* H87g2 updates ([#22819](https://github.com/qmk/qmk_firmware/pull/22819))
* WT boards: extract `g_is31fl3736_leds` from wt_mono_backlight ([#22823](https://github.com/qmk/qmk_firmware/pull/22823))
* Migrate RGB Matrix config to info.json - G ([#22859](https://github.com/qmk/qmk_firmware/pull/22859))
* Use existing columns for 3x5 layout ([#22860](https://github.com/qmk/qmk_firmware/pull/22860))
* Migrate RGB Matrix config to info.json - H ([#22861](https://github.com/qmk/qmk_firmware/pull/22861))
* Migrate RGB Matrix config to info.json - J ([#22862](https://github.com/qmk/qmk_firmware/pull/22862))
* Migrate RGB Matrix config to info.json - I ([#22863](https://github.com/qmk/qmk_firmware/pull/22863))
* Migrate RGB Matrix config to info.json - L ([#22864](https://github.com/qmk/qmk_firmware/pull/22864))
* Migrate RGB Matrix config to info.json - NOPQ ([#22866](https://github.com/qmk/qmk_firmware/pull/22866))
* Migrate RGB Matrix config to info.json - XZY ([#22879](https://github.com/qmk/qmk_firmware/pull/22879))
* Zed65/no_backlight/cor65 correct data layout ([#22898](https://github.com/qmk/qmk_firmware/pull/22898))
* Migrate RGB Matrix config to info.json - M ([#22908](https://github.com/qmk/qmk_firmware/pull/22908))
* Migrate RGB Matrix config to info.json - RS ([#22909](https://github.com/qmk/qmk_firmware/pull/22909))
* Migrate RGB Matrix config to info.json - TUVW ([#22910](https://github.com/qmk/qmk_firmware/pull/22910))
* Migrate RGB Matrix config to info.json - K ([#22911](https://github.com/qmk/qmk_firmware/pull/22911))
* Remove `LAYOUTS_HAS_RGB` ([#22917](https://github.com/qmk/qmk_firmware/pull/22917))
* Migrate lighting defaults to info.json ([#22920](https://github.com/qmk/qmk_firmware/pull/22920))
* Ensure LTO is enabled as a `info.json` build config option ([#22932](https://github.com/qmk/qmk_firmware/pull/22932))
* refactor(keyboard): quokka ([#22942](https://github.com/qmk/qmk_firmware/pull/22942))
* Sango Keyboard ([#22971](https://github.com/qmk/qmk_firmware/pull/22971))
* Add FS streampad ([#22991](https://github.com/qmk/qmk_firmware/pull/22991))
* Remove always enabled effects from lighting animation list ([#22992](https://github.com/qmk/qmk_firmware/pull/22992))
* Migrate RGB Matrix config to info.json - keychron ([#22998](https://github.com/qmk/qmk_firmware/pull/22998))
* Migrate RGB Matrix config to info.json - Misc ([#23000](https://github.com/qmk/qmk_firmware/pull/23000))
* Remove ee_hands config from ferris/sweep firmware ([#23029](https://github.com/qmk/qmk_firmware/pull/23029))
* Migrate dip switch config to info.json - keychron ([#23037](https://github.com/qmk/qmk_firmware/pull/23037))
* [unicorne] Add a layout alias ([#23056](https://github.com/qmk/qmk_firmware/pull/23056))
* nacly/sodium62: Update vid, pid, and add via keymap ([#23063](https://github.com/qmk/qmk_firmware/pull/23063))
* LED drivers: update keyboard LED configs ([#23073](https://github.com/qmk/qmk_firmware/pull/23073))
* Remove invalid keyboard level features ([#23074](https://github.com/qmk/qmk_firmware/pull/23074))
* Migrate WEAR_LEVELING_* to info.json ([#23077](https://github.com/qmk/qmk_firmware/pull/23077))
* [Keymap Removal] keyboard with most keymaps ([#23081](https://github.com/qmk/qmk_firmware/pull/23081))
* Remove obvious user keymaps, keyboards/{v,x,y,z}* edition. ([#23083](https://github.com/qmk/qmk_firmware/pull/23083))
* Remove obvious user keymaps, keyboards/{s,t}* edition. ([#23084](https://github.com/qmk/qmk_firmware/pull/23084))
* [Keymap Removal] keyboard with most keymaps ([#23092](https://github.com/qmk/qmk_firmware/pull/23092))
* Fiuxup takashicompany/heavy_left ([#23094](https://github.com/qmk/qmk_firmware/pull/23094))
* Remove obvious user keymaps, keyboards/{i,j,k}* edition ([#23102](https://github.com/qmk/qmk_firmware/pull/23102))
* Manual user keymap removal ([#23104](https://github.com/qmk/qmk_firmware/pull/23104))
* Manual user keymap removal ([#23119](https://github.com/qmk/qmk_firmware/pull/23119))
* Migrate `RGBLED_NUM` -> `RGBLIGHT_LED_COUNT` in remaining non-user keymaps ([#23128](https://github.com/qmk/qmk_firmware/pull/23128))
Keyboard fixes:
* Fix VID and PID for AnnePro2 ([#22263](https://github.com/qmk/qmk_firmware/pull/22263))
* fix(kikoslab/kl90): Fix firmware to support encoder knobs properly ([#22649](https://github.com/qmk/qmk_firmware/pull/22649))
* fix: improper usage of keyboard/user-level functions ([#22652](https://github.com/qmk/qmk_firmware/pull/22652))
* Temporary fix for mechlovin/olly/octagon ([#22796](https://github.com/qmk/qmk_firmware/pull/22796))
* Keychron Q11 usb poweron fix ([#22799](https://github.com/qmk/qmk_firmware/pull/22799))
* capsunlocked/cu80/v2: Fix invalid RGB matrix config ([#22873](https://github.com/qmk/qmk_firmware/pull/22873))
* Fix typo in Redox config ([#22899](https://github.com/qmk/qmk_firmware/pull/22899))
* Fixup doio/kb16 ([#22921](https://github.com/qmk/qmk_firmware/pull/22921))
* Fixup takashicompany/minizone ([#22922](https://github.com/qmk/qmk_firmware/pull/22922))
* Fixup sofle ([#22934](https://github.com/qmk/qmk_firmware/pull/22934))
* Fix Issue with RGB Matrix not understanding the split keyboard ([#22997](https://github.com/qmk/qmk_firmware/pull/22997))
* Fixup sawnsprojects/krush60 ([#23095](https://github.com/qmk/qmk_firmware/pull/23095))
* Fixup kbd67/rev1 ([#23096](https://github.com/qmk/qmk_firmware/pull/23096))
* Fixup boardsource/equals ([#23106](https://github.com/qmk/qmk_firmware/pull/23106))
* Fixup inett_studio/sq80 ([#23121](https://github.com/qmk/qmk_firmware/pull/23121))
* Add LED/RGB Matrix drivers to info.json schema ([#23127](https://github.com/qmk/qmk_firmware/pull/23127))
* Fix for multiple AMUX usage ([#23155](https://github.com/qmk/qmk_firmware/pull/23155))
Bugs:
* MIDI sustain effect fix on qmk 0.22.2 ([#22114](https://github.com/qmk/qmk_firmware/pull/22114))
* Prevent `qmk migrate` processing unparsed info.json values ([#22374](https://github.com/qmk/qmk_firmware/pull/22374))
* Remove redundant backlight eeconfig init ([#22675](https://github.com/qmk/qmk_firmware/pull/22675))
* pointing_device ifdef indentation fix ([#22802](https://github.com/qmk/qmk_firmware/pull/22802))
* Ensure LED config is extracted when feature is disabled ([#22809](https://github.com/qmk/qmk_firmware/pull/22809))
* Generate true/false for _DEFAULT_ON options ([#22829](https://github.com/qmk/qmk_firmware/pull/22829))
* is31fl3733: fix driver sync backwards compatibility defines ([#22851](https://github.com/qmk/qmk_firmware/pull/22851))
* LED drivers: misc formatting and typos ([#22857](https://github.com/qmk/qmk_firmware/pull/22857))
* Allow generation of both LED and RGB Matrix config ([#22896](https://github.com/qmk/qmk_firmware/pull/22896))
* LED drivers: remove PWM register offsets ([#22897](https://github.com/qmk/qmk_firmware/pull/22897))
* `qmk format-json`: Force Unix line endings and ensure LF at EOF ([#22901](https://github.com/qmk/qmk_firmware/pull/22901))
* Fix cirque connected check ([#22948](https://github.com/qmk/qmk_firmware/pull/22948))
* Fix joystick initialization ([#22953](https://github.com/qmk/qmk_firmware/pull/22953))
* Workaround for `make test:all DEBUG=1` ([#23047](https://github.com/qmk/qmk_firmware/pull/23047))
* Fix unit test execution ([#23048](https://github.com/qmk/qmk_firmware/pull/23048))
* Fix git-submodule running in wrong location ([#23059](https://github.com/qmk/qmk_firmware/pull/23059))
* WS2812 bitbang: prefix for `NOP_FUDGE` define ([#23110](https://github.com/qmk/qmk_firmware/pull/23110))
* Fix make clean test:os_detection ([#23112](https://github.com/qmk/qmk_firmware/pull/23112))
* Fix pmw33xx sensor corruption on get-cpi call ([#23116](https://github.com/qmk/qmk_firmware/pull/23116))
* Ensure `qmk generate-compilation-database` copies to userspace as well. ([#23129](https://github.com/qmk/qmk_firmware/pull/23129))

View File

@ -138,7 +138,7 @@
* Breaking Changes * Breaking Changes
* [Overview](breaking_changes.md) * [Overview](breaking_changes.md)
* [My Pull Request Was Flagged](breaking_changes_instructions.md) * [My Pull Request Was Flagged](breaking_changes_instructions.md)
* [Most Recent ChangeLog](ChangeLog/20231126.md "QMK v0.23.0 - 2023 Nov 26") * [Most Recent ChangeLog](ChangeLog/20240225.md "QMK v0.24.0 - 2024 Feb 25")
* [Past Breaking Changes](breaking_changes_history.md) * [Past Breaking Changes](breaking_changes_history.md)
* C Development * C Development

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 Feb 25](ChangeLog/20240225.md)
* [2023 Nov 26](ChangeLog/20231126.md) * [2023 Nov 26](ChangeLog/20231126.md)
* [2023 Aug 27](ChangeLog/20230827.md) * [2023 Aug 27](ChangeLog/20230827.md)
* [2023 May 28](ChangeLog/20230528.md)
* [Older Breaking Changes](breaking_changes_history.md) * [Older Breaking Changes](breaking_changes_history.md)
## When is the next Breaking Change? ## When is the next Breaking Change?
The next Breaking Change is scheduled for November 26, 2023. The next Breaking Change is scheduled for May 26, 2024.
### Important Dates ### Important Dates
* 2023 Nov 26 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions. * 2024 Feb 25 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2024 Jan 28 - `develop` closed to new PRs. * 2024 Apr 28 - `develop` closed to new PRs.
* 2024 Jan 28 - Call for testers. * 2024 Apr 28 - Call for testers.
* 2024 Feb 4 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes * 2024 May 5 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2024 Feb 18 - `develop` is locked, only critical bugfix PRs merged. * 2024 May 19 - `develop` is locked, only critical bugfix PRs merged.
* 2024 Feb 22 - `master` is locked, no PRs merged. * 2024 May 23 - `master` is locked, no PRs merged.
* 2024 Feb 25 - Merge `develop` to `master`. * 2024 May 26 - Merge `develop` to `master`.
* 2024 Feb 25 - `master` is unlocked. PRs can be merged again. * 2024 May 26 - `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/20240225`. * The PR has a ChangeLog file describing the changes under `<qmk_firmware>/docs/Changelog/20240526`.
* 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 Feb 25](ChangeLog/20240225.md) - version 0.24.0
* [2023 Nov 26](ChangeLog/20231126.md) - version 0.23.0 * [2023 Nov 26](ChangeLog/20231126.md) - version 0.23.0
* [2023 Aug 27](ChangeLog/20230827.md) - version 0.22.0 * [2023 Aug 27](ChangeLog/20230827.md) - version 0.22.0
* [2023 May 28](ChangeLog/20230528.md) - version 0.21.0 * [2023 May 28](ChangeLog/20230528.md) - version 0.21.0

View File

@ -797,3 +797,39 @@ This command converts a TTF font to an intermediate format for editing, before c
This command converts an intermediate font image to the QFF File Format. See the [Quantum Painter](quantum_painter.md?id=quantum-painter-cli) documentation for more information on this command. This command converts an intermediate font image to the QFF File Format. See the [Quantum Painter](quantum_painter.md?id=quantum-painter-cli) documentation for more information on this command.
## `qmk test-c`
This command runs the C unit test suite. If you make changes to C code you should ensure this runs successfully.
**Usage**:
```
qmk test-c [-h] [-t TEST] [-l] [-c] [-e ENV] [-j PARALLEL]
options:
-h, --help show this help message and exit
-t TEST, --test TEST Test to run from the available list. Supports wildcard globs. May be passed multiple times.
-l, --list List available tests.
-c, --clean Remove object files before compiling.
-e ENV, --env ENV Set a variable to be passed to make. May be passed multiple times.
-j PARALLEL, --parallel PARALLEL
Set the number of parallel make jobs; 0 means unlimited.
```
**Examples**:
Run entire test suite:
qmk test-c
List available tests:
qmk test-c --list
Run matching test:
qmk test-c --test unicode*
Run single test:
qmk test-c --test basic

View File

@ -70,13 +70,13 @@ The device name here is the name that appears in Zadig, and may not be what the
|Bootloader |Device Name |VID/PID |Driver | |Bootloader |Device Name |VID/PID |Driver |
|--------------|------------------------------|--------------|-------| |--------------|------------------------------|--------------|-------|
|`atmel-dfu` |ATmega16u2 DFU |`03EB:2FEF` |libusb0| |`atmel-dfu` |ATmega16u2 DFU |`03EB:2FEF` |WinUSB |
|`atmel-dfu` |ATmega32U2 DFU |`03EB:2FF0` |libusb0| |`atmel-dfu` |ATmega32U2 DFU |`03EB:2FF0` |WinUSB |
|`atmel-dfu` |ATm16U4 DFU V1.0.2 |`03EB:2FF3` |libusb0| |`atmel-dfu` |ATm16U4 DFU V1.0.2 |`03EB:2FF3` |WinUSB |
|`atmel-dfu` |ATm32U4DFU |`03EB:2FF4` |libusb0| |`atmel-dfu` |ATm32U4DFU |`03EB:2FF4` |WinUSB |
|`atmel-dfu` |*none* (AT90USB64) |`03EB:2FF9` |libusb0| |`atmel-dfu` |*none* (AT90USB64) |`03EB:2FF9` |WinUSB |
|`atmel-dfu` |AT90USB128 DFU |`03EB:2FFB` |libusb0| |`atmel-dfu` |AT90USB128 DFU |`03EB:2FFB` |WinUSB |
|`qmk-dfu` |(keyboard name) Bootloader |As `atmel-dfu`|libusb0| |`qmk-dfu` |(keyboard name) Bootloader |As `atmel-dfu`|WinUSB |
|`halfkay` |*none* |`16C0:0478` |HidUsb | |`halfkay` |*none* |`16C0:0478` |HidUsb |
|`caterina` |Pro Micro 3.3V |`1B4F:9203` |usbser | |`caterina` |Pro Micro 3.3V |`1B4F:9203` |usbser |
|`caterina` |Pro Micro 5V |`1B4F:9205` |usbser | |`caterina` |Pro Micro 5V |`1B4F:9205` |usbser |

View File

@ -171,29 +171,31 @@ The available keycodes for audio are:
## Audio Config ## Audio Config
| Settings | Default | Description | | Settings | Default | Description |
|---------------------------------|----------------------|-------------------------------------------------------------------------------| |----------------------------------|----------------------|---------------------------------------------------------------------------------------------|
|`AUDIO_PIN` | *Not defined* |Configures the pin that the speaker is connected to. | |`AUDIO_PIN` | *Not defined* |Configures the pin that the speaker is connected to. |
|`AUDIO_PIN_ALT` | *Not defined* |Configures the pin for a second speaker or second pin connected to one speaker.| |`AUDIO_PIN_ALT` | *Not defined* |Configures the pin for a second speaker or second pin connected to one speaker. |
|`AUDIO_PIN_ALT_AS_NEGATIVE` | *Not defined* |Enables support for one speaker connected to two pins. | |`AUDIO_PIN_ALT_AS_NEGATIVE` | *Not defined* |Enables support for one speaker connected to two pins. |
|`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. | |`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. |
|`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. | |`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. |
|`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) | |`AUDIO_POWER_CONTROL_PIN` | *Not defined* |Enables power control code to enable or cut off power to speaker (such as with PAM8302 amp). |
|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) | |`AUDIO_POWER_CONTROL_PIN_ON_STATE`| `1` |The state of the audio power control pin when audio is "on" - `1` for high, `0` for low. |
|`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) | |`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) |
|`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) | |`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) |
|`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) | |`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) |
|`CG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press CG_SWAP (process_magic.c) | |`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) |
|`MUSIC_ON_SONG` | `MUSIC_ON_SOUND` |Plays when music mode is activated (process_music.c) | |`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) |
|`MUSIC_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when music mode is deactivated (process_music.c) | |`CG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press CG_SWAP (process_magic.c) |
|`MIDI_ON_SONG` | `MUSIC_ON_SOUND` |Plays when midi mode is activated (process_music.c) | |`MUSIC_ON_SONG` | `MUSIC_ON_SOUND` |Plays when music mode is activated (process_music.c) |
|`MIDI_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when midi mode is deactivated (process_music.c) | |`MUSIC_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when music mode is deactivated (process_music.c) |
|`CHROMATIC_SONG` | `CHROMATIC_SOUND` |Plays when the chromatic music mode is selected (process_music.c) | |`MIDI_ON_SONG` | `MUSIC_ON_SOUND` |Plays when midi mode is activated (process_music.c) |
|`GUITAR_SONG` | `GUITAR_SOUND` |Plays when the guitar music mode is selected (process_music.c) | |`MIDI_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when midi mode is deactivated (process_music.c) |
|`VIOLIN_SONG` | `VIOLIN_SOUND` |Plays when the violin music mode is selected (process_music.c) | |`CHROMATIC_SONG` | `CHROMATIC_SOUND` |Plays when the chromatic music mode is selected (process_music.c) |
|`MAJOR_SONG` | `MAJOR_SOUND` |Plays when the major music mode is selected (process_music.c) | |`GUITAR_SONG` | `GUITAR_SOUND` |Plays when the guitar music mode is selected (process_music.c) |
|`DEFAULT_LAYER_SONGS` | *Not defined* |Plays song when switched default layers with [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer)(quantum.c) | |`VIOLIN_SONG` | `VIOLIN_SOUND` |Plays when the violin music mode is selected (process_music.c) |
|`SENDSTRING_BELL` | *Not defined* |Plays chime when the "enter" ("\a") character is sent (send_string.c) | |`MAJOR_SONG` | `MAJOR_SOUND` |Plays when the major music mode is selected (process_music.c) |
|`DEFAULT_LAYER_SONGS` | *Not defined* |Plays song when switched default layers with [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer)(quantum.c). |
|`SENDSTRING_BELL` | *Not defined* |Plays chime when the "enter" ("\a") character is sent (send_string.c) |
## Tempo ## Tempo
the 'speed' at which SONGs are played is dictated by the set Tempo, which is measured in beats-per-minute. Note lengths are defined relative to that. the 'speed' at which SONGs are played is dictated by the set Tempo, which is measured in beats-per-minute. Note lengths are defined relative to that.

View File

@ -1,8 +1,8 @@
# Bootmagic Lite :id=bootmagic-lite # Bootmagic :id=bootmagic
The Bootmagic Lite feature that only handles jumping into the bootloader. This is great for boards that don't have a physical reset button, giving you a way to jump into the bootloader The Bootmagic feature that only handles jumping into the bootloader. This is great for boards that don't have a physical reset button, giving you a way to jump into the bootloader
On some keyboards Bootmagic Lite is disabled by default. If this is the case, it must be explicitly enabled in your `rules.mk` with: On some keyboards Bootmagic is disabled by default. If this is the case, it must be explicitly enabled in your `rules.mk` with:
```make ```make
BOOTMAGIC_ENABLE = yes BOOTMAGIC_ENABLE = yes
@ -11,15 +11,15 @@ BOOTMAGIC_ENABLE = yes
Additionally, you may want to specify which key to use. This is especially useful for keyboards that have unusual matrices. To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file: Additionally, you may want to specify which key to use. This is especially useful for keyboards that have unusual matrices. To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file:
```c ```c
#define BOOTMAGIC_LITE_ROW 0 #define BOOTMAGIC_ROW 0
#define BOOTMAGIC_LITE_COLUMN 1 #define BOOTMAGIC_COLUMN 1
``` ```
By default, these are set to 0 and 0, which is usually the "ESC" key on a majority of keyboards. By default, these are set to 0 and 0, which is usually the "ESC" key on a majority of keyboards.
And to trigger the bootloader, you hold this key down when plugging the keyboard in. Just the single key. And to trigger the bootloader, you hold this key down when plugging the keyboard in. Just the single key.
!> Using Bootmagic Lite will **always reset** the EEPROM, so you will lose any settings that have been saved. !> Using Bootmagic will **always reset** the EEPROM, so you will lose any settings that have been saved.
## Split Keyboards ## Split Keyboards
@ -44,35 +44,35 @@ When [handedness](feature_split_keyboard.md#setting-handedness) is predetermined
} }
``` ```
If you pick the top right key for the right half, it is `R05` on the top layout. Within the key matrix below, `R05` is located on row 4 columnn 4. To use that key as the right half's Bootmagic Lite trigger, add these entries to your `config.h` file: If you pick the top right key for the right half, it is `R05` on the top layout. Within the key matrix below, `R05` is located on row 4 columnn 4. To use that key as the right half's Bootmagic trigger, add these entries to your `config.h` file:
```c ```c
#define BOOTMAGIC_LITE_ROW_RIGHT 4 #define BOOTMAGIC_ROW_RIGHT 4
#define BOOTMAGIC_LITE_COLUMN_RIGHT 4 #define BOOTMAGIC_COLUMN_RIGHT 4
``` ```
?> These values are not set by default. ?> These values are not set by default.
## Advanced Bootmagic Lite ## Advanced Bootmagic
The `bootmagic_lite` function is defined weakly, so that you can replace this in your code, if you need. A great example of this is the Zeal60 boards that have some additional handling needed. The `bootmagic_scan` function is defined weakly, so that you can replace this in your code, if you need. A great example of this is the Zeal60 boards that have some additional handling needed.
To replace the function, all you need to do is add something like this to your code: To replace the function, all you need to do is add something like this to your code:
```c ```c
void bootmagic_lite(void) { void bootmagic_scan(void) {
matrix_scan(); matrix_scan();
wait_ms(DEBOUNCE * 2); wait_ms(DEBOUNCE * 2);
matrix_scan(); matrix_scan();
if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) { if (matrix_get_row(BOOTMAGIC_ROW) & (1 << BOOTMAGIC_COLUMN)) {
// Jump to bootloader. // Jump to bootloader.
bootloader_jump(); bootloader_jump();
} }
} }
``` ```
You can define additional logic here. For instance, resetting the EEPROM or requiring additional keys to be pressed to trigger Bootmagic Lite. Keep in mind that `bootmagic_lite` is called before a majority of features are initialized in the firmware. You can define additional logic here. For instance, resetting the EEPROM or requiring additional keys to be pressed to trigger Bootmagic. Keep in mind that `bootmagic_scan` is called before a majority of features are initialized in the firmware.
## Addenda ## Addenda

View File

@ -333,27 +333,26 @@ will give the _NAV layer as a reference to it's self. All other layers
will have the default for their combo reference layer. If the default will have the default for their combo reference layer. If the default
is not set, all other layers will reference themselves. is not set, all other layers will reference themselves.
```c ```c
#define COMBO_REF_DEFAULT _MY_COMBO_LAYER #define COMBO_REF_DEFAULT _MY_COMBO_LAYER
...
uint8_t combo_ref_from_layer(uint8_t layer){ uint8_t combo_ref_from_layer(uint8_t layer){
switch (get_highest_layer(layer_state)){ switch (get_highest_layer(layer_state)){
case _DVORAK: return _QWERTY; case _DVORAK: return _QWERTY;
case _NAV: return _NAV; case _NAV: return _NAV;
default: return _MY_COMBO_LAYER; default: return _MY_COMBO_LAYER;
}
return layer; // important if default is not in case.
} }
``` return layer; // important if default is not in case.
}
```
The equivalent definition using the combo macros is this: The equivalent definition using the combo macros is this:
```c ```c
COMBO_REF_LAYER(_DVORAK, _QWERTY) COMBO_REF_LAYER(_DVORAK, _QWERTY)
COMBO_REF_LAYER(_NAV, _NAV) COMBO_REF_LAYER(_NAV, _NAV)
DEFAULT_REF_LAYER(_MY_COMBO_LAYER). DEFAULT_REF_LAYER(_MY_COMBO_LAYER).
``` ```
## User callbacks ## User callbacks

View File

@ -780,6 +780,9 @@ There are several functions that allow for more advanced interaction with the au
| `get_auto_mouse_timeout(void)` | Return the current timeout for turing off the layer | | `uint16_t` | | `get_auto_mouse_timeout(void)` | Return the current timeout for turing off the layer | | `uint16_t` |
| `set_auto_mouse_debounce(uint16_t timeout)` | Change/set the debounce for preventing layer activation | | `void`(None) | | `set_auto_mouse_debounce(uint16_t timeout)` | Change/set the debounce for preventing layer activation | | `void`(None) |
| `get_auto_mouse_debounce(void)` | Return the current debounce for preventing layer activation | | `uint8_t` | | `get_auto_mouse_debounce(void)` | Return the current debounce for preventing layer activation | | `uint8_t` |
| `is_auto_mouse_active(void)` | Returns the active state of the auto mouse layer (eg if the layer has been triggered)| | `bool` |
| `get_auto_mouse_key_tracker(void)` | Gets the current count for the auto mouse key tracker. | | `int8_t` |
| `set_auto_mouse_key_tracker(int8_t key_tracker)` | Sets/Overrides the current count for the auto mouse key tracker. | | `void`(None) |
_NOTES:_ _NOTES:_
- _Due to the nature of how some functions work, the `auto_mouse_trigger_reset`, and `auto_mouse_layer_off` functions should never be called in the `layer_state_set_*` stack as this can cause indefinite loops._ - _Due to the nature of how some functions work, the `auto_mouse_trigger_reset`, and `auto_mouse_layer_off` functions should never be called in the `layer_state_set_*` stack as this can cause indefinite loops._

View File

@ -139,8 +139,8 @@ BOOTMAGIC_ENABLE = lite
さらに、どのキーを使うかを指定したほうが良いかもしれません。これは普通ではないマトリックスを持つキーボードで特に便利です。そのためには、使いたいキーの行と列を指定する必要があります。`config.h` ファイルにこれらのエントリを追加します: さらに、どのキーを使うかを指定したほうが良いかもしれません。これは普通ではないマトリックスを持つキーボードで特に便利です。そのためには、使いたいキーの行と列を指定する必要があります。`config.h` ファイルにこれらのエントリを追加します:
```c ```c
#define BOOTMAGIC_LITE_ROW 0 #define BOOTMAGIC_ROW 0
#define BOOTMAGIC_LITE_COLUMN 1 #define BOOTMAGIC_COLUMN 1
``` ```
デフォルトでは、これらは 0 と 0 に設定されます。これは通常はほとんどのキーボードで "ESC" キーです。 デフォルトでは、これらは 0 と 0 に設定されます。これは通常はほとんどのキーボードで "ESC" キーです。
@ -154,8 +154,8 @@ BOOTMAGIC_ENABLE = lite
`SPLIT_HAND_PIN` のようなオプションで、左右の設定があらかじめ決められている場合は、キーボードの左右で別のキーを設定する必要があるかもしれません。これを行うには、`config.h` ファイルに以下のエントリを追加します。 `SPLIT_HAND_PIN` のようなオプションで、左右の設定があらかじめ決められている場合は、キーボードの左右で別のキーを設定する必要があるかもしれません。これを行うには、`config.h` ファイルに以下のエントリを追加します。
```c ```c
#define BOOTMAGIC_LITE_ROW_RIGHT 4 #define BOOTMAGIC_ROW_RIGHT 4
#define BOOTMAGIC_LITE_COLUMN_RIGHT 1 #define BOOTMAGIC_COLUMN_RIGHT 1
``` ```
デフォルトでは、これらの値は設定されていません。 デフォルトでは、これらの値は設定されていません。
@ -172,7 +172,7 @@ void bootmagic_lite(void) {
wait_ms(DEBOUNCE * 2); wait_ms(DEBOUNCE * 2);
matrix_scan(); matrix_scan();
if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) { if (matrix_get_row(BOOTMAGIC_ROW) & (1 << BOOTMAGIC_COLUMN)) {
// ブートローダにジャンプする。 // ブートローダにジャンプする。
bootloader_jump(); bootloader_jump();
} }

View File

@ -117,3 +117,77 @@ Using the [standard `compile_commands.json` database](https://clang.llvm.org/doc
1. Start typing `clangd: Restart Language Server` and select it when it appears. 1. Start typing `clangd: Restart Language Server` and select it when it appears.
Now you're ready to code QMK Firmware in VS Code! Now you're ready to code QMK Firmware in VS Code!
# Debugging ARM MCUs with Visual Studio Code
**...and a Black Magic Probe.**
Visual Studio Code has the ability to debug applications, but requires some configuration in order to get it to be able to do so for ARM targets.
This documentation describes a known-working configuration for setting up the use of a Black Magic Probe to debug using VS Code.
It is assumed that you've correctly set up the electrical connectivity of the Black Magic Probe with your MCU. Wiring up `NRST`, `SWDIO`, `SWCLK`, and `GND` should be enough.
Install the following plugin into VS Code:
* [Cortex-Debug](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug) -
This adds debugger support for ARM Cortex targets to VS Code.
A debugging target for the MCU for your board needs to be defined, and can be done so by adding the following to a `.vscode/launch.json` file:
```json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Black Magic Probe (OneKey Proton-C)",
"type": "cortex-debug",
"request": "launch",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/.build/handwired_onekey_proton_c_default.elf",
"servertype": "bmp",
"BMPGDBSerialPort": "COM4",
"svdFile": "Q:\\svd\\STM32F303.svd",
"device": "STM32F303",
"v1": false,
"windows": {
"armToolchainPath": "C:\\QMK_MSYS\\mingw64\\bin"
}
}
]
}
```
You'll need to perform some modifications to the file above in order to target your specific device:
* `"name"`: Can be anything, but if you're debugging multiple targets you'll want something descriptive here.
* `"cwd"`: The path to the QMK Firmware repository root directory -- _if using the `.vscode` directory existing in the `qmk_firmware` git repository, the default above should be correct_
* `"executable"`: The path to the `elf` file generated as part of the build for your keyboard -- _exists in `<qmk_firmware>/.build`_
* `"BMPGDBSerialPort"`: The `COM` port under Windows, or the `/dev/...` path for Linux/macOS. Two serial port devices will be created -- the Black Magic Probe debug port is *usually* the first. If it doesn't work, try the second.
* `"svdFile"`: _[Optional]_ The path to the SVD file that defines the register layout for the MCU -- the appropriate file can be downloaded from the [cmsis-svd repository](https://github.com/posborne/cmsis-svd/tree/master/data/STMicro)
* `"device"`: The name of the MCU, which matches the `<name>` tag at the top of the downloaded `svd` file.
* `"armToolchainPath"`: _[Optional]_ The path to the ARM toolchain installation location on Windows -- under normal circumstances Linux/macOS will auto-detect this correctly and will not need to be specified.
!> Windows builds of QMK Firmware are generally compiled using QMK MSYS, and the path to gdb's location (`C:\\QMK_MSYS\\mingw64\\bin`) needs to be specified under `armToolchainPath` for it to be detected. You may also need to change the GDB path to point at `C:\\QMK_MSYS\\mingw64\\bin\\gdb-multiarch.exe` in the VSCode Cortex-Debug user settings: ![VSCode Settings](https://i.imgur.com/EGrPM1L.png)
Optionally, the following modifications should also be made to the keyboard's `rules.mk` file to disable optimisations -- not strictly required but will ensure breakpoints and variable viewing works correctly:
```makefile
# Disable optimisations for debugging purposes
LTO_ENABLE = no
OPT = g
DEBUG = 3
```
At this point, you should build and flash your firmware through normal methods (`qmk compile ...` and `qmk flash ...`).
Once completed, you can:
* Switch to the debug view in VS Code (in the sidebar, the Play button with a bug next to it)
* Select the newly-created debug target in the dropdown at the top of the sidebar
* Click the green play button next to the dropdown
VS Code's debugger will then start executing the compiled firmware on the MCU.
At this stage, you should have full debugging set up, with breakpoints and variable listings working!

View File

@ -2,7 +2,7 @@
The following table shows the current driver status for peripherals on RP2040 MCUs: The following table shows the current driver status for peripherals on RP2040 MCUs:
| System | Support | | System | Support |
| ---------------------------------------------------------------- | ---------------------------------------------- | | ---------------------------------------------------------------- | ---------------------------------------------- |
| [ADC driver](adc_driver.md) | :heavy_check_mark: | | [ADC driver](adc_driver.md) | :heavy_check_mark: |
| [Audio](audio_driver.md#pwm-hardware) | :heavy_check_mark: | | [Audio](audio_driver.md#pwm-hardware) | :heavy_check_mark: |
@ -13,7 +13,7 @@ The following table shows the current driver status for peripherals on RP2040 MC
| [External EEPROMs](eeprom_driver.md) | :heavy_check_mark: using `I2C` or `SPI` driver | | [External EEPROMs](eeprom_driver.md) | :heavy_check_mark: using `I2C` or `SPI` driver |
| [EEPROM emulation](eeprom_driver.md#wear_leveling-configuration) | :heavy_check_mark: | | [EEPROM emulation](eeprom_driver.md#wear_leveling-configuration) | :heavy_check_mark: |
| [serial driver](serial_driver.md) | :heavy_check_mark: using `SIO` or `PIO` driver | | [serial driver](serial_driver.md) | :heavy_check_mark: using `SIO` or `PIO` driver |
| [UART driver](uart_driver.md) | Support planned (no ETA) | | [UART driver](uart_driver.md) | :heavy_check_mark: using `SIO` driver |
## GPIO ## GPIO
@ -52,6 +52,13 @@ To configure the I2C driver please read the [ChibiOS/ARM](i2c_driver.md#arm-conf
To configure the SPI driver please read the [ChibiOS/ARM](spi_driver.md#chibiosarm-configuration) section. To configure the SPI driver please read the [ChibiOS/ARM](spi_driver.md#chibiosarm-configuration) section.
### UART Driver
| RP2040 Peripheral | `mcuconf.h` values | `UART_DRIVER` |
| ----------------- | ------------------ | ------------- |
| `UART0` | `RP_SIO_USE_UART0` | `SIOD0` |
| `UART1` | `RP_SIO_USE_UART1` | `SIOD1` |
## Double-tap reset boot-loader entry :id=double-tap ## Double-tap reset boot-loader entry :id=double-tap
The double-tap reset mechanism is an alternate way in QMK to enter the embedded mass storage UF2 boot-loader of the RP2040. It enables bootloader entry by a fast double-tap of the reset pin on start up, which is similar to the behavior of AVR Pro Micros. This feature activated by default for the Pro Micro RP2040 board, but has to be configured for other boards. To activate it, add the following options to your keyboards `config.h` file: The double-tap reset mechanism is an alternate way in QMK to enter the embedded mass storage UF2 boot-loader of the RP2040. It enables bootloader entry by a fast double-tap of the reset pin on start up, which is similar to the behavior of AVR Pro Micros. This feature activated by default for the Pro Micro RP2040 board, but has to be configured for other boards. To activate it, add the following options to your keyboards `config.h` file:
@ -87,6 +94,10 @@ This is the default board that is chosen, unless any other RP2040 board is selec
| `SOFT_SERIAL_PIN` | undefined, use `SERIAL_USART_TX_PIN` | | `SOFT_SERIAL_PIN` | undefined, use `SERIAL_USART_TX_PIN` |
| `SERIAL_USART_TX_PIN` | `GP0` | | `SERIAL_USART_TX_PIN` | `GP0` |
| `SERIAL_USART_RX_PIN` | `GP1` | | `SERIAL_USART_RX_PIN` | `GP1` |
| **UART driver** | |
| `UART_DRIVER` | `SIOD0` |
| `UART_TX_PIN` | `GP0` |
| `UART_RX_PIN` | `GP1` |
?> The pin-outs of Adafruit's KB2040 and Boardsource's Blok both deviate from the Sparkfun Pro Micro RP2040. Lookup the pin-out of these boards and adjust your keyboards pin definition accordingly if you want to use these boards. ?> The pin-outs of Adafruit's KB2040 and Boardsource's Blok both deviate from the Sparkfun Pro Micro RP2040. Lookup the pin-out of these boards and adjust your keyboards pin definition accordingly if you want to use these boards.

View File

@ -24,6 +24,7 @@ Supported devices:
| GC9A01 | RGB LCD (circular) | 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += gc9a01_spi` | | GC9A01 | RGB LCD (circular) | 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += gc9a01_spi` |
| ILI9163 | RGB LCD | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9163_spi` | | ILI9163 | RGB LCD | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9163_spi` |
| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_spi` | | ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_spi` |
| ILI9486 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9486_spi` |
| ILI9488 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9488_spi` | | ILI9488 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9488_spi` |
| SSD1351 | RGB OLED | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ssd1351_spi` | | SSD1351 | RGB OLED | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ssd1351_spi` |
| ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` | | ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` |
@ -318,6 +319,39 @@ The maximum number of displays can be configured by changing the following in yo
Native color format rgb565 is compatible with ILI9341 Native color format rgb565 is compatible with ILI9341
#### ** ILI9486 **
Enabling support for the ILI9486 in Quantum Painter is done by adding the following to `rules.mk`:
```make
QUANTUM_PAINTER_ENABLE = yes
QUANTUM_PAINTER_DRIVERS += ili9486_spi
```
Creating a ILI9486 device in firmware can then be done with the following API:
```c
painter_device_t qp_ili9486_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);
```
There's another variant for this [Waveshare module](https://www.waveshare.com/wiki/3.5inch_TFT_Touch_Shield), because it has a quirky SPI->Parallel converter. You can create it with:
```c
painter_device_t qp_ili9486_make_spi_waveshare_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);
```
The device handle returned from these functions can be used to perform all other drawing operations.
The maximum number of displays can be configured by changing the following in your `config.h` (default is 1):
```c
// 3 displays:
#define ILI9486_NUM_DEVICES 3
```
Native color format rgb888 is compatible with ILI9486
Native color format rgb565 is compatible with ILI9486 Waveshare
#### ** ILI9488 ** #### ** ILI9488 **
Enabling support for the ILI9488 in Quantum Painter is done by adding the following to `rules.mk`: Enabling support for the ILI9488 in Quantum Painter is done by adding the following to `rules.mk`:

View File

@ -123,10 +123,17 @@ Configures the [Audio](feature_audio.md) feature.
* Default: `false` * Default: `false`
* `pins` (Required) * `pins` (Required)
* The GPIO pin(s) connected to the speaker(s). * The GPIO pin(s) connected to the speaker(s).
* `power_control`
* `on_state`
* The logical GPIO state required to turn the speaker on.
* Default: `1` (on = high)
* `pin`
* The GPIO pin connected to speaker power circuit.
* `voices` * `voices`
* Use multiple audio voices. * Use multiple audio voices.
* Default: `false` * Default: `false`
## Backlight :id=backlight ## Backlight :id=backlight
Configures the [Backlight](feature_backlight.md) feature. Configures the [Backlight](feature_backlight.md) feature.

View File

@ -32,13 +32,7 @@ No special setup is required - just connect the `RX` and `TX` pins of your UART
You'll need to determine which pins can be used for UART -- as an example, STM32 parts generally have multiple UART peripherals, labeled USART1, USART2, USART3 etc. You'll need to determine which pins can be used for UART -- as an example, STM32 parts generally have multiple UART peripherals, labeled USART1, USART2, USART3 etc.
To enable UART, modify your board's `halconf.h` to enable the serial driver: To enable UART, modify your board's `mcuconf.h` to enable the peripheral you've chosen, for example:
```c
#define HAL_USE_SERIAL TRUE
```
Then, modify your board's `mcuconf.h` to enable the peripheral you've chosen, for example:
```c ```c
#undef STM32_SERIAL_USE_USART2 #undef STM32_SERIAL_USE_USART2
@ -47,17 +41,17 @@ Then, modify your board's `mcuconf.h` to enable the peripheral you've chosen, fo
Configuration-wise, you'll need to set up the peripheral as per your MCU's datasheet -- the defaults match the pins for a Proton-C, i.e. STM32F303. Configuration-wise, you'll need to set up the peripheral as per your MCU's datasheet -- the defaults match the pins for a Proton-C, i.e. STM32F303.
|`config.h` override |Description |Default Value| | `config.h` override | Description | Default Value |
|--------------------------|---------------------------------------------------------------|-------------| | --------------------------- | --------------------------------------------------------------- | ------------- |
|`#define SERIAL_DRIVER` |USART peripheral to use - USART1 -> `SD1`, USART2 -> `SD2` etc.|`SD1` | | `#define UART_DRIVER` | USART peripheral to use - USART1 -> `SD1`, USART2 -> `SD2` etc. | `SD1` |
|`#define SD1_TX_PIN` |The pin to use for TX |`A9` | | `#define UART_TX_PIN` | The pin to use for TX | `A9` |
|`#define SD1_TX_PAL_MODE` |The alternate function mode for TX |`7` | | `#define UART_TX_PAL_MODE` | The alternate function mode for TX | `7` |
|`#define SD1_RX_PIN` |The pin to use for RX |`A10` | | `#define UART_RX_PIN` | The pin to use for RX | `A10` |
|`#define SD1_RX_PAL_MODE` |The alternate function mode for RX |`7` | | `#define UART_RX_PAL_MODE` | The alternate function mode for RX | `7` |
|`#define SD1_CTS_PIN` |The pin to use for CTS |`A11` | | `#define UART_CTS_PIN` | The pin to use for CTS | `A11` |
|`#define SD1_CTS_PAL_MODE`|The alternate function mode for CTS |`7` | | `#define UART_CTS_PAL_MODE` | The alternate function mode for CTS | `7` |
|`#define SD1_RTS_PIN` |The pin to use for RTS |`A12` | | `#define UART_RTS_PIN` | The pin to use for RTS | `A12` |
|`#define SD1_RTS_PAL_MODE`|The alternate function mode for RTS |`7` | | `#define UART_RTS_PAL_MODE` | The alternate function mode for RTS | `7` |
## API :id=api ## API :id=api

View File

@ -208,9 +208,9 @@ The following `#define`s apply only to the `pwm` driver:
|`WS2812_PWM_DRIVER` |`PWMD2` |The PWM driver to use | |`WS2812_PWM_DRIVER` |`PWMD2` |The PWM driver to use |
|`WS2812_PWM_CHANNEL` |`2` |The PWM channel to use | |`WS2812_PWM_CHANNEL` |`2` |The PWM channel to use |
|`WS2812_PWM_PAL_MODE` |`2` |The pin alternative function to use | |`WS2812_PWM_PAL_MODE` |`2` |The pin alternative function to use |
|`WS2812_DMA_STREAM` |`STM32_DMA1_STREAM2`|The DMA Stream for `TIMx_UP` | |`WS2812_PWM_DMA_STREAM` |`STM32_DMA1_STREAM2`|The DMA Stream for `TIMx_UP` |
|`WS2812_DMA_CHANNEL` |`2` |The DMA Channel for `TIMx_UP` | |`WS2812_PWM_DMA_CHANNEL` |`2` |The DMA Channel for `TIMx_UP` |
|`WS2812_DMAMUX_ID` |*Not defined* |The DMAMUX configuration for `TIMx_UP` - only required if your MCU has a DMAMUX peripheral| |`WS2812_PWM_DMAMUX_ID` |*Not defined* |The DMAMUX configuration for `TIMx_UP` - only required if your MCU has a DMAMUX peripheral|
|`WS2812_PWM_COMPLEMENTARY_OUTPUT`|*Not defined* |Whether the PWM output is complementary (`TIMx_CHyN`) | |`WS2812_PWM_COMPLEMENTARY_OUTPUT`|*Not defined* |Whether the PWM output is complementary (`TIMx_CHyN`) |
?> Using a complementary timer output (`TIMx_CHyN`) is possible only for advanced-control timers (1, 8 and 20 on STM32), and the `STM32_PWM_USE_ADVANCED` option in `mcuconf.h` must be set to `TRUE`. Complementary outputs of general-purpose timers are not supported due to ChibiOS limitations. ?> Using a complementary timer output (`TIMx_CHyN`) is possible only for advanced-control timers (1, 8 and 20 on STM32), and the `STM32_PWM_USE_ADVANCED` option in `mcuconf.h` must be set to `TRUE`. Complementary outputs of general-purpose timers are not supported due to ChibiOS limitations.

View File

@ -188,7 +188,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
bool ready = false; bool ready = false;
do { do {
ready = readPin(BLUEFRUIT_LE_IRQ_PIN); ready = gpio_read_pin(BLUEFRUIT_LE_IRQ_PIN);
if (ready) { if (ready) {
break; break;
} }
@ -231,7 +231,7 @@ static void resp_buf_read_one(bool greedy) {
return; return;
} }
if (readPin(BLUEFRUIT_LE_IRQ_PIN)) { if (gpio_read_pin(BLUEFRUIT_LE_IRQ_PIN)) {
struct sdep_msg msg; struct sdep_msg msg;
again: again:
@ -242,7 +242,7 @@ static void resp_buf_read_one(bool greedy) {
dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send)); dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send));
} }
if (greedy && resp_buf.peek(last_send) && readPin(BLUEFRUIT_LE_IRQ_PIN)) { if (greedy && resp_buf.peek(last_send) && gpio_read_pin(BLUEFRUIT_LE_IRQ_PIN)) {
goto again; goto again;
} }
} }
@ -293,16 +293,16 @@ void bluefruit_le_init(void) {
state.configured = false; state.configured = false;
state.is_connected = false; state.is_connected = false;
setPinInput(BLUEFRUIT_LE_IRQ_PIN); gpio_set_pin_input(BLUEFRUIT_LE_IRQ_PIN);
spi_init(); spi_init();
// Perform a hardware reset // Perform a hardware reset
setPinOutput(BLUEFRUIT_LE_RST_PIN); gpio_set_pin_output(BLUEFRUIT_LE_RST_PIN);
writePinHigh(BLUEFRUIT_LE_RST_PIN); gpio_write_pin_high(BLUEFRUIT_LE_RST_PIN);
writePinLow(BLUEFRUIT_LE_RST_PIN); gpio_write_pin_low(BLUEFRUIT_LE_RST_PIN);
wait_ms(10); wait_ms(10);
writePinHigh(BLUEFRUIT_LE_RST_PIN); gpio_write_pin_high(BLUEFRUIT_LE_RST_PIN);
wait_ms(1000); // Give it a second to initialize wait_ms(1000); // Give it a second to initialize
@ -508,7 +508,7 @@ void bluefruit_le_task(void) {
resp_buf_read_one(true); resp_buf_read_one(true);
send_buf_send_one(SdepShortTimeout); send_buf_send_one(SdepShortTimeout);
if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(BLUEFRUIT_LE_IRQ_PIN)) { if (resp_buf.empty() && (state.event_flags & UsingEvents) && gpio_read_pin(BLUEFRUIT_LE_IRQ_PIN)) {
// Must be an event update // Must be an event update
if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) { if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) {
uint32_t mask = strtoul(resbuf, NULL, 16); uint32_t mask = strtoul(resbuf, NULL, 16);

View File

@ -57,8 +57,8 @@ void eeprom_driver_init(void) {
i2c_init(); i2c_init();
#if defined(EXTERNAL_EEPROM_WP_PIN) #if defined(EXTERNAL_EEPROM_WP_PIN)
/* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */ /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
writePin(EXTERNAL_EEPROM_WP_PIN, 1); gpio_write_pin(EXTERNAL_EEPROM_WP_PIN, 1);
setPinInputHigh(EXTERNAL_EEPROM_WP_PIN); gpio_set_pin_input_high(EXTERNAL_EEPROM_WP_PIN);
#endif #endif
} }
@ -100,8 +100,8 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
uintptr_t target_addr = (uintptr_t)addr; uintptr_t target_addr = (uintptr_t)addr;
#if defined(EXTERNAL_EEPROM_WP_PIN) #if defined(EXTERNAL_EEPROM_WP_PIN)
setPinOutput(EXTERNAL_EEPROM_WP_PIN); gpio_set_pin_output(EXTERNAL_EEPROM_WP_PIN);
writePin(EXTERNAL_EEPROM_WP_PIN, 0); gpio_write_pin(EXTERNAL_EEPROM_WP_PIN, 0);
#endif #endif
while (len > 0) { while (len > 0) {
@ -134,7 +134,7 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
#if defined(EXTERNAL_EEPROM_WP_PIN) #if defined(EXTERNAL_EEPROM_WP_PIN)
/* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */ /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
writePin(EXTERNAL_EEPROM_WP_PIN, 1); gpio_write_pin(EXTERNAL_EEPROM_WP_PIN, 1);
setPinInputHigh(EXTERNAL_EEPROM_WP_PIN); gpio_set_pin_input_high(EXTERNAL_EEPROM_WP_PIN);
#endif #endif
} }

View File

@ -0,0 +1,213 @@
// Copyright 2018 Jack Humbert <jack.humb@gmail.com>
// Copyright 2018-2023 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#include <stdint.h>
#include "encoder.h"
#include "gpio.h"
#include "keyboard.h"
#include "action.h"
#include "keycodes.h"
#include "wait.h"
#ifdef SPLIT_KEYBOARD
# include "split_util.h"
#endif
// for memcpy
#include <string.h>
#if !defined(ENCODER_RESOLUTIONS) && !defined(ENCODER_RESOLUTION)
# define ENCODER_RESOLUTION 4
#endif
#undef ENCODER_DEFAULT_PIN_API_IMPL
#if defined(ENCODERS_PAD_A) && defined(ENCODERS_PAD_B)
// Inform the quadrature driver that it needs to implement pin init/read functions
# define ENCODER_DEFAULT_PIN_API_IMPL
#endif
extern volatile bool isLeftHand;
__attribute__((weak)) void encoder_quadrature_init_pin(uint8_t index, bool pad_b);
__attribute__((weak)) uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b);
#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_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_B;
__attribute__((weak)) void encoder_wait_pullup_charge(void) {
wait_us(100);
}
__attribute__((weak)) void encoder_quadrature_init_pin(uint8_t index, bool pad_b) {
pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
if (pin != NO_PIN) {
gpio_set_pin_input_high(pin);
}
}
__attribute__((weak)) uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b) {
pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
if (pin != NO_PIN) {
return gpio_read_pin(pin) ? 1 : 0;
}
return 0;
}
#endif // ENCODER_DEFAULT_PIN_API_IMPL
#ifdef ENCODER_RESOLUTIONS
static uint8_t encoder_resolutions[NUM_ENCODERS] = ENCODER_RESOLUTIONS;
#endif
#ifndef ENCODER_DIRECTION_FLIP
# define ENCODER_CLOCKWISE true
# define ENCODER_COUNTER_CLOCKWISE false
#else
# define ENCODER_CLOCKWISE false
# define ENCODER_COUNTER_CLOCKWISE true
#endif
static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
static uint8_t encoder_state[NUM_ENCODERS] = {0};
static int8_t encoder_pulses[NUM_ENCODERS] = {0};
// encoder counts
static uint8_t thisCount;
#ifdef SPLIT_KEYBOARD
// encoder offsets for each hand
static uint8_t thisHand, thatHand;
// encoder counts for each hand
static uint8_t thatCount;
#endif
__attribute__((weak)) void encoder_quadrature_post_init_kb(void) {
extern void encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state);
// Unused normally, but can be used for things like setting up pin-change interrupts in keyboard code.
// During the interrupt, read the pins then call `encoder_handle_read()` with the pin states and it'll queue up an encoder event if needed.
}
void encoder_quadrature_post_init(void) {
#ifdef ENCODER_DEFAULT_PIN_API_IMPL
for (uint8_t i = 0; i < thisCount; i++) {
encoder_quadrature_init_pin(i, false);
encoder_quadrature_init_pin(i, true);
}
encoder_wait_pullup_charge();
for (uint8_t i = 0; i < thisCount; i++) {
encoder_state[i] = (encoder_quadrature_read_pin(i, false) << 0) | (encoder_quadrature_read_pin(i, true) << 1);
}
#else
memset(encoder_state, 0, sizeof(encoder_state));
#endif
encoder_quadrature_post_init_kb();
}
void encoder_driver_init(void) {
#ifdef SPLIT_KEYBOARD
thisHand = isLeftHand ? 0 : NUM_ENCODERS_LEFT;
thatHand = NUM_ENCODERS_LEFT - thisHand;
thisCount = isLeftHand ? NUM_ENCODERS_LEFT : NUM_ENCODERS_RIGHT;
thatCount = isLeftHand ? NUM_ENCODERS_RIGHT : NUM_ENCODERS_LEFT;
#else // SPLIT_KEYBOARD
thisCount = NUM_ENCODERS;
#endif
#ifdef ENCODER_TESTS
// Annoying that we have to clear out values during initialisation here, but
// because all the arrays are static locals, rerunning tests in the same
// executable doesn't reset any of these. Kinda crappy having test-only code
// here, but it's the simplest solution.
memset(encoder_state, 0, sizeof(encoder_state));
memset(encoder_pulses, 0, sizeof(encoder_pulses));
const pin_t encoders_pad_a_left[] = ENCODERS_PAD_A;
const pin_t encoders_pad_b_left[] = ENCODERS_PAD_B;
for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_left[i];
encoders_pad_b[i] = encoders_pad_b_left[i];
}
#endif
#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
// Re-initialise the pads if it's the right-hand side
if (!isLeftHand) {
const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT;
const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT;
for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_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)
// Encoder resolutions is defined differently in config.h, so concatenate
#if defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS)
# if defined(ENCODER_RESOLUTIONS_RIGHT)
static const uint8_t encoder_resolutions_right[NUM_ENCODERS_RIGHT] = ENCODER_RESOLUTIONS_RIGHT;
# else // defined(ENCODER_RESOLUTIONS_RIGHT)
static const uint8_t encoder_resolutions_right[NUM_ENCODERS_RIGHT] = ENCODER_RESOLUTIONS;
# endif // defined(ENCODER_RESOLUTIONS_RIGHT)
for (uint8_t i = 0; i < NUM_ENCODERS_RIGHT; i++) {
encoder_resolutions[NUM_ENCODERS_LEFT + i] = encoder_resolutions_right[i];
}
#endif // defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS)
encoder_quadrature_post_init();
}
static void encoder_handle_state_change(uint8_t index, uint8_t state) {
uint8_t i = index;
#ifdef SPLIT_KEYBOARD
index += thisHand;
#endif
#ifdef ENCODER_RESOLUTIONS
const uint8_t resolution = encoder_resolutions[index];
#else
const uint8_t resolution = ENCODER_RESOLUTION;
#endif
encoder_pulses[i] += encoder_LUT[state & 0xF];
#ifdef ENCODER_DEFAULT_POS
if ((encoder_pulses[i] >= resolution) || (encoder_pulses[i] <= -resolution) || ((state & 0x3) == ENCODER_DEFAULT_POS)) {
if (encoder_pulses[i] >= 1) {
#else
if (encoder_pulses[i] >= resolution) {
#endif
encoder_queue_event(index, ENCODER_COUNTER_CLOCKWISE);
}
#ifdef ENCODER_DEFAULT_POS
if (encoder_pulses[i] <= -1) {
#else
if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
#endif
encoder_queue_event(index, ENCODER_CLOCKWISE);
}
encoder_pulses[i] %= resolution;
#ifdef ENCODER_DEFAULT_POS
encoder_pulses[i] = 0;
}
#endif
}
void encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state) {
uint8_t state = pin_a_state | (pin_b_state << 1);
if ((encoder_state[index] & 0x3) != state) {
encoder_state[index] <<= 2;
encoder_state[index] |= state;
encoder_handle_state_change(index, encoder_state[index]);
}
}
__attribute__((weak)) void encoder_driver_task(void) {
for (uint8_t i = 0; i < thisCount; i++) {
encoder_quadrature_handle_read(i, encoder_quadrature_read_pin(i, false), encoder_quadrature_read_pin(i, true));
}
}

View File

@ -27,39 +27,39 @@ static const pin_t address_pins[ADDRESS_PIN_COUNT] = SN74X138_ADDRESS_PINS;
void sn74x138_init(void) { void sn74x138_init(void) {
for (int i = 0; i < ADDRESS_PIN_COUNT; i++) { for (int i = 0; i < ADDRESS_PIN_COUNT; i++) {
setPinOutput(address_pins[i]); gpio_set_pin_output(address_pins[i]);
writePinLow(address_pins[i]); gpio_write_pin_low(address_pins[i]);
} }
#if defined(SN74X138_E1_PIN) #if defined(SN74X138_E1_PIN)
setPinOutput(SN74X138_E1_PIN); gpio_set_pin_output(SN74X138_E1_PIN);
writePinHigh(SN74X138_E1_PIN); gpio_write_pin_high(SN74X138_E1_PIN);
#endif #endif
#if defined(SN74X138_E2_PIN) #if defined(SN74X138_E2_PIN)
setPinOutput(SN74X138_E2_PIN); gpio_set_pin_output(SN74X138_E2_PIN);
writePinHigh(SN74X138_E2_PIN); gpio_write_pin_high(SN74X138_E2_PIN);
#endif #endif
#if defined(SN74X138_E3_PIN) #if defined(SN74X138_E3_PIN)
setPinOutput(SN74X138_E3_PIN); gpio_set_pin_output(SN74X138_E3_PIN);
writePinLow(SN74X138_E3_PIN); gpio_write_pin_low(SN74X138_E3_PIN);
#endif #endif
} }
void sn74x138_set_enabled(bool enabled) { void sn74x138_set_enabled(bool enabled) {
#if defined(SN74X138_E1_PIN) #if defined(SN74X138_E1_PIN)
writePin(SN74X138_E1_PIN, !enabled); gpio_write_pin(SN74X138_E1_PIN, !enabled);
#endif #endif
#if defined(SN74X138_E2_PIN) #if defined(SN74X138_E2_PIN)
writePin(SN74X138_E2_PIN, !enabled); gpio_write_pin(SN74X138_E2_PIN, !enabled);
#endif #endif
#if defined(SN74X138_E3_PIN) #if defined(SN74X138_E3_PIN)
writePin(SN74X138_E3_PIN, enabled); gpio_write_pin(SN74X138_E3_PIN, enabled);
#endif #endif
} }
void sn74x138_set_addr(uint8_t address) { void sn74x138_set_addr(uint8_t address) {
for (int i = 0; i < ADDRESS_PIN_COUNT; i++) { for (int i = 0; i < ADDRESS_PIN_COUNT; i++) {
writePin(address_pins[i], address & (1 << i)); gpio_write_pin(address_pins[i], address & (1 << i));
} }
} }

View File

@ -27,32 +27,32 @@ static const pin_t address_pins[ADDRESS_PIN_COUNT] = SN74X154_ADDRESS_PINS;
void sn74x154_init(void) { void sn74x154_init(void) {
for (int i = 0; i < ADDRESS_PIN_COUNT; i++) { for (int i = 0; i < ADDRESS_PIN_COUNT; i++) {
setPinOutput(address_pins[i]); gpio_set_pin_output(address_pins[i]);
writePinLow(address_pins[i]); gpio_write_pin_low(address_pins[i]);
} }
#if defined(SN74X154_E0_PIN) #if defined(SN74X154_E0_PIN)
setPinOutput(SN74X154_E0_PIN); gpio_set_pin_output(SN74X154_E0_PIN);
writePinHigh(SN74X154_E0_PIN); gpio_write_pin_high(SN74X154_E0_PIN);
#endif #endif
#if defined(SN74X154_E1_PIN) #if defined(SN74X154_E1_PIN)
setPinOutput(SN74X154_E1_PIN); gpio_set_pin_output(SN74X154_E1_PIN);
writePinHigh(SN74X154_E1_PIN); gpio_write_pin_high(SN74X154_E1_PIN);
#endif #endif
} }
void sn74x154_set_enabled(bool enabled) { void sn74x154_set_enabled(bool enabled) {
#if defined(SN74X154_E0_PIN) #if defined(SN74X154_E0_PIN)
writePin(SN74X154_E0_PIN, !enabled); gpio_write_pin(SN74X154_E0_PIN, !enabled);
#endif #endif
#if defined(SN74X154_E1_PIN) #if defined(SN74X154_E1_PIN)
writePin(SN74X154_E1_PIN, !enabled); gpio_write_pin(SN74X154_E1_PIN, !enabled);
#endif #endif
} }
void sn74x154_set_addr(uint8_t address) { void sn74x154_set_addr(uint8_t address) {
for (int i = 0; i < ADDRESS_PIN_COUNT; i++) { for (int i = 0; i < ADDRESS_PIN_COUNT; i++) {
writePin(address_pins[i], address & (1 << i)); gpio_write_pin(address_pins[i], address & (1 << i));
} }
} }

View File

@ -61,7 +61,7 @@ void solenoid_set_dwell(uint8_t dwell) {
* @param index select which solenoid to check/stop * @param index select which solenoid to check/stop
*/ */
void solenoid_stop(uint8_t index) { void solenoid_stop(uint8_t index) {
writePin(solenoid_pads[index], !solenoid_active_state[index]); gpio_write_pin(solenoid_pads[index], !solenoid_active_state[index]);
solenoid_on[index] = false; solenoid_on[index] = false;
solenoid_buzzing[index] = false; solenoid_buzzing[index] = false;
} }
@ -78,7 +78,7 @@ void solenoid_fire(uint8_t index) {
solenoid_on[index] = true; solenoid_on[index] = true;
solenoid_buzzing[index] = true; solenoid_buzzing[index] = true;
solenoid_start[index] = timer_read(); solenoid_start[index] = timer_read();
writePin(solenoid_pads[index], solenoid_active_state[index]); gpio_write_pin(solenoid_pads[index], solenoid_active_state[index]);
} }
/** /**
@ -128,12 +128,12 @@ void solenoid_check(void) {
if ((elapsed[i] % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) { if ((elapsed[i] % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) {
if (!solenoid_buzzing[i]) { if (!solenoid_buzzing[i]) {
solenoid_buzzing[i] = true; solenoid_buzzing[i] = true;
writePin(solenoid_pads[i], solenoid_active_state[i]); gpio_write_pin(solenoid_pads[i], solenoid_active_state[i]);
} }
} else { } else {
if (solenoid_buzzing[i]) { if (solenoid_buzzing[i]) {
solenoid_buzzing[i] = false; solenoid_buzzing[i] = false;
writePin(solenoid_pads[i], !solenoid_active_state[i]); gpio_write_pin(solenoid_pads[i], !solenoid_active_state[i]);
} }
} }
} }
@ -156,8 +156,8 @@ void solenoid_setup(void) {
#else #else
solenoid_active_state[i] = high; solenoid_active_state[i] = high;
#endif #endif
writePin(solenoid_pads[i], !solenoid_active_state[i]); gpio_write_pin(solenoid_pads[i], !solenoid_active_state[i]);
setPinOutput(solenoid_pads[i]); gpio_set_pin_output(solenoid_pads[i]);
if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) { if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) {
solenoid_fire(i); solenoid_fire(i);
} }
@ -170,6 +170,6 @@ void solenoid_setup(void) {
*/ */
void solenoid_shutdown(void) { void solenoid_shutdown(void) {
for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) { for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) {
writePin(solenoid_pads[i], !solenoid_active_state[i]); gpio_write_pin(solenoid_pads[i], !solenoid_active_state[i]);
} }
} }

View File

@ -57,67 +57,67 @@ static const pin_t data_pins[4] = HD44780_DATA_PINS;
#define HD44780_ENABLE_DELAY_US 1 #define HD44780_ENABLE_DELAY_US 1
static void hd44780_latch(void) { static void hd44780_latch(void) {
writePinHigh(HD44780_E_PIN); gpio_write_pin_high(HD44780_E_PIN);
wait_us(HD44780_ENABLE_DELAY_US); wait_us(HD44780_ENABLE_DELAY_US);
writePinLow(HD44780_E_PIN); gpio_write_pin_low(HD44780_E_PIN);
} }
void hd44780_write(uint8_t data, bool isData) { void hd44780_write(uint8_t data, bool isData) {
writePin(HD44780_RS_PIN, isData); gpio_write_pin(HD44780_RS_PIN, isData);
writePinLow(HD44780_RW_PIN); gpio_write_pin_low(HD44780_RW_PIN);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
setPinOutput(data_pins[i]); gpio_set_pin_output(data_pins[i]);
} }
// Write high nibble // Write high nibble
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
writePin(data_pins[i], (data >> 4) & (1 << i)); gpio_write_pin(data_pins[i], (data >> 4) & (1 << i));
} }
hd44780_latch(); hd44780_latch();
// Write low nibble // Write low nibble
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
writePin(data_pins[i], data & (1 << i)); gpio_write_pin(data_pins[i], data & (1 << i));
} }
hd44780_latch(); hd44780_latch();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
writePinHigh(data_pins[i]); gpio_write_pin_high(data_pins[i]);
} }
} }
uint8_t hd44780_read(bool isData) { uint8_t hd44780_read(bool isData) {
uint8_t data = 0; uint8_t data = 0;
writePin(HD44780_RS_PIN, isData); gpio_write_pin(HD44780_RS_PIN, isData);
writePinHigh(HD44780_RW_PIN); gpio_write_pin_high(HD44780_RW_PIN);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
setPinInput(data_pins[i]); gpio_set_pin_input(data_pins[i]);
} }
writePinHigh(HD44780_E_PIN); gpio_write_pin_high(HD44780_E_PIN);
wait_us(HD44780_ENABLE_DELAY_US); wait_us(HD44780_ENABLE_DELAY_US);
// Read high nibble // Read high nibble
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
data |= (readPin(data_pins[i]) << i); data |= (gpio_read_pin(data_pins[i]) << i);
} }
data <<= 4; data <<= 4;
writePinLow(HD44780_E_PIN); gpio_write_pin_low(HD44780_E_PIN);
wait_us(HD44780_ENABLE_DELAY_US); wait_us(HD44780_ENABLE_DELAY_US);
writePinHigh(HD44780_E_PIN); gpio_write_pin_high(HD44780_E_PIN);
wait_us(HD44780_ENABLE_DELAY_US); wait_us(HD44780_ENABLE_DELAY_US);
// Read low nibble // Read low nibble
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
data |= (readPin(data_pins[i]) << i); data |= (gpio_read_pin(data_pins[i]) << i);
} }
writePinLow(HD44780_E_PIN); gpio_write_pin_low(HD44780_E_PIN);
return data; return data;
} }
@ -171,20 +171,20 @@ void hd44780_set_ddram_address(uint8_t address) {
} }
void hd44780_init(bool cursor, bool blink) { void hd44780_init(bool cursor, bool blink) {
setPinOutput(HD44780_RS_PIN); gpio_set_pin_output(HD44780_RS_PIN);
setPinOutput(HD44780_RW_PIN); gpio_set_pin_output(HD44780_RW_PIN);
setPinOutput(HD44780_E_PIN); gpio_set_pin_output(HD44780_E_PIN);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
setPinOutput(data_pins[i]); gpio_set_pin_output(data_pins[i]);
} }
wait_ms(HD44780_INIT_DELAY_MS); wait_ms(HD44780_INIT_DELAY_MS);
// Manually configure for 4-bit mode - can't use hd44780_command() yet // Manually configure for 4-bit mode - can't use hd44780_command() yet
// HD44780U datasheet, Fig. 24 (p46) // HD44780U datasheet, Fig. 24 (p46)
writePinHigh(data_pins[0]); // Function set gpio_write_pin_high(data_pins[0]); // Function set
writePinHigh(data_pins[1]); // DL = 1 gpio_write_pin_high(data_pins[1]); // DL = 1
hd44780_latch(); hd44780_latch();
wait_ms(5); wait_ms(5);
// Send again // Send again
@ -194,7 +194,7 @@ void hd44780_init(bool cursor, bool blink) {
hd44780_latch(); hd44780_latch();
wait_us(64); wait_us(64);
writePinLow(data_pins[0]); // DL = 0 gpio_write_pin_low(data_pins[0]); // DL = 0
hd44780_latch(); hd44780_latch();
wait_us(64); wait_us(64);

View File

@ -92,10 +92,10 @@ static void InvertCharacter(uint8_t *cursor) {
} }
bool st7565_init(display_rotation_t rotation) { bool st7565_init(display_rotation_t rotation) {
setPinOutput(ST7565_A0_PIN); gpio_set_pin_output(ST7565_A0_PIN);
writePinHigh(ST7565_A0_PIN); gpio_write_pin_high(ST7565_A0_PIN);
setPinOutput(ST7565_RST_PIN); gpio_set_pin_output(ST7565_RST_PIN);
writePinHigh(ST7565_RST_PIN); gpio_write_pin_high(ST7565_RST_PIN);
st7565_rotation = st7565_init_user(rotation); st7565_rotation = st7565_init_user(rotation);
@ -488,18 +488,18 @@ void st7565_task(void) {
__attribute__((weak)) void st7565_task_user(void) {} __attribute__((weak)) void st7565_task_user(void) {}
void st7565_reset(void) { void st7565_reset(void) {
writePinLow(ST7565_RST_PIN); gpio_write_pin_low(ST7565_RST_PIN);
wait_ms(20); wait_ms(20);
writePinHigh(ST7565_RST_PIN); gpio_write_pin_high(ST7565_RST_PIN);
wait_ms(20); wait_ms(20);
} }
spi_status_t st7565_send_cmd(uint8_t cmd) { spi_status_t st7565_send_cmd(uint8_t cmd) {
writePinLow(ST7565_A0_PIN); gpio_write_pin_low(ST7565_A0_PIN);
return spi_write(cmd); return spi_write(cmd);
} }
spi_status_t st7565_send_data(uint8_t *data, uint16_t length) { spi_status_t st7565_send_data(uint8_t *data, uint16_t length) {
writePinHigh(ST7565_A0_PIN); gpio_write_pin_high(ST7565_A0_PIN);
return spi_transmit(data, length); return spi_transmit(data, length);
} }

View File

@ -43,14 +43,14 @@
} \ } \
} while (0) } while (0)
#define APA102_SEND_BIT(byte, bit) \ #define APA102_SEND_BIT(byte, bit) \
do { \ do { \
writePin(APA102_DI_PIN, (byte >> bit) & 1); \ gpio_write_pin(APA102_DI_PIN, (byte >> bit) & 1); \
io_wait; \ io_wait; \
writePinHigh(APA102_CI_PIN); \ gpio_write_pin_high(APA102_CI_PIN); \
io_wait; \ io_wait; \
writePinLow(APA102_CI_PIN); \ gpio_write_pin_low(APA102_CI_PIN); \
io_wait; \ io_wait; \
} while (0) } while (0)
uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS; uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS;
@ -114,11 +114,11 @@ static void apa102_send_frame(uint8_t red, uint8_t green, uint8_t blue, uint8_t
} }
void apa102_init(void) { void apa102_init(void) {
setPinOutput(APA102_DI_PIN); gpio_set_pin_output(APA102_DI_PIN);
setPinOutput(APA102_CI_PIN); gpio_set_pin_output(APA102_CI_PIN);
writePinLow(APA102_DI_PIN); gpio_write_pin_low(APA102_DI_PIN);
writePinLow(APA102_CI_PIN); gpio_write_pin_low(APA102_CI_PIN);
} }
void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds) { void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds) {

View File

@ -114,8 +114,8 @@ void aw20216s_init_drivers(void) {
spi_init(); spi_init();
#if defined(AW20216S_EN_PIN) #if defined(AW20216S_EN_PIN)
setPinOutput(AW20216S_EN_PIN); gpio_set_pin_output(AW20216S_EN_PIN);
writePinHigh(AW20216S_EN_PIN); gpio_write_pin_high(AW20216S_EN_PIN);
#endif #endif
aw20216s_init(AW20216S_CS_PIN_1); aw20216s_init(AW20216S_CS_PIN_1);

View File

@ -68,8 +68,8 @@ void is31fl3218_init(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3218_SDB_PIN) #if defined(IS31FL3218_SDB_PIN)
setPinOutput(IS31FL3218_SDB_PIN); gpio_set_pin_output(IS31FL3218_SDB_PIN);
writePinHigh(IS31FL3218_SDB_PIN); gpio_write_pin_high(IS31FL3218_SDB_PIN);
#endif #endif
// In case we ever want to reinitialize (?) // In case we ever want to reinitialize (?)

View File

@ -68,8 +68,8 @@ void is31fl3218_init(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3218_SDB_PIN) #if defined(IS31FL3218_SDB_PIN)
setPinOutput(IS31FL3218_SDB_PIN); gpio_set_pin_output(IS31FL3218_SDB_PIN);
writePinHigh(IS31FL3218_SDB_PIN); gpio_write_pin_high(IS31FL3218_SDB_PIN);
#endif #endif
// In case we ever want to reinitialize (?) // In case we ever want to reinitialize (?)

View File

@ -18,6 +18,7 @@
#include "is31fl3729-mono.h" #include "is31fl3729-mono.h"
#include "i2c_master.h" #include "i2c_master.h"
#include "gpio.h"
#include "wait.h" #include "wait.h"
#define IS31FL3729_PWM_REGISTER_COUNT 143 #define IS31FL3729_PWM_REGISTER_COUNT 143
@ -39,26 +40,43 @@
# define IS31FL3729_GLOBAL_CURRENT 0x40 # define IS31FL3729_GLOBAL_CURRENT 0x40
#endif #endif
#ifndef IS31FL3729_PULLDOWNUP #ifndef IS31FL3729_SW_PULLDOWN
# define IS31FL3729_PULLDOWNUP 0x33 # define IS31FL3729_SW_PULLDOWN IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF
#endif
#ifndef IS31FL3729_CS_PULLUP
# define IS31FL3729_CS_PULLUP IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF
#endif #endif
#ifndef IS31FL3729_SPREAD_SPECTRUM #ifndef IS31FL3729_SPREAD_SPECTRUM
# define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SSP_DISABLE # define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SPREAD_SPECTRUM_DISABLE
#endif #endif
#ifndef IS31FL3729_SPREAD_SPECTRUM_RANGE #ifndef IS31FL3729_SPREAD_SPECTRUM_RANGE
# define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_RNG_5_PERCENT # define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT
#endif #endif
#ifndef IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME #ifndef IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME
# define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_CLT_1980_US # define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US
#endif #endif
#ifndef IS31FL3729_PWM_FREQUENCY #ifndef IS31FL3729_PWM_FREQUENCY
# define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ # define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ
#endif #endif
const uint8_t i2c_addresses[IS31FL3729_DRIVER_COUNT] = {
IS31FL3729_I2C_ADDRESS_1,
#ifdef IS31FL3729_I2C_ADDRESS_2
IS31FL3729_I2C_ADDRESS_2,
# ifdef IS31FL3729_I2C_ADDRESS_3
IS31FL3729_I2C_ADDRESS_3,
# ifdef IS31FL3729_I2C_ADDRESS_4
IS31FL3729_I2C_ADDRESS_4,
# endif
# endif
#endif
};
// These buffers match the PWM & scaling registers. // These buffers match the PWM & scaling registers.
// Storing them like this is optimal for I2C transfers to the registers. // Storing them like this is optimal for I2C transfers to the registers.
typedef struct is31fl3729_driver_t { typedef struct is31fl3729_driver_t {
@ -75,27 +93,27 @@ is31fl3729_driver_t driver_buffers[IS31FL3729_DRIVER_COUNT] = {{
.scaling_buffer_dirty = false, .scaling_buffer_dirty = false,
}}; }};
void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data) { void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data) {
#if IS31FL3729_I2C_PERSISTENCE > 0 #if IS31FL3729_I2C_PERSISTENCE > 0
for (uint8_t i = 0; i < IS31FL3729_I2C_PERSISTENCE; i++) { for (uint8_t i = 0; i < IS31FL3729_I2C_PERSISTENCE; i++) {
if (i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; if (i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
} }
#else #else
i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT); i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT);
#endif #endif
} }
void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) { void is31fl3729_write_pwm_buffer(uint8_t index) {
// Transmit PWM registers in 9 transfers of 16 bytes. // Transmit PWM registers in 11 transfers of 13 bytes.
// Iterate over the pwm_buffer contents at 16 byte intervals. // Iterate over the pwm_buffer contents at 13 byte intervals.
for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 16) { for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 13) {
#if IS31FL3729_I2C_PERSISTENCE > 0 #if IS31FL3729_I2C_PERSISTENCE > 0
for (uint8_t j = 0; j < IS31FL3729_I2C_PERSISTENCE; j++) { for (uint8_t j = 0; j < IS31FL3729_I2C_PERSISTENCE; j++) {
if (i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; if (i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
} }
#else #else
i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT); i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT);
#endif #endif
} }
} }
@ -103,53 +121,35 @@ void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) {
void is31fl3729_init_drivers(void) { void is31fl3729_init_drivers(void) {
i2c_init(); i2c_init();
is31fl3729_init(IS31FL3729_I2C_ADDRESS_1); #if defined(IS31FL3729_SDB_PIN)
#if defined(IS31FL3729_I2C_ADDRESS_2) gpio_set_pin_output(IS31FL3729_SDB_PIN);
is31fl3729_init(IS31FL3729_I2C_ADDRESS_2); gpio_write_pin_high(IS31FL3729_SDB_PIN);
# if defined(IS31FL3729_I2C_ADDRESS_3)
is31fl3729_init(IS31FL3729_I2C_ADDRESS_3);
# if defined(IS31FL3729_I2C_ADDRESS_4)
is31fl3729_init(IS31FL3729_I2C_ADDRESS_4);
# endif
# endif
#endif #endif
for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) {
is31fl3729_init(i);
}
for (int i = 0; i < IS31FL3729_LED_COUNT; i++) { for (int i = 0; i < IS31FL3729_LED_COUNT; i++) {
is31fl3729_set_scaling_register(i, 0xFF); is31fl3729_set_scaling_register(i, 0xFF);
} }
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_1, 0); for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) {
#if defined(IS31FL3729_I2C_ADDRESS_2) is31fl3729_update_scaling_registers(i);
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_2, 1); }
# if defined(IS31FL3729_I2C_ADDRESS_3)
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_3, 2);
# if defined(IS31FL3729_I2C_ADDRESS_4)
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_4, 3);
# endif
# endif
#endif
} }
void is31fl3729_init(uint8_t addr) { void is31fl3729_init(uint8_t index) {
// In order to avoid the LEDs being driven with garbage data // In order to avoid the LEDs being driven with garbage data
// in the LED driver's PWM registers, shutdown is enabled last. // in the LED driver's PWM registers, shutdown is enabled last.
// Set up the mode and other settings, clear the PWM registers, // Set up the mode and other settings, clear the PWM registers,
// then disable software shutdown. // then disable software shutdown.
// Set Pull up & Down for SWx CSy is31fl3729_write_register(index, IS31FL3729_REG_PULLDOWNUP, ((IS31FL3729_SW_PULLDOWN & 0b111) << 4) | (IS31FL3729_CS_PULLUP & 0b111));
is31fl3729_write_register(addr, IS31FL3729_REG_PULLDOWNUP, IS31FL3729_PULLDOWNUP); is31fl3729_write_register(index, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11));
is31fl3729_write_register(index, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY);
// Set Spread Spectrum Register if applicable is31fl3729_write_register(index, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT);
is31fl3729_write_register(addr, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11)); is31fl3729_write_register(index, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION);
// Set PWM Frequency Register if applicable
is31fl3729_write_register(addr, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY);
// Set Golbal Current Control Register
is31fl3729_write_register(addr, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT);
// Set to Normal operation
is31fl3729_write_register(addr, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION);
// Wait 10ms to ensure the device has woken up. // Wait 10ms to ensure the device has woken up.
wait_ms(10); wait_ms(10);
@ -188,18 +188,18 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t value) {
driver_buffers[led.driver].scaling_buffer_dirty = true; driver_buffers[led.driver].scaling_buffer_dirty = true;
} }
void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index) { void is31fl3729_update_pwm_buffers(uint8_t index) {
if (driver_buffers[index].pwm_buffer_dirty) { if (driver_buffers[index].pwm_buffer_dirty) {
is31fl3729_write_pwm_buffer(addr, index); is31fl3729_write_pwm_buffer(index);
driver_buffers[index].pwm_buffer_dirty = false; driver_buffers[index].pwm_buffer_dirty = false;
} }
} }
void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) { void is31fl3729_update_scaling_registers(uint8_t index) {
if (driver_buffers[index].scaling_buffer_dirty) { if (driver_buffers[index].scaling_buffer_dirty) {
for (uint8_t i = 0; i < IS31FL3729_SCALING_REGISTER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3729_SCALING_REGISTER_COUNT; i++) {
is31fl3729_write_register(addr, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]); is31fl3729_write_register(index, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]);
} }
driver_buffers[index].scaling_buffer_dirty = false; driver_buffers[index].scaling_buffer_dirty = false;
@ -207,14 +207,7 @@ void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) {
} }
void is31fl3729_flush(void) { void is31fl3729_flush(void) {
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_1, 0); for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) {
#if defined(IS31FL3729_I2C_ADDRESS_2) is31fl3729_update_pwm_buffers(i);
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_2, 1); }
# if defined(IS31FL3729_I2C_ADDRESS_3)
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_3, 2);
# if defined(IS31FL3729_I2C_ADDRESS_4)
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_4, 3);
# endif
# endif
#endif
} }

View File

@ -23,6 +23,7 @@
#include "progmem.h" #include "progmem.h"
#include "util.h" #include "util.h"
#define IS31FL3729_REG_PWM 0x01
#define IS31FL3729_REG_SCALING 0x90 #define IS31FL3729_REG_SCALING 0x90
#define IS31FL3729_REG_CONFIGURATION 0xA0 #define IS31FL3729_REG_CONFIGURATION 0xA0
#define IS31FL3729_REG_GLOBAL_CURRENT 0xA1 #define IS31FL3729_REG_GLOBAL_CURRENT 0xA1
@ -58,8 +59,8 @@ typedef struct is31fl3729_led_t {
extern const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT]; extern const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT];
void is31fl3729_init_drivers(void); void is31fl3729_init_drivers(void);
void is31fl3729_init(uint8_t addr); void is31fl3729_init(uint8_t index);
void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data); void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data);
void is31fl3729_set_value(int index, uint8_t value); void is31fl3729_set_value(int index, uint8_t value);
void is31fl3729_set_value_all(uint8_t value); void is31fl3729_set_value_all(uint8_t value);
@ -70,26 +71,42 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t value);
// (eg. from a timer interrupt). // (eg. from a timer interrupt).
// Call this while idle (in between matrix scans). // Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer. // If the buffer is dirty, it will update the driver with the buffer.
void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index); void is31fl3729_update_pwm_buffers(uint8_t index);
void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index); void is31fl3729_update_scaling_registers(uint8_t index);
void is31fl3729_flush(void); void is31fl3729_flush(void);
// Noise reduction using Spread Spectrum register #define IS31FL3729_SW_PULLDOWN_0_OHM 0b000
#define IS31FL3729_SSP_DISABLE 0b0 #define IS31FL3729_SW_PULLDOWN_0K5_OHM_SW_OFF 0b001
#define IS31FL3729_SSP_ENABLE 0b1 #define IS31FL3729_SW_PULLDOWN_1K_OHM_SW_OFF 0b010
#define IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF 0b011
#define IS31FL3729_SW_PULLDOWN_1K_OHM 0b100
#define IS31FL3729_SW_PULLDOWN_2K_OHM 0b101
#define IS31FL3729_SW_PULLDOWN_4K_OHM 0b110
#define IS31FL3729_SW_PULLDOWN_8K_OHM 0b111
#define IS31FL3729_RNG_5_PERCENT 0b00 #define IS31FL3729_CS_PULLUP_0_OHM 0b000
#define IS31FL3729_RNG_15_PERCENT 0b01 #define IS31FL3729_CS_PULLUP_0K5_OHM_CS_OFF 0b001
#define IS31FL3729_RNG_24_PERCENT 0b10 #define IS31FL3729_CS_PULLUP_1K_OHM_CS_OFF 0b010
#define IS31FL3729_RNG_34_PERCENT 0b11 #define IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF 0b011
#define IS31FL3729_CS_PULLUP_1K_OHM 0b100
#define IS31FL3729_CS_PULLUP_2K_OHM 0b101
#define IS31FL3729_CS_PULLUP_4K_OHM 0b110
#define IS31FL3729_CS_PULLUP_8K_OHM 0b111
#define IS31FL3729_CLT_1980_US 0b00 #define IS31FL3729_SPREAD_SPECTRUM_DISABLE 0b0
#define IS31FL3729_CLT_1200_US 0b01 #define IS31FL3729_SPREAD_SPECTRUM_ENABLE 0b1
#define IS31FL3729_CLT_820_US 0b10
#define IS31FL3729_CLT_660_US 0b11 #define IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT 0b00
#define IS31FL3729_SPREAD_SPECTRUM_RANGE_15_PERCENT 0b01
#define IS31FL3729_SPREAD_SPECTRUM_RANGE_24_PERCENT 0b10
#define IS31FL3729_SPREAD_SPECTRUM_RANGE_34_PERCENT 0b11
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US 0b00
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1200_US 0b01
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_820_US 0b10
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_660_US 0b11
// Noise reduction using PWM Frequency register
#define IS31FL3729_PWM_FREQUENCY_55K_HZ 0b000 #define IS31FL3729_PWM_FREQUENCY_55K_HZ 0b000
#define IS31FL3729_PWM_FREQUENCY_32K_HZ 0b001 #define IS31FL3729_PWM_FREQUENCY_32K_HZ 0b001
#define IS31FL3729_PWM_FREQUENCY_4K_HZ 0b010 #define IS31FL3729_PWM_FREQUENCY_4K_HZ 0b010
@ -99,7 +116,6 @@ void is31fl3729_flush(void);
#define IS31FL3729_PWM_FREQUENCY_250_HZ 0b110 #define IS31FL3729_PWM_FREQUENCY_250_HZ 0b110
#define IS31FL3729_PWM_FREQUENCY_80K_HZ 0b111 #define IS31FL3729_PWM_FREQUENCY_80K_HZ 0b111
// Change SWx Setting using Configuration register
#define IS31FL3729_CONFIG_SWS_15_9 0x01 // 15 CS x 9 SW matrix #define IS31FL3729_CONFIG_SWS_15_9 0x01 // 15 CS x 9 SW matrix
#define IS31FL3729_CONFIG_SWS_16_8 0x11 // 16 CS x 8 SW matrix #define IS31FL3729_CONFIG_SWS_16_8 0x11 // 16 CS x 8 SW matrix
#define IS31FL3729_CONFIG_SWS_16_7 0x21 // 16 CS x 7 SW matrix #define IS31FL3729_CONFIG_SWS_16_7 0x21 // 16 CS x 7 SW matrix
@ -109,157 +125,154 @@ void is31fl3729_flush(void);
#define IS31FL3729_CONFIG_SWS_16_3 0x61 // 16 CS x 3 SW matrix #define IS31FL3729_CONFIG_SWS_16_3 0x61 // 16 CS x 3 SW matrix
#define IS31FL3729_CONFIG_SWS_16_2 0x71 // 16 CS x 2 SW matrix #define IS31FL3729_CONFIG_SWS_16_2 0x71 // 16 CS x 2 SW matrix
// Map CS SW locations to order in PWM / Scaling buffers #define SW1_CS1 0x00
// This matches the ORDER in the Datasheet Register not the POSITION #define SW1_CS2 0x01
// It will always count from 0x01 to (ISSI_MAX_LEDS - 1) #define SW1_CS3 0x02
#define SW1_CS1 0x01 #define SW1_CS4 0x03
#define SW1_CS2 0x02 #define SW1_CS5 0x04
#define SW1_CS3 0x03 #define SW1_CS6 0x05
#define SW1_CS4 0x04 #define SW1_CS7 0x06
#define SW1_CS5 0x05 #define SW1_CS8 0x07
#define SW1_CS6 0x06 #define SW1_CS9 0x08
#define SW1_CS7 0x07 #define SW1_CS10 0x09
#define SW1_CS8 0x08 #define SW1_CS11 0x0A
#define SW1_CS9 0x09 #define SW1_CS12 0x0B
#define SW1_CS10 0x0A #define SW1_CS13 0x0C
#define SW1_CS11 0x0B #define SW1_CS14 0x0D
#define SW1_CS12 0x0C #define SW1_CS15 0x0E
#define SW1_CS13 0x0D #define SW1_CS16 0x0F
#define SW1_CS14 0x0E
#define SW1_CS15 0x0F
#define SW1_CS16 0x10
#define SW2_CS1 0x11 #define SW2_CS1 0x10
#define SW2_CS2 0x12 #define SW2_CS2 0x11
#define SW2_CS3 0x13 #define SW2_CS3 0x12
#define SW2_CS4 0x14 #define SW2_CS4 0x13
#define SW2_CS5 0x15 #define SW2_CS5 0x14
#define SW2_CS6 0x16 #define SW2_CS6 0x15
#define SW2_CS7 0x17 #define SW2_CS7 0x16
#define SW2_CS8 0x18 #define SW2_CS8 0x17
#define SW2_CS9 0x19 #define SW2_CS9 0x18
#define SW2_CS10 0x1A #define SW2_CS10 0x19
#define SW2_CS11 0x1B #define SW2_CS11 0x1A
#define SW2_CS12 0x1C #define SW2_CS12 0x1B
#define SW2_CS13 0x1D #define SW2_CS13 0x1C
#define SW2_CS14 0x1E #define SW2_CS14 0x1D
#define SW2_CS15 0x1F #define SW2_CS15 0x1E
#define SW2_CS16 0x20 #define SW2_CS16 0x1F
#define SW3_CS1 0x21 #define SW3_CS1 0x20
#define SW3_CS2 0x22 #define SW3_CS2 0x21
#define SW3_CS3 0x23 #define SW3_CS3 0x22
#define SW3_CS4 0x24 #define SW3_CS4 0x23
#define SW3_CS5 0x25 #define SW3_CS5 0x24
#define SW3_CS6 0x26 #define SW3_CS6 0x25
#define SW3_CS7 0x27 #define SW3_CS7 0x26
#define SW3_CS8 0x28 #define SW3_CS8 0x27
#define SW3_CS9 0x29 #define SW3_CS9 0x28
#define SW3_CS10 0x2A #define SW3_CS10 0x29
#define SW3_CS11 0x2B #define SW3_CS11 0x2A
#define SW3_CS12 0x2C #define SW3_CS12 0x2B
#define SW3_CS13 0x2D #define SW3_CS13 0x2C
#define SW3_CS14 0x2E #define SW3_CS14 0x2D
#define SW3_CS15 0x2F #define SW3_CS15 0x2E
#define SW3_CS16 0x30 #define SW3_CS16 0x2F
#define SW4_CS1 0x31 #define SW4_CS1 0x30
#define SW4_CS2 0x32 #define SW4_CS2 0x31
#define SW4_CS3 0x33 #define SW4_CS3 0x32
#define SW4_CS4 0x34 #define SW4_CS4 0x33
#define SW4_CS5 0x35 #define SW4_CS5 0x34
#define SW4_CS6 0x36 #define SW4_CS6 0x35
#define SW4_CS7 0x37 #define SW4_CS7 0x36
#define SW4_CS8 0x38 #define SW4_CS8 0x37
#define SW4_CS9 0x39 #define SW4_CS9 0x38
#define SW4_CS10 0x3A #define SW4_CS10 0x39
#define SW4_CS11 0x3B #define SW4_CS11 0x3A
#define SW4_CS12 0x3C #define SW4_CS12 0x3B
#define SW4_CS13 0x3D #define SW4_CS13 0x3C
#define SW4_CS14 0x3E #define SW4_CS14 0x3D
#define SW4_CS15 0x3F #define SW4_CS15 0x3E
#define SW4_CS16 0x40 #define SW4_CS16 0x3F
#define SW5_CS1 0x41 #define SW5_CS1 0x40
#define SW5_CS2 0x42 #define SW5_CS2 0x41
#define SW5_CS3 0x43 #define SW5_CS3 0x42
#define SW5_CS4 0x44 #define SW5_CS4 0x43
#define SW5_CS5 0x45 #define SW5_CS5 0x44
#define SW5_CS6 0x46 #define SW5_CS6 0x45
#define SW5_CS7 0x47 #define SW5_CS7 0x46
#define SW5_CS8 0x48 #define SW5_CS8 0x47
#define SW5_CS9 0x49 #define SW5_CS9 0x48
#define SW5_CS10 0x4A #define SW5_CS10 0x49
#define SW5_CS11 0x4B #define SW5_CS11 0x4A
#define SW5_CS12 0x4C #define SW5_CS12 0x4B
#define SW5_CS13 0x4D #define SW5_CS13 0x4C
#define SW5_CS14 0x4E #define SW5_CS14 0x4D
#define SW5_CS15 0x4F #define SW5_CS15 0x4E
#define SW5_CS16 0x50 #define SW5_CS16 0x4F
#define SW6_CS1 0x51 #define SW6_CS1 0x50
#define SW6_CS2 0x52 #define SW6_CS2 0x51
#define SW6_CS3 0x53 #define SW6_CS3 0x52
#define SW6_CS4 0x54 #define SW6_CS4 0x53
#define SW6_CS5 0x55 #define SW6_CS5 0x54
#define SW6_CS6 0x56 #define SW6_CS6 0x55
#define SW6_CS7 0x57 #define SW6_CS7 0x56
#define SW6_CS8 0x58 #define SW6_CS8 0x57
#define SW6_CS9 0x59 #define SW6_CS9 0x58
#define SW6_CS10 0x5A #define SW6_CS10 0x59
#define SW6_CS11 0x5B #define SW6_CS11 0x5A
#define SW6_CS12 0x5C #define SW6_CS12 0x5B
#define SW6_CS13 0x5D #define SW6_CS13 0x5C
#define SW6_CS14 0x5E #define SW6_CS14 0x5D
#define SW6_CS15 0x5F #define SW6_CS15 0x5E
#define SW6_CS16 0x60 #define SW6_CS16 0x5F
#define SW7_CS1 0x61 #define SW7_CS1 0x60
#define SW7_CS2 0x62 #define SW7_CS2 0x61
#define SW7_CS3 0x63 #define SW7_CS3 0x62
#define SW7_CS4 0x64 #define SW7_CS4 0x63
#define SW7_CS5 0x65 #define SW7_CS5 0x64
#define SW7_CS6 0x66 #define SW7_CS6 0x65
#define SW7_CS7 0x67 #define SW7_CS7 0x66
#define SW7_CS8 0x68 #define SW7_CS8 0x67
#define SW7_CS9 0x69 #define SW7_CS9 0x68
#define SW7_CS10 0x6A #define SW7_CS10 0x69
#define SW7_CS11 0x6B #define SW7_CS11 0x6A
#define SW7_CS12 0x6C #define SW7_CS12 0x6B
#define SW7_CS13 0x6D #define SW7_CS13 0x6C
#define SW7_CS14 0x6E #define SW7_CS14 0x6D
#define SW7_CS15 0x6F #define SW7_CS15 0x6E
#define SW7_CS16 0x70 #define SW7_CS16 0x6F
#define SW8_CS1 0x71 #define SW8_CS1 0x70
#define SW8_CS2 0x72 #define SW8_CS2 0x71
#define SW8_CS3 0x73 #define SW8_CS3 0x72
#define SW8_CS4 0x74 #define SW8_CS4 0x73
#define SW8_CS5 0x75 #define SW8_CS5 0x74
#define SW8_CS6 0x76 #define SW8_CS6 0x75
#define SW8_CS7 0x77 #define SW8_CS7 0x76
#define SW8_CS8 0x78 #define SW8_CS8 0x77
#define SW8_CS9 0x79 #define SW8_CS9 0x78
#define SW8_CS10 0x7A #define SW8_CS10 0x79
#define SW8_CS11 0x7B #define SW8_CS11 0x7A
#define SW8_CS12 0x7C #define SW8_CS12 0x7B
#define SW8_CS13 0x7D #define SW8_CS13 0x7C
#define SW8_CS14 0x7E #define SW8_CS14 0x7D
#define SW8_CS15 0x7F #define SW8_CS15 0x7E
#define SW8_CS16 0x80 #define SW8_CS16 0x7F
#define SW9_CS1 0x81 #define SW9_CS1 0x80
#define SW9_CS2 0x82 #define SW9_CS2 0x81
#define SW9_CS3 0x83 #define SW9_CS3 0x82
#define SW9_CS4 0x84 #define SW9_CS4 0x83
#define SW9_CS5 0x85 #define SW9_CS5 0x84
#define SW9_CS6 0x86 #define SW9_CS6 0x85
#define SW9_CS7 0x87 #define SW9_CS7 0x86
#define SW9_CS8 0x88 #define SW9_CS8 0x87
#define SW9_CS9 0x89 #define SW9_CS9 0x88
#define SW9_CS10 0x8A #define SW9_CS10 0x89
#define SW9_CS11 0x8B #define SW9_CS11 0x8A
#define SW9_CS12 0x8C #define SW9_CS12 0x8B
#define SW9_CS13 0x8D #define SW9_CS13 0x8C
#define SW9_CS14 0x8E #define SW9_CS14 0x8D
#define SW9_CS15 0x8F #define SW9_CS15 0x8E

View File

@ -18,6 +18,7 @@
#include "is31fl3729.h" #include "is31fl3729.h"
#include "i2c_master.h" #include "i2c_master.h"
#include "gpio.h"
#include "wait.h" #include "wait.h"
#define IS31FL3729_PWM_REGISTER_COUNT 143 #define IS31FL3729_PWM_REGISTER_COUNT 143
@ -39,26 +40,43 @@
# define IS31FL3729_GLOBAL_CURRENT 0x40 # define IS31FL3729_GLOBAL_CURRENT 0x40
#endif #endif
#ifndef IS31FL3729_PULLDOWNUP #ifndef IS31FL3729_SW_PULLDOWN
# define IS31FL3729_PULLDOWNUP 0x33 # define IS31FL3729_SW_PULLDOWN IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF
#endif
#ifndef IS31FL3729_CS_PULLUP
# define IS31FL3729_CS_PULLUP IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF
#endif #endif
#ifndef IS31FL3729_SPREAD_SPECTRUM #ifndef IS31FL3729_SPREAD_SPECTRUM
# define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SSP_DISABLE # define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SPREAD_SPECTRUM_DISABLE
#endif #endif
#ifndef IS31FL3729_SPREAD_SPECTRUM_RANGE #ifndef IS31FL3729_SPREAD_SPECTRUM_RANGE
# define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_RNG_5_PERCENT # define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT
#endif #endif
#ifndef IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME #ifndef IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME
# define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_CLT_1980_US # define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US
#endif #endif
#ifndef IS31FL3729_PWM_FREQUENCY #ifndef IS31FL3729_PWM_FREQUENCY
# define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ # define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ
#endif #endif
const uint8_t i2c_addresses[IS31FL3729_DRIVER_COUNT] = {
IS31FL3729_I2C_ADDRESS_1,
#ifdef IS31FL3729_I2C_ADDRESS_2
IS31FL3729_I2C_ADDRESS_2,
# ifdef IS31FL3729_I2C_ADDRESS_3
IS31FL3729_I2C_ADDRESS_3,
# ifdef IS31FL3729_I2C_ADDRESS_4
IS31FL3729_I2C_ADDRESS_4,
# endif
# endif
#endif
};
// These buffers match the PWM & scaling registers. // These buffers match the PWM & scaling registers.
// Storing them like this is optimal for I2C transfers to the registers. // Storing them like this is optimal for I2C transfers to the registers.
typedef struct is31fl3729_driver_t { typedef struct is31fl3729_driver_t {
@ -75,27 +93,27 @@ is31fl3729_driver_t driver_buffers[IS31FL3729_DRIVER_COUNT] = {{
.scaling_buffer_dirty = false, .scaling_buffer_dirty = false,
}}; }};
void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data) { void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data) {
#if IS31FL3729_I2C_PERSISTENCE > 0 #if IS31FL3729_I2C_PERSISTENCE > 0
for (uint8_t i = 0; i < IS31FL3729_I2C_PERSISTENCE; i++) { for (uint8_t i = 0; i < IS31FL3729_I2C_PERSISTENCE; i++) {
if (i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; if (i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
} }
#else #else
i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT); i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT);
#endif #endif
} }
void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) { void is31fl3729_write_pwm_buffer(uint8_t index) {
// Transmit PWM registers in 9 transfers of 16 bytes. // Transmit PWM registers in 11 transfers of 13 bytes.
// Iterate over the pwm_buffer contents at 16 byte intervals. // Iterate over the pwm_buffer contents at 13 byte intervals.
for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 16) { for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 13) {
#if IS31FL3729_I2C_PERSISTENCE > 0 #if IS31FL3729_I2C_PERSISTENCE > 0
for (uint8_t j = 0; j < IS31FL3729_I2C_PERSISTENCE; j++) { for (uint8_t j = 0; j < IS31FL3729_I2C_PERSISTENCE; j++) {
if (i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; if (i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
} }
#else #else
i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT); i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT);
#endif #endif
} }
} }
@ -103,53 +121,35 @@ void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) {
void is31fl3729_init_drivers(void) { void is31fl3729_init_drivers(void) {
i2c_init(); i2c_init();
is31fl3729_init(IS31FL3729_I2C_ADDRESS_1); #if defined(IS31FL3729_SDB_PIN)
#if defined(IS31FL3729_I2C_ADDRESS_2) gpio_set_pin_output(IS31FL3729_SDB_PIN);
is31fl3729_init(IS31FL3729_I2C_ADDRESS_2); gpio_write_pin_high(IS31FL3729_SDB_PIN);
# if defined(IS31FL3729_I2C_ADDRESS_3)
is31fl3729_init(IS31FL3729_I2C_ADDRESS_3);
# if defined(IS31FL3729_I2C_ADDRESS_4)
is31fl3729_init(IS31FL3729_I2C_ADDRESS_4);
# endif
# endif
#endif #endif
for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) {
is31fl3729_init(i);
}
for (int i = 0; i < IS31FL3729_LED_COUNT; i++) { for (int i = 0; i < IS31FL3729_LED_COUNT; i++) {
is31fl3729_set_scaling_register(i, 0xFF, 0xFF, 0xFF); is31fl3729_set_scaling_register(i, 0xFF, 0xFF, 0xFF);
} }
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_1, 0); for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) {
#if defined(IS31FL3729_I2C_ADDRESS_2) is31fl3729_update_scaling_registers(i);
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_2, 1); }
# if defined(IS31FL3729_I2C_ADDRESS_3)
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_3, 2);
# if defined(IS31FL3729_I2C_ADDRESS_4)
is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_4, 3);
# endif
# endif
#endif
} }
void is31fl3729_init(uint8_t addr) { void is31fl3729_init(uint8_t index) {
// In order to avoid the LEDs being driven with garbage data // In order to avoid the LEDs being driven with garbage data
// in the LED driver's PWM registers, shutdown is enabled last. // in the LED driver's PWM registers, shutdown is enabled last.
// Set up the mode and other settings, clear the PWM registers, // Set up the mode and other settings, clear the PWM registers,
// then disable software shutdown. // then disable software shutdown.
// Set Pull up & Down for SWx CSy is31fl3729_write_register(index, IS31FL3729_REG_PULLDOWNUP, ((IS31FL3729_SW_PULLDOWN & 0b111) << 4) | (IS31FL3729_CS_PULLUP & 0b111));
is31fl3729_write_register(addr, IS31FL3729_REG_PULLDOWNUP, IS31FL3729_PULLDOWNUP); is31fl3729_write_register(index, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11));
is31fl3729_write_register(index, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY);
// Set Spread Spectrum Register if applicable is31fl3729_write_register(index, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT);
is31fl3729_write_register(addr, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11)); is31fl3729_write_register(index, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION);
// Set PWM Frequency Register if applicable
is31fl3729_write_register(addr, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY);
// Set Golbal Current Control Register
is31fl3729_write_register(addr, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT);
// Set to Normal operation
is31fl3729_write_register(addr, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION);
// Wait 10ms to ensure the device has woken up. // Wait 10ms to ensure the device has woken up.
wait_ms(10); wait_ms(10);
@ -194,18 +194,18 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t red, uint8_t green,
driver_buffers[led.driver].scaling_buffer_dirty = true; driver_buffers[led.driver].scaling_buffer_dirty = true;
} }
void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index) { void is31fl3729_update_pwm_buffers(uint8_t index) {
if (driver_buffers[index].pwm_buffer_dirty) { if (driver_buffers[index].pwm_buffer_dirty) {
is31fl3729_write_pwm_buffer(addr, index); is31fl3729_write_pwm_buffer(index);
driver_buffers[index].pwm_buffer_dirty = false; driver_buffers[index].pwm_buffer_dirty = false;
} }
} }
void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) { void is31fl3729_update_scaling_registers(uint8_t index) {
if (driver_buffers[index].scaling_buffer_dirty) { if (driver_buffers[index].scaling_buffer_dirty) {
for (uint8_t i = 0; i < IS31FL3729_SCALING_REGISTER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3729_SCALING_REGISTER_COUNT; i++) {
is31fl3729_write_register(addr, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]); is31fl3729_write_register(index, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]);
} }
driver_buffers[index].scaling_buffer_dirty = false; driver_buffers[index].scaling_buffer_dirty = false;
@ -213,14 +213,7 @@ void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) {
} }
void is31fl3729_flush(void) { void is31fl3729_flush(void) {
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_1, 0); for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) {
#if defined(IS31FL3729_I2C_ADDRESS_2) is31fl3729_update_pwm_buffers(i);
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_2, 1); }
# if defined(IS31FL3729_I2C_ADDRESS_3)
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_3, 2);
# if defined(IS31FL3729_I2C_ADDRESS_4)
is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_4, 3);
# endif
# endif
#endif
} }

View File

@ -23,6 +23,7 @@
#include "progmem.h" #include "progmem.h"
#include "util.h" #include "util.h"
#define IS31FL3729_REG_PWM 0x01
#define IS31FL3729_REG_SCALING 0x90 #define IS31FL3729_REG_SCALING 0x90
#define IS31FL3729_REG_CONFIGURATION 0xA0 #define IS31FL3729_REG_CONFIGURATION 0xA0
#define IS31FL3729_REG_GLOBAL_CURRENT 0xA1 #define IS31FL3729_REG_GLOBAL_CURRENT 0xA1
@ -60,8 +61,8 @@ typedef struct is31fl3729_led_t {
extern const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT]; extern const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT];
void is31fl3729_init_drivers(void); void is31fl3729_init_drivers(void);
void is31fl3729_init(uint8_t addr); void is31fl3729_init(uint8_t index);
void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data); void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data);
void is31fl3729_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); void is31fl3729_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
void is31fl3729_set_color_all(uint8_t red, uint8_t green, uint8_t blue); void is31fl3729_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
@ -72,26 +73,42 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t red, uint8_t green,
// (eg. from a timer interrupt). // (eg. from a timer interrupt).
// Call this while idle (in between matrix scans). // Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer. // If the buffer is dirty, it will update the driver with the buffer.
void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index); void is31fl3729_update_pwm_buffers(uint8_t index);
void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index); void is31fl3729_update_scaling_registers(uint8_t index);
void is31fl3729_flush(void); void is31fl3729_flush(void);
// Noise reduction using Spread Spectrum register #define IS31FL3729_SW_PULLDOWN_0_OHM 0b000
#define IS31FL3729_SSP_DISABLE 0b0 #define IS31FL3729_SW_PULLDOWN_0K5_OHM_SW_OFF 0b001
#define IS31FL3729_SSP_ENABLE 0b1 #define IS31FL3729_SW_PULLDOWN_1K_OHM_SW_OFF 0b010
#define IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF 0b011
#define IS31FL3729_SW_PULLDOWN_1K_OHM 0b100
#define IS31FL3729_SW_PULLDOWN_2K_OHM 0b101
#define IS31FL3729_SW_PULLDOWN_4K_OHM 0b110
#define IS31FL3729_SW_PULLDOWN_8K_OHM 0b111
#define IS31FL3729_RNG_5_PERCENT 0b00 #define IS31FL3729_CS_PULLUP_0_OHM 0b000
#define IS31FL3729_RNG_15_PERCENT 0b01 #define IS31FL3729_CS_PULLUP_0K5_OHM_CS_OFF 0b001
#define IS31FL3729_RNG_24_PERCENT 0b10 #define IS31FL3729_CS_PULLUP_1K_OHM_CS_OFF 0b010
#define IS31FL3729_RNG_34_PERCENT 0b11 #define IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF 0b011
#define IS31FL3729_CS_PULLUP_1K_OHM 0b100
#define IS31FL3729_CS_PULLUP_2K_OHM 0b101
#define IS31FL3729_CS_PULLUP_4K_OHM 0b110
#define IS31FL3729_CS_PULLUP_8K_OHM 0b111
#define IS31FL3729_CLT_1980_US 0b00 #define IS31FL3729_SPREAD_SPECTRUM_DISABLE 0b0
#define IS31FL3729_CLT_1200_US 0b01 #define IS31FL3729_SPREAD_SPECTRUM_ENABLE 0b1
#define IS31FL3729_CLT_820_US 0b10
#define IS31FL3729_CLT_660_US 0b11 #define IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT 0b00
#define IS31FL3729_SPREAD_SPECTRUM_RANGE_15_PERCENT 0b01
#define IS31FL3729_SPREAD_SPECTRUM_RANGE_24_PERCENT 0b10
#define IS31FL3729_SPREAD_SPECTRUM_RANGE_34_PERCENT 0b11
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US 0b00
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1200_US 0b01
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_820_US 0b10
#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_660_US 0b11
// Noise reduction using PWM Frequency register
#define IS31FL3729_PWM_FREQUENCY_55K_HZ 0b000 #define IS31FL3729_PWM_FREQUENCY_55K_HZ 0b000
#define IS31FL3729_PWM_FREQUENCY_32K_HZ 0b001 #define IS31FL3729_PWM_FREQUENCY_32K_HZ 0b001
#define IS31FL3729_PWM_FREQUENCY_4K_HZ 0b010 #define IS31FL3729_PWM_FREQUENCY_4K_HZ 0b010
@ -101,7 +118,6 @@ void is31fl3729_flush(void);
#define IS31FL3729_PWM_FREQUENCY_250_HZ 0b110 #define IS31FL3729_PWM_FREQUENCY_250_HZ 0b110
#define IS31FL3729_PWM_FREQUENCY_80K_HZ 0b111 #define IS31FL3729_PWM_FREQUENCY_80K_HZ 0b111
// Change SWx Setting using Configuration register
#define IS31FL3729_CONFIG_SWS_15_9 0x01 // 15 CS x 9 SW matrix #define IS31FL3729_CONFIG_SWS_15_9 0x01 // 15 CS x 9 SW matrix
#define IS31FL3729_CONFIG_SWS_16_8 0x11 // 16 CS x 8 SW matrix #define IS31FL3729_CONFIG_SWS_16_8 0x11 // 16 CS x 8 SW matrix
#define IS31FL3729_CONFIG_SWS_16_7 0x21 // 16 CS x 7 SW matrix #define IS31FL3729_CONFIG_SWS_16_7 0x21 // 16 CS x 7 SW matrix
@ -111,157 +127,154 @@ void is31fl3729_flush(void);
#define IS31FL3729_CONFIG_SWS_16_3 0x61 // 16 CS x 3 SW matrix #define IS31FL3729_CONFIG_SWS_16_3 0x61 // 16 CS x 3 SW matrix
#define IS31FL3729_CONFIG_SWS_16_2 0x71 // 16 CS x 2 SW matrix #define IS31FL3729_CONFIG_SWS_16_2 0x71 // 16 CS x 2 SW matrix
// Map CS SW locations to order in PWM / Scaling buffers #define SW1_CS1 0x00
// This matches the ORDER in the Datasheet Register not the POSITION #define SW1_CS2 0x01
// It will always count from 0x01 to (ISSI_MAX_LEDS - 1) #define SW1_CS3 0x02
#define SW1_CS1 0x01 #define SW1_CS4 0x03
#define SW1_CS2 0x02 #define SW1_CS5 0x04
#define SW1_CS3 0x03 #define SW1_CS6 0x05
#define SW1_CS4 0x04 #define SW1_CS7 0x06
#define SW1_CS5 0x05 #define SW1_CS8 0x07
#define SW1_CS6 0x06 #define SW1_CS9 0x08
#define SW1_CS7 0x07 #define SW1_CS10 0x09
#define SW1_CS8 0x08 #define SW1_CS11 0x0A
#define SW1_CS9 0x09 #define SW1_CS12 0x0B
#define SW1_CS10 0x0A #define SW1_CS13 0x0C
#define SW1_CS11 0x0B #define SW1_CS14 0x0D
#define SW1_CS12 0x0C #define SW1_CS15 0x0E
#define SW1_CS13 0x0D #define SW1_CS16 0x0F
#define SW1_CS14 0x0E
#define SW1_CS15 0x0F
#define SW1_CS16 0x10
#define SW2_CS1 0x11 #define SW2_CS1 0x10
#define SW2_CS2 0x12 #define SW2_CS2 0x11
#define SW2_CS3 0x13 #define SW2_CS3 0x12
#define SW2_CS4 0x14 #define SW2_CS4 0x13
#define SW2_CS5 0x15 #define SW2_CS5 0x14
#define SW2_CS6 0x16 #define SW2_CS6 0x15
#define SW2_CS7 0x17 #define SW2_CS7 0x16
#define SW2_CS8 0x18 #define SW2_CS8 0x17
#define SW2_CS9 0x19 #define SW2_CS9 0x18
#define SW2_CS10 0x1A #define SW2_CS10 0x19
#define SW2_CS11 0x1B #define SW2_CS11 0x1A
#define SW2_CS12 0x1C #define SW2_CS12 0x1B
#define SW2_CS13 0x1D #define SW2_CS13 0x1C
#define SW2_CS14 0x1E #define SW2_CS14 0x1D
#define SW2_CS15 0x1F #define SW2_CS15 0x1E
#define SW2_CS16 0x20 #define SW2_CS16 0x1F
#define SW3_CS1 0x21 #define SW3_CS1 0x20
#define SW3_CS2 0x22 #define SW3_CS2 0x21
#define SW3_CS3 0x23 #define SW3_CS3 0x22
#define SW3_CS4 0x24 #define SW3_CS4 0x23
#define SW3_CS5 0x25 #define SW3_CS5 0x24
#define SW3_CS6 0x26 #define SW3_CS6 0x25
#define SW3_CS7 0x27 #define SW3_CS7 0x26
#define SW3_CS8 0x28 #define SW3_CS8 0x27
#define SW3_CS9 0x29 #define SW3_CS9 0x28
#define SW3_CS10 0x2A #define SW3_CS10 0x29
#define SW3_CS11 0x2B #define SW3_CS11 0x2A
#define SW3_CS12 0x2C #define SW3_CS12 0x2B
#define SW3_CS13 0x2D #define SW3_CS13 0x2C
#define SW3_CS14 0x2E #define SW3_CS14 0x2D
#define SW3_CS15 0x2F #define SW3_CS15 0x2E
#define SW3_CS16 0x30 #define SW3_CS16 0x2F
#define SW4_CS1 0x31 #define SW4_CS1 0x30
#define SW4_CS2 0x32 #define SW4_CS2 0x31
#define SW4_CS3 0x33 #define SW4_CS3 0x32
#define SW4_CS4 0x34 #define SW4_CS4 0x33
#define SW4_CS5 0x35 #define SW4_CS5 0x34
#define SW4_CS6 0x36 #define SW4_CS6 0x35
#define SW4_CS7 0x37 #define SW4_CS7 0x36
#define SW4_CS8 0x38 #define SW4_CS8 0x37
#define SW4_CS9 0x39 #define SW4_CS9 0x38
#define SW4_CS10 0x3A #define SW4_CS10 0x39
#define SW4_CS11 0x3B #define SW4_CS11 0x3A
#define SW4_CS12 0x3C #define SW4_CS12 0x3B
#define SW4_CS13 0x3D #define SW4_CS13 0x3C
#define SW4_CS14 0x3E #define SW4_CS14 0x3D
#define SW4_CS15 0x3F #define SW4_CS15 0x3E
#define SW4_CS16 0x40 #define SW4_CS16 0x3F
#define SW5_CS1 0x41 #define SW5_CS1 0x40
#define SW5_CS2 0x42 #define SW5_CS2 0x41
#define SW5_CS3 0x43 #define SW5_CS3 0x42
#define SW5_CS4 0x44 #define SW5_CS4 0x43
#define SW5_CS5 0x45 #define SW5_CS5 0x44
#define SW5_CS6 0x46 #define SW5_CS6 0x45
#define SW5_CS7 0x47 #define SW5_CS7 0x46
#define SW5_CS8 0x48 #define SW5_CS8 0x47
#define SW5_CS9 0x49 #define SW5_CS9 0x48
#define SW5_CS10 0x4A #define SW5_CS10 0x49
#define SW5_CS11 0x4B #define SW5_CS11 0x4A
#define SW5_CS12 0x4C #define SW5_CS12 0x4B
#define SW5_CS13 0x4D #define SW5_CS13 0x4C
#define SW5_CS14 0x4E #define SW5_CS14 0x4D
#define SW5_CS15 0x4F #define SW5_CS15 0x4E
#define SW5_CS16 0x50 #define SW5_CS16 0x4F
#define SW6_CS1 0x51 #define SW6_CS1 0x50
#define SW6_CS2 0x52 #define SW6_CS2 0x51
#define SW6_CS3 0x53 #define SW6_CS3 0x52
#define SW6_CS4 0x54 #define SW6_CS4 0x53
#define SW6_CS5 0x55 #define SW6_CS5 0x54
#define SW6_CS6 0x56 #define SW6_CS6 0x55
#define SW6_CS7 0x57 #define SW6_CS7 0x56
#define SW6_CS8 0x58 #define SW6_CS8 0x57
#define SW6_CS9 0x59 #define SW6_CS9 0x58
#define SW6_CS10 0x5A #define SW6_CS10 0x59
#define SW6_CS11 0x5B #define SW6_CS11 0x5A
#define SW6_CS12 0x5C #define SW6_CS12 0x5B
#define SW6_CS13 0x5D #define SW6_CS13 0x5C
#define SW6_CS14 0x5E #define SW6_CS14 0x5D
#define SW6_CS15 0x5F #define SW6_CS15 0x5E
#define SW6_CS16 0x60 #define SW6_CS16 0x5F
#define SW7_CS1 0x61 #define SW7_CS1 0x60
#define SW7_CS2 0x62 #define SW7_CS2 0x61
#define SW7_CS3 0x63 #define SW7_CS3 0x62
#define SW7_CS4 0x64 #define SW7_CS4 0x63
#define SW7_CS5 0x65 #define SW7_CS5 0x64
#define SW7_CS6 0x66 #define SW7_CS6 0x65
#define SW7_CS7 0x67 #define SW7_CS7 0x66
#define SW7_CS8 0x68 #define SW7_CS8 0x67
#define SW7_CS9 0x69 #define SW7_CS9 0x68
#define SW7_CS10 0x6A #define SW7_CS10 0x69
#define SW7_CS11 0x6B #define SW7_CS11 0x6A
#define SW7_CS12 0x6C #define SW7_CS12 0x6B
#define SW7_CS13 0x6D #define SW7_CS13 0x6C
#define SW7_CS14 0x6E #define SW7_CS14 0x6D
#define SW7_CS15 0x6F #define SW7_CS15 0x6E
#define SW7_CS16 0x70 #define SW7_CS16 0x6F
#define SW8_CS1 0x71 #define SW8_CS1 0x70
#define SW8_CS2 0x72 #define SW8_CS2 0x71
#define SW8_CS3 0x73 #define SW8_CS3 0x72
#define SW8_CS4 0x74 #define SW8_CS4 0x73
#define SW8_CS5 0x75 #define SW8_CS5 0x74
#define SW8_CS6 0x76 #define SW8_CS6 0x75
#define SW8_CS7 0x77 #define SW8_CS7 0x76
#define SW8_CS8 0x78 #define SW8_CS8 0x77
#define SW8_CS9 0x79 #define SW8_CS9 0x78
#define SW8_CS10 0x7A #define SW8_CS10 0x79
#define SW8_CS11 0x7B #define SW8_CS11 0x7A
#define SW8_CS12 0x7C #define SW8_CS12 0x7B
#define SW8_CS13 0x7D #define SW8_CS13 0x7C
#define SW8_CS14 0x7E #define SW8_CS14 0x7D
#define SW8_CS15 0x7F #define SW8_CS15 0x7E
#define SW8_CS16 0x80 #define SW8_CS16 0x7F
#define SW9_CS1 0x81 #define SW9_CS1 0x80
#define SW9_CS2 0x82 #define SW9_CS2 0x81
#define SW9_CS3 0x83 #define SW9_CS3 0x82
#define SW9_CS4 0x84 #define SW9_CS4 0x83
#define SW9_CS5 0x85 #define SW9_CS5 0x84
#define SW9_CS6 0x86 #define SW9_CS6 0x85
#define SW9_CS7 0x87 #define SW9_CS7 0x86
#define SW9_CS8 0x88 #define SW9_CS8 0x87
#define SW9_CS9 0x89 #define SW9_CS9 0x88
#define SW9_CS10 0x8A #define SW9_CS10 0x89
#define SW9_CS11 0x8B #define SW9_CS11 0x8A
#define SW9_CS12 0x8C #define SW9_CS12 0x8B
#define SW9_CS13 0x8D #define SW9_CS13 0x8C
#define SW9_CS14 0x8E #define SW9_CS14 0x8D
#define SW9_CS15 0x8F #define SW9_CS15 0x8E

View File

@ -99,8 +99,8 @@ void is31fl3731_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3731_SDB_PIN) #if defined(IS31FL3731_SDB_PIN)
setPinOutput(IS31FL3731_SDB_PIN); gpio_set_pin_output(IS31FL3731_SDB_PIN);
writePinHigh(IS31FL3731_SDB_PIN); gpio_write_pin_high(IS31FL3731_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3731_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3731_DRIVER_COUNT; i++) {

View File

@ -98,8 +98,8 @@ void is31fl3731_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3731_SDB_PIN) #if defined(IS31FL3731_SDB_PIN)
setPinOutput(IS31FL3731_SDB_PIN); gpio_set_pin_output(IS31FL3731_SDB_PIN);
writePinHigh(IS31FL3731_SDB_PIN); gpio_write_pin_high(IS31FL3731_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3731_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3731_DRIVER_COUNT; i++) {

View File

@ -144,8 +144,8 @@ void is31fl3733_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3733_SDB_PIN) #if defined(IS31FL3733_SDB_PIN)
setPinOutput(IS31FL3733_SDB_PIN); gpio_set_pin_output(IS31FL3733_SDB_PIN);
writePinHigh(IS31FL3733_SDB_PIN); gpio_write_pin_high(IS31FL3733_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3733_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3733_DRIVER_COUNT; i++) {

View File

@ -143,8 +143,8 @@ void is31fl3733_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3733_SDB_PIN) #if defined(IS31FL3733_SDB_PIN)
setPinOutput(IS31FL3733_SDB_PIN); gpio_set_pin_output(IS31FL3733_SDB_PIN);
writePinHigh(IS31FL3733_SDB_PIN); gpio_write_pin_high(IS31FL3733_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3733_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3733_DRIVER_COUNT; i++) {

View File

@ -115,8 +115,8 @@ void is31fl3736_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3736_SDB_PIN) #if defined(IS31FL3736_SDB_PIN)
setPinOutput(IS31FL3736_SDB_PIN); gpio_set_pin_output(IS31FL3736_SDB_PIN);
writePinHigh(IS31FL3736_SDB_PIN); gpio_write_pin_high(IS31FL3736_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3736_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3736_DRIVER_COUNT; i++) {

View File

@ -115,8 +115,8 @@ void is31fl3736_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3736_SDB_PIN) #if defined(IS31FL3736_SDB_PIN)
setPinOutput(IS31FL3736_SDB_PIN); gpio_set_pin_output(IS31FL3736_SDB_PIN);
writePinHigh(IS31FL3736_SDB_PIN); gpio_write_pin_high(IS31FL3736_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3736_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3736_DRIVER_COUNT; i++) {

View File

@ -117,8 +117,8 @@ void is31fl3737_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3737_SDB_PIN) #if defined(IS31FL3737_SDB_PIN)
setPinOutput(IS31FL3737_SDB_PIN); gpio_set_pin_output(IS31FL3737_SDB_PIN);
writePinHigh(IS31FL3737_SDB_PIN); gpio_write_pin_high(IS31FL3737_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3737_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3737_DRIVER_COUNT; i++) {

View File

@ -117,8 +117,8 @@ void is31fl3737_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3737_SDB_PIN) #if defined(IS31FL3737_SDB_PIN)
setPinOutput(IS31FL3737_SDB_PIN); gpio_set_pin_output(IS31FL3737_SDB_PIN);
writePinHigh(IS31FL3737_SDB_PIN); gpio_write_pin_high(IS31FL3737_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3737_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3737_DRIVER_COUNT; i++) {

View File

@ -143,8 +143,8 @@ void is31fl3741_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3741_SDB_PIN) #if defined(IS31FL3741_SDB_PIN)
setPinOutput(IS31FL3741_SDB_PIN); gpio_set_pin_output(IS31FL3741_SDB_PIN);
writePinHigh(IS31FL3741_SDB_PIN); gpio_write_pin_high(IS31FL3741_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3741_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3741_DRIVER_COUNT; i++) {

View File

@ -143,8 +143,8 @@ void is31fl3741_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3741_SDB_PIN) #if defined(IS31FL3741_SDB_PIN)
setPinOutput(IS31FL3741_SDB_PIN); gpio_set_pin_output(IS31FL3741_SDB_PIN);
writePinHigh(IS31FL3741_SDB_PIN); gpio_write_pin_high(IS31FL3741_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3741_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3741_DRIVER_COUNT; i++) {

View File

@ -116,8 +116,8 @@ void is31fl3742a_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3742A_SDB_PIN) #if defined(IS31FL3742A_SDB_PIN)
setPinOutput(IS31FL3742A_SDB_PIN); gpio_set_pin_output(IS31FL3742A_SDB_PIN);
writePinHigh(IS31FL3742A_SDB_PIN); gpio_write_pin_high(IS31FL3742A_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3742A_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3742A_DRIVER_COUNT; i++) {

View File

@ -116,8 +116,8 @@ void is31fl3742a_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3742A_SDB_PIN) #if defined(IS31FL3742A_SDB_PIN)
setPinOutput(IS31FL3742A_SDB_PIN); gpio_set_pin_output(IS31FL3742A_SDB_PIN);
writePinHigh(IS31FL3742A_SDB_PIN); gpio_write_pin_high(IS31FL3742A_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3742A_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3742A_DRIVER_COUNT; i++) {

View File

@ -138,8 +138,8 @@ void is31fl3743a_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3743A_SDB_PIN) #if defined(IS31FL3743A_SDB_PIN)
setPinOutput(IS31FL3743A_SDB_PIN); gpio_set_pin_output(IS31FL3743A_SDB_PIN);
writePinHigh(IS31FL3743A_SDB_PIN); gpio_write_pin_high(IS31FL3743A_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3743A_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3743A_DRIVER_COUNT; i++) {

View File

@ -138,8 +138,8 @@ void is31fl3743a_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3743A_SDB_PIN) #if defined(IS31FL3743A_SDB_PIN)
setPinOutput(IS31FL3743A_SDB_PIN); gpio_set_pin_output(IS31FL3743A_SDB_PIN);
writePinHigh(IS31FL3743A_SDB_PIN); gpio_write_pin_high(IS31FL3743A_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3743A_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3743A_DRIVER_COUNT; i++) {

View File

@ -138,8 +138,8 @@ void is31fl3745_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3745_SDB_PIN) #if defined(IS31FL3745_SDB_PIN)
setPinOutput(IS31FL3745_SDB_PIN); gpio_set_pin_output(IS31FL3745_SDB_PIN);
writePinHigh(IS31FL3745_SDB_PIN); gpio_write_pin_high(IS31FL3745_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3745_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3745_DRIVER_COUNT; i++) {

View File

@ -138,8 +138,8 @@ void is31fl3745_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3745_SDB_PIN) #if defined(IS31FL3745_SDB_PIN)
setPinOutput(IS31FL3745_SDB_PIN); gpio_set_pin_output(IS31FL3745_SDB_PIN);
writePinHigh(IS31FL3745_SDB_PIN); gpio_write_pin_high(IS31FL3745_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3745_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3745_DRIVER_COUNT; i++) {

View File

@ -116,8 +116,8 @@ void is31fl3746a_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3746A_SDB_PIN) #if defined(IS31FL3746A_SDB_PIN)
setPinOutput(IS31FL3746A_SDB_PIN); gpio_set_pin_output(IS31FL3746A_SDB_PIN);
writePinHigh(IS31FL3746A_SDB_PIN); gpio_write_pin_high(IS31FL3746A_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3746A_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3746A_DRIVER_COUNT; i++) {

View File

@ -116,8 +116,8 @@ void is31fl3746a_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(IS31FL3746A_SDB_PIN) #if defined(IS31FL3746A_SDB_PIN)
setPinOutput(IS31FL3746A_SDB_PIN); gpio_set_pin_output(IS31FL3746A_SDB_PIN);
writePinHigh(IS31FL3746A_SDB_PIN); gpio_write_pin_high(IS31FL3746A_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < IS31FL3746A_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < IS31FL3746A_DRIVER_COUNT; i++) {

View File

@ -105,8 +105,8 @@ void snled27351_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(SNLED27351_SDB_PIN) #if defined(SNLED27351_SDB_PIN)
setPinOutput(SNLED27351_SDB_PIN); gpio_set_pin_output(SNLED27351_SDB_PIN);
writePinHigh(SNLED27351_SDB_PIN); gpio_write_pin_high(SNLED27351_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++) {

View File

@ -105,8 +105,8 @@ void snled27351_init_drivers(void) {
i2c_init(); i2c_init();
#if defined(SNLED27351_SDB_PIN) #if defined(SNLED27351_SDB_PIN)
setPinOutput(SNLED27351_SDB_PIN); gpio_set_pin_output(SNLED27351_SDB_PIN);
writePinHigh(SNLED27351_SDB_PIN); gpio_write_pin_high(SNLED27351_SDB_PIN);
#endif #endif
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++) { for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++) {

View File

@ -192,7 +192,7 @@ __attribute__((weak)) bool oled_send_cmd(const uint8_t *data, uint16_t size) {
return false; return false;
} }
// Command Mode // Command Mode
writePinLow(OLED_DC_PIN); gpio_write_pin_low(OLED_DC_PIN);
// Send the commands // Send the commands
if (spi_transmit(&data[1], size - 1) != SPI_STATUS_SUCCESS) { if (spi_transmit(&data[1], size - 1) != SPI_STATUS_SUCCESS) {
spi_stop(); spi_stop();
@ -215,7 +215,7 @@ __attribute__((weak)) bool oled_send_cmd_P(const uint8_t *data, uint16_t size) {
} }
spi_status_t status = SPI_STATUS_SUCCESS; spi_status_t status = SPI_STATUS_SUCCESS;
// Command Mode // Command Mode
writePinLow(OLED_DC_PIN); gpio_write_pin_low(OLED_DC_PIN);
// Send the commands // Send the commands
for (uint16_t i = 1; i < size && status >= 0; i++) { for (uint16_t i = 1; i < size && status >= 0; i++) {
status = spi_write(pgm_read_byte((const char *)&data[i])); status = spi_write(pgm_read_byte((const char *)&data[i]));
@ -239,7 +239,7 @@ __attribute__((weak)) bool oled_send_data(const uint8_t *data, uint16_t size) {
return false; return false;
} }
// Data Mode // Data Mode
writePinHigh(OLED_DC_PIN); gpio_write_pin_high(OLED_DC_PIN);
// Send the commands // Send the commands
if (spi_transmit(data, size) != SPI_STATUS_SUCCESS) { if (spi_transmit(data, size) != SPI_STATUS_SUCCESS) {
spi_stop(); spi_stop();
@ -256,17 +256,17 @@ __attribute__((weak)) bool oled_send_data(const uint8_t *data, uint16_t size) {
__attribute__((weak)) void oled_driver_init(void) { __attribute__((weak)) void oled_driver_init(void) {
#if defined(OLED_TRANSPORT_SPI) #if defined(OLED_TRANSPORT_SPI)
spi_init(); spi_init();
setPinOutput(OLED_CS_PIN); gpio_set_pin_output(OLED_CS_PIN);
writePinHigh(OLED_CS_PIN); gpio_write_pin_high(OLED_CS_PIN);
setPinOutput(OLED_DC_PIN); gpio_set_pin_output(OLED_DC_PIN);
writePinLow(OLED_DC_PIN); gpio_write_pin_low(OLED_DC_PIN);
# ifdef OLED_RST_PIN # ifdef OLED_RST_PIN
/* Reset device */ /* Reset device */
setPinOutput(OLED_RST_PIN); gpio_set_pin_output(OLED_RST_PIN);
writePinLow(OLED_RST_PIN); gpio_write_pin_low(OLED_RST_PIN);
wait_ms(20); wait_ms(20);
writePinHigh(OLED_RST_PIN); gpio_write_pin_high(OLED_RST_PIN);
wait_ms(20); wait_ms(20);
# endif # endif
#elif defined(OLED_TRANSPORT_I2C) #elif defined(OLED_TRANSPORT_I2C)

View File

@ -17,8 +17,8 @@ bool qp_comms_spi_init(painter_device_t device) {
spi_init(); spi_init();
// Set up CS as output high // Set up CS as output high
setPinOutput(comms_config->chip_select_pin); gpio_set_pin_output(comms_config->chip_select_pin);
writePinHigh(comms_config->chip_select_pin); gpio_write_pin_high(comms_config->chip_select_pin);
return true; return true;
} }
@ -49,7 +49,7 @@ void qp_comms_spi_stop(painter_device_t device) {
painter_driver_t * driver = (painter_driver_t *)device; painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config; qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config;
spi_stop(); spi_stop();
writePinHigh(comms_config->chip_select_pin); gpio_write_pin_high(comms_config->chip_select_pin);
} }
const painter_comms_vtable_t spi_comms_vtable = { const painter_comms_vtable_t spi_comms_vtable = {
@ -74,16 +74,16 @@ bool qp_comms_spi_dc_reset_init(painter_device_t device) {
// Set up D/C as output low, if specified // Set up D/C as output low, if specified
if (comms_config->dc_pin != NO_PIN) { if (comms_config->dc_pin != NO_PIN) {
setPinOutput(comms_config->dc_pin); gpio_set_pin_output(comms_config->dc_pin);
writePinLow(comms_config->dc_pin); gpio_write_pin_low(comms_config->dc_pin);
} }
// Set up RST as output, if specified, performing a reset in the process // Set up RST as output, if specified, performing a reset in the process
if (comms_config->reset_pin != NO_PIN) { if (comms_config->reset_pin != NO_PIN) {
setPinOutput(comms_config->reset_pin); gpio_set_pin_output(comms_config->reset_pin);
writePinLow(comms_config->reset_pin); gpio_write_pin_low(comms_config->reset_pin);
wait_ms(20); wait_ms(20);
writePinHigh(comms_config->reset_pin); gpio_write_pin_high(comms_config->reset_pin);
wait_ms(20); wait_ms(20);
} }
@ -93,14 +93,14 @@ bool qp_comms_spi_dc_reset_init(painter_device_t device) {
uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *data, uint32_t byte_count) { uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
painter_driver_t * driver = (painter_driver_t *)device; painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
writePinHigh(comms_config->dc_pin); gpio_write_pin_high(comms_config->dc_pin);
return qp_comms_spi_send_data(device, data, byte_count); return qp_comms_spi_send_data(device, data, byte_count);
} }
void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) { void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) {
painter_driver_t * driver = (painter_driver_t *)device; painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
writePinLow(comms_config->dc_pin); gpio_write_pin_low(comms_config->dc_pin);
spi_write(cmd); spi_write(cmd);
} }

View File

@ -38,6 +38,7 @@ typedef struct qp_comms_spi_dc_reset_config_t {
bool command_params_uses_command_pin; // keep D/C held low when sending command sequences for data bytes bool command_params_uses_command_pin; // keep D/C held low when sending command sequences for data bytes
} qp_comms_spi_dc_reset_config_t; } qp_comms_spi_dc_reset_config_t;
bool qp_comms_spi_dc_reset_init(painter_device_t device);
void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd); void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd);
uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void* data, uint32_t byte_count); uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void* data, uint32_t byte_count);
void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len); void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len);

View File

@ -0,0 +1,298 @@
// Copyright 2021 Nick Brassel (@tzarc)
// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_ili9486.h"
#include "qp_ili9xxx_opcodes.h"
#include "qp_tft_panel.h"
#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE
# include "spi_master.h"
# include <qp_comms_spi.h>
#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Common
// Driver storage
tft_panel_dc_reset_painter_device_t ili9486_drivers[ILI9486_NUM_DEVICES] = {0};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initialization
bool qp_ili9486_init(painter_device_t device, painter_rotation_t rotation) {
// clang-format off
const uint8_t ili9486_init_sequence[] = {
// Command, Delay, N, Data[N]
ILI9XXX_CMD_RESET, 120, 0,
ILI9XXX_SET_PIX_FMT, 0, 1, 0x55,
ILI9XXX_SET_PGAMMA, 0, 15, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00,
ILI9XXX_SET_NGAMMA, 0, 15, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00,
ILI9XXX_SET_POWER_CTL_1, 0, 2, 0x0D, 0x0D,
ILI9XXX_SET_POWER_CTL_2, 0, 2, 0x43, 0x00,
ILI9XXX_SET_POWER_CTL_3, 0, 1, 0x00,
ILI9XXX_SET_VCOM_CTL_1, 0, 4, 0x00, 0x48, 0x00, 0x48,
ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02,
};
// clang-format on
qp_comms_bulk_command_sequence(device, ili9486_init_sequence, sizeof(ili9486_init_sequence));
// Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
const uint8_t madctl[] = {
[QP_ROTATION_0] = ILI9XXX_MADCTL_BGR,
[QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV,
[QP_ROTATION_180] = ILI9XXX_MADCTL_BGR,
[QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV,
};
const uint8_t functl[] = {
[QP_ROTATION_0] = 0x42,
[QP_ROTATION_90] = 0x62,
[QP_ROTATION_180] = 0x22,
[QP_ROTATION_270] = 0x02,
};
// clang-format off
uint8_t rotation_sequence[] = {
// Command, Delay, N, Data[N]
ILI9XXX_SET_MEM_ACS_CTL, 0, 1, madctl[rotation],
ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0x00, functl[rotation],
ILI9XXX_CMD_SLEEP_OFF, 5, 0,
ILI9XXX_CMD_DISPLAY_ON, 5, 0,
};
// clang-format on
qp_comms_bulk_command_sequence(device, rotation_sequence, sizeof(rotation_sequence));
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver vtable
// waveshare variant needs some tweaks due to shift registers
static void qp_comms_spi_dc_reset_send_command_odd_cs_pulse(painter_device_t device, uint8_t cmd) {
painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
writePinLow(comms_config->spi_config.chip_select_pin);
qp_comms_spi_dc_reset_send_command(device, cmd);
writePinHigh(comms_config->spi_config.chip_select_pin);
}
static uint32_t qp_comms_spi_send_data_odd_cs_pulse(painter_device_t device, const void *data, uint32_t byte_count) {
painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
uint32_t bytes_remaining = byte_count;
const uint8_t *p = (const uint8_t *)data;
uint32_t max_msg_length = 1024;
writePinHigh(comms_config->dc_pin);
while (bytes_remaining > 0) {
uint32_t bytes_this_loop = QP_MIN(bytes_remaining, max_msg_length);
bool odd_bytes = bytes_this_loop & 1;
// send data
writePinLow(comms_config->spi_config.chip_select_pin);
spi_transmit(p, bytes_this_loop);
p += bytes_this_loop;
// extra CS toggle, for alignment
if (odd_bytes) {
writePinHigh(comms_config->spi_config.chip_select_pin);
writePinLow(comms_config->spi_config.chip_select_pin);
}
bytes_remaining -= bytes_this_loop;
}
return byte_count - bytes_remaining;
}
static uint32_t qp_ili9486_send_data_toggling(painter_device_t device, const uint8_t *data, uint32_t byte_count) {
painter_driver_t * driver = (painter_driver_t *)device;
qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
uint32_t ret;
for (uint8_t j = 0; j < byte_count; ++j) {
writePinLow(comms_config->spi_config.chip_select_pin);
ret = qp_comms_spi_dc_reset_send_data(device, &data[j], 1);
writePinHigh(comms_config->spi_config.chip_select_pin);
}
return ret;
}
static void qp_comms_spi_send_command_sequence_odd_cs_pulse(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
for (size_t i = 0; i < sequence_len;) {
uint8_t command = sequence[i];
uint8_t delay = sequence[i + 1];
uint8_t num_bytes = sequence[i + 2];
qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, command);
if (num_bytes > 0) {
qp_ili9486_send_data_toggling(device, &sequence[i + 3], num_bytes);
}
if (delay > 0) {
wait_ms(delay);
}
i += (3 + num_bytes);
}
}
static bool qp_ili9486_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
painter_driver_t * driver = (painter_driver_t *)device;
tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable;
// Fix up the drawing location if required
left += driver->offset_x;
right += driver->offset_x;
top += driver->offset_y;
bottom += driver->offset_y;
// Check if we need to manually swap the window coordinates based on whether or not we're in a sideways rotation
if (vtable->swap_window_coords && (driver->rotation == QP_ROTATION_90 || driver->rotation == QP_ROTATION_270)) {
uint16_t temp;
temp = left;
left = top;
top = temp;
temp = right;
right = bottom;
bottom = temp;
}
// Set up the x-window
uint8_t xbuf[4] = {left >> 8, left & 0xFF, right >> 8, right & 0xFF};
qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.set_column_address);
qp_ili9486_send_data_toggling(device, xbuf, 4);
// Set up the y-window
uint8_t ybuf[4] = {top >> 8, top & 0xFF, bottom >> 8, bottom & 0xFF};
qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.set_row_address);
qp_ili9486_send_data_toggling(device, ybuf, 4);
// Lock in the window
qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.enable_writes);
return true;
}
// Regular
const tft_panel_dc_reset_painter_driver_vtable_t ili9486_driver_vtable = {
.base =
{
.init = qp_ili9486_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 = ILI9XXX_CMD_DISPLAY_ON,
.display_off = ILI9XXX_CMD_DISPLAY_OFF,
.set_column_address = ILI9XXX_SET_COL_ADDR,
.set_row_address = ILI9XXX_SET_PAGE_ADDR,
.enable_writes = ILI9XXX_SET_MEM,
},
};
// Waveshare tweaks
const tft_panel_dc_reset_painter_driver_vtable_t ili9486_waveshare_driver_vtable = {
.base =
{
.init = qp_ili9486_init,
.power = qp_tft_panel_power,
.clear = qp_tft_panel_clear,
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_ili9486_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 = ILI9XXX_CMD_DISPLAY_ON,
.display_off = ILI9XXX_CMD_DISPLAY_OFF,
.set_column_address = ILI9XXX_SET_COL_ADDR,
.set_row_address = ILI9XXX_SET_PAGE_ADDR,
.enable_writes = ILI9XXX_SET_MEM,
},
};
static const painter_comms_with_command_vtable_t spi_comms_odd_cs_pulse_vtable = {
.base =
{
.comms_init = qp_comms_spi_dc_reset_init,
.comms_start = qp_comms_spi_start,
.comms_send = qp_comms_spi_send_data_odd_cs_pulse,
.comms_stop = qp_comms_spi_stop,
},
.send_command = qp_comms_spi_dc_reset_send_command_odd_cs_pulse,
.bulk_command_sequence = qp_comms_spi_send_command_sequence_odd_cs_pulse,
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SPI
#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE
// Factory function for creating a handle to the ILI9486 device
painter_device_t qp_ili9486_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 < ILI9486_NUM_DEVICES; ++i) {
tft_panel_dc_reset_painter_device_t *driver = &ili9486_drivers[i];
if (!driver->base.driver_vtable) {
driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9486_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;
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;
}
painter_device_t qp_ili9486_make_spi_waveshare_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) {
painter_device_t device = qp_ili9486_make_spi_device(panel_width, panel_height, chip_select_pin, dc_pin, reset_pin, spi_divisor, spi_mode);
if (device) {
tft_panel_dc_reset_painter_device_t *driver = (tft_panel_dc_reset_painter_device_t *)device;
driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9486_waveshare_driver_vtable;
driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_odd_cs_pulse_vtable;
}
return device;
}
#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,52 @@
// Copyright 2021 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "gpio.h"
#include "qp_internal.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter ILI9486 configurables (add to your keyboard's config.h)
#ifndef ILI9486_NUM_DEVICES
/**
* @def This controls the maximum number of ILI9486 devices that Quantum Painter can communicate with at any one time.
* Increasing this number allows for multiple displays to be used.
*/
# define ILI9486_NUM_DEVICES 1
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter ILI9486 device factories
#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE
/**
* Factory method for an ILI9486 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_ili9486_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);
/**
* Factory method for an ILI9486 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_ili9486_make_spi_waveshare_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_ILI9486_SPI_ENABLE

View File

@ -70,6 +70,7 @@
#define ILI9XXX_SET_LIGHT_CTL_8 0xBF // Set backlight ctl 8 #define ILI9XXX_SET_LIGHT_CTL_8 0xBF // Set backlight ctl 8
#define ILI9XXX_SET_POWER_CTL_1 0xC0 // Set power ctl 1 #define ILI9XXX_SET_POWER_CTL_1 0xC0 // Set power ctl 1
#define ILI9XXX_SET_POWER_CTL_2 0xC1 // Set power ctl 2 #define ILI9XXX_SET_POWER_CTL_2 0xC1 // Set power ctl 2
#define ILI9XXX_SET_POWER_CTL_3 0xC2 // Set power ctl 3
#define ILI9XXX_SET_VCOM_CTL_1 0xC5 // Set VCOM ctl 1 #define ILI9XXX_SET_VCOM_CTL_1 0xC5 // Set VCOM ctl 1
#define ILI9XXX_SET_VCOM_CTL_2 0xC7 // Set VCOM ctl 2 #define ILI9XXX_SET_VCOM_CTL_2 0xC7 // Set VCOM ctl 2
#define ILI9XXX_POWER_CTL_A 0xCB // Set power control A #define ILI9XXX_POWER_CTL_A 0xCB // Set power control A

View File

@ -47,9 +47,9 @@
void adns5050_init(void) { void adns5050_init(void) {
// Initialize the ADNS serial pins. // Initialize the ADNS serial pins.
setPinOutput(ADNS5050_SCLK_PIN); gpio_set_pin_output(ADNS5050_SCLK_PIN);
setPinOutput(ADNS5050_SDIO_PIN); gpio_set_pin_output(ADNS5050_SDIO_PIN);
setPinOutput(ADNS5050_CS_PIN); gpio_set_pin_output(ADNS5050_CS_PIN);
// reboot the adns. // reboot the adns.
// if the adns hasn't initialized yet, this is harmless. // if the adns hasn't initialized yet, this is harmless.
@ -69,30 +69,30 @@ void adns5050_init(void) {
// Just as with the serial protocol, this is used by the slave to send a // Just as with the serial protocol, this is used by the slave to send a
// synchronization signal to the master. // synchronization signal to the master.
void adns5050_sync(void) { void adns5050_sync(void) {
writePinLow(ADNS5050_CS_PIN); gpio_write_pin_low(ADNS5050_CS_PIN);
wait_us(1); wait_us(1);
writePinHigh(ADNS5050_CS_PIN); gpio_write_pin_high(ADNS5050_CS_PIN);
} }
void adns5050_cs_select(void) { void adns5050_cs_select(void) {
writePinLow(ADNS5050_CS_PIN); gpio_write_pin_low(ADNS5050_CS_PIN);
} }
void adns5050_cs_deselect(void) { void adns5050_cs_deselect(void) {
writePinHigh(ADNS5050_CS_PIN); gpio_write_pin_high(ADNS5050_CS_PIN);
} }
uint8_t adns5050_serial_read(void) { uint8_t adns5050_serial_read(void) {
setPinInput(ADNS5050_SDIO_PIN); gpio_set_pin_input(ADNS5050_SDIO_PIN);
uint8_t byte = 0; uint8_t byte = 0;
for (uint8_t i = 0; i < 8; ++i) { for (uint8_t i = 0; i < 8; ++i) {
writePinLow(ADNS5050_SCLK_PIN); gpio_write_pin_low(ADNS5050_SCLK_PIN);
wait_us(1); wait_us(1);
byte = (byte << 1) | readPin(ADNS5050_SDIO_PIN); byte = (byte << 1) | gpio_read_pin(ADNS5050_SDIO_PIN);
writePinHigh(ADNS5050_SCLK_PIN); gpio_write_pin_high(ADNS5050_SCLK_PIN);
wait_us(1); wait_us(1);
} }
@ -100,19 +100,19 @@ uint8_t adns5050_serial_read(void) {
} }
void adns5050_serial_write(uint8_t data) { void adns5050_serial_write(uint8_t data) {
setPinOutput(ADNS5050_SDIO_PIN); gpio_set_pin_output(ADNS5050_SDIO_PIN);
for (int8_t b = 7; b >= 0; b--) { for (int8_t b = 7; b >= 0; b--) {
writePinLow(ADNS5050_SCLK_PIN); gpio_write_pin_low(ADNS5050_SCLK_PIN);
if (data & (1 << b)) if (data & (1 << b))
writePinHigh(ADNS5050_SDIO_PIN); gpio_write_pin_high(ADNS5050_SDIO_PIN);
else else
writePinLow(ADNS5050_SDIO_PIN); gpio_write_pin_low(ADNS5050_SDIO_PIN);
wait_us(2); wait_us(2);
writePinHigh(ADNS5050_SCLK_PIN); gpio_write_pin_high(ADNS5050_SCLK_PIN);
} }
// tSWR. See page 15 of the ADNS spec sheet. // tSWR. See page 15 of the ADNS spec sheet.

View File

@ -100,7 +100,7 @@ uint8_t adns9800_read(uint8_t reg_addr) {
} }
void adns9800_init(void) { void adns9800_init(void) {
setPinOutput(ADNS9800_CS_PIN); gpio_set_pin_output(ADNS9800_CS_PIN);
spi_init(); spi_init();

View File

@ -122,17 +122,17 @@ report_analog_joystick_t analog_joystick_read(void) {
report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed, 1); report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed, 1);
} }
#ifdef ANALOG_JOYSTICK_CLICK_PIN #ifdef ANALOG_JOYSTICK_CLICK_PIN
report.button = !readPin(ANALOG_JOYSTICK_CLICK_PIN); report.button = !gpio_read_pin(ANALOG_JOYSTICK_CLICK_PIN);
#endif #endif
return report; return report;
} }
void analog_joystick_init(void) { void analog_joystick_init(void) {
setPinInputHigh(ANALOG_JOYSTICK_X_AXIS_PIN); gpio_set_pin_input_high(ANALOG_JOYSTICK_X_AXIS_PIN);
setPinInputHigh(ANALOG_JOYSTICK_Y_AXIS_PIN); gpio_set_pin_input_high(ANALOG_JOYSTICK_Y_AXIS_PIN);
#ifdef ANALOG_JOYSTICK_CLICK_PIN #ifdef ANALOG_JOYSTICK_CLICK_PIN
setPinInputHigh(ANALOG_JOYSTICK_CLICK_PIN); gpio_set_pin_input_high(ANALOG_JOYSTICK_CLICK_PIN);
#endif #endif
// Account for drift // Account for drift
xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN); xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);

View File

@ -51,8 +51,8 @@ uint8_t paw3204_read_reg(uint8_t reg_addr);
void paw3204_write_reg(uint8_t reg_addr, uint8_t data); void paw3204_write_reg(uint8_t reg_addr, uint8_t data);
void paw3204_init(void) { void paw3204_init(void) {
setPinOutput(PAW3204_SCLK_PIN); // setclockpin to output gpio_set_pin_output(PAW3204_SCLK_PIN); // setclockpin to output
setPinInputHigh(PAW3204_SDIO_PIN); // set datapin input high gpio_set_pin_input_high(PAW3204_SDIO_PIN); // set datapin input high
paw3204_write_reg(REG_SETUP, 0x86); // reset sensor and set 1600cpi paw3204_write_reg(REG_SETUP, 0x86); // reset sensor and set 1600cpi
wait_us(5); wait_us(5);
@ -64,16 +64,16 @@ void paw3204_init(void) {
} }
uint8_t paw3204_serial_read(void) { uint8_t paw3204_serial_read(void) {
setPinInput(PAW3204_SDIO_PIN); gpio_set_pin_input(PAW3204_SDIO_PIN);
uint8_t byte = 0; uint8_t byte = 0;
for (uint8_t i = 0; i < 8; ++i) { for (uint8_t i = 0; i < 8; ++i) {
writePinLow(PAW3204_SCLK_PIN); gpio_write_pin_low(PAW3204_SCLK_PIN);
wait_us(1); wait_us(1);
byte = (byte << 1) | readPin(PAW3204_SDIO_PIN); byte = (byte << 1) | gpio_read_pin(PAW3204_SDIO_PIN);
writePinHigh(PAW3204_SCLK_PIN); gpio_write_pin_high(PAW3204_SCLK_PIN);
wait_us(1); wait_us(1);
} }
@ -81,17 +81,17 @@ uint8_t paw3204_serial_read(void) {
} }
void paw3204_serial_write(uint8_t data) { void paw3204_serial_write(uint8_t data) {
writePinLow(PAW3204_SDIO_PIN); gpio_write_pin_low(PAW3204_SDIO_PIN);
setPinOutput(PAW3204_SDIO_PIN); gpio_set_pin_output(PAW3204_SDIO_PIN);
for (int8_t b = 7; b >= 0; b--) { for (int8_t b = 7; b >= 0; b--) {
writePinLow(PAW3204_SCLK_PIN); gpio_write_pin_low(PAW3204_SCLK_PIN);
if (data & (1 << b)) { if (data & (1 << b)) {
writePinHigh(PAW3204_SDIO_PIN); gpio_write_pin_high(PAW3204_SDIO_PIN);
} else { } else {
writePinLow(PAW3204_SDIO_PIN); gpio_write_pin_low(PAW3204_SDIO_PIN);
} }
writePinHigh(PAW3204_SCLK_PIN); gpio_write_pin_high(PAW3204_SCLK_PIN);
} }
wait_us(4); wait_us(4);

View File

@ -24,9 +24,9 @@
void pmw3320_init(void) { void pmw3320_init(void) {
// Initialize sensor serial pins. // Initialize sensor serial pins.
setPinOutput(PMW3320_SCLK_PIN); gpio_set_pin_output(PMW3320_SCLK_PIN);
setPinOutput(PMW3320_SDIO_PIN); gpio_set_pin_output(PMW3320_SDIO_PIN);
setPinOutput(PMW3320_CS_PIN); gpio_set_pin_output(PMW3320_CS_PIN);
// reboot the sensor. // reboot the sensor.
pmw3320_write_reg(REG_Power_Up_Reset, 0x5a); pmw3320_write_reg(REG_Power_Up_Reset, 0x5a);
@ -54,30 +54,30 @@ void pmw3320_init(void) {
// Just as with the serial protocol, this is used by the slave to send a // Just as with the serial protocol, this is used by the slave to send a
// synchronization signal to the master. // synchronization signal to the master.
void pmw3320_sync(void) { void pmw3320_sync(void) {
writePinLow(PMW3320_CS_PIN); gpio_write_pin_low(PMW3320_CS_PIN);
wait_us(1); wait_us(1);
writePinHigh(PMW3320_CS_PIN); gpio_write_pin_high(PMW3320_CS_PIN);
} }
void pmw3320_cs_select(void) { void pmw3320_cs_select(void) {
writePinLow(PMW3320_CS_PIN); gpio_write_pin_low(PMW3320_CS_PIN);
} }
void pmw3320_cs_deselect(void) { void pmw3320_cs_deselect(void) {
writePinHigh(PMW3320_CS_PIN); gpio_write_pin_high(PMW3320_CS_PIN);
} }
uint8_t pmw3320_serial_read(void) { uint8_t pmw3320_serial_read(void) {
setPinInput(PMW3320_SDIO_PIN); gpio_set_pin_input(PMW3320_SDIO_PIN);
uint8_t byte = 0; uint8_t byte = 0;
for (uint8_t i = 0; i < 8; ++i) { for (uint8_t i = 0; i < 8; ++i) {
writePinLow(PMW3320_SCLK_PIN); gpio_write_pin_low(PMW3320_SCLK_PIN);
wait_us(1); wait_us(1);
byte = (byte << 1) | readPin(PMW3320_SDIO_PIN); byte = (byte << 1) | gpio_read_pin(PMW3320_SDIO_PIN);
writePinHigh(PMW3320_SCLK_PIN); gpio_write_pin_high(PMW3320_SCLK_PIN);
wait_us(1); wait_us(1);
} }
@ -85,19 +85,19 @@ uint8_t pmw3320_serial_read(void) {
} }
void pmw3320_serial_write(uint8_t data) { void pmw3320_serial_write(uint8_t data) {
setPinOutput(PMW3320_SDIO_PIN); gpio_set_pin_output(PMW3320_SDIO_PIN);
for (int8_t b = 7; b >= 0; b--) { for (int8_t b = 7; b >= 0; b--) {
writePinLow(PMW3320_SCLK_PIN); gpio_write_pin_low(PMW3320_SCLK_PIN);
if (data & (1 << b)) if (data & (1 << b))
writePinHigh(PMW3320_SDIO_PIN); gpio_write_pin_high(PMW3320_SDIO_PIN);
else else
writePinLow(PMW3320_SDIO_PIN); gpio_write_pin_low(PMW3320_SDIO_PIN);
wait_us(2); wait_us(2);
writePinHigh(PMW3320_SCLK_PIN); gpio_write_pin_high(PMW3320_SCLK_PIN);
} }
// This was taken from ADNS5050 driver. // This was taken from ADNS5050 driver.

View File

@ -15,6 +15,9 @@ uint16_t pmw33xx_get_cpi(uint8_t sensor) {
} }
uint8_t cpival = pmw33xx_read(sensor, REG_Config1); uint8_t cpival = pmw33xx_read(sensor, REG_Config1);
// In some cases (100, 900, 1700, 2500), reading the CPI corrupts the firmware and the sensor stops responding.
// To avoid this, we write the value back to the sensor, which seems to prevent the corruption.
pmw33xx_write(sensor, REG_Config1, cpival);
return (uint16_t)((cpival + 1) & 0xFF) * PMW33XX_CPI_STEP; return (uint16_t)((cpival + 1) & 0xFF) * PMW33XX_CPI_STEP;
} }

View File

@ -346,10 +346,10 @@ static void USB2422_write_block(void) {
void USB2422_init(void) { void USB2422_init(void) {
#ifdef USB2422_RESET_PIN #ifdef USB2422_RESET_PIN
setPinOutput(USB2422_RESET_PIN); gpio_set_pin_output(USB2422_RESET_PIN);
#endif #endif
#ifdef USB2422_ACTIVE_PIN #ifdef USB2422_ACTIVE_PIN
setPinInput(USB2422_ACTIVE_PIN); gpio_set_pin_input(USB2422_ACTIVE_PIN);
#endif #endif
i2c_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration i2c_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration
@ -387,15 +387,15 @@ void USB2422_configure(void) {
void USB2422_reset(void) { void USB2422_reset(void) {
#ifdef USB2422_RESET_PIN #ifdef USB2422_RESET_PIN
writePinLow(USB2422_RESET_PIN); gpio_write_pin_low(USB2422_RESET_PIN);
wait_us(2); wait_us(2);
writePinHigh(USB2422_RESET_PIN); gpio_write_pin_high(USB2422_RESET_PIN);
#endif #endif
} }
bool USB2422_active(void) { bool USB2422_active(void) {
#ifdef USB2422_ACTIVE_PIN #ifdef USB2422_ACTIVE_PIN
return readPin(USB2422_ACTIVE_PIN); return gpio_read_pin(USB2422_ACTIVE_PIN);
#else #else
return 1; return 1;
#endif #endif

View File

@ -18,16 +18,13 @@
"driver": "vendor" "driver": "vendor"
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"matrix_pins": { "matrix_pins": {
"rows": ["GP21", "GP20", "GP19", "GP18"], "rows": ["GP21", "GP20", "GP19", "GP18"],

View File

@ -18,16 +18,13 @@
"driver": "vendor" "driver": "vendor"
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"matrix_pins": { "matrix_pins": {
"rows": ["GP21", "GP20", "GP19", "GP18"], "rows": ["GP21", "GP20", "GP19", "GP18"],

View File

@ -18,16 +18,13 @@
"driver": "vendor" "driver": "vendor"
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"matrix_pins": { "matrix_pins": {
"rows": ["GP21", "GP20", "GP19", "GP18"], "rows": ["GP21", "GP20", "GP19", "GP18"],

View File

@ -15,8 +15,6 @@
"layer_count": 10 "layer_count": 10
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
@ -24,7 +22,6 @@
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true,
"rgblight": false,
"oled": true "oled": true
}, },
"matrix_pins": { "matrix_pins": {

View File

@ -15,8 +15,6 @@
"layer_count": 10 "layer_count": 10
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
@ -24,8 +22,7 @@
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"ws2812": { "ws2812": {
"pin": "GP17", "pin": "GP17",

View File

@ -15,16 +15,13 @@
"layer_count": 10 "layer_count": 10
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"ws2812": { "ws2812": {
"pin": "GP15", "pin": "GP15",

View File

@ -15,16 +15,13 @@
"layer_count": 10 "layer_count": 10
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"ws2812": { "ws2812": {
"pin": "GP19", "pin": "GP19",

View File

@ -12,8 +12,6 @@
"vid": "0x6F75" "vid": "0x6F75"
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
@ -21,8 +19,7 @@
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"ws2812": { "ws2812": {
"pin": "GP6", "pin": "GP6",

View File

@ -11,8 +11,6 @@
"vid": "0x6F75" "vid": "0x6F75"
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,
@ -20,8 +18,7 @@
"extrakey": true, "extrakey": true,
"mousekey": true, "mousekey": true,
"nkro": false, "nkro": false,
"rgb_matrix": true, "rgb_matrix": true
"rgblight": false
}, },
"ws2812": { "ws2812": {
"pin": "D7" "pin": "D7"

View File

@ -29,4 +29,4 @@
#define RGBLIGHT_EFFECT_ALTERNATING #define RGBLIGHT_EFFECT_ALTERNATING
#define RGBLIGHT_EFFECT_TWINKLE #define RGBLIGHT_EFFECT_TWINKLE
#define WS2812_DI_PIN D3 // The pin the LED strip is connected to #define WS2812_DI_PIN D3 // The pin the LED strip is connected to
#define RGBLED_NUM 7 // Number of LEDs in your strip #define RGBLIGHT_LED_COUNT 7 // Number of LEDs in your strip

View File

@ -18,68 +18,68 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef RGB_MATRIX_ENABLE #ifdef RGB_MATRIX_ENABLE
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = { const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
{ 0, K_2, J_2, L_2 }, //D402 { 0, SW11_CS2, SW10_CS2, SW12_CS2 }, //D402
{ 0, K_3, J_3, L_3 }, //D403 { 0, SW11_CS3, SW10_CS3, SW12_CS3 }, //D403
{ 0, K_4, J_4, L_4 }, //D404 { 0, SW11_CS4, SW10_CS4, SW12_CS4 }, //D404
{ 0, K_5, J_5, L_5 }, //D405 { 0, SW11_CS5, SW10_CS5, SW12_CS5 }, //D405
{ 0, K_6, J_6, L_6 }, //D406 { 0, SW11_CS6, SW10_CS6, SW12_CS6 }, //D406
{ 0, K_7, J_7, L_7 }, //D407 { 0, SW11_CS7, SW10_CS7, SW12_CS7 }, //D407
{ 0, K_8, J_8, L_8 }, //D408 { 0, SW11_CS8, SW10_CS8, SW12_CS8 }, //D408
{ 0, K_9, J_9, L_9 }, //D409 { 0, SW11_CS9, SW10_CS9, SW12_CS9 }, //D409
{ 0, K_10, J_10, L_10 }, //D410 { 0, SW11_CS10, SW10_CS10, SW12_CS10 }, //D410
{ 0, K_11, J_11, L_11 }, //D411 { 0, SW11_CS11, SW10_CS11, SW12_CS11 }, //D411
{ 0, K_12, J_12, L_12 }, //D412 { 0, SW11_CS12, SW10_CS12, SW12_CS12 }, //D412
{ 0, K_13, J_13, L_13 }, //D413 { 0, SW11_CS13, SW10_CS13, SW12_CS13 }, //D413
{ 0, K_14, J_14, L_14 }, //D414 { 0, SW11_CS14, SW10_CS14, SW12_CS14 }, //D414
{ 0, K_15, J_15, L_15 }, //D415 { 0, SW11_CS15, SW10_CS15, SW12_CS15 }, //D415
{ 0, K_1, J_1, L_1 }, //D401 { 0, SW11_CS1, SW10_CS1, SW12_CS1 }, //D401
{ 0, H_4, G_4, I_4 }, //D420 { 0, SW8_CS4, SW7_CS4, SW9_CS4 }, //D420
{ 0, H_5, G_5, I_5 }, //D421 { 0, SW8_CS5, SW7_CS5, SW9_CS5 }, //D421
{ 0, H_6, G_6, I_6 }, //D422 { 0, SW8_CS6, SW7_CS6, SW9_CS6 }, //D422
{ 0, H_7, G_7, I_7 }, //D423 { 0, SW8_CS7, SW7_CS7, SW9_CS7 }, //D423
{ 0, H_8, G_8, I_8 }, //D424 { 0, SW8_CS8, SW7_CS8, SW9_CS8 }, //D424
{ 0, H_9, G_9, I_9 }, //D425 { 0, SW8_CS9, SW7_CS9, SW9_CS9 }, //D425
{ 0, H_10, G_10, I_10 }, //D426 { 0, SW8_CS10, SW7_CS10, SW9_CS10 }, //D426
{ 0, H_11, G_11, I_11 }, //D427 { 0, SW8_CS11, SW7_CS11, SW9_CS11 }, //D427
{ 0, H_12, G_12, I_12 }, //D428 { 0, SW8_CS12, SW7_CS12, SW9_CS12 }, //D428
{ 0, H_13, G_13, I_13 }, //D429 { 0, SW8_CS13, SW7_CS13, SW9_CS13 }, //D429
{ 0, H_14, G_14, I_14 }, //D430 { 0, SW8_CS14, SW7_CS14, SW9_CS14 }, //D430
{ 0, H_15, G_15, I_15 }, //D431 { 0, SW8_CS15, SW7_CS15, SW9_CS15 }, //D431
{ 0, K_16, J_16, L_16 }, //D416 { 0, SW11_CS16, SW10_CS16, SW12_CS16 }, //D416
{ 0, H_2, G_2, I_2 }, //D418 { 0, SW8_CS2, SW7_CS2, SW9_CS2 }, //D418
{ 0, H_3, G_3, I_3 }, //D419 { 0, SW8_CS3, SW7_CS3, SW9_CS3 }, //D419
{ 0, E_5, D_5, F_5 }, //D437 { 0, SW5_CS5, SW4_CS5, SW6_CS5 }, //D437
{ 0, E_6, D_6, F_6 }, //D438 { 0, SW5_CS6, SW4_CS6, SW6_CS6 }, //D438
{ 0, E_7, D_7, F_7 }, //D439 { 0, SW5_CS7, SW4_CS7, SW6_CS7 }, //D439
{ 0, E_8, D_8, F_8 }, //D440 { 0, SW5_CS8, SW4_CS8, SW6_CS8 }, //D440
{ 0, E_9, D_9, F_9 }, //D441 { 0, SW5_CS9, SW4_CS9, SW6_CS9 }, //D441
{ 0, E_10, D_10, F_10 }, //D442 { 0, SW5_CS10, SW4_CS10, SW6_CS10 }, //D442
{ 0, E_11, D_11, F_11 }, //D443 { 0, SW5_CS11, SW4_CS11, SW6_CS11 }, //D443
{ 0, E_12, D_12, F_12 }, //D444 { 0, SW5_CS12, SW4_CS12, SW6_CS12 }, //D444
{ 0, E_13, D_13, F_13 }, //D445 { 0, SW5_CS13, SW4_CS13, SW6_CS13 }, //D445
{ 0, E_14, D_14, F_14 }, //D446 { 0, SW5_CS14, SW4_CS14, SW6_CS14 }, //D446
{ 0, H_16, G_16, I_16 }, //D432 { 0, SW8_CS16, SW7_CS16, SW9_CS16 }, //D432
{ 0, H_1, G_1, I_1 }, //D417 { 0, SW8_CS1, SW7_CS1, SW9_CS1 }, //D417
{ 0, E_3, D_3, F_3 }, //D435 { 0, SW5_CS3, SW4_CS3, SW6_CS3 }, //D435
{ 0, E_4, D_4, F_4 }, //D436 { 0, SW5_CS4, SW4_CS4, SW6_CS4 }, //D436
{ 0, B_2, A_2, C_2 }, //D450 { 0, SW2_CS2, SW1_CS2, SW3_CS2 }, //D450
{ 0, B_3, A_3, C_3 }, //D451 { 0, SW2_CS3, SW1_CS3, SW3_CS3 }, //D451
{ 0, B_4, A_4, C_4 }, //D452 { 0, SW2_CS4, SW1_CS4, SW3_CS4 }, //D452
{ 0, B_6, A_6, C_6 }, //D454 { 0, SW2_CS6, SW1_CS6, SW3_CS6 }, //D454
{ 0, B_8, A_8, C_8 }, //D456 { 0, SW2_CS8, SW1_CS8, SW3_CS8 }, //D456
{ 0, B_9, A_9, C_9 }, //D457 { 0, SW2_CS9, SW1_CS9, SW3_CS9 }, //D457
{ 0, B_10, A_10, C_10 }, //D458 { 0, SW2_CS10, SW1_CS10, SW3_CS10 }, //D458
{ 0, B_12, A_12, C_12 }, //D460 { 0, SW2_CS12, SW1_CS12, SW3_CS12 }, //D460
{ 0, B_13, A_13, C_13 }, //D461 { 0, SW2_CS13, SW1_CS13, SW3_CS13 }, //D461
{ 0, E_15, D_15, F_15 }, //D447 { 0, SW5_CS15, SW4_CS15, SW6_CS15 }, //D447
{ 0, E_1, D_1, F_1 }, //D433 { 0, SW5_CS1, SW4_CS1, SW6_CS1 }, //D433
{ 0, E_2, D_2, F_2 }, //D434 { 0, SW5_CS2, SW4_CS2, SW6_CS2 }, //D434
{ 0, B_1, A_1, C_1 }, //D449 { 0, SW2_CS1, SW1_CS1, SW3_CS1 }, //D449
{ 0, B_7, A_7, C_7 }, //D455 { 0, SW2_CS7, SW1_CS7, SW3_CS7 }, //D455
{ 0, B_11, A_11, C_11 }, //D459 { 0, SW2_CS11, SW1_CS11, SW3_CS11 }, //D459
{ 0, B_14, A_14, C_14 }, //D462 { 0, SW2_CS14, SW1_CS14, SW3_CS14 }, //D462
{ 0, B_15, A_15, C_15 }, //D463 { 0, SW2_CS15, SW1_CS15, SW3_CS15 }, //D463
{ 0, B_16, A_16, C_16 } //D464 { 0, SW2_CS16, SW1_CS16, SW3_CS16 } //D464
}; };
#define XXX NO_LED #define XXX NO_LED

View File

@ -30,8 +30,6 @@
"rows": ["C2", "D0", "B0", "C7", "C5"] "rows": ["C2", "D0", "B0", "C7", "C5"]
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,

View File

@ -26,8 +26,6 @@
"rows": ["B8", "A15", "C13", "A2", "A6"] "rows": ["B8", "A15", "C13", "A2", "A6"]
}, },
"features": { "features": {
"audio": false,
"backlight": false,
"bootmagic": true, "bootmagic": true,
"command": false, "command": false,
"console": false, "console": false,

View File

@ -22,9 +22,7 @@
"console": false, "console": false,
"command": false, "command": false,
"nkro": true, "nkro": true,
"backlight": false, "rgblight": true
"rgblight": true,
"audio": false
}, },
"ws2812": { "ws2812": {
"pin": "A8" "pin": "A8"

View File

@ -17,94 +17,94 @@
#include QMK_KEYBOARD_H #include QMK_KEYBOARD_H
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = { const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
{0, G_1, I_1, H_1}, {0, SW7_CS1, SW9_CS1, SW8_CS1},
{0, G_3, I_3, H_3}, {0, SW7_CS3, SW9_CS3, SW8_CS3},
{0, G_4, I_4, H_4}, {0, SW7_CS4, SW9_CS4, SW8_CS4},
{0, G_5, I_5, H_5}, {0, SW7_CS5, SW9_CS5, SW8_CS5},
{0, G_6, I_6, H_6}, {0, SW7_CS6, SW9_CS6, SW8_CS6},
{0, G_7, I_7, H_7}, {0, SW7_CS7, SW9_CS7, SW8_CS7},
{0, G_8, I_8, H_8}, {0, SW7_CS8, SW9_CS8, SW8_CS8},
{0, G_9, I_9, H_9}, {0, SW7_CS9, SW9_CS9, SW8_CS9},
{0, G_10, I_10, H_10}, {0, SW7_CS10, SW9_CS10, SW8_CS10},
{0, G_11, I_11, H_11}, {0, SW7_CS11, SW9_CS11, SW8_CS11},
{0, G_12, I_12, H_12}, {0, SW7_CS12, SW9_CS12, SW8_CS12},
{0, G_13, I_13, H_13}, {0, SW7_CS13, SW9_CS13, SW8_CS13},
{0, G_14, I_14, H_14}, {0, SW7_CS14, SW9_CS14, SW8_CS14},
{0, G_15, I_15, H_15}, {0, SW7_CS15, SW9_CS15, SW8_CS15},
{0, D_1, F_1, E_1}, {0, SW4_CS1, SW6_CS1, SW5_CS1},
{0, D_2, F_2, E_2}, {0, SW4_CS2, SW6_CS2, SW5_CS2},
{0, D_3, F_3, E_3}, {0, SW4_CS3, SW6_CS3, SW5_CS3},
{0, D_4, F_4, E_4}, {0, SW4_CS4, SW6_CS4, SW5_CS4},
{0, D_5, F_5, E_5}, {0, SW4_CS5, SW6_CS5, SW5_CS5},
{0, D_6, F_6, E_6}, {0, SW4_CS6, SW6_CS6, SW5_CS6},
{0, D_7, F_7, E_7}, {0, SW4_CS7, SW6_CS7, SW5_CS7},
{0, D_8, F_8, E_8}, {0, SW4_CS8, SW6_CS8, SW5_CS8},
{0, D_9, F_9, E_9}, {0, SW4_CS9, SW6_CS9, SW5_CS9},
{0, D_10, F_10, E_10}, {0, SW4_CS10, SW6_CS10, SW5_CS10},
{0, D_11, F_11, E_11}, {0, SW4_CS11, SW6_CS11, SW5_CS11},
{0, D_12, F_12, E_12}, {0, SW4_CS12, SW6_CS12, SW5_CS12},
{0, D_13, F_13, E_13}, {0, SW4_CS13, SW6_CS13, SW5_CS13},
{0, D_14, F_14, E_14}, {0, SW4_CS14, SW6_CS14, SW5_CS14},
{0, D_15, F_15, E_15}, {0, SW4_CS15, SW6_CS15, SW5_CS15},
{0, A_1, C_1, B_1}, {0, SW1_CS1, SW3_CS1, SW2_CS1},
{0, A_2, C_2, B_2}, {0, SW1_CS2, SW3_CS2, SW2_CS2},
{0, A_3, C_3, B_3}, {0, SW1_CS3, SW3_CS3, SW2_CS3},
{0, A_4, C_4, B_4}, {0, SW1_CS4, SW3_CS4, SW2_CS4},
{0, A_5, C_5, B_5}, {0, SW1_CS5, SW3_CS5, SW2_CS5},
{0, A_6, C_6, B_6}, {0, SW1_CS6, SW3_CS6, SW2_CS6},
{0, A_7, C_7, B_7}, {0, SW1_CS7, SW3_CS7, SW2_CS7},
{0, A_8, C_8, B_8}, {0, SW1_CS8, SW3_CS8, SW2_CS8},
{0, A_9, C_9, B_9}, {0, SW1_CS9, SW3_CS9, SW2_CS9},
{0, A_10, C_10, B_10}, {0, SW1_CS10, SW3_CS10, SW2_CS10},
{0, A_11, C_11, B_11}, {0, SW1_CS11, SW3_CS11, SW2_CS11},
{0, A_12, C_12, B_12}, {0, SW1_CS12, SW3_CS12, SW2_CS12},
{0, A_13, C_13, B_13}, {0, SW1_CS13, SW3_CS13, SW2_CS13},
{0, A_14, C_14, B_14}, {0, SW1_CS14, SW3_CS14, SW2_CS14},
{0, A_15, C_15, B_15}, {0, SW1_CS15, SW3_CS15, SW2_CS15},
{1, G_1, I_1, H_1}, {1, SW7_CS1, SW9_CS1, SW8_CS1},
{1, G_2, I_2, H_2}, {1, SW7_CS2, SW9_CS2, SW8_CS2},
{1, G_3, I_3, H_3}, {1, SW7_CS3, SW9_CS3, SW8_CS3},
{1, G_4, I_4, H_4}, {1, SW7_CS4, SW9_CS4, SW8_CS4},
{1, G_5, I_5, H_5}, {1, SW7_CS5, SW9_CS5, SW8_CS5},
{1, G_6, I_6, H_6}, {1, SW7_CS6, SW9_CS6, SW8_CS6},
{1, G_7, I_7, H_7}, {1, SW7_CS7, SW9_CS7, SW8_CS7},
{1, G_8, I_8, H_8}, {1, SW7_CS8, SW9_CS8, SW8_CS8},
{1, G_9, I_9, H_9}, {1, SW7_CS9, SW9_CS9, SW8_CS9},
{1, G_10, I_10, H_10}, {1, SW7_CS10, SW9_CS10, SW8_CS10},
{1, G_11, I_11, H_11}, {1, SW7_CS11, SW9_CS11, SW8_CS11},
{1, G_12, I_12, H_12}, {1, SW7_CS12, SW9_CS12, SW8_CS12},
{1, G_13, I_13, H_13}, {1, SW7_CS13, SW9_CS13, SW8_CS13},
{1, G_14, I_14, H_14}, {1, SW7_CS14, SW9_CS14, SW8_CS14},
{1, G_15, I_15, H_15}, {1, SW7_CS15, SW9_CS15, SW8_CS15},
{1, D_1, F_1, E_1}, {1, SW4_CS1, SW6_CS1, SW5_CS1},
{1, D_2, F_2, E_2}, {1, SW4_CS2, SW6_CS2, SW5_CS2},
{1, D_3, F_3, E_3}, {1, SW4_CS3, SW6_CS3, SW5_CS3},
{1, D_4, F_4, E_4}, {1, SW4_CS4, SW6_CS4, SW5_CS4},
{1, D_5, F_5, E_5}, {1, SW4_CS5, SW6_CS5, SW5_CS5},
{1, D_6, F_6, E_6}, {1, SW4_CS6, SW6_CS6, SW5_CS6},
{1, D_7, F_7, E_7}, {1, SW4_CS7, SW6_CS7, SW5_CS7},
{1, D_8, F_8, E_8}, {1, SW4_CS8, SW6_CS8, SW5_CS8},
{1, D_9, F_9, E_9}, {1, SW4_CS9, SW6_CS9, SW5_CS9},
{1, D_10, F_10, E_10}, {1, SW4_CS10, SW6_CS10, SW5_CS10},
{1, D_11, F_11, E_11}, {1, SW4_CS11, SW6_CS11, SW5_CS11},
{1, D_12, F_12, E_12}, {1, SW4_CS12, SW6_CS12, SW5_CS12},
{1, D_13, F_13, E_13}, {1, SW4_CS13, SW6_CS13, SW5_CS13},
{1, D_14, F_14, E_14}, {1, SW4_CS14, SW6_CS14, SW5_CS14},
{1, D_15, F_15, E_15}, {1, SW4_CS15, SW6_CS15, SW5_CS15},
{1, A_1, C_1, B_1}, {1, SW1_CS1, SW3_CS1, SW2_CS1},
{1, A_2, C_2, B_2}, {1, SW1_CS2, SW3_CS2, SW2_CS2},
{1, A_3, C_3, B_3}, {1, SW1_CS3, SW3_CS3, SW2_CS3},
{1, A_5, C_5, B_5}, {1, SW1_CS5, SW3_CS5, SW2_CS5},
{1, A_6, C_6, B_6}, {1, SW1_CS6, SW3_CS6, SW2_CS6},
{1, A_7, C_7, B_7}, {1, SW1_CS7, SW3_CS7, SW2_CS7},
{1, A_8, C_8, B_8}, {1, SW1_CS8, SW3_CS8, SW2_CS8},
{1, A_9, C_9, B_9}, {1, SW1_CS9, SW3_CS9, SW2_CS9},
{1, A_10, C_10, B_10}, {1, SW1_CS10, SW3_CS10, SW2_CS10},
{1, A_11, C_11, B_11}, {1, SW1_CS11, SW3_CS11, SW2_CS11},
{1, A_12, C_12, B_12}, {1, SW1_CS12, SW3_CS12, SW2_CS12},
{1, A_13, C_13, B_13}, {1, SW1_CS13, SW3_CS13, SW2_CS13},
{1, A_14, C_14, B_14}, {1, SW1_CS14, SW3_CS14, SW2_CS14},
{1, A_15, C_15, B_15}, {1, SW1_CS15, SW3_CS15, SW2_CS15},
{0, G_2, I_2, H_2}, {0, SW7_CS2, SW9_CS2, SW8_CS2},
{1, A_4, C_4, B_4} {1, SW1_CS4, SW3_CS4, SW2_CS4}
}; };

View File

@ -28,5 +28,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define WS2812_PWM_DRIVER PWMD1 #define WS2812_PWM_DRIVER PWMD1
#define WS2812_PWM_CHANNEL 3 #define WS2812_PWM_CHANNEL 3
#define WS2812_PWM_PAL_MODE 1 #define WS2812_PWM_PAL_MODE 1
#define WS2812_DMA_STREAM STM32_DMA2_STREAM5 #define WS2812_PWM_DMA_STREAM STM32_DMA2_STREAM5
#define WS2812_DMA_CHANNEL 6 #define WS2812_PWM_DMA_CHANNEL 6

View File

@ -26,98 +26,98 @@ const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = {
* | | | B location * | | | B location
* | | | | */ * | | | | */
// First row // First row
{0, CS7_SW9 , CS9_SW9 , CS8_SW9 }, //ESC 0 {0, SW9_CS7 , SW9_CS9 , SW9_CS8 }, //ESC 0
{0, CS7_SW8 , CS9_SW8 , CS8_SW8 }, //F1 1 {0, SW8_CS7 , SW8_CS9 , SW8_CS8 }, //F1 1
{0, CS7_SW7 , CS9_SW7 , CS8_SW7 }, //F2 2 {0, SW7_CS7 , SW7_CS9 , SW7_CS8 }, //F2 2
{0, CS7_SW6 , CS9_SW6 , CS8_SW6 }, //F3 3 {0, SW6_CS7 , SW6_CS9 , SW6_CS8 }, //F3 3
{0, CS7_SW5 , CS9_SW5 , CS8_SW5 }, //F4 4 {0, SW5_CS7 , SW5_CS9 , SW5_CS8 }, //F4 4
{0, CS7_SW4 , CS9_SW4 , CS8_SW4 }, //F5 5 {0, SW4_CS7 , SW4_CS9 , SW4_CS8 }, //F5 5
{0, CS7_SW3 , CS9_SW3 , CS8_SW3 }, //F6 6 {0, SW3_CS7 , SW3_CS9 , SW3_CS8 }, //F6 6
{0, CS7_SW2 , CS9_SW2 , CS8_SW2 }, //F7 7 {0, SW2_CS7 , SW2_CS9 , SW2_CS8 }, //F7 7
{0, CS7_SW1 , CS9_SW1 , CS8_SW1 }, //F8 8 {0, SW1_CS7 , SW1_CS9 , SW1_CS8 }, //F8 8
{0, CS18_SW2, CS16_SW2, CS17_SW2 }, //F9 9 {0, SW2_CS18, SW2_CS16, SW2_CS17 }, //F9 9
{0, CS18_SW3, CS16_SW3, CS17_SW3 }, //F10 10 {0, SW3_CS18, SW3_CS16, SW3_CS17 }, //F10 10
{0, CS18_SW4, CS16_SW4, CS17_SW4 }, //F11 11 {0, SW4_CS18, SW4_CS16, SW4_CS17 }, //F11 11
{0, CS18_SW6, CS16_SW6, CS17_SW6 }, //F12 12 {0, SW6_CS18, SW6_CS16, SW6_CS17 }, //F12 12
{0, CS18_SW7, CS16_SW7, CS17_SW7 }, //PRI 13 {0, SW7_CS18, SW7_CS16, SW7_CS17 }, //PRI 13
{0, CS18_SW8, CS16_SW8, CS17_SW8 }, //SCR 14 {0, SW8_CS18, SW8_CS16, SW8_CS17 }, //SCR 14
{0, CS18_SW9, CS16_SW9, CS17_SW9 }, //PAUS 15 {0, SW9_CS18, SW9_CS16, SW9_CS17 }, //PAUS 15
//Second row //Second row
{0, CS12_SW9, CS11_SW9, CS10_SW9 }, //GRAVE 16 {0, SW9_CS12, SW9_CS11, SW9_CS10 }, //GRAVE 16
{0, CS12_SW8, CS11_SW8, CS10_SW8 }, //1 17 {0, SW8_CS12, SW8_CS11, SW8_CS10 }, //1 17
{0, CS12_SW7, CS11_SW7, CS10_SW7 }, //2 18 {0, SW7_CS12, SW7_CS11, SW7_CS10 }, //2 18
{0, CS12_SW6, CS11_SW6, CS10_SW6 }, //3 19 {0, SW6_CS12, SW6_CS11, SW6_CS10 }, //3 19
{0, CS12_SW5, CS11_SW5, CS10_SW5 }, //4 20 {0, SW5_CS12, SW5_CS11, SW5_CS10 }, //4 20
{0, CS12_SW4, CS11_SW4, CS10_SW4 }, //5 21 {0, SW4_CS12, SW4_CS11, SW4_CS10 }, //5 21
{0, CS12_SW3, CS11_SW3, CS10_SW3 }, //6 22 {0, SW3_CS12, SW3_CS11, SW3_CS10 }, //6 22
{0, CS12_SW2, CS11_SW2, CS10_SW2 }, //7 23 {0, SW2_CS12, SW2_CS11, SW2_CS10 }, //7 23
{0, CS12_SW1, CS11_SW1, CS10_SW1 }, //8 24 {0, SW1_CS12, SW1_CS11, SW1_CS10 }, //8 24
{0, CS15_SW1, CS13_SW1, CS14_SW1 }, //9 25 {0, SW1_CS15, SW1_CS13, SW1_CS14 }, //9 25
{0, CS15_SW2, CS13_SW2, CS14_SW2 }, //0 26 {0, SW2_CS15, SW2_CS13, SW2_CS14 }, //0 26
{0, CS15_SW3, CS13_SW3, CS14_SW3 }, //MINUS 27 {0, SW3_CS15, SW3_CS13, SW3_CS14 }, //MINUS 27
{0, CS15_SW4, CS13_SW4, CS14_SW4 }, //PLUS 28 {0, SW4_CS15, SW4_CS13, SW4_CS14 }, //PLUS 28
{0, CS15_SW5, CS13_SW5, CS14_SW5 }, //BKSP 29 {0, SW5_CS15, SW5_CS13, SW5_CS14 }, //BKSP 29
{0, CS15_SW7, CS13_SW7, CS14_SW7 }, //INS 30 {0, SW7_CS15, SW7_CS13, SW7_CS14 }, //INS 30
{0, CS15_SW8, CS13_SW8, CS14_SW8 }, //HOME 31 {0, SW8_CS15, SW8_CS13, SW8_CS14 }, //HOME 31
{0, CS15_SW9, CS13_SW9, CS14_SW9 }, //PGUP 32 {0, SW9_CS15, SW9_CS13, SW9_CS14 }, //PGUP 32
//Third row //Third row
{0, CS4_SW9 , CS6_SW9 , CS5_SW9 }, //TAB 33 {0, SW9_CS4 , SW9_CS6 , SW9_CS5 }, //TAB 33
{0, CS4_SW8 , CS6_SW8 , CS5_SW8 }, //Q 34 {0, SW8_CS4 , SW8_CS6 , SW8_CS5 }, //Q 34
{0, CS4_SW7 , CS6_SW7 , CS5_SW7 }, //W 35 {0, SW7_CS4 , SW7_CS6 , SW7_CS5 }, //W 35
{0, CS4_SW6 , CS6_SW6 , CS5_SW6 }, //E 36 {0, SW6_CS4 , SW6_CS6 , SW6_CS5 }, //E 36
{0, CS4_SW5 , CS6_SW5 , CS5_SW5 }, //R 37 {0, SW5_CS4 , SW5_CS6 , SW5_CS5 }, //R 37
{0, CS4_SW4 , CS6_SW4 , CS5_SW4 }, //T 38 {0, SW4_CS4 , SW4_CS6 , SW4_CS5 }, //T 38
{0, CS4_SW3 , CS6_SW3 , CS5_SW3 }, //Y 39 {0, SW3_CS4 , SW3_CS6 , SW3_CS5 }, //Y 39
{0, CS4_SW2 , CS6_SW2 , CS5_SW2 }, //U 40 {0, SW2_CS4 , SW2_CS6 , SW2_CS5 }, //U 40
{0, CS4_SW1 , CS6_SW1 , CS5_SW1 }, //I 41 {0, SW1_CS4 , SW1_CS6 , SW1_CS5 }, //I 41
{0, CS3_SW2 , CS1_SW2 , CS2_SW2 }, //O 42 {0, SW2_CS3 , SW2_CS1 , SW2_CS2 }, //O 42
{0, CS3_SW3 , CS1_SW3 , CS2_SW3 }, //P 43 {0, SW3_CS3 , SW3_CS1 , SW3_CS2 }, //P 43
{0, CS3_SW4 , CS1_SW4 , CS2_SW4 }, //LBRKT 44 {0, SW4_CS3 , SW4_CS1 , SW4_CS2 }, //LBRKT 44
{0, CS3_SW5 , CS1_SW5 , CS2_SW5 }, //RBRKT 45 {0, SW5_CS3 , SW5_CS1 , SW5_CS2 }, //RBRKT 45
{0, CS3_SW6 , CS1_SW6 , CS2_SW6 }, //BSLS 46 {0, SW6_CS3 , SW6_CS1 , SW6_CS2 }, //BSLS 46
{0, CS3_SW7 , CS1_SW7 , CS2_SW7 }, //DEL 47 {0, SW7_CS3 , SW7_CS1 , SW7_CS2 }, //DEL 47
{0, CS3_SW8 , CS1_SW8 , CS2_SW8 }, //END 48 {0, SW8_CS3 , SW8_CS1 , SW8_CS2 }, //END 48
{0, CS3_SW9 , CS1_SW9 , CS2_SW9 }, //PGDN 49 {0, SW9_CS3 , SW9_CS1 , SW9_CS2 }, //PGDN 49
//Fourth row //Fourth row
{0, CS33_SW9, CS32_SW9, CS31_SW9 }, //CAPS 50 {0, SW9_CS33, SW9_CS32, SW9_CS31 }, //CAPS 50
{0, CS33_SW8, CS32_SW8, CS31_SW8 }, //A 51 {0, SW8_CS33, SW8_CS32, SW8_CS31 }, //A 51
{0, CS33_SW7, CS32_SW7, CS31_SW7 }, //S 52 {0, SW7_CS33, SW7_CS32, SW7_CS31 }, //S 52
{0, CS33_SW6, CS32_SW6, CS31_SW6 }, //D 53 {0, SW6_CS33, SW6_CS32, SW6_CS31 }, //D 53
{0, CS33_SW5, CS32_SW5, CS31_SW5 }, //F 54 {0, SW5_CS33, SW5_CS32, SW5_CS31 }, //F 54
{0, CS33_SW4, CS32_SW4, CS31_SW4 }, //G 55 {0, SW4_CS33, SW4_CS32, SW4_CS31 }, //G 55
{0, CS33_SW3, CS32_SW3, CS31_SW3 }, //H 56 {0, SW3_CS33, SW3_CS32, SW3_CS31 }, //H 56
{0, CS33_SW2, CS32_SW2, CS31_SW2 }, //J 57 {0, SW2_CS33, SW2_CS32, SW2_CS31 }, //J 57
{0, CS33_SW1, CS32_SW1, CS31_SW1 }, //K 58 {0, SW1_CS33, SW1_CS32, SW1_CS31 }, //K 58
{0, CS39_SW2, CS38_SW2, CS37_SW2 }, //L 59 {0, SW2_CS39, SW2_CS38, SW2_CS37 }, //L 59
{0, CS39_SW3, CS38_SW3, CS37_SW3 }, //COLON 60 {0, SW3_CS39, SW3_CS38, SW3_CS37 }, //COLON 60
{0, CS39_SW4, CS38_SW4, CS37_SW4 }, //QUOTE 61 {0, SW4_CS39, SW4_CS38, SW4_CS37 }, //QUOTE 61
{0, CS39_SW6, CS38_SW6, CS37_SW6 }, //ENTER 62 {0, SW6_CS39, SW6_CS38, SW6_CS37 }, //ENTER 62
//Fifth row //Fifth row
{0, CS30_SW9, CS28_SW9, CS29_SW9 }, //LSFT 63 {0, SW9_CS30, SW9_CS28, SW9_CS29 }, //LSFT 63
{0, CS30_SW7, CS28_SW7, CS29_SW7 }, //Z 64 {0, SW7_CS30, SW7_CS28, SW7_CS29 }, //Z 64
{0, CS30_SW6, CS28_SW6, CS29_SW6 }, //X 65 {0, SW6_CS30, SW6_CS28, SW6_CS29 }, //X 65
{0, CS30_SW5, CS28_SW5, CS29_SW5 }, //C 66 {0, SW5_CS30, SW5_CS28, SW5_CS29 }, //C 66
{0, CS30_SW4, CS28_SW4, CS29_SW4 }, //V 67 {0, SW4_CS30, SW4_CS28, SW4_CS29 }, //V 67
{0, CS30_SW3, CS28_SW3, CS29_SW3 }, //B 68 {0, SW3_CS30, SW3_CS28, SW3_CS29 }, //B 68
{0, CS30_SW2, CS28_SW2, CS29_SW2 }, //N 69 {0, SW2_CS30, SW2_CS28, SW2_CS29 }, //N 69
{0, CS30_SW1, CS28_SW1, CS29_SW1 }, //M 70 {0, SW1_CS30, SW1_CS28, SW1_CS29 }, //M 70
{0, CS36_SW1, CS35_SW1, CS34_SW1 }, //COMMA 71 {0, SW1_CS36, SW1_CS35, SW1_CS34 }, //COMMA 71
{0, CS36_SW3, CS35_SW3, CS34_SW3 }, //DOT 72 {0, SW3_CS36, SW3_CS35, SW3_CS34 }, //DOT 72
{0, CS36_SW4, CS35_SW4, CS34_SW4 }, //SLASH 73 {0, SW4_CS36, SW4_CS35, SW4_CS34 }, //SLASH 73
{0, CS36_SW6, CS35_SW6, CS34_SW6 }, //RSFT 74 {0, SW6_CS36, SW6_CS35, SW6_CS34 }, //RSFT 74
{0, CS36_SW7, CS35_SW7, CS34_SW7 }, //UP 75 {0, SW7_CS36, SW7_CS35, SW7_CS34 }, //UP 75
//Sixth row //Sixth row
{0, CS27_SW9, CS25_SW9, CS26_SW9 }, //LCTRL 76 {0, SW9_CS27, SW9_CS25, SW9_CS26 }, //LCTRL 76
{0, CS27_SW7, CS25_SW7, CS26_SW7 }, //LWIN 77 {0, SW7_CS27, SW7_CS25, SW7_CS26 }, //LWIN 77
{0, CS27_SW6, CS25_SW6, CS26_SW6 }, //LALT 78 {0, SW6_CS27, SW6_CS25, SW6_CS26 }, //LALT 78
{0, CS27_SW5, CS25_SW5, CS26_SW5 }, //SPACE 79 {0, SW5_CS27, SW5_CS25, SW5_CS26 }, //SPACE 79
{0, CS27_SW3, CS25_SW3, CS26_SW3 }, //RALT 80 {0, SW3_CS27, SW3_CS25, SW3_CS26 }, //RALT 80
{0, CS24_SW4, CS23_SW4, CS22_SW4 }, //RGUI 81 {0, SW4_CS24, SW4_CS23, SW4_CS22 }, //RGUI 81
{0, CS24_SW5, CS23_SW5, CS22_SW5 }, //MENU 82 {0, SW5_CS24, SW5_CS23, SW5_CS22 }, //MENU 82
{0, CS24_SW6, CS23_SW6, CS22_SW6 }, //RCTRL 83 {0, SW6_CS24, SW6_CS23, SW6_CS22 }, //RCTRL 83
{0, CS24_SW1, CS23_SW1, CS22_SW1 }, //LEFT 84 {0, SW1_CS24, SW1_CS23, SW1_CS22 }, //LEFT 84
{0, CS24_SW2, CS23_SW2, CS22_SW2 }, //DOWN 85 {0, SW2_CS24, SW2_CS23, SW2_CS22 }, //DOWN 85
{0, CS24_SW3, CS23_SW3, CS22_SW3 }, //RIGHT 86 {0, SW3_CS24, SW3_CS23, SW3_CS22 }, //RIGHT 86
}; };

View File

@ -28,5 +28,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define WS2812_PWM_DRIVER PWMD1 #define WS2812_PWM_DRIVER PWMD1
#define WS2812_PWM_CHANNEL 3 #define WS2812_PWM_CHANNEL 3
#define WS2812_PWM_PAL_MODE 1 #define WS2812_PWM_PAL_MODE 1
#define WS2812_DMA_STREAM STM32_DMA2_STREAM5 #define WS2812_PWM_DMA_STREAM STM32_DMA2_STREAM5
#define WS2812_DMA_CHANNEL 6 #define WS2812_PWM_DMA_CHANNEL 6

View File

@ -28,5 +28,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define WS2812_PWM_DRIVER PWMD1 #define WS2812_PWM_DRIVER PWMD1
#define WS2812_PWM_CHANNEL 3 #define WS2812_PWM_CHANNEL 3
#define WS2812_PWM_PAL_MODE 1 #define WS2812_PWM_PAL_MODE 1
#define WS2812_DMA_STREAM STM32_DMA2_STREAM5 #define WS2812_PWM_DMA_STREAM STM32_DMA2_STREAM5
#define WS2812_DMA_CHANNEL 6 #define WS2812_PWM_DMA_CHANNEL 6

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