mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-09-10 17:15:43 +00:00
Compare commits
1 Commits
potentiome
...
more_dd_ee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
668c29ca52 |
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
qmk --verbose generate-docs
|
||||
|
||||
- name: Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@v4.5.0
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BASE_BRANCH: master
|
||||
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
- uses: actions/labeler@main
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
configuration-path: '.github/labeler.yml'
|
||||
|
||||
3
.github/workflows/stale.yml
vendored
3
.github/workflows/stale.yml
vendored
@@ -3,7 +3,6 @@ name: 'Close stale issues and PRs'
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
actions: write
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@@ -14,7 +13,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@main
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
30
Makefile
30
Makefile
@@ -38,11 +38,6 @@ $(info QMK Firmware $(QMK_VERSION))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Try to determine userspace from qmk config, if set.
|
||||
ifeq ($(QMK_USERSPACE),)
|
||||
QMK_USERSPACE = $(shell qmk config -ro user.overlay_dir | cut -d= -f2 | sed -e 's@^None$$@@g')
|
||||
endif
|
||||
|
||||
# Determine which qmk cli to use
|
||||
QMK_BIN := qmk
|
||||
|
||||
@@ -196,20 +191,9 @@ define PARSE_KEYBOARD
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/keymaps/*/.)))
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/keymaps/*/.)))
|
||||
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_1)/keymaps/*/.)))
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_2)/keymaps/*/.)))
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_3)/keymaps/*/.)))
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/keymaps/*/.)))
|
||||
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/keymaps/*/.)))
|
||||
endif
|
||||
|
||||
KEYBOARD_LAYOUTS := $(shell $(QMK_BIN) list-layouts --keyboard $1)
|
||||
LAYOUT_KEYMAPS :=
|
||||
$$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/layouts/*/$$(LAYOUT)/*/.)))))
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
$$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(QMK_USERSPACE)/layouts/$$(LAYOUT)/*/.)))))
|
||||
endif
|
||||
|
||||
KEYMAPS := $$(sort $$(KEYMAPS) $$(LAYOUT_KEYMAPS))
|
||||
|
||||
@@ -447,18 +431,8 @@ clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
echo 'done.'
|
||||
|
||||
.PHONY: distclean distclean_qmk
|
||||
distclean: distclean_qmk
|
||||
distclean_qmk: clean
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
echo -n 'Deleting *.bin, *.hex, and *.uf2 ... '
|
||||
rm -f *.bin *.hex *.uf2
|
||||
echo 'done.'
|
||||
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
.PHONY: distclean_userspace
|
||||
distclean: distclean_userspace
|
||||
distclean_userspace: clean
|
||||
echo -n 'Deleting userspace *.bin, *.hex, and *.uf2 ... '
|
||||
rm -f $(QMK_USERSPACE)/*.bin $(QMK_USERSPACE)/*.hex $(QMK_USERSPACE)/*.uf2
|
||||
echo 'done.'
|
||||
endif
|
||||
|
||||
@@ -15,22 +15,3 @@ else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
|
||||
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json
|
||||
KEYMAP_JSON_PATH := $(MAIN_KEYMAP_PATH_1)
|
||||
endif
|
||||
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.json)","")
|
||||
KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.json
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.json)","")
|
||||
KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.json
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.json)","")
|
||||
KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.json
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.json)","")
|
||||
KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.json
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.json)","")
|
||||
KEYMAP_JSON := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.json
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -127,60 +127,34 @@ include $(INFO_RULES_MK)
|
||||
include $(BUILDDEFS_PATH)/build_json.mk
|
||||
|
||||
# Pull in keymap level rules.mk
|
||||
ifeq ("$(wildcard $(KEYMAP_PATH))", "")
|
||||
# Look through the possible keymap folders until we find a matching keymap.c
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.c)","")
|
||||
-include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/rules.mk
|
||||
KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)/keymap.c
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_1)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.c)","")
|
||||
-include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/rules.mk
|
||||
KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)/keymap.c
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.c)","")
|
||||
-include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/rules.mk
|
||||
KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)/keymap.c
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.c)","")
|
||||
-include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/rules.mk
|
||||
KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)/keymap.c
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.c)","")
|
||||
-include $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/rules.mk
|
||||
KEYMAP_C := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)/keymap.c
|
||||
KEYMAP_PATH := $(QMK_USERSPACE)/$(MAIN_KEYMAP_PATH_5)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(KEYMAP_PATH),)
|
||||
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_1)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_2)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_3)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_4)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_5)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
|
||||
else ifneq ($(LAYOUTS),)
|
||||
# If we haven't found a keymap yet fall back to community layouts
|
||||
include $(BUILDDEFS_PATH)/build_layout.mk
|
||||
else ifeq ("$(wildcard $(KEYMAP_JSON_PATH))", "") # Not finding keymap.c is fine if we found a keymap.json
|
||||
$(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
|
||||
# this state should never be reached
|
||||
endif
|
||||
endif
|
||||
# Look through the possible keymap folders until we find a matching keymap.c
|
||||
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_1)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_1)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_2)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_2)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_3)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_3)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_4)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_4)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
|
||||
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
|
||||
-include $(MAIN_KEYMAP_PATH_5)/rules.mk
|
||||
KEYMAP_C := $(MAIN_KEYMAP_PATH_5)/keymap.c
|
||||
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
|
||||
else ifneq ($(LAYOUTS),)
|
||||
# If we haven't found a keymap yet fall back to community layouts
|
||||
include $(BUILDDEFS_PATH)/build_layout.mk
|
||||
# Not finding keymap.c is fine if we found a keymap.json
|
||||
else ifeq ("$(wildcard $(KEYMAP_JSON_PATH))", "")
|
||||
$(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
|
||||
# this state should never be reached
|
||||
endif
|
||||
|
||||
# Have we found a keymap.json?
|
||||
@@ -390,16 +364,6 @@ ifeq ("$(USER_NAME)","")
|
||||
endif
|
||||
USER_PATH := users/$(USER_NAME)
|
||||
|
||||
# If we have userspace, then add it to the lookup VPATH
|
||||
ifneq ($(wildcard $(QMK_USERSPACE)),)
|
||||
VPATH += $(QMK_USERSPACE)
|
||||
endif
|
||||
|
||||
# If the equivalent users directory exists in userspace, use that in preference to anything currently in the main repo
|
||||
ifneq ($(wildcard $(QMK_USERSPACE)/$(USER_PATH)),)
|
||||
USER_PATH := $(QMK_USERSPACE)/$(USER_PATH)
|
||||
endif
|
||||
|
||||
# Pull in user level rules.mk
|
||||
-include $(USER_PATH)/rules.mk
|
||||
ifneq ("$(wildcard $(USER_PATH)/config.h)","")
|
||||
@@ -440,10 +404,6 @@ ifneq ("$(KEYMAP_H)","")
|
||||
CONFIG_H += $(KEYMAP_H)
|
||||
endif
|
||||
|
||||
ifeq ($(KEYMAP_C),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
|
||||
endif
|
||||
|
||||
OPT_DEFS += -DKEYMAP_C=\"$(KEYMAP_C)\"
|
||||
|
||||
# If a keymap or userspace places their keymap array in another file instead, allow for it to be included
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
LAYOUTS_PATH := layouts
|
||||
LAYOUTS_REPOS := $(patsubst %/,%,$(sort $(dir $(wildcard $(LAYOUTS_PATH)/*/))))
|
||||
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
LAYOUTS_REPOS += $(patsubst %/,%,$(QMK_USERSPACE)/$(LAYOUTS_PATH))
|
||||
endif
|
||||
|
||||
define SEARCH_LAYOUTS_REPO
|
||||
LAYOUT_KEYMAP_PATH := $$(LAYOUTS_REPO)/$$(LAYOUT)/$$(KEYMAP)
|
||||
LAYOUT_KEYMAP_JSON := $$(LAYOUT_KEYMAP_PATH)/keymap.json
|
||||
|
||||
@@ -75,7 +75,10 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(SEQUENCER_ENABLE)), yes)
|
||||
OPT_DEFS += -DSEQUENCER_ENABLE
|
||||
MUSIC_ENABLE = yes
|
||||
SRC += $(QUANTUM_DIR)/sequencer/sequencer.c
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(MIDI_ENABLE)), yes)
|
||||
@@ -91,6 +94,11 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
|
||||
endif
|
||||
|
||||
MUSIC_ENABLE ?= no
|
||||
ifeq ($(MUSIC_ENABLE), yes)
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
|
||||
endif
|
||||
|
||||
VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
|
||||
STENO_PROTOCOL ?= all
|
||||
ifeq ($(strip $(STENO_ENABLE)), yes)
|
||||
@@ -116,11 +124,17 @@ ifeq ($(strip $(STENO_ENABLE)), yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
|
||||
MOUSE_ENABLE := yes
|
||||
ifeq ($(strip $(VIRTSER_ENABLE)), yes)
|
||||
OPT_DEFS += -DVIRTSER_ENABLE
|
||||
endif
|
||||
|
||||
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick azoteq_iqs5xx cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball custom
|
||||
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
|
||||
OPT_DEFS += -DMOUSEKEY_ENABLE
|
||||
MOUSE_ENABLE := yes
|
||||
SRC += $(QUANTUM_DIR)/mousekey.c
|
||||
endif
|
||||
|
||||
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball custom
|
||||
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
|
||||
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid POINTING_DEVICE_DRIVER,POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
|
||||
@@ -139,9 +153,8 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
|
||||
ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800)
|
||||
SPI_DRIVER_REQUIRED = yes
|
||||
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick)
|
||||
ANALOG_DRIVER_REQUIRED = yes
|
||||
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), azoteq_iqs5xx)
|
||||
I2C_DRIVER_REQUIRED = yes
|
||||
OPT_DEFS += -DSTM32_ADC -DHAL_USE_ADC=TRUE
|
||||
LIB_SRC += analog.c
|
||||
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_i2c)
|
||||
I2C_DRIVER_REQUIRED = yes
|
||||
SRC += drivers/sensors/cirque_pinnacle.c
|
||||
@@ -313,7 +326,6 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
OPT_DEFS += -DRGBLIGHT_$(strip $(shell echo $(RGBLIGHT_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||
SRC += $(QUANTUM_DIR)/color.c
|
||||
SRC += $(QUANTUM_DIR)/rgblight/rgblight.c
|
||||
SRC += $(QUANTUM_DIR)/rgblight/rgblight_drivers.c
|
||||
CIE1931_CURVE := yes
|
||||
RGB_KEYCODES_ENABLE := yes
|
||||
endif
|
||||
@@ -348,7 +360,10 @@ ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
|
||||
endif
|
||||
OPT_DEFS += -DLED_MATRIX_ENABLE
|
||||
OPT_DEFS += -DLED_MATRIX_$(strip $(shell echo $(LED_MATRIX_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
|
||||
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
|
||||
OPT_DEFS += -DLIB8_ATTINY
|
||||
endif
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners
|
||||
@@ -356,7 +371,7 @@ ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
|
||||
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c
|
||||
SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c
|
||||
LIB8TION_ENABLE := yes
|
||||
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
|
||||
CIE1931_CURVE := yes
|
||||
|
||||
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3218)
|
||||
@@ -448,7 +463,10 @@ ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||
endif
|
||||
OPT_DEFS += -DRGB_MATRIX_ENABLE
|
||||
OPT_DEFS += -DRGB_MATRIX_$(strip $(shell echo $(RGB_MATRIX_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
|
||||
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
|
||||
OPT_DEFS += -DLIB8_ATTINY
|
||||
endif
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners
|
||||
@@ -456,7 +474,7 @@ ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/color.c
|
||||
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c
|
||||
SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c
|
||||
LIB8TION_ENABLE := yes
|
||||
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
|
||||
CIE1931_CURVE := yes
|
||||
RGB_KEYCODES_ENABLE := yes
|
||||
|
||||
@@ -614,6 +632,8 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
|
||||
RAW_ENABLE := yes
|
||||
BOOTMAGIC_ENABLE := yes
|
||||
TRI_LAYER_ENABLE := yes
|
||||
SRC += $(QUANTUM_DIR)/via.c
|
||||
OPT_DEFS += -DVIA_ENABLE
|
||||
endif
|
||||
|
||||
VALID_MAGIC_TYPES := yes
|
||||
@@ -698,20 +718,17 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
|
||||
COMMON_VPATH += $(QUANTUM_PATH)/split_common
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CRC_ENABLE)), yes)
|
||||
OPT_DEFS += -DCRC_ENABLE
|
||||
SRC += crc.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(FNV_ENABLE)), yes)
|
||||
OPT_DEFS += -DFNV_ENABLE
|
||||
VPATH += $(LIB_PATH)/fnv
|
||||
SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(LIB8TION_ENABLE)), yes)
|
||||
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
|
||||
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
|
||||
OPT_DEFS += -DLIB8_ATTINY
|
||||
endif
|
||||
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
|
||||
endif
|
||||
|
||||
VALID_HAPTIC_DRIVER_TYPES := drv2605l solenoid
|
||||
ifeq ($(strip $(HAPTIC_ENABLE)),yes)
|
||||
ifeq ($(filter $(HAPTIC_DRIVER),$(VALID_HAPTIC_DRIVER_TYPES)),)
|
||||
@@ -802,6 +819,27 @@ ifeq ($(strip $(UNICODE_COMMON)), yes)
|
||||
$(QUANTUM_DIR)/unicode/utf8.c
|
||||
endif
|
||||
|
||||
MAGIC_ENABLE ?= yes
|
||||
ifeq ($(strip $(MAGIC_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_magic.c
|
||||
OPT_DEFS += -DMAGIC_KEYCODE_ENABLE
|
||||
endif
|
||||
|
||||
SEND_STRING_ENABLE ?= yes
|
||||
ifeq ($(strip $(SEND_STRING_ENABLE)), yes)
|
||||
OPT_DEFS += -DSEND_STRING_ENABLE
|
||||
COMMON_VPATH += $(QUANTUM_DIR)/send_string
|
||||
SRC += $(QUANTUM_DIR)/send_string/send_string.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
|
||||
OPT_DEFS += -DAUTO_SHIFT_ENABLE
|
||||
ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
|
||||
OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
|
||||
PS2_ENABLE := yes
|
||||
MOUSE_ENABLE := yes
|
||||
@@ -842,8 +880,8 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/joystick.c
|
||||
|
||||
ifeq ($(strip $(JOYSTICK_DRIVER)), analog)
|
||||
ANALOG_DRIVER_REQUIRED = yes
|
||||
OPT_DEFS += -DANALOG_JOYSTICK_ENABLE
|
||||
SRC += analog.c
|
||||
endif
|
||||
ifeq ($(strip $(JOYSTICK_DRIVER)), digital)
|
||||
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
|
||||
@@ -888,9 +926,9 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
|
||||
|
||||
ifeq ($(strip $(BLUETOOTH_DRIVER)), bluefruit_le)
|
||||
SPI_DRIVER_REQUIRED = yes
|
||||
ANALOG_DRIVER_REQUIRED = yes
|
||||
SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
|
||||
SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp
|
||||
QUANTUM_LIB_SRC += analog.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(BLUETOOTH_DRIVER)), rn42)
|
||||
@@ -908,16 +946,14 @@ ifeq ($(strip $(ENCODER_ENABLE)), yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
|
||||
ifeq ($(strip $(DIP_SWITCH_MAP_ENABLE)), yes)
|
||||
OPT_DEFS += -DDIP_SWITCH_MAP_ENABLE
|
||||
ifeq ($(strip $(OS_DETECTION_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/os_detection.c
|
||||
OPT_DEFS += -DOS_DETECTION_ENABLE
|
||||
ifeq ($(strip $(OS_DETECTION_DEBUG_ENABLE)), yes)
|
||||
OPT_DEFS += -DOS_DETECTION_DEBUG_ENABLE
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(POTENTIOMETER_ENABLE)), yes)
|
||||
ANALOG_DRIVER_REQUIRED = yes
|
||||
endif
|
||||
|
||||
VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor
|
||||
|
||||
WS2812_DRIVER ?= bitbang
|
||||
@@ -947,11 +983,6 @@ ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes)
|
||||
SRC += apa102.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(ANALOG_DRIVER_REQUIRED)), yes)
|
||||
OPT_DEFS += -DHAL_USE_ADC=TRUE
|
||||
QUANTUM_LIB_SRC += analog.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(I2C_DRIVER_REQUIRED)), yes)
|
||||
OPT_DEFS += -DHAL_USE_I2C=TRUE
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
|
||||
@@ -191,7 +191,7 @@ DFU_SUFFIX_ARGS ?=
|
||||
elf: $(BUILD_DIR)/$(TARGET).elf
|
||||
hex: $(BUILD_DIR)/$(TARGET).hex
|
||||
uf2: $(BUILD_DIR)/$(TARGET).uf2
|
||||
cpfirmware_qmk: $(FIRMWARE_FORMAT)
|
||||
cpfirmware: $(FIRMWARE_FORMAT)
|
||||
$(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD)
|
||||
$(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK)
|
||||
eep: $(BUILD_DIR)/$(TARGET).eep
|
||||
@@ -200,15 +200,6 @@ sym: $(BUILD_DIR)/$(TARGET).sym
|
||||
LIBNAME=lib$(TARGET).a
|
||||
lib: $(LIBNAME)
|
||||
|
||||
cpfirmware: cpfirmware_qmk
|
||||
|
||||
ifneq ($(QMK_USERSPACE),)
|
||||
cpfirmware: cpfirmware_userspace
|
||||
cpfirmware_userspace: cpfirmware_qmk
|
||||
$(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to userspace folder" | $(AWK_CMD)
|
||||
$(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(QMK_USERSPACE)/$(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK)
|
||||
endif
|
||||
|
||||
# Display size of file, modifying the output so people don't mistakenly grab the hex output
|
||||
BINARY_SIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(SED) -e 's/\.build\/.*$$/$(TARGET).$(FIRMWARE_FORMAT)/g'
|
||||
|
||||
|
||||
@@ -25,9 +25,7 @@ ifneq ($(CONVERT_TO),)
|
||||
-include $(CONVERTER)/pre_converter.mk
|
||||
|
||||
PLATFORM_KEY = $(shell echo $(CONVERTER) | cut -d "/" -f2)
|
||||
|
||||
# force setting as value can be from environment
|
||||
override TARGET := $(TARGET)_$(CONVERT_TO)
|
||||
TARGET := $(TARGET)_$(CONVERT_TO)
|
||||
|
||||
# Configure any defaults
|
||||
OPT_DEFS += -DCONVERT_TO_$(shell echo $(CONVERT_TO) | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
@@ -13,53 +13,38 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
GRAVE_ESC_ENABLE ?= yes
|
||||
MAGIC_ENABLE ?= yes
|
||||
SEND_STRING_ENABLE ?= yes
|
||||
SPACE_CADET_ENABLE ?= yes
|
||||
GRAVE_ESC_ENABLE ?= yes
|
||||
|
||||
GENERIC_FEATURES = \
|
||||
AUTO_SHIFT \
|
||||
AUTOCORRECT \
|
||||
CAPS_WORD \
|
||||
COMBO \
|
||||
COMMAND \
|
||||
CRC \
|
||||
DEFERRED_EXEC \
|
||||
DIGITIZER \
|
||||
DIP_SWITCH \
|
||||
DYNAMIC_KEYMAP \
|
||||
DYNAMIC_MACRO \
|
||||
DYNAMIC_TAPPING_TERM \
|
||||
GRAVE_ESC \
|
||||
HAPTIC \
|
||||
KEY_LOCK \
|
||||
KEY_OVERRIDE \
|
||||
LEADER \
|
||||
MAGIC \
|
||||
MOUSEKEY \
|
||||
MUSIC \
|
||||
OS_DETECTION \
|
||||
POTENTIOMETER \
|
||||
PROGRAMMABLE_BUTTON \
|
||||
REPEAT_KEY \
|
||||
SECURE \
|
||||
SEND_STRING \
|
||||
SEQUENCER \
|
||||
SPACE_CADET \
|
||||
SWAP_HANDS \
|
||||
TAP_DANCE \
|
||||
TRI_LAYER \
|
||||
VIA \
|
||||
VIRTSER \
|
||||
WPM \
|
||||
DYNAMIC_TAPPING_TERM \
|
||||
TRI_LAYER
|
||||
|
||||
define HANDLE_GENERIC_FEATURE
|
||||
# $$(info "Processing: $1_ENABLE $2.c")
|
||||
SRC += $$(wildcard $$(QUANTUM_DIR)/process_keycode/process_$2.c)
|
||||
SRC += $$(wildcard $$(QUANTUM_DIR)/$2/$2.c)
|
||||
SRC += $$(wildcard $$(QUANTUM_DIR)/$2.c)
|
||||
VPATH += $$(wildcard $$(QUANTUM_DIR)/$2/)
|
||||
OPT_DEFS += -D$1_ENABLE
|
||||
endef
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ OTHER_OPTION_NAMES = \
|
||||
UNICODEMAP_ENABLE \
|
||||
UNICODE_COMMON \
|
||||
AUTO_SHIFT_ENABLE \
|
||||
AUTO_SHIFT_MODIFIERS \
|
||||
DYNAMIC_TAPPING_TERM_ENABLE \
|
||||
COMBO_ENABLE \
|
||||
KEY_LOCK_ENABLE \
|
||||
@@ -59,6 +60,7 @@ OTHER_OPTION_NAMES = \
|
||||
ENCODER_ENABLE_CUSTOM \
|
||||
GERMAN_ENABLE \
|
||||
HAPTIC_ENABLE \
|
||||
ISSI_ENABLE \
|
||||
KEYLOGGER_ENABLE \
|
||||
LCD_BACKLIGHT_ENABLE \
|
||||
MACROS_ENABLED \
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
{
|
||||
"aliases": {
|
||||
/*
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
* │ | │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ ' │ ¿ │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ ´ │ + │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ñ │ { │ } │ │
|
||||
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* │ │ < │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ - │ │
|
||||
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
|
||||
*/
|
||||
"KC_GRV": {
|
||||
"key": "ES_PIPE",
|
||||
"label": "|",
|
||||
}
|
||||
"KC_1": {
|
||||
"key": "ES_1",
|
||||
"label": "1",
|
||||
}
|
||||
"KC_2": {
|
||||
"key": "ES_2",
|
||||
"label": "2",
|
||||
}
|
||||
"KC_3": {
|
||||
"key": "ES_3",
|
||||
"label": "3",
|
||||
}
|
||||
"KC_4": {
|
||||
"key": "ES_4",
|
||||
"label": "4",
|
||||
}
|
||||
"KC_5": {
|
||||
"key": "ES_5",
|
||||
"label": "5",
|
||||
}
|
||||
"KC_6": {
|
||||
"key": "ES_6",
|
||||
"label": "6",
|
||||
}
|
||||
"KC_7": {
|
||||
"key": "ES_7",
|
||||
"label": "7",
|
||||
}
|
||||
"KC_8": {
|
||||
"key": "ES_8",
|
||||
"label": "8",
|
||||
}
|
||||
"KC_9": {
|
||||
"key": "ES_9",
|
||||
"label": "9",
|
||||
}
|
||||
"KC_0": {
|
||||
"key": "ES_0",
|
||||
"label": "0",
|
||||
}
|
||||
"KC_MINS": {
|
||||
"key": "ES_QUOT",
|
||||
"label": "'",
|
||||
}
|
||||
"KC_EQL": {
|
||||
"key": "ES_IQUE",
|
||||
"label": "¿",
|
||||
}
|
||||
"KC_Q": {
|
||||
"key": "ES_Q",
|
||||
"label": "Q",
|
||||
}
|
||||
"KC_W": {
|
||||
"key": "ES_W",
|
||||
"label": "W",
|
||||
}
|
||||
"KC_E": {
|
||||
"key": "ES_E",
|
||||
"label": "E",
|
||||
}
|
||||
"KC_R": {
|
||||
"key": "ES_R",
|
||||
"label": "R",
|
||||
}
|
||||
"KC_T": {
|
||||
"key": "ES_T",
|
||||
"label": "T",
|
||||
}
|
||||
"KC_Y": {
|
||||
"key": "ES_Y",
|
||||
"label": "Y",
|
||||
}
|
||||
"KC_U": {
|
||||
"key": "ES_U",
|
||||
"label": "U",
|
||||
}
|
||||
"KC_I": {
|
||||
"key": "ES_I",
|
||||
"label": "I",
|
||||
}
|
||||
"KC_O": {
|
||||
"key": "ES_O",
|
||||
"label": "O",
|
||||
}
|
||||
"KC_P": {
|
||||
"key": "ES_P",
|
||||
"label": "P",
|
||||
}
|
||||
"KC_LBRC": {
|
||||
"key": "ES_ACUT",
|
||||
"label": "´ (dead)",
|
||||
}
|
||||
"KC_RBRC": {
|
||||
"key": "ES_PLUS",
|
||||
"label": "+",
|
||||
}
|
||||
"KC_A": {
|
||||
"key": "ES_A",
|
||||
"label": "A",
|
||||
}
|
||||
"KC_S": {
|
||||
"key": "ES_S",
|
||||
"label": "S",
|
||||
}
|
||||
"KC_D": {
|
||||
"key": "ES_D",
|
||||
"label": "D",
|
||||
}
|
||||
"KC_F": {
|
||||
"key": "ES_F",
|
||||
"label": "F",
|
||||
}
|
||||
"KC_G": {
|
||||
"key": "ES_G",
|
||||
"label": "G",
|
||||
}
|
||||
"KC_H": {
|
||||
"key": "ES_H",
|
||||
"label": "H",
|
||||
}
|
||||
"KC_J": {
|
||||
"key": "ES_J",
|
||||
"label": "J",
|
||||
}
|
||||
"KC_K": {
|
||||
"key": "ES_K",
|
||||
"label": "K",
|
||||
}
|
||||
"KC_L": {
|
||||
"key": "ES_L",
|
||||
"label": "L",
|
||||
}
|
||||
"KC_SCLN": {
|
||||
"key": "ES_NTIL",
|
||||
"label": "Ñ",
|
||||
}
|
||||
"KC_QUOT": {
|
||||
"key": "ES_LCBR",
|
||||
"label": "{",
|
||||
}
|
||||
"KC_NUHS": {
|
||||
"key": "ES_RCBR",
|
||||
"label": "}",
|
||||
}
|
||||
"KC_NUBS": {
|
||||
"key": "ES_LABK",
|
||||
"label": "<",
|
||||
}
|
||||
"KC_Z": {
|
||||
"key": "ES_Z",
|
||||
"label": "Z",
|
||||
}
|
||||
"KC_X": {
|
||||
"key": "ES_X",
|
||||
"label": "X",
|
||||
}
|
||||
"KC_C": {
|
||||
"key": "ES_C",
|
||||
"label": "C",
|
||||
}
|
||||
"KC_V": {
|
||||
"key": "ES_V",
|
||||
"label": "V",
|
||||
}
|
||||
"KC_B": {
|
||||
"key": "ES_B",
|
||||
"label": "B",
|
||||
}
|
||||
"KC_N": {
|
||||
"key": "ES_N",
|
||||
"label": "N",
|
||||
}
|
||||
"KC_M": {
|
||||
"key": "ES_M",
|
||||
"label": "M",
|
||||
}
|
||||
"KC_COMM": {
|
||||
"key": "ES_COMM",
|
||||
"label": ",",
|
||||
}
|
||||
"KC_DOT": {
|
||||
"key": "ES_DOT",
|
||||
"label": ".",
|
||||
}
|
||||
"KC_SLSH": {
|
||||
"key": "ES_MINS",
|
||||
"label": "-",
|
||||
}
|
||||
/* Shifted symbols
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
* │ ° │ ! │ " │ # │ $ │ % │ & │ / │ ( │ ) │ = │ ? │ ¡ │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ ¨ │ * │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ [ │ ] │ │
|
||||
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* │ │ > │ │ │ │ │ │ │ │ ; │ : │ _ │ │
|
||||
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
|
||||
*/
|
||||
"S(ES_PIPE)": {
|
||||
"key": "ES_MORD",
|
||||
"label": "°",
|
||||
}
|
||||
"S(ES_1)": {
|
||||
"key": "ES_EXLM",
|
||||
"label": "!",
|
||||
}
|
||||
"S(ES_2)": {
|
||||
"key": "ES_DQUO",
|
||||
"label": "\"",
|
||||
}
|
||||
"S(ES_3)": {
|
||||
"key": "ES_NUMB",
|
||||
"label": "#",
|
||||
}
|
||||
"S(ES_4)": {
|
||||
"key": "ES_DLR",
|
||||
"label": "$",
|
||||
}
|
||||
"S(ES_5)": {
|
||||
"key": "ES_PERC",
|
||||
"label": "%",
|
||||
}
|
||||
"S(ES_6)": {
|
||||
"key": "ES_AMPR",
|
||||
"label": "&",
|
||||
}
|
||||
"S(ES_7)": {
|
||||
"key": "ES_SLSH",
|
||||
"label": "/",
|
||||
}
|
||||
"S(ES_8)": {
|
||||
"key": "ES_LPRN",
|
||||
"label": "(",
|
||||
}
|
||||
"S(ES_9)": {
|
||||
"key": "ES_RPRN",
|
||||
"label": ")",
|
||||
}
|
||||
"S(ES_0)": {
|
||||
"key": "ES_EQL",
|
||||
"label": "=",
|
||||
}
|
||||
"S(ES_QUOT)": {
|
||||
"key": "ES_QUES",
|
||||
"label": "?",
|
||||
}
|
||||
"S(ES_IQUE)": {
|
||||
"key": "ES_IEXL",
|
||||
"label": "¡",
|
||||
}
|
||||
"S(ES_ACUT)": {
|
||||
"key": "ES_DIAE",
|
||||
"label": "¨ (dead)",
|
||||
}
|
||||
"S(ES_PLUS)": {
|
||||
"key": "ES_ASTR",
|
||||
"label": "*",
|
||||
}
|
||||
"S(ES_LCBR)": {
|
||||
"key": "ES_LBRC",
|
||||
"label": "[",
|
||||
}
|
||||
"S(ES_RCBR)": {
|
||||
"key": "ES_RBRC",
|
||||
"label": "]",
|
||||
}
|
||||
"S(ES_LABK)": {
|
||||
"key": "ES_RABK",
|
||||
"label": ">",
|
||||
}
|
||||
"S(ES_COMM)": {
|
||||
"key": "ES_SCLN",
|
||||
"label": ";",
|
||||
}
|
||||
"S(ES_DOT)": {
|
||||
"key": "ES_COLN",
|
||||
"label": ":",
|
||||
}
|
||||
"S(ES_MINS)": {
|
||||
"key": "ES_UNDS",
|
||||
"label": "_",
|
||||
}
|
||||
/* AltGr symbols
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
|
||||
* │ ¬ │ │ │ │ │ │ │ │ │ │ │ \ │ │ │
|
||||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
|
||||
* │ │ @ │ │ │ │ │ │ │ │ │ │ │ ~ │ │
|
||||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ │
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ ^ │ ` │ │
|
||||
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
|
||||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
|
||||
* │ │ │ │ │ │ │ │ │
|
||||
* └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
|
||||
*/
|
||||
"ALGR(ES_PIPE)": {
|
||||
"key": "ES_NOT",
|
||||
"label": "¬",
|
||||
}
|
||||
"ALGR(ES_QUOT)": {
|
||||
"key": "ES_BSLS",
|
||||
"label": "\\",
|
||||
}
|
||||
"ALGR(ES_Q)": {
|
||||
"key": "ES_AT",
|
||||
"label": "@",
|
||||
}
|
||||
"ALGR(ES_PLUS)": {
|
||||
"key": "ES_TILD",
|
||||
"label": "~",
|
||||
}
|
||||
"ALGR(ES_LCBR)": {
|
||||
"key": "ES_CIRC",
|
||||
"label": "^",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +1,84 @@
|
||||
{
|
||||
"development_board": {
|
||||
"bit_c_pro": {
|
||||
"board": "QMK_PM2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"blackpill_f401": {
|
||||
"board": "BLACKPILL_STM32_F401",
|
||||
"bootloader": "stm32-dfu",
|
||||
"processor": "STM32F401"
|
||||
},
|
||||
"blackpill_f411": {
|
||||
"board": "BLACKPILL_STM32_F411",
|
||||
"bootloader": "stm32-dfu",
|
||||
"processor": "STM32F411"
|
||||
},
|
||||
"blok": {
|
||||
"board": "QMK_BLOK",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"bluepill": {
|
||||
"board": "STM32_F103_STM32DUINO",
|
||||
"bootloader": "stm32duino",
|
||||
"processor": "STM32F103"
|
||||
},
|
||||
"bonsai_c4": {
|
||||
"board": "BONSAI_C4",
|
||||
"bootloader": "stm32-dfu",
|
||||
"processor": "STM32F411"
|
||||
"promicro": {
|
||||
"processor": "atmega32u4",
|
||||
"bootloader": "caterina",
|
||||
"pin_compatible": "promicro"
|
||||
},
|
||||
"elite_c": {
|
||||
"processor": "atmega32u4",
|
||||
"bootloader": "atmel-dfu",
|
||||
"pin_compatible": "promicro",
|
||||
"processor": "atmega32u4"
|
||||
"pin_compatible": "promicro"
|
||||
},
|
||||
"elite_pi": {
|
||||
"board": "QMK_PM2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"helios": {
|
||||
"board": "QMK_PM2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"imera": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"proton_c": {
|
||||
"processor": "STM32F303",
|
||||
"bootloader": "stm32-dfu",
|
||||
"board": "QMK_PROTON_C"
|
||||
},
|
||||
"kb2040": {
|
||||
"board": "QMK_PM2040",
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"liatris": {
|
||||
"board": "QMK_PM2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"michi": {
|
||||
"board": "QMK_PM2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
},
|
||||
"promicro": {
|
||||
"bootloader": "caterina",
|
||||
"pin_compatible": "promicro",
|
||||
"processor": "atmega32u4"
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"promicro_rp2040": {
|
||||
"board": "QMK_PM2040",
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"processor": "RP2040"
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"proton_c": {
|
||||
"board": "QMK_PROTON_C",
|
||||
"blok": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_BLOK"
|
||||
},
|
||||
"michi": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"bit_c_pro": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"bluepill": {
|
||||
"processor": "STM32F103",
|
||||
"bootloader": "stm32duino",
|
||||
"board": "STM32_F103_STM32DUINO"
|
||||
},
|
||||
"blackpill_f401": {
|
||||
"processor": "STM32F401",
|
||||
"bootloader": "stm32-dfu",
|
||||
"processor": "STM32F303"
|
||||
"board": "BLACKPILL_STM32_F401"
|
||||
},
|
||||
"blackpill_f411": {
|
||||
"processor": "STM32F411",
|
||||
"bootloader": "stm32-dfu",
|
||||
"board": "BLACKPILL_STM32_F411"
|
||||
},
|
||||
"stemcell": {
|
||||
"board": "STEMCELL",
|
||||
"processor": "STM32F411",
|
||||
"bootloader": "tinyuf2",
|
||||
"processor": "STM32F411"
|
||||
"board": "STEMCELL"
|
||||
},
|
||||
"bonsai_c4": {
|
||||
"processor": "STM32F411",
|
||||
"bootloader": "stm32-dfu",
|
||||
"board": "BONSAI_C4"
|
||||
},
|
||||
"helios": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
},
|
||||
"liatris": {
|
||||
"processor": "RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"board": "QMK_PM2040"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
"BACKLIGHT_PIN": {"info_key": "backlight.pin"},
|
||||
"BACKLIGHT_PINS": {"info_key": "backlight.pins", "value_type": "array"},
|
||||
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
|
||||
"BACKLIGHT_DEFAULT_ON": {"info_key": "backlight.default.on", "value_type": "bool"},
|
||||
"BACKLIGHT_DEFAULT_BREATHING": {"info_key": "backlight.default.breathing", "value_type": "bool"},
|
||||
"BACKLIGHT_DEFAULT_LEVEL": {"info_key": "backlight.default.brightness", "value_type": "int"},
|
||||
|
||||
// Bootmagic
|
||||
"BOOTMAGIC_LITE_COLUMN": {"info_key": "bootmagic.matrix.1", "value_type": "int"},
|
||||
@@ -48,15 +45,14 @@
|
||||
// Combos
|
||||
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"},
|
||||
|
||||
"DIP_SWITCH_MATRIX_GRID": {"info_key": "dip_switch.matrix_grid", "value_type": "array.array.int", "to_json": false},
|
||||
"DIP_SWITCH_PINS": {"info_key": "dip_switch.pins", "value_type": "array"},
|
||||
"DIP_SWITCH_PINS_RIGHT": {"info_key": "split.dip_switch.right.pins", "value_type": "array"},
|
||||
|
||||
// Dynamic Keymap
|
||||
"DYNAMIC_KEYMAP_EEPROM_MAX_ADDR": {"info_key": "dynamic_keymap.eeprom_max_addr", "value_type": "int"},
|
||||
"DYNAMIC_KEYMAP_LAYER_COUNT": {"info_key": "dynamic_keymap.layer_count", "value_type": "int"},
|
||||
|
||||
// EEPROM
|
||||
"EXTERNAL_EEPROM_WP_PIN": {"info_key": "eeprom.i2c.write_protect_pin"},
|
||||
"EXTERNAL_EEPROM_I2C_BASE_ADDRESS": {"info_key": "eeprom.i2c.address", "to_json": false},
|
||||
"EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN": {"info_key": "eeprom.spi.chip_select_pin"},
|
||||
"WEAR_LEVELING_BACKING_SIZE": {"info_key": "eeprom.wear_leveling.backing_size", "value_type": "int", "to_json": false},
|
||||
"WEAR_LEVELING_LOGICAL_SIZE": {"info_key": "eeprom.wear_leveling.logical_size", "value_type": "int", "to_json": false},
|
||||
|
||||
@@ -85,13 +81,6 @@
|
||||
"LED_MATRIX_TIMEOUT": {"info_key": "led_matrix.timeout", "value_type": "int"},
|
||||
"LED_MATRIX_VAL_STEP": {"info_key": "led_matrix.val_steps", "value_type": "int"},
|
||||
"LED_MATRIX_LED_COUNT": {"info_key": "led_matrix.led_count", "value_type": "int", "to_json": false},
|
||||
"LED_MATRIX_DEFAULT_ON": {"info_key": "led_matrix.default.on", "value_type": "bool"},
|
||||
"LED_MATRIX_DEFAULT_VAL": {"info_key": "led_matrix.default.val", "value_type": "int"},
|
||||
"LED_MATRIX_DEFAULT_SPD": {"info_key": "led_matrix.default.speed", "value_type": "int"},
|
||||
|
||||
// Locking Switch
|
||||
"LOCKING_SUPPORT_ENABLE": {"info_key": "qmk.locking.enabled", "value_type": "bool"},
|
||||
"LOCKING_RESYNC_ENABLE": {"info_key": "qmk.locking.resync", "value_type": "bool"},
|
||||
|
||||
// LUFA Bootloader
|
||||
"QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"},
|
||||
@@ -117,9 +106,6 @@
|
||||
"ONESHOT_TIMEOUT": {"info_key": "oneshot.timeout", "value_type": "int"},
|
||||
"ONESHOT_TAP_TOGGLE": {"info_key": "oneshot.tap_toggle", "value_type": "int"},
|
||||
|
||||
// Potentiometer
|
||||
"POTENTIOMETER_PINS": {"info_key": "potentiometer.pins", "value_type": "array"},
|
||||
|
||||
// PS/2
|
||||
"PS2_CLOCK_PIN": {"info_key": "ps2.clock_pin"},
|
||||
"PS2_DATA_PIN": {"info_key": "ps2.data_pin"},
|
||||
@@ -138,11 +124,6 @@
|
||||
"RGB_MATRIX_TIMEOUT": {"info_key": "rgb_matrix.timeout", "value_type": "int"},
|
||||
"RGB_MATRIX_VAL_STEP": {"info_key": "rgb_matrix.val_steps", "value_type": "int"},
|
||||
"RGB_MATRIX_LED_COUNT": {"info_key": "rgb_matrix.led_count", "value_type": "int", "to_json": false},
|
||||
"RGB_MATRIX_DEFAULT_ON": {"info_key": "rgb_matrix.default.on", "value_type": "bool"},
|
||||
"RGB_MATRIX_DEFAULT_HUE": {"info_key": "rgb_matrix.default.hue", "value_type": "int"},
|
||||
"RGB_MATRIX_DEFAULT_SAT": {"info_key": "rgb_matrix.default.sat", "value_type": "int"},
|
||||
"RGB_MATRIX_DEFAULT_VAL": {"info_key": "rgb_matrix.default.val", "value_type": "int"},
|
||||
"RGB_MATRIX_DEFAULT_SPD": {"info_key": "rgb_matrix.default.speed", "value_type": "int"},
|
||||
|
||||
// RGBLight
|
||||
"RGBLED_NUM": {"info_key": "rgblight.led_count", "value_type": "int"},
|
||||
@@ -158,11 +139,6 @@
|
||||
"RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"},
|
||||
"RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"},
|
||||
"RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"},
|
||||
"RGBLIGHT_DEFAULT_ON": {"info_key": "rgblight.default.on", "value_type": "bool"},
|
||||
"RGBLIGHT_DEFAULT_HUE": {"info_key": "rgblight.default.hue", "value_type": "int"},
|
||||
"RGBLIGHT_DEFAULT_SAT": {"info_key": "rgblight.default.sat", "value_type": "int"},
|
||||
"RGBLIGHT_DEFAULT_VAL": {"info_key": "rgblight.default.val", "value_type": "int"},
|
||||
"RGBLIGHT_DEFAULT_SPD": {"info_key": "rgblight.default.speed", "value_type": "int"},
|
||||
"RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"},
|
||||
|
||||
// Secure
|
||||
@@ -173,8 +149,6 @@
|
||||
// Split Keyboard
|
||||
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
|
||||
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
|
||||
"SPLIT_HAND_MATRIX_GRID": {"info_key": "split.handedness.matrix_grid", "value_type": "array", "to_c": false},
|
||||
"SPLIT_HAND_PIN": {"info_key": "split.handedness.pin"},
|
||||
"SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"},
|
||||
"SPLIT_USB_TIMEOUT": {"info_key": "split.usb_detect.timeout", "value_type": "int"},
|
||||
"SPLIT_USB_TIMEOUT_POLL": {"info_key": "split.usb_detect.polling_interval", "value_type": "int"},
|
||||
@@ -239,9 +213,4 @@
|
||||
"PRODUCT": {"info_key": "keyboard_name", "warn_duplicate": false, "value_type": "str", "deprecated": true, "replace_with": "`keyboard_name` in info.json"},
|
||||
"PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex", "deprecated": true, "replace_with": "`usb.pid` in info.json"},
|
||||
"VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex", "deprecated": true, "replace_with": "`usb.vid` in info.json"},
|
||||
|
||||
// Items we want flagged in lint
|
||||
"VIAL_KEYBOARD_UID": {"info_key": "_invalid.vial_uid", "invalid": true},
|
||||
"VIAL_UNLOCK_COMBO_COLS": {"info_key": "_invalid.vial_unlock_cols", "invalid": true},
|
||||
"VIAL_UNLOCK_COMBO_ROWS": {"info_key": "_invalid.vial_unlock_rows", "invalid": true}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
"BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
|
||||
"BOOTMAGIC_ENABLE": {"info_key": "bootmagic.enabled", "value_type": "bool"},
|
||||
"CAPS_WORD_ENABLE": {"info_key": "caps_word.enabled", "value_type": "bool"},
|
||||
"DIP_SWITCH_ENABLE": {"info_key": "dip_switch.enabled", "value_type": "bool"},
|
||||
"DEBOUNCE_TYPE": {"info_key": "build.debounce_type"},
|
||||
"EEPROM_DRIVER": {"info_key": "eeprom.driver"},
|
||||
"ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"},
|
||||
@@ -32,7 +31,6 @@
|
||||
"NO_USB_STARTUP_CHECK": {"info_key": "usb.no_startup_check", "value_type": "bool"},
|
||||
"PIN_COMPATIBLE": {"info_key": "pin_compatible"},
|
||||
"PLATFORM_KEY": {"info_key": "platform_key", "to_json": false},
|
||||
"POTENTIOMETER_ENABLE": {"info_key": "potentiometer.enabled", "value_type": "bool"},
|
||||
"PS2_DRIVER": {"info_key": "ps2.driver"},
|
||||
"PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"},
|
||||
"PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"},
|
||||
|
||||
@@ -143,9 +143,6 @@
|
||||
"daisy": {
|
||||
"target": "ktec/daisy"
|
||||
},
|
||||
"dp3000": {
|
||||
"target": "dp3000/rev1"
|
||||
},
|
||||
"drakon": {
|
||||
"target": "jagdpietr/drakon"
|
||||
},
|
||||
@@ -185,9 +182,6 @@
|
||||
"eek": {
|
||||
"target": "eek/silk_down"
|
||||
},
|
||||
"era/klein": {
|
||||
"target": "era/sirind/klein_sd"
|
||||
},
|
||||
"ergodone": {
|
||||
"target": "ktec/ergodone"
|
||||
},
|
||||
@@ -413,9 +407,6 @@
|
||||
"maartenwut/wonderland": {
|
||||
"target": "evyd13/wonderland"
|
||||
},
|
||||
"matchstickworks/southpad": {
|
||||
"target": "matchstickworks/southpad/rev2/"
|
||||
},
|
||||
"matrix/m12og": {
|
||||
"target": "matrix/m12og/rev1"
|
||||
},
|
||||
@@ -951,12 +942,6 @@
|
||||
"launchpad/rev1": {
|
||||
"target": "maple_computing/launchpad/rev1"
|
||||
},
|
||||
"lefty": {
|
||||
"target": "smoll/lefty/rev2"
|
||||
},
|
||||
"lefty/rev1": {
|
||||
"target": "smoll/lefty/rev1"
|
||||
},
|
||||
"lck75": {
|
||||
"target": "lyso1/lck75"
|
||||
},
|
||||
@@ -1110,9 +1095,6 @@
|
||||
"pursuit40": {
|
||||
"target": "checkerboards/pursuit40"
|
||||
},
|
||||
"pw88": {
|
||||
"target": "smoll/pw88"
|
||||
},
|
||||
"qaz": {
|
||||
"target": "tominabox1/qaz"
|
||||
},
|
||||
@@ -1230,12 +1212,6 @@
|
||||
"setta21": {
|
||||
"target": "salicylic_acid3/setta21"
|
||||
},
|
||||
"soda/mango": {
|
||||
"target": "magic_force/mf17"
|
||||
},
|
||||
"soda/pocket": {
|
||||
"target": "magic_force/mf34"
|
||||
},
|
||||
"space_space/rev1": {
|
||||
"target": "qpockets/space_space/rev1"
|
||||
},
|
||||
@@ -1311,9 +1287,6 @@
|
||||
"vn66": {
|
||||
"target": "hnahkb/vn66"
|
||||
},
|
||||
"w1_at": {
|
||||
"target": "geonworks/w1_at"
|
||||
},
|
||||
"wallaby": {
|
||||
"target": "kkatano/wallaby"
|
||||
},
|
||||
|
||||
@@ -3,25 +3,10 @@
|
||||
"$id": "qmk.definitions.v1",
|
||||
"title": "Common definitions used across QMK's jsonschemas.",
|
||||
"type": "object",
|
||||
"bcd_version": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]{1,2}\\.[0-9]\\.[0-9]$"
|
||||
},
|
||||
"bit": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"boolean_array": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "boolean"}
|
||||
},
|
||||
"build_target": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/keyboard_keymap_tuple"},
|
||||
{"$ref": "#/json_file_path"}
|
||||
]
|
||||
},
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
@@ -35,56 +20,18 @@
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9A-F]{4}$"
|
||||
},
|
||||
"json_file_path": {
|
||||
"bcd_version": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-z_/\\-]+\\.json$"
|
||||
"pattern": "^[0-9]{1,2}\\.[0-9]\\.[0-9]$"
|
||||
},
|
||||
"key_unit": {
|
||||
"type": "number"
|
||||
},
|
||||
"keyboard": {
|
||||
"text_identifier": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-z][0-9a-z_/]*$"
|
||||
"minLength": 1,
|
||||
"maxLength": 250
|
||||
},
|
||||
"keyboard_keymap_tuple": {
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"$ref": "#/keyboard"},
|
||||
{"$ref": "#/filename"}
|
||||
],
|
||||
"unevaluatedItems": false
|
||||
},
|
||||
"keycode": {
|
||||
"snake_case": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 50,
|
||||
"pattern": "^[A-Z][A-Zs_0-9]*$"
|
||||
},
|
||||
"keycode_decl": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key"
|
||||
],
|
||||
"properties": {
|
||||
"key": {"$ref": "#/keycode"},
|
||||
"label": {"$ref": "#/text_identifier"},
|
||||
"aliases": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {"$ref": "#/keycode_short"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"keycode_decl_array": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {"$ref": "#/keycode_decl"}
|
||||
},
|
||||
"keycode_short": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 7,
|
||||
"pattern": "^[A-Z][A-Zs_0-9]*$"
|
||||
"pattern": "^[a-z][a-z0-9_]*$"
|
||||
},
|
||||
"layout_macro": {
|
||||
"oneOf": [
|
||||
@@ -121,6 +68,49 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_unit": {
|
||||
"type": "number"
|
||||
},
|
||||
"keyboard": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-z][0-9a-z_/]*$"
|
||||
},
|
||||
"keycode": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 50,
|
||||
"pattern": "^[A-Z][A-Zs_0-9]*$"
|
||||
},
|
||||
"keycode_short": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 7,
|
||||
"pattern": "^[A-Z][A-Zs_0-9]*$"
|
||||
},
|
||||
"keycode_decl": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key"
|
||||
],
|
||||
"properties": {
|
||||
"key": {"$ref": "#/keycode"},
|
||||
"label": {"$ref": "#/text_identifier"},
|
||||
"aliases": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {"$ref": "#/keycode_short"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"keycode_decl_array": {
|
||||
"type": "array",
|
||||
"minItems": 1
|
||||
"items": {"$ref": "#/keycode_decl"}
|
||||
},
|
||||
"mcu_pin_array": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/mcu_pin"}
|
||||
},
|
||||
"mcu_pin": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -139,14 +129,14 @@
|
||||
"type": "string",
|
||||
"pattern": "^GP\\d{1,2}$"
|
||||
},
|
||||
{"type": "integer"},
|
||||
{"type": "null"}
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mcu_pin_array": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/mcu_pin"}
|
||||
},
|
||||
"signed_decimal": {
|
||||
"type": "number"
|
||||
},
|
||||
@@ -158,22 +148,17 @@
|
||||
"minimum": -127,
|
||||
"maximum": 127
|
||||
},
|
||||
"snake_case": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_]*$"
|
||||
},
|
||||
"string_array": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"string_object": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
},
|
||||
"text_identifier": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 250
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"unsigned_decimal": {
|
||||
"type": "number",
|
||||
@@ -187,5 +172,10 @@
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"bit": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dip_switch_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pins": {
|
||||
"$ref": "qmk.definitions.v1#/mcu_pin_array"
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"not": { "required": [ "vendorId", "productId" ] }, // reject via keys...
|
||||
@@ -43,7 +35,7 @@
|
||||
},
|
||||
"development_board": {
|
||||
"type": "string",
|
||||
"enum": ["promicro", "elite_c", "elite_pi", "proton_c", "kb2040", "promicro_rp2040", "blok", "michi", "bit_c_pro", "stemcell", "bluepill", "blackpill_f401", "blackpill_f411", "bonsai_c4", "helios", "liatris", "imera"]
|
||||
"enum": ["promicro", "elite_c", "elite_pi", "proton_c", "kb2040", "promicro_rp2040", "blok", "michi", "bit_c_pro", "stemcell", "bluepill", "blackpill_f401", "blackpill_f411", "bonsai_c4", "helios", "liatris"]
|
||||
},
|
||||
"pin_compatible": {
|
||||
"type": "string",
|
||||
@@ -136,15 +128,6 @@
|
||||
"type": "string",
|
||||
"enum": ["pwm", "software", "timer", "custom"]
|
||||
},
|
||||
"default": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"on": {"type": "boolean"},
|
||||
"breathing": {"type": "boolean"},
|
||||
"brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
|
||||
}
|
||||
},
|
||||
"breathing": {"type": "boolean"},
|
||||
"breathing_period": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"levels": {
|
||||
@@ -262,28 +245,26 @@
|
||||
"type": "array",
|
||||
"items": {"$ref": "qmk.definitions.v1#/filename"}
|
||||
},
|
||||
"dip_switch": {
|
||||
"$ref": "#/definitions/dip_switch_config",
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"matrix_grid": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2,
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eeprom": {
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"device": {"type": "string"},
|
||||
"address": {"$ref": "qmk.definitions.v1#/hex_number_2d"},
|
||||
"write_protect_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
|
||||
}
|
||||
},
|
||||
"spi": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"device": {"type": "string"},
|
||||
"chip_select_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
|
||||
}
|
||||
},
|
||||
"wear_leveling": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -348,7 +329,6 @@
|
||||
"additionalProperties": false,
|
||||
"required": ["x", "y"],
|
||||
"properties": {
|
||||
"encoder": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"label": {
|
||||
"type": "string",
|
||||
"pattern": "^[^\\n]*$"
|
||||
@@ -418,13 +398,6 @@
|
||||
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
}
|
||||
},
|
||||
"potentiometer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
|
||||
}
|
||||
},
|
||||
"led_matrix": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -435,16 +408,6 @@
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"on": {"type": "boolean"},
|
||||
"animation": {"type": "string"},
|
||||
"val": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
|
||||
}
|
||||
},
|
||||
"driver": {"type": "string"},
|
||||
"center_point": {
|
||||
"type": "array",
|
||||
@@ -499,18 +462,6 @@
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"on": {"type": "boolean"},
|
||||
"animation": {"type": "string"},
|
||||
"hue": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"sat": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"val": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
|
||||
}
|
||||
},
|
||||
"driver": {"type": "string"},
|
||||
"center_point": {
|
||||
"type": "array",
|
||||
@@ -569,18 +520,6 @@
|
||||
}
|
||||
},
|
||||
"brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"default": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"on": {"type": "boolean"},
|
||||
"animation": {"type": "string"},
|
||||
"hue": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"sat": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"val": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
|
||||
}
|
||||
},
|
||||
"driver": {
|
||||
"type": "string",
|
||||
"enum": ["apa102", "custom", "ws2812"]
|
||||
@@ -691,6 +630,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"matrix_grid": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "qmk.definitions.v1#/mcu_pin"}
|
||||
},
|
||||
"matrix_pins": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -710,15 +653,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dip_switch": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"right": {
|
||||
"$ref": "#/definitions/dip_switch_config"
|
||||
}
|
||||
}
|
||||
},
|
||||
"encoder": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -728,17 +662,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"handedness": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"matrix_grid": {
|
||||
"$ref": "qmk.definitions.v1#/mcu_pin_array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
"main": {
|
||||
"type": "string",
|
||||
"enum": ["eeprom", "left", "matrix_grid", "pin", "right"]
|
||||
},
|
||||
"soft_serial_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"soft_serial_speed": {
|
||||
@@ -790,16 +716,6 @@
|
||||
"polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
}
|
||||
},
|
||||
"main": {
|
||||
"type": "string",
|
||||
"enum": ["eeprom", "left", "matrix_grid", "pin", "right"],
|
||||
"$comment": "Deprecated: use config.h options for now"
|
||||
},
|
||||
"matrix_grid": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"$comment": "Deprecated: use split.handedness.matrix_grid instead"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -857,15 +773,7 @@
|
||||
"properties": {
|
||||
"keys_per_scan": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"tap_keycode_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"locking": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"resync": {"type": "boolean"}
|
||||
}
|
||||
}
|
||||
"tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
}
|
||||
},
|
||||
"qmk_lufa_bootloader": {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema#",
|
||||
"$id": "qmk.user_repo.v0",
|
||||
"title": "User Repository Information",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"userspace_version"
|
||||
],
|
||||
"properties": {
|
||||
"userspace_version": {
|
||||
"type": "string",
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema#",
|
||||
"$id": "qmk.user_repo.v1",
|
||||
"title": "User Repository Information",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"userspace_version",
|
||||
"build_targets"
|
||||
],
|
||||
"properties": {
|
||||
"userspace_version": {
|
||||
"type": "string",
|
||||
"enum": ["1.0"]
|
||||
},
|
||||
"build_targets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "qmk.definitions.v1#/build_target"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,336 +0,0 @@
|
||||
# QMK Breaking Changes - 2023 November 26 Changelog
|
||||
|
||||
## Notable Features :id=notable-features
|
||||
|
||||
As per last few breaking changes cycles, there have been _a lot_ of behind-the-scenes changes, mainly around consolidation of config into `info.json` files, cleanup of `info.json` files, cleaning up driver naming, as well as addressing technical debt.
|
||||
|
||||
As a followup to last cycle's [notable changes](20230827.md#notable-changes), as `qmk/qmk_firmware` is no longer accepting PRs for keymaps we're pleased to announce that storing and building keymaps externally from the normal QMK Firmware repository is now possible. This is done through the new [External Userspace](newbs_external_userspace.md) feature, more details below!
|
||||
|
||||
## Changes Requiring User Action :id=changes-requiring-user-action
|
||||
|
||||
### Updated Keyboard Codebases :id=updated-keyboard-codebases
|
||||
|
||||
| Old Keyboard Name | New Keyboard Name |
|
||||
|---------------------------------------|-------------------------------|
|
||||
| adm42 | adm42/rev4 |
|
||||
| dp3000 | dp3000/rev1 |
|
||||
| handwired/dactyl_manuform/dmote/62key | handwired/dmote |
|
||||
| keychron/q0/rev_0130 | keychron/q0/base |
|
||||
| keychron/q0/rev_0131 | keychron/q0/plus |
|
||||
| keychron/q1/ansi | keychron/q1v1/ansi |
|
||||
| keychron/q1/ansi_encoder | keychron/q1v1/ansi_encoder |
|
||||
| keychron/q1/iso | keychron/q1v1/iso |
|
||||
| keychron/q1/iso_encoder | keychron/q1v1/iso_encoder |
|
||||
| keychron/q4/ansi_v1 | keychron/q4/ansi |
|
||||
| kprepublic/bm40hsrgb | kprepublic/bm40hsrgb/rev1 |
|
||||
| matchstickworks/southpad | matchstickworks/southpad/rev2 |
|
||||
| soda/mango | magic_force/mf17 |
|
||||
| soda/pocket | magic_force/mf34 |
|
||||
| studiokestra/line_tkl | studiokestra/line_friends_tkl |
|
||||
| ymdk/melody96 | ymdk/melody96/soldered |
|
||||
|
||||
## Notable core changes :id=notable-core
|
||||
|
||||
### External Userspace ([#22222](https://github.com/qmk/qmk_firmware/pull/22222))
|
||||
|
||||
As mentioned above, the new External Userspace feature allows for keymaps to be stored and built externally from the main QMK Firmware repository. This allows for keymaps to be stored separately -- usually in their own repository -- and for users to be able to maintain and build their keymaps without needing to fork the main QMK Firmware repository.
|
||||
|
||||
See the [External Userspace documentation](newbs_external_userspace.md) for more details.
|
||||
|
||||
A significant portion of user keymaps have already been removed from `qmk/qmk_firmware` and more will follow in coming weeks. You can still recover your keymap from the tag [user-keymaps-still-present](https://github.com/qmk/qmk_firmware/tree/user-keymaps-still-present) if required -- a perfect time to migrate to the new External Userspace!
|
||||
|
||||
!> This feature is still in beta, and we're looking for feedback on it. Please try it out and let us know what you think -- a new `#help-userspace` channel has been set up on Discord.
|
||||
|
||||
### Improve and Cleanup Shutdown callbacks ([#21060](https://github.com/qmk/qmk_firmware/pull/20160)) :id=improve-and-cleanup-shutdown-callbacks
|
||||
|
||||
Shutdown callbacks at the keyboard level were never present, preventing safe shutdown sequencing for peripherals such as OLEDs, RGB LEDs, and other devices. This PR adds a new `shutdown_kb` function, as well as amending `shutdown_user`, allowing for safe shutdown of peripherals at both keyboard and keymap level.
|
||||
|
||||
See the [Keyboard Shutdown/Reboot Code](custom_quantum_functions.md#keyboard-shutdown-reboot-code) documentation for more details.
|
||||
|
||||
### OLED Force Flush ([#20953](https://github.com/qmk/qmk_firmware/pull/20953)) :id=oled-force-flush
|
||||
|
||||
Along with the new `shutdown_kb` function, a new API `oled_render_dirty(bool)` function has been added. This allows OLED contents to be written deterministically when supplied with `true` -- that is, the OLED will be updated immediately, rather than waiting for the next OLED update cycle. This allows for OLEDs to show things such as "BOOTLOADER MODE" and the like if resetting to bootloader from QMK.
|
||||
|
||||
### Switch statement helpers for keycode ranges ([#20059](https://github.com/qmk/qmk_firmware/pull/20059)) :id=switch-statement-helpers-for-keycode-ranges
|
||||
|
||||
Predefined ranges usable within switch statements have been added for groups of similar keycodes, where people who wish to handle entire blocks at once can do so. This allows keymaps to be immune to changes in keycode values, and also allows for more efficient code generation.
|
||||
|
||||
The ranges are as follows:
|
||||
|
||||
| Name | Mapping |
|
||||
|-------------------------------------|------------------------------------------------------------------------|
|
||||
| `INTERNAL_KEYCODE_RANGE` | `KC_NO ... KC_TRANSPARENT` |
|
||||
| `BASIC_KEYCODE_RANGE` | `KC_A ... KC_EXSEL` |
|
||||
| `SYSTEM_KEYCODE_RANGE` | `KC_SYSTEM_POWER ... KC_SYSTEM_WAKE` |
|
||||
| `CONSUMER_KEYCODE_RANGE` | `KC_AUDIO_MUTE ... KC_LAUNCHPAD` |
|
||||
| `MOUSE_KEYCODE_RANGE` | `KC_MS_UP ... KC_MS_ACCEL2` |
|
||||
| `MODIFIER_KEYCODE_RANGE` | `KC_LEFT_CTRL ... KC_RIGHT_GUI` |
|
||||
| `SWAP_HANDS_KEYCODE_RANGE` | `QK_SWAP_HANDS_TOGGLE ... QK_SWAP_HANDS_ONE_SHOT` |
|
||||
| `MAGIC_KEYCODE_RANGE` | `QK_MAGIC_SWAP_CONTROL_CAPS_LOCK ... QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK` |
|
||||
| `MIDI_KEYCODE_RANGE` | `QK_MIDI_ON ... QK_MIDI_PITCH_BEND_UP` |
|
||||
| `SEQUENCER_KEYCODE_RANGE` | `QK_SEQUENCER_ON ... QK_SEQUENCER_STEPS_CLEAR` |
|
||||
| `JOYSTICK_KEYCODE_RANGE` | `QK_JOYSTICK_BUTTON_0 ... QK_JOYSTICK_BUTTON_31` |
|
||||
| `PROGRAMMABLE_BUTTON_KEYCODE_RANGE` | `QK_PROGRAMMABLE_BUTTON_1 ... QK_PROGRAMMABLE_BUTTON_32` |
|
||||
| `AUDIO_KEYCODE_RANGE` | `QK_AUDIO_ON ... QK_AUDIO_VOICE_PREVIOUS` |
|
||||
| `STENO_KEYCODE_RANGE` | `QK_STENO_BOLT ... QK_STENO_COMB_MAX` |
|
||||
| `MACRO_KEYCODE_RANGE` | `QK_MACRO_0 ... QK_MACRO_31` |
|
||||
| `BACKLIGHT_KEYCODE_RANGE` | `QK_BACKLIGHT_ON ... QK_BACKLIGHT_TOGGLE_BREATHING` |
|
||||
| `RGB_KEYCODE_RANGE` | `RGB_TOG ... RGB_MODE_TWINKLE` |
|
||||
| `QUANTUM_KEYCODE_RANGE` | `QK_BOOTLOADER ... QK_ALT_REPEAT_KEY` |
|
||||
| `KB_KEYCODE_RANGE` | `QK_KB_0 ... QK_KB_31` |
|
||||
| `USER_KEYCODE_RANGE` | `QK_USER_0 ... QK_USER_31` |
|
||||
|
||||
Usage:
|
||||
|
||||
```c
|
||||
switch (keycode) {
|
||||
case KC_A ... KC_EXSEL:
|
||||
case KC_LEFT_CTRL ... KC_RIGHT_GUI:
|
||||
/* do stuff with basic and modifier keycodes */
|
||||
```
|
||||
|
||||
Becomes:
|
||||
|
||||
```c
|
||||
switch (keycode) {
|
||||
case BASIC_KEYCODE_RANGE:
|
||||
case MODIFIER_KEYCODE_RANGE:
|
||||
/* do stuff with basic and modifier keycodes */
|
||||
```
|
||||
|
||||
### Quantum Painter OLED support ([#19997](https://github.com/qmk/qmk_firmware/pull/19997)) :id=quantum-painter-oled-support
|
||||
|
||||
Quantum Painter has picked up support for SH1106 displays -- commonly seen as 128x64 OLEDs. Support for both I2C and SPI displays is available.
|
||||
|
||||
If you're already using OLED through `OLED_DRIVER_ENABLE = yes` or equivalent in `info.json` and wish to use Quantum Painter instead, you'll need to disable the old OLED system, instead enabling Quantum Painter as well as enabling the appropriate SH1106 driver. See the [Quantum Painter driver documentation](quantum_painter.md#quantum-painter-drivers) for more details. The old OLED driver is still available, and keymaps do not require migrating to Quantum Painter if you don't want to do so.
|
||||
|
||||
### RGB/LED lighting driver naming and cleanup ([#21890](https://github.com/qmk/qmk_firmware/pull/21890), [#21891](https://github.com/qmk/qmk_firmware/pull/21891), [#21892](https://github.com/qmk/qmk_firmware/pull/21892), [#21903](https://github.com/qmk/qmk_firmware/pull/21903), [#21904](https://github.com/qmk/qmk_firmware/pull/21904), [#21905](https://github.com/qmk/qmk_firmware/pull/21905), [#21918](https://github.com/qmk/qmk_firmware/pull/21918), [#21929](https://github.com/qmk/qmk_firmware/pull/21929), [#21938](https://github.com/qmk/qmk_firmware/pull/21938), [#22004](https://github.com/qmk/qmk_firmware/pull/22004), [#22008](https://github.com/qmk/qmk_firmware/pull/22008), [#22009](https://github.com/qmk/qmk_firmware/pull/22009), [#22071](https://github.com/qmk/qmk_firmware/pull/22071), [#22090](https://github.com/qmk/qmk_firmware/pull/22090), [#22099](https://github.com/qmk/qmk_firmware/pull/22099), [#22126](https://github.com/qmk/qmk_firmware/pull/22126), [#22133](https://github.com/qmk/qmk_firmware/pull/22133), [#22163](https://github.com/qmk/qmk_firmware/pull/22163), [#22200](https://github.com/qmk/qmk_firmware/pull/22200), [#22308](https://github.com/qmk/qmk_firmware/pull/22308), [#22309](https://github.com/qmk/qmk_firmware/pull/22309), [#22311](https://github.com/qmk/qmk_firmware/pull/22311), [#22325](https://github.com/qmk/qmk_firmware/pull/22325), [#22365](https://github.com/qmk/qmk_firmware/pull/22365), [#22379](https://github.com/qmk/qmk_firmware/pull/22379), [#22380](https://github.com/qmk/qmk_firmware/pull/22380), [#22381](https://github.com/qmk/qmk_firmware/pull/22381), [#22383](https://github.com/qmk/qmk_firmware/pull/22383), [#22436](https://github.com/qmk/qmk_firmware/pull/22436))
|
||||
|
||||
As you can probably tell by the list of PRs just above, there has been a lot of cleanup and consolidation this cycle when it comes to RGB/LED lighting drivers. The number of changes is too large to list here, but the general theme has been focusing on consistency of naming, both of drivers themselves and their respective implementation and configuration. Most changes only affect keyboard designers -- if you find that your in-development keyboard is no longer building due to naming of defines changing, your best bet is to refer to another board already in the repository which has had the changes applied.
|
||||
|
||||
### Peripheral subsystem enabling ([#22253](https://github.com/qmk/qmk_firmware/pull/22253), [#22448](https://github.com/qmk/qmk_firmware/pull/22448), [#22106](https://github.com/qmk/qmk_firmware/pull/22106)) :id=peripheral-subsystem-enabling
|
||||
|
||||
When enabling peripherals such as I2C, SPI, or Analog/ADC, some required manual inclusion of source files in order to provide driver support, and in some cases, when multiple drivers were using the same underlying peripheral, files were being added to the build multiple times.
|
||||
|
||||
Most systems requiring other peripherals now mark their respective dependencies as "required", allowing the build system to check whether peripherals are necessary before including them in the build rather than having each location enable them manually.
|
||||
|
||||
For a concrete example, users or keyboard designers who previously added `SRC += analog.c` in order to allow for analog readings via an ADC now should specify `ANALOG_DRIVER_REQUIRED = yes` instead. The full list of added options is as follows:
|
||||
|
||||
| New option | Old Equivalent |
|
||||
|--------------------------------|------------------------------------------------------------|
|
||||
| `ANALOG_DRIVER_REQUIRED = yes` | `SRC += analog.c` |
|
||||
| `APA102_DRIVER_REQUIRED = yes` | `SRC += apa102.c` |
|
||||
| `I2C_DRIVER_REQUIRED = yes` | `SRC += i2c_master.c` or `QUANTUM_LIB_SRC += i2c_master.c` |
|
||||
| `SPI_DRIVER_REQUIRED = yes` | `SRC += spi_master.c` or `QUANTUM_LIB_SRC += spi_master.c` |
|
||||
| `UART_DRIVER_REQUIRED = yes` | `SRC += uart.c` |
|
||||
| `WS2812_DRIVER_REQUIRED = yes` | `SRC += ws2812.c` |
|
||||
|
||||
### NKRO on V-USB boards ([#22398](https://github.com/qmk/qmk_firmware/pull/22398)) :id=vusb-nkro
|
||||
|
||||
NKRO is now available for ATmega32A and 328P-based keyboards (including PS2AVRGB/Bootmapper boards), thanks to some internal refactoring and cleanup. To enable it, the process is the same as always - add `NKRO_ENABLE = yes` to your `rules.mk`, then assign and press the `NK_TOGG` keycode to switch modes.
|
||||
|
||||
## Full changelist :id=full-changelist
|
||||
|
||||
Core:
|
||||
* Compilation warning if both `keymap.json` and `keymap.c` exist ([#19939](https://github.com/qmk/qmk_firmware/pull/19939))
|
||||
* [QP] Add support for OLED, variable framebuffer bpp ([#19997](https://github.com/qmk/qmk_firmware/pull/19997))
|
||||
* Generate switch statement helpers for keycode ranges ([#20059](https://github.com/qmk/qmk_firmware/pull/20059))
|
||||
* Chibios SPI driver: allow some SPI pins to be left unassigned ([#20315](https://github.com/qmk/qmk_firmware/pull/20315))
|
||||
* Take care of scroll divisor remainders for PS/2 drag scroll ([#20732](https://github.com/qmk/qmk_firmware/pull/20732))
|
||||
* Add `RGBLIGHT_DEFAULT_ON` macro configuration option ([#20857](https://github.com/qmk/qmk_firmware/pull/20857))
|
||||
* Allow force flush of oled display. ([#20953](https://github.com/qmk/qmk_firmware/pull/20953))
|
||||
* Improve and Cleanup Shutdown callbacks ([#21060](https://github.com/qmk/qmk_firmware/pull/21060))
|
||||
* [Enhancement] QP Getters ([#21171](https://github.com/qmk/qmk_firmware/pull/21171))
|
||||
* Russian typewriter keymap file for popular legacy layout. ([#21174](https://github.com/qmk/qmk_firmware/pull/21174))
|
||||
* Improve directional transition of overlapping mouse keys ([#21494](https://github.com/qmk/qmk_firmware/pull/21494))
|
||||
* Add full solenoid support on split keyboards ([#21583](https://github.com/qmk/qmk_firmware/pull/21583))
|
||||
* Reduce popping during audio initialization using the additive DAC ([#21642](https://github.com/qmk/qmk_firmware/pull/21642))
|
||||
* [Maintenance] USB HID control packet as struct ([#21688](https://github.com/qmk/qmk_firmware/pull/21688))
|
||||
* Bump mouse endpoint packet size to 16 bytes ([#21711](https://github.com/qmk/qmk_firmware/pull/21711))
|
||||
* Allow customizing PWM frequency ([#21717](https://github.com/qmk/qmk_firmware/pull/21717))
|
||||
* Add simpler method for relocating functions to RAM. ([#21804](https://github.com/qmk/qmk_firmware/pull/21804))
|
||||
* Clean up RGB LED type ([#21859](https://github.com/qmk/qmk_firmware/pull/21859))
|
||||
* is31fl3741: Allow changing config register ([#21861](https://github.com/qmk/qmk_firmware/pull/21861))
|
||||
* Add _DEFAULT_ON lighting configuration options ([#21865](https://github.com/qmk/qmk_firmware/pull/21865))
|
||||
* Modify split config is_keyboard_master/left checks. ([#21875](https://github.com/qmk/qmk_firmware/pull/21875))
|
||||
* Remove old `IS_LED_ON/OFF()` macros ([#21878](https://github.com/qmk/qmk_firmware/pull/21878))
|
||||
* ckled2001: driver naming cleanups ([#21890](https://github.com/qmk/qmk_firmware/pull/21890))
|
||||
* aw20216: driver naming cleanups ([#21891](https://github.com/qmk/qmk_firmware/pull/21891))
|
||||
* is31fl3218: driver naming cleanups ([#21892](https://github.com/qmk/qmk_firmware/pull/21892))
|
||||
* is31fl3736: driver naming cleanups ([#21903](https://github.com/qmk/qmk_firmware/pull/21903))
|
||||
* is31fl3737: driver naming cleanups ([#21904](https://github.com/qmk/qmk_firmware/pull/21904))
|
||||
* is31fl3733: driver naming cleanups ([#21905](https://github.com/qmk/qmk_firmware/pull/21905))
|
||||
* Enable RP2040 support for apa102 RGB LED driver ([#21908](https://github.com/qmk/qmk_firmware/pull/21908))
|
||||
* is31fl3731: driver naming cleanups ([#21918](https://github.com/qmk/qmk_firmware/pull/21918))
|
||||
* is31fl3741: driver naming cleanups ([#21929](https://github.com/qmk/qmk_firmware/pull/21929))
|
||||
* refactor: move default RGB/LED matrix #defines ([#21938](https://github.com/qmk/qmk_firmware/pull/21938))
|
||||
* Added flower blooming on RGB Matrix effect ([#21948](https://github.com/qmk/qmk_firmware/pull/21948))
|
||||
* Remove 'Firmware size check does not yet support' message ([#21977](https://github.com/qmk/qmk_firmware/pull/21977))
|
||||
* chibios: mark boot2 bootlader data readonly ([#21986](https://github.com/qmk/qmk_firmware/pull/21986))
|
||||
* Complete RGB Matrix support for IS31FL3218 ([#22004](https://github.com/qmk/qmk_firmware/pull/22004))
|
||||
* Default wear leveling logical size to half backing ([#22006](https://github.com/qmk/qmk_firmware/pull/22006))
|
||||
* chibios: disable RWX segment warning on newer GNU lds ([#22007](https://github.com/qmk/qmk_firmware/pull/22007))
|
||||
* Add and use I2C address defines for ISSI LED drivers ([#22008](https://github.com/qmk/qmk_firmware/pull/22008))
|
||||
* Add and use PWM frequency defines for ISSI LED drivers ([#22009](https://github.com/qmk/qmk_firmware/pull/22009))
|
||||
* directly use object files when linking ELF ([#22025](https://github.com/qmk/qmk_firmware/pull/22025))
|
||||
* Lvgl rate control ([#22049](https://github.com/qmk/qmk_firmware/pull/22049))
|
||||
* Rename CKLED2001 driver to SNLED27351 ([#22071](https://github.com/qmk/qmk_firmware/pull/22071))
|
||||
* Move `PACKED` define to util.h ([#22074](https://github.com/qmk/qmk_firmware/pull/22074))
|
||||
* Simplify more feature driver defines ([#22090](https://github.com/qmk/qmk_firmware/pull/22090))
|
||||
* Update ISSI LED types ([#22099](https://github.com/qmk/qmk_firmware/pull/22099))
|
||||
* Move velocikey to within rgblight ([#22123](https://github.com/qmk/qmk_firmware/pull/22123))
|
||||
* is31fl3218: Add LED Matrix support ([#22126](https://github.com/qmk/qmk_firmware/pull/22126))
|
||||
* Set default board files for uf2boot bootloader ([#22129](https://github.com/qmk/qmk_firmware/pull/22129))
|
||||
* is31fl3736: extract single-color API ([#22133](https://github.com/qmk/qmk_firmware/pull/22133))
|
||||
* is31fl3737/3741: add LED Matrix support ([#22163](https://github.com/qmk/qmk_firmware/pull/22163))
|
||||
* Rename `DRIVER_ADDR_n` defines ([#22200](https://github.com/qmk/qmk_firmware/pull/22200))
|
||||
* New RGB Animations - 4 "Starlight" Animation Variations ([#22212](https://github.com/qmk/qmk_firmware/pull/22212))
|
||||
* QMK Userspace ([#22222](https://github.com/qmk/qmk_firmware/pull/22222))
|
||||
* Dedupe I2C, SPI, UART driver inclusions ([#22253](https://github.com/qmk/qmk_firmware/pull/22253))
|
||||
* Add "AC Next Keyboard Layout Select" consumer usage entry (macOS Globe key) ([#22256](https://github.com/qmk/qmk_firmware/pull/22256))
|
||||
* Separate 6KRO and NKRO report structs ([#22267](https://github.com/qmk/qmk_firmware/pull/22267))
|
||||
* Azoteq IQS5xx support ([#22280](https://github.com/qmk/qmk_firmware/pull/22280))
|
||||
* Add `_flush()` functions to LED drivers ([#22308](https://github.com/qmk/qmk_firmware/pull/22308))
|
||||
* Add `_LED_COUNT` defines to LED drivers ([#22309](https://github.com/qmk/qmk_firmware/pull/22309))
|
||||
* Infer LED DRIVER_COUNT from configured addresses ([#22311](https://github.com/qmk/qmk_firmware/pull/22311))
|
||||
* Added gamma values for ST7735 displays ([#22313](https://github.com/qmk/qmk_firmware/pull/22313))
|
||||
* Consolidate some EEPROM Driver configuration ([#22321](https://github.com/qmk/qmk_firmware/pull/22321))
|
||||
* V-USB: Add generic `send_report()` function ([#22323](https://github.com/qmk/qmk_firmware/pull/22323))
|
||||
* V-USB: Implement `GET_PROTOCOL` and `SET_PROTOCOL` handling ([#22324](https://github.com/qmk/qmk_firmware/pull/22324))
|
||||
* RGB/LED matrix use limits size optimisation ([#22325](https://github.com/qmk/qmk_firmware/pull/22325))
|
||||
* Relocate LED driver init code ([#22365](https://github.com/qmk/qmk_firmware/pull/22365))
|
||||
* WT RGB cleanups ([#22379](https://github.com/qmk/qmk_firmware/pull/22379))
|
||||
* LED drivers: use `PACKED` define from util.h ([#22380](https://github.com/qmk/qmk_firmware/pull/22380))
|
||||
* LED drivers: clean up `SWx`/`CSy` pullup/down resistor config ([#22381](https://github.com/qmk/qmk_firmware/pull/22381))
|
||||
* LED drivers: add defines for PWM and LED control register counts ([#22383](https://github.com/qmk/qmk_firmware/pull/22383))
|
||||
* V-USB: implement NKRO ([#22398](https://github.com/qmk/qmk_firmware/pull/22398))
|
||||
* Allow generic_features to handle subdirectories ([#22400](https://github.com/qmk/qmk_firmware/pull/22400))
|
||||
* Migrate some common features to generic ([#22403](https://github.com/qmk/qmk_firmware/pull/22403))
|
||||
* Remove requirement for `keymap_steno.h` include in keymaps ([#22423](https://github.com/qmk/qmk_firmware/pull/22423))
|
||||
* LED drivers: register naming cleanups ([#22436](https://github.com/qmk/qmk_firmware/pull/22436))
|
||||
* Slight refactor of joystick axis type into typedef ([#22445](https://github.com/qmk/qmk_firmware/pull/22445))
|
||||
* Generalise analog SRC inclusion ([#22448](https://github.com/qmk/qmk_firmware/pull/22448))
|
||||
* Revert "chibios: disable RWX segment warning on newer GNU lds" ([#22469](https://github.com/qmk/qmk_firmware/pull/22469))
|
||||
* chibios: disable RWX segment warning on newer GNU lds ([#22471](https://github.com/qmk/qmk_firmware/pull/22471))
|
||||
|
||||
CLI:
|
||||
* Implement data driven lighting defaults ([#21825](https://github.com/qmk/qmk_firmware/pull/21825))
|
||||
* Generate keymap.json config options more forcefully ([#21960](https://github.com/qmk/qmk_firmware/pull/21960))
|
||||
* Implement data driven dip switches ([#22017](https://github.com/qmk/qmk_firmware/pull/22017))
|
||||
* Improve argument handling of c2json ([#22170](https://github.com/qmk/qmk_firmware/pull/22170))
|
||||
* Support additional split sync items for info.json ([#22193](https://github.com/qmk/qmk_firmware/pull/22193))
|
||||
* CLI refactoring for common build target APIs ([#22221](https://github.com/qmk/qmk_firmware/pull/22221))
|
||||
* Add dd mapping for hardware based split handedness ([#22369](https://github.com/qmk/qmk_firmware/pull/22369))
|
||||
* CLI parallel search updates ([#22525](https://github.com/qmk/qmk_firmware/pull/22525))
|
||||
* Remove duplicates from search results ([#22528](https://github.com/qmk/qmk_firmware/pull/22528))
|
||||
|
||||
Keyboards:
|
||||
* Add KPRepublic/BM40hsrgb rev2 ([#16689](https://github.com/qmk/qmk_firmware/pull/16689))
|
||||
* update to data driven - superseeds part of https://github.com/qmk/qmk… ([#20220](https://github.com/qmk/qmk_firmware/pull/20220))
|
||||
* Modernize `dactyl_manuform/dmote` keyboard ([#20427](https://github.com/qmk/qmk_firmware/pull/20427))
|
||||
* add Skyloong/GK61_V1 keyboard ([#21364](https://github.com/qmk/qmk_firmware/pull/21364))
|
||||
* [Refactor] Make changes to some pins ([#21380](https://github.com/qmk/qmk_firmware/pull/21380))
|
||||
* Add missing fullsize extended default layouts ([#21402](https://github.com/qmk/qmk_firmware/pull/21402))
|
||||
* Add Skyloong/Gk61 PRO keyboard ([#21450](https://github.com/qmk/qmk_firmware/pull/21450))
|
||||
* Added skyloong/Qk21 v1 Number Pad ([#21467](https://github.com/qmk/qmk_firmware/pull/21467))
|
||||
* matchstickworks/southpad - Move files to rev1, add rev2 ([#21574](https://github.com/qmk/qmk_firmware/pull/21574))
|
||||
* partially modernize `dactyl_minidox` ([#21576](https://github.com/qmk/qmk_firmware/pull/21576))
|
||||
* tominabox1/le_chiffre oled rework ([#21611](https://github.com/qmk/qmk_firmware/pull/21611))
|
||||
* Add Skyloong/Gk61_pro_48 keyboard ([#21654](https://github.com/qmk/qmk_firmware/pull/21654))
|
||||
* Adding support for new Waffling60 revision ([#21664](https://github.com/qmk/qmk_firmware/pull/21664))
|
||||
* Leeloo revision 2 updates. ([#21671](https://github.com/qmk/qmk_firmware/pull/21671))
|
||||
* rename og60 to tofu60 ([#21684](https://github.com/qmk/qmk_firmware/pull/21684))
|
||||
* add tofujr v2 keyboard ([#21740](https://github.com/qmk/qmk_firmware/pull/21740))
|
||||
* Rotary numpad ([#21744](https://github.com/qmk/qmk_firmware/pull/21744))
|
||||
* Update era/divine ([#21767](https://github.com/qmk/qmk_firmware/pull/21767))
|
||||
* 1UpKeyboards Pi60 Layout Additions ([#21874](https://github.com/qmk/qmk_firmware/pull/21874))
|
||||
* BIOI keyboards: use core UART driver ([#21879](https://github.com/qmk/qmk_firmware/pull/21879))
|
||||
* Resolve some "Layout should not contain name of keyboard" lint warnings ([#21898](https://github.com/qmk/qmk_firmware/pull/21898))
|
||||
* fc660c/fc980c: clean up actuation point adjustment code ([#21964](https://github.com/qmk/qmk_firmware/pull/21964))
|
||||
* Chromatonemini info json revised to support qmk 0.22.2 ([#21966](https://github.com/qmk/qmk_firmware/pull/21966))
|
||||
* Migrate spi_flash WEAR_LEVELING_DRIVER to info.json ([#21978](https://github.com/qmk/qmk_firmware/pull/21978))
|
||||
* Remove duplication of RP2040 EEPROM defaults ([#21979](https://github.com/qmk/qmk_firmware/pull/21979))
|
||||
* Remove duplication of STM32L432 EEPROM defaults ([#21981](https://github.com/qmk/qmk_firmware/pull/21981))
|
||||
* Migrate spi EEPROM_DRIVER to info.json ([#21991](https://github.com/qmk/qmk_firmware/pull/21991))
|
||||
* Update Keychron Q1v1 ([#21993](https://github.com/qmk/qmk_firmware/pull/21993))
|
||||
* Update Keychron Q2 ([#21994](https://github.com/qmk/qmk_firmware/pull/21994))
|
||||
* Update Keychron Q3 ([#21995](https://github.com/qmk/qmk_firmware/pull/21995))
|
||||
* Update Keychron Q4 ([#21996](https://github.com/qmk/qmk_firmware/pull/21996))
|
||||
* Migrate WEAR_LEVELING_*_SIZE to info.json ([#22010](https://github.com/qmk/qmk_firmware/pull/22010))
|
||||
* Remove duplication of EEPROM defaults ([#22011](https://github.com/qmk/qmk_firmware/pull/22011))
|
||||
* Migrate i2c EEPROM_DRIVER to info.json ([#22013](https://github.com/qmk/qmk_firmware/pull/22013))
|
||||
* Remove config.h which only set DYNAMIC_KEYMAP_LAYER_COUNT ([#22034](https://github.com/qmk/qmk_firmware/pull/22034))
|
||||
* Add community layout support to tofu60 ([#22041](https://github.com/qmk/qmk_firmware/pull/22041))
|
||||
* Update Keychron Q0 ([#22068](https://github.com/qmk/qmk_firmware/pull/22068))
|
||||
* Remove custom ISSI lighting code ([#22073](https://github.com/qmk/qmk_firmware/pull/22073))
|
||||
* add dp3000 rev2 featuring rgblight ([#22084](https://github.com/qmk/qmk_firmware/pull/22084))
|
||||
* Remove ALLOW_WARNINGS and PICO_INTRINSICS_ENABLED ([#22085](https://github.com/qmk/qmk_firmware/pull/22085))
|
||||
* Partially migrate `DYNAMIC_KEYMAP_LAYER_COUNT` ([#22087](https://github.com/qmk/qmk_firmware/pull/22087))
|
||||
* feat(eyeohdesigns/babyv): rgb matrix ([#22105](https://github.com/qmk/qmk_firmware/pull/22105))
|
||||
* input_club/infinity60: remove custom 3731 code, convert to LED Matrix ([#22117](https://github.com/qmk/qmk_firmware/pull/22117))
|
||||
* YMDK Melody96 Break-Up ([#22121](https://github.com/qmk/qmk_firmware/pull/22121))
|
||||
* Remove duplicated rgblight implementation from mxss ([#22122](https://github.com/qmk/qmk_firmware/pull/22122))
|
||||
* KC60 Layout Standardization and Cleanup ([#22125](https://github.com/qmk/qmk_firmware/pull/22125))
|
||||
* Convert adm42 to data driven ([#22144](https://github.com/qmk/qmk_firmware/pull/22144))
|
||||
* Update Drop keyboards for develop ([#22145](https://github.com/qmk/qmk_firmware/pull/22145))
|
||||
* move soda/mango and soda/pocket to magic_force/mf17 and magic_force/mf34 ([#22151](https://github.com/qmk/qmk_firmware/pull/22151))
|
||||
* GMMK2 65% ISO Community Layout Support ([#22152](https://github.com/qmk/qmk_firmware/pull/22152))
|
||||
* Leeloo v2.1 revision 3 updates. ([#22236](https://github.com/qmk/qmk_firmware/pull/22236))
|
||||
* jian/rev1: convert to DIP Switch ([#22248](https://github.com/qmk/qmk_firmware/pull/22248))
|
||||
* Enable linking of encoders to switch within layout macros ([#22264](https://github.com/qmk/qmk_firmware/pull/22264))
|
||||
* Migrate recently introduced sync items ([#22305](https://github.com/qmk/qmk_firmware/pull/22305))
|
||||
* Rename LINE FRIENDS TKL keyboard ([#22310](https://github.com/qmk/qmk_firmware/pull/22310))
|
||||
* feat(mechwild/clunker): new layouts ([#22342](https://github.com/qmk/qmk_firmware/pull/22342))
|
||||
* Remove use of broken split.main ([#22363](https://github.com/qmk/qmk_firmware/pull/22363))
|
||||
* whitefox: remove pointless file ([#22366](https://github.com/qmk/qmk_firmware/pull/22366))
|
||||
* Migrate some EEPROM config to info.json ([#22434](https://github.com/qmk/qmk_firmware/pull/22434))
|
||||
* Remove unnecessary driver counts ([#22435](https://github.com/qmk/qmk_firmware/pull/22435))
|
||||
* Migrate some dip switch config to info.json ([#22437](https://github.com/qmk/qmk_firmware/pull/22437))
|
||||
* Remove userspace keymaps ([#22544](https://github.com/qmk/qmk_firmware/pull/22544))
|
||||
* Stub out community layout directory structure ([#22545](https://github.com/qmk/qmk_firmware/pull/22545))
|
||||
* Remove symbolic linked userspace folder ([#22548](https://github.com/qmk/qmk_firmware/pull/22548))
|
||||
|
||||
Keyboard fixes:
|
||||
* fix unxmaal for 60_iso ([#21975](https://github.com/qmk/qmk_firmware/pull/21975))
|
||||
* Fix input_club/k_type when RGB Matrix disabled ([#22021](https://github.com/qmk/qmk_firmware/pull/22021))
|
||||
* Fixup snes_macropad on develop ([#22444](https://github.com/qmk/qmk_firmware/pull/22444))
|
||||
* Fix missed shutdown callbacks ([#22549](https://github.com/qmk/qmk_firmware/pull/22549))
|
||||
|
||||
Others:
|
||||
* Implement data driven wear leveling ([#21906](https://github.com/qmk/qmk_firmware/pull/21906))
|
||||
* More data driven RGB/LED Matrix config ([#21939](https://github.com/qmk/qmk_firmware/pull/21939))
|
||||
* Update WS2812 docs and add APA102 docs ([#22106](https://github.com/qmk/qmk_firmware/pull/22106))
|
||||
* Add DD mappings for locking switch ([#22242](https://github.com/qmk/qmk_firmware/pull/22242))
|
||||
|
||||
Bugs:
|
||||
* Improve test invocation, fix Retro Shift bugs, and add Auto+Retro Shift test cases ([#15889](https://github.com/qmk/qmk_firmware/pull/15889))
|
||||
* [Bugfix] `qp_ellipse` overflow ([#19005](https://github.com/qmk/qmk_firmware/pull/19005))
|
||||
* Cater for ECC failures in EFL wear-leveling. ([#19749](https://github.com/qmk/qmk_firmware/pull/19749))
|
||||
* Fix OSM on a OSL activated layer ([#20410](https://github.com/qmk/qmk_firmware/pull/20410))
|
||||
* Fixed WB32 MCU remote wakeup issue ([#20863](https://github.com/qmk/qmk_firmware/pull/20863))
|
||||
* Optimize the additive DAC code, fixing performance-related hangs ([#21662](https://github.com/qmk/qmk_firmware/pull/21662))
|
||||
* [Enhancement] Improvements for debounce test coverage + bug fixes for sym_defer_g and sym_eager_pr ([#21667](https://github.com/qmk/qmk_firmware/pull/21667))
|
||||
* fix: make clicky delay silent ([#21866](https://github.com/qmk/qmk_firmware/pull/21866))
|
||||
* Add `mousekey.h` include to `quantum.h` ([#21897](https://github.com/qmk/qmk_firmware/pull/21897))
|
||||
* Fix default layer value in eeconfig_init ([#21909](https://github.com/qmk/qmk_firmware/pull/21909))
|
||||
* Add RTC IRQ Priority to RP2040 board files ([#21926](https://github.com/qmk/qmk_firmware/pull/21926))
|
||||
* Update AW20216S LED type ([#22072](https://github.com/qmk/qmk_firmware/pull/22072))
|
||||
* LED/RGB Matrix: prefix driver defines ([#22088](https://github.com/qmk/qmk_firmware/pull/22088))
|
||||
* RGBLight/Backlight: add prefixed driver defines ([#22089](https://github.com/qmk/qmk_firmware/pull/22089))
|
||||
* Fix lower cpi bound on PMW33XX ([#22108](https://github.com/qmk/qmk_firmware/pull/22108))
|
||||
* Fix parsing/validation for 21939 ([#22148](https://github.com/qmk/qmk_firmware/pull/22148))
|
||||
* is31fl3733: complete LED Matrix support ([#22149](https://github.com/qmk/qmk_firmware/pull/22149))
|
||||
* Fix memory leak in realloc failure handling ([#22188](https://github.com/qmk/qmk_firmware/pull/22188))
|
||||
* avrdude: Version 7.2 changes the text output ([#22235](https://github.com/qmk/qmk_firmware/pull/22235))
|
||||
* Resolve invalid keyboard alias targets ([#22239](https://github.com/qmk/qmk_firmware/pull/22239))
|
||||
* Prep work for NKRO report separation ([#22268](https://github.com/qmk/qmk_firmware/pull/22268))
|
||||
* ChibiOS pin defs: use only vendor if present ([#22297](https://github.com/qmk/qmk_firmware/pull/22297))
|
||||
* Fix invalid LED driver config ([#22312](https://github.com/qmk/qmk_firmware/pull/22312))
|
||||
* Fix compilation error when led/rgb process limit is zero. ([#22328](https://github.com/qmk/qmk_firmware/pull/22328))
|
||||
* V-USB: Fix `GET_IDLE/SET_IDLE` ([#22332](https://github.com/qmk/qmk_firmware/pull/22332))
|
||||
* QP getters correction ([#22357](https://github.com/qmk/qmk_firmware/pull/22357))
|
||||
* Fix 'to_c' for config.h mappings ([#22364](https://github.com/qmk/qmk_firmware/pull/22364))
|
||||
* snled27351: fix missing `i2c_init()` ([#22446](https://github.com/qmk/qmk_firmware/pull/22446))
|
||||
* Move BACKLIGHT_PWM_PERIOD to correct docs section ([#22480](https://github.com/qmk/qmk_firmware/pull/22480))
|
||||
* `qmk find`: Fix failure with multiple filters ([#22497](https://github.com/qmk/qmk_firmware/pull/22497))
|
||||
* Fix `qmk find` failure due to circular imports ([#22523](https://github.com/qmk/qmk_firmware/pull/22523))
|
||||
@@ -4,7 +4,7 @@
|
||||
* [Building Your First Firmware](newbs_building_firmware.md)
|
||||
* [Flashing Firmware](newbs_flashing.md)
|
||||
* [Getting Help/Support](support.md)
|
||||
* [External Userspace](newbs_external_userspace.md)
|
||||
* [Building With GitHub Userspace](newbs_building_firmware_workflow.md)
|
||||
* [Other Resources](newbs_learn_more_resources.md)
|
||||
* [Syllabus](syllabus.md)
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
* [LED Indicators](feature_led_indicators.md)
|
||||
* [MIDI](feature_midi.md)
|
||||
* [Pointing Device](feature_pointing_device.md)
|
||||
* [Potentiometer](feature_potentiometers.md)
|
||||
* [PS/2 Mouse](feature_ps2_mouse.md)
|
||||
* [Split Keyboard](feature_split_keyboard.md)
|
||||
* [Stenography](feature_stenography.md)
|
||||
@@ -139,7 +138,7 @@
|
||||
* Breaking Changes
|
||||
* [Overview](breaking_changes.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/20230827.md "QMK v0.22.0 - 2023 Aug 27")
|
||||
* [Past Breaking Changes](breaking_changes_history.md)
|
||||
|
||||
* C Development
|
||||
|
||||
@@ -9,7 +9,7 @@ This driver currently supports both AVR and a limited selection of ARM devices.
|
||||
To use this driver, add the following to your `rules.mk`:
|
||||
|
||||
```make
|
||||
ANALOG_DRIVER_REQUIRED = yes
|
||||
SRC += analog.c
|
||||
```
|
||||
|
||||
Then place this include at the top of your code:
|
||||
|
||||
@@ -10,9 +10,9 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
|
||||
|
||||
## What has been included in past Breaking Changes?
|
||||
|
||||
* [2023 Nov 26](ChangeLog/20231126.md)
|
||||
* [2023 Aug 27](ChangeLog/20230827.md)
|
||||
* [2023 May 28](ChangeLog/20230528.md)
|
||||
* [2023 Feb 26](ChangeLog/20230226.md)
|
||||
* [Older Breaking Changes](breaking_changes_history.md)
|
||||
|
||||
## When is the next Breaking Change?
|
||||
@@ -21,14 +21,14 @@ The next Breaking Change is scheduled for November 26, 2023.
|
||||
|
||||
### 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 Jan 28 - `develop` closed to new PRs.
|
||||
* 2024 Jan 28 - Call for testers.
|
||||
* 2024 Feb 4 - 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 Feb 22 - `master` is locked, no PRs merged.
|
||||
* 2024 Feb 25 - Merge `develop` to `master`.
|
||||
* 2024 Feb 25 - `master` is unlocked. PRs can be merged again.
|
||||
* 2023 Aug 27 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
|
||||
* 2023 Oct 29 - `develop` closed to new PRs.
|
||||
* 2023 Oct 29 - Call for testers.
|
||||
* 2023 Nov 5 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
|
||||
* 2023 Nov 19 - `develop` is locked, only critical bugfix PRs merged.
|
||||
* 2023 Nov 23 - `master` is locked, no PRs merged.
|
||||
* 2023 Nov 26 - Merge `develop` to `master`.
|
||||
* 2023 Nov 26 - `master` is unlocked. PRs can be merged again.
|
||||
|
||||
## What changes will be included?
|
||||
|
||||
@@ -48,7 +48,7 @@ Criteria for acceptance:
|
||||
|
||||
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/20231126`.
|
||||
* 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.
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
This page links to all previous changelogs from the QMK Breaking Changes process.
|
||||
|
||||
* [2023 Nov 26](ChangeLog/20231126.md) - version 0.23.0
|
||||
* [2023 Aug 27](ChangeLog/20230827.md) - version 0.22.0
|
||||
* [2023 May 28](ChangeLog/20230528.md) - version 0.21.0
|
||||
* [2023 Feb 26](ChangeLog/20230226.md) - version 0.20.0
|
||||
|
||||
@@ -482,131 +482,6 @@ $ qmk import-kbfirmware ~/Downloads/gh62.json
|
||||
|
||||
---
|
||||
|
||||
# External Userspace Commands
|
||||
|
||||
## `qmk userspace-add`
|
||||
|
||||
This command adds a keyboard/keymap to the External Userspace build targets.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk userspace-add [-h] [-km KEYMAP] [-kb KEYBOARD] [builds ...]
|
||||
|
||||
positional arguments:
|
||||
builds List of builds in form <keyboard>:<keymap>, or path to a keymap JSON file.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-km KEYMAP, --keymap KEYMAP
|
||||
The keymap to build a firmware for. Ignored when a configurator export is supplied.
|
||||
-kb KEYBOARD, --keyboard KEYBOARD
|
||||
The keyboard to build a firmware for. Ignored when a configurator export is supplied.
|
||||
```
|
||||
|
||||
**Example**:
|
||||
|
||||
```
|
||||
$ qmk userspace-add -kb planck/rev6 -km default
|
||||
Ψ Added planck/rev6:default to userspace build targets
|
||||
Ψ Saved userspace file to /home/you/qmk_userspace/qmk.json
|
||||
```
|
||||
|
||||
## `qmk userspace-remove`
|
||||
|
||||
This command removes a keyboard/keymap from the External Userspace build targets.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk userspace-remove [-h] [-km KEYMAP] [-kb KEYBOARD] [builds ...]
|
||||
|
||||
positional arguments:
|
||||
builds List of builds in form <keyboard>:<keymap>, or path to a keymap JSON file.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-km KEYMAP, --keymap KEYMAP
|
||||
The keymap to build a firmware for. Ignored when a configurator export is supplied.
|
||||
-kb KEYBOARD, --keyboard KEYBOARD
|
||||
The keyboard to build a firmware for. Ignored when a configurator export is supplied.
|
||||
```
|
||||
|
||||
**Example**:
|
||||
|
||||
```
|
||||
$ qmk userspace-remove -kb planck/rev6 -km default
|
||||
Ψ Removed planck/rev6:default from userspace build targets
|
||||
Ψ Saved userspace file to /home/you/qmk_userspace/qmk.json
|
||||
```
|
||||
|
||||
## `qmk userspace-list`
|
||||
|
||||
This command lists the External Userspace build targets.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk userspace-list [-h] [-e]
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-e, --expand Expands any use of `all` for either keyboard or keymap.
|
||||
```
|
||||
|
||||
**Example**:
|
||||
|
||||
```
|
||||
$ qmk userspace-list
|
||||
Ψ Current userspace build targets:
|
||||
Ψ Keyboard: planck/rev6, keymap: you
|
||||
Ψ Keyboard: clueboard/66/rev3, keymap: you
|
||||
```
|
||||
|
||||
## `qmk userspace-compile`
|
||||
|
||||
This command compiles all the External Userspace build targets.
|
||||
|
||||
**Usage**:
|
||||
|
||||
```
|
||||
qmk userspace-compile [-h] [-e ENV] [-n] [-c] [-j PARALLEL] [-t]
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-e ENV, --env ENV Set a variable to be passed to make. May be passed multiple times.
|
||||
-n, --dry-run Don't actually build, just show the commands to be run.
|
||||
-c, --clean Remove object files before compiling.
|
||||
-j PARALLEL, --parallel PARALLEL
|
||||
Set the number of parallel make jobs; 0 means unlimited.
|
||||
-t, --no-temp Remove temporary files during build.
|
||||
```
|
||||
|
||||
**Example**:
|
||||
|
||||
```
|
||||
$ qmk userspace-compile
|
||||
Ψ Preparing target list...
|
||||
Build planck/rev6:you [OK]
|
||||
Build clueboard/66/rev3:you [OK]
|
||||
```
|
||||
|
||||
## `qmk userspace-doctor`
|
||||
|
||||
This command examines your environment and alerts you to potential problems related to External Userspace.
|
||||
|
||||
**Example**:
|
||||
|
||||
```
|
||||
% qmk userspace-doctor
|
||||
Ψ QMK home: /home/you/qmk_userspace/qmk_firmware
|
||||
Ψ Testing userspace candidate: /home/you/qmk_userspace -- Valid `qmk.json`
|
||||
Ψ QMK userspace: /home/you/qmk_userspace
|
||||
Ψ Userspace enabled: True
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Developer Commands
|
||||
|
||||
## `qmk format-text`
|
||||
|
||||
@@ -70,7 +70,6 @@ We have a few different types of changes in QMK, each requiring a different leve
|
||||
* Keymaps: Make sure that `make keyboard:keymap` does not return any errors.
|
||||
* Keyboards: Make sure that `make keyboard:all` does not return any errors.
|
||||
* Core: Make sure that `make all` does not return any errors.
|
||||
* Note that user-keymap and userspace contributions are no longer accepted.
|
||||
* Make sure commit messages are understandable on their own. You should put a short description (no more than 70 characters) on the first line, the second line should be empty, and on the 3rd and later lines you should describe your commit in detail, if required. Example:
|
||||
|
||||
```
|
||||
@@ -81,6 +80,8 @@ The kerpleplork was intermittently failing with error code 23. The root cause wa
|
||||
Limited experimentation on the devices I have available shows that 7 is high enough to avoid confusing the kerpleplork, but I'd like to get some feedback from people with ARM devices to be sure.
|
||||
```
|
||||
|
||||
!> **IMPORTANT:** If you would like to contribute a bugfix or improvement to user code, such as non-default keymaps, userspace and layouts, be sure to tag the original submitter of the code in your PR. Many users, regardless of skill level with Git and GitHub, may be confused or frustrated at their code being modified without their knowledge.
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation is one of the easiest ways to get started contributing to QMK. Finding places where the documentation is wrong or incomplete and fixing those is easy! We also very badly need someone to edit our documentation, so if you have editing skills but aren't sure where or how to jump in please [reach out for help](#where-can-i-go-for-help)!
|
||||
|
||||
@@ -283,65 +283,6 @@ void suspend_wakeup_init_user(void) {
|
||||
* Keyboard/Revision: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
|
||||
* Keymap: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)`
|
||||
|
||||
|
||||
# Keyboard Shutdown/Reboot Code :id=keyboard-shutdown-reboot-code
|
||||
|
||||
This function gets called whenever the firmware is reset, whether it's a soft reset or reset to the bootloader. This is the spot to use for any sort of cleanup, as this happens right before the actual reset. And it can be useful for turning off different systems (such as RGB, onboard screens, etc).
|
||||
|
||||
Additionally, it differentiates between the soft reset (eg, rebooting back into the firmware) or jumping to the bootloader.
|
||||
|
||||
Certain tasks are performed during shutdown too. The keyboard is cleared, music and midi is stopped (if enabled), the shutdown chime is triggered (if audio is enabled), and haptic is stopped.
|
||||
|
||||
If `jump_to_bootloader` is set to `true`, this indicates that the board will be entering the bootloader for a new firmware flash, whereas `false` indicates that this is happening for a soft reset and will load the firmware agaim immediately (such as when using `QK_REBOOT` or `QK_CLEAR_EEPROM`).
|
||||
|
||||
As there is a keyboard and user level function, returning `false` for the user function will disable the keyboard level function, allowing for customization.
|
||||
|
||||
?> Bootmagic does not trigger `shutdown_*()` as it happens before most of the initialization process.
|
||||
|
||||
### Example `shutdown_kb()` Implementation
|
||||
|
||||
```c
|
||||
bool shutdown_kb(bool jump_to_bootloader) {
|
||||
if (!shutdown_user(jump_to_bootloader)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (jump_to_bootloader) {
|
||||
// red for bootloader
|
||||
rgb_matrix_set_color_all(RGB_OFF);
|
||||
} else {
|
||||
// off for soft reset
|
||||
rgb_matrix_set_color_all(RGB_GREEN);
|
||||
}
|
||||
// force flushing -- otherwise will never happen
|
||||
rgb_matrix_update_pwm_buffers();
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Example `shutdown_user()` Implementation
|
||||
|
||||
```c
|
||||
bool shutdown_user(bool jump_to_bootloader) {
|
||||
if (jump_to_bootloader) {
|
||||
// red for bootloader
|
||||
rgb_matrix_set_color_all(RGB_RED);
|
||||
} else {
|
||||
// off for soft reset
|
||||
rgb_matrix_set_color_all(RGB_OFF);
|
||||
}
|
||||
// force flushing -- otherwise will never happen
|
||||
rgb_matrix_update_pwm_buffers();
|
||||
// false to not process kb level
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
### Keyboard shutdown/reboot Function Documentation
|
||||
|
||||
* Keyboard/Revision: `bool shutdown_kb(bool jump_to_bootloader)`
|
||||
* Keymap: `bool shutdown_user(bool jump_to_bootloader)`
|
||||
|
||||
# Deferred Execution :id=deferred-execution
|
||||
|
||||
QMK has the ability to execute a callback after a specified period of time, rather than having to manually manage timers. To enable this functionality, set `DEFERRED_EXEC_ENABLE = yes` in rules.mk.
|
||||
|
||||
@@ -40,6 +40,7 @@ Add the following to your `config.h`:
|
||||
|`BACKLIGHT_DEFAULT_ON` |`true` |Enable backlight upon clearing the EEPROM |
|
||||
|`BACKLIGHT_DEFAULT_BREATHING`|`false` |Whether to enable backlight breathing upon clearing the EEPROM |
|
||||
|`BACKLIGHT_DEFAULT_LEVEL` |`BACKLIGHT_LEVELS`|The default backlight level to use upon clearing the EEPROM |
|
||||
|`BACKLIGHT_PWM_PERIOD` |2048Hz |Defaults to `BACKLIGHT_PWM_COUNTER_FREQUENCY / 2048`, which results in a PWM frequency of 2048Hz. |
|
||||
|
||||
Unless you are designing your own keyboard, you generally should not need to change the `BACKLIGHT_PIN` or `BACKLIGHT_ON_STATE`.
|
||||
|
||||
@@ -173,13 +174,11 @@ Depending on the ChibiOS board configuration, you may need to enable PWM at the
|
||||
|
||||
The following `#define`s apply only to the `pwm` driver:
|
||||
|
||||
|Define |Default |Description |
|
||||
|-----------------------|-------------|---------------------------------------------------------------|
|
||||
|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use |
|
||||
|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
|
||||
|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use |
|
||||
|`BACKLIGHT_PWM_PERIOD` |*Not defined*|The PWM period in counter ticks - Default is platform dependent|
|
||||
|
||||
|Define |Default |Description |
|
||||
|-----------------------|--------|-----------------------------------|
|
||||
|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use |
|
||||
|`BACKLIGHT_PWM_CHANNEL`|`3` |The PWM channel to use |
|
||||
|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use|
|
||||
|
||||
Refer to the ST datasheet for your particular MCU to determine these values. For example, these defaults are set up for pin `B8` on a Proton-C (STM32F303) using `TIM4_CH3` on AF2. Unless you are designing your own keyboard, you generally should not need to change them.
|
||||
|
||||
|
||||
@@ -345,9 +345,10 @@ is not set, all other layers will reference themselves.
|
||||
}
|
||||
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
|
||||
COMBO_REF_LAYER(_DVORAK, _QWERTY)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# Converters
|
||||
|
||||
This page documents the automated process for converting keyboards to use drop-in replacement controllers. This process is designed to be easy to use and can be completed in a few simple steps.
|
||||
Since many drop-in replacement controllers now exist, we've done our best to make them easy to use in existing designs.
|
||||
|
||||
## Supported Converters
|
||||
This page documents the handy automated process for converting keyboards.
|
||||
|
||||
The following converters are available at this time:
|
||||
### Supported Converters
|
||||
|
||||
Currently the following converters are available:
|
||||
|
||||
| From | To |
|
||||
|------------|-------------------|
|
||||
@@ -19,7 +21,6 @@ The following converters are available at this time:
|
||||
| `promicro` | `elite_pi` |
|
||||
| `promicro` | `helios` |
|
||||
| `promicro` | `liatris` |
|
||||
| `promicro` | `imera` |
|
||||
| `promicro` | `michi` |
|
||||
| `elite_c` | `stemcell` |
|
||||
| `elite_c` | `rp2040_ce` |
|
||||
@@ -27,10 +28,14 @@ The following converters are available at this time:
|
||||
| `elite_c` | `helios` |
|
||||
| `elite_c` | `liatris` |
|
||||
|
||||
See below for more in depth information on each converter.
|
||||
|
||||
## Overview
|
||||
|
||||
Each converter category is broken down by its declared `pin compatibility`. This ensures that only valid combinations are attempted. You can generate the firmware by appending `-e CONVERT_TO=<target>` to your compile/flash command. For example:
|
||||
Each converter category is broken down by its declared `pin compatibility`.
|
||||
This ensures that only valid combinations are attempted.
|
||||
|
||||
You can generate the firmware by appending `-e CONVERT_TO=<target>` to your compile/flash command. For example:
|
||||
|
||||
```sh
|
||||
qmk flash -c -kb keebio/bdn9/rev1 -km default -e CONVERT_TO=proton_c
|
||||
@@ -54,12 +59,14 @@ Once a converter is enabled, it exposes the `CONVERT_TO_<target_uppercase>` flag
|
||||
|
||||
### Pin Compatibility
|
||||
|
||||
To ensure compatibility, provide validation, and enable future workflows, a keyboard should declare its `pin compatibility`. For legacy reasons, this is currently assumed to be `promicro`. The following pin compatibility interfaces are currently defined:
|
||||
To ensure compatibility, provide validation, and power future workflows, a keyboard should declare its `pin compatibility`. For legacy reasons, this is currently assumed to be `promicro`.
|
||||
|
||||
| Pin Compatibility | Notes |
|
||||
|-------------------|-----------------------------------|
|
||||
| `promicro` | Includes RX/TX LEDs |
|
||||
| `elite_c` | Includes bottom row pins, no LEDs |
|
||||
Currently the following pin compatibility interfaces are defined:
|
||||
|
||||
| Pinout | Notes |
|
||||
|------------|-----------------------------------|
|
||||
| `promicro` | Includes RX/TX LEDs |
|
||||
| `elite_c` | Includes bottom row pins, no LEDs |
|
||||
|
||||
To declare the base for conversions, add this line to your keyboard's `rules.mk`:
|
||||
|
||||
@@ -83,7 +90,6 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
|
||||
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
|
||||
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
|
||||
| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
|
||||
| [Imera](https://splitkb.com/products/imera) | `imera` |
|
||||
| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` |
|
||||
|
||||
Converter summary:
|
||||
@@ -101,7 +107,6 @@ Converter summary:
|
||||
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
|
||||
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
|
||||
| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
|
||||
| `imera` | `-e CONVERT_TO=imera` | `CONVERT_TO=imera` | `#ifdef CONVERT_TO_IMERA` |
|
||||
| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` |
|
||||
|
||||
### Proton C :id=proton_c
|
||||
@@ -135,7 +140,7 @@ The following defaults are based on what has been implemented for [RP2040](platf
|
||||
|
||||
### SparkFun Pro Micro - RP2040, Blok, Bit-C PRO and Michi :id=promicro_rp2040
|
||||
|
||||
Feature set is identical to [Adafruit KB2040](#kb2040).
|
||||
Currently identical to [Adafruit KB2040](#kb2040).
|
||||
|
||||
### STeMCell :id=stemcell
|
||||
|
||||
@@ -145,7 +150,9 @@ There are two versions of STeMCell available, with different pinouts:
|
||||
- v2.0.0 (pre-release v1.0.1, v1.0.2)
|
||||
Default official firmware only supports v2.0.0 STeMCell.
|
||||
|
||||
STeMCell has support to swap UART and I2C pins to enable single-wire uart communication in STM chips. The following additional flags has to be used while compiling, based on the pin used for split communication:
|
||||
STeMCell has support to swap UART and I2C pins, to enable single-wire uart communication in STM chips.
|
||||
|
||||
The following additional flags has to be used while compiling, based on the pin used for split communication.
|
||||
|
||||
| Split Pin | Compile flags |
|
||||
|-----------|---------------|
|
||||
@@ -166,8 +173,11 @@ The Bonsai C4 only has one on-board LED (B2), and by default, both the Pro Micro
|
||||
|
||||
### RP2040 Community Edition - Elite-Pi, Helios, and Liatris :id=rp2040_ce
|
||||
|
||||
Feature set is identical to [Adafruit KB2040](#kb2040). VBUS detection is enabled by default for superior split keyboard support. For more information, refer to the [Community Edition pinout](platformdev_rp2040.md#rp2040_ce) docs.
|
||||
Feature set currently identical to [Adafruit KB2040](#kb2040).
|
||||
|
||||
Enables VBUS detection by default for superior split keyboard support.
|
||||
|
||||
For more information, refer to the [RP2040 Community Edition](platformdev_rp2040.md#rp2040_ce) docs.
|
||||
|
||||
## Elite-C
|
||||
|
||||
@@ -192,8 +202,8 @@ Converter summary:
|
||||
|
||||
### STeMCell :id=stemcell_elite
|
||||
|
||||
Identical to [Pro Micro - STeMCell](#stemcell) with support for the additional bottom row of pins.
|
||||
Currently identical to [STeMCell](#stemcell) with support for the additional bottom row of pins.
|
||||
|
||||
### RP2040 Community Edition :id=rp2040_ce_elite
|
||||
|
||||
Identical to [Pro Micro - RP2040 Community Edition](#rp2040_ce) with support for the additional bottom row of pins.
|
||||
Currently identical to [RP2040 Community Edition](#rp2040_ce), with support for the additional bottom row of pins.
|
||||
|
||||
@@ -20,27 +20,6 @@ or
|
||||
#define DIP_SWITCH_MATRIX_GRID { {0,6}, {1,6}, {2,6} } // List of row and col pairs
|
||||
```
|
||||
|
||||
## DIP Switch map :id=dip-switch-map
|
||||
|
||||
DIP Switch mapping may be added to your `keymap.c`, which replicates the normal keyswitch functionality, but with dip switches. Add this to your keymap's `rules.mk`:
|
||||
|
||||
```make
|
||||
DIP_SWITCH_MAP_ENABLE = yes
|
||||
```
|
||||
|
||||
Your `keymap.c` will then need a dip switch mapping defined (for two dip switches):
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
?> This should only be enabled at the keymap level.
|
||||
|
||||
## Callbacks
|
||||
|
||||
The callback functions can be inserted into your `<keyboard>.c`:
|
||||
|
||||
@@ -21,7 +21,7 @@ Then, in your `keymap.c` file, you'll need to define the array `key_overrides`,
|
||||
The `key_override_t` struct has many options that allow you to precisely tune your overrides. The full reference is shown below. Instead of manually creating a `key_override_t` value, it is recommended to use these dedicated initializers:
|
||||
|
||||
#### `ko_make_basic(modifiers, key, replacement)`
|
||||
Returns a `key_override_t`, which sends `replacement` (can be a key-modifier combination), when `key` and `modifiers` are all pressed down. This override still activates if any additional modifiers not specified in `modifiers` are also pressed down. See `ko_make_with_layers_and_negmods` to customize this behavior.
|
||||
Returns a `key_override_t`, which sends `replacement` (can be a key-modifer combination), when `key` and `modifiers` are all pressed down. This override still activates if any additional modifiers not specified in `modifiers` are also pressed down. See `ko_make_with_layers_and_negmods` to customize this behavior.
|
||||
|
||||
#### `ko_make_with_layers(modifiers, key, replacement, layers)`
|
||||
Additionally takes a bitmask `layers` that defines on which layers the override is used.
|
||||
@@ -224,7 +224,7 @@ The duration of the key repeat delay is controlled with the `KEY_OVERRIDE_REPEAT
|
||||
|
||||
## Difference to Combos :id=difference-to-combos
|
||||
|
||||
Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interaction with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable.
|
||||
Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interacton with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable.
|
||||
|
||||
## Solution to the problem of flashing modifiers :id=neutralize-flashing-modifiers
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ You can use between 1 and 4 IS31FL3731 IC's. Do not specify `LED_DRIVER_ADDR_<N>
|
||||
|----------|-------------|---------|
|
||||
| `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
|
||||
| `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
|
||||
| `IS31FL3731_DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
|
||||
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
|
||||
| `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first LED driver | |
|
||||
| `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second LED driver | |
|
||||
@@ -42,6 +43,7 @@ Here is an example using 2 drivers.
|
||||
#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
|
||||
#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
|
||||
|
||||
#define IS31FL3731_DRIVER_COUNT 2
|
||||
#define LED_DRIVER_1_LED_TOTAL 25
|
||||
#define LED_DRIVER_2_LED_TOTAL 24
|
||||
#define LED_MATRIX_LED_COUNT (LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL)
|
||||
@@ -94,6 +96,7 @@ Configure the hardware via your `config.h`:
|
||||
|----------|-------------|---------|
|
||||
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
|
||||
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
|
||||
| `DRIVER_COUNT` | (Required) How many LED driver IC's are present | |
|
||||
| `LED_MATRIX_LED_COUNT` | (Required) How many LED lights are present across all drivers | |
|
||||
| `DRIVER_ADDR_1` | (Optional) Address for the first LED driver | |
|
||||
| `DRIVER_ADDR_<N>` | (Required) Address for the additional LED drivers | |
|
||||
@@ -126,6 +129,7 @@ Here is an example using 2 drivers.
|
||||
```c
|
||||
#define DRIVER_ADDR_2 0b0100001
|
||||
|
||||
#define DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 66
|
||||
#define DRIVER_2_LED_TOTAL 42
|
||||
#define LED_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
|
||||
@@ -69,9 +69,9 @@ The current list of available languages is:
|
||||
| **italian_osx_iso** | **jis** | **latvian** | **lithuanian_azerty** |
|
||||
| **lithuanian_qwerty** | **norman** | **norwegian** | **portuguese** |
|
||||
| **portuguese_osx_iso** | **romanian** | **serbian_latin** | **slovak** |
|
||||
| **slovenian** | **spanish_dvorak** | **spanish_latin_america** | **spanish** |
|
||||
| **swedish** | **turkish_f** | **turkish_q** | **uk** |
|
||||
| **us_international** | **workman** | **workman_zxcvm** |
|
||||
| **slovenian** | **spanish_dvorak** | **spanish** | **swedish** |
|
||||
| **turkish_f** | **turkish_q** | **uk** | **us_international** |
|
||||
| **workman** | **workman_zxcvm** |
|
||||
|
||||
### Macro Basics
|
||||
|
||||
|
||||
@@ -183,8 +183,22 @@ void oled_render_boot(bool bootloader) {
|
||||
oled_render_dirty(true);
|
||||
}
|
||||
|
||||
bool shutdown_user(bool jump_to_bootloader) {
|
||||
oled_render_boot(jump_to_bootloader);
|
||||
bool reboot = false;
|
||||
|
||||
bool uint16_t keycode, keyrecord_t *record) {
|
||||
if (record->event.pressed) {
|
||||
|
||||
// Display a special message prior to rebooting...
|
||||
if (keycode == QK_BOOT) {
|
||||
reboot = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown_user(void) {
|
||||
oled_render_boot(reboot);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -213,7 +227,7 @@ These configuration options should be placed in `config.h`. Example:
|
||||
|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
|
||||
|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
|
||||
|`OLED_UPDATE_INTERVAL` |`0` (`50` for split keyboards) |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
|
||||
|`OLED_UPDATE_PROCESS_LIMIT`|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
|
||||
|`OLED_UPDATE_PROCESS_LIMIT'|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
|
||||
|
||||
### I2C Configuration
|
||||
|Define |Default |Description |
|
||||
|
||||
@@ -36,15 +36,10 @@ This time is quite short, probably hundreds of milliseconds, but this data may b
|
||||
|
||||
If OS is guessed incorrectly, you may want to collect data about USB setup packets to refine the detection logic.
|
||||
|
||||
To do so in your `config.h` add:
|
||||
|
||||
```c
|
||||
#define OS_DETECTION_DEBUG_ENABLE
|
||||
```
|
||||
|
||||
And in your `rules.mk` add:
|
||||
To do so in your `rules.mk` add:
|
||||
|
||||
```make
|
||||
OS_DETECTION_DEBUG_ENABLE = yes
|
||||
CONSOLE_ENABLE = yes
|
||||
```
|
||||
|
||||
|
||||
@@ -69,94 +69,10 @@ The Analog Joystick is an analog (ADC) driven sensor. There are a variety of jo
|
||||
| `ANALOG_JOYSTICK_Y_AXIS_PIN` | (Required) The pin used for the horizontal/Y axis. | _not defined_ |
|
||||
| `ANALOG_JOYSTICK_AXIS_MIN` | (Optional) Sets the lower range to be considered movement. | `0` |
|
||||
| `ANALOG_JOYSTICK_AXIS_MAX` | (Optional) Sets the upper range to be considered movement. | `1023` |
|
||||
| `ANALOG_JOYSTICK_AUTO_AXIS` | (Optional) Sets ranges to be considered movement automatically. | _not defined_ |
|
||||
| `ANALOG_JOYSTICK_SPEED_REGULATOR` | (Optional) The divisor used to slow down movement. (lower makes it faster) | `20` |
|
||||
| `ANALOG_JOYSTICK_READ_INTERVAL` | (Optional) The interval in milliseconds between reads. | `10` |
|
||||
| `ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maximum value used for motion. | `2` |
|
||||
| `ANALOG_JOYSTICK_CLICK_PIN` | (Optional) The pin wired up to the press switch of the analog stick. | _not defined_ |
|
||||
| `ANALOG_JOYSTICK_WEIGHTS` | (Optional) Use custom weights for lever positions. | _not defined_ |
|
||||
| `ANALOG_JOYSTICK_CUTOFF` | (Optional) Cut off movement when joystick returns to start position. | _not defined_ |
|
||||
|
||||
If `ANALOG_JOYSTICK_AUTO_AXIS` is used, then `ANALOG_JOYSTICK_AXIS_MIN` and `ANALOG_JOYSTICK_AXIS_MAX` are ignored.
|
||||
|
||||
By default analog joystick implementation uses `x^2` weighting for lever positions. `ANALOG_JOYSTICK_WEIGHTS` allows to experiment with different configurations that might feel better.
|
||||
|
||||
E.g. This is weights for `((x-0.4)^3+0.064)/0.282`:
|
||||
|
||||
```c
|
||||
#define ANALOG_JOYSTICK_WEIGHTS {0,2,4,5,7,8,9,10,12,13,14,15,15,16,17,18,18,19,19,20,20,21,21,21,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,25,25,25,26,26,26,27,28,28,29,29,30,31,32,33,34,35,36,37,38,40,41,43,44,46,48,49,51,53,56,58,60,62,65,68,70,73,76,79,82,85,89,92,96,100}
|
||||
```
|
||||
|
||||
You can use following JS code to generate weights for different formulas:
|
||||
|
||||
```js
|
||||
JSON.stringify(Array.from(Array(101).keys()).map(x => Math.ceil((((x/100-0.4)**3+0.064)/0.282*100))))
|
||||
```
|
||||
|
||||
### Azoteq IQS5XX Trackpad
|
||||
|
||||
To use a Azoteq IQS5XX trackpad, add this to your `rules.mk`:
|
||||
|
||||
```make
|
||||
POINTING_DEVICE_DRIVER = azoteq_iqs5xx
|
||||
```
|
||||
|
||||
This supports the IQS525, IQS550 and IQS572 controllers, with the latter two being used in the TPS43 and TPS65 trackpads.
|
||||
|
||||
#### Device settings
|
||||
|
||||
Specific device profiles are provided which set the required values for dimensions and resolution.
|
||||
|
||||
| Setting | Description |
|
||||
| -------------------------------- | ---------------------------------------------------------- |
|
||||
| `AZOTEQ_IQS5XX_TPS43` | (Pick One) Sets resolution/mm to TPS43 specifications. |
|
||||
| `AZOTEQ_IQS5XX_TPS65` | (Pick One) Sets resolution/mm to TPS65 specifications. |
|
||||
|
||||
?> If using one of the above defines you can skip to gesture settings.
|
||||
|
||||
| Setting | Description | Default |
|
||||
| -------------------------------- | ---------------------------------------------------------- | ------------- |
|
||||
| `AZOTEQ_IQS5XX_WIDTH_MM` | (Required) Width of the trackpad sensor in millimeters. | _not defined_ |
|
||||
| `AZOTEQ_IQS5XX_HEIGHT_MM` | (Required) Height of the trackpad sensor in millimeters. | _not defined_ |
|
||||
| `AZOTEQ_IQS5XX_RESOLUTION_X` | (Optional) Specify X resolution for CPI calculation. | _not defined_ |
|
||||
| `AZOTEQ_IQS5XX_RESOLUTION_Y` | (Optional) Specify Y resolution for CPI calculation. | _not defined_ |
|
||||
|
||||
**`AZOTEQ_IQS5XX_RESOLUTION_X/Y`** fall back resolutions are provided within the driver based on controller model.
|
||||
|
||||
| I2C Setting | Description | Default |
|
||||
| ------------------------- | ------------------------------------------------------------------------------- | ------- |
|
||||
| `AZOTEQ_IQS5XX_ADDRESS` | (Optional) Sets the I2C Address for the Azoteq trackpad | `0xE8` |
|
||||
| `AZOTEQ_IQS5XX_TIMEOUT_MS`| (Optional) The timeout for i2c communication with in milliseconds. | `10` |
|
||||
|
||||
#### Gesture settings
|
||||
|
||||
| Setting | Description | Default |
|
||||
| ----------------------------------------- | ------------------------------------------------------------------------------------ | ----------- |
|
||||
| `AZOTEQ_IQS5XX_TAP_ENABLE` | (Optional) Enable single finger tap. (Left click) | `true` |
|
||||
| `AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE` | (Optional) Enable two finger tap. (Right click) | `true` |
|
||||
| `AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE` | (Optional) Emulates holding left click to select text. | `false` |
|
||||
| `AZOTEQ_IQS5XX_SWIPE_X_ENABLE` | (Optional) Enable swipe gestures X+ (Mouse Button 5) / X- (Mouse Button 4) | `false` |
|
||||
| `AZOTEQ_IQS5XX_SWIPE_Y_ENABLE` | (Optional) Enable swipe gestures Y+ (Mouse Button 3) / Y- (Mouse Button 6) | `false` |
|
||||
| `AZOTEQ_IQS5XX_ZOOM_ENABLE` | (Optional) Enable zoom gestures Zoom Out (Mouse Button 7) / Zoom In (Mouse Button 8) | `false` |
|
||||
| `AZOTEQ_IQS5XX_SCROLL_ENABLE` | (Optional) Enable scrolling using two fingers. | `true` |
|
||||
| `AZOTEQ_IQS5XX_TAP_TIME` | (Optional) Maximum time in ms for tap to be registered. | `150` |
|
||||
| `AZOTEQ_IQS5XX_TAP_DISTANCE` | (Optional) Maximum deviation in pixels before single tap is no longer valid. | `25` |
|
||||
| `AZOTEQ_IQS5XX_HOLD_TIME` | (Optional) Minimum time in ms for press and hold. | `300` |
|
||||
| `AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME` | (Optional) Maximum time to travel initial distance before swipe is registered. | `150` |
|
||||
| `AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE` | (Optional) Minimum travel in pixels before swipe is registered. | `300` |
|
||||
| `AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME` | (Optional) Maximum time to travel consecutive distance before swipe is registered. | `0` |
|
||||
| `AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE`| (Optional) Minimum travel in pixels before a consecutive swipe is registered. | `2000` |
|
||||
| `AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE` | (Optional) Minimum travel in pixels before scroll is registered. | `50` |
|
||||
| `AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE` | (Optional) Minimum travel in pixels before zoom is registered. | `50` |
|
||||
| `AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE` | (Optional) Maximum time to travel zoom distance before zoom is registered. | `25` |
|
||||
|
||||
#### Rotation settings
|
||||
|
||||
| Setting | Description | Default |
|
||||
| ---------------------------- | ---------------------------------------------------------- | ------------- |
|
||||
| `AZOTEQ_IQS5XX_ROTATION_90` | (Optional) Configures hardware for 90 degree rotation. | _not defined_ |
|
||||
| `AZOTEQ_IQS5XX_ROTATION_180` | (Optional) Configures hardware for 180 degree rotation. | _not defined_ |
|
||||
| `AZOTEQ_IQS5XX_ROTATION_270` | (Optional) Configures hardware for 270 degree rotation. | _not defined_ |
|
||||
|
||||
### Cirque Trackpad
|
||||
|
||||
@@ -177,13 +93,12 @@ This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the
|
||||
|
||||
#### Common settings
|
||||
|
||||
| Setting | Description | Default |
|
||||
| ------------------------------------ | ---------------------------------------------------------- | ------------------------------------------- |
|
||||
| `CIRQUE_PINNACLE_DIAMETER_MM` | (Optional) Diameter of the trackpad sensor in millimeters. | `40` |
|
||||
| `CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X` |
|
||||
| `CIRQUE_PINNACLE_CURVED_OVERLAY` | (Optional) Applies settings tuned for curved overlay. | _not defined_ |
|
||||
| `CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Mode of operation. | _not defined_ |
|
||||
| `CIRQUE_PINNACLE_SKIP_SENSOR_CHECK` | (Optional) Skips sensor presence check | _not defined_ |
|
||||
| Setting | Description | Default |
|
||||
| -------------------------------- | ---------------------------------------------------------- | ------------------------------------------- |
|
||||
| `CIRQUE_PINNACLE_DIAMETER_MM` | (Optional) Diameter of the trackpad sensor in millimeters. | `40` |
|
||||
| `CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X` |
|
||||
| `CIRQUE_PINNACLE_CURVED_OVERLAY` | (Optional) Applies settings tuned for curved overlay. | _not defined_ |
|
||||
| `CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Mode of operation. | _not defined_ |
|
||||
|
||||
**`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be.
|
||||
|
||||
@@ -820,11 +735,9 @@ layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
|
||||
#### Set different target layer when a particular layer is active:
|
||||
|
||||
The below code will change the auto mouse layer target to `_MOUSE_LAYER_2` when `_DEFAULT_LAYER_2` is highest default layer state.
|
||||
|
||||
*NOTE: that `auto_mouse_layer_off` is used here instead of `remove_auto_mouse_layer` as `default_layer_state_set_*` stack is separate from the `layer_state_set_*` stack*, if something similar was to be done in `layer_state_set_user`, `state = remove_auto_mouse_layer(state, false)` should be used instead.
|
||||
|
||||
*ADDITIONAL NOTE: `AUTO_MOUSE_TARGET_LAYER` is checked if already set to avoid deactivating the target layer unless needed*.
|
||||
The below code will change the auto mouse layer target to `_MOUSE_LAYER_2` when `_DEFAULT_LAYER_2` is highest default layer state.
|
||||
*NOTE: that `auto_mouse_layer_off` is used here instead of `remove_auto_mouse_layer` as `default_layer_state_set_*` stack is separate from the `layer_state_set_*` stack* if something similar was to be done in `layer_state_set_user `state = remove_auto_mouse_layer(state, false)` should be used instead
|
||||
*ADDITIONAL NOTE: `AUTO_MOUSE_TARGET_LAYER` is checked if already set to avoid deactivating the target layer unless needed*
|
||||
|
||||
```c
|
||||
// in keymap.c
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# Potentiometers
|
||||
|
||||
Add this to your `rules.mk`:
|
||||
|
||||
```make
|
||||
POTENTIOMETER_ENABLE = yes
|
||||
```
|
||||
|
||||
and this to your `config.h`:
|
||||
|
||||
```c
|
||||
#define POTENTIOMETER_PINS { B0 }
|
||||
```
|
||||
|
||||
## Callbacks
|
||||
|
||||
The callback functions can be inserted into your `<keyboard>.c`:
|
||||
|
||||
```c
|
||||
bool potentiometer_update_kb(uint8_t index, uint16_t value) {
|
||||
if (!potentiometer_update_user(index, value)) {
|
||||
midi_send_cc(&midi_device, 2, 0x3E, 0x7F + value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
or `keymap.c`:
|
||||
|
||||
```c
|
||||
bool potentiometer_update_user(uint8_t index, uint16_t value) {
|
||||
midi_send_cc(&midi_device, 2, 0x3E, 0x7F + value);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
@@ -22,6 +22,7 @@ You can use between 1 and 4 IS31FL3731 IC's. Do not specify `DRIVER_ADDR_<N>` de
|
||||
| `IS31FL3731_I2C_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
|
||||
| `IS31FL3731_I2C_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
|
||||
| `IS31FL3731_DEGHOST` | (Optional) Set this define to enable de-ghosting by halving Vcc during blanking time | |
|
||||
| `IS31FL3731_DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `IS31FL3731_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
|
||||
| `IS31FL3731_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
|
||||
@@ -43,6 +44,7 @@ Here is an example using 2 drivers.
|
||||
#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
|
||||
#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
|
||||
|
||||
#define IS31FL3731_DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 25
|
||||
#define DRIVER_2_LED_TOTAL 24
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
@@ -89,6 +91,7 @@ You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_<N>` de
|
||||
| `IS31FL3733_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
|
||||
| `IS31FL3733_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `IS31FL3733_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `IS31FL3733_DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `IS31FL3733_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
|
||||
| `IS31FL3733_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
|
||||
@@ -127,6 +130,7 @@ Here is an example using 2 drivers.
|
||||
#define IS31FL3733_I2C_ADDRESS_1 IS31FL3733_I2C_ADDRESS_GND_GND
|
||||
#define IS31FL3733_I2C_ADDRESS_2 IS31FL3733_I2C_ADDRESS_GND_VCC
|
||||
|
||||
#define IS31FL3733_DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 58
|
||||
#define DRIVER_2_LED_TOTAL 10
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
@@ -174,6 +178,7 @@ Configure the hardware via your `config.h`:
|
||||
| `IS31FL3736_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
|
||||
| `IS31FL3736_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `IS31FL3736_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `IS31FL3736_DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `IS31FL3736_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
|
||||
| `IS31FL3736_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
|
||||
@@ -209,6 +214,7 @@ Here is an example using 2 drivers.
|
||||
#define IS31FL3736_I2C_ADDRESS_1 IS31FL3736_I2C_ADDRESS_GND_GND
|
||||
#define IS31FL3736_I2C_ADDRESS_2 IS31FL3736_I2C_ADDRESS_GND_SCL
|
||||
|
||||
#define IS31FL3736_DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 30
|
||||
#define DRIVER_2_LED_TOTAL 32
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
@@ -249,6 +255,7 @@ Configure the hardware via your `config.h`:
|
||||
| `IS31FL3737_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
|
||||
| `IS31FL3737_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `IS31FL3737_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
|
||||
| `IS31FL3737_DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `IS31FL3737_I2C_ADDRESS_1` | (Required) Address for the first RGB driver | |
|
||||
| `IS31FL3737_I2C_ADDRESS_2` | (Optional) Address for the second RGB driver | |
|
||||
@@ -283,6 +290,7 @@ Here is an example using 2 drivers.
|
||||
#define IS31FL3737_I2C_ADDRESS_1 IS31FL3737_I2C_ADDRESS_GND
|
||||
#define IS31FL3737_I2C_ADDRESS_2 IS31FL3737_I2C_ADDRESS_SCL
|
||||
|
||||
#define IS31FL3737_DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 30
|
||||
#define DRIVER_2_LED_TOTAL 36
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
@@ -333,6 +341,7 @@ Configure the hardware via your `config.h`:
|
||||
|----------|-------------|---------|
|
||||
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
|
||||
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
|
||||
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `DRIVER_ADDR_1` | (Optional) Address for the first RGB driver | |
|
||||
| `DRIVER_ADDR_<N>` | (Required) Address for the additional RGB drivers | |
|
||||
@@ -367,6 +376,7 @@ Here is an example using 2 drivers.
|
||||
```c
|
||||
#define DRIVER_ADDR_2 0b0100001
|
||||
|
||||
#define DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 66
|
||||
#define DRIVER_2_LED_TOTAL 42
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
@@ -476,6 +486,7 @@ You can use up to 2 AW20216S IC's. Do not specify `DRIVER_<N>_xxx` defines for I
|
||||
| `AW20216S_EN_PIN_2` | (Optional) MCU pin connected to second RGB driver hardware enable line | |
|
||||
| `DRIVER_1_LED_TOTAL` | (Required) How many RGB lights are connected to first RGB driver | |
|
||||
| `DRIVER_2_LED_TOTAL` | (Optional) How many RGB lights are connected to second RGB driver | |
|
||||
| `AW20216S_DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
|
||||
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
|
||||
| `AW20216S_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
|
||||
| `AW20216S_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
|
||||
@@ -491,6 +502,7 @@ Here is an example using 2 drivers.
|
||||
#define AW20216S_EN_PIN_1 C13
|
||||
#define AW20216S_EN_PIN_2 C13
|
||||
|
||||
#define AW20216S_DRIVER_COUNT 2
|
||||
#define DRIVER_1_LED_TOTAL 66
|
||||
#define DRIVER_2_LED_TOTAL 32
|
||||
#define RGB_MATRIX_LED_COUNT (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
|
||||
@@ -656,10 +668,6 @@ enum rgb_matrix_effects {
|
||||
RGB_MATRIX_MULTISPLASH, // Full gradient & value pulse away from multiple key hits then fades value out
|
||||
RGB_MATRIX_SOLID_SPLASH, // Hue & value pulse away from a single key hit then fades value out
|
||||
RGB_MATRIX_SOLID_MULTISPLASH, // Hue & value pulse away from multiple key hits then fades value out
|
||||
RGB_MATRIX_STARLIGHT, // LEDs turn on and off at random at varying brightness, maintaining user set color
|
||||
RGB_MATRIX_STARLIGHT_DUAL_HUE, // LEDs turn on and off at random at varying brightness, modifies user set hue by +- 30
|
||||
RGB_MATRIX_STARLIGHT_DUAL_SAT, // LEDs turn on and off at random at varying brightness, modifies user set saturation by +- 30
|
||||
RGB_MATRIX_RIVERFLOW, // Modification to breathing animation, offset's animation depending on key location to simulate a river flowing
|
||||
RGB_MATRIX_EFFECT_MAX
|
||||
};
|
||||
```
|
||||
@@ -699,10 +707,6 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|
||||
|`#define ENABLE_RGB_MATRIX_PIXEL_FRACTAL` |Enables `RGB_MATRIX_PIXEL_FRACTAL` |
|
||||
|`#define ENABLE_RGB_MATRIX_PIXEL_FLOW` |Enables `RGB_MATRIX_PIXEL_FLOW` |
|
||||
|`#define ENABLE_RGB_MATRIX_PIXEL_RAIN` |Enables `RGB_MATRIX_PIXEL_RAIN` |
|
||||
|`#define ENABLE_RGB_MATRIX_STARLIGHT` |Enables `RGB_MATRIX_STARLIGHT` |
|
||||
|`#define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_HUE` |Enables `RGB_MATRIX_STARLIGHT_DUAL_HUE` |
|
||||
|`#define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_SAT` |Enables `RGB_MATRIX_STARLIGHT_DUAL_SAT` |
|
||||
|`#define ENABLE_RGB_MATRIX_RIVERFLOW` |Enables `RGB_MATRIX_RIVERFLOW` |
|
||||
|
||||
|Framebuffer Defines |Description |
|
||||
|------------------------------------------------------|----------------------------------------------|
|
||||
|
||||
@@ -525,6 +525,7 @@ By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED
|
||||
```
|
||||
<img src="https://user-images.githubusercontent.com/2170248/55743725-08ad7a80-5a6e-11e9-83ed-126a2b0209fc.JPG" alt="simple mapped" width="50%"/>
|
||||
|
||||
```
|
||||
## Clipping Range
|
||||
|
||||
Using the `rgblight_set_clipping_range()` function, you can prepare more buffers than the actual number of LEDs, and output some of the buffers to the LEDs. This is useful if you want the split keyboard to treat left and right LEDs as logically contiguous.
|
||||
@@ -544,8 +545,8 @@ In addition to setting the Clipping Range, you can use `RGBLIGHT_LED_MAP` togeth
|
||||
#define RGBLED_NUM 8
|
||||
#define RGBLIGHT_LED_MAP { 7, 6, 5, 4, 3, 2, 1, 0 }
|
||||
|
||||
// some source
|
||||
rgblight_set_clipping_range(3, 4);
|
||||
// some soruce
|
||||
rgblight_set_clipping_range(3, 4);
|
||||
```
|
||||
<img src="https://user-images.githubusercontent.com/2170248/55743747-119e4c00-5a6e-11e9-91e5-013203ffae8a.JPG" alt="clip mapped" width="70%"/>
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ This sets the pin to be used for serial communication. If you're not using seria
|
||||
However, if you are using serial and I<sup>2</sup>C on the board, you will need to set this, and to something other than D0 and D1 (as these are used for I<sup>2</sup>C communication).
|
||||
|
||||
```c
|
||||
#define SELECT_SOFT_SERIAL_SPEED {#}
|
||||
#define SELECT_SOFT_SERIAL_SPEED {#}`
|
||||
```
|
||||
|
||||
If you're having issues with serial communication, you can change this value, as it controls the communication speed for serial. The default is 1, and the possible values are:
|
||||
|
||||
@@ -104,7 +104,7 @@ After enabling stenography and optionally selecting a protocol, you may also nee
|
||||
|
||||
!> If you had *explicitly* set `VIRSTER_ENABLE = no`, none of the serial stenography protocols (GeminiPR, TX Bolt) will work properly. You are expected to either set it to `yes`, remove the line from your `rules.mk` or send the steno chords yourself in an alternative way using the [provided interceptable hooks](#interfacing-with-the-code).
|
||||
|
||||
In your keymap, create a new layer for Plover, that you can fill in with the [steno keycodes](#keycode-reference). Remember to create a key to switch to the layer as well as a key for exiting the layer.
|
||||
In your keymap, create a new layer for Plover, that you can fill in with the [steno keycodes](#keycode-reference) (you will need to include `keymap_steno.h`, see `planck/keymaps/steno/keymap.c` for an example). Remember to create a key to switch to the layer as well as a key for exiting the layer.
|
||||
|
||||
Once you have your keyboard flashed, launch Plover. Click the 'Configure...' button. In the 'Machine' tab, select the Stenotype Machine that corresponds to your desired protocol. Click the 'Configure...' button on this tab and enter the serial port or click 'Scan'. Baud rate is fine at 9600 (although you should be able to set as high as 115200 with no issues). Use the default settings for everything else (Data Bits: 8, Stop Bits: 1, Parity: N, no flow control).
|
||||
|
||||
@@ -149,6 +149,8 @@ At the end of this scenario given as an example, `chord` would have five bits se
|
||||
|
||||
## Keycode Reference :id=keycode-reference
|
||||
|
||||
You must include `keymap_steno.h` to your `keymap.c` with `#include "keymap_steno.h"` before you can use these keycodes
|
||||
|
||||
> Note: TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
|
||||
|
||||
|GeminiPR|TX Bolt|Steno Key|
|
||||
@@ -196,7 +198,7 @@ At the end of this scenario given as an example, `chord` would have five bits se
|
||||
|`STN_RES2`||(Reset 2)|
|
||||
|`STN_PWR`||(Power)|
|
||||
|
||||
If you do not want to hit two keys with one finger combined keycodes can be used. These cause both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file.
|
||||
If you do not want to hit two keys with one finger combined keycodes can be used. These are also defined in `keymap_steno.h`, and causes both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file.
|
||||
|
||||
|Combined key | Key1 | Key 2 |
|
||||
|---------------|--------|----------|
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Userspace: Sharing Code Between Keymaps
|
||||
|
||||
!> Please note, userspace submissions to the upstream `qmk/qmk_firmware` repository are no longer being accepted. The userspace feature itself remains functional and can be configured locally.
|
||||
|
||||
If you use more than one keyboard with a similar keymap, you might see the benefit in being able to share code between them. Create your own folder in `users/` named the same as your keymap (ideally your GitHub username, `<name>`) with the following structure:
|
||||
|
||||
* `/users/<name>/` (added to the path automatically)
|
||||
|
||||
@@ -110,11 +110,11 @@ enum my_keycodes {
|
||||
|
||||
開発環境をセットアップした場合は、プルリクエストを開く前に以下のコマンドを `qmk_firmware/` フォルダから実行することで、あなたの変更をプレビューすることができます:
|
||||
|
||||
qmk docs
|
||||
./bin/qmk docs
|
||||
|
||||
または、Python 3 のみがインストールされている場合:
|
||||
|
||||
python3 -m http.server 8936 --directory docs
|
||||
python3 -m http.server 8936
|
||||
|
||||
その後、ウェブブラウザで、`http://localhost:8936/` を表示します。
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
「キー別」の関数全てにキーレコードを含んでいることに気付いたかもしれません。そしてなぜそうしたのか不思議に思っているかもしれません。
|
||||
|
||||
まぁ、それは単純に本当にカスタマイズのためです。ただし、具体的には、それはキーボードの配線方法によって異なります。例えば、各行が実際にキーボードのマトリックスの1行を使っている場合、キーコード全体をチェックする代わりに、`if (record->event.key.row == 3)` を使うほうが簡単かもしれません。これは、ホームキー行でタップホールドタイプのキーを使っている人にとって特に便利です。そのため、通常のタイピングを妨げないように微調整することができるのではないでしょうか。
|
||||
まぁ、それは単純に本当にカスタマイズのためです。ただし、具体的には、それはキーボードの配線方法によって異なります。例えば、各行が実際にキーボードのマトリックスの1行を使っている場合、キーコード全体をチェックする代わりに、`if (record->event.row == 3)` を使うほうが簡単かもしれません。これは、ホームキー行でタップホールドタイプのキーを使っている人にとって特に便利です。そのため、通常のタイピングを妨げないように微調整することができるのではないでしょうか。
|
||||
|
||||
## `*_kb` や `*_user` 関数が無いのはなぜですか?
|
||||
|
||||
|
||||
@@ -143,13 +143,13 @@ Replace `username.json` with the JSON file name that was downloaded from [QMK Co
|
||||
|
||||
If you have completed all steps correctly, the folder `qmk_keymap/` will contain the following files:
|
||||
```
|
||||
├── .github
|
||||
│ └── workflows
|
||||
│ └── build.yml
|
||||
├── rules.mk
|
||||
├── config.h
|
||||
├── source.c
|
||||
└── username.json
|
||||
|-- .github
|
||||
| `-- workflows
|
||||
| `-- build.yml
|
||||
|-- rules.mk
|
||||
|-- config.h
|
||||
|-- source.c
|
||||
|-- username.json
|
||||
```
|
||||
|
||||
To commit and push them into GitHub, run the following commands (replacing `gh-username` with your GitHub user name):
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
# External QMK Userspace
|
||||
|
||||
QMK Firmware now officially supports storing user keymaps outside of the normal QMK Firmware repository, allowing users to maintain their own keymaps without having to fork, modify, and maintain a copy of QMK Firmware themselves.
|
||||
|
||||
External Userspace mirrors the structure of the main QMK Firmware repository, but only contains the keymaps that you wish to build. You can still use `keyboards/<my keyboard>/keymaps/<my keymap>` to store your keymaps, or you can use the `layouts/<my layout>/<my keymap>` system as before -- they're just stored external to QMK Firmware.
|
||||
|
||||
The build system will still honor the use of `users/<my keymap>` if you rely on the traditional QMK Firmware [userspace feature](feature_userspace.md) -- it's now supported externally too, using the same location inside the External Userspace directory.
|
||||
|
||||
Additionally, there is first-class support for using GitHub Actions to build your keymaps, allowing you to automatically compile your keymaps whenever you push changes to your External Userspace repository.
|
||||
|
||||
!> External Userspace is new functionality and may have issues. Tighter integration with the `qmk` command will occur over time.
|
||||
|
||||
?> Historical keymap.json and GitHub-based firmware build instructions can be found [here](newbs_building_firmware_workflow.md). This document supersedes those instructions, but they should still function correctly.
|
||||
|
||||
## Setting up QMK Locally
|
||||
|
||||
If you wish to build on your local machine, you will need to set up QMK locally. This is a one-time process, and is documented in the [newbs setup guide](https://docs.qmk.fm/#/newbs).
|
||||
|
||||
!> If you wish to use any QMK CLI commands related to manipulating External Userspace definitions, you will currently need a copy of QMK Firmware as well.
|
||||
|
||||
!> Building locally has a much shorter turnaround time than waiting for GitHub Actions to complete.
|
||||
|
||||
## External Userspace Repository Setup (forked on GitHub)
|
||||
|
||||
A basic skeleton External Userspace repository can be found [here](https://github.com/qmk/qmk_userspace). If you wish to keep your keymaps on GitHub (strongly recommended!), you can fork the repository and use it as a base:
|
||||
|
||||

|
||||
|
||||
Going ahead with your fork will copy it to your account, at which point you can clone it to your local machine and begin adding your keymaps:
|
||||
|
||||

|
||||
|
||||
```sh
|
||||
cd $HOME
|
||||
git clone https://github.com/{myusername}/qmk_userspace.git
|
||||
qmk config user.overlay_dir="$(realpath qmk_userspace)"
|
||||
```
|
||||
|
||||
## External Userspace Setup (locally stored only)
|
||||
|
||||
If you don't want to use GitHub and prefer to keep everything local, you can clone a copy of the default External Userspace locally instead:
|
||||
|
||||
```sh
|
||||
cd $HOME
|
||||
git clone https://github.com/qmk/qmk_userspace.git
|
||||
qmk config user.overlay_dir="$(realpath qmk_userspace)"
|
||||
```
|
||||
|
||||
## Adding a Keymap
|
||||
|
||||
_These instructions assume you have already set up QMK locally, and have a copy of the QMK Firmware repository on your machine._
|
||||
|
||||
Keymaps within External Userspace are defined in the same way as they are in the main QMK repository. You can either use the `qmk new-keymap` command to create a new keymap, or manually create a new directory in the `keyboards` directory.
|
||||
|
||||
Alternatively, you can use the `layouts` directory to store your keymaps, using the same layout system as the main QMK repository -- if you choose to do so you'll want to use the path `layouts/<layout name>/<keymap name>/keymap.*` to store your keymap files, where `layout name` matches an existing layout in QMK, such as `tkl_ansi`.
|
||||
|
||||
After creating your new keymap, building the keymap matches normal QMK usage:
|
||||
|
||||
```sh
|
||||
qmk compile -kb <keyboard> -km <keymap>
|
||||
```
|
||||
|
||||
!> The `qmk config user.overlay_dir=...` command must have been run when cloning the External Userspace repository for this to work correctly.
|
||||
|
||||
## Adding the keymap to External Userspace build targets
|
||||
|
||||
Once you have created your keymap, if you want to use GitHub Actions to build your firmware, you will need to add it to the External Userspace build targets. This is done using the `qmk userspace-add` command:
|
||||
|
||||
```sh
|
||||
# for a keyboard/keymap combo:
|
||||
qmk userspace-add -kb <keyboard> -km <keymap>
|
||||
# or, for a json-based keymap (if kept "loose"):
|
||||
qmk userspace-add <relative/path/to/my/keymap.json>
|
||||
```
|
||||
|
||||
This updates the `qmk.json` file in the root of your External Userspace directory. If you're using a git repository to store your keymaps, now is a great time to commit and push to your own fork.
|
||||
|
||||
## Compiling External Userspace build targets
|
||||
|
||||
Once you have added your keymaps to the External Userspace build targets, you can compile all of them at once using the `qmk userspace-compile` command:
|
||||
|
||||
```sh
|
||||
qmk userspace-compile
|
||||
```
|
||||
|
||||
All firmware builds you've added to the External Userspace build targets will be built, and the resulting firmware files will be placed in the root of your External Userspace directory.
|
||||
|
||||
## Using GitHub Actions
|
||||
|
||||
GitHub Actions can be used to automatically build your keymaps whenever you push changes to your External Userspace repository. If you have set up your list of build targets, this is as simple as enabling workflows in the GitHub repository settings:
|
||||
|
||||

|
||||
|
||||
Any push will result in compilation of all configured builds, and once completed a new release containing the newly-minted firmware files will be created on GitHub, which you can subsequently download and flash to your keyboard:
|
||||
|
||||

|
||||
@@ -39,7 +39,7 @@ If there are any inconsistencies with these recommendations, you're best off [cr
|
||||
|
||||
## Keymap PRs
|
||||
|
||||
!> Note that personal keymap submissions will no longer be accepted. This section applies to manufacturer-supported keymaps.
|
||||
Note that personal keymap submissions will no longer be accepted. This section applies to manufacturer-supported keymaps.
|
||||
|
||||
- `#include QMK_KEYBOARD_H` preferred to including specific board files
|
||||
- prefer layer `enum`s to `#define`s
|
||||
@@ -103,7 +103,7 @@ https://github.com/qmk/qmk_firmware/pulls?q=is%3Apr+is%3Aclosed+label%3Akeyboard
|
||||
- keyboard `config.h`
|
||||
- no `#define DESCRIPTION`
|
||||
- no Magic Key Options, MIDI Options or HD44780 configuration
|
||||
- user preference configurable `#define`s should not be placed at the keyboard level
|
||||
- user preference configurable `#define`s need to be moved to keymap `config.h`
|
||||
- default values should not be redefined, such as `DEBOUNCE`, RGB related settings, etc.
|
||||
- feature specific documentation contains most default values
|
||||
- `grep` or alternative tool can be used to search for default values in core directories (e.g. `grep -r "define DEBOUNCE" quantum`)
|
||||
@@ -117,7 +117,8 @@ https://github.com/qmk/qmk_firmware/pulls?q=is%3Apr+is%3Aclosed+label%3Akeyboard
|
||||
- mirroring existing functionality of a commercial board (like custom keycodes and special animations etc.) should be handled through non-`default` keymaps
|
||||
- Vial-related files or changes will not be accepted, as they are not used by QMK firmware (no Vial-specific core code has been submitted or merged)
|
||||
- `<keyboard>.c`
|
||||
- empty `xxxx_xxxx_kb()`, `xxxx_xxxx_user()`, or other weak-defined default implemented functions removed
|
||||
- empty `xxxx_xxxx_kb()` or other weak-defined default implemented functions removed
|
||||
- empty `xxxx_xxxx_user()` or other user-level functions are disallowed at the keyboard level and must be moved to keymaps
|
||||
- commented-out functions removed too
|
||||
- `matrix_init_board()` etc. migrated to `keyboard_pre_init_kb()`, see: [keyboard_pre_init*](custom_quantum_functions.md?id=keyboard_pre_init_-function-documentation)
|
||||
- prefer `CUSTOM_MATRIX = lite` if custom matrix used, allows for standard debounce, see [custom matrix 'lite'](custom_matrix.md?id=lite)
|
||||
|
||||
@@ -19,20 +19,18 @@ The QMK CLI can be used to convert from normal images such as PNG files or anima
|
||||
|
||||
Supported devices:
|
||||
|
||||
| Display Panel | Panel Type | Size | Comms Transport | Driver |
|
||||
|----------------|--------------------|------------------|-----------------|------------------------------------------|
|
||||
| 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` |
|
||||
| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_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` |
|
||||
| ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` |
|
||||
| ST7789 | RGB LCD | 240x320, 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7789_spi` |
|
||||
| SH1106 (SPI) | Monochrome OLED | 128x64 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += sh1106_spi` |
|
||||
| SH1106 (I2C) | Monochrome OLED | 128x64 | I2C | `QUANTUM_PAINTER_DRIVERS += sh1106_i2c` |
|
||||
| SSD1306 (SPI) | Monochrome OLED | 128x64 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += sh1106_spi` |
|
||||
| SSD1306 (I2C) | Monochrome OLED | 128x32 | I2C | `QUANTUM_PAINTER_DRIVERS += sh1106_i2c` |
|
||||
| Surface | Virtual | User-defined | None | `QUANTUM_PAINTER_DRIVERS += surface` |
|
||||
| Display Panel | Panel Type | Size | Comms Transport | Driver |
|
||||
|---------------|--------------------|------------------|-----------------|------------------------------------------|
|
||||
| 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` |
|
||||
| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_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` |
|
||||
| ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` |
|
||||
| ST7789 | RGB LCD | 240x320, 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7789_spi` |
|
||||
| SH1106 (SPI) | Monochrome OLED | 128x64 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += sh1106_spi` |
|
||||
| SH1106 (I2C) | Monochrome OLED | 128x64 | I2C | `QUANTUM_PAINTER_DRIVERS += sh1106_i2c` |
|
||||
| Surface | Virtual | User-defined | None | `QUANTUM_PAINTER_DRIVERS += surface` |
|
||||
|
||||
## Quantum Painter Configuration :id=quantum-painter-config
|
||||
|
||||
@@ -435,10 +433,6 @@ The maximum number of displays of each type can be configured by changing the fo
|
||||
|
||||
Native color format mono2 is compatible with SH1106
|
||||
|
||||
#### ** SSD1306 **
|
||||
|
||||
SSD1306 and SH1106 are almost entirely identical, to the point of being indisinguishable by Quantum Painter. Enable SH1106 support in Quantum Painter and create SH1106 devices in firmware to perform drawing operations on SSD1306 displays.
|
||||
|
||||
<!-- tabs:end -->
|
||||
|
||||
### ** Surface **
|
||||
@@ -494,10 +488,10 @@ The maximum number of surfaces can be configured by changing the following in yo
|
||||
To transfer the contents of the surface to another display of the same pixel format, the following API can be invoked:
|
||||
|
||||
```c
|
||||
bool qp_surface_draw(painter_device_t surface, painter_device_t display, uint16_t x, uint16_t y, bool entire_surface);
|
||||
bool qp_surface_draw(painter_device_t surface, painter_device_t display, uint16_t x, uint16_t y);
|
||||
```
|
||||
|
||||
The `surface` is the surface to copy out from. The `display` is the target display to draw into. `x` and `y` are the target location to draw the surface pixel data. Under normal circumstances, the location should be consistent, as the dirty region is calculated with respect to the `x` and `y` coordinates -- changing those will result in partial, overlapping draws. `entire_surface` whether the entire surface should be drawn, instead of just the dirty region.
|
||||
The `surface` is the surface to copy out from. The `display` is the target display to draw into. `x` and `y` are the target location to draw the surface pixel data. Under normal circumstances, the location should be consistent, as the dirty region is calculated with respect to the `x` and `y` coordinates -- changing those will result in partial, overlapping draws.
|
||||
|
||||
!> The surface and display panel must have the same native pixel format.
|
||||
|
||||
|
||||
@@ -60,13 +60,6 @@ You can create `info.json` files at every level under `qmk_firmware/keyboards/<k
|
||||
}
|
||||
```
|
||||
* `qmk`
|
||||
* `locking`
|
||||
* `enabled`
|
||||
* Enable locking switch support.
|
||||
* Default: `false`
|
||||
* `resync`
|
||||
* Keep switch state consistent with keyboard LED state.
|
||||
* Default: `false`
|
||||
* `tap_capslock_delay`
|
||||
* The delay between keydown and keyup for Caps Lock tap events in milliseconds.
|
||||
* Default: `80` (80 ms)
|
||||
@@ -134,16 +127,6 @@ Configures the [Backlight](feature_backlight.md) feature.
|
||||
* `breathing_period`
|
||||
* The length of one backlight breathing cycle in seconds.
|
||||
* Default: `6` (6 seconds)
|
||||
* `default`
|
||||
* `on`
|
||||
* The default backlight enabled state.
|
||||
* Default: `true`
|
||||
* `breathing`
|
||||
* The default backlight breathing state.
|
||||
* Default: `false`
|
||||
* `brightness`
|
||||
* The default brightness level.
|
||||
* Default: `max_brightness`
|
||||
* `driver`
|
||||
* The driver to use. Must be one of `custom`, `pwm`, `software`, `timer`.
|
||||
* Default: `"pwm"`
|
||||
@@ -211,20 +194,6 @@ Configures the [Combo](feature_combo.md) feature.
|
||||
* The amount of time to recognize a combo in milliseconds.
|
||||
* Default: `50` (50 ms)
|
||||
|
||||
## DIP Switches :id=dip-switch
|
||||
|
||||
Configures the [DIP Switches](feature_dip_switch.md) feature.
|
||||
|
||||
* `dip_switch`
|
||||
* `enabled`
|
||||
* Enable the DIP Switches feature.
|
||||
* Default: `false`
|
||||
* `pins`
|
||||
* A list of GPIO pins connected to the MCU.
|
||||
* `matrix_grid`
|
||||
* A list of matrix locations in the key matrix.
|
||||
* Example: `[ [0,6], [1,6], [2,6] ]`
|
||||
|
||||
## EEPROM :id=eeprom
|
||||
|
||||
Configures the [EEPROM](eeprom_driver.md) driver.
|
||||
@@ -324,8 +293,6 @@ The ISO enter key is represented by a 1.25u×2uh key. Renderers which utilize in
|
||||
* `w`
|
||||
* The width of the key, in key units.
|
||||
* Default: `1` (1u)
|
||||
* `encoder`
|
||||
* The index of an encoder this key should be linked to
|
||||
* Example: `{"label": "Shift", "matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25}`
|
||||
|
||||
## Leader Key :id=leader-key
|
||||
@@ -353,7 +320,7 @@ Configures the [LED Matrix](feature_led_matrix.md) feature.
|
||||
* Example:
|
||||
```json
|
||||
{
|
||||
"alphas_mods": true,
|
||||
"alpha_mods": true,
|
||||
"breathing": true,
|
||||
"cycle_left_right": false
|
||||
}
|
||||
@@ -361,19 +328,6 @@ Configures the [LED Matrix](feature_led_matrix.md) feature.
|
||||
* `center_point`
|
||||
* The centroid (geometric center) of the LEDs. Used for certain effects.
|
||||
* Default: `[112, 32]`
|
||||
* `default`
|
||||
* `animation`
|
||||
* The default effect. Must be one of `led_matrix.animations`
|
||||
* Default: `"solid"`
|
||||
* `on`
|
||||
* The default enabled state.
|
||||
* Default: `true`
|
||||
* `val`
|
||||
* The default brightness level.
|
||||
* Default: `max_brightness`
|
||||
* `speed`
|
||||
* The default animation speed.
|
||||
* Default: `128`
|
||||
* `driver` (Required)
|
||||
* The driver to use. Must be one of `custom`, `is31fl3218`, `is31fl3731`, `is31fl3733`, `is31fl3736`, `is31fl3737`, `is31fl3741`, `is31fl3742a`, `is31fl3743a`, `is31fl3745`, `is31fl3746a`, `snled27351`.
|
||||
* `layout` (Required)
|
||||
@@ -480,17 +434,6 @@ Configures [One Shot keys](one_shot_keys.md).
|
||||
* `timeout`
|
||||
* The amount of time before the key is released in milliseconds.
|
||||
|
||||
## Potentiometer :id=potentiometer
|
||||
|
||||
Configures the [Potentiometer](feature_Potentiometers.md) feature.
|
||||
|
||||
* `potentiometer`
|
||||
* `enabled`
|
||||
* Enable the Potentiometer feature.
|
||||
* Default: `false`
|
||||
* `pins` (Required)
|
||||
* The GPIO pin(s) connected to the Potentiometer(s).
|
||||
|
||||
## PS/2 :id=ps2
|
||||
|
||||
Configures the [PS/2](feature_ps2_mouse.md) feature.
|
||||
@@ -542,25 +485,6 @@ Configures the [RGB Lighting](feature_rgblight.md) feature.
|
||||
* `brightness_steps`
|
||||
* The number of brightness adjustment steps.
|
||||
* Default: `17`
|
||||
* `default`
|
||||
* `animation`
|
||||
* The default effect. Must be one of `rgblight.animations`
|
||||
* Default: `"static_light"`
|
||||
* `on`
|
||||
* The default enabled state.
|
||||
* Default: `true`
|
||||
* `hue`
|
||||
* The default hue value.
|
||||
* Default: `0`
|
||||
* `sat`
|
||||
* The default saturation value.
|
||||
* Default: `255`
|
||||
* `val`
|
||||
* The default brightness level.
|
||||
* Default: `max_brightness`
|
||||
* `speed`
|
||||
* The default animation speed.
|
||||
* Default: `0`
|
||||
* `driver`
|
||||
* The driver to use. Must be one of `apa102`, `custom`, `ws2812`.
|
||||
* Default: `"ws2812"`
|
||||
@@ -609,7 +533,7 @@ Configures the [RGB Matrix](feature_rgb_matrix.md) feature.
|
||||
* Example:
|
||||
```json
|
||||
{
|
||||
"alphas_mods": true,
|
||||
"alpha_mods": true,
|
||||
"breathing": true,
|
||||
"cycle_left_right": false
|
||||
}
|
||||
@@ -617,25 +541,6 @@ Configures the [RGB Matrix](feature_rgb_matrix.md) feature.
|
||||
* `center_point`
|
||||
* The centroid (geometric center) of the LEDs. Used for certain effects.
|
||||
* Default: `[112, 32]`
|
||||
* `default`
|
||||
* `animation`
|
||||
* The default effect. Must be one of `rgb_matrix.animations`
|
||||
* Default: `"solid_color"`
|
||||
* `on`
|
||||
* The default enabled state.
|
||||
* Default: `true`
|
||||
* `hue`
|
||||
* The default hue value.
|
||||
* Default: `0`
|
||||
* `sat`
|
||||
* The default saturation value.
|
||||
* Default: `255`
|
||||
* `val`
|
||||
* The default brightness level.
|
||||
* Default: `max_brightness`
|
||||
* `speed`
|
||||
* The default animation speed.
|
||||
* Default: `128`
|
||||
* `driver` (Required)
|
||||
* The driver to use. Must be one of `aw20216s`, `custom`, `is31fl3218`, `is31fl3731`, `is31fl3733`, `is31fl3736`, `is31fl3737`, `is31fl3741`, `is31fl3742a`, `is31fl3743a`, `is31fl3745`, `is31fl3746a`, `snled27351`, `ws2812`.
|
||||
* `hue_steps`
|
||||
@@ -710,10 +615,6 @@ Configures the [Split Keyboard](feature_split_keyboard.md) feature.
|
||||
* `bootmagic`
|
||||
* `matrix`
|
||||
* See [Bootmagic](#bootmagic) config.
|
||||
* `dip_switch`
|
||||
* `right`
|
||||
* `pins`
|
||||
* See [DIP Switches](#dip-switch) config.
|
||||
* `enabled`
|
||||
* Enable the Split Keyboard feature.
|
||||
* Default: `false`
|
||||
@@ -721,12 +622,6 @@ Configures the [Split Keyboard](feature_split_keyboard.md) feature.
|
||||
* `right`
|
||||
* `rotary`
|
||||
* See [Encoder](#encoder) config.
|
||||
* `handedness`
|
||||
* `pin`
|
||||
* The GPIO pin connected to determine handedness.
|
||||
* `matrix_grid`
|
||||
* The GPIO pins of the matrix position which determines the handedness.
|
||||
* Example: `["A1", "B5"]`
|
||||
* `matrix_pins`
|
||||
* `right`
|
||||
* See [Matrix](#matrix) config.
|
||||
|
||||
@@ -67,7 +67,6 @@ These headers are located in [`quantum/keymap_extras/`](https://github.com/qmk/q
|
||||
|Slovenian |`keymap_slovenian.h` |`sendstring_slovenian.h` |
|
||||
|Spanish |`keymap_spanish.h` |`sendstring_spanish.h` |
|
||||
|Spanish (Dvorak) |`keymap_spanish_dvorak.h` |`sendstring_spanish_dvorak.h` |
|
||||
|Spanish (Latin America) |`keymap_spanish_latin_america.h` |`sendstring_spanish_latin_america.h`|
|
||||
|Swedish |`keymap_swedish.h` |`sendstring_swedish.h` |
|
||||
|Swedish (macOS, ANSI) |`keymap_swedish_mac_ansi.h` | |
|
||||
|Swedish (macOS, ISO) |`keymap_swedish_mac_iso.h` | |
|
||||
@@ -88,5 +87,6 @@ There are also a few which are not quite language-specific, but useful if you ar
|
||||
|Norman |`keymap_norman.h` |`sendstring_norman.h` |
|
||||
|Plover |`keymap_plover.h` | |
|
||||
|Plover (Dvorak) |`keymap_plover_dvorak.h` | |
|
||||
|Steno |`keymap_steno.h` | |
|
||||
|Workman |`keymap_workman.h` |`sendstring_workman.h` |
|
||||
|Workman (ZXCVM) |`keymap_workman_zxcvm.h` |`sendstring_workman_zxcvm.h` |
|
||||
|
||||
@@ -235,7 +235,7 @@ Where 'n' matches the peripheral number of your selected USART on the MCU.
|
||||
|
||||
The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU. Because of the flexible nature of the PIO peripherals, **any** GPIO pin can be used as a `TX` or `RX` pin. Half-duplex and Full-duplex operation is fully supported. The Half-duplex operation mode uses the built-in pull-ups and GPIO manipulation on the RP2040 to drive the line high by default. An external pull-up is therefore not necessary.
|
||||
|
||||
You may optionally switch the PIO peripheral used with the following define in config.h:
|
||||
Configure the hardware via your config.h:
|
||||
```c
|
||||
#define SERIAL_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the Serial implementation uses the PIO0 peripheral
|
||||
```
|
||||
|
||||
@@ -210,7 +210,6 @@ That said, there are a number of Pro Micro replacements with ARM controllers:
|
||||
* [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040)
|
||||
* [0xCB Helios](https://keeb.supply/products/0xcb-helios) ([Open Source](https://github.com/0xCB-dev/0xCB-Helios), DIY/PCBA/Shop)
|
||||
* [Liatris](https://splitkb.com/products/liatris)
|
||||
* [Imera](https://splitkb.com/products/imera)
|
||||
* [Michi](https://github.com/ci-bus/michi-promicro-rp2040)
|
||||
|
||||
There are other, non-Pro Micro compatible boards out there. The most popular being:
|
||||
|
||||
@@ -493,7 +493,7 @@ Examples:
|
||||
|
||||
One thing that you may notice is that we include the key record for all of the "per key" functions, and may be wondering why we do that.
|
||||
|
||||
Well, it's simple really: customization. But specifically, it depends on how your keyboard is wired up. For instance, if each row is actually using a row in the keyboard's matrix, then it may be simpler to use `if (record->event.key.row == 3)` instead of checking a whole bunch of keycodes. Which is especially good for those people using the Tap Hold type keys on the home row. So you could fine-tune those to not interfere with your normal typing.
|
||||
Well, it's simple really: customization. But specifically, it depends on how your keyboard is wired up. For instance, if each row is actually using a row in the keyboard's matrix, then it may be simpler to use `if (record->event.row == 3)` instead of checking a whole bunch of keycodes. Which is especially good for those people using the Tap Hold type keys on the home row. So you could fine-tune those to not interfere with your normal typing.
|
||||
|
||||
## Why are there no `*_kb` or `*_user` functions?!
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@ void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds) {
|
||||
apa102_end_frame(num_leds);
|
||||
}
|
||||
|
||||
// Overwrite the default rgblight_call_driver to use apa102 driver
|
||||
void rgblight_call_driver(rgb_led_t *start_led, uint8_t num_leds) {
|
||||
apa102_setleds(start_led, num_leds);
|
||||
}
|
||||
|
||||
void static apa102_init(void) {
|
||||
setPinOutput(APA102_DI_PIN);
|
||||
setPinOutput(APA102_CI_PIN);
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#if defined(RGBLED_NUM)
|
||||
# define APA102_LED_COUNT RGBLED_NUM
|
||||
#elif defined(RGB_MATRIX_LED_COUNT)
|
||||
# define APA102_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#ifndef APA102_DEFAULT_BRIGHTNESS
|
||||
# define APA102_DEFAULT_BRIGHTNESS 31
|
||||
#endif
|
||||
|
||||
@@ -19,16 +19,39 @@
|
||||
#include "wait.h"
|
||||
#include "spi_master.h"
|
||||
|
||||
/* The AW20216S appears to be somewhat similar to the IS31FL743, although quite
|
||||
* a few things are different, such as the command byte format and page ordering.
|
||||
* The LED addresses start from 0x00 instead of 0x01.
|
||||
*/
|
||||
#define AW20216S_ID 0b1010 << 4
|
||||
|
||||
#define AW20216S_PAGE_FUNCTION 0x00 << 1 // PG0, Function registers
|
||||
#define AW20216S_PAGE_PWM 0x01 << 1 // PG1, LED PWM control
|
||||
#define AW20216S_PAGE_SCALING 0x02 << 1 // PG2, LED current scaling control
|
||||
#define AW20216S_PAGE_PATCHOICE 0x03 << 1 // PG3, Pattern choice?
|
||||
#define AW20216S_PAGE_PWMSCALING 0x04 << 1 // PG4, LED PWM + Scaling control?
|
||||
|
||||
#define AW20216S_WRITE 0
|
||||
#define AW20216S_READ 1
|
||||
|
||||
#define AW20216S_REG_CONFIGURATION 0x00 // PG0
|
||||
#define AW20216S_REG_GLOBALCURRENT 0x01 // PG0
|
||||
#define AW20216S_REG_RESET 0x2F // PG0
|
||||
#define AW20216S_REG_MIXFUNCTION 0x46 // PG0
|
||||
|
||||
// Default value of AW20216S_REG_CONFIGURATION
|
||||
// D7:D4 = 1011, SWSEL (SW1~SW12 active)
|
||||
// D3 = 0?, reserved (apparently this should be 1 but it doesn't seem to matter)
|
||||
// D2:D1 = 00, OSDE (open/short detection enable)
|
||||
// D0 = 0, CHIPEN (write 1 to enable LEDs when hardware enable pulled high)
|
||||
#define AW20216S_CONFIG_DEFAULT 0b10110000
|
||||
#define AW20216S_MIXCR_DEFAULT 0b00000000
|
||||
#define AW20216S_RESET_CMD 0xAE
|
||||
#define AW20216S_CHIPEN 1
|
||||
#define AW20216S_LPEN (0x01 << 1)
|
||||
|
||||
#define AW20216S_PWM_REGISTER_COUNT 216
|
||||
|
||||
#ifndef AW20216S_CONFIGURATION
|
||||
# define AW20216S_CONFIGURATION (AW20216S_CONFIGURATION_SWSEL_1_12 | AW20216S_CONFIGURATION_CHIPEN)
|
||||
#endif
|
||||
|
||||
#ifndef AW20216S_MIX_FUNCTION
|
||||
# define AW20216S_MIX_FUNCTION (AW20216S_MIX_FUNCTION_LPEN)
|
||||
#endif
|
||||
|
||||
#ifndef AW20216S_SCALING_MAX
|
||||
# define AW20216S_SCALING_MAX 150
|
||||
#endif
|
||||
@@ -79,7 +102,7 @@ static inline bool aw20216s_write_register(pin_t cs_pin, uint8_t page, uint8_t r
|
||||
}
|
||||
|
||||
void aw20216s_soft_reset(pin_t cs_pin) {
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_FUNCTION_REG_RESET, AW20216S_RESET_MAGIC);
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_REG_RESET, AW20216S_RESET_CMD);
|
||||
}
|
||||
|
||||
static void aw20216s_init_scaling(pin_t cs_pin) {
|
||||
@@ -91,25 +114,16 @@ static void aw20216s_init_scaling(pin_t cs_pin) {
|
||||
|
||||
static inline void aw20216s_init_current_limit(pin_t cs_pin) {
|
||||
// Push config
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_FUNCTION_REG_GLOBAL_CURRENT, AW20216S_GLOBAL_CURRENT_MAX);
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_REG_GLOBALCURRENT, AW20216S_GLOBAL_CURRENT_MAX);
|
||||
}
|
||||
|
||||
static inline void aw20216s_soft_enable(pin_t cs_pin) {
|
||||
// Push config
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_FUNCTION_REG_CONFIGURATION, AW20216S_CONFIGURATION);
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_REG_CONFIGURATION, AW20216S_CONFIG_DEFAULT | AW20216S_CHIPEN);
|
||||
}
|
||||
|
||||
static inline void aw20216s_auto_lowpower(pin_t cs_pin) {
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_FUNCTION_REG_MIX_FUNCTION, AW20216S_MIX_FUNCTION);
|
||||
}
|
||||
|
||||
void aw20216s_init_drivers(void) {
|
||||
spi_init();
|
||||
|
||||
aw20216s_init(AW20216S_CS_PIN_1, AW20216S_EN_PIN_1);
|
||||
#if defined(AW20216S_CS_PIN_2)
|
||||
aw20216s_init(AW20216S_CS_PIN_2, AW20216S_EN_PIN_2);
|
||||
#endif
|
||||
aw20216s_write_register(cs_pin, AW20216S_PAGE_FUNCTION, AW20216S_REG_MIXFUNCTION, AW20216S_MIXCR_DEFAULT | AW20216S_LPEN);
|
||||
}
|
||||
|
||||
void aw20216s_init(pin_t cs_pin, pin_t en_pin) {
|
||||
@@ -141,7 +155,7 @@ void aw20216s_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void aw20216s_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (uint8_t i = 0; i < AW20216S_LED_COUNT; i++) {
|
||||
for (uint8_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
aw20216s_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "gpio.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_COUNT
|
||||
# define AW20216S_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef AW_SCALING_MAX
|
||||
# define AW20216S_SCALING_MAX AW_SCALING_MAX
|
||||
#endif
|
||||
@@ -52,48 +54,15 @@
|
||||
#define g_aw_leds g_aw20216s_leds
|
||||
// ========
|
||||
|
||||
#define AW20216S_ID (0b1010 << 4)
|
||||
#define AW20216S_WRITE 0
|
||||
#define AW20216S_READ 1
|
||||
|
||||
#define AW20216S_PAGE_FUNCTION (0x00 << 1)
|
||||
#define AW20216S_PAGE_PWM (0x01 << 1)
|
||||
#define AW20216S_PAGE_SCALING (0x02 << 1)
|
||||
#define AW20216S_PAGE_PATTERN_CHOICE (0x03 << 1)
|
||||
#define AW20216S_PAGE_PWM_SCALING (0x04 << 1)
|
||||
|
||||
#define AW20216S_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define AW20216S_CONFIGURATION_SWSEL_1_12 (0b1011 << 4)
|
||||
#define AW20216S_CONFIGURATION_CHIPEN (0b1 << 0)
|
||||
|
||||
#define AW20216S_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
|
||||
#define AW20216S_FUNCTION_REG_RESET 0x2F
|
||||
#define AW20216S_RESET_MAGIC 0xAE
|
||||
|
||||
#define AW20216S_FUNCTION_REG_MIX_FUNCTION 0x46
|
||||
#define AW20216S_MIX_FUNCTION_LPEN (0b1 << 1)
|
||||
|
||||
#if defined(RGB_MATRIX_AW20216S)
|
||||
# define AW20216S_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(AW20216S_CS_PIN_2)
|
||||
# define AW20216S_DRIVER_COUNT 2
|
||||
#elif defined(AW20216S_CS_PIN_1)
|
||||
# define AW20216S_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct aw20216s_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED aw20216s_led_t;
|
||||
} aw20216s_led_t;
|
||||
|
||||
extern const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT];
|
||||
extern const aw20216s_led_t PROGMEM g_aw20216s_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void aw20216s_init_drivers(void);
|
||||
void aw20216s_init(pin_t cs_pin, pin_t en_pin);
|
||||
void aw20216s_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
void aw20216s_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
@@ -17,8 +17,12 @@
|
||||
#include <string.h>
|
||||
#include "i2c_master.h"
|
||||
|
||||
#define IS31FL3218_PWM_REGISTER_COUNT 18
|
||||
#define IS31FL3218_LED_CONTROL_REGISTER_COUNT 3
|
||||
// These are the register addresses
|
||||
#define IS31FL3218_REG_SHUTDOWN 0x00
|
||||
#define IS31FL3218_REG_PWM 0x01
|
||||
#define IS31FL3218_REG_CONTROL 0x13
|
||||
#define IS31FL3218_REG_UPDATE 0x16
|
||||
#define IS31FL3218_REG_RESET 0x17
|
||||
|
||||
#ifndef IS31FL3218_I2C_TIMEOUT
|
||||
# define IS31FL3218_I2C_TIMEOUT 100
|
||||
@@ -28,43 +32,42 @@
|
||||
# define IS31FL3218_I2C_PERSISTENCE 0
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Reusable buffer for transfers
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining.
|
||||
uint8_t g_pwm_buffer[IS31FL3218_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[18];
|
||||
bool g_pwm_buffer_update_required = false;
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3218_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required = false;
|
||||
uint8_t g_led_control_registers[3] = {0};
|
||||
bool g_led_control_registers_update_required = false;
|
||||
|
||||
void is31fl3218_write_register(uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
#if IS31FL3218_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT);
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3218_write_pwm_buffer(uint8_t *pwm_buffer) {
|
||||
i2c_transfer_buffer[0] = IS31FL3218_REG_PWM;
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer, 18);
|
||||
g_twi_transfer_buffer[0] = IS31FL3218_REG_PWM;
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer, 18);
|
||||
|
||||
#if IS31FL3218_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) {
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
}
|
||||
#else
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3218_init(void) {
|
||||
i2c_init();
|
||||
|
||||
// In case we ever want to reinitialize (?)
|
||||
is31fl3218_write_register(IS31FL3218_REG_RESET, 0x00);
|
||||
|
||||
@@ -72,28 +75,22 @@ void is31fl3218_init(void) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_SHUTDOWN, 0x01);
|
||||
|
||||
// Set all PWM values to zero
|
||||
for (uint8_t i = 0; i < IS31FL3218_PWM_REGISTER_COUNT; i++) {
|
||||
for (uint8_t i = 0; i < 18; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_PWM + i, 0x00);
|
||||
}
|
||||
|
||||
// turn off all LEDs in the LED control register
|
||||
for (uint8_t i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, 0x00);
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, 0x00);
|
||||
}
|
||||
|
||||
// Load PWM registers and LED Control register data
|
||||
is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01);
|
||||
|
||||
for (int i = 0; i < IS31FL3218_LED_COUNT; i++) {
|
||||
is31fl3218_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
is31fl3218_update_led_control_registers();
|
||||
}
|
||||
|
||||
void is31fl3218_set_value(int index, uint8_t value) {
|
||||
is31fl3218_led_t led;
|
||||
if (index >= 0 && index < IS31FL3218_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led));
|
||||
}
|
||||
if (g_pwm_buffer[led.v - IS31FL3218_REG_PWM] == value) {
|
||||
@@ -104,7 +101,7 @@ void is31fl3218_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void is31fl3218_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < IS31FL3218_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3218_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -137,8 +134,8 @@ void is31fl3218_update_pwm_buffers(void) {
|
||||
|
||||
void is31fl3218_update_led_control_registers(void) {
|
||||
if (g_led_control_registers_update_required) {
|
||||
for (int i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, g_led_control_registers[i]);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, g_led_control_registers[i]);
|
||||
}
|
||||
|
||||
g_led_control_registers_update_required = false;
|
||||
|
||||
@@ -19,32 +19,17 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
#define IS31FL3218_REG_SHUTDOWN 0x00
|
||||
#define IS31FL3218_REG_PWM 0x01
|
||||
#define IS31FL3218_REG_LED_CONTROL_1 0x13
|
||||
#define IS31FL3218_REG_LED_CONTROL_2 0x14
|
||||
#define IS31FL3218_REG_LED_CONTROL_3 0x15
|
||||
#define IS31FL3218_REG_UPDATE 0x16
|
||||
#define IS31FL3218_REG_RESET 0x17
|
||||
|
||||
#define IS31FL3218_I2C_ADDRESS 0x54
|
||||
|
||||
#if defined(LED_MATRIX_IS31FL3218)
|
||||
# define IS31FL3218_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3218_led_t {
|
||||
uint8_t v;
|
||||
} PACKED is31fl3218_led_t;
|
||||
} __attribute__((packed)) is31fl3218_led_t;
|
||||
|
||||
extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT];
|
||||
extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[LED_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3218_init(void);
|
||||
|
||||
void is31fl3218_write_register(uint8_t reg, uint8_t data);
|
||||
|
||||
void is31fl3218_set_value(int index, uint8_t value);
|
||||
|
||||
void is31fl3218_set_value_all(uint8_t value);
|
||||
|
||||
@@ -17,8 +17,12 @@
|
||||
#include <string.h>
|
||||
#include "i2c_master.h"
|
||||
|
||||
#define IS31FL3218_PWM_REGISTER_COUNT 18
|
||||
#define IS31FL3218_LED_CONTROL_REGISTER_COUNT 3
|
||||
// These are the register addresses
|
||||
#define IS31FL3218_REG_SHUTDOWN 0x00
|
||||
#define IS31FL3218_REG_PWM 0x01
|
||||
#define IS31FL3218_REG_CONTROL 0x13
|
||||
#define IS31FL3218_REG_UPDATE 0x16
|
||||
#define IS31FL3218_REG_RESET 0x17
|
||||
|
||||
#ifndef IS31FL3218_I2C_TIMEOUT
|
||||
# define IS31FL3218_I2C_TIMEOUT 100
|
||||
@@ -28,43 +32,42 @@
|
||||
# define IS31FL3218_I2C_PERSISTENCE 0
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Reusable buffer for transfers
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining.
|
||||
uint8_t g_pwm_buffer[IS31FL3218_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[18];
|
||||
bool g_pwm_buffer_update_required = false;
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3218_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required = false;
|
||||
uint8_t g_led_control_registers[3] = {0};
|
||||
bool g_led_control_registers_update_required = false;
|
||||
|
||||
void is31fl3218_write_register(uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
#if IS31FL3218_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT);
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3218_write_pwm_buffer(uint8_t *pwm_buffer) {
|
||||
i2c_transfer_buffer[0] = IS31FL3218_REG_PWM;
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer, 18);
|
||||
g_twi_transfer_buffer[0] = IS31FL3218_REG_PWM;
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer, 18);
|
||||
|
||||
#if IS31FL3218_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) {
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
}
|
||||
#else
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3218_init(void) {
|
||||
i2c_init();
|
||||
|
||||
// In case we ever want to reinitialize (?)
|
||||
is31fl3218_write_register(IS31FL3218_REG_RESET, 0x00);
|
||||
|
||||
@@ -72,28 +75,22 @@ void is31fl3218_init(void) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_SHUTDOWN, 0x01);
|
||||
|
||||
// Set all PWM values to zero
|
||||
for (uint8_t i = 0; i < IS31FL3218_PWM_REGISTER_COUNT; i++) {
|
||||
for (uint8_t i = 0; i < 18; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_PWM + i, 0x00);
|
||||
}
|
||||
|
||||
// turn off all LEDs in the LED control register
|
||||
for (uint8_t i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, 0x00);
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, 0x00);
|
||||
}
|
||||
|
||||
// Load PWM registers and LED Control register data
|
||||
is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01);
|
||||
|
||||
for (int i = 0; i < IS31FL3218_LED_COUNT; i++) {
|
||||
is31fl3218_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
is31fl3218_update_led_control_registers();
|
||||
}
|
||||
|
||||
void is31fl3218_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
is31fl3218_led_t led;
|
||||
if (index >= 0 && index < IS31FL3218_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led));
|
||||
}
|
||||
if (g_pwm_buffer[led.r - IS31FL3218_REG_PWM] == red && g_pwm_buffer[led.g - IS31FL3218_REG_PWM] == green && g_pwm_buffer[led.b - IS31FL3218_REG_PWM] == blue) {
|
||||
@@ -106,7 +103,7 @@ void is31fl3218_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void is31fl3218_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < IS31FL3218_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3218_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -153,8 +150,8 @@ void is31fl3218_update_pwm_buffers(void) {
|
||||
|
||||
void is31fl3218_update_led_control_registers(void) {
|
||||
if (g_led_control_registers_update_required) {
|
||||
for (int i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, g_led_control_registers[i]);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, g_led_control_registers[i]);
|
||||
}
|
||||
|
||||
g_led_control_registers_update_required = false;
|
||||
|
||||
@@ -19,34 +19,19 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
#define IS31FL3218_REG_SHUTDOWN 0x00
|
||||
#define IS31FL3218_REG_PWM 0x01
|
||||
#define IS31FL3218_REG_LED_CONTROL_1 0x13
|
||||
#define IS31FL3218_REG_LED_CONTROL_2 0x14
|
||||
#define IS31FL3218_REG_LED_CONTROL_3 0x15
|
||||
#define IS31FL3218_REG_UPDATE 0x16
|
||||
#define IS31FL3218_REG_RESET 0x17
|
||||
|
||||
#define IS31FL3218_I2C_ADDRESS 0x54
|
||||
|
||||
#if defined(RGB_MATRIX_IS31FL3218)
|
||||
# define IS31FL3218_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3218_led_t {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED is31fl3218_led_t;
|
||||
} __attribute__((packed)) is31fl3218_led_t;
|
||||
|
||||
extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT];
|
||||
extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3218_init(void);
|
||||
|
||||
void is31fl3218_write_register(uint8_t reg, uint8_t data);
|
||||
|
||||
void is31fl3218_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
void is31fl3218_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
@@ -22,8 +22,25 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3731_PWM_REGISTER_COUNT 144
|
||||
#define IS31FL3731_LED_CONTROL_REGISTER_COUNT 18
|
||||
#define IS31FL3731_REG_CONFIG 0x00
|
||||
#define IS31FL3731_REG_CONFIG_PICTUREMODE 0x00
|
||||
#define IS31FL3731_REG_CONFIG_AUTOPLAYMODE 0x08
|
||||
#define IS31FL3731_REG_CONFIG_AUDIOPLAYMODE 0x18
|
||||
|
||||
#define IS31FL3731_CONF_PICTUREMODE 0x00
|
||||
#define IS31FL3731_CONF_AUTOFRAMEMODE 0x04
|
||||
#define IS31FL3731_CONF_AUDIOMODE 0x08
|
||||
|
||||
#define IS31FL3731_REG_PICTUREFRAME 0x01
|
||||
|
||||
// Not defined in the datasheet -- See AN for IC
|
||||
#define IS31FL3731_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting
|
||||
|
||||
#define IS31FL3731_REG_SHUTDOWN 0x0A
|
||||
#define IS31FL3731_REG_AUDIOSYNC 0x06
|
||||
|
||||
#define IS31FL3731_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3731_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine'
|
||||
|
||||
#ifndef IS31FL3731_I2C_TIMEOUT
|
||||
# define IS31FL3731_I2C_TIMEOUT 100
|
||||
@@ -33,121 +50,90 @@
|
||||
# define IS31FL3731_I2C_PERSISTENCE 0
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3731 PWM registers 0x24-0xB3.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3731_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3731_DRIVER_COUNT][IS31FL3731_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3731_DRIVER_COUNT][144];
|
||||
bool g_pwm_buffer_update_required[IS31FL3731_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3731_DRIVER_COUNT][IS31FL3731_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3731_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3731_DRIVER_COUNT][18] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3731_DRIVER_COUNT] = {false};
|
||||
|
||||
void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3731_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT) == 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3731_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// assumes page 0 is already selected
|
||||
// assumes bank is already selected
|
||||
|
||||
// transmit PWM registers in 9 transfers of 16 bytes
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// iterate over the pwm_buffer contents at 16 byte intervals
|
||||
for (int i = 0; i < IS31FL3731_PWM_REGISTER_COUNT; i += 16) {
|
||||
for (int i = 0; i < 144; i += 16) {
|
||||
// set the first register, e.g. 0x24, 0x34, 0x44, etc.
|
||||
i2c_transfer_buffer[0] = 0x24 + i;
|
||||
g_twi_transfer_buffer[0] = 0x24 + i;
|
||||
// copy the data from i to i+15
|
||||
// device will auto-increment register for data after the first byte
|
||||
// thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3731_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void is31fl3731_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3731_I2C_ADDRESS_2)
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_3)
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_4)
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3731_LED_COUNT; i++) {
|
||||
is31fl3731_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3731_I2C_ADDRESS_2)
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_3)
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_4)
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3731_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, first enable software shutdown,
|
||||
// then set up the mode and other settings, clear the PWM registers,
|
||||
// then disable software shutdown.
|
||||
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION);
|
||||
// select "function register" bank
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, IS31FL3731_BANK_FUNCTIONREG);
|
||||
|
||||
// enable software shutdown
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x00);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_SHUTDOWN, 0x00);
|
||||
#ifdef IS31FL3731_DEGHOST // set to enable de-ghosting of the array
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION, IS31FL3731_GHOST_IMAGE_PREVENTION_GEN);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_GHOST_IMAGE_PREVENTION, 0x10);
|
||||
#endif
|
||||
|
||||
// this delay was copied from other drivers, might not be needed
|
||||
wait_ms(10);
|
||||
|
||||
// picture mode
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_CONFIG, IS31FL3731_CONFIG_MODE_PICTURE);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_CONFIG, IS31FL3731_REG_CONFIG_PICTUREMODE);
|
||||
// display frame 0
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY, 0x00);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_PICTUREFRAME, 0x00);
|
||||
// audio sync off
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_AUDIO_SYNC, 0x00);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_AUDIOSYNC, 0x00);
|
||||
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1);
|
||||
// select bank 0
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, 0);
|
||||
|
||||
// turn off all LEDs in the LED control register
|
||||
for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x11; i++) {
|
||||
is31fl3731_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
@@ -161,20 +147,21 @@ void is31fl3731_init(uint8_t addr) {
|
||||
is31fl3731_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION);
|
||||
// select "function register" bank
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, IS31FL3731_BANK_FUNCTIONREG);
|
||||
|
||||
// disable software shutdown
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x01);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_SHUTDOWN, 0x01);
|
||||
|
||||
// select page 0 and leave it selected.
|
||||
// most usage after initialization is just writing PWM buffers in page 0
|
||||
// select bank 0 and leave it selected.
|
||||
// most usage after initialization is just writing PWM buffers in bank 0
|
||||
// as there's not much point in double-buffering
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1);
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, 0);
|
||||
}
|
||||
|
||||
void is31fl3731_set_value(int index, uint8_t value) {
|
||||
is31fl3731_led_t led;
|
||||
if (index >= 0 && index < IS31FL3731_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3731_leds[index]), sizeof(led));
|
||||
|
||||
// Subtract 0x24 to get the second index of g_pwm_buffer
|
||||
@@ -188,7 +175,7 @@ void is31fl3731_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void is31fl3731_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < IS31FL3731_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3731_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -218,7 +205,7 @@ void is31fl3731_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3731_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0; i < 18; i++) {
|
||||
is31fl3731_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef LED_DRIVER_ADDR_1
|
||||
@@ -36,6 +35,9 @@
|
||||
#ifdef LED_DRIVER_ADDR_4
|
||||
# define IS31FL3731_I2C_ADDRESS_4 LED_DRIVER_ADDR_4
|
||||
#endif
|
||||
#ifdef LED_DRIVER_COUNT
|
||||
# define IS31FL3731_DRIVER_COUNT LED_DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3731_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -50,60 +52,20 @@
|
||||
#define g_is31_leds g_is31fl3731_leds
|
||||
// ========
|
||||
|
||||
#define IS31FL3731_REG_COMMAND 0xFD
|
||||
#define IS31FL3731_COMMAND_FRAME_1 0x00
|
||||
#define IS31FL3731_COMMAND_FRAME_2 0x01
|
||||
#define IS31FL3731_COMMAND_FRAME_3 0x02
|
||||
#define IS31FL3731_COMMAND_FRAME_4 0x03
|
||||
#define IS31FL3731_COMMAND_FRAME_5 0x04
|
||||
#define IS31FL3731_COMMAND_FRAME_6 0x05
|
||||
#define IS31FL3731_COMMAND_FRAME_7 0x06
|
||||
#define IS31FL3731_COMMAND_FRAME_8 0x07
|
||||
#define IS31FL3731_COMMAND_FUNCTION 0x0B
|
||||
|
||||
#define IS31FL3731_FUNCTION_REG_CONFIG 0x00
|
||||
#define IS31FL3731_CONFIG_MODE_PICTURE 0x00
|
||||
#define IS31FL3731_CONFIG_MODE_AUTO_PLAY 0x08
|
||||
#define IS31FL3731_CONFIG_MODE_AUDIO_PLAY 0x18
|
||||
|
||||
#define IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY 0x01
|
||||
#define IS31FL3731_FUNCTION_REG_AUDIO_SYNC 0x06
|
||||
#define IS31FL3731_FUNCTION_REG_SHUTDOWN 0x0A
|
||||
|
||||
// Not defined in the datasheet -- See AN for IC
|
||||
#define IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION 0xC2
|
||||
#define IS31FL3731_GHOST_IMAGE_PREVENTION_GEN 0x10
|
||||
|
||||
#define IS31FL3731_I2C_ADDRESS_GND 0x74
|
||||
#define IS31FL3731_I2C_ADDRESS_SCL 0x75
|
||||
#define IS31FL3731_I2C_ADDRESS_SDA 0x76
|
||||
#define IS31FL3731_I2C_ADDRESS_VCC 0x77
|
||||
|
||||
#if defined(LED_MATRIX_IS31FL3731)
|
||||
# define IS31FL3731_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined IS31FL3731_I2C_ADDRESS_4
|
||||
# define IS31FL3731_DRIVER_COUNT 4
|
||||
#elif defined IS31FL3731_I2C_ADDRESS_3
|
||||
# define IS31FL3731_DRIVER_COUNT 3
|
||||
#elif defined IS31FL3731_I2C_ADDRESS_2
|
||||
# define IS31FL3731_DRIVER_COUNT 2
|
||||
#elif defined IS31FL3731_I2C_ADDRESS_1
|
||||
# define IS31FL3731_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3731_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t v;
|
||||
} PACKED is31fl3731_led_t;
|
||||
} __attribute__((packed)) is31fl3731_led_t;
|
||||
|
||||
extern const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT];
|
||||
extern const is31fl3731_led_t PROGMEM g_is31fl3731_leds[LED_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3731_init_drivers(void);
|
||||
void is31fl3731_init(uint8_t addr);
|
||||
void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3731_select_page(uint8_t addr, uint8_t page);
|
||||
void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3731_set_value(int index, uint8_t value);
|
||||
|
||||
@@ -21,8 +21,25 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3731_PWM_REGISTER_COUNT 144
|
||||
#define IS31FL3731_LED_CONTROL_REGISTER_COUNT 18
|
||||
#define IS31FL3731_REG_CONFIG 0x00
|
||||
#define IS31FL3731_REG_CONFIG_PICTUREMODE 0x00
|
||||
#define IS31FL3731_REG_CONFIG_AUTOPLAYMODE 0x08
|
||||
#define IS31FL3731_REG_CONFIG_AUDIOPLAYMODE 0x18
|
||||
|
||||
#define IS31FL3731_CONF_PICTUREMODE 0x00
|
||||
#define IS31FL3731_CONF_AUTOFRAMEMODE 0x04
|
||||
#define IS31FL3731_CONF_AUDIOMODE 0x08
|
||||
|
||||
#define IS31FL3731_REG_PICTUREFRAME 0x01
|
||||
|
||||
// Not defined in the datasheet -- See AN for IC
|
||||
#define IS31FL3731_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting
|
||||
|
||||
#define IS31FL3731_REG_SHUTDOWN 0x0A
|
||||
#define IS31FL3731_REG_AUDIOSYNC 0x06
|
||||
|
||||
#define IS31FL3731_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3731_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine'
|
||||
|
||||
#ifndef IS31FL3731_I2C_TIMEOUT
|
||||
# define IS31FL3731_I2C_TIMEOUT 100
|
||||
@@ -32,119 +49,88 @@
|
||||
# define IS31FL3731_I2C_PERSISTENCE 0
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3731 PWM registers 0x24-0xB3.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3731_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3731_DRIVER_COUNT][IS31FL3731_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3731_DRIVER_COUNT][144];
|
||||
bool g_pwm_buffer_update_required[IS31FL3731_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3731_DRIVER_COUNT][IS31FL3731_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3731_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3731_DRIVER_COUNT][18] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3731_DRIVER_COUNT] = {false};
|
||||
|
||||
void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3731_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3731_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// assumes page 0 is already selected
|
||||
// assumes bank is already selected
|
||||
|
||||
// transmit PWM registers in 9 transfers of 16 bytes
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// iterate over the pwm_buffer contents at 16 byte intervals
|
||||
for (int i = 0; i < IS31FL3731_PWM_REGISTER_COUNT; i += 16) {
|
||||
for (int i = 0; i < 144; i += 16) {
|
||||
// set the first register, e.g. 0x24, 0x34, 0x44, etc.
|
||||
i2c_transfer_buffer[0] = 0x24 + i;
|
||||
g_twi_transfer_buffer[0] = 0x24 + i;
|
||||
// copy the data from i to i+15
|
||||
// device will auto-increment register for data after the first byte
|
||||
// thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3731_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void is31fl3731_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3731_I2C_ADDRESS_2)
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_3)
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_4)
|
||||
is31fl3731_init(IS31FL3731_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3731_LED_COUNT; i++) {
|
||||
is31fl3731_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3731_I2C_ADDRESS_2)
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_3)
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3731_I2C_ADDRESS_4)
|
||||
is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3731_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, first enable software shutdown,
|
||||
// then set up the mode and other settings, clear the PWM registers,
|
||||
// then disable software shutdown.
|
||||
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION);
|
||||
// select "function register" bank
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, IS31FL3731_BANK_FUNCTIONREG);
|
||||
|
||||
// enable software shutdown
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x00);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_SHUTDOWN, 0x00);
|
||||
#ifdef IS31FL3731_DEGHOST // set to enable de-ghosting of the array
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION, IS31FL3731_GHOST_IMAGE_PREVENTION_GEN);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_GHOST_IMAGE_PREVENTION, 0x10);
|
||||
#endif
|
||||
|
||||
// this delay was copied from other drivers, might not be needed
|
||||
wait_ms(10);
|
||||
|
||||
// picture mode
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_CONFIG, IS31FL3731_CONFIG_MODE_PICTURE);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_CONFIG, IS31FL3731_REG_CONFIG_PICTUREMODE);
|
||||
// display frame 0
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY, 0x00);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_PICTUREFRAME, 0x00);
|
||||
// audio sync off
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_AUDIO_SYNC, 0x00);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_AUDIOSYNC, 0x00);
|
||||
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1);
|
||||
// select bank 0
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, 0);
|
||||
|
||||
// turn off all LEDs in the LED control register
|
||||
for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x11; i++) {
|
||||
is31fl3731_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
@@ -158,20 +144,21 @@ void is31fl3731_init(uint8_t addr) {
|
||||
is31fl3731_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION);
|
||||
// select "function register" bank
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, IS31FL3731_BANK_FUNCTIONREG);
|
||||
|
||||
// disable software shutdown
|
||||
is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x01);
|
||||
is31fl3731_write_register(addr, IS31FL3731_REG_SHUTDOWN, 0x01);
|
||||
|
||||
// select page 0 and leave it selected.
|
||||
// most usage after initialization is just writing PWM buffers in page 0
|
||||
// select bank 0 and leave it selected.
|
||||
// most usage after initialization is just writing PWM buffers in bank 0
|
||||
// as there's not much point in double-buffering
|
||||
is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1);
|
||||
is31fl3731_write_register(addr, IS31FL3731_COMMANDREGISTER, 0);
|
||||
}
|
||||
|
||||
void is31fl3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
is31fl3731_led_t led;
|
||||
if (index >= 0 && index < IS31FL3731_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3731_leds[index]), sizeof(led));
|
||||
|
||||
// Subtract 0x24 to get the second index of g_pwm_buffer
|
||||
@@ -186,7 +173,7 @@ void is31fl3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void is31fl3731_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < IS31FL3731_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3731_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -230,7 +217,7 @@ void is31fl3731_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3731_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0; i < 18; i++) {
|
||||
is31fl3731_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_ADDR_1
|
||||
@@ -35,6 +34,9 @@
|
||||
#ifdef DRIVER_ADDR_4
|
||||
# define IS31FL3731_I2C_ADDRESS_4 DRIVER_ADDR_4
|
||||
#endif
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3731_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3731_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -49,62 +51,22 @@
|
||||
#define g_is31_leds g_is31fl3731_leds
|
||||
// ========
|
||||
|
||||
#define IS31FL3731_REG_COMMAND 0xFD
|
||||
#define IS31FL3731_COMMAND_FRAME_1 0x00
|
||||
#define IS31FL3731_COMMAND_FRAME_2 0x01
|
||||
#define IS31FL3731_COMMAND_FRAME_3 0x02
|
||||
#define IS31FL3731_COMMAND_FRAME_4 0x03
|
||||
#define IS31FL3731_COMMAND_FRAME_5 0x04
|
||||
#define IS31FL3731_COMMAND_FRAME_6 0x05
|
||||
#define IS31FL3731_COMMAND_FRAME_7 0x06
|
||||
#define IS31FL3731_COMMAND_FRAME_8 0x07
|
||||
#define IS31FL3731_COMMAND_FUNCTION 0x0B
|
||||
|
||||
#define IS31FL3731_FUNCTION_REG_CONFIG 0x00
|
||||
#define IS31FL3731_CONFIG_MODE_PICTURE 0x00
|
||||
#define IS31FL3731_CONFIG_MODE_AUTO_PLAY 0x08
|
||||
#define IS31FL3731_CONFIG_MODE_AUDIO_PLAY 0x18
|
||||
|
||||
#define IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY 0x01
|
||||
#define IS31FL3731_FUNCTION_REG_AUDIO_SYNC 0x06
|
||||
#define IS31FL3731_FUNCTION_REG_SHUTDOWN 0x0A
|
||||
|
||||
// Not defined in the datasheet -- See AN for IC
|
||||
#define IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION 0xC2
|
||||
#define IS31FL3731_GHOST_IMAGE_PREVENTION_GEN 0x10
|
||||
|
||||
#define IS31FL3731_I2C_ADDRESS_GND 0x74
|
||||
#define IS31FL3731_I2C_ADDRESS_SCL 0x75
|
||||
#define IS31FL3731_I2C_ADDRESS_SDA 0x76
|
||||
#define IS31FL3731_I2C_ADDRESS_VCC 0x77
|
||||
|
||||
#if defined(RGB_MATRIX_IS31FL3731)
|
||||
# define IS31FL3731_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3731_I2C_ADDRESS_4)
|
||||
# define IS31FL3731_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3731_I2C_ADDRESS_3)
|
||||
# define IS31FL3731_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3731_I2C_ADDRESS_2)
|
||||
# define IS31FL3731_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3731_I2C_ADDRESS_1)
|
||||
# define IS31FL3731_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3731_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED is31fl3731_led_t;
|
||||
} __attribute__((packed)) is31fl3731_led_t;
|
||||
|
||||
extern const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT];
|
||||
extern const is31fl3731_led_t PROGMEM g_is31fl3731_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3731_init_drivers(void);
|
||||
void is31fl3731_init(uint8_t addr);
|
||||
void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3731_select_page(uint8_t addr, uint8_t page);
|
||||
void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
@@ -23,8 +23,21 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3733_PWM_REGISTER_COUNT 192
|
||||
#define IS31FL3733_LED_CONTROL_REGISTER_COUNT 24
|
||||
#define IS31FL3733_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3733_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3733_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3733_INTERRUPTSTATUSREGISTER 0xF1
|
||||
|
||||
#define IS31FL3733_PAGE_LEDCONTROL 0x00 // PG0
|
||||
#define IS31FL3733_PAGE_PWM 0x01 // PG1
|
||||
#define IS31FL3733_PAGE_AUTOBREATH 0x02 // PG2
|
||||
#define IS31FL3733_PAGE_FUNCTION 0x03 // PG3
|
||||
|
||||
#define IS31FL3733_REG_CONFIGURATION 0x00 // PG3
|
||||
#define IS31FL3733_REG_GLOBALCURRENT 0x01 // PG3
|
||||
#define IS31FL3733_REG_RESET 0x11 // PG3
|
||||
#define IS31FL3733_REG_SWPULLUP 0x0F // PG3
|
||||
#define IS31FL3733_REG_CSPULLUP 0x10 // PG3
|
||||
|
||||
#ifndef IS31FL3733_I2C_TIMEOUT
|
||||
# define IS31FL3733_I2C_TIMEOUT 100
|
||||
@@ -38,91 +51,74 @@
|
||||
# define IS31FL3733_PWM_FREQUENCY IS31FL3733_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3733B only
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_SW_PULLUP
|
||||
# define IS31FL3733_SW_PULLUP IS31FL3733_PUR_0_OHM
|
||||
#ifndef IS31FL3733_SWPULLUP
|
||||
# define IS31FL3733_SWPULLUP IS31FL3733_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_CS_PULLDOWN
|
||||
# define IS31FL3733_CSPULLDOWN IS31FL3733_PDR_0_OHM
|
||||
#ifndef IS31FL3733_CSPULLUP
|
||||
# define IS31FL3733_CSPULLUP IS31FL3733_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_GLOBAL_CURRENT
|
||||
# define IS31FL3733_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3733_GLOBALCURRENT
|
||||
# define IS31FL3733_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_SYNC_1
|
||||
# define IS31FL3733_SYNC_1 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
#ifndef IS31FL3733_SYNC_2
|
||||
# define IS31FL3733_SYNC_2 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
#ifndef IS31FL3733_SYNC_3
|
||||
# define IS31FL3733_SYNC_3 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
#ifndef IS31FL3733_SYNC_4
|
||||
# define IS31FL3733_SYNC_4 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3733 PWM registers.
|
||||
// The control buffers match the page 0 LED On/Off registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3733_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3733_DRIVER_COUNT][IS31FL3733_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3733_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[IS31FL3733_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3733_DRIVER_COUNT][IS31FL3733_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3733_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3733_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3733_DRIVER_COUNT] = {false};
|
||||
|
||||
bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
// If the transaction fails function returns false.
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3733_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void is31fl3733_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND_WRITE_LOCK, IS31FL3733_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// Assumes page 1 is already selected.
|
||||
// Assumes PG1 is already selected.
|
||||
// If any of the transactions fails function returns false.
|
||||
// Transmit PWM registers in 12 transfers of 16 bytes.
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// Iterate over the pwm_buffer contents at 16 byte intervals.
|
||||
for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// Copy the data from i to i+15.
|
||||
// Device will auto-increment register for data after the first byte
|
||||
// Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3733_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -130,36 +126,6 @@ bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void is31fl3733_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_1, IS31FL3733_SYNC_1);
|
||||
#if defined(IS31FL3733_I2C_ADDRESS_2)
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_2, IS31FL3733_SYNC_2);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_3)
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_3, IS31FL3733_SYNC_3);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_4)
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_4, IS31FL3733_SYNC_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3733_LED_COUNT; i++) {
|
||||
is31fl3733_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3733_I2C_ADDRESS_2)
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_3)
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_4)
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3733_init(uint8_t addr, uint8_t sync) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
@@ -167,31 +133,40 @@ void is31fl3733_init(uint8_t addr, uint8_t sync) {
|
||||
// then disable software shutdown.
|
||||
// Sync is passed so set it according to the datasheet.
|
||||
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL);
|
||||
// Unlock the command register.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG0
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_LEDCONTROL);
|
||||
// Turn off all LEDs.
|
||||
for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x17; i++) {
|
||||
is31fl3733_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM);
|
||||
// Unlock the command register.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG1
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_PWM);
|
||||
// Set PWM on all LEDs to 0
|
||||
// No need to setup Breath registers to PWM as that is the default.
|
||||
for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0xBF; i++) {
|
||||
is31fl3733_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG3
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_FUNCTION);
|
||||
// Set de-ghost pull-up resistors (SWx)
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_SW_PULLUP, IS31FL3733_SW_PULLUP);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_SWPULLUP, IS31FL3733_SWPULLUP);
|
||||
// Set de-ghost pull-down resistors (CSx)
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CS_PULLDOWN, IS31FL3733_CS_PULLDOWN);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_CSPULLUP, IS31FL3733_CSPULLUP);
|
||||
// Set global current to maximum.
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3733_GLOBAL_CURRENT);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_GLOBALCURRENT, IS31FL3733_GLOBALCURRENT);
|
||||
// Disable software shutdown.
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((IS31FL3733_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((IS31FL3733_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
|
||||
// Wait 10ms to ensure the device has woken up.
|
||||
wait_ms(10);
|
||||
@@ -199,7 +174,7 @@ void is31fl3733_init(uint8_t addr, uint8_t sync) {
|
||||
|
||||
void is31fl3733_set_value(int index, uint8_t value) {
|
||||
is31fl3733_led_t led;
|
||||
if (index >= 0 && index < IS31FL3733_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3733_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.v] == value) {
|
||||
@@ -211,7 +186,7 @@ void is31fl3733_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void is31fl3733_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < IS31FL3733_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3733_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -234,9 +209,11 @@ void is31fl3733_set_led_control_register(uint8_t index, bool value) {
|
||||
|
||||
void is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM);
|
||||
// Firstly we need to unlock the command register and select PG1.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_PWM);
|
||||
|
||||
// If any of the transactions fail we risk writing dirty page 0,
|
||||
// If any of the transactions fail we risk writing dirty PG0,
|
||||
// refresh page 0 just in case.
|
||||
if (!is31fl3733_write_pwm_buffer(addr, g_pwm_buffer[index])) {
|
||||
g_led_control_registers_update_required[index] = true;
|
||||
@@ -247,9 +224,10 @@ void is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
// Firstly we need to unlock the command register and select PG0
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_LEDCONTROL);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
is31fl3733_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef LED_DRIVER_COUNT
|
||||
# define IS31FL3733_DRIVER_COUNT LED_DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3733_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -36,46 +38,27 @@
|
||||
# define IS31FL3733_PWM_FREQUENCY ISSI_PWM_FREQUENCY
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3733_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3733_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3733_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3733_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3733_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3733_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define is31_led is31fl3733_led_t
|
||||
#define g_is31_leds g_is31fl3733_leds
|
||||
|
||||
#define PUR_0R IS31FL3733_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3733_PUR_1K_OHM
|
||||
#define PUR_3KR IS31FL3733_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3733_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3733_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3733_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3733_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3733_PUR_0R
|
||||
#define PUR_05KR IS31FL3733_PUR_05KR
|
||||
#define PUR_3KR IS31FL3733_PUR_3KR
|
||||
#define PUR_4KR IS31FL3733_PUR_4KR
|
||||
#define PUR_8KR IS31FL3733_PUR_8KR
|
||||
#define PUR_16KR IS31FL3733_PUR_16KR
|
||||
#define PUR_32KR IS31FL3733_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3733_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3733_REG_INTERRUPT_STATUS 0xF1
|
||||
|
||||
#define IS31FL3733_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3733_COMMAND_LED_CONTROL 0x00
|
||||
#define IS31FL3733_COMMAND_PWM 0x01
|
||||
#define IS31FL3733_COMMAND_AUTO_BREATH 0x02
|
||||
#define IS31FL3733_COMMAND_FUNCTION 0x03
|
||||
|
||||
#define IS31FL3733_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3733_FUNCTION_REG_SW_PULLUP 0x0F
|
||||
#define IS31FL3733_FUNCTION_REG_CS_PULLDOWN 0x10
|
||||
#define IS31FL3733_FUNCTION_REG_RESET 0x11
|
||||
|
||||
#define IS31FL3733_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3733_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3733_I2C_ADDRESS_GND_GND 0x50
|
||||
#define IS31FL3733_I2C_ADDRESS_GND_SCL 0x51
|
||||
#define IS31FL3733_I2C_ADDRESS_GND_SDA 0x52
|
||||
@@ -93,31 +76,15 @@
|
||||
#define IS31FL3733_I2C_ADDRESS_VCC_SDA 0x5E
|
||||
#define IS31FL3733_I2C_ADDRESS_VCC_VCC 0x5F
|
||||
|
||||
#if defined(LED_MATRIX_IS31FL3733)
|
||||
# define IS31FL3733_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3733_I2C_ADDRESS_4)
|
||||
# define IS31FL3733_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3733_I2C_ADDRESS_3)
|
||||
# define IS31FL3733_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3733_I2C_ADDRESS_2)
|
||||
# define IS31FL3733_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3733_I2C_ADDRESS_1)
|
||||
# define IS31FL3733_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3733_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t v;
|
||||
} PACKED is31fl3733_led_t;
|
||||
} __attribute__((packed)) is31fl3733_led_t;
|
||||
|
||||
extern const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT];
|
||||
extern const is31fl3733_led_t PROGMEM g_is31fl3733_leds[LED_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3733_init_drivers(void);
|
||||
void is31fl3733_init(uint8_t addr, uint8_t sync);
|
||||
bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3733_select_page(uint8_t addr, uint8_t page);
|
||||
bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3733_set_value(int index, uint8_t value);
|
||||
@@ -134,23 +101,13 @@ void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void is31fl3733_flush(void);
|
||||
|
||||
#define IS31FL3733_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3733_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3733_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3733_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3733_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3733_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3733_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3733_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3733_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3733_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3733_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3733_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3733_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3733_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3733_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3733_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3733_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3733_PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL
|
||||
#define IS31FL3733_PUR_3KR 0x03 // 3.0k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_4KR 0x04 // 4.0k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_8KR 0x05 // 8.0k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_16KR 0x06 // 16k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
|
||||
|
||||
#define IS31FL3733_PWM_FREQUENCY_8K4_HZ 0b000
|
||||
#define IS31FL3733_PWM_FREQUENCY_4K2_HZ 0b001
|
||||
@@ -158,10 +115,6 @@ void is31fl3733_flush(void);
|
||||
#define IS31FL3733_PWM_FREQUENCY_2K1_HZ 0b011
|
||||
#define IS31FL3733_PWM_FREQUENCY_1K05_HZ 0b100
|
||||
|
||||
#define IS31FL3733_SYNC_NONE 0b00
|
||||
#define IS31FL3733_SYNC_MASTER 0b01
|
||||
#define IS31FL3733_SYNC_SLAVE 0b10
|
||||
|
||||
#define A_1 0x00
|
||||
#define A_2 0x01
|
||||
#define A_3 0x02
|
||||
|
||||
@@ -22,8 +22,21 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3733_PWM_REGISTER_COUNT 192
|
||||
#define IS31FL3733_LED_CONTROL_REGISTER_COUNT 24
|
||||
#define IS31FL3733_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3733_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3733_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3733_INTERRUPTSTATUSREGISTER 0xF1
|
||||
|
||||
#define IS31FL3733_PAGE_LEDCONTROL 0x00 // PG0
|
||||
#define IS31FL3733_PAGE_PWM 0x01 // PG1
|
||||
#define IS31FL3733_PAGE_AUTOBREATH 0x02 // PG2
|
||||
#define IS31FL3733_PAGE_FUNCTION 0x03 // PG3
|
||||
|
||||
#define IS31FL3733_REG_CONFIGURATION 0x00 // PG3
|
||||
#define IS31FL3733_REG_GLOBALCURRENT 0x01 // PG3
|
||||
#define IS31FL3733_REG_RESET 0x11 // PG3
|
||||
#define IS31FL3733_REG_SWPULLUP 0x0F // PG3
|
||||
#define IS31FL3733_REG_CSPULLUP 0x10 // PG3
|
||||
|
||||
#ifndef IS31FL3733_I2C_TIMEOUT
|
||||
# define IS31FL3733_I2C_TIMEOUT 100
|
||||
@@ -37,91 +50,74 @@
|
||||
# define IS31FL3733_PWM_FREQUENCY IS31FL3733_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3733B only
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_SW_PULLUP
|
||||
# define IS31FL3733_SW_PULLUP IS31FL3733_PUR_0_OHM
|
||||
#ifndef IS31FL3733_SWPULLUP
|
||||
# define IS31FL3733_SWPULLUP IS31FL3733_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_CS_PULLDOWN
|
||||
# define IS31FL3733_CS_PULLDOWN IS31FL3733_PDR_0_OHM
|
||||
#ifndef IS31FL3733_CSPULLUP
|
||||
# define IS31FL3733_CSPULLUP IS31FL3733_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_GLOBAL_CURRENT
|
||||
# define IS31FL3733_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3733_GLOBALCURRENT
|
||||
# define IS31FL3733_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3733_SYNC_1
|
||||
# define IS31FL3733_SYNC_1 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
#ifndef IS31FL3733_SYNC_2
|
||||
# define IS31FL3733_SYNC_2 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
#ifndef IS31FL3733_SYNC_3
|
||||
# define IS31FL3733_SYNC_3 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
#ifndef IS31FL3733_SYNC_4
|
||||
# define IS31FL3733_SYNC_4 IS31FL3733_SYNC_NONE
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3733 PWM registers.
|
||||
// The control buffers match the page 0 LED On/Off registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3733_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3733_DRIVER_COUNT][IS31FL3733_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3733_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[IS31FL3733_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3733_DRIVER_COUNT][IS31FL3733_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3733_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3733_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3733_DRIVER_COUNT] = {false};
|
||||
|
||||
bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
// If the transaction fails function returns false.
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3733_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void is31fl3733_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND_WRITE_LOCK, IS31FL3733_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// Assumes page 1 is already selected.
|
||||
// Assumes PG1 is already selected.
|
||||
// If any of the transactions fails function returns false.
|
||||
// Transmit PWM registers in 12 transfers of 16 bytes.
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// Iterate over the pwm_buffer contents at 16 byte intervals.
|
||||
for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// Copy the data from i to i+15.
|
||||
// Device will auto-increment register for data after the first byte
|
||||
// Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3733_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -129,36 +125,6 @@ bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void is31fl3733_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_1, IS31FL3733_SYNC_1);
|
||||
#if defined(IS31FL3733_I2C_ADDRESS_2)
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_2, IS31FL3733_SYNC_2);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_3)
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_3, IS31FL3733_SYNC_3);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_4)
|
||||
is31fl3733_init(IS31FL3733_I2C_ADDRESS_4, IS31FL3733_SYNC_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3733_LED_COUNT; i++) {
|
||||
is31fl3733_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3733_I2C_ADDRESS_2)
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_3)
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3733_I2C_ADDRESS_4)
|
||||
is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3733_init(uint8_t addr, uint8_t sync) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
@@ -166,31 +132,40 @@ void is31fl3733_init(uint8_t addr, uint8_t sync) {
|
||||
// then disable software shutdown.
|
||||
// Sync is passed so set it according to the datasheet.
|
||||
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL);
|
||||
// Unlock the command register.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG0
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_LEDCONTROL);
|
||||
// Turn off all LEDs.
|
||||
for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x17; i++) {
|
||||
is31fl3733_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM);
|
||||
// Unlock the command register.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG1
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_PWM);
|
||||
// Set PWM on all LEDs to 0
|
||||
// No need to setup Breath registers to PWM as that is the default.
|
||||
for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0xBF; i++) {
|
||||
is31fl3733_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG3
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_FUNCTION);
|
||||
// Set de-ghost pull-up resistors (SWx)
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_SW_PULLUP, IS31FL3733_SW_PULLUP);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_SWPULLUP, IS31FL3733_SWPULLUP);
|
||||
// Set de-ghost pull-down resistors (CSx)
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CS_PULLDOWN, IS31FL3733_CS_PULLDOWN);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_CSPULLUP, IS31FL3733_CSPULLUP);
|
||||
// Set global current to maximum.
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3733_GLOBAL_CURRENT);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_GLOBALCURRENT, IS31FL3733_GLOBALCURRENT);
|
||||
// Disable software shutdown.
|
||||
is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((IS31FL3733_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
is31fl3733_write_register(addr, IS31FL3733_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((IS31FL3733_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
|
||||
// Wait 10ms to ensure the device has woken up.
|
||||
wait_ms(10);
|
||||
@@ -198,7 +173,7 @@ void is31fl3733_init(uint8_t addr, uint8_t sync) {
|
||||
|
||||
void is31fl3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
is31fl3733_led_t led;
|
||||
if (index >= 0 && index < IS31FL3733_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3733_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.r] == red && g_pwm_buffer[led.driver][led.g] == green && g_pwm_buffer[led.driver][led.b] == blue) {
|
||||
@@ -212,7 +187,7 @@ void is31fl3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void is31fl3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < IS31FL3733_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3733_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -249,9 +224,11 @@ void is31fl3733_set_led_control_register(uint8_t index, bool red, bool green, bo
|
||||
|
||||
void is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM);
|
||||
// Firstly we need to unlock the command register and select PG1.
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_PWM);
|
||||
|
||||
// If any of the transactions fail we risk writing dirty page 0,
|
||||
// If any of the transactions fail we risk writing dirty PG0,
|
||||
// refresh page 0 just in case.
|
||||
if (!is31fl3733_write_pwm_buffer(addr, g_pwm_buffer[index])) {
|
||||
g_led_control_registers_update_required[index] = true;
|
||||
@@ -262,9 +239,10 @@ void is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
// Firstly we need to unlock the command register and select PG0
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3733_write_register(addr, IS31FL3733_COMMANDREGISTER, IS31FL3733_PAGE_LEDCONTROL);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
is31fl3733_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_ADDR_1
|
||||
@@ -49,6 +48,9 @@
|
||||
#ifdef DRIVER_ADDR_4
|
||||
# define IS31FL3733_SYNC_4 DRIVER_SYNC_4
|
||||
#endif
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3733_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3733_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -59,46 +61,27 @@
|
||||
# define IS31FL3733_PWM_FREQUENCY ISSI_PWM_FREQUENCY
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3733_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3733_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3733_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3733_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3733_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3733_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define is31_led is31fl3733_led_t
|
||||
#define g_is31_leds g_is31fl3733_leds
|
||||
|
||||
#define PUR_0R IS31FL3733_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3733_PUR_1K_OHM
|
||||
#define PUR_3KR IS31FL3733_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3733_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3733_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3733_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3733_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3733_PUR_0R
|
||||
#define PUR_05KR IS31FL3733_PUR_05KR
|
||||
#define PUR_3KR IS31FL3733_PUR_3KR
|
||||
#define PUR_4KR IS31FL3733_PUR_4KR
|
||||
#define PUR_8KR IS31FL3733_PUR_8KR
|
||||
#define PUR_16KR IS31FL3733_PUR_16KR
|
||||
#define PUR_32KR IS31FL3733_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3733_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3733_REG_INTERRUPT_STATUS 0xF1
|
||||
|
||||
#define IS31FL3733_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3733_COMMAND_LED_CONTROL 0x00
|
||||
#define IS31FL3733_COMMAND_PWM 0x01
|
||||
#define IS31FL3733_COMMAND_AUTO_BREATH 0x02
|
||||
#define IS31FL3733_COMMAND_FUNCTION 0x03
|
||||
|
||||
#define IS31FL3733_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3733_FUNCTION_REG_SW_PULLUP 0x0F
|
||||
#define IS31FL3733_FUNCTION_REG_CS_PULLDOWN 0x10
|
||||
#define IS31FL3733_FUNCTION_REG_RESET 0x11
|
||||
|
||||
#define IS31FL3733_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3733_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3733_I2C_ADDRESS_GND_GND 0x50
|
||||
#define IS31FL3733_I2C_ADDRESS_GND_SCL 0x51
|
||||
#define IS31FL3733_I2C_ADDRESS_GND_SDA 0x52
|
||||
@@ -116,33 +99,17 @@
|
||||
#define IS31FL3733_I2C_ADDRESS_VCC_SDA 0x5E
|
||||
#define IS31FL3733_I2C_ADDRESS_VCC_VCC 0x5F
|
||||
|
||||
#if defined(RGB_MATRIX_IS31FL3733)
|
||||
# define IS31FL3733_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3733_I2C_ADDRESS_4)
|
||||
# define IS31FL3733_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3733_I2C_ADDRESS_3)
|
||||
# define IS31FL3733_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3733_I2C_ADDRESS_2)
|
||||
# define IS31FL3733_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3733_I2C_ADDRESS_1)
|
||||
# define IS31FL3733_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3733_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED is31fl3733_led_t;
|
||||
} __attribute__((packed)) is31fl3733_led_t;
|
||||
|
||||
extern const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT];
|
||||
extern const is31fl3733_led_t PROGMEM g_is31fl3733_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3733_init_drivers(void);
|
||||
void is31fl3733_init(uint8_t addr, uint8_t sync);
|
||||
bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3733_select_page(uint8_t addr, uint8_t page);
|
||||
bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
@@ -159,23 +126,13 @@ void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void is31fl3733_flush(void);
|
||||
|
||||
#define IS31FL3733_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3733_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3733_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3733_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3733_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3733_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3733_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3733_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3733_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3733_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3733_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3733_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3733_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3733_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3733_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3733_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3733_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3733_PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL
|
||||
#define IS31FL3733_PUR_3KR 0x03 // 3.0k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_4KR 0x04 // 4.0k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_8KR 0x05 // 8.0k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_16KR 0x06 // 16k Ohm resistor on all the time
|
||||
#define IS31FL3733_PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
|
||||
|
||||
#define IS31FL3733_PWM_FREQUENCY_8K4_HZ 0b000
|
||||
#define IS31FL3733_PWM_FREQUENCY_4K2_HZ 0b001
|
||||
@@ -183,10 +140,6 @@ void is31fl3733_flush(void);
|
||||
#define IS31FL3733_PWM_FREQUENCY_2K1_HZ 0b011
|
||||
#define IS31FL3733_PWM_FREQUENCY_1K05_HZ 0b100
|
||||
|
||||
#define IS31FL3733_SYNC_NONE 0b00
|
||||
#define IS31FL3733_SYNC_MASTER 0b01
|
||||
#define IS31FL3733_SYNC_SLAVE 0b10
|
||||
|
||||
#define A_1 0x00
|
||||
#define A_2 0x01
|
||||
#define A_3 0x02
|
||||
|
||||
@@ -20,8 +20,21 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3736_PWM_REGISTER_COUNT 192 // actually 96
|
||||
#define IS31FL3736_LED_CONTROL_REGISTER_COUNT 24
|
||||
#define IS31FL3736_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3736_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3736_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3736_INTERRUPTSTATUSREGISTER 0xF1
|
||||
|
||||
#define IS31FL3736_PAGE_LEDCONTROL 0x00 // PG0
|
||||
#define IS31FL3736_PAGE_PWM 0x01 // PG1
|
||||
#define IS31FL3736_PAGE_AUTOBREATH 0x02 // PG2
|
||||
#define IS31FL3736_PAGE_FUNCTION 0x03 // PG3
|
||||
|
||||
#define IS31FL3736_REG_CONFIGURATION 0x00 // PG3
|
||||
#define IS31FL3736_REG_GLOBALCURRENT 0x01 // PG3
|
||||
#define IS31FL3736_REG_RESET 0x11 // PG3
|
||||
#define IS31FL3736_REG_SWPULLUP 0x0F // PG3
|
||||
#define IS31FL3736_REG_CSPULLUP 0x10 // PG3
|
||||
|
||||
#ifndef IS31FL3736_I2C_TIMEOUT
|
||||
# define IS31FL3736_I2C_TIMEOUT 100
|
||||
@@ -35,135 +48,110 @@
|
||||
# define IS31FL3736_PWM_FREQUENCY IS31FL3736_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3736B only
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3736_SW_PULLUP
|
||||
# define IS31FL3736_SW_PULLUP IS31FL3736_PUR_0_OHM
|
||||
#ifndef IS31FL3736_SWPULLUP
|
||||
# define IS31FL3736_SWPULLUP IS31FL3736_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3736_CS_PULLDOWN
|
||||
# define IS31FL3736_CS_PULLDOWN IS31FL3736_PDR_0_OHM
|
||||
#ifndef IS31FL3736_CSPULLUP
|
||||
# define IS31FL3736_CSPULLUP IS31FL3736_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3736_GLOBAL_CURRENT
|
||||
# define IS31FL3736_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3736_GLOBALCURRENT
|
||||
# define IS31FL3736_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3736 PWM registers.
|
||||
// The control buffers match the page 0 LED On/Off registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3736_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][IS31FL3736_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[IS31FL3736_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][IS31FL3736_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3736_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3736_DRIVER_COUNT] = {false};
|
||||
|
||||
void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3736_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3736_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND_WRITE_LOCK, IS31FL3736_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// assumes page 1 is already selected
|
||||
// assumes PG1 is already selected
|
||||
|
||||
// transmit PWM registers in 12 transfers of 16 bytes
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// iterate over the pwm_buffer contents at 16 byte intervals
|
||||
for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// copy the data from i to i+15
|
||||
// device will auto-increment register for data after the first byte
|
||||
// thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3736_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void is31fl3736_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3736_I2C_ADDRESS_2)
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_3)
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_4)
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3736_LED_COUNT; i++) {
|
||||
is31fl3736_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3736_I2C_ADDRESS_2)
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_3)
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_4)
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3736_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
// Set up the mode and other settings, clear the PWM registers,
|
||||
// then disable software shutdown.
|
||||
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL);
|
||||
// Unlock the command register.
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG0
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL);
|
||||
// Turn off all LEDs.
|
||||
for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x17; i++) {
|
||||
is31fl3736_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM);
|
||||
// Unlock the command register.
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG1
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_PWM);
|
||||
// Set PWM on all LEDs to 0
|
||||
// No need to setup Breath registers to PWM as that is the default.
|
||||
for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0xBF; i++) {
|
||||
is31fl3736_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG3
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_FUNCTION);
|
||||
// Set de-ghost pull-up resistors (SWx)
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_SW_PULLUP, IS31FL3736_SW_PULLUP);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_SWPULLUP, IS31FL3736_SWPULLUP);
|
||||
// Set de-ghost pull-down resistors (CSx)
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CS_PULLDOWN, IS31FL3736_CS_PULLDOWN);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_CSPULLUP, IS31FL3736_CSPULLUP);
|
||||
// Set global current to maximum.
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3736_GLOBAL_CURRENT);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_GLOBALCURRENT, IS31FL3736_GLOBALCURRENT);
|
||||
// Disable software shutdown.
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CONFIGURATION, ((IS31FL3736_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_CONFIGURATION, ((IS31FL3736_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
|
||||
// Wait 10ms to ensure the device has woken up.
|
||||
wait_ms(10);
|
||||
@@ -171,7 +159,7 @@ void is31fl3736_init(uint8_t addr) {
|
||||
|
||||
void is31fl3736_set_value(int index, uint8_t value) {
|
||||
is31fl3736_led_t led;
|
||||
if (index >= 0 && index < IS31FL3736_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3736_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.v] == value) {
|
||||
@@ -183,7 +171,7 @@ void is31fl3736_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void is31fl3736_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < IS31FL3736_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3736_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -212,7 +200,9 @@ void is31fl3736_set_led_control_register(uint8_t index, bool value) {
|
||||
|
||||
void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM);
|
||||
// Firstly we need to unlock the command register and select PG1
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_PWM);
|
||||
|
||||
is31fl3736_write_pwm_buffer(addr, g_pwm_buffer[index]);
|
||||
g_pwm_buffer_update_required[index] = false;
|
||||
@@ -221,9 +211,10 @@ void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
// Firstly we need to unlock the command register and select PG0
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
is31fl3736_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3736_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3736_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -30,47 +32,28 @@
|
||||
# define IS31FL3736_I2C_PERSISTENCE ISSI_PERSISTENCE
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3736_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3736_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3736_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3736_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3736_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3736_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define is31_led is31fl3736_led_t
|
||||
#define g_is31_leds g_is31fl3736_leds
|
||||
|
||||
#define PUR_0R IS31FL3736_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3736_PUR_05K_OHM
|
||||
#define PUR_1KR IS31FL3736_PUR_1K_OHM
|
||||
#define PUR_2KR IS31FL3736_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3736_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3736_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3736_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3736_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3736_PUR_0R
|
||||
#define PUR_05KR IS31FL3736_PUR_05KR
|
||||
#define PUR_1KR IS31FL3736_PUR_1KR
|
||||
#define PUR_2KR IS31FL3736_PUR_2KR
|
||||
#define PUR_4KR IS31FL3736_PUR_4KR
|
||||
#define PUR_8KR IS31FL3736_PUR_8KR
|
||||
#define PUR_16KR IS31FL3736_PUR_16KR
|
||||
#define PUR_32KR IS31FL3736_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3736_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3736_REG_INTERRUPT_STATUS 0xF1
|
||||
|
||||
#define IS31FL3736_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3736_COMMAND_LED_CONTROL 0x00
|
||||
#define IS31FL3736_COMMAND_PWM 0x01
|
||||
#define IS31FL3736_COMMAND_AUTO_BREATH 0x02
|
||||
#define IS31FL3736_COMMAND_FUNCTION 0x03
|
||||
|
||||
#define IS31FL3736_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3736_FUNCTION_REG_SW_PULLUP 0x0F
|
||||
#define IS31FL3736_FUNCTION_REG_CS_PULLDOWN 0x10
|
||||
#define IS31FL3736_FUNCTION_REG_RESET 0x11
|
||||
|
||||
#define IS31FL3736_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3736_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3736_I2C_ADDRESS_GND_GND 0x50
|
||||
#define IS31FL3736_I2C_ADDRESS_GND_SCL 0x51
|
||||
#define IS31FL3736_I2C_ADDRESS_GND_SDA 0x52
|
||||
@@ -88,31 +71,15 @@
|
||||
#define IS31FL3736_I2C_ADDRESS_VCC_SDA 0x5E
|
||||
#define IS31FL3736_I2C_ADDRESS_VCC_VCC 0x5F
|
||||
|
||||
#if defined(LED_MATRIX_IS31FL3736)
|
||||
# define IS31FL3736_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3736_I2C_ADDRESS_4)
|
||||
# define IS31FL3736_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3736_I2C_ADDRESS_3)
|
||||
# define IS31FL3736_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3736_I2C_ADDRESS_2)
|
||||
# define IS31FL3736_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3736_I2C_ADDRESS_1)
|
||||
# define IS31FL3736_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3736_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t v;
|
||||
} PACKED is31fl3736_led_t;
|
||||
} __attribute__((packed)) is31fl3736_led_t;
|
||||
|
||||
extern const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT];
|
||||
extern const is31fl3736_led_t PROGMEM g_is31fl3736_leds[LED_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3736_init_drivers(void);
|
||||
void is31fl3736_init(uint8_t addr);
|
||||
void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3736_select_page(uint8_t addr, uint8_t page);
|
||||
void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3736_set_value(int index, uint8_t value);
|
||||
@@ -129,23 +96,14 @@ void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void is31fl3736_flush(void);
|
||||
|
||||
#define IS31FL3736_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3736_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3736_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3736_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3736_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3736_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3736_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3736_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3736_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3736_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3736_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3736_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3736_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3736_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3736_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3736_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3736_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3736_PUR_05KR 0x01 // 0.5k Ohm resistor
|
||||
#define IS31FL3736_PUR_1KR 0x02 // 1.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_2KR 0x03 // 2.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_4KR 0x04 // 4.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_8KR 0x05 // 8.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_16KR 0x06 // 16k Ohm resistor
|
||||
#define IS31FL3736_PUR_32KR 0x07 // 32k Ohm resistor
|
||||
|
||||
#define IS31FL3736_PWM_FREQUENCY_8K4_HZ 0b000
|
||||
#define IS31FL3736_PWM_FREQUENCY_4K2_HZ 0b001
|
||||
|
||||
@@ -20,8 +20,21 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3736_PWM_REGISTER_COUNT 192 // actually 96
|
||||
#define IS31FL3736_LED_CONTROL_REGISTER_COUNT 24
|
||||
#define IS31FL3736_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3736_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3736_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3736_INTERRUPTSTATUSREGISTER 0xF1
|
||||
|
||||
#define IS31FL3736_PAGE_LEDCONTROL 0x00 // PG0
|
||||
#define IS31FL3736_PAGE_PWM 0x01 // PG1
|
||||
#define IS31FL3736_PAGE_AUTOBREATH 0x02 // PG2
|
||||
#define IS31FL3736_PAGE_FUNCTION 0x03 // PG3
|
||||
|
||||
#define IS31FL3736_REG_CONFIGURATION 0x00 // PG3
|
||||
#define IS31FL3736_REG_GLOBALCURRENT 0x01 // PG3
|
||||
#define IS31FL3736_REG_RESET 0x11 // PG3
|
||||
#define IS31FL3736_REG_SWPULLUP 0x0F // PG3
|
||||
#define IS31FL3736_REG_CSPULLUP 0x10 // PG3
|
||||
|
||||
#ifndef IS31FL3736_I2C_TIMEOUT
|
||||
# define IS31FL3736_I2C_TIMEOUT 100
|
||||
@@ -35,135 +48,110 @@
|
||||
# define IS31FL3736_PWM_FREQUENCY IS31FL3736_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3736B only
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3736_SW_PULLUP
|
||||
# define IS31FL3736_SW_PULLUP IS31FL3736_PUR_0_OHM
|
||||
#ifndef IS31FL3736_SWPULLUP
|
||||
# define IS31FL3736_SWPULLUP IS31FL3736_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3736_CS_PULLDOWN
|
||||
# define IS31FL3736_CS_PULLDOWN IS31FL3736_PDR_0_OHM
|
||||
#ifndef IS31FL3736_CSPULLUP
|
||||
# define IS31FL3736_CSPULLUP IS31FL3736_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3736_GLOBAL_CURRENT
|
||||
# define IS31FL3736_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3736_GLOBALCURRENT
|
||||
# define IS31FL3736_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3736 PWM registers.
|
||||
// The control buffers match the page 0 LED On/Off registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3736_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][IS31FL3736_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[IS31FL3736_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][IS31FL3736_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3736_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3736_DRIVER_COUNT] = {false};
|
||||
|
||||
void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3736_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3736_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND_WRITE_LOCK, IS31FL3736_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// assumes page 1 is already selected
|
||||
// assumes PG1 is already selected
|
||||
|
||||
// transmit PWM registers in 12 transfers of 16 bytes
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// iterate over the pwm_buffer contents at 16 byte intervals
|
||||
for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// copy the data from i to i+15
|
||||
// device will auto-increment register for data after the first byte
|
||||
// thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3736_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void is31fl3736_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3736_I2C_ADDRESS_2)
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_3)
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_4)
|
||||
is31fl3736_init(IS31FL3736_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3736_LED_COUNT; i++) {
|
||||
is31fl3736_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3736_I2C_ADDRESS_2)
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_3)
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3736_I2C_ADDRESS_4)
|
||||
is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3736_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
// Set up the mode and other settings, clear the PWM registers,
|
||||
// then disable software shutdown.
|
||||
|
||||
is31fl3736_select_page(addr, IS31FL3736_REG_LED_CONTROL);
|
||||
// Unlock the command register.
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG0
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL);
|
||||
// Turn off all LEDs.
|
||||
for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x17; i++) {
|
||||
is31fl3736_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM);
|
||||
// Unlock the command register.
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG1
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_PWM);
|
||||
// Set PWM on all LEDs to 0
|
||||
// No need to setup Breath registers to PWM as that is the default.
|
||||
for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0xBF; i++) {
|
||||
is31fl3736_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG3
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_FUNCTION);
|
||||
// Set de-ghost pull-up resistors (SWx)
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_SW_PULLUP, IS31FL3736_SW_PULLUP);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_SWPULLUP, IS31FL3736_SWPULLUP);
|
||||
// Set de-ghost pull-down resistors (CSx)
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CS_PULLDOWN, IS31FL3736_CS_PULLDOWN);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_CSPULLUP, IS31FL3736_CSPULLUP);
|
||||
// Set global current to maximum.
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3736_GLOBAL_CURRENT);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_GLOBALCURRENT, IS31FL3736_GLOBALCURRENT);
|
||||
// Disable software shutdown.
|
||||
is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CONFIGURATION, ((IS31FL3736_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
is31fl3736_write_register(addr, IS31FL3736_REG_CONFIGURATION, ((IS31FL3736_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
|
||||
// Wait 10ms to ensure the device has woken up.
|
||||
wait_ms(10);
|
||||
@@ -171,7 +159,7 @@ void is31fl3736_init(uint8_t addr) {
|
||||
|
||||
void is31fl3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
is31fl3736_led_t led;
|
||||
if (index >= 0 && index < IS31FL3736_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3736_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.r] == red && g_pwm_buffer[led.driver][led.g] == green && g_pwm_buffer[led.driver][led.b] == blue) {
|
||||
@@ -185,7 +173,7 @@ void is31fl3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void is31fl3736_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < IS31FL3736_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3736_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -229,7 +217,9 @@ void is31fl3736_set_led_control_register(uint8_t index, bool red, bool green, bo
|
||||
|
||||
void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM);
|
||||
// Firstly we need to unlock the command register and select PG1
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_PWM);
|
||||
|
||||
is31fl3736_write_pwm_buffer(addr, g_pwm_buffer[index]);
|
||||
g_pwm_buffer_update_required[index] = false;
|
||||
@@ -238,9 +228,10 @@ void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
// Firstly we need to unlock the command register and select PG0
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
is31fl3736_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_ADDR_1
|
||||
@@ -35,6 +34,9 @@
|
||||
#ifdef DRIVER_ADDR_4
|
||||
# define IS31FL3736_I2C_ADDRESS_4 DRIVER_ADDR_4
|
||||
#endif
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3736_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3736_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -42,47 +44,28 @@
|
||||
# define IS31FL3736_I2C_PERSISTENCE ISSI_PERSISTENCE
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3736_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3736_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3736_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3736_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3736_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3736_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define is31_led is31fl3736_led_t
|
||||
#define g_is31_leds g_is31fl3736_leds
|
||||
|
||||
#define PUR_0R IS31FL3736_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3736_PUR_0K5_OHM
|
||||
#define PUR_1KR IS31FL3736_PUR_1K_OHM
|
||||
#define PUR_2KR IS31FL3736_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3736_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3736_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3736_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3736_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3736_PUR_0R
|
||||
#define PUR_05KR IS31FL3736_PUR_05KR
|
||||
#define PUR_1KR IS31FL3736_PUR_1KR
|
||||
#define PUR_2KR IS31FL3736_PUR_2KR
|
||||
#define PUR_4KR IS31FL3736_PUR_4KR
|
||||
#define PUR_8KR IS31FL3736_PUR_8KR
|
||||
#define PUR_16KR IS31FL3736_PUR_16KR
|
||||
#define PUR_32KR IS31FL3736_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3736_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3736_REG_INTERRUPT_STATUS 0xF1
|
||||
|
||||
#define IS31FL3736_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3736_COMMAND_LED_CONTROL 0x00
|
||||
#define IS31FL3736_COMMAND_PWM 0x01
|
||||
#define IS31FL3736_COMMAND_AUTO_BREATH 0x02
|
||||
#define IS31FL3736_COMMAND_FUNCTION 0x03
|
||||
|
||||
#define IS31FL3736_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3736_FUNCTION_REG_SW_PULLUP 0x0F
|
||||
#define IS31FL3736_FUNCTION_REG_CS_PULLDOWN 0x10
|
||||
#define IS31FL3736_FUNCTION_REG_RESET 0x11
|
||||
|
||||
#define IS31FL3736_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3736_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3736_I2C_ADDRESS_GND_GND 0x50
|
||||
#define IS31FL3736_I2C_ADDRESS_GND_SCL 0x51
|
||||
#define IS31FL3736_I2C_ADDRESS_GND_SDA 0x52
|
||||
@@ -100,33 +83,17 @@
|
||||
#define IS31FL3736_I2C_ADDRESS_VCC_SDA 0x5E
|
||||
#define IS31FL3736_I2C_ADDRESS_VCC_VCC 0x5F
|
||||
|
||||
#if defined(RGB_MATRIX_IS31FL3736)
|
||||
# define IS31FL3736_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3736_I2C_ADDRESS_4)
|
||||
# define IS31FL3736_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3736_I2C_ADDRESS_3)
|
||||
# define IS31FL3736_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3736_I2C_ADDRESS_2)
|
||||
# define IS31FL3736_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3736_I2C_ADDRESS_1)
|
||||
# define IS31FL3736_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3736_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED is31fl3736_led_t;
|
||||
} __attribute__((packed)) is31fl3736_led_t;
|
||||
|
||||
extern const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT];
|
||||
extern const is31fl3736_led_t PROGMEM g_is31fl3736_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3736_init_drivers(void);
|
||||
void is31fl3736_init(uint8_t addr);
|
||||
void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3736_select_page(uint8_t addr, uint8_t page);
|
||||
void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
@@ -143,23 +110,14 @@ void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void is31fl3736_flush(void);
|
||||
|
||||
#define IS31FL3736_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3736_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3736_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3736_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3736_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3736_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3736_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3736_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3736_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3736_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3736_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3736_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3736_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3736_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3736_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3736_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3736_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3736_PUR_05KR 0x01 // 0.5k Ohm resistor
|
||||
#define IS31FL3736_PUR_1KR 0x02 // 1.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_2KR 0x03 // 2.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_4KR 0x04 // 4.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_8KR 0x05 // 8.0k Ohm resistor
|
||||
#define IS31FL3736_PUR_16KR 0x06 // 16k Ohm resistor
|
||||
#define IS31FL3736_PUR_32KR 0x07 // 32k Ohm resistor
|
||||
|
||||
#define IS31FL3736_PWM_FREQUENCY_8K4_HZ 0b000
|
||||
#define IS31FL3736_PWM_FREQUENCY_4K2_HZ 0b001
|
||||
|
||||
@@ -22,8 +22,21 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3737_PWM_REGISTER_COUNT 192 // actually 144
|
||||
#define IS31FL3737_LED_CONTROL_REGISTER_COUNT 24
|
||||
#define IS31FL3737_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3737_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3737_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3737_INTERRUPTSTATUSREGISTER 0xF1
|
||||
|
||||
#define IS31FL3737_PAGE_LEDCONTROL 0x00 // PG0
|
||||
#define IS31FL3737_PAGE_PWM 0x01 // PG1
|
||||
#define IS31FL3737_PAGE_AUTOBREATH 0x02 // PG2
|
||||
#define IS31FL3737_PAGE_FUNCTION 0x03 // PG3
|
||||
|
||||
#define IS31FL3737_REG_CONFIGURATION 0x00 // PG3
|
||||
#define IS31FL3737_REG_GLOBALCURRENT 0x01 // PG3
|
||||
#define IS31FL3737_REG_RESET 0x11 // PG3
|
||||
#define IS31FL3737_REG_SWPULLUP 0x0F // PG3
|
||||
#define IS31FL3737_REG_CSPULLUP 0x10 // PG3
|
||||
|
||||
#ifndef IS31FL3737_I2C_TIMEOUT
|
||||
# define IS31FL3737_I2C_TIMEOUT 100
|
||||
@@ -37,136 +50,111 @@
|
||||
# define IS31FL3737_PWM_FREQUENCY IS31FL3737_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3737B only
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3737_SW_PULLUP
|
||||
# define IS31FL3737_SW_PULLUP IS31FL3737_PUR_0_OHM
|
||||
#ifndef IS31FL3737_SWPULLUP
|
||||
# define IS31FL3737_SWPULLUP IS31FL3737_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3737_CS_PULLDOWN
|
||||
# define IS31FL3737_CS_PULLDOWN IS31FL3737_PDR_0_OHM
|
||||
#ifndef IS31FL3737_CSPULLUP
|
||||
# define IS31FL3737_CSPULLUP IS31FL3737_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3737_GLOBAL_CURRENT
|
||||
# define IS31FL3737_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3737_GLOBALCURRENT
|
||||
# define IS31FL3737_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3737 PWM registers.
|
||||
// The control buffers match the page 0 LED On/Off registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3737_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
|
||||
uint8_t g_pwm_buffer[IS31FL3737_DRIVER_COUNT][IS31FL3737_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3737_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[IS31FL3737_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3737_DRIVER_COUNT][IS31FL3737_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3737_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3737_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3737_DRIVER_COUNT] = {false};
|
||||
|
||||
void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3737_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3737_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND_WRITE_LOCK, IS31FL3737_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// assumes page 1 is already selected
|
||||
// assumes PG1 is already selected
|
||||
|
||||
// transmit PWM registers in 12 transfers of 16 bytes
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// iterate over the pwm_buffer contents at 16 byte intervals
|
||||
for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// copy the data from i to i+15
|
||||
// device will auto-increment register for data after the first byte
|
||||
// thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3737_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void is31fl3737_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3737_I2C_ADDRESS_2)
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_3)
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_4)
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3737_LED_COUNT; i++) {
|
||||
is31fl3737_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3737_I2C_ADDRESS_2)
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_3)
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_4)
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3737_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
// Set up the mode and other settings, clear the PWM registers,
|
||||
// then disable software shutdown.
|
||||
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL);
|
||||
// Unlock the command register.
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG0
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_LEDCONTROL);
|
||||
// Turn off all LEDs.
|
||||
for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x17; i++) {
|
||||
is31fl3737_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM);
|
||||
// Unlock the command register.
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG1
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_PWM);
|
||||
// Set PWM on all LEDs to 0
|
||||
// No need to setup Breath registers to PWM as that is the default.
|
||||
for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0xBF; i++) {
|
||||
is31fl3737_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG3
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_FUNCTION);
|
||||
// Set de-ghost pull-up resistors (SWx)
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_SW_PULLUP, IS31FL3737_SW_PULLUP);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_SWPULLUP, IS31FL3737_SWPULLUP);
|
||||
// Set de-ghost pull-down resistors (CSx)
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CS_PULLDOWN, IS31FL3737_CS_PULLDOWN);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_CSPULLUP, IS31FL3737_CSPULLUP);
|
||||
// Set global current to maximum.
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3737_GLOBAL_CURRENT);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_GLOBALCURRENT, IS31FL3737_GLOBALCURRENT);
|
||||
// Disable software shutdown.
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CONFIGURATION, ((IS31FL3737_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_CONFIGURATION, ((IS31FL3737_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
|
||||
// Wait 10ms to ensure the device has woken up.
|
||||
wait_ms(10);
|
||||
@@ -174,7 +162,7 @@ void is31fl3737_init(uint8_t addr) {
|
||||
|
||||
void is31fl3737_set_value(int index, uint8_t value) {
|
||||
is31fl3737_led_t led;
|
||||
if (index >= 0 && index < IS31FL3737_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3737_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.v] == value) {
|
||||
@@ -186,7 +174,7 @@ void is31fl3737_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void is31fl3737_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < IS31FL3737_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3737_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -209,7 +197,9 @@ void is31fl3737_set_led_control_register(uint8_t index, bool value) {
|
||||
|
||||
void is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM);
|
||||
// Firstly we need to unlock the command register and select PG1
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_PWM);
|
||||
|
||||
is31fl3737_write_pwm_buffer(addr, g_pwm_buffer[index]);
|
||||
g_pwm_buffer_update_required[index] = false;
|
||||
@@ -218,9 +208,10 @@ void is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
// Firstly we need to unlock the command register and select PG0
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_LEDCONTROL);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
is31fl3737_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3737_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3737_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -35,74 +37,39 @@
|
||||
# define IS31FL3737_PWM_FREQUENCY ISSI_PWM_FREQUENCY
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3737_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3737_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3737_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3737_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3737_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3737_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define PUR_0R IS31FL3737_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3737_PUR_0K5_OHM
|
||||
#define PUR_1KR IS31FL3737_PUR_1K_OHM
|
||||
#define PUR_2KR IS31FL3737_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3737_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3737_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3737_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3737_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3737_PUR_0R
|
||||
#define PUR_05KR IS31FL3737_PUR_05KR
|
||||
#define PUR_1KR IS31FL3737_PUR_1KR
|
||||
#define PUR_2KR IS31FL3737_PUR_2KR
|
||||
#define PUR_4KR IS31FL3737_PUR_4KR
|
||||
#define PUR_8KR IS31FL3737_PUR_8KR
|
||||
#define PUR_16KR IS31FL3737_PUR_16KR
|
||||
#define PUR_32KR IS31FL3737_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3737_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3737_REG_INTERRUPT_STATUS 0xF1
|
||||
|
||||
#define IS31FL3737_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3737_COMMAND_LED_CONTROL 0x00
|
||||
#define IS31FL3737_COMMAND_PWM 0x01
|
||||
#define IS31FL3737_COMMAND_AUTO_BREATH 0x02
|
||||
#define IS31FL3737_COMMAND_FUNCTION 0x03
|
||||
|
||||
#define IS31FL3737_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3737_FUNCTION_REG_SW_PULLUP 0x0F
|
||||
#define IS31FL3737_FUNCTION_REG_CS_PULLDOWN 0x10
|
||||
#define IS31FL3737_FUNCTION_REG_RESET 0x11
|
||||
|
||||
#define IS31FL3737_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3737_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3737_I2C_ADDRESS_GND 0x50
|
||||
#define IS31FL3737_I2C_ADDRESS_SCL 0x55
|
||||
#define IS31FL3737_I2C_ADDRESS_SDA 0x5A
|
||||
#define IS31FL3737_I2C_ADDRESS_VCC 0x5F
|
||||
|
||||
#if defined(LED_MATRIX_IS31FL3737)
|
||||
# define IS31FL3737_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3737_I2C_ADDRESS_4)
|
||||
# define IS31FL3737_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3737_I2C_ADDRESS_3)
|
||||
# define IS31FL3737_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3737_I2C_ADDRESS_2)
|
||||
# define IS31FL3737_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3737_I2C_ADDRESS_1)
|
||||
# define IS31FL3737_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3737_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t v;
|
||||
} PACKED is31fl3737_led_t;
|
||||
} __attribute__((packed)) is31fl3737_led_t;
|
||||
|
||||
extern const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT];
|
||||
extern const is31fl3737_led_t PROGMEM g_is31fl3737_leds[LED_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3737_init_drivers(void);
|
||||
void is31fl3737_init(uint8_t addr);
|
||||
void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3737_select_page(uint8_t addr, uint8_t page);
|
||||
void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3737_set_value(int index, uint8_t value);
|
||||
@@ -119,23 +86,14 @@ void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void is31fl3737_flush(void);
|
||||
|
||||
#define IS31FL3737_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3737_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3737_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3737_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3737_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3737_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3737_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3737_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3737_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3737_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3737_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3737_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3737_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3737_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3737_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3737_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3737_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3737_PUR_05KR 0x01 // 0.5k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_1KR 0x02 // 1.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_2KR 0x03 // 2.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_4KR 0x04 // 4.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_8KR 0x05 // 8.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_16KR 0x06 // 16k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
|
||||
|
||||
#define IS31FL3737_PWM_FREQUENCY_8K4_HZ 0b000
|
||||
#define IS31FL3737_PWM_FREQUENCY_4K2_HZ 0b001
|
||||
|
||||
@@ -22,8 +22,21 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3737_PWM_REGISTER_COUNT 192 // actually 144
|
||||
#define IS31FL3737_LED_CONTROL_REGISTER_COUNT 24
|
||||
#define IS31FL3737_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3737_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3737_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3737_INTERRUPTSTATUSREGISTER 0xF1
|
||||
|
||||
#define IS31FL3737_PAGE_LEDCONTROL 0x00 // PG0
|
||||
#define IS31FL3737_PAGE_PWM 0x01 // PG1
|
||||
#define IS31FL3737_PAGE_AUTOBREATH 0x02 // PG2
|
||||
#define IS31FL3737_PAGE_FUNCTION 0x03 // PG3
|
||||
|
||||
#define IS31FL3737_REG_CONFIGURATION 0x00 // PG3
|
||||
#define IS31FL3737_REG_GLOBALCURRENT 0x01 // PG3
|
||||
#define IS31FL3737_REG_RESET 0x11 // PG3
|
||||
#define IS31FL3737_REG_SWPULLUP 0x0F // PG3
|
||||
#define IS31FL3737_REG_CSPULLUP 0x10 // PG3
|
||||
|
||||
#ifndef IS31FL3737_I2C_TIMEOUT
|
||||
# define IS31FL3737_I2C_TIMEOUT 100
|
||||
@@ -37,136 +50,111 @@
|
||||
# define IS31FL3737_PWM_FREQUENCY IS31FL3737_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3737B only
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3737_SW_PULLUP
|
||||
# define IS31FL3737_SW_PULLUP IS31FL3737_PUR_0_OHM
|
||||
#ifndef IS31FL3737_SWPULLUP
|
||||
# define IS31FL3737_SWPULLUP IS31FL3737_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3737_CS_PULLDONW
|
||||
# define IS31FL3737_CS_PULLDOWN IS31FL3737_PDR_0_OHM
|
||||
#ifndef IS31FL3737_CSPULLUP
|
||||
# define IS31FL3737_CSPULLUP IS31FL3737_PUR_0R
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3737_GLOBAL_CURRENT
|
||||
# define IS31FL3737_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3737_GLOBALCURRENT
|
||||
# define IS31FL3737_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the IS31FL3737 PWM registers.
|
||||
// The control buffers match the page 0 LED On/Off registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3737_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
|
||||
uint8_t g_pwm_buffer[IS31FL3737_DRIVER_COUNT][IS31FL3737_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3737_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[IS31FL3737_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[IS31FL3737_DRIVER_COUNT][IS31FL3737_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3737_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[IS31FL3737_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[IS31FL3737_DRIVER_COUNT] = {false};
|
||||
|
||||
void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3737_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3737_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND_WRITE_LOCK, IS31FL3737_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// assumes page 1 is already selected
|
||||
// assumes PG1 is already selected
|
||||
|
||||
// transmit PWM registers in 12 transfers of 16 bytes
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// iterate over the pwm_buffer contents at 16 byte intervals
|
||||
for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// copy the data from i to i+15
|
||||
// device will auto-increment register for data after the first byte
|
||||
// thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 16);
|
||||
|
||||
#if IS31FL3737_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void is31fl3737_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3737_I2C_ADDRESS_2)
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_3)
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_4)
|
||||
is31fl3737_init(IS31FL3737_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3737_LED_COUNT; i++) {
|
||||
is31fl3737_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3737_I2C_ADDRESS_2)
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_3)
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3737_I2C_ADDRESS_4)
|
||||
is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3737_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
// Set up the mode and other settings, clear the PWM registers,
|
||||
// then disable software shutdown.
|
||||
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL);
|
||||
// Unlock the command register.
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG0
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_LEDCONTROL);
|
||||
// Turn off all LEDs.
|
||||
for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0x17; i++) {
|
||||
is31fl3737_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM);
|
||||
// Unlock the command register.
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG1
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_PWM);
|
||||
// Set PWM on all LEDs to 0
|
||||
// No need to setup Breath registers to PWM as that is the default.
|
||||
for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i++) {
|
||||
for (int i = 0x00; i <= 0xBF; i++) {
|
||||
is31fl3737_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG3
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_FUNCTION);
|
||||
// Set de-ghost pull-up resistors (SWx)
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_SW_PULLUP, IS31FL3737_SW_PULLUP);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_SWPULLUP, IS31FL3737_SWPULLUP);
|
||||
// Set de-ghost pull-down resistors (CSx)
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CS_PULLDOWN, IS31FL3737_CS_PULLDOWN);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_CSPULLUP, IS31FL3737_CSPULLUP);
|
||||
// Set global current to maximum.
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3737_GLOBAL_CURRENT);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_GLOBALCURRENT, IS31FL3737_GLOBALCURRENT);
|
||||
// Disable software shutdown.
|
||||
is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CONFIGURATION, ((IS31FL3737_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
is31fl3737_write_register(addr, IS31FL3737_REG_CONFIGURATION, ((IS31FL3737_PWM_FREQUENCY & 0b111) << 3) | 0x01);
|
||||
|
||||
// Wait 10ms to ensure the device has woken up.
|
||||
wait_ms(10);
|
||||
@@ -174,7 +162,7 @@ void is31fl3737_init(uint8_t addr) {
|
||||
|
||||
void is31fl3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
is31fl3737_led_t led;
|
||||
if (index >= 0 && index < IS31FL3737_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3737_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.r] == red && g_pwm_buffer[led.driver][led.g] == green && g_pwm_buffer[led.driver][led.b] == blue) {
|
||||
@@ -188,7 +176,7 @@ void is31fl3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void is31fl3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < IS31FL3737_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3737_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -225,7 +213,9 @@ void is31fl3737_set_led_control_register(uint8_t index, bool red, bool green, bo
|
||||
|
||||
void is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM);
|
||||
// Firstly we need to unlock the command register and select PG1
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_PWM);
|
||||
|
||||
is31fl3737_write_pwm_buffer(addr, g_pwm_buffer[index]);
|
||||
g_pwm_buffer_update_required[index] = false;
|
||||
@@ -234,9 +224,10 @@ void is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
// Firstly we need to unlock the command register and select PG0
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3737_write_register(addr, IS31FL3737_COMMANDREGISTER, IS31FL3737_PAGE_LEDCONTROL);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
is31fl3737_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
g_led_control_registers_update_required[index] = false;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_ADDR_1
|
||||
@@ -37,6 +36,9 @@
|
||||
#ifdef DRIVER_ADDR_4
|
||||
# define IS31FL3737_I2C_ADDRESS_4 DRIVER_ADDR_4
|
||||
#endif
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3737_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3737_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -47,79 +49,44 @@
|
||||
# define IS31FL3737_PWM_FREQUENCY ISSI_PWM_FREQUENCY
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3737_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3737_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3737_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3737_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3737_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3737_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define is31_led is31fl3737_led_t
|
||||
#define g_is31_leds g_is31fl3737_leds
|
||||
|
||||
#define PUR_0R IS31FL3737_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3737_PUR_0K5_OHM
|
||||
#define PUR_1KR IS31FL3737_PUR_1K_OHM
|
||||
#define PUR_2KR IS31FL3737_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3737_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3737_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3737_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3737_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3737_PUR_0R
|
||||
#define PUR_05KR IS31FL3737_PUR_05KR
|
||||
#define PUR_1KR IS31FL3737_PUR_1KR
|
||||
#define PUR_2KR IS31FL3737_PUR_2KR
|
||||
#define PUR_4KR IS31FL3737_PUR_4KR
|
||||
#define PUR_8KR IS31FL3737_PUR_8KR
|
||||
#define PUR_16KR IS31FL3737_PUR_16KR
|
||||
#define PUR_32KR IS31FL3737_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3737_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3737_REG_INTERRUPT_STATUS 0xF1
|
||||
|
||||
#define IS31FL3737_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3737_COMMAND_LED_CONTROL 0x00
|
||||
#define IS31FL3737_COMMAND_PWM 0x01
|
||||
#define IS31FL3737_COMMAND_AUTO_BREATH 0x02
|
||||
#define IS31FL3737_COMMAND_FUNCTION 0x03
|
||||
|
||||
#define IS31FL3737_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3737_FUNCTION_REG_SW_PULLUP 0x0F
|
||||
#define IS31FL3737_FUNCTION_REG_CS_PULLDOWN 0x10
|
||||
#define IS31FL3737_FUNCTION_REG_RESET 0x11
|
||||
|
||||
#define IS31FL3737_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3737_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3737_I2C_ADDRESS_GND 0x50
|
||||
#define IS31FL3737_I2C_ADDRESS_SCL 0x55
|
||||
#define IS31FL3737_I2C_ADDRESS_SDA 0x5A
|
||||
#define IS31FL3737_I2C_ADDRESS_VCC 0x5F
|
||||
|
||||
#if defined(RGB_MATRIX_IS31FL3737)
|
||||
# define IS31FL3737_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3737_I2C_ADDRESS_4)
|
||||
# define IS31FL3737_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3737_I2C_ADDRESS_3)
|
||||
# define IS31FL3737_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3737_I2C_ADDRESS_2)
|
||||
# define IS31FL3737_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3737_I2C_ADDRESS_1)
|
||||
# define IS31FL3737_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3737_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED is31fl3737_led_t;
|
||||
} __attribute__((packed)) is31fl3737_led_t;
|
||||
|
||||
extern const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT];
|
||||
extern const is31fl3737_led_t PROGMEM g_is31fl3737_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3737_init_drivers(void);
|
||||
void is31fl3737_init(uint8_t addr);
|
||||
void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3737_select_page(uint8_t addr, uint8_t page);
|
||||
void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
@@ -136,23 +103,14 @@ void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void is31fl3737_flush(void);
|
||||
|
||||
#define IS31FL3737_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3737_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3737_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3737_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3737_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3737_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3737_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3737_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3737_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3737_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3737_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3737_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3737_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3737_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3737_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3737_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3737_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3737_PUR_05KR 0x01 // 0.5k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_1KR 0x02 // 1.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_2KR 0x03 // 2.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_4KR 0x04 // 4.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_8KR 0x05 // 8.0k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_16KR 0x06 // 16k Ohm resistor in t_NOL
|
||||
#define IS31FL3737_PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
|
||||
|
||||
#define IS31FL3737_PWM_FREQUENCY_8K4_HZ 0b000
|
||||
#define IS31FL3737_PWM_FREQUENCY_4K2_HZ 0b001
|
||||
|
||||
@@ -22,7 +22,23 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3741_PWM_REGISTER_COUNT 351
|
||||
#define IS31FL3741_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3741_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3741_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3741_INTERRUPTSTATUSREGISTER 0xF1
|
||||
#define IS31FL3741_IDREGISTER 0xFC
|
||||
|
||||
#define IS31FL3741_PAGE_PWM0 0x00 // PG0
|
||||
#define IS31FL3741_PAGE_PWM1 0x01 // PG1
|
||||
#define IS31FL3741_PAGE_SCALING_0 0x02 // PG2
|
||||
#define IS31FL3741_PAGE_SCALING_1 0x03 // PG3
|
||||
#define IS31FL3741_PAGE_FUNCTION 0x04 // PG4
|
||||
|
||||
#define IS31FL3741_REG_CONFIGURATION 0x00 // PG4
|
||||
#define IS31FL3741_REG_GLOBALCURRENT 0x01 // PG4
|
||||
#define IS31FL3741_REG_PULLDOWNUP 0x02 // PG4
|
||||
#define IS31FL3741_REG_PWM_FREQUENCY 0x36 // PG4
|
||||
#define IS31FL3741_REG_RESET 0x3F // PG4
|
||||
|
||||
#ifndef IS31FL3741_I2C_TIMEOUT
|
||||
# define IS31FL3741_I2C_TIMEOUT 100
|
||||
@@ -40,86 +56,86 @@
|
||||
# define IS31FL3741_PWM_FREQUENCY IS31FL3741_PWM_FREQUENCY_29K_HZ
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3741_SW_PULLUP
|
||||
# define IS31FL3741_SW_PULLUP IS31FL3741_PUR_32K_OHM
|
||||
#ifndef IS31FL3741_SWPULLUP
|
||||
# define IS31FL3741_SWPULLUP IS31FL3741_PUR_32KR
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3741_CS_PULLDOWN
|
||||
# define IS31FL3741_CS_PULLDOWN IS31FL3741_PDR_32K_OHM
|
||||
#ifndef IS31FL3741_CSPULLUP
|
||||
# define IS31FL3741_CSPULLUP IS31FL3741_PUR_32KR
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3741_GLOBAL_CURRENT
|
||||
# define IS31FL3741_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3741_GLOBALCURRENT
|
||||
# define IS31FL3741_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20] = {0xFF};
|
||||
#define IS31FL3741_MAX_LEDS 351
|
||||
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20] = {0xFF};
|
||||
|
||||
// These buffers match the IS31FL3741 and IS31FL3741A PWM registers.
|
||||
// The scaling buffers match the page 2 and 3 LED On/Off registers.
|
||||
// The scaling buffers match the PG2 and PG3 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3741_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3741_DRIVER_COUNT][IS31FL3741_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3741_DRIVER_COUNT][IS31FL3741_MAX_LEDS];
|
||||
bool g_pwm_buffer_update_required[IS31FL3741_DRIVER_COUNT] = {false};
|
||||
bool g_scaling_registers_update_required[IS31FL3741_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_scaling_registers[IS31FL3741_DRIVER_COUNT][IS31FL3741_PWM_REGISTER_COUNT];
|
||||
uint8_t g_scaling_registers[IS31FL3741_DRIVER_COUNT][IS31FL3741_MAX_LEDS];
|
||||
|
||||
void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3741_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3741_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND_WRITE_LOCK, IS31FL3741_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// Assume page 0 is already selected
|
||||
// Assume PG0 is already selected
|
||||
|
||||
for (int i = 0; i < 342; i += 18) {
|
||||
if (i == 180) {
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_1);
|
||||
// unlock the command register and select PG1
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_PWM1);
|
||||
}
|
||||
|
||||
i2c_transfer_buffer[0] = i % 180;
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 18);
|
||||
g_twi_transfer_buffer[0] = i % 180;
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 18);
|
||||
|
||||
#if IS31FL3741_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// transfer the left cause the total number is 351
|
||||
i2c_transfer_buffer[0] = 162;
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + 342, 9);
|
||||
g_twi_transfer_buffer[0] = 162;
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + 342, 9);
|
||||
|
||||
#if IS31FL3741_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -127,36 +143,6 @@ bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void is31fl3741_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3741_I2C_ADDRESS_2)
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_3)
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_4)
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3741_LED_COUNT; i++) {
|
||||
is31fl3741_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3741_I2C_ADDRESS_2)
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_3)
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_4)
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3741_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
@@ -164,17 +150,21 @@ void is31fl3741_init(uint8_t addr) {
|
||||
// then disable software shutdown.
|
||||
// Unlock the command register.
|
||||
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG4
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_FUNCTION);
|
||||
|
||||
// Set to Normal operation
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_CONFIGURATION, IS31FL3741_CONFIGURATION);
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_CONFIGURATION, IS31FL3741_CONFIGURATION);
|
||||
|
||||
// Set Golbal Current Control Register
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3741_GLOBAL_CURRENT);
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_GLOBALCURRENT, IS31FL3741_GLOBALCURRENT);
|
||||
// Set Pull up & Down for SWx CSy
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PULLDOWNUP, ((IS31FL3741_CS_PULLDOWN << 4) | IS31FL3741_SW_PULLUP));
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_PULLDOWNUP, ((IS31FL3741_CSPULLUP << 4) | IS31FL3741_SWPULLUP));
|
||||
// Set PWM frequency
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3741_PWM_FREQUENCY & 0b1111));
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_PWM_FREQUENCY, (IS31FL3741_PWM_FREQUENCY & 0b1111));
|
||||
|
||||
// is31fl3741_update_led_scaling_registers(addr, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
@@ -184,7 +174,7 @@ void is31fl3741_init(uint8_t addr) {
|
||||
|
||||
void is31fl3741_set_value(int index, uint8_t value) {
|
||||
is31fl3741_led_t led;
|
||||
if (index >= 0 && index < IS31FL3741_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.v] == value) {
|
||||
@@ -196,7 +186,7 @@ void is31fl3741_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void is31fl3741_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < IS31FL3741_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3741_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -216,7 +206,9 @@ void is31fl3741_set_led_control_register(uint8_t index, bool value) {
|
||||
|
||||
void is31fl3741_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_0);
|
||||
// unlock the command register and select PG2
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_PWM0);
|
||||
|
||||
is31fl3741_write_pwm_buffer(addr, g_pwm_buffer[index]);
|
||||
}
|
||||
@@ -232,16 +224,20 @@ void is31fl3741_set_pwm_buffer(const is31fl3741_led_t *pled, uint8_t value) {
|
||||
|
||||
void is31fl3741_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_scaling_registers_update_required[index]) {
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_0);
|
||||
// unlock the command register and select PG2
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_SCALING_0);
|
||||
|
||||
// CS1_SW1 to CS30_SW6 are on page 2
|
||||
// CS1_SW1 to CS30_SW6 are on PG2
|
||||
for (int i = CS1_SW1; i <= CS30_SW6; ++i) {
|
||||
is31fl3741_write_register(addr, i, g_scaling_registers[index][i]);
|
||||
}
|
||||
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_1);
|
||||
// unlock the command register and select PG3
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_SCALING_1);
|
||||
|
||||
// CS1_SW7 to CS39_SW9 are on page 3
|
||||
// CS1_SW7 to CS39_SW9 are on PG3
|
||||
for (int i = CS1_SW7; i <= CS39_SW9; ++i) {
|
||||
is31fl3741_write_register(addr, i - CS1_SW7, g_scaling_registers[index][i]);
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3741_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3741_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -35,76 +37,39 @@
|
||||
# define IS31FL3741_CONFIGURATION ISSI_CONFIGURATION
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3741_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3741_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3741_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3741_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3741_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3741_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define PUR_0R IS31FL3741_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3741_PUR_0K5_OHM
|
||||
#define PUR_1KR IS31FL3741_PUR_1K_OHM
|
||||
#define PUR_2KR IS31FL3741_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3741_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3741_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3741_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3741_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3741_PUR_0R
|
||||
#define PUR_05KR IS31FL3741_PUR_05KR
|
||||
#define PUR_1KR IS31FL3741_PUR_1KR
|
||||
#define PUR_2KR IS31FL3741_PUR_2KR
|
||||
#define PUR_4KR IS31FL3741_PUR_4KR
|
||||
#define PUR_8KR IS31FL3741_PUR_8KR
|
||||
#define PUR_16KR IS31FL3741_PUR_16KR
|
||||
#define PUR_32KR IS31FL3741_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3741_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3741_REG_INTERRUPT_STATUS 0xF1
|
||||
#define IS31FL3741_REG_ID 0xFC
|
||||
|
||||
#define IS31FL3741_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3741_COMMAND_PWM_0 0x00
|
||||
#define IS31FL3741_COMMAND_PWM_1 0x01
|
||||
#define IS31FL3741_COMMAND_SCALING_0 0x02
|
||||
#define IS31FL3741_COMMAND_SCALING_1 0x03
|
||||
#define IS31FL3741_COMMAND_FUNCTION 0x04
|
||||
|
||||
#define IS31FL3741_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3741_FUNCTION_REG_PULLDOWNUP 0x02
|
||||
#define IS31FL3741_FUNCTION_REG_PWM_FREQUENCY 0x36
|
||||
#define IS31FL3741_FUNCTION_REG_RESET 0x3F
|
||||
|
||||
#define IS31FL3741_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3741_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3741_I2C_ADDRESS_GND 0x30
|
||||
#define IS31FL3741_I2C_ADDRESS_SCL 0x31
|
||||
#define IS31FL3741_I2C_ADDRESS_SDA 0x32
|
||||
#define IS31FL3741_I2C_ADDRESS_VCC 0x33
|
||||
|
||||
#if defined(LED_MATRIX_IS31FL3741)
|
||||
# define IS31FL3741_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3741_I2C_ADDRESS_4)
|
||||
# define IS31FL3741_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3741_I2C_ADDRESS_3)
|
||||
# define IS31FL3741_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3741_I2C_ADDRESS_2)
|
||||
# define IS31FL3741_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3741_I2C_ADDRESS_1)
|
||||
# define IS31FL3741_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3741_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint16_t v : 9;
|
||||
} PACKED is31fl3741_led_t;
|
||||
uint32_t driver : 2;
|
||||
uint32_t v : 10;
|
||||
} __attribute__((packed)) is31fl3741_led_t;
|
||||
|
||||
extern const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT];
|
||||
extern const is31fl3741_led_t PROGMEM g_is31fl3741_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3741_init_drivers(void);
|
||||
void is31fl3741_init(uint8_t addr);
|
||||
void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3741_select_page(uint8_t addr, uint8_t page);
|
||||
bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3741_set_value(int index, uint8_t value);
|
||||
@@ -124,23 +89,14 @@ void is31fl3741_set_pwm_buffer(const is31fl3741_led *pled, uint8_t value);
|
||||
|
||||
void is31fl3741_flush(void);
|
||||
|
||||
#define IS31FL3741_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3741_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3741_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3741_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3741_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3741_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3741_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3741_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3741_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3741_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3741_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3741_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3741_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3741_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3741_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3741_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3741_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3741_PUR_05KR 0x01 // 0.5k Ohm resistor
|
||||
#define IS31FL3741_PUR_1KR 0x02 // 1.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_2KR 0x03 // 2.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_4KR 0x04 // 4.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_8KR 0x05 // 8.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_16KR 0x06 // 16k Ohm resistor
|
||||
#define IS31FL3741_PUR_32KR 0x07 // 32k Ohm resistor
|
||||
|
||||
#define IS31FL3741_PWM_FREQUENCY_29K_HZ 0b0000
|
||||
#define IS31FL3741_PWM_FREQUENCY_3K6_HZ 0b0011
|
||||
|
||||
@@ -22,7 +22,23 @@
|
||||
#include "i2c_master.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define IS31FL3741_PWM_REGISTER_COUNT 351
|
||||
#define IS31FL3741_COMMANDREGISTER 0xFD
|
||||
#define IS31FL3741_COMMANDREGISTER_WRITELOCK 0xFE
|
||||
#define IS31FL3741_INTERRUPTMASKREGISTER 0xF0
|
||||
#define IS31FL3741_INTERRUPTSTATUSREGISTER 0xF1
|
||||
#define IS31FL3741_IDREGISTER 0xFC
|
||||
|
||||
#define IS31FL3741_PAGE_PWM0 0x00 // PG0
|
||||
#define IS31FL3741_PAGE_PWM1 0x01 // PG1
|
||||
#define IS31FL3741_PAGE_SCALING_0 0x02 // PG2
|
||||
#define IS31FL3741_PAGE_SCALING_1 0x03 // PG3
|
||||
#define IS31FL3741_PAGE_FUNCTION 0x04 // PG4
|
||||
|
||||
#define IS31FL3741_REG_CONFIGURATION 0x00 // PG4
|
||||
#define IS31FL3741_REG_GLOBALCURRENT 0x01 // PG4
|
||||
#define IS31FL3741_REG_PULLDOWNUP 0x02 // PG4
|
||||
#define IS31FL3741_REG_PWM_FREQUENCY 0x36 // PG4
|
||||
#define IS31FL3741_REG_RESET 0x3F // PG4
|
||||
|
||||
#ifndef IS31FL3741_I2C_TIMEOUT
|
||||
# define IS31FL3741_I2C_TIMEOUT 100
|
||||
@@ -40,86 +56,86 @@
|
||||
# define IS31FL3741_PWM_FREQUENCY IS31FL3741_PWM_FREQUENCY_29K_HZ
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3741_SW_PULLUP
|
||||
# define IS31FL3741_SW_PULLUP IS31FL3741_PUR_32K_OHM
|
||||
#ifndef IS31FL3741_SWPULLUP
|
||||
# define IS31FL3741_SWPULLUP IS31FL3741_PUR_32KR
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3741_CS_PULLDOWN
|
||||
# define IS31FL3741_CS_PULLDOWN IS31FL3741_PDR_32K_OHM
|
||||
#ifndef IS31FL3741_CSPULLUP
|
||||
# define IS31FL3741_CSPULLUP IS31FL3741_PUR_32KR
|
||||
#endif
|
||||
|
||||
#ifndef IS31FL3741_GLOBAL_CURRENT
|
||||
# define IS31FL3741_GLOBAL_CURRENT 0xFF
|
||||
#ifndef IS31FL3741_GLOBALCURRENT
|
||||
# define IS31FL3741_GLOBALCURRENT 0xFF
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20] = {0xFF};
|
||||
#define IS31FL3741_MAX_LEDS 351
|
||||
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20] = {0xFF};
|
||||
|
||||
// These buffers match the IS31FL3741 and IS31FL3741A PWM registers.
|
||||
// The scaling buffers match the page 2 and 3 LED On/Off registers.
|
||||
// The scaling buffers match the PG2 and PG3 LED On/Off registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in is31fl3741_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[IS31FL3741_DRIVER_COUNT][IS31FL3741_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[IS31FL3741_DRIVER_COUNT][IS31FL3741_MAX_LEDS];
|
||||
bool g_pwm_buffer_update_required[IS31FL3741_DRIVER_COUNT] = {false};
|
||||
bool g_scaling_registers_update_required[IS31FL3741_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_scaling_registers[IS31FL3741_DRIVER_COUNT][IS31FL3741_PWM_REGISTER_COUNT];
|
||||
uint8_t g_scaling_registers[IS31FL3741_DRIVER_COUNT][IS31FL3741_MAX_LEDS];
|
||||
|
||||
void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if IS31FL3741_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3741_select_page(uint8_t addr, uint8_t page) {
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND_WRITE_LOCK, IS31FL3741_COMMAND_WRITE_LOCK_MAGIC);
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// Assume page 0 is already selected
|
||||
// Assume PG0 is already selected
|
||||
|
||||
for (int i = 0; i < 342; i += 18) {
|
||||
if (i == 180) {
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_1);
|
||||
// unlock the command register and select PG1
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_PWM1);
|
||||
}
|
||||
|
||||
i2c_transfer_buffer[0] = i % 180;
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 18);
|
||||
g_twi_transfer_buffer[0] = i % 180;
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + i, 18);
|
||||
|
||||
#if IS31FL3741_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// transfer the left cause the total number is 351
|
||||
i2c_transfer_buffer[0] = 162;
|
||||
memcpy(i2c_transfer_buffer + 1, pwm_buffer + 342, 9);
|
||||
g_twi_transfer_buffer[0] = 162;
|
||||
memcpy(g_twi_transfer_buffer + 1, pwm_buffer + 342, 9);
|
||||
|
||||
#if IS31FL3741_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -127,36 +143,6 @@ bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void is31fl3741_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_1);
|
||||
#if defined(IS31FL3741_I2C_ADDRESS_2)
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_2);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_3)
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_3);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_4)
|
||||
is31fl3741_init(IS31FL3741_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < IS31FL3741_LED_COUNT; i++) {
|
||||
is31fl3741_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_1, 0);
|
||||
#if defined(IS31FL3741_I2C_ADDRESS_2)
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_2, 1);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_3)
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_3, 2);
|
||||
# if defined(IS31FL3741_I2C_ADDRESS_4)
|
||||
is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void is31fl3741_init(uint8_t addr) {
|
||||
// In order to avoid the LEDs being driven with garbage data
|
||||
// in the LED driver's PWM registers, shutdown is enabled last.
|
||||
@@ -164,17 +150,21 @@ void is31fl3741_init(uint8_t addr) {
|
||||
// then disable software shutdown.
|
||||
// Unlock the command register.
|
||||
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_FUNCTION);
|
||||
// Unlock the command register.
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
|
||||
// Select PG4
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_FUNCTION);
|
||||
|
||||
// Set to Normal operation
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_CONFIGURATION, IS31FL3741_CONFIGURATION);
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_CONFIGURATION, IS31FL3741_CONFIGURATION);
|
||||
|
||||
// Set Golbal Current Control Register
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3741_GLOBAL_CURRENT);
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_GLOBALCURRENT, IS31FL3741_GLOBALCURRENT);
|
||||
// Set Pull up & Down for SWx CSy
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PULLDOWNUP, ((IS31FL3741_CS_PULLDOWN << 4) | IS31FL3741_SW_PULLUP));
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_PULLDOWNUP, ((IS31FL3741_CSPULLUP << 4) | IS31FL3741_SWPULLUP));
|
||||
// Set PWM frequency
|
||||
is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3741_PWM_FREQUENCY & 0b1111));
|
||||
is31fl3741_write_register(addr, IS31FL3741_REG_PWM_FREQUENCY, (IS31FL3741_PWM_FREQUENCY & 0b1111));
|
||||
|
||||
// is31fl3741_update_led_scaling_registers(addr, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
@@ -184,7 +174,7 @@ void is31fl3741_init(uint8_t addr) {
|
||||
|
||||
void is31fl3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
is31fl3741_led_t led;
|
||||
if (index >= 0 && index < IS31FL3741_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.r] == red && g_pwm_buffer[led.driver][led.g] == green && g_pwm_buffer[led.driver][led.b] == blue) {
|
||||
@@ -198,7 +188,7 @@ void is31fl3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void is31fl3741_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < IS31FL3741_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
is31fl3741_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -230,7 +220,9 @@ void is31fl3741_set_led_control_register(uint8_t index, bool red, bool green, bo
|
||||
|
||||
void is31fl3741_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_0);
|
||||
// unlock the command register and select PG2
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_PWM0);
|
||||
|
||||
is31fl3741_write_pwm_buffer(addr, g_pwm_buffer[index]);
|
||||
}
|
||||
@@ -248,16 +240,20 @@ void is31fl3741_set_pwm_buffer(const is31fl3741_led_t *pled, uint8_t red, uint8_
|
||||
|
||||
void is31fl3741_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_scaling_registers_update_required[index]) {
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_0);
|
||||
// unlock the command register and select PG2
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_SCALING_0);
|
||||
|
||||
// CS1_SW1 to CS30_SW6 are on page 2
|
||||
// CS1_SW1 to CS30_SW6 are on PG2
|
||||
for (int i = CS1_SW1; i <= CS30_SW6; ++i) {
|
||||
is31fl3741_write_register(addr, i, g_scaling_registers[index][i]);
|
||||
}
|
||||
|
||||
is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_1);
|
||||
// unlock the command register and select PG3
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER_WRITELOCK, 0xC5);
|
||||
is31fl3741_write_register(addr, IS31FL3741_COMMANDREGISTER, IS31FL3741_PAGE_SCALING_1);
|
||||
|
||||
// CS1_SW7 to CS39_SW9 are on page 3
|
||||
// CS1_SW7 to CS39_SW9 are on PG3
|
||||
for (int i = CS1_SW7; i <= CS39_SW9; ++i) {
|
||||
is31fl3741_write_register(addr, i - CS1_SW7, g_scaling_registers[index][i]);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_ADDR_1
|
||||
@@ -37,6 +36,9 @@
|
||||
#ifdef DRIVER_ADDR_4
|
||||
# define IS31FL3741_I2C_ADDRESS_4 DRIVER_ADDR_4
|
||||
#endif
|
||||
#ifdef DRIVER_COUNT
|
||||
# define IS31FL3741_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef ISSI_TIMEOUT
|
||||
# define IS31FL3741_I2C_TIMEOUT ISSI_TIMEOUT
|
||||
#endif
|
||||
@@ -47,81 +49,44 @@
|
||||
# define IS31FL3741_CONFIGURATION ISSI_CONFIGURATION
|
||||
#endif
|
||||
#ifdef ISSI_SWPULLUP
|
||||
# define IS31FL3741_SW_PULLUP ISSI_SWPULLUP
|
||||
# define IS31FL3741_SWPULLUP ISSI_SWPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_CSPULLUP
|
||||
# define IS31FL3741_CS_PULLDOWN ISSI_CSPULLUP
|
||||
# define IS31FL3741_CSPULLUP ISSI_CSPULLUP
|
||||
#endif
|
||||
#ifdef ISSI_GLOBALCURRENT
|
||||
# define IS31FL3741_GLOBAL_CURRENT ISSI_GLOBALCURRENT
|
||||
# define IS31FL3741_GLOBALCURRENT ISSI_GLOBALCURRENT
|
||||
#endif
|
||||
|
||||
#define is31_led is31fl3741_led_t
|
||||
#define g_is31_leds g_is31fl3741_leds
|
||||
|
||||
#define PUR_0R IS31FL3741_PUR_0_OHM
|
||||
#define PUR_05KR IS31FL3741_PUR_0K5_OHM
|
||||
#define PUR_1KR IS31FL3741_PUR_1K_OHM
|
||||
#define PUR_2KR IS31FL3741_PUR_2K_OHM
|
||||
#define PUR_4KR IS31FL3741_PUR_4K_OHM
|
||||
#define PUR_8KR IS31FL3741_PUR_8K_OHM
|
||||
#define PUR_16KR IS31FL3741_PUR_16K_OHM
|
||||
#define PUR_32KR IS31FL3741_PUR_32K_OHM
|
||||
#define PUR_0R IS31FL3741_PUR_0R
|
||||
#define PUR_05KR IS31FL3741_PUR_05KR
|
||||
#define PUR_1KR IS31FL3741_PUR_1KR
|
||||
#define PUR_2KR IS31FL3741_PUR_2KR
|
||||
#define PUR_4KR IS31FL3741_PUR_4KR
|
||||
#define PUR_8KR IS31FL3741_PUR_8KR
|
||||
#define PUR_16KR IS31FL3741_PUR_16KR
|
||||
#define PUR_32KR IS31FL3741_PUR_32KR
|
||||
// ========
|
||||
|
||||
#define IS31FL3741_REG_INTERRUPT_MASK 0xF0
|
||||
#define IS31FL3741_REG_INTERRUPT_STATUS 0xF1
|
||||
#define IS31FL3741_REG_ID 0xFC
|
||||
|
||||
#define IS31FL3741_REG_COMMAND 0xFD
|
||||
|
||||
#define IS31FL3741_COMMAND_PWM_0 0x00
|
||||
#define IS31FL3741_COMMAND_PWM_1 0x01
|
||||
#define IS31FL3741_COMMAND_SCALING_0 0x02
|
||||
#define IS31FL3741_COMMAND_SCALING_1 0x03
|
||||
#define IS31FL3741_COMMAND_FUNCTION 0x04
|
||||
|
||||
#define IS31FL3741_FUNCTION_REG_CONFIGURATION 0x00
|
||||
#define IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT 0x01
|
||||
#define IS31FL3741_FUNCTION_REG_PULLDOWNUP 0x02
|
||||
#define IS31FL3741_FUNCTION_REG_PWM_FREQUENCY 0x36
|
||||
#define IS31FL3741_FUNCTION_REG_RESET 0x3F
|
||||
|
||||
#define IS31FL3741_REG_COMMAND_WRITE_LOCK 0xFE
|
||||
#define IS31FL3741_COMMAND_WRITE_LOCK_MAGIC 0xC5
|
||||
|
||||
#define IS31FL3741_I2C_ADDRESS_GND 0x30
|
||||
#define IS31FL3741_I2C_ADDRESS_SCL 0x31
|
||||
#define IS31FL3741_I2C_ADDRESS_SDA 0x32
|
||||
#define IS31FL3741_I2C_ADDRESS_VCC 0x33
|
||||
|
||||
#if defined(RGB_MATRIX_IS31FL3741)
|
||||
# define IS31FL3741_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(IS31FL3741_I2C_ADDRESS_4)
|
||||
# define IS31FL3741_DRIVER_COUNT 4
|
||||
#elif defined(IS31FL3741_I2C_ADDRESS_3)
|
||||
# define IS31FL3741_DRIVER_COUNT 3
|
||||
#elif defined(IS31FL3741_I2C_ADDRESS_2)
|
||||
# define IS31FL3741_DRIVER_COUNT 2
|
||||
#elif defined(IS31FL3741_I2C_ADDRESS_1)
|
||||
# define IS31FL3741_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct is31fl3741_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint16_t r : 9;
|
||||
uint16_t g : 9;
|
||||
uint16_t b : 9;
|
||||
} PACKED is31fl3741_led_t;
|
||||
uint32_t driver : 2;
|
||||
uint32_t r : 10;
|
||||
uint32_t g : 10;
|
||||
uint32_t b : 10;
|
||||
} __attribute__((packed)) is31fl3741_led_t;
|
||||
|
||||
extern const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT];
|
||||
extern const is31fl3741_led_t PROGMEM g_is31fl3741_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void is31fl3741_init_drivers(void);
|
||||
void is31fl3741_init(uint8_t addr);
|
||||
void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
void is31fl3741_select_page(uint8_t addr, uint8_t page);
|
||||
bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void is31fl3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
@@ -141,23 +106,14 @@ void is31fl3741_set_pwm_buffer(const is31fl3741_led_t *pled, uint8_t red, uint8_
|
||||
|
||||
void is31fl3741_flush(void);
|
||||
|
||||
#define IS31FL3741_PDR_0_OHM 0b000 // No pull-down resistor
|
||||
#define IS31FL3741_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3741_PDR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3741_PDR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3741_PDR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3741_PDR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3741_PDR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3741_PDR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
|
||||
#define IS31FL3741_PUR_0_OHM 0b000 // No pull-up resistor
|
||||
#define IS31FL3741_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor
|
||||
#define IS31FL3741_PUR_1K_OHM 0b010 // 1 kOhm resistor
|
||||
#define IS31FL3741_PUR_2K_OHM 0b011 // 2 kOhm resistor
|
||||
#define IS31FL3741_PUR_4K_OHM 0b100 // 4 kOhm resistor
|
||||
#define IS31FL3741_PUR_8K_OHM 0b101 // 8 kOhm resistor
|
||||
#define IS31FL3741_PUR_16K_OHM 0b110 // 16 kOhm resistor
|
||||
#define IS31FL3741_PUR_32K_OHM 0b111 // 32 kOhm resistor
|
||||
#define IS31FL3741_PUR_0R 0x00 // No PUR resistor
|
||||
#define IS31FL3741_PUR_05KR 0x01 // 0.5k Ohm resistor
|
||||
#define IS31FL3741_PUR_1KR 0x02 // 1.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_2KR 0x03 // 2.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_4KR 0x04 // 4.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_8KR 0x05 // 8.0k Ohm resistor
|
||||
#define IS31FL3741_PUR_16KR 0x06 // 16k Ohm resistor
|
||||
#define IS31FL3741_PUR_32KR 0x07 // 32k Ohm resistor
|
||||
|
||||
#define IS31FL3741_PWM_FREQUENCY_29K_HZ 0b0000
|
||||
#define IS31FL3741_PWM_FREQUENCY_3K6_HZ 0b0011
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
// Set defaults for Spread Spectrum Register
|
||||
#ifndef ISSI_SSR_1
|
||||
# ifndef DRIVER_ADDR_2
|
||||
# if DRIVER_COUNT == 1
|
||||
# define ISSI_SSR_1 0x00
|
||||
# else
|
||||
# define ISSI_SSR_1 0xC0
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
// Set defaults for Spread Spectrum Register
|
||||
#ifndef ISSI_SSR_1
|
||||
# ifndef DRIVER_ADDR_2
|
||||
# if DRIVER_COUNT == 1
|
||||
# define ISSI_SSR_1 0x00
|
||||
# else
|
||||
# define ISSI_SSR_1 0xC0
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
# define ISSI_PERSISTENCE 0
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the PWM & scaling registers.
|
||||
// Storing them like this is optimal for I2C transfers to the registers.
|
||||
@@ -44,15 +45,15 @@ bool g_scaling_buffer_update_required[DRIVER_COUNT] = {false};
|
||||
// For writing of single register entry
|
||||
void IS31FL_write_single_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
// Set register address and register data ready to write
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if ISSI_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, ISSI_TIMEOUT) == 0) break;
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) break;
|
||||
}
|
||||
#else
|
||||
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, ISSI_TIMEOUT);
|
||||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -63,18 +64,18 @@ bool IS31FL_write_multi_registers(uint8_t addr, uint8_t *source_buffer, uint8_t
|
||||
// Split the buffer into chunks to transfer
|
||||
for (int i = 0; i < buffer_size; i += transfer_size) {
|
||||
// Set the first entry of transfer buffer to the first register we want to write
|
||||
i2c_transfer_buffer[0] = i + start_reg_addr;
|
||||
g_twi_transfer_buffer[0] = i + start_reg_addr;
|
||||
// Copy the section of our source buffer into the transfer buffer after first register address
|
||||
memcpy(i2c_transfer_buffer + 1, source_buffer + i, transfer_size);
|
||||
memcpy(g_twi_transfer_buffer + 1, source_buffer + i, transfer_size);
|
||||
|
||||
#if ISSI_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, transfer_size + 1, ISSI_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, transfer_size + 1, ISSI_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, transfer_size + 1, ISSI_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, transfer_size + 1, ISSI_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -187,41 +188,6 @@ void IS31FL_common_flush(void) {
|
||||
}
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
void IS31FL_RGB_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
IS31FL_common_init(DRIVER_ADDR_1, ISSI_SSR_1);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
IS31FL_common_init(DRIVER_ADDR_2, ISSI_SSR_2);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
IS31FL_common_init(DRIVER_ADDR_3, ISSI_SSR_3);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
IS31FL_common_init(DRIVER_ADDR_4, ISSI_SSR_4);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
IS31FL_RGB_set_scaling_buffer(i, true, true, true);
|
||||
}
|
||||
|
||||
// This actually updates the LED drivers
|
||||
# ifdef ISSI_MANUAL_SCALING
|
||||
IS31FL_set_manual_scaling_buffer();
|
||||
# endif
|
||||
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_1, 0);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_2, 1);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_3, 2);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
// Colour is set by adjusting PWM register
|
||||
void IS31FL_RGB_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
@@ -265,41 +231,6 @@ void IS31FL_RGB_set_scaling_buffer(uint8_t index, bool red, bool green, bool blu
|
||||
|
||||
#elif defined(LED_MATRIX_ENABLE)
|
||||
// LED Matrix Specific scripts
|
||||
void IS31FL_simple_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
IS31FL_common_init(DRIVER_ADDR_1, ISSI_SSR_1);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
IS31FL_common_init(DRIVER_ADDR_2, ISSI_SSR_2);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
IS31FL_common_init(DRIVER_ADDR_3, ISSI_SSR_3);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
IS31FL_common_init(DRIVER_ADDR_4, ISSI_SSR_4);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
IS31FL_simple_set_scaling_buffer(i, true);
|
||||
}
|
||||
|
||||
// This actually updates the LED drivers
|
||||
# ifdef ISSI_MANUAL_SCALING
|
||||
IS31FL_set_manual_scaling_buffer();
|
||||
# endif
|
||||
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_1, 0);
|
||||
# if defined(DRIVER_ADDR_2)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_2, 1);
|
||||
# if defined(DRIVER_ADDR_3)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_3, 2);
|
||||
# if defined(DRIVER_ADDR_4)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
void IS31FL_simple_set_scaling_buffer(uint8_t index, bool value) {
|
||||
is31_led led;
|
||||
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// Which variant header file to use
|
||||
#if defined(LED_MATRIX_IS31FL3742A) || defined(RGB_MATRIX_IS31FL3742A)
|
||||
@@ -36,31 +35,21 @@
|
||||
# include "is31fl3746.h"
|
||||
#endif
|
||||
|
||||
#if defined DRIVER_ADDR_4
|
||||
# define DRIVER_COUNT 4
|
||||
#elif defined DRIVER_ADDR_3
|
||||
# define DRIVER_COUNT 3
|
||||
#elif defined DRIVER_ADDR_2
|
||||
# define DRIVER_COUNT 2
|
||||
#elif defined DRIVER_ADDR_1
|
||||
# define DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
typedef struct is31_led {
|
||||
uint8_t driver : 2;
|
||||
uint8_t driver;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED is31_led;
|
||||
} __attribute__((packed)) is31_led;
|
||||
|
||||
extern const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
#elif defined(LED_MATRIX_ENABLE)
|
||||
typedef struct is31_led {
|
||||
uint8_t driver : 2;
|
||||
uint8_t driver;
|
||||
uint8_t v;
|
||||
} PACKED is31_led;
|
||||
} __attribute__((packed)) is31_led;
|
||||
|
||||
extern const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT];
|
||||
#endif
|
||||
@@ -82,13 +71,11 @@ void IS31FL_common_flush(void);
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
// RGB Matrix Specific scripts
|
||||
void IS31FL_RGB_init_drivers(void);
|
||||
void IS31FL_RGB_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
void IS31FL_RGB_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||
void IS31FL_RGB_set_scaling_buffer(uint8_t index, bool red, bool green, bool blue);
|
||||
#elif defined(LED_MATRIX_ENABLE)
|
||||
// LED Matrix Specific scripts
|
||||
void IS31FL_simple_init_drivers(void);
|
||||
void IS31FL_simple_set_scaling_buffer(uint8_t index, bool value);
|
||||
void IS31FL_simple_set_brightness(int index, uint8_t value);
|
||||
void IS31FL_simple_set_brigntness_all(uint8_t value);
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
#include "snled27351-simple.h"
|
||||
#include "i2c_master.h"
|
||||
|
||||
#define SNLED27351_PWM_REGISTER_COUNT 192
|
||||
#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24
|
||||
|
||||
#ifndef SNLED27351_I2C_TIMEOUT
|
||||
# define SNLED27351_I2C_TIMEOUT 100
|
||||
#endif
|
||||
@@ -29,7 +26,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef SNLED27351_PHASE_CHANNEL
|
||||
# define SNLED27351_PHASE_CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL
|
||||
# define SNLED27351_PHASE_CHANNEL SNLED27351_MSKPHASE_12CHANNEL
|
||||
#endif
|
||||
|
||||
#ifndef SNLED27351_CURRENT_TUNE
|
||||
@@ -37,7 +34,8 @@
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[20];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
// These buffers match the SNLED27351 PWM registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
@@ -45,59 +43,55 @@ uint8_t i2c_transfer_buffer[20];
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in snled27351_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[SNLED27351_DRIVER_COUNT][SNLED27351_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[SNLED27351_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[SNLED27351_DRIVER_COUNT][SNLED27351_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[SNLED27351_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||
|
||||
bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
// If the transaction fails function returns false.
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if SNLED27351_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void snled27351_select_page(uint8_t addr, uint8_t page) {
|
||||
snled27351_write_register(addr, SNLED27351_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// Assumes PG1 is already selected.
|
||||
// If any of the transactions fails function returns false.
|
||||
// Transmit PWM registers in 12 transfers of 16 bytes.
|
||||
// i2c_transfer_buffer[] is 20 bytes
|
||||
// g_twi_transfer_buffer[] is 20 bytes
|
||||
|
||||
// Iterate over the pwm_buffer contents at 16 byte intervals.
|
||||
for (int i = 0; i < SNLED27351_PWM_REGISTER_COUNT; i += 16) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (int i = 0; i < 192; i += 16) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// Copy the data from i to i+15.
|
||||
// Device will auto-increment register for data after the first byte
|
||||
// Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
|
||||
for (int j = 0; j < 16; j++) {
|
||||
i2c_transfer_buffer[1 + j] = pwm_buffer[i + j];
|
||||
g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
|
||||
}
|
||||
|
||||
#if SNLED27351_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -105,87 +99,55 @@ bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void snled27351_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_1);
|
||||
#if defined(SNLED27351_I2C_ADDRESS_2)
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_2);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_3)
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_3);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_4)
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < SNLED27351_LED_COUNT; i++) {
|
||||
snled27351_set_led_control_register(i, true);
|
||||
}
|
||||
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_1, 0);
|
||||
#if defined(SNLED27351_I2C_ADDRESS_2)
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_2, 1);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_3)
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_3, 2);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_4)
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void snled27351_init(uint8_t addr) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to shutdown mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_SHUT_DOWN_MODE);
|
||||
// Setting internal channel pulldown/pullup
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_PULLDOWNUP, SNLED27351_PULLDOWNUP_ALL_ENABLED);
|
||||
snled27351_write_register(addr, SNLED27351_REG_PDU, SNLED27351_MSKSET_CA_CB_CHANNEL);
|
||||
// Select number of scan phase
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SCAN_PHASE, SNLED27351_PHASE_CHANNEL);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SCAN_PHASE, SNLED27351_PHASE_CHANNEL);
|
||||
// Setting PWM Delay Phase
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1, SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SLEW_RATE_CONTROL_MODE1, SNLED27351_MSKPWM_DELAY_PHASE_ENABLE);
|
||||
// Setting Driving/Sinking Channel Slew Rate
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2, SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE | SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SLEW_RATE_CONTROL_MODE2, SNLED27351_MSKDRIVING_SINKING_CHANNEL_SLEWRATE_ENABLE);
|
||||
// Setting Iref
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, 0);
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL);
|
||||
|
||||
snled27351_write_register(addr, SNLED27351_REG_SOFTWARE_SLEEP, SNLED27351_MSKSLEEP_DISABLE);
|
||||
// Set LED CONTROL PAGE (Page 0)
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_CONTROL_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_PWM);
|
||||
|
||||
// Set PWM PAGE (Page 1)
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_PWM_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_CURRENT_TUNE);
|
||||
|
||||
// Set CURRENT PAGE (Page 4)
|
||||
uint8_t current_tune_reg_list[SNLED27351_LED_CURRENT_TUNE_LENGTH] = SNLED27351_CURRENT_TUNE;
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_CURRENT_TUNE_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, current_tune_reg_list[i]);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL);
|
||||
|
||||
// Enable LEDs ON/OFF
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_CONTROL_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, 0xFF);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to normal mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_NORMAL_MODE);
|
||||
}
|
||||
|
||||
void snled27351_set_value(int index, uint8_t value) {
|
||||
snled27351_led_t led;
|
||||
if (index >= 0 && index < SNLED27351_LED_COUNT) {
|
||||
if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_snled27351_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.v] == value) {
|
||||
@@ -197,7 +159,7 @@ void snled27351_set_value(int index, uint8_t value) {
|
||||
}
|
||||
|
||||
void snled27351_set_value_all(uint8_t value) {
|
||||
for (int i = 0; i < SNLED27351_LED_COUNT; i++) {
|
||||
for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
|
||||
snled27351_set_value(i, value);
|
||||
}
|
||||
}
|
||||
@@ -220,7 +182,7 @@ void snled27351_set_led_control_register(uint8_t index, bool value) {
|
||||
|
||||
void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_PWM);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_PWM_PAGE);
|
||||
|
||||
// If any of the transactions fail we risk writing dirty PG0,
|
||||
// refresh page 0 just in case.
|
||||
@@ -233,9 +195,8 @@ void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < SNLED27351_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_CONTROL_PAGE);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
snled27351_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
}
|
||||
@@ -256,17 +217,17 @@ void snled27351_flush(void) {
|
||||
}
|
||||
|
||||
void snled27351_sw_return_normal(uint8_t addr) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to normal mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_NORMAL_MODE);
|
||||
}
|
||||
|
||||
void snled27351_sw_shutdown(uint8_t addr) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to shutdown mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_SHUT_DOWN_MODE);
|
||||
// Write SW Sleep Register
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, SNLED27351_SOFTWARE_SLEEP_ENABLE);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SOFTWARE_SLEEP, SNLED27351_MSKSLEEP_ENABLE);
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_COUNT
|
||||
# define SNLED27351_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef CKLED2001_TIMEOUT
|
||||
# define SNLED27351_I2C_TIMEOUT CKLED2001_TIMEOUT
|
||||
#endif
|
||||
@@ -35,72 +37,116 @@
|
||||
# define SNLED27351_CURRENT_TUNE CKLED2001_CURRENT_TUNE
|
||||
#endif
|
||||
|
||||
#define MSKPHASE_12CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL
|
||||
#define MSKPHASE_11CHANNEL SNLED27351_SCAN_PHASE_11_CHANNEL
|
||||
#define MSKPHASE_10CHANNEL SNLED27351_SCAN_PHASE_10_CHANNEL
|
||||
#define MSKPHASE_9CHANNEL SNLED27351_SCAN_PHASE_9_CHANNEL
|
||||
#define MSKPHASE_8CHANNEL SNLED27351_SCAN_PHASE_8_CHANNEL
|
||||
#define MSKPHASE_7CHANNEL SNLED27351_SCAN_PHASE_7_CHANNEL
|
||||
#define MSKPHASE_6CHANNEL SNLED27351_SCAN_PHASE_6_CHANNEL
|
||||
#define MSKPHASE_5CHANNEL SNLED27351_SCAN_PHASE_5_CHANNEL
|
||||
#define MSKPHASE_4CHANNEL SNLED27351_SCAN_PHASE_4_CHANNEL
|
||||
#define MSKPHASE_3CHANNEL SNLED27351_SCAN_PHASE_3_CHANNEL
|
||||
#define MSKPHASE_2CHANNEL SNLED27351_SCAN_PHASE_2_CHANNEL
|
||||
#define MSKPHASE_1CHANNEL SNLED27351_SCAN_PHASE_1_CHANNEL
|
||||
#define MSKPHASE_12CHANNEL SNLED27351_MSKPHASE_12CHANNEL
|
||||
#define MSKPHASE_11CHANNEL SNLED27351_MSKPHASE_11CHANNEL
|
||||
#define MSKPHASE_10CHANNEL SNLED27351_MSKPHASE_10CHANNEL
|
||||
#define MSKPHASE_9CHANNEL SNLED27351_MSKPHASE_9CHANNEL
|
||||
#define MSKPHASE_8CHANNEL SNLED27351_MSKPHASE_8CHANNEL
|
||||
#define MSKPHASE_7CHANNEL SNLED27351_MSKPHASE_7CHANNEL
|
||||
#define MSKPHASE_6CHANNEL SNLED27351_MSKPHASE_6CHANNEL
|
||||
#define MSKPHASE_5CHANNEL SNLED27351_MSKPHASE_5CHANNEL
|
||||
#define MSKPHASE_4CHANNEL SNLED27351_MSKPHASE_4CHANNEL
|
||||
#define MSKPHASE_3CHANNEL SNLED27351_MSKPHASE_3CHANNEL
|
||||
#define MSKPHASE_2CHANNEL SNLED27351_MSKPHASE_2CHANNEL
|
||||
#define MSKPHASE_1CHANNEL SNLED27351_MSKPHASE_1CHANNEL
|
||||
|
||||
#define ckled2001_led snled27351_led_t
|
||||
#define g_ckled2001_leds g_snled27351_leds
|
||||
// ========
|
||||
|
||||
#define SNLED27351_REG_COMMAND 0xFD
|
||||
#define SNLED27351_COMMAND_LED_CONTROL 0x00
|
||||
#define SNLED27351_COMMAND_PWM 0x01
|
||||
#define SNLED27351_COMMAND_FUNCTION 0x03
|
||||
#define SNLED27351_COMMAND_CURRENT_TUNE 0x04
|
||||
#define SNLED27351_I2C_ADDRESS_GND 0x74
|
||||
#define SNLED27351_I2C_ADDRESS_SCL 0x75
|
||||
#define SNLED27351_I2C_ADDRESS_SDA 0x76
|
||||
#define SNLED27351_I2C_ADDRESS_VDDIO 0x77
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN 0x00
|
||||
#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN (0x0 << 0)
|
||||
#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL (0x1 << 0)
|
||||
typedef struct snled27351_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t v;
|
||||
} __attribute__((packed)) snled27351_led_t;
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_ID 0x11
|
||||
extern const snled27351_led_t PROGMEM g_snled27351_leds[LED_MATRIX_LED_COUNT];
|
||||
|
||||
void snled27351_init(uint8_t addr);
|
||||
bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void snled27351_set_value(int index, uint8_t value);
|
||||
void snled27351_set_value_all(uint8_t value);
|
||||
|
||||
void snled27351_set_led_control_register(uint8_t index, bool value);
|
||||
|
||||
// This should not be called from an interrupt
|
||||
// (eg. from a timer interrupt).
|
||||
// Call this while idle (in between matrix scans).
|
||||
// If the buffer is dirty, it will update the driver with the buffer.
|
||||
void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index);
|
||||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void snled27351_flush(void);
|
||||
|
||||
void snled27351_sw_return_normal(uint8_t addr);
|
||||
void snled27351_sw_shutdown(uint8_t addr);
|
||||
|
||||
// Registers Page Define
|
||||
#define SNLED27351_REG_CONFIGURE_CMD_PAGE 0xFD
|
||||
#define SNLED27351_LED_CONTROL_PAGE 0x00
|
||||
#define SNLED27351_LED_PWM_PAGE 0x01
|
||||
#define SNLED27351_FUNCTION_PAGE 0x03
|
||||
#define SNLED27351_CURRENT_TUNE_PAGE 0x04
|
||||
|
||||
// Function Register: address 0x00
|
||||
#define SNLED27351_REG_CONFIGURATION 0x00
|
||||
#define SNLED27351_MSKSW_SHUT_DOWN_MODE (0x0 << 0)
|
||||
#define SNLED27351_MSKSW_NORMAL_MODE (0x1 << 0)
|
||||
|
||||
#define SNLED27351_REG_DRIVER_ID 0x11
|
||||
#define SNLED27351_DRIVER_ID 0x8A
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_PULLDOWNUP 0x13
|
||||
#define SNLED27351_PULLDOWNUP_ALL_ENABLED 0xAA
|
||||
#define SNLED27351_REG_PDU 0x13
|
||||
#define SNLED27351_MSKSET_CA_CB_CHANNEL 0xAA
|
||||
#define SNLED27351_MSKCLR_CA_CB_CHANNEL 0x00
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SCAN_PHASE 0x14
|
||||
#define SNLED27351_SCAN_PHASE_12_CHANNEL 0x00
|
||||
#define SNLED27351_SCAN_PHASE_11_CHANNEL 0x01
|
||||
#define SNLED27351_SCAN_PHASE_10_CHANNEL 0x02
|
||||
#define SNLED27351_SCAN_PHASE_9_CHANNEL 0x03
|
||||
#define SNLED27351_SCAN_PHASE_8_CHANNEL 0x04
|
||||
#define SNLED27351_SCAN_PHASE_7_CHANNEL 0x05
|
||||
#define SNLED27351_SCAN_PHASE_6_CHANNEL 0x06
|
||||
#define SNLED27351_SCAN_PHASE_5_CHANNEL 0x07
|
||||
#define SNLED27351_SCAN_PHASE_4_CHANNEL 0x08
|
||||
#define SNLED27351_SCAN_PHASE_3_CHANNEL 0x09
|
||||
#define SNLED27351_SCAN_PHASE_2_CHANNEL 0x0A
|
||||
#define SNLED27351_SCAN_PHASE_1_CHANNEL 0x0B
|
||||
#define SNLED27351_REG_SCAN_PHASE 0x14
|
||||
#define SNLED27351_MSKPHASE_12CHANNEL 0x00
|
||||
#define SNLED27351_MSKPHASE_11CHANNEL 0x01
|
||||
#define SNLED27351_MSKPHASE_10CHANNEL 0x02
|
||||
#define SNLED27351_MSKPHASE_9CHANNEL 0x03
|
||||
#define SNLED27351_MSKPHASE_8CHANNEL 0x04
|
||||
#define SNLED27351_MSKPHASE_7CHANNEL 0x05
|
||||
#define SNLED27351_MSKPHASE_6CHANNEL 0x06
|
||||
#define SNLED27351_MSKPHASE_5CHANNEL 0x07
|
||||
#define SNLED27351_MSKPHASE_4CHANNEL 0x08
|
||||
#define SNLED27351_MSKPHASE_3CHANNEL 0x09
|
||||
#define SNLED27351_MSKPHASE_2CHANNEL 0x0A
|
||||
#define SNLED27351_MSKPHASE_1CHANNEL 0x0B
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1 0x15
|
||||
#define SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE (0b1 << 2)
|
||||
#define SNLED27351_REG_SLEW_RATE_CONTROL_MODE1 0x15
|
||||
#define SNLED27351_MSKPWM_DELAY_PHASE_ENABLE 0x04
|
||||
#define SNLED27351_MSKPWM_DELAY_PHASE_DISABLE 0x00
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2 0x16
|
||||
#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE (0b1 << 6)
|
||||
#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE (0b1 << 7)
|
||||
#define SNLED27351_REG_SLEW_RATE_CONTROL_MODE2 0x16
|
||||
#define SNLED27351_MSKDRIVING_SINKING_CHANNEL_SLEWRATE_ENABLE 0xC0
|
||||
#define SNLED27351_MSKDRIVING_SINKING_CHANNEL_SLEWRATE_DISABLE 0x00
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_OPEN_SHORT_ENABLE 0x17
|
||||
#define SNLED27351_OPEN_SHORT_ENABLE_SDS_ENABLE (0b1 << 6)
|
||||
#define SNLED27351_OPEN_SHORT_ENABLE_ODS_ENABLE (0b1 << 7)
|
||||
#define SNLED27351_REG_OPEN_SHORT_ENABLE 0x17
|
||||
#define SNLED27351_MSKOPEN_DETECTION_ENABLE (0x01 << 7)
|
||||
#define SNLED27351_MSKOPEN_DETECTION_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_OPEN_SHORT_DUTY 0x18
|
||||
#define SNLED27351_MSKSHORT_DETECTION_ENABLE (0x01 << 6)
|
||||
#define SNLED27351_MSKSHORT_DETECTION_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_OPEN_SHORT_FLAG 0x19
|
||||
#define SNLED27351_OPEN_SHORT_FLAG_OSINT_ENABLE (0b1 << 6)
|
||||
#define SNLED27351_OPEN_SHORT_FLAG_ODINT_ENABLE (0b1 << 7)
|
||||
#define SNLED27351_REG_OPEN_SHORT_DUTY 0x18
|
||||
#define SNLED27351_REG_OPEN_SHORT_FLAG 0x19
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP 0x1A
|
||||
#define SNLED27351_SOFTWARE_SLEEP_ENABLE (0b1 << 1)
|
||||
#define SNLED27351_MSKOPEN_DETECTION_INTERRUPT_ENABLE (0x01 << 7)
|
||||
#define SNLED27351_MSKOPEN_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_MSKSHORT_DETECTION_INTERRUPT_ENABLE (0x01 << 6)
|
||||
#define SNLED27351_MSKSHORT_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_REG_SOFTWARE_SLEEP 0x1A
|
||||
#define SNLED27351_MSKSLEEP_ENABLE 0x02
|
||||
#define SNLED27351_MSKSLEEP_DISABLE 0x00
|
||||
|
||||
// LED Control Registers
|
||||
#define SNLED27351_LED_CONTROL_ON_OFF_FIRST_ADDR 0x0
|
||||
@@ -127,55 +173,6 @@
|
||||
#define SNLED27351_LED_CURRENT_TUNE_LAST_ADDR 0x0B
|
||||
#define SNLED27351_LED_CURRENT_TUNE_LENGTH 0x0C
|
||||
|
||||
#define SNLED27351_I2C_ADDRESS_GND 0x74
|
||||
#define SNLED27351_I2C_ADDRESS_SCL 0x75
|
||||
#define SNLED27351_I2C_ADDRESS_SDA 0x76
|
||||
#define SNLED27351_I2C_ADDRESS_VDDIO 0x77
|
||||
|
||||
#if defined(LED_MATRIX_SNLED27351)
|
||||
# define SNLED27351_LED_COUNT LED_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(SNLED27351_I2C_ADDRESS_4)
|
||||
# define SNLED27351_DRIVER_COUNT 4
|
||||
#elif defined(SNLED27351_I2C_ADDRESS_3)
|
||||
# define SNLED27351_DRIVER_COUNT 3
|
||||
#elif defined(SNLED27351_I2C_ADDRESS_2)
|
||||
# define SNLED27351_DRIVER_COUNT 2
|
||||
#elif defined(SNLED27351_I2C_ADDRESS_1)
|
||||
# define SNLED27351_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct snled27351_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t v;
|
||||
} PACKED snled27351_led_t;
|
||||
|
||||
extern const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT];
|
||||
|
||||
void snled27351_init_drivers(void);
|
||||
void snled27351_init(uint8_t addr);
|
||||
void snled27351_select_page(uint8_t addr, uint8_t page);
|
||||
bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void snled27351_set_value(int index, uint8_t value);
|
||||
void snled27351_set_value_all(uint8_t value);
|
||||
|
||||
void snled27351_set_led_control_register(uint8_t index, bool value);
|
||||
|
||||
// This should not be called from an interrupt
|
||||
// (eg. from a timer interrupt).
|
||||
// Call this while idle (in between matrix scans).
|
||||
// If the buffer is dirty, it will update the driver with the buffer.
|
||||
void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index);
|
||||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void snled27351_flush(void);
|
||||
|
||||
void snled27351_sw_return_normal(uint8_t addr);
|
||||
void snled27351_sw_shutdown(uint8_t addr);
|
||||
|
||||
#define A_1 0x00
|
||||
#define A_2 0x01
|
||||
#define A_3 0x02
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
#include "snled27351.h"
|
||||
#include "i2c_master.h"
|
||||
|
||||
#define SNLED27351_PWM_REGISTER_COUNT 192
|
||||
#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24
|
||||
|
||||
#ifndef SNLED27351_I2C_TIMEOUT
|
||||
# define SNLED27351_I2C_TIMEOUT 100
|
||||
#endif
|
||||
@@ -29,7 +26,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef SNLED27351_PHASE_CHANNEL
|
||||
# define SNLED27351_PHASE_CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL
|
||||
# define SNLED27351_PHASE_CHANNEL SNLED27351_MSKPHASE_12CHANNEL
|
||||
#endif
|
||||
|
||||
#ifndef SNLED27351_CURRENT_TUNE
|
||||
@@ -37,7 +34,8 @@
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||
#endif
|
||||
|
||||
uint8_t i2c_transfer_buffer[65];
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[65];
|
||||
|
||||
// These buffers match the SNLED27351 PWM registers.
|
||||
// The control buffers match the PG0 LED On/Off registers.
|
||||
@@ -45,58 +43,54 @@ uint8_t i2c_transfer_buffer[65];
|
||||
// We could optimize this and take out the unused registers from these
|
||||
// buffers and the transfers in snled27351_write_pwm_buffer() but it's
|
||||
// probably not worth the extra complexity.
|
||||
uint8_t g_pwm_buffer[SNLED27351_DRIVER_COUNT][SNLED27351_PWM_REGISTER_COUNT];
|
||||
uint8_t g_pwm_buffer[SNLED27351_DRIVER_COUNT][192];
|
||||
bool g_pwm_buffer_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||
|
||||
uint8_t g_led_control_registers[SNLED27351_DRIVER_COUNT][SNLED27351_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||
bool g_led_control_registers_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||
uint8_t g_led_control_registers[SNLED27351_DRIVER_COUNT][24] = {0};
|
||||
bool g_led_control_registers_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||
|
||||
bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
// If the transaction fails function returns false.
|
||||
i2c_transfer_buffer[0] = reg;
|
||||
i2c_transfer_buffer[1] = data;
|
||||
g_twi_transfer_buffer[0] = reg;
|
||||
g_twi_transfer_buffer[1] = data;
|
||||
|
||||
#if SNLED27351_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void snled27351_select_page(uint8_t addr, uint8_t page) {
|
||||
snled27351_write_register(addr, SNLED27351_REG_COMMAND, page);
|
||||
}
|
||||
|
||||
bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
// Assumes PG1 is already selected.
|
||||
// If any of the transactions fails function returns false.
|
||||
// Transmit PWM registers in 3 transfers of 64 bytes.
|
||||
|
||||
// Iterate over the pwm_buffer contents at 64 byte intervals.
|
||||
for (uint8_t i = 0; i < SNLED27351_PWM_REGISTER_COUNT; i += 64) {
|
||||
i2c_transfer_buffer[0] = i;
|
||||
for (uint8_t i = 0; i < 192; i += 64) {
|
||||
g_twi_transfer_buffer[0] = i;
|
||||
// Copy the data from i to i+63.
|
||||
// Device will auto-increment register for data after the first byte
|
||||
// Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
|
||||
for (uint8_t j = 0; j < 64; j++) {
|
||||
i2c_transfer_buffer[1 + j] = pwm_buffer[i + j];
|
||||
g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
|
||||
}
|
||||
|
||||
#if SNLED27351_I2C_PERSISTENCE > 0
|
||||
for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) {
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 65, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 65, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 65, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 65, SNLED27351_I2C_TIMEOUT) != 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -104,86 +98,55 @@ bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void snled27351_init_drivers(void) {
|
||||
i2c_init();
|
||||
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_1);
|
||||
#if defined(SNLED27351_I2C_ADDRESS_2)
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_2);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_3)
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_3);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_4)
|
||||
snled27351_init(SNLED27351_I2C_ADDRESS_4);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < SNLED27351_LED_COUNT; i++) {
|
||||
snled27351_set_led_control_register(i, true, true, true);
|
||||
}
|
||||
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_1, 0);
|
||||
#if defined(SNLED27351_I2C_ADDRESS_2)
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_2, 1);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_3)
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_3, 2);
|
||||
# if defined(SNLED27351_I2C_ADDRESS_4)
|
||||
snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void snled27351_init(uint8_t addr) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to shutdown mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_SHUT_DOWN_MODE);
|
||||
// Setting internal channel pulldown/pullup
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_PULLDOWNUP, SNLED27351_PULLDOWNUP_ALL_ENABLED);
|
||||
snled27351_write_register(addr, SNLED27351_REG_PDU, SNLED27351_MSKSET_CA_CB_CHANNEL);
|
||||
// Select number of scan phase
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SCAN_PHASE, SNLED27351_PHASE_CHANNEL);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SCAN_PHASE, SNLED27351_PHASE_CHANNEL);
|
||||
// Setting PWM Delay Phase
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1, SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SLEW_RATE_CONTROL_MODE1, SNLED27351_MSKPWM_DELAY_PHASE_ENABLE);
|
||||
// Setting Driving/Sinking Channel Slew Rate
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2, SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE | SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SLEW_RATE_CONTROL_MODE2, SNLED27351_MSKDRIVING_SINKING_CHANNEL_SLEWRATE_ENABLE);
|
||||
// Setting Iref
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, 0);
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL);
|
||||
|
||||
snled27351_write_register(addr, SNLED27351_REG_SOFTWARE_SLEEP, SNLED27351_MSKSLEEP_DISABLE);
|
||||
// Set LED CONTROL PAGE (Page 0)
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_CONTROL_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_PWM);
|
||||
|
||||
// Set PWM PAGE (Page 1)
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_PWM_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, 0x00);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_CURRENT_TUNE);
|
||||
|
||||
// Set CURRENT PAGE (Page 4)
|
||||
uint8_t current_tune_reg_list[SNLED27351_LED_CURRENT_TUNE_LENGTH] = SNLED27351_CURRENT_TUNE;
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_CURRENT_TUNE_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, current_tune_reg_list[i]);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL);
|
||||
|
||||
// Enable LEDs ON/OFF
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_CONTROL_PAGE);
|
||||
for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) {
|
||||
snled27351_write_register(addr, i, 0xFF);
|
||||
}
|
||||
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to normal mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_NORMAL_MODE);
|
||||
}
|
||||
|
||||
void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
snled27351_led_t led;
|
||||
if (index >= 0 && index < SNLED27351_LED_COUNT) {
|
||||
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
|
||||
memcpy_P(&led, (&g_snled27351_leds[index]), sizeof(led));
|
||||
|
||||
if (g_pwm_buffer[led.driver][led.r] == red && g_pwm_buffer[led.driver][led.g] == green && g_pwm_buffer[led.driver][led.b] == blue) {
|
||||
@@ -197,7 +160,7 @@ void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
}
|
||||
|
||||
void snled27351_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int i = 0; i < SNLED27351_LED_COUNT; i++) {
|
||||
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
|
||||
snled27351_set_color(i, red, green, blue);
|
||||
}
|
||||
}
|
||||
@@ -234,7 +197,7 @@ void snled27351_set_led_control_register(uint8_t index, bool red, bool green, bo
|
||||
|
||||
void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
if (g_pwm_buffer_update_required[index]) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_PWM);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_PWM_PAGE);
|
||||
|
||||
// If any of the transactions fail we risk writing dirty PG0,
|
||||
// refresh page 0 just in case.
|
||||
@@ -247,9 +210,8 @@ void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index) {
|
||||
|
||||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index) {
|
||||
if (g_led_control_registers_update_required[index]) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL);
|
||||
|
||||
for (int i = 0; i < SNLED27351_LED_CONTROL_REGISTER_COUNT; i++) {
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_LED_CONTROL_PAGE);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
snled27351_write_register(addr, i, g_led_control_registers[index][i]);
|
||||
}
|
||||
}
|
||||
@@ -270,17 +232,17 @@ void snled27351_flush(void) {
|
||||
}
|
||||
|
||||
void snled27351_sw_return_normal(uint8_t addr) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to normal mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_NORMAL_MODE);
|
||||
}
|
||||
|
||||
void snled27351_sw_shutdown(uint8_t addr) {
|
||||
snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION);
|
||||
|
||||
// Select to function page
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURE_CMD_PAGE, SNLED27351_FUNCTION_PAGE);
|
||||
// Setting LED driver to shutdown mode
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN);
|
||||
snled27351_write_register(addr, SNLED27351_REG_CONFIGURATION, SNLED27351_MSKSW_SHUT_DOWN_MODE);
|
||||
// Write SW Sleep Register
|
||||
snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, SNLED27351_SOFTWARE_SLEEP_ENABLE);
|
||||
snled27351_write_register(addr, SNLED27351_REG_SOFTWARE_SLEEP, SNLED27351_MSKSLEEP_ENABLE);
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.h"
|
||||
#include "util.h"
|
||||
|
||||
// ======== DEPRECATED DEFINES - DO NOT USE ========
|
||||
#ifdef DRIVER_COUNT
|
||||
# define SNLED27351_DRIVER_COUNT DRIVER_COUNT
|
||||
#endif
|
||||
#ifdef DRIVER_ADDR_1
|
||||
# define SNLED27351_I2C_ADDRESS_1 DRIVER_ADDR_1
|
||||
#endif
|
||||
@@ -47,72 +49,118 @@
|
||||
# define SNLED27351_CURRENT_TUNE CKLED2001_CURRENT_TUNE
|
||||
#endif
|
||||
|
||||
#define MSKPHASE_12CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL
|
||||
#define MSKPHASE_11CHANNEL SNLED27351_SCAN_PHASE_11_CHANNEL
|
||||
#define MSKPHASE_10CHANNEL SNLED27351_SCAN_PHASE_10_CHANNEL
|
||||
#define MSKPHASE_9CHANNEL SNLED27351_SCAN_PHASE_9_CHANNEL
|
||||
#define MSKPHASE_8CHANNEL SNLED27351_SCAN_PHASE_8_CHANNEL
|
||||
#define MSKPHASE_7CHANNEL SNLED27351_SCAN_PHASE_7_CHANNEL
|
||||
#define MSKPHASE_6CHANNEL SNLED27351_SCAN_PHASE_6_CHANNEL
|
||||
#define MSKPHASE_5CHANNEL SNLED27351_SCAN_PHASE_5_CHANNEL
|
||||
#define MSKPHASE_4CHANNEL SNLED27351_SCAN_PHASE_4_CHANNEL
|
||||
#define MSKPHASE_3CHANNEL SNLED27351_SCAN_PHASE_3_CHANNEL
|
||||
#define MSKPHASE_2CHANNEL SNLED27351_SCAN_PHASE_2_CHANNEL
|
||||
#define MSKPHASE_1CHANNEL SNLED27351_SCAN_PHASE_1_CHANNEL
|
||||
#define MSKPHASE_12CHANNEL SNLED27351_MSKPHASE_12CHANNEL
|
||||
#define MSKPHASE_11CHANNEL SNLED27351_MSKPHASE_11CHANNEL
|
||||
#define MSKPHASE_10CHANNEL SNLED27351_MSKPHASE_10CHANNEL
|
||||
#define MSKPHASE_9CHANNEL SNLED27351_MSKPHASE_9CHANNEL
|
||||
#define MSKPHASE_8CHANNEL SNLED27351_MSKPHASE_8CHANNEL
|
||||
#define MSKPHASE_7CHANNEL SNLED27351_MSKPHASE_7CHANNEL
|
||||
#define MSKPHASE_6CHANNEL SNLED27351_MSKPHASE_6CHANNEL
|
||||
#define MSKPHASE_5CHANNEL SNLED27351_MSKPHASE_5CHANNEL
|
||||
#define MSKPHASE_4CHANNEL SNLED27351_MSKPHASE_4CHANNEL
|
||||
#define MSKPHASE_3CHANNEL SNLED27351_MSKPHASE_3CHANNEL
|
||||
#define MSKPHASE_2CHANNEL SNLED27351_MSKPHASE_2CHANNEL
|
||||
#define MSKPHASE_1CHANNEL SNLED27351_MSKPHASE_1CHANNEL
|
||||
|
||||
#define ckled2001_led snled27351_led_t
|
||||
#define g_ckled2001_leds g_snled27351_leds
|
||||
// ========
|
||||
|
||||
#define SNLED27351_REG_COMMAND 0xFD
|
||||
#define SNLED27351_COMMAND_LED_CONTROL 0x00
|
||||
#define SNLED27351_COMMAND_PWM 0x01
|
||||
#define SNLED27351_COMMAND_FUNCTION 0x03
|
||||
#define SNLED27351_COMMAND_CURRENT_TUNE 0x04
|
||||
#define SNLED27351_I2C_ADDRESS_GND 0x74
|
||||
#define SNLED27351_I2C_ADDRESS_SCL 0x75
|
||||
#define SNLED27351_I2C_ADDRESS_SDA 0x76
|
||||
#define SNLED27351_I2C_ADDRESS_VDDIO 0x77
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN 0x00
|
||||
#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN (0x0 << 0)
|
||||
#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL (0x1 << 0)
|
||||
typedef struct snled27351_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} __attribute__((packed)) snled27351_led_t;
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_ID 0x11
|
||||
extern const snled27351_led_t PROGMEM g_snled27351_leds[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
void snled27351_init(uint8_t addr);
|
||||
bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
void snled27351_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
void snled27351_set_led_control_register(uint8_t index, bool red, bool green, bool blue);
|
||||
|
||||
// This should not be called from an interrupt
|
||||
// (eg. from a timer interrupt).
|
||||
// Call this while idle (in between matrix scans).
|
||||
// If the buffer is dirty, it will update the driver with the buffer.
|
||||
void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index);
|
||||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void snled27351_flush(void);
|
||||
|
||||
void snled27351_sw_return_normal(uint8_t addr);
|
||||
void snled27351_sw_shutdown(uint8_t addr);
|
||||
|
||||
// Registers Page Define
|
||||
#define SNLED27351_REG_CONFIGURE_CMD_PAGE 0xFD
|
||||
#define SNLED27351_LED_CONTROL_PAGE 0x00
|
||||
#define SNLED27351_LED_PWM_PAGE 0x01
|
||||
#define SNLED27351_FUNCTION_PAGE 0x03
|
||||
#define SNLED27351_CURRENT_TUNE_PAGE 0x04
|
||||
|
||||
// Function Register: address 0x00
|
||||
#define SNLED27351_REG_CONFIGURATION 0x00
|
||||
#define SNLED27351_MSKSW_SHUT_DOWN_MODE (0x0 << 0)
|
||||
#define SNLED27351_MSKSW_NORMAL_MODE (0x1 << 0)
|
||||
|
||||
#define SNLED27351_REG_DRIVER_ID 0x11
|
||||
#define SNLED27351_DRIVER_ID 0x8A
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_PULLDOWNUP 0x13
|
||||
#define SNLED27351_PULLDOWNUP_ALL_ENABLED 0xAA
|
||||
#define SNLED27351_REG_PDU 0x13
|
||||
#define SNLED27351_MSKSET_CA_CB_CHANNEL 0xAA
|
||||
#define SNLED27351_MSKCLR_CA_CB_CHANNEL 0x00
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SCAN_PHASE 0x14
|
||||
#define SNLED27351_SCAN_PHASE_12_CHANNEL 0x00
|
||||
#define SNLED27351_SCAN_PHASE_11_CHANNEL 0x01
|
||||
#define SNLED27351_SCAN_PHASE_10_CHANNEL 0x02
|
||||
#define SNLED27351_SCAN_PHASE_9_CHANNEL 0x03
|
||||
#define SNLED27351_SCAN_PHASE_8_CHANNEL 0x04
|
||||
#define SNLED27351_SCAN_PHASE_7_CHANNEL 0x05
|
||||
#define SNLED27351_SCAN_PHASE_6_CHANNEL 0x06
|
||||
#define SNLED27351_SCAN_PHASE_5_CHANNEL 0x07
|
||||
#define SNLED27351_SCAN_PHASE_4_CHANNEL 0x08
|
||||
#define SNLED27351_SCAN_PHASE_3_CHANNEL 0x09
|
||||
#define SNLED27351_SCAN_PHASE_2_CHANNEL 0x0A
|
||||
#define SNLED27351_SCAN_PHASE_1_CHANNEL 0x0B
|
||||
#define SNLED27351_REG_SCAN_PHASE 0x14
|
||||
#define SNLED27351_MSKPHASE_12CHANNEL 0x00
|
||||
#define SNLED27351_MSKPHASE_11CHANNEL 0x01
|
||||
#define SNLED27351_MSKPHASE_10CHANNEL 0x02
|
||||
#define SNLED27351_MSKPHASE_9CHANNEL 0x03
|
||||
#define SNLED27351_MSKPHASE_8CHANNEL 0x04
|
||||
#define SNLED27351_MSKPHASE_7CHANNEL 0x05
|
||||
#define SNLED27351_MSKPHASE_6CHANNEL 0x06
|
||||
#define SNLED27351_MSKPHASE_5CHANNEL 0x07
|
||||
#define SNLED27351_MSKPHASE_4CHANNEL 0x08
|
||||
#define SNLED27351_MSKPHASE_3CHANNEL 0x09
|
||||
#define SNLED27351_MSKPHASE_2CHANNEL 0x0A
|
||||
#define SNLED27351_MSKPHASE_1CHANNEL 0x0B
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1 0x15
|
||||
#define SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE (0b1 << 2)
|
||||
#define SNLED27351_REG_SLEW_RATE_CONTROL_MODE1 0x15
|
||||
#define SNLED27351_MSKPWM_DELAY_PHASE_ENABLE 0x04
|
||||
#define SNLED27351_MSKPWM_DELAY_PHASE_DISABLE 0x00
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2 0x16
|
||||
#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE (0b1 << 6)
|
||||
#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE (0b1 << 7)
|
||||
#define SNLED27351_REG_SLEW_RATE_CONTROL_MODE2 0x16
|
||||
#define SNLED27351_MSKDRIVING_SINKING_CHANNEL_SLEWRATE_ENABLE 0xC0
|
||||
#define SNLED27351_MSKDRIVING_SINKING_CHANNEL_SLEWRATE_DISABLE 0x00
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_OPEN_SHORT_ENABLE 0x17
|
||||
#define SNLED27351_OPEN_SHORT_ENABLE_SDS_ENABLE (0b1 << 6)
|
||||
#define SNLED27351_OPEN_SHORT_ENABLE_ODS_ENABLE (0b1 << 7)
|
||||
#define SNLED27351_REG_OPEN_SHORT_ENABLE 0x17
|
||||
#define SNLED27351_MSKOPEN_DETECTION_ENABLE (0x01 << 7)
|
||||
#define SNLED27351_MSKOPEN_DETECTION_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_OPEN_SHORT_DUTY 0x18
|
||||
#define SNLED27351_MSKSHORT_DETECTION_ENABLE (0x01 << 6)
|
||||
#define SNLED27351_MSKSHORT_DETECTION_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_OPEN_SHORT_FLAG 0x19
|
||||
#define SNLED27351_OPEN_SHORT_FLAG_OSINT_ENABLE (0b1 << 6)
|
||||
#define SNLED27351_OPEN_SHORT_FLAG_ODINT_ENABLE (0b1 << 7)
|
||||
#define SNLED27351_REG_OPEN_SHORT_DUTY 0x18
|
||||
#define SNLED27351_REG_OPEN_SHORT_FLAG 0x19
|
||||
|
||||
#define SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP 0x1A
|
||||
#define SNLED27351_SOFTWARE_SLEEP_ENABLE (0b1 << 1)
|
||||
#define SNLED27351_MSKOPEN_DETECTION_INTERRUPT_ENABLE (0x01 << 7)
|
||||
#define SNLED27351_MSKOPEN_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_MSKSHORT_DETECTION_INTERRUPT_ENABLE (0x01 << 6)
|
||||
#define SNLED27351_MSKSHORT_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||
|
||||
#define SNLED27351_REG_SOFTWARE_SLEEP 0x1A
|
||||
#define SNLED27351_MSKSLEEP_ENABLE 0x02
|
||||
#define SNLED27351_MSKSLEEP_DISABLE 0x00
|
||||
|
||||
// LED Control Registers
|
||||
#define SNLED27351_LED_CONTROL_ON_OFF_FIRST_ADDR 0x0
|
||||
@@ -139,57 +187,6 @@
|
||||
#define SNLED27351_LED_CURRENT_TUNE_LAST_ADDR 0x0B
|
||||
#define SNLED27351_LED_CURRENT_TUNE_LENGTH 0x0C
|
||||
|
||||
#define SNLED27351_I2C_ADDRESS_GND 0x74
|
||||
#define SNLED27351_I2C_ADDRESS_SCL 0x75
|
||||
#define SNLED27351_I2C_ADDRESS_SDA 0x76
|
||||
#define SNLED27351_I2C_ADDRESS_VDDIO 0x77
|
||||
|
||||
#if defined(RGB_MATRIX_SNLED27351)
|
||||
# define SNLED27351_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||
#endif
|
||||
|
||||
#if defined(SNLED27351_I2C_ADDRESS_4)
|
||||
# define SNLED27351_DRIVER_COUNT 4
|
||||
#elif defined(SNLED27351_I2C_ADDRESS_3)
|
||||
# define SNLED27351_DRIVER_COUNT 3
|
||||
#elif defined(SNLED27351_I2C_ADDRESS_2)
|
||||
# define SNLED27351_DRIVER_COUNT 2
|
||||
#elif defined(SNLED27351_I2C_ADDRESS_1)
|
||||
# define SNLED27351_DRIVER_COUNT 1
|
||||
#endif
|
||||
|
||||
typedef struct snled27351_led_t {
|
||||
uint8_t driver : 2;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} PACKED snled27351_led_t;
|
||||
|
||||
extern const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT];
|
||||
|
||||
void snled27351_init_drivers(void);
|
||||
void snled27351_init(uint8_t addr);
|
||||
void snled27351_select_page(uint8_t addr, uint8_t page);
|
||||
bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
|
||||
|
||||
void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
void snled27351_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
void snled27351_set_led_control_register(uint8_t index, bool red, bool green, bool blue);
|
||||
|
||||
// This should not be called from an interrupt
|
||||
// (eg. from a timer interrupt).
|
||||
// Call this while idle (in between matrix scans).
|
||||
// If the buffer is dirty, it will update the driver with the buffer.
|
||||
void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index);
|
||||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index);
|
||||
|
||||
void snled27351_flush(void);
|
||||
|
||||
void snled27351_sw_return_normal(uint8_t addr);
|
||||
void snled27351_sw_shutdown(uint8_t addr);
|
||||
|
||||
#define A_1 0x00
|
||||
#define A_2 0x01
|
||||
#define A_3 0x02
|
||||
|
||||
@@ -44,7 +44,7 @@ __attribute__((weak)) bool qp_sh1106_init(painter_device_t device, painter_rotat
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
uint8_t sh1106_init_sequence[] = {
|
||||
const uint8_t sh1106_init_sequence[] = {
|
||||
// Command, Delay, N, Data[N]
|
||||
SH1106_SET_MUX_RATIO, 0, 1, 0x3F,
|
||||
SH1106_DISPLAY_OFFSET, 0, 1, 0x00,
|
||||
@@ -61,16 +61,6 @@ __attribute__((weak)) bool qp_sh1106_init(painter_device_t device, painter_rotat
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// If the display height is anything other than the default 64 pixels, change SH1106_SET_MUX_RATIO data byte to the correct value
|
||||
if (driver->oled.base.panel_height != 64) {
|
||||
sh1106_init_sequence[3] = driver->oled.base.panel_height - 1;
|
||||
}
|
||||
|
||||
// For 128x32 or 96x16 displays, change SH1106_COM_PADS_HW_CFG data byte from alternative (0x12) to sequential (0x02) configuration
|
||||
if (driver->oled.base.panel_height <= 32) {
|
||||
sh1106_init_sequence[20] = 0x02;
|
||||
}
|
||||
|
||||
qp_comms_bulk_command_sequence(device, sh1106_init_sequence, sizeof(sh1106_init_sequence));
|
||||
return true;
|
||||
}
|
||||
@@ -213,4 +203,4 @@ painter_device_t qp_sh1106_make_i2c_device(uint16_t panel_width, uint16_t panel_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // QUANTUM_PAINTER_SH1106_I2C_ENABLE
|
||||
#endif // QUANTUM_PAINTER_SH1106_SPI_ENABLE
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#define SH1106_COM_PADS_HW_CFG 0xDA
|
||||
#define SH1106_SET_CONTRAST 0x81
|
||||
#define SH1106_SET_PRECHARGE_PERIOD 0xD9
|
||||
#define SH1106_VCOM_DESELECT_LEVEL 0xDB
|
||||
#define SH1106_VCOM_DETECT 0xDB
|
||||
#define SH1106_ALL_ON_RESUME 0xA4
|
||||
#define SH1106_NON_INVERTING_DISPLAY 0xA6
|
||||
#define SH1106_DEACTIVATE_SCROLL 0x2E
|
||||
|
||||
@@ -58,8 +58,6 @@ __attribute__((weak)) bool qp_st7735_init(painter_device_t device, painter_rotat
|
||||
ST77XX_SET_PIX_FMT, 0, 1, 0x55,
|
||||
ST77XX_CMD_INVERT_OFF, 0, 0,
|
||||
ST77XX_CMD_NORMAL_ON, 0, 0,
|
||||
ST7735_SET_PGAMMA, 0, 16, 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10,
|
||||
ST7735_SET_NGAMMA, 0, 16, 0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10,
|
||||
ST77XX_CMD_DISPLAY_ON, 20, 0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -22,28 +22,17 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
// Set Parameters
|
||||
#ifndef ANALOG_JOYSTICK_AUTO_AXIS
|
||||
uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
|
||||
uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
|
||||
#else
|
||||
int16_t minAxisValues[2];
|
||||
int16_t maxAxisValues[2];
|
||||
#endif
|
||||
|
||||
uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
|
||||
uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
|
||||
|
||||
#ifdef ANALOG_JOYSTICK_WEIGHTS
|
||||
int8_t weights[101] = ANALOG_JOYSTICK_WEIGHTS;
|
||||
#endif
|
||||
|
||||
int16_t xOrigin, yOrigin;
|
||||
|
||||
uint16_t lastCursor = 0;
|
||||
|
||||
uint8_t prevValues[2] = {0, 0};
|
||||
|
||||
int16_t axisCoordinate(pin_t pin, uint16_t origin, uint8_t axis) {
|
||||
int16_t axisCoordinate(pin_t pin, uint16_t origin) {
|
||||
int8_t direction;
|
||||
int16_t distanceFromOrigin;
|
||||
int16_t range;
|
||||
@@ -54,27 +43,12 @@ int16_t axisCoordinate(pin_t pin, uint16_t origin, uint8_t axis) {
|
||||
return 0;
|
||||
} else if (origin > position) {
|
||||
distanceFromOrigin = origin - position;
|
||||
#ifdef ANALOG_JOYSTICK_AUTO_AXIS
|
||||
if (position < minAxisValues[axis]) {
|
||||
minAxisValues[axis] = position;
|
||||
}
|
||||
range = origin - minAxisValues[axis];
|
||||
#else
|
||||
range = origin - minAxisValue;
|
||||
#endif
|
||||
direction = -1;
|
||||
range = origin - minAxisValue;
|
||||
direction = -1;
|
||||
} else {
|
||||
distanceFromOrigin = position - origin;
|
||||
|
||||
#ifdef ANALOG_JOYSTICK_AUTO_AXIS
|
||||
if (position > maxAxisValues[axis]) {
|
||||
maxAxisValues[axis] = position;
|
||||
}
|
||||
range = maxAxisValues[axis] - origin;
|
||||
#else
|
||||
range = maxAxisValue - origin;
|
||||
#endif
|
||||
direction = 1;
|
||||
range = maxAxisValue - origin;
|
||||
direction = 1;
|
||||
}
|
||||
|
||||
float percent = (float)distanceFromOrigin / range;
|
||||
@@ -88,29 +62,14 @@ int16_t axisCoordinate(pin_t pin, uint16_t origin, uint8_t axis) {
|
||||
}
|
||||
}
|
||||
|
||||
int8_t axisToMouseComponent(pin_t pin, int16_t origin, uint8_t maxSpeed, uint8_t axis) {
|
||||
int16_t coordinate = axisCoordinate(pin, origin, axis);
|
||||
int8_t result;
|
||||
#ifndef ANALOG_JOYSTICK_WEIGHTS
|
||||
int8_t axisToMouseComponent(pin_t pin, int16_t origin, uint8_t maxSpeed) {
|
||||
int16_t coordinate = axisCoordinate(pin, origin);
|
||||
if (coordinate != 0) {
|
||||
float percent = (float)coordinate / 100;
|
||||
result = percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
|
||||
return percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
result = weights[abs(coordinate)] * (coordinate < 0 ? -1 : 1) * maxCursorSpeed / speedRegulator;
|
||||
#endif
|
||||
|
||||
#ifdef ANALOG_JOYSTICK_CUTOFF
|
||||
uint8_t pv = prevValues[axis];
|
||||
prevValues[axis] = abs(result);
|
||||
if (pv > abs(result)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
report_analog_joystick_t analog_joystick_read(void) {
|
||||
@@ -118,8 +77,8 @@ report_analog_joystick_t analog_joystick_read(void) {
|
||||
|
||||
if (timer_elapsed(lastCursor) > ANALOG_JOYSTICK_READ_INTERVAL) {
|
||||
lastCursor = timer_read();
|
||||
report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed, 0);
|
||||
report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed, 1);
|
||||
report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed);
|
||||
report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed);
|
||||
}
|
||||
#ifdef ANALOG_JOYSTICK_CLICK_PIN
|
||||
report.button = !readPin(ANALOG_JOYSTICK_CLICK_PIN);
|
||||
@@ -134,11 +93,4 @@ void analog_joystick_init(void) {
|
||||
// Account for drift
|
||||
xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);
|
||||
yOrigin = analogReadPin(ANALOG_JOYSTICK_Y_AXIS_PIN);
|
||||
|
||||
#ifdef ANALOG_JOYSTICK_AUTO_AXIS
|
||||
minAxisValues[0] = xOrigin - 100;
|
||||
minAxisValues[1] = yOrigin - 100;
|
||||
maxAxisValues[0] = xOrigin + 100;
|
||||
maxAxisValues[1] = yOrigin + 100;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,315 +0,0 @@
|
||||
// Copyright 2023 Dasky (@daskygit)
|
||||
// Copyright 2023 George Norton (@george-norton)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "azoteq_iqs5xx.h"
|
||||
#include "pointing_device_internal.h"
|
||||
#include "wait.h"
|
||||
|
||||
#ifndef AZOTEQ_IQS5XX_ADDRESS
|
||||
# define AZOTEQ_IQS5XX_ADDRESS (0x74 << 1)
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TIMEOUT_MS
|
||||
# define AZOTEQ_IQS5XX_TIMEOUT_MS 10
|
||||
#endif
|
||||
|
||||
#define AZOTEQ_IQS5XX_REG_PRODUCT_NUMBER 0x0000
|
||||
#define AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME 0x000C
|
||||
#define AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1 0x0432
|
||||
#define AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE 0x057A
|
||||
#define AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0 0x058E
|
||||
#define AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1 0x058F
|
||||
#define AZOTEQ_IQS5XX_REG_X_RESOLUTION 0x066E
|
||||
#define AZOTEQ_IQS5XX_REG_XY_CONFIG_0 0x0669
|
||||
#define AZOTEQ_IQS5XX_REG_Y_RESOLUTION 0x0670
|
||||
#define AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES 0x06B7
|
||||
#define AZOTEQ_IQS5XX_REG_END_COMMS 0xEEEE
|
||||
|
||||
// Gesture configuration
|
||||
#ifndef AZOTEQ_IQS5XX_TAP_ENABLE
|
||||
# define AZOTEQ_IQS5XX_TAP_ENABLE true
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE
|
||||
# define AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE
|
||||
# define AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE true
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SCROLL_ENABLE
|
||||
# define AZOTEQ_IQS5XX_SCROLL_ENABLE true
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_X_ENABLE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_X_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_Y_ENABLE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_Y_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_ZOOM_ENABLE
|
||||
# define AZOTEQ_IQS5XX_ZOOM_ENABLE false
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TAP_TIME
|
||||
# define AZOTEQ_IQS5XX_TAP_TIME 0x96
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_TAP_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_TAP_DISTANCE 0x19
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_HOLD_TIME
|
||||
# define AZOTEQ_IQS5XX_HOLD_TIME 0x12C
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME
|
||||
# define AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME 0x64 // 0x96
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE 0x12C
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME
|
||||
# define AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME 0x0
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE 0x7D0
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE 0x32
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE 0x32
|
||||
#endif
|
||||
#ifndef AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE
|
||||
# define AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE 0x19
|
||||
#endif
|
||||
|
||||
#if defined(AZOTEQ_IQS5XX_TPS43)
|
||||
# define AZOTEQ_IQS5XX_WIDTH_MM 43
|
||||
# define AZOTEQ_IQS5XX_HEIGHT_MM 40
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_X 2048
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_Y 1792
|
||||
#elif defined(AZOTEQ_IQS5XX_TPS65)
|
||||
# define AZOTEQ_IQS5XX_WIDTH_MM 65
|
||||
# define AZOTEQ_IQS5XX_HEIGHT_MM 49
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_X 3072
|
||||
# define AZOTEQ_IQS5XX_RESOLUTION_Y 2048
|
||||
#elif !defined(AZOTEQ_IQS5XX_WIDTH_MM) && !defined(AZOTEQ_IQS5XX_HEIGHT_MM)
|
||||
# error "You must define one of the available azoteq trackpads or specify at least the width and height"
|
||||
#endif
|
||||
|
||||
#define DIVIDE_UNSIGNED_ROUND(numerator, denominator) (((numerator) + ((denominator) / 2)) / (denominator))
|
||||
#define AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_X(inch) (DIVIDE_UNSIGNED_ROUND((inch) * (uint32_t)AZOTEQ_IQS5XX_WIDTH_MM * 10, 254))
|
||||
#define AZOTEQ_IQS5XX_RESOLUTION_X_TO_INCH(px) (DIVIDE_UNSIGNED_ROUND((px) * (uint32_t)254, AZOTEQ_IQS5XX_WIDTH_MM * 10))
|
||||
#define AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_Y(inch) (DIVIDE_UNSIGNED_ROUND((inch) * (uint32_t)AZOTEQ_IQS5XX_HEIGHT_MM * 10, 254))
|
||||
#define AZOTEQ_IQS5XX_RESOLUTION_Y_TO_INCH(px) (DIVIDE_UNSIGNED_ROUND((px) * (uint32_t)254, AZOTEQ_IQS5XX_HEIGHT_MM * 10))
|
||||
|
||||
static uint16_t azoteq_iqs5xx_product_number = AZOTEQ_IQS5XX_UNKNOWN;
|
||||
|
||||
static struct {
|
||||
uint16_t resolution_x;
|
||||
uint16_t resolution_y;
|
||||
} azoteq_iqs5xx_device_resolution_t;
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_wake(void) {
|
||||
uint8_t data = 0;
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME, (uint8_t *)&data, sizeof(data), 1);
|
||||
i2c_stop();
|
||||
wait_us(150);
|
||||
return status;
|
||||
}
|
||||
i2c_status_t azoteq_iqs5xx_end_session(void) {
|
||||
const uint8_t END_BYTE = 1; // any data
|
||||
return i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_END_COMMS, &END_BYTE, 1, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_get_base_data(azoteq_iqs5xx_base_data_t *base_data) {
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_PREVIOUS_CYCLE_TIME, (uint8_t *)base_data, 10, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_get_report_rate(azoteq_iqs5xx_report_rate_t *report_rate, azoteq_iqs5xx_charging_modes_t mode, bool end_session) {
|
||||
if (mode > AZOTEQ_IQS5XX_LP2) {
|
||||
pd_dprintf("IQS5XX - Invalid mode for get report rate.\n");
|
||||
return I2C_STATUS_ERROR;
|
||||
}
|
||||
uint16_t selected_reg = AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE + (2 * mode);
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, selected_reg, (uint8_t *)report_rate, 2, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_report_rate(uint16_t report_rate_ms, azoteq_iqs5xx_charging_modes_t mode, bool end_session) {
|
||||
if (mode > AZOTEQ_IQS5XX_LP2) {
|
||||
pd_dprintf("IQS5XX - Invalid mode for set report rate.\n");
|
||||
return I2C_STATUS_ERROR;
|
||||
}
|
||||
uint16_t selected_reg = AZOTEQ_IQS5XX_REG_REPORT_RATE_ACTIVE + (2 * mode);
|
||||
azoteq_iqs5xx_report_rate_t report_rate = {0};
|
||||
report_rate.h = (uint8_t)((report_rate_ms >> 8) & 0xFF);
|
||||
report_rate.l = (uint8_t)(report_rate_ms & 0xFF);
|
||||
i2c_status_t status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, selected_reg, (uint8_t *)&report_rate, 2, AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_reati(bool enabled, bool end_session) {
|
||||
azoteq_iqs5xx_system_config_0_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.reati = enabled;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_event_mode(bool enabled, bool end_session) {
|
||||
azoteq_iqs5xx_system_config_1_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.event_mode = enabled;
|
||||
config.touch_event = true;
|
||||
config.tp_event = true;
|
||||
config.prox_event = false;
|
||||
config.snap_event = false;
|
||||
config.reati_event = false;
|
||||
config.alp_prox_event = false;
|
||||
config.gesture_event = true;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONFIG_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_config_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_gesture_config(bool end_session) {
|
||||
azoteq_iqs5xx_gesture_config_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES, (uint8_t *)&config, sizeof(azoteq_iqs5xx_gesture_config_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
pd_dprintf("azo scroll: %d\n", config.multi_finger_gestures.scroll);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.single_finger_gestures.single_tap = AZOTEQ_IQS5XX_TAP_ENABLE;
|
||||
config.single_finger_gestures.press_and_hold = AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE;
|
||||
config.single_finger_gestures.swipe_x_plus = AZOTEQ_IQS5XX_SWIPE_X_ENABLE;
|
||||
config.single_finger_gestures.swipe_x_minus = AZOTEQ_IQS5XX_SWIPE_X_ENABLE;
|
||||
config.single_finger_gestures.swipe_y_plus = AZOTEQ_IQS5XX_SWIPE_Y_ENABLE;
|
||||
config.single_finger_gestures.swipe_y_minus = AZOTEQ_IQS5XX_SWIPE_Y_ENABLE;
|
||||
config.multi_finger_gestures.two_finger_tap = AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE;
|
||||
config.multi_finger_gestures.scroll = AZOTEQ_IQS5XX_SCROLL_ENABLE;
|
||||
config.multi_finger_gestures.zoom = AZOTEQ_IQS5XX_ZOOM_ENABLE;
|
||||
config.tap_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_TAP_TIME);
|
||||
config.tap_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_TAP_DISTANCE);
|
||||
config.hold_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_HOLD_TIME);
|
||||
config.swipe_initial_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME);
|
||||
config.swipe_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE);
|
||||
config.swipe_consecutive_time = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME);
|
||||
config.swipe_consecutive_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE);
|
||||
config.scroll_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE);
|
||||
config.zoom_initial_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE);
|
||||
config.zoom_consecutive_distance = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE);
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SINGLE_FINGER_GESTURES, (uint8_t *)&config, sizeof(azoteq_iqs5xx_gesture_config_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_set_xy_config(bool flip_x, bool flip_y, bool switch_xy, bool palm_reject, bool end_session) {
|
||||
azoteq_iqs5xx_xy_config_0_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_XY_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_xy_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
if (flip_x) {
|
||||
config.flip_x = !config.flip_x;
|
||||
}
|
||||
if (flip_y) {
|
||||
config.flip_y = !config.flip_y;
|
||||
}
|
||||
if (switch_xy) {
|
||||
config.switch_xy_axis = !config.switch_xy_axis;
|
||||
}
|
||||
config.palm_reject = palm_reject;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_XY_CONFIG_0, (uint8_t *)&config, sizeof(azoteq_iqs5xx_xy_config_0_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
i2c_status_t azoteq_iqs5xx_reset_suspend(bool reset, bool suspend, bool end_session) {
|
||||
azoteq_iqs5xx_system_control_1_t config = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_control_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
config.reset = reset;
|
||||
config.suspend = suspend;
|
||||
status = i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_SYSTEM_CONTROL_1, (uint8_t *)&config, sizeof(azoteq_iqs5xx_system_control_1_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
if (end_session) {
|
||||
azoteq_iqs5xx_end_session();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void azoteq_iqs5xx_set_cpi(uint16_t cpi) {
|
||||
if (azoteq_iqs5xx_product_number != AZOTEQ_IQS5XX_UNKNOWN) {
|
||||
azoteq_iqs5xx_resolution_t resolution = {0};
|
||||
resolution.x_resolution = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(MIN(azoteq_iqs5xx_device_resolution_t.resolution_x, AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_X(cpi)));
|
||||
resolution.y_resolution = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(MIN(azoteq_iqs5xx_device_resolution_t.resolution_y, AZOTEQ_IQS5XX_INCH_TO_RESOLUTION_Y(cpi)));
|
||||
i2c_writeReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_X_RESOLUTION, (uint8_t *)&resolution, sizeof(azoteq_iqs5xx_resolution_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t azoteq_iqs5xx_get_cpi(void) {
|
||||
if (azoteq_iqs5xx_product_number != AZOTEQ_IQS5XX_UNKNOWN) {
|
||||
azoteq_iqs5xx_resolution_t resolution = {0};
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_X_RESOLUTION, (uint8_t *)&resolution, sizeof(azoteq_iqs5xx_resolution_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
return AZOTEQ_IQS5XX_RESOLUTION_X_TO_INCH(AZOTEQ_IQS5XX_SWAP_H_L_BYTES(resolution.x_resolution));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t azoteq_iqs5xx_get_product(void) {
|
||||
i2c_status_t status = i2c_readReg16(AZOTEQ_IQS5XX_ADDRESS, AZOTEQ_IQS5XX_REG_PRODUCT_NUMBER, (uint8_t *)&azoteq_iqs5xx_product_number, sizeof(uint16_t), AZOTEQ_IQS5XX_TIMEOUT_MS);
|
||||
if (status == I2C_STATUS_SUCCESS) {
|
||||
azoteq_iqs5xx_product_number = AZOTEQ_IQS5XX_SWAP_H_L_BYTES(azoteq_iqs5xx_product_number);
|
||||
}
|
||||
pd_dprintf("AZOTEQ: Product number %u\n", azoteq_iqs5xx_product_number);
|
||||
return azoteq_iqs5xx_product_number;
|
||||
}
|
||||
|
||||
void azoteq_iqs5xx_setup_resolution(void) {
|
||||
#if !defined(AZOTEQ_IQS5XX_RESOLUTION_X) && !defined(AZOTEQ_IQS5XX_RESOLUTION_Y)
|
||||
switch (azoteq_iqs5xx_product_number) {
|
||||
case AZOTEQ_IQS550:
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 3584;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 2304;
|
||||
break;
|
||||
case AZOTEQ_IQS572:
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 2048;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 1792;
|
||||
break;
|
||||
case AZOTEQ_IQS525:
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 1280;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 768;
|
||||
break;
|
||||
default:
|
||||
// shouldn't be here
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = 0;
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef AZOTEQ_IQS5XX_RESOLUTION_X
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_x = AZOTEQ_IQS5XX_RESOLUTION_X;
|
||||
#endif
|
||||
#ifdef AZOTEQ_IQS5XX_RESOLUTION_Y
|
||||
azoteq_iqs5xx_device_resolution_t.resolution_y = AZOTEQ_IQS5XX_RESOLUTION_Y;
|
||||
#endif
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
// Copyright 2023 Dasky (@daskygit)
|
||||
// Copyright 2023 George Norton (@george-norton)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_master.h"
|
||||
#include "pointing_device.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef enum {
|
||||
AZOTEQ_IQS5XX_UNKNOWN,
|
||||
AZOTEQ_IQS550 = 40,
|
||||
AZOTEQ_IQS525 = 52,
|
||||
AZOTEQ_IQS572 = 58,
|
||||
} azoteq_iqs5xx_product_numbers_t;
|
||||
typedef enum {
|
||||
AZOTEQ_IQS5XX_ACTIVE,
|
||||
AZOTEQ_IQS5XX_IDLE_TOUCH,
|
||||
AZOTEQ_IQS5XX_IDLE,
|
||||
AZOTEQ_IQS5XX_LP1,
|
||||
AZOTEQ_IQS5XX_LP2,
|
||||
} azoteq_iqs5xx_charging_modes_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t h : 8;
|
||||
uint8_t l : 8;
|
||||
} azoteq_iqs5xx_report_rate_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool single_tap : 1; // Single tap gesture status
|
||||
bool press_and_hold : 1; // Press and hold gesture status
|
||||
bool swipe_x_neg : 1; // Swipe in negative X direction status
|
||||
bool swipe_x_pos : 1; // Swipe in positive X direction status
|
||||
bool swipe_y_pos : 1; // Swipe in positive Y direction status
|
||||
bool swipe_y_neg : 1; // Swipe in negative Y direction status
|
||||
uint8_t _unused : 2; // unused
|
||||
} azoteq_iqs5xx_gesture_events_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool two_finger_tap : 1; // Two finger tap gesture status
|
||||
bool scroll : 1; // Scroll status
|
||||
bool zoom : 1; // Zoom gesture status
|
||||
uint8_t _unused : 5; // unused
|
||||
} azoteq_iqs5xx_gesture_events_1_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
azoteq_iqs5xx_charging_modes_t charging_mode : 3; // Indicates current mode
|
||||
bool ati_error : 1; //
|
||||
bool reati_occurred : 1; //
|
||||
bool alp_ati_error : 1; //
|
||||
bool alp_reati_occurred : 1; //
|
||||
bool show_reset : 1; //
|
||||
} azoteq_iqs5xx_system_info_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool tp_movement : 1; //
|
||||
bool palm_detect : 1; // Palm detect status
|
||||
bool too_many_fingers : 1; // Total finger status
|
||||
bool rr_missed : 1; // Report rate status
|
||||
bool snap_toggle : 1; // Change in any snap channel status
|
||||
bool switch_state : 1; // Status of input pin SW_IN
|
||||
uint8_t _unused : 2; // unused
|
||||
} azoteq_iqs5xx_system_info_1_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t h : 8;
|
||||
uint8_t l : 8;
|
||||
} azoteq_iqs5xx_relative_xy_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t previous_cycle_time;
|
||||
azoteq_iqs5xx_gesture_events_0_t gesture_events_0;
|
||||
azoteq_iqs5xx_gesture_events_1_t gesture_events_1;
|
||||
azoteq_iqs5xx_system_info_0_t system_info_0;
|
||||
azoteq_iqs5xx_system_info_1_t system_info_1;
|
||||
uint8_t number_of_fingers;
|
||||
azoteq_iqs5xx_relative_xy_t x;
|
||||
azoteq_iqs5xx_relative_xy_t y;
|
||||
} azoteq_iqs5xx_base_data_t;
|
||||
|
||||
_Static_assert(sizeof(azoteq_iqs5xx_base_data_t) == 10, "azoteq_iqs5xx_basic_report_t should be 10 bytes");
|
||||
|
||||
typedef struct {
|
||||
uint8_t number_of_fingers;
|
||||
azoteq_iqs5xx_relative_xy_t x;
|
||||
azoteq_iqs5xx_relative_xy_t y;
|
||||
} azoteq_iqs5xx_report_data_t;
|
||||
|
||||
_Static_assert(sizeof(azoteq_iqs5xx_report_data_t) == 5, "azoteq_iqs5xx_report_data_t should be 5 bytes");
|
||||
|
||||
typedef struct PACKED {
|
||||
bool sw_input : 1;
|
||||
bool sw_input_select : 1;
|
||||
bool reati : 1;
|
||||
bool alp_reati : 1;
|
||||
bool sw_input_event : 1;
|
||||
bool wdt : 1;
|
||||
bool setup_complete : 1;
|
||||
bool manual_control : 1;
|
||||
} azoteq_iqs5xx_system_config_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool event_mode : 1;
|
||||
bool gesture_event : 1;
|
||||
bool tp_event : 1;
|
||||
bool reati_event : 1;
|
||||
bool alp_prox_event : 1;
|
||||
bool snap_event : 1;
|
||||
bool touch_event : 1;
|
||||
bool prox_event : 1;
|
||||
} azoteq_iqs5xx_system_config_1_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool flip_x : 1;
|
||||
bool flip_y : 1;
|
||||
bool switch_xy_axis : 1;
|
||||
bool palm_reject : 1;
|
||||
uint8_t _unused : 4;
|
||||
} azoteq_iqs5xx_xy_config_0_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool suspend : 1;
|
||||
bool reset : 1;
|
||||
int8_t _unused : 6;
|
||||
} azoteq_iqs5xx_system_control_1_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool single_tap : 1;
|
||||
bool press_and_hold : 1;
|
||||
bool swipe_x_minus : 1;
|
||||
bool swipe_x_plus : 1;
|
||||
bool swipe_y_plus : 1;
|
||||
bool swipe_y_minus : 1;
|
||||
int8_t _unused : 2;
|
||||
} azoteq_iqs5xx_single_finger_gesture_enable_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
bool two_finger_tap : 1;
|
||||
bool scroll : 1;
|
||||
bool zoom : 1;
|
||||
int8_t _unused : 5;
|
||||
} azoteq_iqs5xx_multi_finger_gesture_enable_t;
|
||||
|
||||
typedef struct PACKED {
|
||||
azoteq_iqs5xx_single_finger_gesture_enable_t single_finger_gestures;
|
||||
azoteq_iqs5xx_multi_finger_gesture_enable_t multi_finger_gestures;
|
||||
uint16_t tap_time;
|
||||
uint16_t tap_distance;
|
||||
uint16_t hold_time;
|
||||
uint16_t swipe_initial_time;
|
||||
uint16_t swipe_initial_distance;
|
||||
uint16_t swipe_consecutive_time;
|
||||
uint16_t swipe_consecutive_distance;
|
||||
int8_t swipe_angle;
|
||||
uint16_t scroll_initial_distance;
|
||||
int8_t scroll_angle;
|
||||
uint16_t zoom_initial_distance;
|
||||
uint16_t zoom_consecutive_distance;
|
||||
} azoteq_iqs5xx_gesture_config_t;
|
||||
|
||||
_Static_assert(sizeof(azoteq_iqs5xx_gesture_config_t) == 24, "azoteq_iqs5xx_gesture_config_t should be 24 bytes");
|
||||
|
||||
typedef struct {
|
||||
uint16_t x_resolution;
|
||||
uint16_t y_resolution;
|
||||
} azoteq_iqs5xx_resolution_t;
|
||||
|
||||
#define AZOTEQ_IQS5XX_COMBINE_H_L_BYTES(h, l) ((int16_t)(h << 8) | l)
|
||||
#define AZOTEQ_IQS5XX_SWAP_H_L_BYTES(b) ((uint16_t)((b & 0xff) << 8) | (b >> 8))
|
||||
|
||||
#ifndef AZOTEQ_IQS5XX_REPORT_RATE
|
||||
# define AZOTEQ_IQS5XX_REPORT_RATE 10
|
||||
#endif
|
||||
#if !defined(POINTING_DEVICE_TASK_THROTTLE_MS) && !defined(POINTING_DEVICE_MOTION_PIN)
|
||||
# define POINTING_DEVICE_TASK_THROTTLE_MS AZOTEQ_IQS5XX_REPORT_RATE
|
||||
#endif
|
||||
|
||||
void azoteq_iqs5xx_init(void);
|
||||
i2c_status_t azoteq_iqs5xx_wake(void);
|
||||
report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report);
|
||||
i2c_status_t azoteq_iqs5xx_get_report_rate(azoteq_iqs5xx_report_rate_t *report_rate, azoteq_iqs5xx_charging_modes_t mode, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_report_rate(uint16_t report_rate_ms, azoteq_iqs5xx_charging_modes_t mode, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_event_mode(bool enabled, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_reati(bool enabled, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_gesture_config(bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_set_xy_config(bool flip_x, bool flip_y, bool switch_xy, bool palm_reject, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_reset_suspend(bool reset, bool suspend, bool end_session);
|
||||
i2c_status_t azoteq_iqs5xx_get_base_data(azoteq_iqs5xx_base_data_t *base_data);
|
||||
void azoteq_iqs5xx_set_cpi(uint16_t cpi);
|
||||
uint16_t azoteq_iqs5xx_get_cpi(void);
|
||||
uint16_t azoteq_iqs5xx_get_product(void);
|
||||
void azoteq_iqs5xx_setup_resolution(void);
|
||||
@@ -216,13 +216,6 @@ void cirque_pinnacle_cursor_smoothing(bool enable) {
|
||||
RAP_Write(HOSTREG__FEEDCONFIG3, feedconfig3);
|
||||
}
|
||||
|
||||
// Check sensor is connected
|
||||
bool cirque_pinnacle_connected(void) {
|
||||
uint8_t zidle = 0;
|
||||
RAP_ReadBytes(HOSTREG__ZIDLE, &zidle, 1);
|
||||
return zidle == HOSTREG__ZIDLE_DEFVAL;
|
||||
}
|
||||
|
||||
/* Pinnacle-based TM040040/TM035035/TM023023 Functions */
|
||||
void cirque_pinnacle_init(void) {
|
||||
#if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
|
||||
@@ -281,10 +274,6 @@ void cirque_pinnacle_init(void) {
|
||||
}
|
||||
|
||||
cirque_pinnacle_enable_feed(true);
|
||||
|
||||
#ifndef CIRQUE_PINNACLE_SKIP_SENSOR_CHECK
|
||||
touchpad_init = cirque_pinnacle_connected();
|
||||
#endif
|
||||
}
|
||||
|
||||
pinnacle_data_t cirque_pinnacle_read_data(void) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_BREATHING
|
||||
#define RGB_MATRIX_DEFAULT_HUE 152
|
||||
#define RGB_MATRIX_DEFAULT_SAT 232
|
||||
#define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS
|
||||
#define RGB_MATRIX_DEFAULT_SPD 50
|
||||
|
||||
#define ENABLE_RGB_MATRIX_BREATHING
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user