Merge commit 'd9e077468ab3446cbd7306a453a73dad2c1403e8' into firmware_21

This commit is contained in:
Drashna Jael're
2021-10-11 20:36:47 -07:00
831 changed files with 23110 additions and 8122 deletions

View File

@@ -7,11 +7,12 @@ on:
paths: paths:
- 'keyboards/**' - 'keyboards/**'
- 'layouts/community/**' - 'layouts/community/**'
workflow_dispatch:
jobs: jobs:
api_data: api_data:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: qmkfm/base_container container: qmkfm/qmk_cli
# protect against those who develop with their fork on master # protect against those who develop with their fork on master
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'

View File

@@ -16,7 +16,7 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: qmkfm/base_container container: qmkfm/qmk_cli
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -25,4 +25,4 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: pip3 install -r requirements-dev.txt run: pip3 install -r requirements-dev.txt
- name: Run tests - name: Run tests
run: bin/qmk pytest run: qmk pytest

View File

@@ -7,11 +7,12 @@ on:
paths: paths:
- 'keyboards/**' - 'keyboards/**'
- 'layouts/community/**' - 'layouts/community/**'
workflow_dispatch:
jobs: jobs:
api_data: api_data:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: qmkfm/base_container container: qmkfm/qmk_cli
# protect against those who work in their fork on develop # protect against those who work in their fork on develop
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'

View File

@@ -14,7 +14,7 @@ on:
jobs: jobs:
generate: generate:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: qmkfm/base_container container: qmkfm/qmk_cli
# protect against those who develop with their fork on master # protect against those who develop with their fork on master
if: github.repository == 'qmk/qmk_firmware' if: github.repository == 'qmk/qmk_firmware'

View File

@@ -16,7 +16,7 @@ jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: qmkfm/base_container container: qmkfm/qmk_cli
steps: steps:
- uses: rlespinasse/github-slug-action@v3.x - uses: rlespinasse/github-slug-action@v3.x
@@ -31,12 +31,12 @@ jobs:
output: ' ' output: ' '
fileOutput: ' ' fileOutput: ' '
- name: Run qmk cformat and qmk pyformat - name: Run qmk format-c and qmk format-python
shell: 'bash {0}' shell: 'bash {0}'
run: | run: |
qmk cformat --core-only -n $(< ~/files.txt) qmk format-c --core-only -n $(< ~/files.txt)
cformat_exit=$? format_c_exit=$?
qmk pyformat -n qmk format-python -n
pyformat_exit=$? format_python_exit=$?
exit $((cformat_exit + pyformat_exit)) exit $((format_c_exit + format_python_exit))

View File

@@ -9,7 +9,7 @@ jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: qmkfm/base_container container: qmkfm/qmk_cli
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

99
.gitignore vendored
View File

@@ -1,77 +1,86 @@
.history/ # Junk files
.dep *.bak
*.o *.swp
*.bin *~
*.eep .DS_Store
# Build artifacts
.clang_complete
.build/
*.elf *.elf
*.hex
*.uf2
*.qmk
!util/bootloader.hex
!quantum/tools/eeprom_reset.hex
*.log *.log
*.lss *.lss
*.lst *.lst
*.map *.map
*.o
*.stackdump
*.sym *.sym
*.swp
tags # QMK-specific
*~
api_data/v1 api_data/v1
build/
.build/
*.bak
.vagrant/
quantum/version.h
.idea/
CMakeLists.txt
cmake-build-debug
.clang_complete
doxygen/ doxygen/
.DS_Store quantum/version.h
/util/wsl_downloaded *.bin
/util/win_downloaded *.eep
/users/ *.hex
/layouts/ *.qmk
*.uf2
# Old-style QMK Makefiles
/keyboards/*/Makefile /keyboards/*/Makefile
!/keyboards/ergodox_ez/ !/keyboards/ergodox_ez/
!/keyboards/planck/ !/keyboards/planck/
# Eclipse/PyCharm/Other IDE Settings # Eclipse/PyCharm/Other IDE Settings
.cproject
.project
.settings/
.idea
*.iml *.iml
.browse.VC.db* .browse.VC.db*
*.stackdump .cproject
.idea
.idea/
.project
.settings/
.vagrant/
# ?
.dep
.history/
build/
cmake-build-debug
CMakeLists.txt
# Let these ones be user specific, since we have so many different configurations # Let these ones be user specific, since we have so many different configurations
*.code-workspace *.code-workspace
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/tasks.json
.vscode/last.sql
.vscode/temp.sql
.vscode/ipch/
.stfolder .stfolder
.tags .tags
.vscode/c_cpp_properties.json
.vscode/ipch/
.vscode/last.sql
.vscode/launch.json
.vscode/tasks.json
.vscode/temp.sql
tags
# ignore image files # Ignore image files
*.png
*.gif *.gif
*.jpg *.jpg
*.png
# things travis sees # Things Travis sees
secrets.tar
id_rsa_*
/.vs /.vs
id_rsa_*
secrets.tar
# python things # Python things
__pycache__ __pycache__
.python-version .python-version
# prerequisites for updating ChibiOS # Prerequisites for updating ChibiOS
/util/fmpp* /util/fmpp*
# Allow to exist but don't include it in the repo # Allow to exist but don't include it in the repo
user_song_list.h user_song_list.h
/util/wsl_downloaded
/util/win_downloaded
/users/
/layouts/

View File

@@ -1,24 +0,0 @@
# Code Of Conduct
QMK strives to be an inclusive, tolerant, and welcoming community. We encourage participation from anyone regardless of age, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, political belief, race, religion, or sexual identity and orientation.
> “A gentle word turns away wrath, but a harsh word stirs up anger."
Our users, contributors, and collaborators are expected to treat each other with kindness and respect, to assume good intentions, and to gently correct, where possible, rather than react with escalation. While our goal is to be as accurate as possible, kindness and understanding are more valuable than correctness. Some examples of behavior we will not tolerate include, but is not limited to:
* The use of sexualized language or imagery
* Unwelcome advances, sexual or otherwise
* Deliberate intimidation, stalking, or following
* Insults or derogatory comments, or personal or political attacks
* Publishing others private information without explicit permission
* Sustained disruption of talks or other events
* Other conduct which could reasonably be considered inappropriate in a professional setting
* Advocating for, or encouraging, any of the above behaviour
# Reporting
If someone is violating this Code of Conduct, please email hello@qmk.fm or reach out to one of the Collaborators to bring it to our attention. All complaints will be reviewed and investigated.
QMK will seek to use the least punitive means available to resolve an issue. If the circumstances require asking an offender to leave, we will do that.
Reports will be taken and kept in strict confidence. You will not be required to confront an offender directly.

View File

@@ -1,7 +1,6 @@
FROM qmkfm/base_container FROM qmkfm/qmk_cli
VOLUME /qmk_firmware VOLUME /qmk_firmware
WORKDIR /qmk_firmware WORKDIR /qmk_firmware
COPY . .
CMD make all:all CMD qmk compile -kb all -km default

View File

@@ -264,11 +264,20 @@ define PARSE_RULE
else else
$$(info make: *** No rule to make target '$1'. Stop.) $$(info make: *** No rule to make target '$1'. Stop.)
$$(info |) $$(info |)
$$(info | QMK's make format recently changed to use folder locations and colons:) $$(info | QMK's make format is:)
$$(info | make project_folder:keymap[:target]) $$(info | make keyboard_folder:keymap_folder[:target])
$$(info |)
$$(info | Where `keyboard_folder` is the path to the keyboard relative to)
$$(info | `qmk_firmware/keyboards/`, and `keymap_folder` is the name of the)
$$(info | keymap folder under that board's `keymaps/` directory.)
$$(info |)
$$(info | Examples:) $$(info | Examples:)
$$(info | make planck/ez:default:flash) $$(info | keyboards/dz60, keyboards/dz60/keymaps/default)
$$(info | make planck/ez:default) $$(info | -> make dz60:default)
$$(info | -> qmk compile -kb dz60 -km default)
$$(info | keyboards/planck/rev6, keyboards/planck/keymaps/default)
$$(info | -> make planck/rev6:default:flash)
$$(info | -> qmk flash -kb planck/rev6 -km default)
$$(info |) $$(info |)
endif endif
endef endef
@@ -306,37 +315,8 @@ define PARSE_KEYBOARD
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_3)/keymaps/*/.))) KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_3)/keymaps/*/.)))
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/keymaps/*/.))) KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/keymaps/*/.)))
KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/keymaps/*/.))) KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/keymaps/*/.)))
# this might be needed, but in a different form
#KEYMAPS := $$(sort $$(filter-out $$(KEYBOARD_FOLDER_1) $$(KEYBOARD_FOLDER_2) \
$$(KEYBOARD_FOLDER_3) $$(KEYBOARD_FOLDER_4) $$(KEYBOARD_FOLDER_5), $$(KEYMAPS)))
KEYBOARD_LAYOUTS :=
ifneq ("$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/rules.mk)","")
LAYOUTS :=
$$(eval include $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_5)/rules.mk)
KEYBOARD_LAYOUTS := $$(sort $$(LAYOUTS) $$(KEYBOARD_LAYOUTS))
endif
ifneq ("$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/rules.mk)","")
LAYOUTS :=
$$(eval include $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_4)/rules.mk)
KEYBOARD_LAYOUTS := $$(sort $$(LAYOUTS) $$(KEYBOARD_LAYOUTS))
endif
ifneq ("$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_3)/rules.mk)","")
LAYOUTS :=
$$(eval include $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_3)/rules.mk)
KEYBOARD_LAYOUTS := $$(sort $$(LAYOUTS) $$(KEYBOARD_LAYOUTS))
endif
ifneq ("$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_2)/rules.mk)","")
LAYOUTS :=
$$(eval include $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_2)/rules.mk)
KEYBOARD_LAYOUTS := $$(sort $$(LAYOUTS) $$(KEYBOARD_LAYOUTS))
endif
ifneq ("$$(wildcard $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_1)/rules.mk)","")
LAYOUTS :=
$$(eval include $(ROOT_DIR)/keyboards/$$(KEYBOARD_FOLDER_PATH_1)/rules.mk)
KEYBOARD_LAYOUTS := $$(sort $$(LAYOUTS) $$(KEYBOARD_LAYOUTS))
endif
KEYBOARD_LAYOUTS := $(shell $(QMK_BIN) list-layouts --keyboard $1)
LAYOUT_KEYMAPS := LAYOUT_KEYMAPS :=
$$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/layouts/*/$$(LAYOUT)/*/.))))) $$(foreach LAYOUT,$$(KEYBOARD_LAYOUTS),$$(eval LAYOUT_KEYMAPS += $$(notdir $$(patsubst %/.,%,$$(wildcard $(ROOT_DIR)/layouts/*/$$(LAYOUT)/*/.)))))
@@ -560,29 +540,14 @@ git-submodule:
git submodule sync --recursive git submodule sync --recursive
git submodule update --init --recursive --progress git submodule update --init --recursive --progress
# Generate the version.h file
ifdef SKIP_GIT
VERSION_H_FLAGS := --skip-git
endif
ifdef SKIP_VERSION ifdef SKIP_VERSION
VERSION_H_FLAGS := --skip-all
SKIP_GIT := yes SKIP_GIT := yes
endif endif
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o quantum/version.h)
# Generate the version.h file
ifndef SKIP_GIT
GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
CHIBIOS_VERSION := $(shell cd lib/chibios && git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
CHIBIOS_CONTRIB_VERSION := $(shell cd lib/chibios-contrib && git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
else
GIT_VERSION := NA
CHIBIOS_VERSION := NA
CHIBIOS_CONTRIB_VERSION := NA
endif
ifndef SKIP_VERSION
BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S")
else
BUILD_DATE := 2020-01-01-00:00:00
endif
$(shell echo '#define QMK_VERSION "$(GIT_VERSION)"' > $(ROOT_DIR)/quantum/version.h)
$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(ROOT_DIR)/quantum/version.h)
$(shell echo '#define CHIBIOS_VERSION "$(CHIBIOS_VERSION)"' >> $(ROOT_DIR)/quantum/version.h)
$(shell echo '#define CHIBIOS_CONTRIB_VERSION "$(CHIBIOS_CONTRIB_VERSION)"' >> $(ROOT_DIR)/quantum/version.h)
include $(ROOT_DIR)/testlist.mk include $(ROOT_DIR)/testlist.mk

6
Vagrantfile vendored
View File

@@ -6,7 +6,7 @@ Vagrant.configure(2) do |config|
config.vm.define "qmk_firmware" config.vm.define "qmk_firmware"
# VMware/Virtualbox ( and also Hyperv/Parallels) 64 bit # VMware/Virtualbox ( and also Hyperv/Parallels) 64 bit
config.vm.box = "generic/debian9" config.vm.box = "generic/debian10"
config.vm.synced_folder '.', '/vagrant' config.vm.synced_folder '.', '/vagrant'
@@ -68,13 +68,13 @@ Vagrant.configure(2) do |config|
["virtualbox", "vmware_workstation", "vmware_fusion"].each do |type| ["virtualbox", "vmware_workstation", "vmware_fusion"].each do |type|
config.vm.provider type do |virt, override| config.vm.provider type do |virt, override|
override.vm.provision "docker" do |d| override.vm.provision "docker" do |d|
d.run "qmkfm/base_container", d.run "qmkfm/qmk_cli",
cmd: "tail -f /dev/null", cmd: "tail -f /dev/null",
args: "--privileged -v /dev:/dev -v '/vagrant:/vagrant'" args: "--privileged -v /dev:/dev -v '/vagrant:/vagrant'"
end end
override.vm.provision "shell", inline: <<-SHELL override.vm.provision "shell", inline: <<-SHELL
echo 'docker restart qmkfm-base_container && exec docker exec -it qmkfm-base_container /bin/bash -l' >> ~vagrant/.bashrc echo 'docker restart qmkfm-qmk_cli && exec docker exec -it qmkfm-qmk_cli /bin/bash -l' >> ~vagrant/.bashrc
SHELL SHELL
end end
end end

View File

@@ -26,8 +26,9 @@
# atmel-dfu Atmel factory DFU # atmel-dfu Atmel factory DFU
# lufa-dfu LUFA DFU # lufa-dfu LUFA DFU
# qmk-dfu QMK DFU (LUFA + blinkenlight) # qmk-dfu QMK DFU (LUFA + blinkenlight)
# bootloadHID HIDBootFlash compatible (ATmega32A) # qmk-hid QMK HID (LUFA + blinkenlight)
# USBasp USBaspLoader (ATmega328P) # bootloadhid HIDBootFlash compatible (ATmega32A)
# usbasploader USBaspLoader (ATmega328P)
# ARM: # ARM:
# kiibohd Input:Club Kiibohd bootloader (only used on their boards) # kiibohd Input:Club Kiibohd bootloader (only used on their boards)
# stm32duino STM32Duino (STM32F103x8) # stm32duino STM32Duino (STM32F103x8)
@@ -67,6 +68,11 @@ ifeq ($(strip $(BOOTLOADER)), qmk-dfu)
BOOTLOADER_SIZE = 8192 BOOTLOADER_SIZE = 8192
endif endif
endif endif
ifeq ($(strip $(BOOTLOADER)), qmk-hid)
OPT_DEFS += -DBOOTLOADER_QMK_HID
OPT_DEFS += -DBOOTLOADER_HID
BOOTLOADER_SIZE = 4096
endif
ifeq ($(strip $(BOOTLOADER)), halfkay) ifeq ($(strip $(BOOTLOADER)), halfkay)
OPT_DEFS += -DBOOTLOADER_HALFKAY OPT_DEFS += -DBOOTLOADER_HALFKAY
ifeq ($(strip $(MCU)), atmega32u4) ifeq ($(strip $(MCU)), atmega32u4)
@@ -80,11 +86,11 @@ ifeq ($(strip $(BOOTLOADER)), caterina)
OPT_DEFS += -DBOOTLOADER_CATERINA OPT_DEFS += -DBOOTLOADER_CATERINA
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif
ifeq ($(strip $(BOOTLOADER)), bootloadHID) ifneq (,$(filter $(BOOTLOADER), bootloadhid bootloadHID))
OPT_DEFS += -DBOOTLOADER_BOOTLOADHID OPT_DEFS += -DBOOTLOADER_BOOTLOADHID
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif
ifeq ($(strip $(BOOTLOADER)), USBasp) ifneq (,$(filter $(BOOTLOADER), usbasploader USBasp))
OPT_DEFS += -DBOOTLOADER_USBASP OPT_DEFS += -DBOOTLOADER_USBASP
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif

View File

@@ -1,31 +1,17 @@
# Look for a json keymap file # Look for a json keymap file
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","") ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","")
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5) KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","")
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4) KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","")
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3) KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","")
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2) KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","") else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1) KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
endif endif
# Load the keymap-level rules.mk if exists
ifneq ("$(wildcard $(KEYMAP_PATH))", "")
-include $(KEYMAP_PATH)/rules.mk
endif
# Generate the keymap.c
$(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)

View File

@@ -23,6 +23,15 @@ KEYBOARD_OUTPUT := $(BUILD_DIR)/obj_$(KEYBOARD_FILESAFE)
# Force expansion # Force expansion
TARGET := $(TARGET) TARGET := $(TARGET)
ifneq ($(FORCE_LAYOUT),)
TARGET := $(TARGET)_$(FORCE_LAYOUT)
endif
# Object files and generated keymap directory
# To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro!
KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
# For split boards we need to set a master half. # For split boards we need to set a master half.
MASTER ?= left MASTER ?= left
ifdef master ifdef master
@@ -100,7 +109,7 @@ MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP)
MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP) MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
# Pull in rules from info.json # Pull in rules from info.json
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/rules.mk) INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_rules.mk)
include $(INFO_RULES_MK) include $(INFO_RULES_MK)
# Check for keymap.json first, so we can regenerate keymap.c # Check for keymap.json first, so we can regenerate keymap.c
@@ -137,16 +146,35 @@ ifeq ("$(wildcard $(KEYMAP_PATH))", "")
endif endif
endif endif
# Have we found a keymap.json?
ifneq ("$(wildcard $(KEYMAP_JSON))", "")
KEYMAP_C := $(KEYMAP_OUTPUT)/src/keymap.c
KEYMAP_H := $(KEYMAP_OUTPUT)/src/config.h
# Load the keymap-level rules.mk if exists
-include $(KEYMAP_PATH)/rules.mk
# Load any rules.mk content from keymap.json
INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --keymap $(KEYMAP) --output $(KEYMAP_OUTPUT)/src/rules.mk)
include $(INFO_RULES_MK)
# Add rules to generate the keymap files - indentation here is important
$(KEYMAP_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)
$(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON)
$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --keymap $(KEYMAP) --output $(KEYMAP_H)
generated-files: $(KEYMAP_OUTPUT)/src/config.h $(KEYMAP_OUTPUT)/src/keymap.c
endif
ifeq ($(strip $(CTPC)), yes) ifeq ($(strip $(CTPC)), yes)
CONVERT_TO_PROTON_C=yes CONVERT_TO_PROTON_C=yes
endif endif
ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes) ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes)
include platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk include platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk
endif
ifneq ($(FORCE_LAYOUT),)
TARGET := $(TARGET)_$(FORCE_LAYOUT)
endif endif
include quantum/mcu_selection.mk include quantum/mcu_selection.mk
@@ -232,6 +260,7 @@ ifdef MCU_FAMILY
PLATFORM=CHIBIOS PLATFORM=CHIBIOS
PLATFORM_KEY=chibios PLATFORM_KEY=chibios
FIRMWARE_FORMAT?=bin FIRMWARE_FORMAT?=bin
OPT_DEFS += -DMCU_$(MCU_FAMILY)
else ifdef ARM_ATSAM else ifdef ARM_ATSAM
PLATFORM=ARM_ATSAM PLATFORM=ARM_ATSAM
PLATFORM_KEY=arm_atsam PLATFORM_KEY=arm_atsam
@@ -327,19 +356,19 @@ endif
# Disable features that a keyboard doesn't support # Disable features that a keyboard doesn't support
-include disable_features.mk -include disable_features.mk
# Object files directory
# To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro!
KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","") ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
CONFIG_H += $(KEYMAP_PATH)/config.h CONFIG_H += $(KEYMAP_PATH)/config.h
endif endif
ifneq ("$(KEYMAP_H)","")
CONFIG_H += $(KEYMAP_H)
endif
# project specific files # project specific files
SRC += $(KEYBOARD_SRC) \ SRC += \
$(KEYBOARD_SRC) \
$(KEYMAP_C) \ $(KEYMAP_C) \
$(QUANTUM_SRC) $(QUANTUM_SRC) \
$(QUANTUM_DIR)/main.c \
# Optimize size but this may cause error "relocation truncated to fit" # Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax #EXTRALDFLAGS = -Wl,--relax
@@ -374,6 +403,7 @@ ifneq ($(strip $(PROTOCOL)),)
else else
include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk
endif endif
-include $(TOP_DIR)/platforms/$(PLATFORM_KEY)/flash.mk
# TODO: remove this bodge? # TODO: remove this bodge?
PROJECT_DEFS := $(OPT_DEFS) PROJECT_DEFS := $(OPT_DEFS)

View File

@@ -7,7 +7,6 @@ define SEARCH_LAYOUTS_REPO
LAYOUT_KEYMAP_C := $$(LAYOUT_KEYMAP_PATH)/keymap.c LAYOUT_KEYMAP_C := $$(LAYOUT_KEYMAP_PATH)/keymap.c
ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_JSON))","") ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_JSON))","")
-include $$(LAYOUT_KEYMAP_PATH)/rules.mk -include $$(LAYOUT_KEYMAP_PATH)/rules.mk
KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c
KEYMAP_JSON := $$(LAYOUT_KEYMAP_JSON) KEYMAP_JSON := $$(LAYOUT_KEYMAP_JSON)
KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH) KEYMAP_PATH := $$(LAYOUT_KEYMAP_PATH)
else ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","") else ifneq ("$$(wildcard $$(LAYOUT_KEYMAP_C))","")
@@ -31,6 +30,3 @@ ifneq ($(FORCE_LAYOUT),)
endif endif
$(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS))) $(foreach LAYOUT,$(LAYOUTS),$(eval $(call SEARCH_LAYOUTS)))
# Use rule from build_json.mk, but update prerequisite in case KEYMAP_JSON was updated
$(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)

View File

@@ -24,7 +24,6 @@ GTEST_INTERNAL_INC :=\
$(GTEST_OUTPUT)_SRC :=\ $(GTEST_OUTPUT)_SRC :=\
googletest/src/gtest-all.cc\ googletest/src/gtest-all.cc\
googletest/src/gtest_main.cc\
googlemock/src/gmock-all.cc googlemock/src/gmock-all.cc
$(GTEST_OUTPUT)_DEFS := $(GTEST_OUTPUT)_DEFS :=
@@ -35,7 +34,8 @@ CREATE_MAP := no
VPATH +=\ VPATH +=\
$(LIB_PATH)/googletest\ $(LIB_PATH)/googletest\
$(LIB_PATH)/googlemock $(LIB_PATH)/googlemock\
$(LIB_PATH)/printf
all: elf all: elf
@@ -43,18 +43,29 @@ VPATH += $(COMMON_VPATH)
PLATFORM:=TEST PLATFORM:=TEST
PLATFORM_KEY:=test PLATFORM_KEY:=test
ifeq ($(strip $(DEBUG)), 1)
CONSOLE_ENABLE = yes
endif
ifneq ($(filter $(FULL_TESTS),$(TEST)),) ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include tests/$(TEST)/rules.mk include tests/$(TEST)/rules.mk
endif endif
include common_features.mk include common_features.mk
include $(TMK_PATH)/common.mk include $(TMK_PATH)/common.mk
include $(QUANTUM_PATH)/debounce/tests/rules.mk
include $(QUANTUM_PATH)/sequencer/tests/rules.mk include $(QUANTUM_PATH)/sequencer/tests/rules.mk
include $(QUANTUM_PATH)/serial_link/tests/rules.mk include $(QUANTUM_PATH)/serial_link/tests/rules.mk
include $(TMK_PATH)/common/test/rules.mk
ifneq ($(filter $(FULL_TESTS),$(TEST)),) ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include build_full_test.mk include build_full_test.mk
endif endif
$(TEST)_SRC += \
tests/test_common/main.c \
$(LIB_PATH)/printf/printf.c \
$(QUANTUM_PATH)/logging/print.c
$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC) $(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC)
$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC) $(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS) $(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)

View File

@@ -12,6 +12,9 @@ QUANTUM_PATH = $(QUANTUM_DIR)
DRIVER_DIR = drivers DRIVER_DIR = drivers
DRIVER_PATH = $(DRIVER_DIR) DRIVER_PATH = $(DRIVER_DIR)
PLATFORM_DIR = platforms
PLATFORM_PATH = $(PLATFORM_DIR)
BUILD_DIR := .build BUILD_DIR := .build
COMMON_VPATH := $(TOP_DIR) COMMON_VPATH := $(TOP_DIR)

View File

@@ -20,8 +20,23 @@ QUANTUM_SRC += \
$(QUANTUM_DIR)/send_string.c \ $(QUANTUM_DIR)/send_string.c \
$(QUANTUM_DIR)/bitwise.c \ $(QUANTUM_DIR)/bitwise.c \
$(QUANTUM_DIR)/led.c \ $(QUANTUM_DIR)/led.c \
$(QUANTUM_DIR)/action.c \
$(QUANTUM_DIR)/action_layer.c \
$(QUANTUM_DIR)/action_macro.c \
$(QUANTUM_DIR)/action_tapping.c \
$(QUANTUM_DIR)/action_util.c \
$(QUANTUM_DIR)/eeconfig.c \
$(QUANTUM_DIR)/keyboard.c \
$(QUANTUM_DIR)/keymap_common.c \ $(QUANTUM_DIR)/keymap_common.c \
$(QUANTUM_DIR)/keycode_config.c $(QUANTUM_DIR)/keycode_config.c \
$(QUANTUM_DIR)/logging/debug.c \
$(QUANTUM_DIR)/logging/sendchar.c \
VPATH += $(QUANTUM_DIR)/logging
# Fall back to lib/printf if there is no platform provided print
ifeq ("$(wildcard $(TMK_PATH)/common/$(PLATFORM_KEY)/printf.mk)","")
include $(QUANTUM_PATH)/logging/print.mk
endif
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes) ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
@@ -83,13 +98,13 @@ endif
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
OPT_DEFS += -DMOUSEKEY_ENABLE OPT_DEFS += -DMOUSEKEY_ENABLE
OPT_DEFS += -DMOUSE_ENABLE MOUSE_ENABLE := yes
SRC += $(QUANTUM_DIR)/mousekey.c SRC += $(QUANTUM_DIR)/mousekey.c
endif endif
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
OPT_DEFS += -DPOINTING_DEVICE_ENABLE OPT_DEFS += -DPOINTING_DEVICE_ENABLE
OPT_DEFS += -DMOUSE_ENABLE MOUSE_ENABLE := yes
SRC += $(QUANTUM_DIR)/pointing_device.c SRC += $(QUANTUM_DIR)/pointing_device.c
endif endif
@@ -150,6 +165,7 @@ else
else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),) else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
OPT_DEFS += -DEEPROM_DRIVER OPT_DEFS += -DEEPROM_DRIVER
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom
SRC += eeprom_driver.c eeprom_stm32_L0_L1.c SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
else else
# This will effectively work the same as "transient" if not supported by the chip # This will effectively work the same as "transient" if not supported by the chip
@@ -176,10 +192,11 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),) ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),)
$(error RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type) $(error RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type)
else else
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h COMMON_VPATH += $(QUANTUM_DIR)/rgblight
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h
OPT_DEFS += -DRGBLIGHT_ENABLE OPT_DEFS += -DRGBLIGHT_ENABLE
SRC += $(QUANTUM_DIR)/color.c SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgblight.c SRC += $(QUANTUM_DIR)/rgblight/rgblight.c
CIE1931_CURVE := yes CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes RGB_KEYCODES_ENABLE := yes
endif endif
@@ -210,21 +227,25 @@ ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
OPT_DEFS += -DLIB8_ATTINY OPT_DEFS += -DLIB8_ATTINY
endif endif
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations
COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners
SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
SRC += $(QUANTUM_DIR)/led_matrix.c SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c
SRC += $(QUANTUM_DIR)/led_matrix_drivers.c SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
CIE1931_CURVE := yes CIE1931_CURVE := yes
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731) ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731-simple.c SRC += is31fl3731-simple.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
endif endif
RGB_MATRIX_ENABLE ?= no RGB_MATRIX_ENABLE ?= no
VALID_RGB_MATRIX_TYPES := IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),) ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
@@ -235,36 +256,47 @@ ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
# ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
OPT_DEFS += -DLIB8_ATTINY OPT_DEFS += -DLIB8_ATTINY
endif endif
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations
COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners
SRC += $(QUANTUM_DIR)/color.c SRC += $(QUANTUM_DIR)/color.c
SRC += $(QUANTUM_DIR)/rgb_matrix.c SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c
SRC += $(QUANTUM_DIR)/rgb_matrix_drivers.c SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c
SRC += $(LIB_PATH)/lib8tion/lib8tion.c
CIE1931_CURVE := yes CIE1931_CURVE := yes
RGB_KEYCODES_ENABLE := yes RGB_KEYCODES_ENABLE := yes
ifeq ($(strip $(RGB_MATRIX_DRIVER)), AW20216)
OPT_DEFS += -DAW20216 -DSTM32_SPI -DHAL_USE_SPI=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led
SRC += aw20216.c
QUANTUM_LIB_SRC += spi_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731) ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3731.c SRC += is31fl3731.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733) ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733)
OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3733.c SRC += is31fl3733.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737) ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737)
OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3737.c SRC += is31fl3737.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741) ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741)
OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/issi COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3741.c SRC += is31fl3741.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
@@ -322,11 +354,6 @@ ifeq ($(strip $(LCD_ENABLE)), yes)
CIE1931_CURVE := yes CIE1931_CURVE := yes
endif endif
# backward compat
ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
BACKLIGHT_DRIVER := custom
endif
VALID_BACKLIGHT_TYPES := pwm timer software custom VALID_BACKLIGHT_TYPES := pwm timer software custom
BACKLIGHT_ENABLE ?= no BACKLIGHT_ENABLE ?= no
@@ -386,7 +413,7 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
endif endif
ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes) ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes)
COMMON_VPATH += $(DRIVER_PATH)/apa102 COMMON_VPATH += $(DRIVER_PATH)/led
SRC += apa102.c SRC += apa102.c
endif endif
@@ -448,18 +475,15 @@ ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/dip_switch.c SRC += $(QUANTUM_DIR)/dip_switch.c
endif endif
VALID_MAGIC_TYPES := yes full lite VALID_MAGIC_TYPES := yes lite
BOOTMAGIC_ENABLE ?= no BOOTMAGIC_ENABLE ?= no
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no) ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),) ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),)
$(error BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic) $(error BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic)
endif endif
ifneq ($(strip $(BOOTMAGIC_ENABLE)), full) ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
OPT_DEFS += -DBOOTMAGIC_LITE OPT_DEFS += -DBOOTMAGIC_LITE
QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_lite.c QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_lite.c
else
OPT_DEFS += -DBOOTMAGIC_ENABLE
QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_full.c
endif endif
endif endif
COMMON_VPATH += $(QUANTUM_DIR)/bootmagic COMMON_VPATH += $(QUANTUM_DIR)/bootmagic
@@ -480,42 +504,31 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes)
# if 'lite' then skip the actual matrix implementation # if 'lite' then skip the actual matrix implementation
ifneq ($(strip $(CUSTOM_MATRIX)), lite) ifneq ($(strip $(CUSTOM_MATRIX)), lite)
# Include the standard or split matrix code if needed # Include the standard or split matrix code if needed
ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
QUANTUM_SRC += $(QUANTUM_DIR)/split_common/matrix.c
else
QUANTUM_SRC += $(QUANTUM_DIR)/matrix.c QUANTUM_SRC += $(QUANTUM_DIR)/matrix.c
endif endif
endif
endif endif
# Support for translating old names to new names:
ifeq ($(strip $(DEBOUNCE_TYPE)),sym_g)
DEBOUNCE_TYPE:=sym_defer_g
else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pk)
DEBOUNCE_TYPE:=sym_eager_pk
else ifeq ($(strip $(DEBOUNCE_TYPE)),sym_pk)
DEBOUNCE_TYPE:=sym_defer_pk
else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pr)
DEBOUNCE_TYPE:=sym_eager_pr
endif
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
# Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually. # Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually.
DEBOUNCE_TYPE?= sym_defer_g DEBOUNCE_TYPE ?= sym_defer_g
ifneq ($(strip $(DEBOUNCE_TYPE)), custom) ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c QUANTUM_SRC += $(QUANTUM_DIR)/debounce/$(strip $(DEBOUNCE_TYPE)).c
endif endif
ifeq ($(strip $(SPLIT_KEYBOARD)), yes) ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h
OPT_DEFS += -DSPLIT_KEYBOARD OPT_DEFS += -DSPLIT_KEYBOARD
CRC_ENABLE := yes
# Include files used by all split keyboards # Include files used by all split keyboards
QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_util.c QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_util.c
# Determine which (if any) transport files are required # Determine which (if any) transport files are required
ifneq ($(strip $(SPLIT_TRANSPORT)), custom) ifneq ($(strip $(SPLIT_TRANSPORT)), custom)
QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/transport.c QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \
$(QUANTUM_DIR)/split_common/transactions.c
OPT_DEFS += -DSPLIT_COMMON_TRANSACTIONS
# Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called. # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called.
# Unused functions are pruned away, which is why we can add multiple drivers here without bloat. # Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
ifeq ($(PLATFORM),AVR) ifeq ($(PLATFORM),AVR)
@@ -536,11 +549,17 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
COMMON_VPATH += $(QUANTUM_PATH)/split_common COMMON_VPATH += $(QUANTUM_PATH)/split_common
endif endif
ifeq ($(strip $(CRC_ENABLE)), yes)
OPT_DEFS += -DCRC_ENABLE
SRC += crc.c
endif
HAPTIC_ENABLE ?= no HAPTIC_ENABLE ?= no
ifneq ($(strip $(HAPTIC_ENABLE)),no) ifneq ($(strip $(HAPTIC_ENABLE)),no)
COMMON_VPATH += $(DRIVER_PATH)/haptic COMMON_VPATH += $(DRIVER_PATH)/haptic
SRC += haptic.c
OPT_DEFS += -DHAPTIC_ENABLE OPT_DEFS += -DHAPTIC_ENABLE
SRC += $(QUANTUM_DIR)/haptic.c
SRC += $(QUANTUM_DIR)/process_keycode/process_haptic.c
endif endif
ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), ) ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
@@ -555,15 +574,33 @@ ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), )
endif endif
ifeq ($(strip $(HD44780_ENABLE)), yes) ifeq ($(strip $(HD44780_ENABLE)), yes)
SRC += drivers/avr/hd44780.c SRC += platforms/avr/drivers/hd44780.c
OPT_DEFS += -DHD44780_ENABLE OPT_DEFS += -DHD44780_ENABLE
endif endif
ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes) VALID_OLED_DRIVER_TYPES := SSD1306 custom
OPT_DEFS += -DOLED_DRIVER_ENABLE OLED_DRIVER ?= SSD1306
ifeq ($(strip $(OLED_ENABLE)), yes)
ifeq ($(filter $(OLED_DRIVER),$(VALID_OLED_DRIVER_TYPES)),)
$(error OLED_DRIVER="$(OLED_DRIVER)" is not a valid OLED driver)
else
OPT_DEFS += -DOLED_ENABLE
COMMON_VPATH += $(DRIVER_PATH)/oled COMMON_VPATH += $(DRIVER_PATH)/oled
OPT_DEFS += -DOLED_DRIVER_$(strip $(shell echo $(OLED_DRIVER) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(OLED_DRIVER)), SSD1306)
SRC += ssd1306_sh1106.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
SRC += oled_driver.c endif
endif
endif
ifeq ($(strip $(ST7565_ENABLE)), yes)
OPT_DEFS += -DST7565_ENABLE
COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h
COMMON_VPATH += $(DRIVER_PATH)/lcd
QUANTUM_LIB_SRC += spi_master.c
SRC += st7565.c
endif endif
include $(DRIVER_PATH)/qwiic/qwiic.mk include $(DRIVER_PATH)/qwiic/qwiic.mk
@@ -618,6 +655,11 @@ ifeq ($(strip $(COMBO_ENABLE)), yes)
OPT_DEFS += -DCOMBO_ENABLE OPT_DEFS += -DCOMBO_ENABLE
endif endif
ifeq ($(strip $(KEY_OVERRIDE_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_key_override.c
OPT_DEFS += -DKEY_OVERRIDE_ENABLE
endif
ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
OPT_DEFS += -DTAP_DANCE_ENABLE OPT_DEFS += -DTAP_DANCE_ENABLE
@@ -642,19 +684,28 @@ ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
endif endif
JOYSTICK_ENABLE ?= no JOYSTICK_ENABLE ?= no
ifneq ($(strip $(JOYSTICK_ENABLE)), no) VALID_JOYSTICK_TYPES := analog digital
JOYSTICK_DRIVER ?= analog
ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
ifeq ($(filter $(JOYSTICK_DRIVER),$(VALID_JOYSTICK_TYPES)),)
$(error "$(JOYSTICK_DRIVER)" is not a valid joystick driver)
endif
OPT_DEFS += -DJOYSTICK_ENABLE OPT_DEFS += -DJOYSTICK_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c
SRC += $(QUANTUM_DIR)/joystick.c SRC += $(QUANTUM_DIR)/joystick.c
endif
ifeq ($(strip $(JOYSTICK_ENABLE)), analog) ifeq ($(strip $(JOYSTICK_DRIVER)), analog)
OPT_DEFS += -DANALOG_JOYSTICK_ENABLE OPT_DEFS += -DANALOG_JOYSTICK_ENABLE
SRC += analog.c SRC += analog.c
endif
ifeq ($(strip $(JOYSTICK_DRIVER)), digital)
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
endif
endif endif
ifeq ($(strip $(JOYSTICK_ENABLE)), digital) DIGITIZER_ENABLE ?= no
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE ifneq ($(strip $(DIGITIZER_ENABLE)), no)
SRC += $(QUANTUM_DIR)/digitizer.c
endif endif
USBPD_ENABLE ?= no USBPD_ENABLE ?= no

View File

@@ -3,19 +3,46 @@
{ {
# Format: # Format:
# <config.h key>: {"info_key": <info.json key>, ["value_type": <value_type>], ["to_json": <true/false>], ["to_c": <true/false>]} # <config.h key>: {"info_key": <info.json key>, ["value_type": <value_type>], ["to_json": <true/false>], ["to_c": <true/false>]}
# value_type: one of "array", "array.int", "int", "hex", "list", "mapping" # value_type: one of "array", "array.int", "bool", "int", "hex", "list", "mapping"
# to_json: Default `true`. Set to `false` to exclude this mapping from info.json # to_json: Default `true`. Set to `false` to exclude this mapping from info.json
# to_c: Default `true`. Set to `false` to exclude this mapping from config.h # to_c: Default `true`. Set to `false` to exclude this mapping from config.h
# warn_duplicate: Default `true`. Set to `false` to turn off warning when a value exists in both places # warn_duplicate: Default `true`. Set to `false` to turn off warning when a value exists in both places
"DEBOUNCE": {"info_key": "debounce", "value_type": "int"} "AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "bool"},
"BACKLIGHT_BREATHING": {"info_key": "backlight.breathing", "value_type": "bool"},
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
"BACKLIGHT_PIN": {"info_key": "backlight.pin"},
"COMBO_COUNT": {"info_key": "combo.count", "value_type": "int"},
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"},
"DEBOUNCE": {"info_key": "debounce", "value_type": "int"},
"DEVICE_VER": {"info_key": "usb.device_ver", "value_type": "hex"}, "DEVICE_VER": {"info_key": "usb.device_ver", "value_type": "hex"},
"DESCRIPTION": {"info_key": "keyboard_folder", "to_json": false}, "DESCRIPTION": {"info_key": "keyboard_folder", "to_json": false},
"DIODE_DIRECTION": {"info_key": "diode_direction"}, "DIODE_DIRECTION": {"info_key": "diode_direction"},
"FORCE_NKRO": {"info_key": "usb.force_nkro", "value_type": "bool"},
"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"},
"IGNORE_MOD_TAP_INTERRUPT": {"info_key": "tapping.ignore_mod_tap_interrupt", "value_type": "bool"},
"IGNORE_MOD_TAP_INTERRUPT_PER_KEY": {"info_key": "tapping.ignore_mod_tap_interrupt_per_key", "value_type": "bool"},
"LAYOUTS": {"info_key": "layout_aliases", "value_type": "mapping"}, "LAYOUTS": {"info_key": "layout_aliases", "value_type": "mapping"},
"LEADER_PER_KEY_TIMING": {"info_key": "leader_key.timing", "value_type": "bool"},
"LEADER_KEY_STRICT_KEY_PROCESSING": {"info_key": "leader_key.strict_processing", "value_type": "bool"},
"LEADER_TIMEOUT": {"info_key": "leader_key.timeout", "value_type": "int"},
"LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"}, "LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"},
"LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"}, "LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"},
"LED_SCROLL_LOCK_PIN": {"info_key": "indicators.scroll_lock"}, "LED_SCROLL_LOCK_PIN": {"info_key": "indicators.scroll_lock"},
"MANUFACTURER": {"info_key": "manufacturer"}, "MANUFACTURER": {"info_key": "manufacturer"},
"MATRIX_HAS_GHOST": {"info_key": "matrix_pins.ghost", "value_type": "bool"},
"MATRIX_IO_DELAY": {"info_key": "matrix_pins.io_delay", "value_type": "int"},
"MOUSEKEY_DELAY": {"info_key": "mousekey.delay", "value_type": "int"},
"MOUSEKEY_INTERVAL": {"info_key": "mousekey.interval", "value_type": "int"},
"MOUSEKEY_MAX_SPEED": {"info_key": "mousekey.max_speed", "value_type": "int"},
"MOUSEKEY_TIME_TO_MAX": {"info_key": "mousekey.time_to_max", "value_type": "int"},
"MOUSEKEY_WHEEL_DELAY": {"info_key": "mousekey.wheel_delay", "value_type": "int"},
"ONESHOT_TIMEOUT": {"info_key": "oneshot.timeout", "value_type": "int"},
"ONESHOT_TAP_TOGGLE": {"info_key": "oneshot.tap_toggle", "value_type": "int"},
"PERMISSIVE_HOLD": {"info_key": "tapping.permissive_hold", "value_type": "bool"},
"PERMISSIVE_HOLD_PER_KEY": {"info_key": "tapping.permissive_hold_per_key", "value_type": "bool"},
"RETRO_TAPPING": {"info_key": "tapping.retro", "value_type": "bool"},
"RETRO_TAPPING_PER_KEY": {"info_key": "tapping.retro_per_key", "value_type": "bool"},
"RGB_DI_PIN": {"info_key": "rgblight.pin"}, "RGB_DI_PIN": {"info_key": "rgblight.pin"},
"RGBLED_NUM": {"info_key": "rgblight.led_count", "value_type": "int"}, "RGBLED_NUM": {"info_key": "rgblight.led_count", "value_type": "int"},
"RGBLED_SPLIT": {"info_key": "rgblight.split_count", "value_type": "array.int"}, "RGBLED_SPLIT": {"info_key": "rgblight.split_count", "value_type": "array.int"},
@@ -30,17 +57,40 @@
"RGBLIGHT_EFFECT_SNAKE": {"info_key": "rgblight.animations.snake", "value_type": "bool"}, "RGBLIGHT_EFFECT_SNAKE": {"info_key": "rgblight.animations.snake", "value_type": "bool"},
"RGBLIGHT_EFFECT_STATIC_GRADIENT": {"info_key": "rgblight.animations.static_gradient", "value_type": "bool"}, "RGBLIGHT_EFFECT_STATIC_GRADIENT": {"info_key": "rgblight.animations.static_gradient", "value_type": "bool"},
"RGBLIGHT_EFFECT_TWINKLE": {"info_key": "rgblight.animations.twinkle"}, "RGBLIGHT_EFFECT_TWINKLE": {"info_key": "rgblight.animations.twinkle"},
"RGBLIGHT_LAYER_BLINK": {"info_key": "rgblight.layers.blink", "value_type": "bool"},
"RGBLIGHT_LAYERS": {"info_key": "rgblight.layers.enabled", "value_type": "bool"},
"RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF": {"info_key": "rgblight.layers.override_rgb", "value_type": "bool"},
"RGBLIGHT_LIMIT_VAL": {"info_key": "rgblight.max_brightness", "value_type": "int"}, "RGBLIGHT_LIMIT_VAL": {"info_key": "rgblight.max_brightness", "value_type": "int"},
"RGBLIGHT_MAX_LAYERS": {"info_key": "rgblight.layers.max", "value_type": "int"},
"RGBLIGHT_HUE_STEP": {"info_key": "rgblight.hue_steps", "value_type": "int"}, "RGBLIGHT_HUE_STEP": {"info_key": "rgblight.hue_steps", "value_type": "int"},
"RGBLIGHT_SAT_STEP": {"info_key": "rgblight.saturation_steps", "value_type": "int"}, "RGBLIGHT_SAT_STEP": {"info_key": "rgblight.saturation_steps", "value_type": "int"},
"RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"}, "RGBLIGHT_VAL_STEP": {"info_key": "rgblight.brightness_steps", "value_type": "int"},
"RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"}, "RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"},
"RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"}, "RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"},
"RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"},
"PRODUCT": {"info_key": "keyboard_folder", "to_json": false}, "PRODUCT": {"info_key": "keyboard_folder", "to_json": false},
"PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex"}, "PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex"},
"VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex"}, "VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex"},
"QMK_ESC_OUTPUT": {"info_key": "qmk_lufa_bootloader.esc_output"}, "QMK_ESC_OUTPUT": {"info_key": "qmk_lufa_bootloader.esc_output"},
"QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"}, "QMK_ESC_INPUT": {"info_key": "qmk_lufa_bootloader.esc_input"},
"QMK_KEYS_PER_SCAN": {"info_key": "qmk.keys_per_scan", "value_type": "int"},
"QMK_LED": {"info_key": "qmk_lufa_bootloader.led"}, "QMK_LED": {"info_key": "qmk_lufa_bootloader.led"},
"QMK_SPEAKER": {"info_key": "qmk_lufa_bootloader.speaker"} "QMK_SPEAKER": {"info_key": "qmk_lufa_bootloader.speaker"},
"SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync_modifiers", "value_type": "bool"},
"SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync_matrix_state", "value_type": "bool"},
"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"},
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
"TAP_CODE_DELAY": {"info_key": "qmk.tap_keycode_delay", "value_type": "int"},
"TAP_HOLD_CAPS_DELAY": {"info_key": "qmk.tap_capslock_delay", "value_type": "int"},
"TAPPING_FORCE_HOLD": {"info_key": "tapping.force_hold", "value_type": "bool"},
"TAPPING_FORCE_HOLD_PER_KEY": {"info_key": "tapping.force_hold_per_key", "value_type": "bool"},
"TAPPING_TERM": {"info_key": "tapping.term", "value_type": "int"},
"TAPPING_TERM_PER_KEY": {"info_key": "tapping.term_per_key", "value_type": "bool"},
"TAPPING_TOGGLE": {"info_key": "tapping.toggle", "value_type": "int"},
"USB_MAX_POWER_CONSUMPTION": {"info_key": "usb.max_power", "value_type": "int"},
"USB_POLLING_INTERVAL_MS": {"info_key": "usb.polling_interval", "value_type": "int"},
"USB_SUSPEND_WAKEUP_DELAY": {"info_key": "usb.suspend_wakeup_delay", "value_type": "int"},
} }

View File

@@ -3,13 +3,23 @@
{ {
# Format: # Format:
# <rules.mk key>: {"info_key": <info.json key>, ["value_type": <value_type>], ["to_json": <true/false>], ["to_c": <true/false>]} # <rules.mk key>: {"info_key": <info.json key>, ["value_type": <value_type>], ["to_json": <true/false>], ["to_c": <true/false>]}
# value_type: one of "array", "array.int", "int", "list", "hex", "mapping" # value_type: one of "array", "array.int", "bool", "int", "list", "hex", "mapping"
# to_json: Default `true`. Set to `false` to exclude this mapping from info.json # to_json: Default `true`. Set to `false` to exclude this mapping from info.json
# to_c: Default `true`. Set to `false` to exclude this mapping from rules.mk # to_c: Default `true`. Set to `false` to exclude this mapping from rules.mk
# warn_duplicate: Default `true`. Set to `false` to turn off warning when a value exists in both places # warn_duplicate: Default `true`. Set to `false` to turn off warning when a value exists in both places
"BOARD": {"info_key": "board"}, "BOARD": {"info_key": "board"},
"BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false}, "BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
"BLUETOOTH": {"info_key": "bluetooth.driver"},
"FIRMWARE_FORMAT": {"info_key": "build.firmware_format"},
"KEYBOARD_SHARED_EP": {"info_key": "usb.shared_endpoint.keyboard", "value_type": "bool"},
"MOUSE_SHARED_EP": {"info_key": "usb.shared_endpoint.mouse", "value_type": "bool"},
"LAYOUTS": {"info_key": "community_layouts", "value_type": "list"}, "LAYOUTS": {"info_key": "community_layouts", "value_type": "list"},
"LED_MATRIX_DRIVER": {"info_key": "led_matrix.driver"}, "LED_MATRIX_DRIVER": {"info_key": "led_matrix.driver"},
"LTO_ENABLE": {"info_key": "build.lto", "value_type": "bool"},
"MCU": {"info_key": "processor", "warn_duplicate": false}, "MCU": {"info_key": "processor", "warn_duplicate": false},
"MOUSEKEY_ENABLE": {"info_key": "mouse_key.enabled", "value_type": "bool"},
"NO_USB_STARTUP_CHECK": {"info_key": "usb.no_startup_check", "value_type": "bool"},
"SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"},
"SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "value_type": "str", "to_c": false},
"WAIT_FOR_USB": {"info_key": "usb.wait_for", "value_type": "bool"}
} }

View File

@@ -11,6 +11,9 @@
'2_milk': { '2_milk': {
target: 'spaceman/2_milk' target: 'spaceman/2_milk'
}, },
'aeboards/constellation': {
target: 'aeboards/constellation/rev1'
},
'aeboards/ext65': { 'aeboards/ext65': {
target: 'aeboards/ext65/rev1' target: 'aeboards/ext65/rev1'
}, },
@@ -38,9 +41,36 @@
'atom47/rev3': { 'atom47/rev3': {
target: 'maartenwut/atom47/rev3' target: 'maartenwut/atom47/rev3'
}, },
bakeneko65: {
target: 'bakeneko65/rev2'
},
bear_face: { bear_face: {
target: 'bear_face/v1' target: 'bear_face/v1'
}, },
bm16a: {
target: 'kprepublic/bm16a'
},
bm16s: {
target: 'kprepublic/bm16s'
},
bm40hsrgb: {
target: 'kprepublic/bm40hsrgb'
},
bm43a: {
target: 'kprepublic/bm43a'
},
bm60poker: {
target: 'kprepublic/bm60poker'
},
bm60rgb: {
target: 'kprepublic/bm60rgb'
},
bm60rgb_iso: {
target: 'kprepublic/bm60rgb_iso'
},
bm68rgb: {
target: 'kprepublic/bm68rgb'
},
'bpiphany/pegasushoof': { 'bpiphany/pegasushoof': {
target: 'bpiphany/pegasushoof/2013' target: 'bpiphany/pegasushoof/2013'
}, },
@@ -56,15 +86,27 @@
canoe: { canoe: {
target: 'percent/canoe' target: 'percent/canoe'
}, },
'clawsome/gamebuddy': {
target: 'clawsome/gamebuddy/v1_0'
},
'cmm_studio/saka68': { 'cmm_studio/saka68': {
target: 'cmm_studio/saka68/solder' target: 'cmm_studio/saka68/solder'
}, },
'cospad': {
target: 'kprepublic/cospad'
},
'crkbd/rev1/legacy': { 'crkbd/rev1/legacy': {
target: 'crkbd/rev1' target: 'crkbd/rev1'
}, },
'crkbd/rev1/common': { 'crkbd/rev1/common': {
target: 'crkbd/rev1' target: 'crkbd/rev1'
}, },
'custommk/genesis': {
target: 'custommk/genesis/rev1'
},
'daisy': {
target: 'ktec/daisy'
},
'doro67/multi': { 'doro67/multi': {
layouts: { layouts: {
LAYOUT_ansi: 'LAYOUT_65_ansi_blocker' LAYOUT_ansi: 'LAYOUT_65_ansi_blocker'
@@ -83,6 +125,9 @@
drakon: { drakon: {
target: 'jagdpietr/drakon' target: 'jagdpietr/drakon'
}, },
'durgod/k320': {
target: 'durgod/k3x0/k320'
},
'dztech/dz60rgb': { 'dztech/dz60rgb': {
target: 'dztech/dz60rgb/v1' target: 'dztech/dz60rgb/v1'
}, },
@@ -95,9 +140,15 @@
'dztech/dz65rgb': { 'dztech/dz65rgb': {
target: 'dztech/dz65rgb/v1' target: 'dztech/dz65rgb/v1'
}, },
'dztech/volcano660': {
target: 'ilumkb/volcano660'
},
eek: { eek: {
target: 'eek/silk_down' target: 'eek/silk_down'
}, },
'ergodone': {
target: 'ktec/ergodone'
},
ergoinu: { ergoinu: {
target: 'dm9records/ergoinu' target: 'dm9records/ergoinu'
}, },
@@ -107,9 +158,15 @@
gh60: { gh60: {
target: 'gh60/revc' target: 'gh60/revc'
}, },
'gmmk/pro': {
target: 'gmmk/pro/ansi'
},
'handwired/ferris': { 'handwired/ferris': {
target: 'ferris/0_1' target: 'ferris/0_1'
}, },
'handwired/p1800fl': {
target: 'team0110/p1800fl'
},
'helix/pico/sc/back': { 'helix/pico/sc/back': {
target: 'helix/pico/sc' target: 'helix/pico/sc'
}, },
@@ -158,6 +215,15 @@
LAYOUT: 'LAYOUT_all' LAYOUT: 'LAYOUT_all'
} }
}, },
'jj40': {
target: 'kprepublic/jj40'
},
'jj4x4': {
target: 'kprepublic/jj4x4'
},
'jj50': {
target: 'kprepublic/jj50'
},
jones: { jones: {
target: 'jones/v03_1' target: 'jones/v03_1'
}, },
@@ -182,6 +248,12 @@
kudox: { kudox: {
target: 'kudox/rev1' target: 'kudox/rev1'
}, },
'kyria': {
target: 'splitkb/kyria'
},
'lazydesigners/the60': {
target: 'lazydesigners/the60/rev1'
},
'lfkeyboards/lfk78': { 'lfkeyboards/lfk78': {
target: 'lfkeyboards/lfk78/revj' target: 'lfkeyboards/lfk78/revj'
}, },
@@ -251,6 +323,9 @@
'maartenwut/wonderland': { 'maartenwut/wonderland': {
target: 'evyd13/wonderland' target: 'evyd13/wonderland'
}, },
'matrix/m12og': {
target: 'matrix/m12og/rev1'
},
'mechlovin/hannah910': { 'mechlovin/hannah910': {
target: 'mechlovin/hannah910/rev1' target: 'mechlovin/hannah910/rev1'
}, },
@@ -266,6 +341,9 @@
'mechlovin/hannah60rgb': { 'mechlovin/hannah60rgb': {
target: 'mechlovin/hannah60rgb/rev1' target: 'mechlovin/hannah60rgb/rev1'
}, },
'mechlovin/hannah65/mechlovin9': {
target: 'mechlovin/mechlovin9/rev1'
},
'melgeek/z70ultra': { 'melgeek/z70ultra': {
target: 'melgeek/z70ultra/rev1' target: 'melgeek/z70ultra/rev1'
}, },
@@ -304,6 +382,9 @@
'pancake/promicro': { 'pancake/promicro': {
target: 'spaceman/pancake/promicro' target: 'spaceman/pancake/promicro'
}, },
'peiorisboards/ixora': {
target: 'coarse/ixora'
},
'percent/canoe': { 'percent/canoe': {
layouts: { layouts: {
LAYOUT_iso: 'LAYOUT_65_iso_blocker' LAYOUT_iso: 'LAYOUT_65_iso_blocker'
@@ -366,6 +447,9 @@
'ramonimbao/herringbone': { 'ramonimbao/herringbone': {
target: 'ramonimbao/herringbone/v1' target: 'ramonimbao/herringbone/v1'
}, },
'ramonimbao/mona': {
target: 'ramonimbao/mona/v1'
},
'rgbkb/pan': { 'rgbkb/pan': {
target: 'rgbkb/pan/rev1/32a' target: 'rgbkb/pan/rev1/32a'
}, },
@@ -387,6 +471,9 @@
speedo: { speedo: {
target: 'cozykeys/speedo/v2' target: 'cozykeys/speedo/v2'
}, },
'staryu': {
target: 'ktec/staryu'
},
stoutgat: { stoutgat: {
target: 'tkw/stoutgat/v1' target: 'tkw/stoutgat/v1'
}, },
@@ -405,10 +492,14 @@
'tkw/stoutgat/v2': { 'tkw/stoutgat/v2': {
target: 'tkw/stoutgat/v2/f411' target: 'tkw/stoutgat/v2/f411'
}, },
'tokyo60': {
target: 'tokyokeyboard/tokyo60'
},
underscore33: { underscore33: {
target: 'underscore33/rev1' target: 'underscore33/rev1'
}, },
vinta: { vinta: {
target: 'coarse/vinta',
layouts: { layouts: {
LAYOUT_67_ansi: 'LAYOUT_65_ansi_blocker' LAYOUT_67_ansi: 'LAYOUT_65_ansi_blocker'
} }
@@ -422,6 +513,33 @@
'whale/sk': { 'whale/sk': {
target: 'whale/sk/v3' target: 'whale/sk/v3'
}, },
'xd002': {
target: 'xiudi/xd002'
},
'xd004': {
target: 'xiudi/xd004'
},
'xd60': {
target: 'xiudi/xd60'
},
'xd68': {
target: 'xiudi/xd68'
},
'xd75': {
target: 'xiudi/xd75'
},
'xd84': {
target: 'xiudi/xd84'
},
'xd84pro': {
target: 'xiudi/xd84pro'
},
'xd87': {
target: 'xiudi/xd87'
},
'xd96': {
target: 'xiudi/xd96'
},
'xelus/dawn60': { 'xelus/dawn60': {
target: 'xelus/dawn60/rev1' target: 'xelus/dawn60/rev1'
}, },

View File

@@ -1,34 +1,22 @@
{ {
"allOf": [
{ "$ref": "qmk.keyboard.v1" },
{
"$id": "qmk.api.keyboard.v1", "$id": "qmk.api.keyboard.v1",
"allOf": [
{"$ref": "qmk.keyboard.v1"},
{
"properties": {
"keymaps": { "keymaps": {
"type": "string" "type": "object",
}, "properties": {
"parse_errors": { "url": {"type": "string"}
"type": "array",
"items": {
"type": "string"
} }
}, },
"parse_warnings": { "parse_errors": {"$ref": "qmk.definitions.v1#/string_array"},
"type": "array", "parse_warnings": {"$ref": "qmk.definitions.v1#/string_array"},
"items": { "processor_type": {"type": "string"},
"type": "string" "protocol": {"type": "string"},
} "keyboard_folder": {"type": "string"},
}, "platform": {"type": "string"}
"processor_type": {
"type": "string"
},
"protocol": {
"type": "string"
},
"keyboard_folder": {
"type": "string"
},
"platform": {
"type": "string"
} }
} }
] ]

View File

@@ -0,0 +1,107 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "qmk.definitions.v1",
"title": "Common definitions used across QMK's jsonschemas.",
"type": "object",
"boolean_array": {
"type": "object",
"additionalProperties": {"type": "boolean"}
},
"filename": {
"type": "string",
"minLength": 1,
"pattern": "^[0-9a-z_]*$"
},
"hex_number_2d": {
"type": "string",
"pattern": "^0x[0-9A-F]{2}$"
},
"hex_number_4d": {
"type": "string",
"pattern": "^0x[0-9A-F]{4}$"
},
"text_identifier": {
"type": "string",
"minLength": 1,
"maxLength": 250
},
"layout_macro": {
"oneOf": [
{
"type": "string",
"enum": ["LAYOUT", "LAYOUT_planck_1x2uC"]
},
{
"type": "string",
"pattern": "^LAYOUT_[0-9a-z_]*$"
}
]
},
"key_unit": {
"type": "number",
"min": 0.25
},
"mcu_pin_array": {
"type": "array",
"items": {"$ref": "#/mcu_pin"}
},
"mcu_pin": {
"oneOf": [
{
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
},
{
"type": "string",
"pattern": "^LINE_PIN\\d{1,2}$"
},
{
"type": "number",
"multipleOf": 1
},
{
"type": "null"
}
]
},
"signed_decimal": {
"type": "number"
},
"signed_int": {
"type": "number",
"multipleOf": 1
}
"signed_int_8": {
"type": "number",
"min": -127,
"max": 127,
"multipleOf": 1
}
"string_array": {
"type": "array",
"items": {
"type": "string"
}
},
"string_object": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"unsigned_decimal": {
"type": "number",
"min": 0
},
"unsigned_int": {
"type": "number",
"min": 0,
"multipleOf": 1
}
"unsigned_int_8": {
"type": "number",
"min": 0,
"max": 255,
"multipleOf": 1
}
}

View File

@@ -1,31 +1,53 @@
{ {
"$schema": "http://json-schema.org/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"$id": "qmk.keyboard.v1", "$id": "qmk.keyboard.v1",
"title": "Keyboard Information", "title": "Keyboard Information",
"type": "object", "type": "object",
"properties": { "properties": {
"keyboard_name": { "keyboard_name": {"$ref": "qmk.definitions.v1#/text_identifier"},
"type": "string", "maintainer": {"$ref": "qmk.definitions.v1#/text_identifier"},
"minLength": 2, "manufacturer": {"$ref": "qmk.definitions.v1#/text_identifier"},
"maxLength": 250
},
"maintainer": {
"type": "string",
"minLength": 2,
"maxLength": 250
},
"manufacturer": {
"type": "string",
"minLength": 2,
"maxLength": 250
},
"url": { "url": {
"type": "string", "type": "string",
"format": "uri" "format": "uri"
}, },
"processor": { "processor": {
"type": "string", "type": "string",
"enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66F18", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L433", "STM32L443", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"] "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66F18", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L433", "STM32L443", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
},
"audio": {
"type": "object",
"additionalProperties": false,
"properties": {
"pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"voices": {"type": "boolean"}
}
},
"backlight": {
"type": "object",
"additionalProperties": false,
"properties": {
"breathing": {"type": "boolean"},
"breathing_period": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"levels": {
"type": "number",
"min": 1,
"max": 31,
"multipleOf": 1
},
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
}
},
"bluetooth": {
"type": "object",
"additionalProperties": false,
"properties": {
"driver": {
"type": "string",
"enum": ["AdafruitBLE", "RN42"]
},
"lto": {"type": "boolean"},
}
}, },
"board": { "board": {
"type": "string", "type": "string",
@@ -34,68 +56,55 @@
}, },
"bootloader": { "bootloader": {
"type": "string", "type": "string",
"enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "stm32-dfu", "stm32duino", "unknown", "USBasp", "tinyuf2"] "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "unknown", "usbasploader", "USBasp", "tinyuf2"],
},
"bootloader_instructions": {
"type": "string",
"description": "Instructions for putting the keyboard into a mode that allows for firmware flashing."
},
"build": {
"type": "object",
"additionalProperties": false,
"properties": {
"debounce_type": {
"type": "string",
"enum": ["custom", "eager_pk", "eager_pr", "sym_defer_pk", "sym_eager_pk"]
},
"firmware_format": {
"type": "string",
"enum": ["bin", "hex", "uf2"]
},
"lto": {"type": "boolean"},
}
}, },
"diode_direction": { "diode_direction": {
"type": "string", "type": "string",
"enum": ["COL2ROW", "ROW2COL"] "enum": ["COL2ROW", "ROW2COL"]
}, },
"debounce": { "debounce": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"type": "number", "combo": {
"min": 0, "type": "object",
"multipleOf": 1 "properties": {
}, "count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"height": { "term": {"$ref": "qmk.definitions.v1#/unsigned_int"}
"type": "number", }
"min": 0.25
},
"width": {
"type": "number",
"min": 0.25
}, },
"community_layouts": { "community_layouts": {
"type": "array", "type": "array",
"items": { "items": {"$ref": "qmk.definitions.v1#/filename"}
"type": "string",
"minLength": 2,
"pattern": "^[0-9a-z_]*$"
}
},
"features": {
"type": "object",
"additionalProperties": {"type": "boolean"}
}, },
"features": {"$ref": "qmk.definitions.v1#/boolean_array"},
"indicators": { "indicators": {
"type": "object", "type": "object",
"properties": { "properties": {
"caps_lock": { "caps_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"type": "string", "num_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"pattern": "^[A-K]\\d{1,2}$" "scroll_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"}
},
"num_lock": {
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
},
"scroll_lock": {
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
}
} }
}, },
"layout_aliases": { "layout_aliases": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {"$ref": "qmk.definitions.v1#/layout_macro"}
"oneOf": [
{
"type": "string",
"enum": ["LAYOUT", "LAYOUT_planck_1x2uC"]
},
{
"type": "string",
"pattern": "^LAYOUT_[0-9a-z_]*$"
}
]
}
}, },
"layouts": { "layouts": {
"type": "object", "type": "object",
@@ -109,11 +118,6 @@
"c_macro": { "c_macro": {
"type": "boolean" "type": "boolean"
}, },
"key_count": {
"type": "number",
"min": 0,
"multipleOf": 1
},
"layout": { "layout": {
"type": "array", "type": "array",
"items": { "items": {
@@ -131,101 +135,60 @@
"multipleOf": 1 "multipleOf": 1
} }
}, },
"h": { "r": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
"type": "number", "rx": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
"min": 0.25 "ry": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
}, "h": {"$ref": "qmk.definitions.v1#/key_unit"},
"r": { "w": {"$ref": "qmk.definitions.v1#/key_unit"},
"type": "number", "x": {"$ref": "qmk.definitions.v1#/key_unit"},
"min": 0 "y": {"$ref": "qmk.definitions.v1#/key_unit"}
},
"rx": {
"type": "number",
"min": 0
},
"ry": {
"type": "number",
"min": 0
},
"w": {
"type": "number",
"min": 0.25
},
"x": {
"type": "number",
"min": 0
},
"y": {
"type": "number",
"min": 0
} }
} }
} }
} }
} }
},
"leader_key": {
"type": "object",
"properties": {
"timing": {"type": "boolean"},
"strict_processing": {"type": "boolean"},
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
} }
}, },
"matrix_pins": { "matrix_pins": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"custom": {"type": "boolean"},
"custom_lite": {"type": "boolean"},
"ghost": {"type": "boolean"},
"io_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"direct": { "direct": {
"type": "array", "type": "array",
"items": { "items": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
"type": "array",
"items": {
"oneOf": [
{
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
}, },
{ "cols": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"type": "number", "rows": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"multipleOf": 1 "unused": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
},
{
"type": "null"
}
]
}
} }
}, },
"cols": { "mouse_key": {
"type": "array", "type": "object",
"items": { "properties": {
"oneOf": [ "enabled": {"type": "boolean"},
{ "delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
"type": "string", "interval": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
"pattern": "^[A-K]\\d{1,2}$" "max_speed": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
}, "time_to_max": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
{ "wheel_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
"type": "number",
"multipleOf": 1
},
{
"type": "null"
}
]
} }
}, },
"rows": { "oneshot": {
"type": "array", "type": "object",
"items": { "properties": {
"oneOf": [ "tap_toggle": {"$ref": "qmk.definitions.v1#/unsigned_int"},
{ "timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
},
{
"type": "number",
"multipleOf": 1
},
{
"type": "null"
}
]
}
}
} }
}, },
"rgblight": { "rgblight": {
@@ -238,88 +201,160 @@
"type": "boolean" "type": "boolean"
} }
}, },
"brightness_steps": { "brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"layers": {
"type": "object",
"additionalProperties": false,
"properties": {
"blink": {"type": "boolean"},
"enabled": {"type": "boolean"},
"max": {
"type": "number", "type": "number",
"min": 0, "min": 1,
"max": 32,
"multipleOf": 1 "multipleOf": 1
}, },
"hue_steps": { "override_rgb": {"type": "boolean"}
"type": "number", }
"min": 0,
"multipleOf": 1
},
"led_count": {
"type": "number",
"min": 0,
"multipleOf": 1
},
"max_brightness": {
"type": "number",
"min": 0,
"max": 255,
"multipleOf": 1
},
"pin": {
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
},
"saturation_steps": {
"type": "number",
"min": 0,
"multipleOf": 1
}, },
"led_count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"rgbw": {"type": "boolean"},
"saturation_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"sleep": {"type": "boolean"}, "sleep": {"type": "boolean"},
"split": {"type": "boolean"}, "split": {"type": "boolean"},
"split_count": { "split_count": {
"type": "array", "type": "array",
"minLength": 2, "minLength": 2,
"maxLength": 2, "maxLength": 2,
"items": { "items": {"$ref": "qmk.definitions.v1#/unsigned_int"}
}
}
},
"split": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {"type": "boolean"},
"matrix_grid": {
"type": "array",
"items": {"$ref": "qmk.definitions.v1#/mcu_pin"}
},
"matrix_pins": {
"type": "object",
"additionalProperties": false,
"properties": {
"right": {
"type": "object",
"additionalProperties": false,
"properties": {
"direct": {
"type": "array",
"items": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
},
"cols": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"rows": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"unused": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
}
}
}
},
"main": {
"type": "string",
"enum": ["eeprom", "left", "matrix_grid", "pin", "right"]
},
"soft_serial_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"soft_serial_speed": {
"type": "number", "type": "number",
"min": 0, "min": 0,
"max": 5,
"multipleOf": 1 "multipleOf": 1
},
"transport": {
"type": "object",
"additionalProperties": false,
"properties": {
"protocol": {
"type": "string",
"enum": ["custom", "i2c", "serial", "serial_usart"]
},
"sync_matrix_state": {"type": "boolean"},
"sync_modifiers": {"type": "boolean"}
}
},
"usb_detect": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {"type": "boolean"},
"polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
} }
} }
} }
}, },
"tags": {
"type": "array",
"items": {"type": "string"}
},
"tapping": {
"type": "object",
"properties": {
"force_hold": {"type": "boolean"},
"force_hold_per_key": {"type": "boolean"},
"ignore_mod_tap_interrupt": {"type": "boolean"},
"ignore_mod_tap_interrupt_per_key": {"type": "boolean"},
"permissive_hold": {"type": "boolean"},
"permissive_hold_per_key": {"type": "boolean"},
"retro": {"type": "boolean"},
"retro_per_key": {"type": "boolean"},
"term": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"term_per_key": {"type": "boolean"},
"toggle": {"$ref": "qmk.definitions.v1#/unsigned_int"},
}
},
"usb": { "usb": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"device_ver": { "device_ver": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
"type": "string", "force_nkro": {"type": "boolean"},
"pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]" "pid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
}, "vid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
"pid": { "max_power": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"type": "string", "no_startup_check": {"type": "boolean"},
"pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]" "polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
}, "shared_endpoint": {
"vid": { "type": "object",
"type": "string", "additionalProperties": false,
"pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]" "properties": {
"keyboard": {"type": "boolean"},
"mouse": {"type": "boolean"}
} }
},
"suspend_wakeup_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"wait_for": {"type": "boolean"},
}
},
"qmk": {
"type": "object",
"additionalProperties": false,
"properties": {
"keys_per_scan": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"tap_keycode_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
} }
}, },
"qmk_lufa_bootloader": { "qmk_lufa_bootloader": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"esc_output": { "esc_output": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"type": "string", "esc_input": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"pattern": "^[A-K]\\d{1,2}$" "led": {"$ref": "qmk.definitions.v1#/mcu_pin"},
}, "speaker": {"$ref": "qmk.definitions.v1#/mcu_pin"}
"esc_input": {
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
},
"led": {
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
},
"speaker": {
"type": "string",
"pattern": "^[A-K]\\d{1,2}$"
}
} }
} }
} }

View File

@@ -0,0 +1,24 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "qmk.keymap.v1",
"title": "Keymap Information",
"type": "object",
"properties": {
"author": {"type": "string"},
"keyboard": {"$ref": "qmk.definitions.v1#/text_identifier"},
"keymap": {"$ref": "qmk.definitions.v1#/text_identifier"},
"layout": {"$ref": "qmk.definitions.v1#/layout_macro"},
"layers": {
"type": "array",
"items": {
"type": "array",
"items": {"type": "string"}
}
},
"config": {"$ref": "qmk.keyboard.v1"},
"notes": {
"type": "string",
"description": "asdf"
}
}
}

View File

@@ -17,3 +17,11 @@ Flashing example for this keyboard:
make %KEYBOARD%:default:flash make %KEYBOARD%:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead
* **Keycode in layout**: Press the key mapped to `RESET` if it is available

View File

@@ -7,7 +7,7 @@ BOOTLOADER = atmel-dfu
# Build Options # Build Options
# change yes to no to disable # change yes to no to disable
# #
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug CONSOLE_ENABLE = no # Console for debug
@@ -18,5 +18,4 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
NKRO_ENABLE = no # USB Nkey Rollover NKRO_ENABLE = no # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no # Enable Bluetooth
AUDIO_ENABLE = no # Audio output AUDIO_ENABLE = no # Audio output

View File

@@ -2,8 +2,6 @@
"keyboard_name": "%KEYBOARD%", "keyboard_name": "%KEYBOARD%",
"url": "", "url": "",
"maintainer": "%YOUR_NAME%", "maintainer": "%YOUR_NAME%",
"width": 3,
"height": 2,
"layouts": { "layouts": {
"LAYOUT": { "LAYOUT": {
"layout": [ "layout": [

View File

@@ -16,6 +16,13 @@ Flashing example for this keyboard ([after setting up the bootloadHID flashing e
make %KEYBOARD%:default:flash make %KEYBOARD%:default:flash
**Reset Key**: Hold down the key located at *LOCATION*, commonly programmed as *KEY* while plugging in the keyboard.
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **BootloadHID reset**: Hold down the key connected to the `A0` and `B0` pins on the MCU if it is known (often top left or bottom left) and plug in the keyboard
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead
* **Keycode in layout**: Press the key mapped to `RESET` if it is available

View File

@@ -2,12 +2,12 @@
MCU = atmega32a MCU = atmega32a
# Bootloader selection # Bootloader selection
BOOTLOADER = bootloadHID BOOTLOADER = bootloadhid
# Build Options # Build Options
# change yes to no to disable # change yes to no to disable
# #
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug CONSOLE_ENABLE = no # Console for debug

View File

@@ -21,7 +21,6 @@ quantum/tools
quantum/visualizer quantum/visualizer
quantum/visualizer/resources quantum/visualizer/resources
drivers drivers
drivers/avr
drivers/ugfx drivers/ugfx
drivers/ugfx/gdisp drivers/ugfx/gdisp
drivers/ugfx/gdisp/is31fl3731c drivers/ugfx/gdisp/is31fl3731c

View File

@@ -1,62 +0,0 @@
#pragma once
#include <stdbool.h>
// /////////////////////////////////////////////////////////////////
// Need Soft Serial defines in config.h
// /////////////////////////////////////////////////////////////////
// ex.
// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
// // 1: about 137kbps (default)
// // 2: about 75kbps
// // 3: about 39kbps
// // 4: about 26kbps
// // 5: about 20kbps
//
// //// USE simple API (using signle-type transaction function)
// /* nothing */
// //// USE flexible API (using multi-type transaction function)
// #define SERIAL_USE_MULTI_TRANSACTION
//
// /////////////////////////////////////////////////////////////////
// Soft Serial Transaction Descriptor
typedef struct _SSTD_t {
uint8_t *status;
uint8_t initiator2target_buffer_size;
uint8_t *initiator2target_buffer;
uint8_t target2initiator_buffer_size;
uint8_t *target2initiator_buffer;
} SSTD_t;
#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t))
// initiator is transaction start side
void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
// target is interrupt accept side
void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
// initiator resullt
#define TRANSACTION_END 0
#define TRANSACTION_NO_RESPONSE 0x1
#define TRANSACTION_DATA_ERROR 0x2
#define TRANSACTION_TYPE_ERROR 0x4
#ifndef SERIAL_USE_MULTI_TRANSACTION
int soft_serial_transaction(void);
#else
int soft_serial_transaction(int sstd_index);
#endif
// target status
// *SSTD_t.status has
// initiator:
// TRANSACTION_END
// or TRANSACTION_NO_RESPONSE
// or TRANSACTION_DATA_ERROR
// target:
// TRANSACTION_DATA_ERROR
// or TRANSACTION_ACCEPTED
#define TRANSACTION_ACCEPTED 0x8
#ifdef SERIAL_USE_MULTI_TRANSACTION
int soft_serial_get_and_clean_status(int sstd_index);
#endif

View File

@@ -1,62 +0,0 @@
#pragma once
#include <stdbool.h>
// /////////////////////////////////////////////////////////////////
// Need Soft Serial defines in config.h
// /////////////////////////////////////////////////////////////////
// ex.
// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
// // 1: about 137kbps (default)
// // 2: about 75kbps
// // 3: about 39kbps
// // 4: about 26kbps
// // 5: about 20kbps
//
// //// USE simple API (using signle-type transaction function)
// /* nothing */
// //// USE flexible API (using multi-type transaction function)
// #define SERIAL_USE_MULTI_TRANSACTION
//
// /////////////////////////////////////////////////////////////////
// Soft Serial Transaction Descriptor
typedef struct _SSTD_t {
uint8_t *status;
uint8_t initiator2target_buffer_size;
uint8_t *initiator2target_buffer;
uint8_t target2initiator_buffer_size;
uint8_t *target2initiator_buffer;
} SSTD_t;
#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t))
// initiator is transaction start side
void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
// target is interrupt accept side
void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
// initiator result
#define TRANSACTION_END 0
#define TRANSACTION_NO_RESPONSE 0x1
#define TRANSACTION_DATA_ERROR 0x2
#define TRANSACTION_TYPE_ERROR 0x4
#ifndef SERIAL_USE_MULTI_TRANSACTION
int soft_serial_transaction(void);
#else
int soft_serial_transaction(int sstd_index);
#endif
// target status
// *SSTD_t.status has
// initiator:
// TRANSACTION_END
// or TRANSACTION_NO_RESPONSE
// or TRANSACTION_DATA_ERROR
// target:
// TRANSACTION_DATA_ERROR
// or TRANSACTION_ACCEPTED
#define TRANSACTION_ACCEPTED 0x8
#ifdef SERIAL_USE_MULTI_TRANSACTION
int soft_serial_get_and_clean_status(int sstd_index);
#endif

View File

@@ -1,219 +0,0 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serial_usart.h"
#ifndef USE_GPIOV1
// The default PAL alternate modes are used to signal that the pins are used for USART
# ifndef SERIAL_USART_TX_PAL_MODE
# define SERIAL_USART_TX_PAL_MODE 7
# endif
#endif
#ifndef SERIAL_USART_DRIVER
# define SERIAL_USART_DRIVER SD1
#endif
#ifdef SOFT_SERIAL_PIN
# define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN
#endif
static inline msg_t sdWriteHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size) {
msg_t ret = sdWrite(driver, data, size);
// Half duplex requires us to read back the data we just wrote - just throw it away
uint8_t dump[size];
sdRead(driver, dump, size);
return ret;
}
#undef sdWrite
#define sdWrite sdWriteHalfDuplex
static inline msg_t sdWriteTimeoutHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size, uint32_t timeout) {
msg_t ret = sdWriteTimeout(driver, data, size, timeout);
// Half duplex requires us to read back the data we just wrote - just throw it away
uint8_t dump[size];
sdReadTimeout(driver, dump, size, timeout);
return ret;
}
#undef sdWriteTimeout
#define sdWriteTimeout sdWriteTimeoutHalfDuplex
static inline void sdClear(SerialDriver* driver) {
while (sdGetTimeout(driver, TIME_IMMEDIATE) != MSG_TIMEOUT) {
// Do nothing with the data
}
}
static SerialConfig sdcfg = {
(SERIAL_USART_SPEED), // speed - mandatory
(SERIAL_USART_CR1), // CR1
(SERIAL_USART_CR2), // CR2
(SERIAL_USART_CR3) // CR3
};
void handle_soft_serial_slave(void);
/*
* This thread runs on the slave and responds to transactions initiated
* by the master
*/
static THD_WORKING_AREA(waSlaveThread, 2048);
static THD_FUNCTION(SlaveThread, arg) {
(void)arg;
chRegSetThreadName("slave_transport");
while (true) {
handle_soft_serial_slave();
}
}
__attribute__((weak)) void usart_init(void) {
#if defined(USE_GPIOV1)
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
#else
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
#endif
#if defined(USART_REMAP)
USART_REMAP;
#endif
}
void usart_master_init(void) {
usart_init();
sdcfg.cr3 |= USART_CR3_HDSEL;
sdStart(&SERIAL_USART_DRIVER, &sdcfg);
}
void usart_slave_init(void) {
usart_init();
sdcfg.cr3 |= USART_CR3_HDSEL;
sdStart(&SERIAL_USART_DRIVER, &sdcfg);
// Start transport thread
chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
}
static SSTD_t* Transaction_table = NULL;
static uint8_t Transaction_table_size = 0;
void soft_serial_initiator_init(SSTD_t* sstd_table, int sstd_table_size) {
Transaction_table = sstd_table;
Transaction_table_size = (uint8_t)sstd_table_size;
usart_master_init();
}
void soft_serial_target_init(SSTD_t* sstd_table, int sstd_table_size) {
Transaction_table = sstd_table;
Transaction_table_size = (uint8_t)sstd_table_size;
usart_slave_init();
}
void handle_soft_serial_slave(void) {
uint8_t sstd_index = sdGet(&SERIAL_USART_DRIVER); // first chunk is always transaction id
SSTD_t* trans = &Transaction_table[sstd_index];
// Always write back the sstd_index as part of a basic handshake
sstd_index ^= HANDSHAKE_MAGIC;
sdWrite(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index));
if (trans->initiator2target_buffer_size) {
sdRead(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size);
}
if (trans->target2initiator_buffer_size) {
sdWrite(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size);
}
if (trans->status) {
*trans->status = TRANSACTION_ACCEPTED;
}
}
/////////
// start transaction by initiator
//
// int soft_serial_transaction(int sstd_index)
//
// Returns:
// TRANSACTION_END
// TRANSACTION_NO_RESPONSE
// TRANSACTION_DATA_ERROR
#ifndef SERIAL_USE_MULTI_TRANSACTION
int soft_serial_transaction(void) {
uint8_t sstd_index = 0;
#else
int soft_serial_transaction(int index) {
uint8_t sstd_index = index;
#endif
if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR;
SSTD_t* trans = &Transaction_table[sstd_index];
msg_t res = 0;
sdClear(&SERIAL_USART_DRIVER);
// First chunk is always transaction id
<<<<<<< HEAD
sdWriteTimeout(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index), TIME_MS2I(TIMEOUT));
=======
sdWriteTimeout(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index), TIME_MS2I(SERIAL_USART_TIMEOUT));
// - due to the half duplex limitations on return codes, we always have to read *something*
// - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready
<<<<<<< HEAD
res = sdReadTimeout(&SERIAL_USART_DRIVER, &sstd_index_shake, sizeof(sstd_index_shake), TIME_MS2I(TIMEOUT));
=======
res = sdReadTimeout(&SERIAL_USART_DRIVER, &sstd_index_shake, sizeof(sstd_index_shake), TIME_MS2I(SERIAL_USART_TIMEOUT));
>>>>>>> 0.12.52~1
if (res < 0 || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
dprintf("serial::usart_shake NO_RESPONSE\n");
return TRANSACTION_NO_RESPONSE;
}
if (trans->initiator2target_buffer_size) {
<<<<<<< HEAD
res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(TIMEOUT));
=======
res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
>>>>>>> 0.12.52~1
if (res < 0) {
dprintf("serial::usart_transmit NO_RESPONSE\n");
return TRANSACTION_NO_RESPONSE;
}
}
if (trans->target2initiator_buffer_size) {
<<<<<<< HEAD
res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(TIMEOUT));
=======
res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
>>>>>>> 0.12.52~1
if (res < 0) {
dprintf("serial::usart_receive NO_RESPONSE\n");
return TRANSACTION_NO_RESPONSE;
}
}
return TRANSACTION_END;
}

View File

@@ -1,261 +0,0 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serial_usart.h"
#include <stdatomic.h>
#if !defined(USE_GPIOV1)
// The default PAL alternate modes are used to signal that the pins are used for USART
# if !defined(SERIAL_USART_TX_PAL_MODE)
# define SERIAL_USART_TX_PAL_MODE 7
# endif
# if !defined(SERIAL_USART_RX_PAL_MODE)
# define SERIAL_USART_RX_PAL_MODE 7
# endif
#endif
#if !defined(SERIAL_USART_DRIVER)
# define SERIAL_USART_DRIVER UARTD1
#endif
#if !defined(SERIAL_USART_TX_PIN)
# define SERIAL_USART_TX_PIN A9
#endif
#if !defined(SERIAL_USART_RX_PIN)
# define SERIAL_USART_RX_PIN A10
#endif
#define SIGNAL_HANDSHAKE_RECEIVED 0x1
void handle_transactions_slave(uint8_t sstd_index);
static void receive_transaction_handshake(UARTDriver* uartp, uint16_t received_handshake);
/*
* UART driver configuration structure. We use the blocking DMA enabled API and
* the rxchar callback to receive handshake tokens but only on the slave halve.
*/
// clang-format off
static UARTConfig uart_config = {
.txend1_cb = NULL,
.txend2_cb = NULL,
.rxend_cb = NULL,
.rxchar_cb = NULL,
.rxerr_cb = NULL,
.timeout_cb = NULL,
.speed = (SERIAL_USART_SPEED),
.cr1 = (SERIAL_USART_CR1),
.cr2 = (SERIAL_USART_CR2),
.cr3 = (SERIAL_USART_CR3)
};
// clang-format on
static SSTD_t* Transaction_table = NULL;
static uint8_t Transaction_table_size = 0;
static atomic_uint_least8_t handshake = 0xFF;
static thread_reference_t tp_target = NULL;
/*
* This callback is invoked when a character is received but the application
* was not ready to receive it, the character is passed as parameter.
* Receive transaction table index from initiator, which doubles as basic handshake token. */
static void receive_transaction_handshake(UARTDriver* uartp, uint16_t received_handshake) {
/* Check if received handshake is not a valid transaction id.
* Please note that we can still catch a seemingly valid handshake
* i.e. a byte from a ongoing transfer which is in the allowed range.
* So this check mainly prevents any obviously wrong handshakes and
* subsequent wakeups of the receiving thread, which is a costly operation. */
if (received_handshake > Transaction_table_size) {
return;
}
handshake = (uint8_t)received_handshake;
chSysLockFromISR();
/* Wakeup receiving thread to start a transaction. */
chEvtSignalI(tp_target, (eventmask_t)SIGNAL_HANDSHAKE_RECEIVED);
chSysUnlockFromISR();
}
__attribute__((weak)) void usart_init(void) {
#if defined(USE_GPIOV1)
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
#else
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
#endif
}
/*
* This thread runs on the slave half and reacts to transactions initiated from the master.
*/
static THD_WORKING_AREA(waSlaveThread, 1024);
static THD_FUNCTION(SlaveThread, arg) {
(void)arg;
chRegSetThreadName("slave_usart_tx_rx");
while (true) {
/* We sleep as long as there is no handshake waiting for us. */
chEvtWaitAny((eventmask_t)SIGNAL_HANDSHAKE_RECEIVED);
handle_transactions_slave(handshake);
}
}
void soft_serial_target_init(SSTD_t* const sstd_table, int sstd_table_size) {
Transaction_table = sstd_table;
Transaction_table_size = (uint8_t)sstd_table_size;
usart_init();
#if defined(USART_REMAP)
USART_REMAP;
#endif
tp_target = chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
// Start receiving handshake tokens on slave halve
uart_config.rxchar_cb = receive_transaction_handshake;
uartStart(&SERIAL_USART_DRIVER, &uart_config);
}
/**
* @brief React to transactions started by the master.
* This version uses duplex send and receive usart pheriphals and DMA backed transfers.
*/
void inline handle_transactions_slave(uint8_t sstd_index) {
size_t buffer_size = 0;
msg_t msg = 0;
SSTD_t* trans = &Transaction_table[sstd_index];
/* Send back the handshake which is XORed as a simple checksum,
to signal that the slave is ready to receive possible transaction buffers */
sstd_index ^= HANDSHAKE_MAGIC;
buffer_size = (size_t)sizeof(sstd_index);
msg = uartSendTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index, TIME_MS2I(SERIAL_USART_TIMEOUT));
if (msg != MSG_OK) {
if (trans->status) {
*trans->status = TRANSACTION_NO_RESPONSE;
}
return;
}
/* Receive transaction buffer from the master. If this transaction requires it.*/
buffer_size = (size_t)trans->initiator2target_buffer_size;
if (buffer_size) {
msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->initiator2target_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
if (msg != MSG_OK) {
if (trans->status) {
*trans->status = TRANSACTION_NO_RESPONSE;
}
return;
}
}
/* Send transaction buffer to the master. If this transaction requires it. */
buffer_size = (size_t)trans->target2initiator_buffer_size;
if (buffer_size) {
msg = uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->target2initiator_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
if (msg != MSG_OK) {
if (trans->status) {
*trans->status = TRANSACTION_NO_RESPONSE;
}
return;
}
}
if (trans->status) {
*trans->status = TRANSACTION_ACCEPTED;
}
}
void soft_serial_initiator_init(SSTD_t* const sstd_table, int sstd_table_size) {
Transaction_table = sstd_table;
Transaction_table_size = (uint8_t)sstd_table_size;
usart_init();
#if defined(SERIAL_USART_PIN_SWAP)
uart_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins
#endif
#if defined(USART_REMAP)
USART_REMAP;
#endif
uartStart(&SERIAL_USART_DRIVER, &uart_config);
}
/**
* @brief Start transaction from the master to the slave.
* This version uses duplex send and receive usart pheriphals and DMA backed transfers.
*
* @param index Transaction Table index of the transaction to start.
* @return int TRANSACTION_NO_RESPONSE in case of Timeout.
* TRANSACTION_TYPE_ERROR in case of invalid transaction index.
* TRANSACTION_END in case of success.
*/
#if !defined(SERIAL_USE_MULTI_TRANSACTION)
int soft_serial_transaction(void) {
uint8_t sstd_index = 0;
#else
int soft_serial_transaction(int index) {
uint8_t sstd_index = index;
#endif
if (sstd_index > Transaction_table_size) {
return TRANSACTION_TYPE_ERROR;
}
SSTD_t* const trans = &Transaction_table[sstd_index];
msg_t msg = 0;
size_t buffer_size = (size_t)sizeof(sstd_index);
/* Send transaction table index to the slave, which doubles as basic handshake token. */
uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index, TIME_MS2I(SERIAL_USART_TIMEOUT));
uint8_t sstd_index_shake = 0xFF;
buffer_size = (size_t)sizeof(sstd_index_shake);
/* Receive the handshake token from the slave. The token was XORed by the slave as a simple checksum.
If the tokens match, the master will start to send and receive possible transaction buffers. */
msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index_shake, TIME_MS2I(SERIAL_USART_TIMEOUT));
if (msg != MSG_OK || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
dprintln("USART: Handshake Failed");
return TRANSACTION_NO_RESPONSE;
}
/* Send transaction buffer to the slave. If this transaction requires it. */
buffer_size = (size_t)trans->initiator2target_buffer_size;
if (buffer_size) {
msg = uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->initiator2target_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
if (msg != MSG_OK) {
dprintln("USART: Send Failed");
return TRANSACTION_NO_RESPONSE;
}
}
/* Receive transaction buffer from the slave. If this transaction requires it. */
buffer_size = (size_t)trans->target2initiator_buffer_size;
if (buffer_size) {
msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->target2initiator_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
if (msg != MSG_OK) {
dprintln("USART: Receive Failed");
return TRANSACTION_NO_RESPONSE;
}
}
return TRANSACTION_END;
}

View File

@@ -16,6 +16,9 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#if defined(EXTERNAL_EEPROM_WP_PIN)
# include "gpio.h"
#endif
/* /*
Note that the implementations of eeprom_XXXX_YYYY on AVR are normally Note that the implementations of eeprom_XXXX_YYYY on AVR are normally
@@ -50,7 +53,14 @@ static inline void fill_target_address(uint8_t *buffer, const void *addr) {
} }
} }
void eeprom_driver_init(void) { i2c_init(); } void eeprom_driver_init(void) {
i2c_init();
#if defined(EXTERNAL_EEPROM_WP_PIN)
/* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
writePin(EXTERNAL_EEPROM_WP_PIN, 1);
setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
#endif
}
void eeprom_driver_erase(void) { void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
@@ -89,6 +99,11 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
uint8_t * read_buf = (uint8_t *)buf; uint8_t * read_buf = (uint8_t *)buf;
uintptr_t target_addr = (uintptr_t)addr; uintptr_t target_addr = (uintptr_t)addr;
#if defined(EXTERNAL_EEPROM_WP_PIN)
setPinOutput(EXTERNAL_EEPROM_WP_PIN);
writePin(EXTERNAL_EEPROM_WP_PIN, 0);
#endif
while (len > 0) { while (len > 0) {
uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE; uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE;
int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset; int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset;
@@ -116,4 +131,10 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
target_addr += write_length; target_addr += write_length;
len -= write_length; len -= write_length;
} }
#if defined(EXTERNAL_EEPROM_WP_PIN)
/* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
writePin(EXTERNAL_EEPROM_WP_PIN, 1);
setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
#endif
} }

View File

@@ -31,6 +31,8 @@
*/ */
#include "wait.h" #include "wait.h"
#include "debug.h"
#include "timer.h"
#include "spi_master.h" #include "spi_master.h"
#include "eeprom.h" #include "eeprom.h"
#include "eeprom_spi.h" #include "eeprom_spi.h"
@@ -50,11 +52,6 @@
# define EXTERNAL_EEPROM_SPI_TIMEOUT 100 # define EXTERNAL_EEPROM_SPI_TIMEOUT 100
#endif #endif
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
# include "timer.h"
# include "debug.h"
#endif // CONSOLE_ENABLE
static bool spi_eeprom_start(void) { return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR); } static bool spi_eeprom_start(void) { return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR); }
static spi_status_t spi_eeprom_wait_while_busy(int timeout) { static spi_status_t spi_eeprom_wait_while_busy(int timeout) {

View File

@@ -18,6 +18,7 @@
#include "timer.h" #include "timer.h"
#include "solenoid.h" #include "solenoid.h"
#include "haptic.h" #include "haptic.h"
#include "gpio.h"
bool solenoid_on = false; bool solenoid_on = false;
bool solenoid_buzzing = false; bool solenoid_buzzing = false;

496
drivers/lcd/st7565.c Normal file
View File

@@ -0,0 +1,496 @@
/*
Copyright 2021
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "st7565.h"
#include <string.h>
#include "keyboard.h"
#include "progmem.h"
#include "timer.h"
#include "wait.h"
#include ST7565_FONT_H
// Fundamental Commands
#define CONTRAST 0x81
#define DISPLAY_ALL_ON 0xA5
#define DISPLAY_ALL_ON_RESUME 0xA4
#define NORMAL_DISPLAY 0xA6
#define INVERT_DISPLAY 0xA7
#define DISPLAY_ON 0xAF
#define DISPLAY_OFF 0xAE
#define NOP 0xE3
// Addressing Setting Commands
#define PAM_SETCOLUMN_LSB 0x00
#define PAM_SETCOLUMN_MSB 0x10
#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
// Hardware Configuration Commands
#define DISPLAY_START_LINE 0x40
#define SEGMENT_REMAP 0xA0
#define SEGMENT_REMAP_INV 0xA1
#define COM_SCAN_INC 0xC0
#define COM_SCAN_DEC 0xC8
#define LCD_BIAS_7 0xA3
#define LCD_BIAS_9 0xA2
#define RESISTOR_RATIO 0x20
#define POWER_CONTROL 0x28
// Misc defines
#ifndef ST7565_BLOCK_COUNT
# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8)
#endif
#ifndef ST7565_BLOCK_SIZE
# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)
#endif
#define ST7565_ALL_BLOCKS_MASK (((((ST7565_BLOCK_TYPE)1 << (ST7565_BLOCK_COUNT - 1)) - 1) << 1) | 1)
#define HAS_FLAGS(bits, flags) ((bits & flags) == flags)
// Display buffer's is the same as the display memory layout
// this is so we don't end up with rounding errors with
// parts of the display unusable or don't get cleared correctly
// and also allows for drawing & inverting
uint8_t st7565_buffer[ST7565_MATRIX_SIZE];
uint8_t * st7565_cursor;
ST7565_BLOCK_TYPE st7565_dirty = 0;
bool st7565_initialized = false;
bool st7565_active = false;
bool st7565_inverted = false;
display_rotation_t st7565_rotation = DISPLAY_ROTATION_0;
#if ST7565_TIMEOUT > 0
uint32_t st7565_timeout;
#endif
#if ST7565_UPDATE_INTERVAL > 0
uint16_t st7565_update_timeout;
#endif
// Flips the rendering bits for a character at the current cursor position
static void InvertCharacter(uint8_t *cursor) {
const uint8_t *end = cursor + ST7565_FONT_WIDTH;
while (cursor < end) {
*cursor = ~(*cursor);
cursor++;
}
}
bool st7565_init(display_rotation_t rotation) {
setPinOutput(ST7565_A0_PIN);
writePinHigh(ST7565_A0_PIN);
setPinOutput(ST7565_RST_PIN);
writePinHigh(ST7565_RST_PIN);
st7565_rotation = st7565_init_user(rotation);
spi_init();
spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
st7565_reset();
st7565_send_cmd(LCD_BIAS_7);
if (!HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) {
st7565_send_cmd(SEGMENT_REMAP);
st7565_send_cmd(COM_SCAN_DEC);
} else {
st7565_send_cmd(SEGMENT_REMAP_INV);
st7565_send_cmd(COM_SCAN_INC);
}
st7565_send_cmd(DISPLAY_START_LINE | 0x00);
st7565_send_cmd(CONTRAST);
st7565_send_cmd(ST7565_CONTRAST);
st7565_send_cmd(RESISTOR_RATIO | 0x01);
st7565_send_cmd(POWER_CONTROL | 0x04);
wait_ms(50);
st7565_send_cmd(POWER_CONTROL | 0x06);
wait_ms(50);
st7565_send_cmd(POWER_CONTROL | 0x07);
wait_ms(10);
st7565_send_cmd(DISPLAY_ON);
st7565_send_cmd(DISPLAY_ALL_ON_RESUME);
st7565_send_cmd(NORMAL_DISPLAY);
spi_stop();
#if ST7565_TIMEOUT > 0
st7565_timeout = timer_read32() + ST7565_TIMEOUT;
#endif
st7565_clear();
st7565_initialized = true;
st7565_active = true;
return true;
}
__attribute__((weak)) display_rotation_t st7565_init_user(display_rotation_t rotation) { return rotation; }
void st7565_clear(void) {
memset(st7565_buffer, 0, sizeof(st7565_buffer));
st7565_cursor = &st7565_buffer[0];
st7565_dirty = ST7565_ALL_BLOCKS_MASK;
}
uint8_t crot(uint8_t a, int8_t n) {
const uint8_t mask = 0x7;
n &= mask;
return a << n | a >> (-n & mask);
}
void st7565_render(void) {
if (!st7565_initialized) {
return;
}
// Do we have work to do?
st7565_dirty &= ST7565_ALL_BLOCKS_MASK;
if (!st7565_dirty) {
return;
}
// Find first dirty block
uint8_t update_start = 0;
while (!(st7565_dirty & ((ST7565_BLOCK_TYPE)1 << update_start))) {
++update_start;
}
// Calculate commands to set memory addressing bounds.
uint8_t start_page = ST7565_BLOCK_SIZE * update_start / ST7565_DISPLAY_WIDTH;
uint8_t start_column = ST7565_BLOCK_SIZE * update_start % ST7565_DISPLAY_WIDTH;
// IC has 132 segment drivers, for panels with less width we need to offset the starting column
if (HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) {
start_column += (132 - ST7565_DISPLAY_WIDTH);
}
spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
st7565_send_cmd(PAM_PAGE_ADDR | start_page);
st7565_send_cmd(PAM_SETCOLUMN_LSB | ((ST7565_COLUMN_OFFSET + start_column) & 0x0f));
st7565_send_cmd(PAM_SETCOLUMN_MSB | ((ST7565_COLUMN_OFFSET + start_column) >> 4 & 0x0f));
st7565_send_data(&st7565_buffer[ST7565_BLOCK_SIZE * update_start], ST7565_BLOCK_SIZE);
// Turn on display if it is off
st7565_on();
// Clear dirty flag
st7565_dirty &= ~((ST7565_BLOCK_TYPE)1 << update_start);
}
void st7565_set_cursor(uint8_t col, uint8_t line) {
uint16_t index = line * ST7565_DISPLAY_WIDTH + col * ST7565_FONT_WIDTH;
// Out of bounds?
if (index >= ST7565_MATRIX_SIZE) {
index = 0;
}
st7565_cursor = &st7565_buffer[index];
}
void st7565_advance_page(bool clearPageRemainder) {
uint16_t index = st7565_cursor - &st7565_buffer[0];
uint8_t remaining = ST7565_DISPLAY_WIDTH - (index % ST7565_DISPLAY_WIDTH);
if (clearPageRemainder) {
// Remaining Char count
remaining = remaining / ST7565_FONT_WIDTH;
// Write empty character until next line
while (remaining--) st7565_write_char(' ', false);
} else {
// Next page index out of bounds?
if (index + remaining >= ST7565_MATRIX_SIZE) {
index = 0;
remaining = 0;
}
st7565_cursor = &st7565_buffer[index + remaining];
}
}
void st7565_advance_char(void) {
uint16_t nextIndex = st7565_cursor - &st7565_buffer[0] + ST7565_FONT_WIDTH;
uint8_t remainingSpace = ST7565_DISPLAY_WIDTH - (nextIndex % ST7565_DISPLAY_WIDTH);
// Do we have enough space on the current line for the next character
if (remainingSpace < ST7565_FONT_WIDTH) {
nextIndex += remainingSpace;
}
// Did we go out of bounds
if (nextIndex >= ST7565_MATRIX_SIZE) {
nextIndex = 0;
}
// Update cursor position
st7565_cursor = &st7565_buffer[nextIndex];
}
// Main handler that writes character data to the display buffer
void st7565_write_char(const char data, bool invert) {
// Advance to the next line if newline
if (data == '\n') {
// Old source wrote ' ' until end of line...
st7565_advance_page(true);
return;
}
if (data == '\r') {
st7565_advance_page(false);
return;
}
// copy the current render buffer to check for dirty after
static uint8_t st7565_temp_buffer[ST7565_FONT_WIDTH];
memcpy(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH);
_Static_assert(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array");
// set the reder buffer data
uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index
if (cast_data < ST7565_FONT_START || cast_data > ST7565_FONT_END) {
memset(st7565_cursor, 0x00, ST7565_FONT_WIDTH);
} else {
const uint8_t *glyph = &font[(cast_data - ST7565_FONT_START) * ST7565_FONT_WIDTH];
memcpy_P(st7565_cursor, glyph, ST7565_FONT_WIDTH);
}
// Invert if needed
if (invert) {
InvertCharacter(st7565_cursor);
}
// Dirty check
if (memcmp(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH)) {
uint16_t index = st7565_cursor - &st7565_buffer[0];
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
// Edgecase check if the written data spans the 2 chunks
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << ((index + ST7565_FONT_WIDTH - 1) / ST7565_BLOCK_SIZE));
}
// Finally move to the next char
st7565_advance_char();
}
void st7565_write(const char *data, bool invert) {
const char *end = data + strlen(data);
while (data < end) {
st7565_write_char(*data, invert);
data++;
}
}
void st7565_write_ln(const char *data, bool invert) {
st7565_write(data, invert);
st7565_advance_page(true);
}
void st7565_pan(bool left) {
uint16_t i = 0;
for (uint16_t y = 0; y < ST7565_DISPLAY_HEIGHT / 8; y++) {
if (left) {
for (uint16_t x = 0; x < ST7565_DISPLAY_WIDTH - 1; x++) {
i = y * ST7565_DISPLAY_WIDTH + x;
st7565_buffer[i] = st7565_buffer[i + 1];
}
} else {
for (uint16_t x = ST7565_DISPLAY_WIDTH - 1; x > 0; x--) {
i = y * ST7565_DISPLAY_WIDTH + x;
st7565_buffer[i] = st7565_buffer[i - 1];
}
}
}
st7565_dirty = ST7565_ALL_BLOCKS_MASK;
}
display_buffer_reader_t st7565_read_raw(uint16_t start_index) {
if (start_index > ST7565_MATRIX_SIZE) start_index = ST7565_MATRIX_SIZE;
display_buffer_reader_t ret_reader;
ret_reader.current_element = &st7565_buffer[start_index];
ret_reader.remaining_element_count = ST7565_MATRIX_SIZE - start_index;
return ret_reader;
}
void st7565_write_raw_byte(const char data, uint16_t index) {
if (index > ST7565_MATRIX_SIZE) index = ST7565_MATRIX_SIZE;
if (st7565_buffer[index] == data) return;
st7565_buffer[index] = data;
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
}
void st7565_write_raw(const char *data, uint16_t size) {
uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0];
if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index;
for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
uint8_t c = *data++;
if (st7565_buffer[i] == c) continue;
st7565_buffer[i] = c;
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
}
}
void st7565_write_pixel(uint8_t x, uint8_t y, bool on) {
if (x >= ST7565_DISPLAY_WIDTH) {
return;
}
uint16_t index = x + (y / 8) * ST7565_DISPLAY_WIDTH;
if (index >= ST7565_MATRIX_SIZE) {
return;
}
uint8_t data = st7565_buffer[index];
if (on) {
data |= (1 << (y % 8));
} else {
data &= ~(1 << (y % 8));
}
if (st7565_buffer[index] != data) {
st7565_buffer[index] = data;
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
}
}
#if defined(__AVR__)
void st7565_write_P(const char *data, bool invert) {
uint8_t c = pgm_read_byte(data);
while (c != 0) {
st7565_write_char(c, invert);
c = pgm_read_byte(++data);
}
}
void st7565_write_ln_P(const char *data, bool invert) {
st7565_write_P(data, invert);
st7565_advance_page(true);
}
void st7565_write_raw_P(const char *data, uint16_t size) {
uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0];
if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index;
for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
uint8_t c = pgm_read_byte(data++);
if (st7565_buffer[i] == c) continue;
st7565_buffer[i] = c;
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
}
}
#endif // defined(__AVR__)
bool st7565_on(void) {
if (!st7565_initialized) {
return st7565_active;
}
#if ST7565_TIMEOUT > 0
st7565_timeout = timer_read32() + ST7565_TIMEOUT;
#endif
if (!st7565_active) {
spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
st7565_send_cmd(DISPLAY_ON);
spi_stop();
st7565_active = true;
st7565_on_user();
}
return st7565_active;
}
__attribute__((weak)) void st7565_on_user(void) {}
bool st7565_off(void) {
if (!st7565_initialized) {
return !st7565_active;
}
if (st7565_active) {
spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
st7565_send_cmd(DISPLAY_OFF);
spi_stop();
st7565_active = false;
st7565_off_user();
}
return !st7565_active;
}
__attribute__((weak)) void st7565_off_user(void) {}
bool st7565_is_on(void) { return st7565_active; }
bool st7565_invert(bool invert) {
if (!st7565_initialized) {
return st7565_inverted;
}
if (invert != st7565_inverted) {
spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
st7565_send_cmd(invert ? INVERT_DISPLAY : NORMAL_DISPLAY);
spi_stop();
st7565_inverted = invert;
}
return st7565_inverted;
}
uint8_t st7565_max_chars(void) { return ST7565_DISPLAY_WIDTH / ST7565_FONT_WIDTH; }
uint8_t st7565_max_lines(void) { return ST7565_DISPLAY_HEIGHT / ST7565_FONT_HEIGHT; }
void st7565_task(void) {
if (!st7565_initialized) {
return;
}
#if ST7565_UPDATE_INTERVAL > 0
if (timer_elapsed(st7565_update_timeout) >= ST7565_UPDATE_INTERVAL) {
st7565_update_timeout = timer_read();
st7565_set_cursor(0, 0);
st7565_task_user();
}
#else
st7565_set_cursor(0, 0);
st7565_task_user();
#endif
// Smart render system, no need to check for dirty
st7565_render();
// Display timeout check
#if ST7565_TIMEOUT > 0
if (st7565_active && timer_expired32(timer_read32(), st7565_timeout)) {
st7565_off();
}
#endif
}
__attribute__((weak)) void st7565_task_user(void) {}
void st7565_reset(void) {
writePinLow(ST7565_RST_PIN);
wait_ms(20);
writePinHigh(ST7565_RST_PIN);
wait_ms(20);
}
spi_status_t st7565_send_cmd(uint8_t cmd) {
writePinLow(ST7565_A0_PIN);
return spi_write(cmd);
}
spi_status_t st7565_send_data(uint8_t *data, uint16_t length) {
writePinHigh(ST7565_A0_PIN);
return spi_transmit(data, length);
}

219
drivers/lcd/st7565.h Normal file
View File

@@ -0,0 +1,219 @@
/*
Copyright 2021
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "spi_master.h"
#ifndef ST7565_DISPLAY_WIDTH
# define ST7565_DISPLAY_WIDTH 128
#endif
#ifndef ST7565_DISPLAY_HEIGHT
# define ST7565_DISPLAY_HEIGHT 32
#endif
#ifndef ST7565_MATRIX_SIZE
# define ST7565_MATRIX_SIZE (ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH) // 1024 (compile time mathed)
#endif
#ifndef ST7565_BLOCK_TYPE
# define ST7565_BLOCK_TYPE uint16_t
#endif
#ifndef ST7565_BLOCK_COUNT
# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) // 32 (compile time mathed)
#endif
#ifndef ST7565_BLOCK_SIZE
# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) // 32 (compile time mathed)
#endif
// the column address corresponding to the first column in the display hardware
#if !defined(ST7565_COLUMN_OFFSET)
# define ST7565_COLUMN_OFFSET 0
#endif
// spi clock divisor
#if !defined(ST7565_SPI_CLK_DIVISOR)
# define ST7565_SPI_CLK_DIVISOR 4
#endif
// Custom font file to use
#if !defined(ST7565_FONT_H)
# define ST7565_FONT_H "glcdfont.c"
#endif
// unsigned char value of the first character in the font file
#if !defined(ST7565_FONT_START)
# define ST7565_FONT_START 0
#endif
// unsigned char value of the last character in the font file
#if !defined(ST7565_FONT_END)
# define ST7565_FONT_END 223
#endif
// Font render width
#if !defined(ST7565_FONT_WIDTH)
# define ST7565_FONT_WIDTH 6
#endif
// Font render height
#if !defined(ST7565_FONT_HEIGHT)
# define ST7565_FONT_HEIGHT 8
#endif
// Default contrast level
#if !defined(ST7565_CONTRAST)
# define ST7565_CONTRAST 32
#endif
#if !defined(ST7565_TIMEOUT)
# if defined(ST7565_DISABLE_TIMEOUT)
# define ST7565_TIMEOUT 0
# else
# define ST7565_TIMEOUT 60000
# endif
#endif
#if !defined(ST7565_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD)
# define ST7565_UPDATE_INTERVAL 50
#endif
typedef struct __attribute__((__packed__)) {
uint8_t *current_element;
uint16_t remaining_element_count;
} display_buffer_reader_t;
// Rotation enum values are flags
typedef enum { DISPLAY_ROTATION_0, DISPLAY_ROTATION_180 } display_rotation_t;
// Initialize the display, rotating the rendered output based on the define passed in.
// Returns true if the display was initialized successfully
bool st7565_init(display_rotation_t rotation);
// Called at the start of st7565_init, weak function overridable by the user
// rotation - the value passed into st7565_init
// Return new display_rotation_t if you want to override default rotation
display_rotation_t st7565_init_user(display_rotation_t rotation);
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
void st7565_clear(void);
// Renders the dirty chunks of the buffer to display
void st7565_render(void);
// Moves cursor to character position indicated by column and line, wraps if out of bounds
// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions
void st7565_set_cursor(uint8_t col, uint8_t line);
// Advances the cursor to the next page, writing ' ' if true
// Wraps to the begining when out of bounds
void st7565_advance_page(bool clearPageRemainder);
// Moves the cursor forward 1 character length
// Advance page if there is not enough room for the next character
// Wraps to the begining when out of bounds
void st7565_advance_char(void);
// Writes a single character to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
// Main handler that writes character data to the display buffer
void st7565_write_char(const char data, bool invert);
// Writes a string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
void st7565_write(const char *data, bool invert);
// Writes a string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
void st7565_write_ln(const char *data, bool invert);
// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
// Useful for moving the screen in preparation for new drawing
void st7565_pan(bool left);
// Returns a pointer to the requested start index in the buffer plus remaining
// buffer length as struct
display_buffer_reader_t st7565_read_raw(uint16_t start_index);
// Writes a string to the buffer at current cursor position
void st7565_write_raw(const char *data, uint16_t size);
// Writes a single byte into the buffer at the specified index
void st7565_write_raw_byte(const char data, uint16_t index);
// Sets a specific pixel on or off
// Coordinates start at top-left and go right and down for positive x and y
void st7565_write_pixel(uint8_t x, uint8_t y, bool on);
#if defined(__AVR__)
// Writes a PROGMEM string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM
void st7565_write_P(const char *data, bool invert);
// Writes a PROGMEM string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM
void st7565_write_ln_P(const char *data, bool invert);
// Writes a PROGMEM string to the buffer at current cursor position
void st7565_write_raw_P(const char *data, uint16_t size);
#else
# define st7565_write_P(data, invert) st7565_write(data, invert)
# define st7565_write_ln_P(data, invert) st7565_write_ln(data, invert)
# define st7565_write_raw_P(data, size) st7565_write_raw(data, size)
#endif // defined(__AVR__)
// Can be used to manually turn on the screen if it is off
// Returns true if the screen was on or turns on
bool st7565_on(void);
// Called when st7565_on() turns on the screen, weak function overridable by the user
// Not called if the screen is already on
void st7565_on_user(void);
// Can be used to manually turn off the screen if it is on
// Returns true if the screen was off or turns off
bool st7565_off(void);
// Called when st7565_off() turns off the screen, weak function overridable by the user
// Not called if the screen is already off
void st7565_off_user(void);
// Returns true if the screen is currently on, false if it is
// not
bool st7565_is_on(void);
// Basically it's st7565_render, but with timeout management and st7565_task_user calling!
void st7565_task(void);
// Called at the start of st7565_task, weak function overridable by the user
void st7565_task_user(void);
// Inverts the display
// Returns true if the screen was or is inverted
bool st7565_invert(bool invert);
// Returns the maximum number of characters that will fit on a line
uint8_t st7565_max_chars(void);
// Returns the maximum number of lines that will fit on the display
uint8_t st7565_max_lines(void);
void st7565_reset(void);
spi_status_t st7565_send_cmd(uint8_t cmd);
spi_status_t st7565_send_data(uint8_t *data, uint16_t length);

141
drivers/led/aw20216.c Normal file
View File

@@ -0,0 +1,141 @@
/* Copyright 2021 Jasper Chan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aw20216.h"
#include "spi_master.h"
/* The AW20216 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 AWINIC_ID 0b1010 << 4
#define AW_PAGE_FUNCTION 0x00 << 1 // PG0, Function registers
#define AW_PAGE_PWM 0x01 << 1 // PG1, LED PWM control
#define AW_PAGE_SCALING 0x02 << 1 // PG2, LED current scaling control
#define AW_PAGE_PATCHOICE 0x03 << 1 // PG3, Pattern choice?
#define AW_PAGE_PWMSCALING 0x04 << 1 // PG4, LED PWM + Scaling control?
#define AW_WRITE 0
#define AW_READ 1
#define AW_REG_CONFIGURATION 0x00 // PG0
#define AW_REG_GLOBALCURRENT 0x01 // PG0
// Default value of AW_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 AW_CONFIG_DEFAULT 0b10110000
#define AW_CHIPEN 1
#define AW_PWM_REGISTER_COUNT 216
#ifndef AW_SCALING_MAX
# define AW_SCALING_MAX 150
#endif
#ifndef AW_GLOBAL_CURRENT_MAX
# define AW_GLOBAL_CURRENT_MAX 150
#endif
#ifndef AW_SPI_DIVISOR
# define AW_SPI_DIVISOR 4
#endif
uint8_t g_pwm_buffer[DRIVER_COUNT][AW_PWM_REGISTER_COUNT];
bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
bool AW20216_write(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t* data, uint8_t len) {
static uint8_t s_spi_transfer_buffer[2] = {0};
if (!spi_start(cs_pin, false, 0, AW_SPI_DIVISOR)) {
spi_stop();
return false;
}
s_spi_transfer_buffer[0] = (AWINIC_ID | page | AW_WRITE);
s_spi_transfer_buffer[1] = reg;
if (spi_transmit(s_spi_transfer_buffer, 2) != SPI_STATUS_SUCCESS) {
spi_stop();
return false;
}
if (spi_transmit(data, len) != SPI_STATUS_SUCCESS) {
spi_stop();
return false;
}
spi_stop();
return true;
}
static inline bool AW20216_write_register(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t value) {
// Little wrapper so callers need not care about sending a buffer
return AW20216_write(cs_pin, page, reg, &value, 1);
}
static void AW20216_init_scaling(pin_t cs_pin) {
// Set constant current to the max, control brightness with PWM
for (uint8_t i = 0; i < AW_PWM_REGISTER_COUNT; i++) {
AW20216_write_register(cs_pin, AW_PAGE_SCALING, i, AW_SCALING_MAX);
}
}
static inline void AW20216_init_current_limit(pin_t cs_pin) {
// Push config
AW20216_write_register(cs_pin, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX);
}
static inline void AW20216_soft_enable(pin_t cs_pin) {
// Push config
AW20216_write_register(cs_pin, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN);
}
void AW20216_init(pin_t cs_pin, pin_t en_pin) {
setPinOutput(en_pin);
writePinHigh(en_pin);
// Drivers should start with all scaling and PWM registers as off
AW20216_init_current_limit(cs_pin);
AW20216_init_scaling(cs_pin);
AW20216_soft_enable(cs_pin);
}
void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
aw_led led = g_aw_leds[index];
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
g_pwm_buffer[led.driver][led.b] = blue;
g_pwm_buffer_update_required[led.driver] = true;
}
void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
AW20216_set_color(i, red, green, blue);
}
}
void AW20216_update_pwm_buffers(pin_t cs_pin, uint8_t index) {
if (g_pwm_buffer_update_required[index]) {
AW20216_write(cs_pin, AW_PAGE_PWM, 0, g_pwm_buffer[index], AW_PWM_REGISTER_COUNT);
}
g_pwm_buffer_update_required[index] = false;
}

253
drivers/led/aw20216.h Normal file
View File

@@ -0,0 +1,253 @@
/* Copyright 2021 Jasper Chan (Gigahawk)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "progmem.h"
#include "gpio.h"
typedef struct aw_led {
uint8_t driver : 2;
uint8_t r;
uint8_t g;
uint8_t b;
} aw_led;
extern const aw_led __flash g_aw_leds[DRIVER_LED_TOTAL];
void AW20216_init(pin_t cs_pin, pin_t en_pin);
void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
void AW20216_update_pwm_buffers(pin_t cs_pin, uint8_t index);
#define CS1_SW1 0x00
#define CS2_SW1 0x01
#define CS3_SW1 0x02
#define CS4_SW1 0x03
#define CS5_SW1 0x04
#define CS6_SW1 0x05
#define CS7_SW1 0x06
#define CS8_SW1 0x07
#define CS9_SW1 0x08
#define CS10_SW1 0x09
#define CS11_SW1 0x0A
#define CS12_SW1 0x0B
#define CS13_SW1 0x0C
#define CS14_SW1 0x0D
#define CS15_SW1 0x0E
#define CS16_SW1 0x0F
#define CS17_SW1 0x10
#define CS18_SW1 0x11
#define CS1_SW2 0x12
#define CS2_SW2 0x13
#define CS3_SW2 0x14
#define CS4_SW2 0x15
#define CS5_SW2 0x16
#define CS6_SW2 0x17
#define CS7_SW2 0x18
#define CS8_SW2 0x19
#define CS9_SW2 0x1A
#define CS10_SW2 0x1B
#define CS11_SW2 0x1C
#define CS12_SW2 0x1D
#define CS13_SW2 0x1E
#define CS14_SW2 0x1F
#define CS15_SW2 0x20
#define CS16_SW2 0x21
#define CS17_SW2 0x22
#define CS18_SW2 0x23
#define CS1_SW3 0x24
#define CS2_SW3 0x25
#define CS3_SW3 0x26
#define CS4_SW3 0x27
#define CS5_SW3 0x28
#define CS6_SW3 0x29
#define CS7_SW3 0x2A
#define CS8_SW3 0x2B
#define CS9_SW3 0x2C
#define CS10_SW3 0x2D
#define CS11_SW3 0x2E
#define CS12_SW3 0x2F
#define CS13_SW3 0x30
#define CS14_SW3 0x31
#define CS15_SW3 0x32
#define CS16_SW3 0x33
#define CS17_SW3 0x34
#define CS18_SW3 0x35
#define CS1_SW4 0x36
#define CS2_SW4 0x37
#define CS3_SW4 0x38
#define CS4_SW4 0x39
#define CS5_SW4 0x3A
#define CS6_SW4 0x3B
#define CS7_SW4 0x3C
#define CS8_SW4 0x3D
#define CS9_SW4 0x3E
#define CS10_SW4 0x3F
#define CS11_SW4 0x40
#define CS12_SW4 0x41
#define CS13_SW4 0x42
#define CS14_SW4 0x43
#define CS15_SW4 0x44
#define CS16_SW4 0x45
#define CS17_SW4 0x46
#define CS18_SW4 0x47
#define CS1_SW5 0x48
#define CS2_SW5 0x49
#define CS3_SW5 0x4A
#define CS4_SW5 0x4B
#define CS5_SW5 0x4C
#define CS6_SW5 0x4D
#define CS7_SW5 0x4E
#define CS8_SW5 0x4F
#define CS9_SW5 0x50
#define CS10_SW5 0x51
#define CS11_SW5 0x52
#define CS12_SW5 0x53
#define CS13_SW5 0x54
#define CS14_SW5 0x55
#define CS15_SW5 0x56
#define CS16_SW5 0x57
#define CS17_SW5 0x58
#define CS18_SW5 0x59
#define CS1_SW6 0x5A
#define CS2_SW6 0x5B
#define CS3_SW6 0x5C
#define CS4_SW6 0x5D
#define CS5_SW6 0x5E
#define CS6_SW6 0x5F
#define CS7_SW6 0x60
#define CS8_SW6 0x61
#define CS9_SW6 0x62
#define CS10_SW6 0x63
#define CS11_SW6 0x64
#define CS12_SW6 0x65
#define CS13_SW6 0x66
#define CS14_SW6 0x67
#define CS15_SW6 0x68
#define CS16_SW6 0x69
#define CS17_SW6 0x6A
#define CS18_SW6 0x6B
#define CS1_SW7 0x6C
#define CS2_SW7 0x6D
#define CS3_SW7 0x6E
#define CS4_SW7 0x6F
#define CS5_SW7 0x70
#define CS6_SW7 0x71
#define CS7_SW7 0x72
#define CS8_SW7 0x73
#define CS9_SW7 0x74
#define CS10_SW7 0x75
#define CS11_SW7 0x76
#define CS12_SW7 0x77
#define CS13_SW7 0x78
#define CS14_SW7 0x79
#define CS15_SW7 0x7A
#define CS16_SW7 0x7B
#define CS17_SW7 0x7C
#define CS18_SW7 0x7D
#define CS1_SW8 0x7E
#define CS2_SW8 0x7F
#define CS3_SW8 0x80
#define CS4_SW8 0x81
#define CS5_SW8 0x82
#define CS6_SW8 0x83
#define CS7_SW8 0x84
#define CS8_SW8 0x85
#define CS9_SW8 0x86
#define CS10_SW8 0x87
#define CS11_SW8 0x88
#define CS12_SW8 0x89
#define CS13_SW8 0x8A
#define CS14_SW8 0x8B
#define CS15_SW8 0x8C
#define CS16_SW8 0x8D
#define CS17_SW8 0x8E
#define CS18_SW8 0x8F
#define CS1_SW9 0x90
#define CS2_SW9 0x91
#define CS3_SW9 0x92
#define CS4_SW9 0x93
#define CS5_SW9 0x94
#define CS6_SW9 0x95
#define CS7_SW9 0x96
#define CS8_SW9 0x97
#define CS9_SW9 0x98
#define CS10_SW9 0x99
#define CS11_SW9 0x9A
#define CS12_SW9 0x9B
#define CS13_SW9 0x9C
#define CS14_SW9 0x9D
#define CS15_SW9 0x9E
#define CS16_SW9 0x9F
#define CS17_SW9 0xA0
#define CS18_SW9 0xA1
#define CS1_SW10 0xA2
#define CS2_SW10 0xA3
#define CS3_SW10 0xA4
#define CS4_SW10 0xA5
#define CS5_SW10 0xA6
#define CS6_SW10 0xA7
#define CS7_SW10 0xA8
#define CS8_SW10 0xA9
#define CS9_SW10 0xAA
#define CS10_SW10 0xAB
#define CS11_SW10 0xAC
#define CS12_SW10 0xAD
#define CS13_SW10 0xAE
#define CS14_SW10 0xAF
#define CS15_SW10 0xB0
#define CS16_SW10 0xB1
#define CS17_SW10 0xB2
#define CS18_SW10 0xB3
#define CS1_SW11 0xB4
#define CS2_SW11 0xB5
#define CS3_SW11 0xB6
#define CS4_SW11 0xB7
#define CS5_SW11 0xB8
#define CS6_SW11 0xB9
#define CS7_SW11 0xBA
#define CS8_SW11 0xBB
#define CS9_SW11 0xBC
#define CS10_SW11 0xBD
#define CS11_SW11 0xBE
#define CS12_SW11 0xBF
#define CS13_SW11 0xC0
#define CS14_SW11 0xC1
#define CS15_SW11 0xC2
#define CS16_SW11 0xC3
#define CS17_SW11 0xC4
#define CS18_SW11 0xC5
#define CS1_SW12 0xC6
#define CS2_SW12 0xC7
#define CS3_SW12 0xC8
#define CS4_SW12 0xC9
#define CS5_SW12 0xCA
#define CS6_SW12 0xCB
#define CS7_SW12 0xCC
#define CS8_SW12 0xCD
#define CS9_SW12 0xCE
#define CS10_SW12 0xCF
#define CS11_SW12 0xD0
#define CS12_SW12 0xD1
#define CS13_SW12 0xD2
#define CS14_SW12 0xD3
#define CS15_SW12 0xD4
#define CS16_SW12 0xD5
#define CS17_SW12 0xD6
#define CS18_SW12 0xD7

View File

@@ -20,13 +20,14 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "progmem.h"
typedef struct is31_led { typedef struct is31_led {
uint8_t driver : 2; uint8_t driver : 2;
uint8_t v; uint8_t v;
} __attribute__((packed)) is31_led; } __attribute__((packed)) is31_led;
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3731_init(uint8_t addr); void IS31FL3731_init(uint8_t addr);
void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);

View File

@@ -19,6 +19,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "progmem.h"
typedef struct is31_led { typedef struct is31_led {
uint8_t driver : 2; uint8_t driver : 2;
@@ -27,7 +28,7 @@ typedef struct is31_led {
uint8_t b; uint8_t b;
} __attribute__((packed)) is31_led; } __attribute__((packed)) is31_led;
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3731_init(uint8_t addr); void IS31FL3731_init(uint8_t addr);
void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);

View File

@@ -20,6 +20,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "progmem.h"
typedef struct is31_led { typedef struct is31_led {
uint8_t driver : 2; uint8_t driver : 2;
@@ -28,7 +29,7 @@ typedef struct is31_led {
uint8_t b; uint8_t b;
} __attribute__((packed)) is31_led; } __attribute__((packed)) is31_led;
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3733_init(uint8_t addr, uint8_t sync); void IS31FL3733_init(uint8_t addr, uint8_t sync);
bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);

View File

@@ -18,6 +18,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "progmem.h"
// Simple interface option. // Simple interface option.
// If these aren't defined, just define them to make it compile // If these aren't defined, just define them to make it compile
@@ -37,7 +38,7 @@ typedef struct is31_led {
uint8_t b; uint8_t b;
} __attribute__((packed)) is31_led; } __attribute__((packed)) is31_led;
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3736_init(uint8_t addr); void IS31FL3736_init(uint8_t addr);
void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data); void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data);

View File

@@ -65,11 +65,12 @@ uint8_t g_twi_transfer_buffer[20];
// We could optimize this and take out the unused registers from these // We could optimize this and take out the unused registers from these
// buffers and the transfers in IS31FL3737_write_pwm_buffer() but it's // buffers and the transfers in IS31FL3737_write_pwm_buffer() but it's
// probably not worth the extra complexity. // probably not worth the extra complexity.
uint8_t g_pwm_buffer[DRIVER_COUNT][192];
bool g_pwm_buffer_update_required = false;
uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}}; uint8_t g_pwm_buffer[DRIVER_COUNT][192];
bool g_led_control_registers_update_required = false; bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0};
bool g_led_control_registers_update_required[DRIVER_COUNT] = {false};
void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) { void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
g_twi_transfer_buffer[0] = reg; g_twi_transfer_buffer[0] = reg;
@@ -158,7 +159,7 @@ void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green; g_pwm_buffer[led.driver][led.g] = green;
g_pwm_buffer[led.driver][led.b] = blue; g_pwm_buffer[led.driver][led.b] = blue;
g_pwm_buffer_update_required = true; g_pwm_buffer_update_required[led.driver] = true;
} }
} }
@@ -194,30 +195,28 @@ void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bo
g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
} }
g_led_control_registers_update_required = true; g_led_control_registers_update_required[led.driver] = true;
} }
void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2) { void IS31FL3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
if (g_pwm_buffer_update_required) { if (g_pwm_buffer_update_required[index]) {
// Firstly we need to unlock the command register and select PG1 // Firstly we need to unlock the command register and select PG1
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM); IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
IS31FL3737_write_pwm_buffer(addr1, g_pwm_buffer[0]); IS31FL3737_write_pwm_buffer(addr, g_pwm_buffer[index]);
// IS31FL3737_write_pwm_buffer(addr2, g_pwm_buffer[1]);
} }
g_pwm_buffer_update_required = false; g_pwm_buffer_update_required[index] = false;
} }
void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2) { void IS31FL3737_update_led_control_registers(uint8_t addr, uint8_t index) {
if (g_led_control_registers_update_required) { if (g_led_control_registers_update_required[index]) {
// Firstly we need to unlock the command register and select PG0 // Firstly we need to unlock the command register and select PG0
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL); IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
IS31FL3737_write_register(addr1, i, g_led_control_registers[0][i]); IS31FL3737_write_register(addr, i, g_led_control_registers[index][i]);
// IS31FL3737_write_register(addr2, i, g_led_control_registers[1][i]);
} }
g_led_control_registers_update_required = false;
} }
g_led_control_registers_update_required[index] = false;
} }

View File

@@ -20,6 +20,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "progmem.h"
typedef struct is31_led { typedef struct is31_led {
uint8_t driver : 2; uint8_t driver : 2;
@@ -28,7 +29,7 @@ typedef struct is31_led {
uint8_t b; uint8_t b;
} __attribute__((packed)) is31_led; } __attribute__((packed)) is31_led;
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3737_init(uint8_t addr); void IS31FL3737_init(uint8_t addr);
void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data); void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data);

View File

@@ -73,7 +73,7 @@ uint8_t g_twi_transfer_buffer[20] = {0xFF};
// buffers and the transfers in IS31FL3741_write_pwm_buffer() but it's // buffers and the transfers in IS31FL3741_write_pwm_buffer() but it's
// probably not worth the extra complexity. // probably not worth the extra complexity.
uint8_t g_pwm_buffer[DRIVER_COUNT][ISSI_MAX_LEDS]; uint8_t g_pwm_buffer[DRIVER_COUNT][ISSI_MAX_LEDS];
bool g_pwm_buffer_update_required = false; bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
bool g_scaling_registers_update_required[DRIVER_COUNT] = {false}; bool g_scaling_registers_update_required[DRIVER_COUNT] = {false};
uint8_t g_scaling_registers[DRIVER_COUNT][ISSI_MAX_LEDS]; uint8_t g_scaling_registers[DRIVER_COUNT][ISSI_MAX_LEDS];
@@ -172,7 +172,7 @@ void IS31FL3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green; g_pwm_buffer[led.driver][led.g] = green;
g_pwm_buffer[led.driver][led.b] = blue; g_pwm_buffer[led.driver][led.b] = blue;
g_pwm_buffer_update_required = true; g_pwm_buffer_update_required[led.driver] = true;
} }
} }
@@ -206,12 +206,12 @@ void IS31FL3741_set_led_control_register(uint8_t index, bool red, bool green, bo
g_scaling_registers_update_required[led.driver] = true; g_scaling_registers_update_required[led.driver] = true;
} }
void IS31FL3741_update_pwm_buffers(uint8_t addr1, uint8_t addr2) { void IS31FL3741_update_pwm_buffers(uint8_t addr, uint8_t index) {
if (g_pwm_buffer_update_required) { if (g_pwm_buffer_update_required[index]) {
IS31FL3741_write_pwm_buffer(addr1, g_pwm_buffer[0]); IS31FL3741_write_pwm_buffer(addr, g_pwm_buffer[index]);
} }
g_pwm_buffer_update_required = false; g_pwm_buffer_update_required[index] = false;
} }
void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue) { void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue) {
@@ -219,7 +219,7 @@ void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green,
g_pwm_buffer[pled->driver][pled->g] = green; g_pwm_buffer[pled->driver][pled->g] = green;
g_pwm_buffer[pled->driver][pled->b] = blue; g_pwm_buffer[pled->driver][pled->b] = blue;
g_pwm_buffer_update_required = true; g_pwm_buffer_update_required[pled->driver] = true;
} }
void IS31FL3741_update_led_control_registers(uint8_t addr, uint8_t index) { void IS31FL3741_update_led_control_registers(uint8_t addr, uint8_t index) {

View File

@@ -21,6 +21,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "progmem.h"
typedef struct is31_led { typedef struct is31_led {
uint32_t driver : 2; uint32_t driver : 2;
@@ -29,7 +30,7 @@ typedef struct is31_led {
uint32_t b : 10; uint32_t b : 10;
} __attribute__((packed)) is31_led; } __attribute__((packed)) is31_led;
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3741_init(uint8_t addr); void IS31FL3741_init(uint8_t addr);
void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data); void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data);
@@ -44,8 +45,8 @@ void IS31FL3741_set_led_control_register(uint8_t index, bool red, bool green, bo
// (eg. from a timer interrupt). // (eg. from a timer interrupt).
// Call this while idle (in between matrix scans). // Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer. // If the buffer is dirty, it will update the driver with the buffer.
void IS31FL3741_update_pwm_buffers(uint8_t addr1, uint8_t addr2); void IS31FL3741_update_pwm_buffers(uint8_t addr, uint8_t index);
void IS31FL3741_update_led_control_registers(uint8_t addr1, uint8_t addr2); void IS31FL3741_update_led_control_registers(uint8_t addr, uint8_t index);
void IS31FL3741_set_scaling_registers(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue); void IS31FL3741_set_scaling_registers(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue);
void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue); void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue);

View File

@@ -313,6 +313,14 @@ bool oled_scroll_left(void);
// Returns true if the screen was not scrolling or stops scrolling // Returns true if the screen was not scrolling or stops scrolling
bool oled_scroll_off(void); bool oled_scroll_off(void);
// Returns true if the oled is currently scrolling, false if it is
// not
bool is_oled_scrolling(void);
// Inverts the display
// Returns true if the screen was or is inverted
bool oled_invert(bool invert);
// Returns the maximum number of characters that will fit on a line // Returns the maximum number of characters that will fit on a line
uint8_t oled_max_chars(void); uint8_t oled_max_chars(void);

View File

@@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DISPLAY_ALL_ON 0xA5 #define DISPLAY_ALL_ON 0xA5
#define DISPLAY_ALL_ON_RESUME 0xA4 #define DISPLAY_ALL_ON_RESUME 0xA4
#define NORMAL_DISPLAY 0xA6 #define NORMAL_DISPLAY 0xA6
#define INVERT_DISPLAY 0xA7
#define DISPLAY_ON 0xAF #define DISPLAY_ON 0xAF
#define DISPLAY_OFF 0xAE #define DISPLAY_OFF 0xAE
#define NOP 0xE3 #define NOP 0xE3
@@ -114,6 +115,7 @@ OLED_BLOCK_TYPE oled_dirty = 0;
bool oled_initialized = false; bool oled_initialized = false;
bool oled_active = false; bool oled_active = false;
bool oled_scrolling = false; bool oled_scrolling = false;
bool oled_inverted = false;
uint8_t oled_brightness = OLED_BRIGHTNESS; uint8_t oled_brightness = OLED_BRIGHTNESS;
oled_rotation_t oled_rotation = 0; oled_rotation_t oled_rotation = 0;
uint8_t oled_rotation_width = 0; uint8_t oled_rotation_width = 0;
@@ -690,6 +692,32 @@ bool oled_scroll_off(void) {
return !oled_scrolling; return !oled_scrolling;
} }
bool is_oled_scrolling(void) { return oled_scrolling; }
bool oled_invert(bool invert) {
if (!oled_initialized) {
return oled_inverted;
}
if (invert && !oled_inverted) {
static const uint8_t PROGMEM display_inverted[] = {I2C_CMD, INVERT_DISPLAY};
if (I2C_TRANSMIT_P(display_inverted) != I2C_STATUS_SUCCESS) {
print("oled_invert cmd failed\n");
return oled_inverted;
}
oled_inverted = true;
} else if (!invert && oled_inverted) {
static const uint8_t PROGMEM display_normal[] = {I2C_CMD, NORMAL_DISPLAY};
if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) {
print("oled_invert cmd failed\n");
return oled_inverted;
}
oled_inverted = false;
}
return oled_inverted;
}
uint8_t oled_max_chars(void) { uint8_t oled_max_chars(void) {
if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH; return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH;

View File

@@ -70,8 +70,11 @@ static uint8_t micro_oled_screen_current[LCDWIDTH * LCDHEIGHT / 8] = {0};
D6 D6.............D6 / D6 D6.............D6 /
D7 D7.............D7 ---- D7 D7.............D7 ----
*/ */
#ifdef NO_LCD_SPLASH
#if LCDWIDTH == 64 // do not initialize with a splash screen
static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
#else
# if LCDWIDTH == 64
# if LCDHEIGHT == 48 # if LCDHEIGHT == 48
static uint8_t micro_oled_screen_buffer[] = { static uint8_t micro_oled_screen_buffer[] = {
// QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php // QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
@@ -80,7 +83,7 @@ static uint8_t micro_oled_screen_buffer[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF, 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7, 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF, 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7, 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
# endif # endif
#elif LCDWIDTH == 128 # elif LCDWIDTH == 128
# if LCDHEIGHT == 32 # if LCDHEIGHT == 32
static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = { static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {
// 128x32 qmk image // 128x32 qmk image
@@ -100,9 +103,10 @@ static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// TODO: generate bitmap of QMK logo here // TODO: generate bitmap of QMK logo here
# endif # endif
#else # else
// catchall for custom screen sizes // catchall for custom screen sizes
static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0}; static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
# endif
#endif #endif
void micro_oled_init(void) { void micro_oled_init(void) {
@@ -145,7 +149,7 @@ void micro_oled_init(void) {
#endif #endif
send_command(MEMORYMODE); send_command(MEMORYMODE);
send_command(0x10); send_command(0x02); // 0x02 = 10b, Page addressing mode
send_command(SETCOMPINS); // 0xDA send_command(SETCOMPINS); // 0xDA
if (LCDHEIGHT > 32) { if (LCDHEIGHT > 32) {
@@ -250,13 +254,14 @@ void send_buffer(void) {
if (micro_oled_screen_buffer[i * LCDWIDTH + j] != micro_oled_screen_current[i * LCDWIDTH + j]) { if (micro_oled_screen_buffer[i * LCDWIDTH + j] != micro_oled_screen_current[i * LCDWIDTH + j]) {
if (page_addr != i) { if (page_addr != i) {
set_page_address(i); set_page_address(i);
page_addr = i;
} }
if (col_addr != j) { if (col_addr != j) {
set_column_address(j); set_column_address(j);
col_addr = j + 1;
} }
send_data(micro_oled_screen_buffer[i * LCDWIDTH + j]); send_data(micro_oled_screen_buffer[i * LCDWIDTH + j]);
micro_oled_screen_current[i * LCDWIDTH + j] = micro_oled_screen_buffer[i * LCDWIDTH + j]; micro_oled_screen_current[i * LCDWIDTH + j] = micro_oled_screen_buffer[i * LCDWIDTH + j];
col_addr = j + 1;
} }
} }
} }

193
drivers/sensors/adns5050.c Normal file
View File

@@ -0,0 +1,193 @@
/* Copyright 2021 Colin Lam (Ploopy Corporation)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2019 Sunjun Kim
* Copyright 2019 Hiroyuki Okada
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "adns5050.h"
#include "wait.h"
#include "debug.h"
#include "print.h"
#include "gpio.h"
#ifndef OPTIC_ROTATED
# define OPTIC_ROTATED false
#endif
// Definitions for the ADNS serial line.
#ifndef ADNS_SCLK_PIN
# define ADNS_SCLK_PIN B7
#endif
#ifndef ADNS_SDIO_PIN
# define ADNS_SDIO_PIN C6
#endif
#ifndef ADNS_CS_PIN
# define ADNS_CS_PIN B4
#endif
#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
#endif
// Initialize the ADNS serial pins.
void adns_init(void) {
setPinOutput(ADNS_SCLK_PIN);
setPinOutput(ADNS_SDIO_PIN);
setPinOutput(ADNS_CS_PIN);
}
// Perform a synchronization with the ADNS.
// Just as with the serial protocol, this is used by the slave to send a
// synchronization signal to the master.
void adns_sync(void) {
writePinLow(ADNS_CS_PIN);
wait_us(1);
writePinHigh(ADNS_CS_PIN);
}
void adns_cs_select(void) {
writePinLow(ADNS_CS_PIN);
}
void adns_cs_deselect(void) {
writePinHigh(ADNS_CS_PIN);
}
uint8_t adns_serial_read(void) {
setPinInput(ADNS_SDIO_PIN);
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; ++i) {
writePinLow(ADNS_SCLK_PIN);
wait_us(1);
byte = (byte << 1) | readPin(ADNS_SDIO_PIN);
writePinHigh(ADNS_SCLK_PIN);
wait_us(1);
}
return byte;
}
void adns_serial_write(uint8_t data) {
setPinOutput(ADNS_SDIO_PIN);
for (int8_t b = 7; b >= 0; b--) {
writePinLow(ADNS_SCLK_PIN);
if (data & (1 << b))
writePinHigh(ADNS_SDIO_PIN);
else
writePinLow(ADNS_SDIO_PIN);
wait_us(2);
writePinHigh(ADNS_SCLK_PIN);
}
// tSWR. See page 15 of the ADNS spec sheet.
// Technically, this is only necessary if the next operation is an SDIO
// read. This is not guaranteed to be the case, but we're being lazy.
wait_us(4);
// Note that tSWW is never necessary. All write operations require at
// least 32us, which exceeds tSWW, so there's never a need to wait for it.
}
// Read a byte of data from a register on the ADNS.
// Don't forget to use the register map (as defined in the header file).
uint8_t adns_read_reg(uint8_t reg_addr) {
adns_cs_select();
adns_serial_write(reg_addr);
// We don't need a minimum tSRAD here. That's because a 4ms wait time is
// already included in adns_serial_write(), so we're good.
// See page 10 and 15 of the ADNS spec sheet.
//wait_us(4);
uint8_t byte = adns_serial_read();
// tSRW & tSRR. See page 15 of the ADNS spec sheet.
// Technically, this is only necessary if the next operation is an SDIO
// read or write. This is not guaranteed to be the case.
// Honestly, this wait could probably be removed.
wait_us(1);
adns_cs_deselect();
return byte;
}
void adns_write_reg(uint8_t reg_addr, uint8_t data) {
adns_cs_select();
adns_serial_write( 0b10000000 | reg_addr );
adns_serial_write(data);
adns_cs_deselect();
}
report_adns_t adns_read_burst(void) {
adns_cs_select();
report_adns_t data;
data.dx = 0;
data.dy = 0;
adns_serial_write(REG_MOTION_BURST);
// We don't need a minimum tSRAD here. That's because a 4ms wait time is
// already included in adns_serial_write(), so we're good.
// See page 10 and 15 of the ADNS spec sheet.
//wait_us(4);
uint8_t x = adns_serial_read();
uint8_t y = adns_serial_read();
// Burst mode returns a bunch of other shit that we don't really need.
// Setting CS to high ends burst mode early.
adns_cs_deselect();
data.dx = convert_twoscomp(x);
data.dy = convert_twoscomp(y);
return data;
}
// Convert a two's complement byte from an unsigned data type into a signed
// data type.
int8_t convert_twoscomp(uint8_t data) {
if ((data & 0x80) == 0x80)
return -128 + (data & 0x7F);
else
return data;
}
// Don't forget to use the definitions for CPI in the header file.
void adns_set_cpi(uint8_t cpi) {
adns_write_reg(REG_MOUSE_CONTROL2, cpi);
}
bool adns_check_signature(void) {
uint8_t pid = adns_read_reg(REG_PRODUCT_ID);
uint8_t rid = adns_read_reg(REG_REVISION_ID);
uint8_t pid2 = adns_read_reg(REG_PRODUCT_ID2);
return (pid == 0x12 && rid == 0x01 && pid2 == 0x26);
}

View File

@@ -0,0 +1,79 @@
/* Copyright 2021 Colin Lam (Ploopy Corporation)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2019 Sunjun Kim
* Copyright 2019 Hiroyuki Okada
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdbool.h>
// Registers
#define REG_PRODUCT_ID 0x00
#define REG_REVISION_ID 0x01
#define REG_MOTION 0x02
#define REG_DELTA_X 0x03
#define REG_DELTA_Y 0x04
#define REG_SQUAL 0x05
#define REG_SHUTTER_UPPER 0x06
#define REG_SHUTTER_LOWER 0x07
#define REG_MAXIMUM_PIXEL 0x08
#define REG_PIXEL_SUM 0x09
#define REG_MINIMUM_PIXEL 0x0a
#define REG_PIXEL_GRAB 0x0b
#define REG_MOUSE_CONTROL 0x0d
#define REG_MOUSE_CONTROL2 0x19
#define REG_LED_DC_MODE 0x22
#define REG_CHIP_RESET 0x3a
#define REG_PRODUCT_ID2 0x3e
#define REG_INV_REV_ID 0x3f
#define REG_MOTION_BURST 0x63
// CPI values
#define CPI125 0x11
#define CPI250 0x12
#define CPI375 0x13
#define CPI500 0x14
#define CPI625 0x15
#define CPI750 0x16
#define CPI875 0x17
#define CPI1000 0x18
#define CPI1125 0x19
#define CPI1250 0x1a
#define CPI1375 0x1b
#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte);
#endif
typedef struct {
int8_t dx;
int8_t dy;
} report_adns_t;
// A bunch of functions to implement the ADNS5050-specific serial protocol.
// Note that the "serial.h" driver is insufficient, because it does not
// manually manipulate a serial clock signal.
void adns_init(void);
void adns_sync(void);
uint8_t adns_serial_read(void);
void adns_serial_write(uint8_t data);
uint8_t adns_read_reg(uint8_t reg_addr);
void adns_write_reg(uint8_t reg_addr, uint8_t data);
report_adns_t adns_read_burst(void);
int8_t convert_twoscomp(uint8_t data);
void adns_set_cpi(uint8_t cpi);
bool adns_check_signature(void);

219
drivers/sensors/adns9800.c Normal file
View File

@@ -0,0 +1,219 @@
/* Copyright 2020 Alexander Tulloh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "spi_master.h"
#include "quantum.h"
#include "adns9800_srom_A6.h"
#include "adns9800.h"
// registers
#define REG_Product_ID 0x00
#define REG_Revision_ID 0x01
#define REG_Motion 0x02
#define REG_Delta_X_L 0x03
#define REG_Delta_X_H 0x04
#define REG_Delta_Y_L 0x05
#define REG_Delta_Y_H 0x06
#define REG_SQUAL 0x07
#define REG_Pixel_Sum 0x08
#define REG_Maximum_Pixel 0x09
#define REG_Minimum_Pixel 0x0a
#define REG_Shutter_Lower 0x0b
#define REG_Shutter_Upper 0x0c
#define REG_Frame_Period_Lower 0x0d
#define REG_Frame_Period_Upper 0x0e
#define REG_Configuration_I 0x0f
#define REG_Configuration_II 0x10
#define REG_Frame_Capture 0x12
#define REG_SROM_Enable 0x13
#define REG_Run_Downshift 0x14
#define REG_Rest1_Rate 0x15
#define REG_Rest1_Downshift 0x16
#define REG_Rest2_Rate 0x17
#define REG_Rest2_Downshift 0x18
#define REG_Rest3_Rate 0x19
#define REG_Frame_Period_Max_Bound_Lower 0x1a
#define REG_Frame_Period_Max_Bound_Upper 0x1b
#define REG_Frame_Period_Min_Bound_Lower 0x1c
#define REG_Frame_Period_Min_Bound_Upper 0x1d
#define REG_Shutter_Max_Bound_Lower 0x1e
#define REG_Shutter_Max_Bound_Upper 0x1f
#define REG_LASER_CTRL0 0x20
#define REG_Observation 0x24
#define REG_Data_Out_Lower 0x25
#define REG_Data_Out_Upper 0x26
#define REG_SROM_ID 0x2a
#define REG_Lift_Detection_Thr 0x2e
#define REG_Configuration_V 0x2f
#define REG_Configuration_IV 0x39
#define REG_Power_Up_Reset 0x3a
#define REG_Shutdown 0x3b
#define REG_Inverse_Product_ID 0x3f
#define REG_Motion_Burst 0x50
#define REG_SROM_Load_Burst 0x62
#define REG_Pixel_Burst 0x64
#define ADNS_CLOCK_SPEED 2000000
#define MIN_CPI 200
#define MAX_CPI 8200
#define CPI_STEP 200
#define CLAMP_CPI(value) value < MIN_CPI ? MIN_CPI : value > MAX_CPI ? MAX_CPI : value
#define SPI_MODE 3
#define SPI_DIVISOR (F_CPU / ADNS_CLOCK_SPEED)
#define US_BETWEEN_WRITES 120
#define US_BETWEEN_READS 20
#define US_BEFORE_MOTION 100
#define MSB1 0x80
extern const uint16_t adns_firmware_length;
extern const uint8_t adns_firmware_data[];
void adns_spi_start(void){
spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR);
}
void adns_write(uint8_t reg_addr, uint8_t data){
adns_spi_start();
spi_write(reg_addr | MSB1);
spi_write(data);
spi_stop();
wait_us(US_BETWEEN_WRITES);
}
uint8_t adns_read(uint8_t reg_addr){
adns_spi_start();
spi_write(reg_addr & 0x7f );
uint8_t data = spi_read();
spi_stop();
wait_us(US_BETWEEN_READS);
return data;
}
void adns_init() {
setPinOutput(SPI_SS_PIN);
spi_init();
// reboot
adns_write(REG_Power_Up_Reset, 0x5a);
wait_ms(50);
// read registers and discard
adns_read(REG_Motion);
adns_read(REG_Delta_X_L);
adns_read(REG_Delta_X_H);
adns_read(REG_Delta_Y_L);
adns_read(REG_Delta_Y_H);
// upload firmware
// 3k firmware mode
adns_write(REG_Configuration_IV, 0x02);
// enable initialisation
adns_write(REG_SROM_Enable, 0x1d);
// wait a frame
wait_ms(10);
// start SROM download
adns_write(REG_SROM_Enable, 0x18);
// write the SROM file
adns_spi_start();
spi_write(REG_SROM_Load_Burst | 0x80);
wait_us(15);
// send all bytes of the firmware
unsigned char c;
for(int i = 0; i < adns_firmware_length; i++){
c = (unsigned char)pgm_read_byte(adns_firmware_data + i);
spi_write(c);
wait_us(15);
}
spi_stop();
wait_ms(10);
// enable laser
uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
}
config_adns_t adns_get_config(void) {
uint8_t config_1 = adns_read(REG_Configuration_I);
return (config_adns_t){ (config_1 & 0xFF) * CPI_STEP };
}
void adns_set_config(config_adns_t config) {
uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
adns_write(REG_Configuration_I, config_1);
}
static int16_t convertDeltaToInt(uint8_t high, uint8_t low){
// join bytes into twos compliment
uint16_t twos_comp = (high << 8) | low;
// convert twos comp to int
if (twos_comp & 0x8000)
return -1 * (~twos_comp + 1);
return twos_comp;
}
report_adns_t adns_get_report(void) {
report_adns_t report = {0, 0};
adns_spi_start();
// start burst mode
spi_write(REG_Motion_Burst & 0x7f);
wait_us(US_BEFORE_MOTION);
uint8_t motion = spi_read();
if(motion & 0x80) {
// clear observation register
spi_read();
// delta registers
uint8_t delta_x_l = spi_read();
uint8_t delta_x_h = spi_read();
uint8_t delta_y_l = spi_read();
uint8_t delta_y_h = spi_read();
report.x = convertDeltaToInt(delta_x_h, delta_x_l);
report.y = convertDeltaToInt(delta_y_h, delta_y_l);
}
// clear residual motion
spi_write(REG_Motion & 0x7f);
spi_stop();
return report;
}

View File

@@ -0,0 +1,35 @@
/* Copyright 2020 Alexander Tulloh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
typedef struct {
/* 200 - 8200 CPI supported */
uint16_t cpi;
} config_adns_t;
typedef struct {
int16_t x;
int16_t y;
} report_adns_t;
void adns_init(void);
config_adns_t adns_get_config(void);
void adns_set_config(config_adns_t);
/* Reads and clears the current delta values on the ADNS sensor */
report_adns_t adns_get_report(void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2021 Dasky (@daskygit)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pimoroni_trackball.h"
#include "i2c_master.h"
#include "print.h"
#ifndef PIMORONI_TRACKBALL_ADDRESS
# define PIMORONI_TRACKBALL_ADDRESS 0x0A
#endif
#ifndef PIMORONI_TRACKBALL_INTERVAL_MS
# define PIMORONI_TRACKBALL_INTERVAL_MS 8
#endif
#ifndef PIMORONI_TRACKBALL_MOUSE_SCALE
# define PIMORONI_TRACKBALL_MOUSE_SCALE 5
#endif
#ifndef PIMORONI_TRACKBALL_SCROLL_SCALE
# define PIMORONI_TRACKBALL_SCROLL_SCALE 1
#endif
#ifndef PIMORONI_TRACKBALL_DEBOUNCE_CYCLES
# define PIMORONI_TRACKBALL_DEBOUNCE_CYCLES 20
#endif
#ifndef PIMORONI_TRACKBALL_ERROR_COUNT
# define PIMORONI_TRACKBALL_ERROR_COUNT 10
#endif
#define TRACKBALL_TIMEOUT 100
#define TRACKBALL_REG_LED_RED 0x00
#define TRACKBALL_REG_LED_GRN 0x01
#define TRACKBALL_REG_LED_BLU 0x02
#define TRACKBALL_REG_LED_WHT 0x03
#define TRACKBALL_REG_LEFT 0x04
#define TRACKBALL_REG_RIGHT 0x05
#define TRACKBALL_REG_UP 0x06
#define TRACKBALL_REG_DOWN 0x07
static pimoroni_data current_pimoroni_data;
static report_mouse_t mouse_report;
static bool scrolling = false;
static int16_t x_offset = 0;
static int16_t y_offset = 0;
static int16_t h_offset = 0;
static int16_t v_offset = 0;
static uint16_t precision = 128;
static uint8_t error_count = 0;
float trackball_get_precision(void) { return ((float)precision / 128); }
void trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); }
bool trackball_is_scrolling(void) { return scrolling; }
void trackball_set_scrolling(bool scroll) { scrolling = scroll; }
void trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
uint8_t data[4] = {r, g, b, w};
__attribute__((unused)) i2c_status_t status = i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LED_RED, data, sizeof(data), TRACKBALL_TIMEOUT);
#ifdef TRACKBALL_DEBUG
dprintf("Trackball RGBW i2c_status_t: %d\n", status);
#endif
}
i2c_status_t read_pimoroni_trackball(pimoroni_data* data) {
i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LEFT, (uint8_t*)data, sizeof(*data), TRACKBALL_TIMEOUT);
#ifdef TRACKBALL_DEBUG
dprintf("Trackball READ i2c_status_t: %d\nLeft: %d\nRight: %d\nUp: %d\nDown: %d\nSwtich: %d\n", status, data->left, data->right, data->up, data->down, data->click);
#endif
return status;
}
__attribute__((weak)) void pointing_device_init(void) {
i2c_init();
trackball_set_rgbw(0x00, 0x00, 0x00, 0x00);
}
int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale) {
uint8_t offset = 0;
bool isnegative = false;
if (negative_dir > positive_dir) {
offset = negative_dir - positive_dir;
isnegative = true;
} else {
offset = positive_dir - negative_dir;
}
uint16_t magnitude = (scale * offset * offset * precision) >> 7;
return isnegative ? -(int16_t)(magnitude) : (int16_t)(magnitude);
}
void trackball_adapt_values(int8_t* mouse, int16_t* offset) {
if (*offset > 127) {
*mouse = 127;
*offset -= 127;
} else if (*offset < -127) {
*mouse = -127;
*offset += 127;
} else {
*mouse = *offset;
*offset = 0;
}
}
__attribute__((weak)) void trackball_click(bool pressed, report_mouse_t* mouse) {
#ifdef PIMORONI_TRACKBALL_CLICK
if (pressed) {
mouse->buttons |= MOUSE_BTN1;
} else {
mouse->buttons &= ~MOUSE_BTN1;
}
#endif
}
__attribute__((weak)) bool pointing_device_task_user(pimoroni_data* trackball_data) { return true; };
__attribute__((weak)) void pointing_device_task() {
static fast_timer_t throttle = 0;
static uint16_t debounce = 0;
if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
i2c_status_t status = read_pimoroni_trackball(&current_pimoroni_data);
if (status == I2C_STATUS_SUCCESS) {
error_count = 0;
if (pointing_device_task_user(&current_pimoroni_data)) {
mouse_report = pointing_device_get_report();
if (!(current_pimoroni_data.click & 128)) {
trackball_click(false, &mouse_report);
if (!debounce) {
if (scrolling) {
#ifdef PIMORONI_TRACKBALL_INVERT_X
h_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE);
#else
h_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE);
#endif
#ifdef PIMORONI_TRACKBALL_INVERT_Y
v_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE);
#else
v_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE);
#endif
} else {
#ifdef PIMORONI_TRACKBALL_INVERT_X
x_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE);
#else
x_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE);
#endif
#ifdef PIMORONI_TRACKBALL_INVERT_Y
y_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE);
#else
y_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE);
#endif
}
if (scrolling) {
#ifndef PIMORONI_TRACKBALL_ROTATE
trackball_adapt_values(&mouse_report.h, &h_offset);
trackball_adapt_values(&mouse_report.v, &v_offset);
#else
trackball_adapt_values(&mouse_report.h, &v_offset);
trackball_adapt_values(&mouse_report.v, &h_offset);
#endif
mouse_report.x = 0;
mouse_report.y = 0;
} else {
#ifndef PIMORONI_TRACKBALL_ROTATE
trackball_adapt_values(&mouse_report.x, &x_offset);
trackball_adapt_values(&mouse_report.y, &y_offset);
#else
trackball_adapt_values(&mouse_report.x, &y_offset);
trackball_adapt_values(&mouse_report.y, &x_offset);
#endif
mouse_report.h = 0;
mouse_report.v = 0;
}
} else {
debounce--;
}
} else {
trackball_click(true, &mouse_report);
debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
}
}
} else {
error_count++;
}
pointing_device_set_report(mouse_report);
pointing_device_send();
throttle = timer_read_fast();
}
}

View File

@@ -0,0 +1,37 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2021 Dasky (@daskygit)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
#include "pointing_device.h"
typedef struct pimoroni_data {
uint8_t left;
uint8_t right;
uint8_t up;
uint8_t down;
uint8_t click;
} pimoroni_data;
void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
void trackball_click(bool pressed, report_mouse_t* mouse);
int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
void trackball_adapt_values(int8_t* mouse, int16_t* offset);
float trackball_get_precision(void);
void trackball_set_precision(float precision);
bool trackball_is_scrolling(void);
void trackball_set_scrolling(bool scroll);

271
drivers/sensors/pmw3360.c Normal file
View File

@@ -0,0 +1,271 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2019 Sunjun Kim
* Copyright 2020 Ploopy Corporation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pmw3360.h"
#include "wait.h"
#include "debug.h"
#include "print.h"
#include "pmw3360_firmware.h"
// Registers
#define REG_Product_ID 0x00
#define REG_Revision_ID 0x01
#define REG_Motion 0x02
#define REG_Delta_X_L 0x03
#define REG_Delta_X_H 0x04
#define REG_Delta_Y_L 0x05
#define REG_Delta_Y_H 0x06
#define REG_SQUAL 0x07
#define REG_Raw_Data_Sum 0x08
#define REG_Maximum_Raw_data 0x09
#define REG_Minimum_Raw_data 0x0A
#define REG_Shutter_Lower 0x0B
#define REG_Shutter_Upper 0x0C
#define REG_Control 0x0D
#define REG_Config1 0x0F
#define REG_Config2 0x10
#define REG_Angle_Tune 0x11
#define REG_Frame_Capture 0x12
#define REG_SROM_Enable 0x13
#define REG_Run_Downshift 0x14
#define REG_Rest1_Rate_Lower 0x15
#define REG_Rest1_Rate_Upper 0x16
#define REG_Rest1_Downshift 0x17
#define REG_Rest2_Rate_Lower 0x18
#define REG_Rest2_Rate_Upper 0x19
#define REG_Rest2_Downshift 0x1A
#define REG_Rest3_Rate_Lower 0x1B
#define REG_Rest3_Rate_Upper 0x1C
#define REG_Observation 0x24
#define REG_Data_Out_Lower 0x25
#define REG_Data_Out_Upper 0x26
#define REG_Raw_Data_Dump 0x29
#define REG_SROM_ID 0x2A
#define REG_Min_SQ_Run 0x2B
#define REG_Raw_Data_Threshold 0x2C
#define REG_Config5 0x2F
#define REG_Power_Up_Reset 0x3A
#define REG_Shutdown 0x3B
#define REG_Inverse_Product_ID 0x3F
#define REG_LiftCutoff_Tune3 0x41
#define REG_Angle_Snap 0x42
#define REG_LiftCutoff_Tune1 0x4A
#define REG_Motion_Burst 0x50
#define REG_LiftCutoff_Tune_Timeout 0x58
#define REG_LiftCutoff_Tune_Min_Length 0x5A
#define REG_SROM_Load_Burst 0x62
#define REG_Lift_Config 0x63
#define REG_Raw_Data_Burst 0x64
#define REG_LiftCutoff_Tune2 0x65
bool _inBurst = false;
void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
bool spi_start_adv(void) {
bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR);
wait_us(1);
return status;
}
void spi_stop_adv(void) {
wait_us(1);
spi_stop();
}
spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
if (reg_addr != REG_Motion_Burst) {
_inBurst = false;
}
spi_start_adv();
// send address of the register, with MSBit = 1 to indicate it's a write
spi_status_t status = spi_write(reg_addr | 0x80);
status = spi_write(data);
// tSCLK-NCS for write operation
wait_us(20);
// tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
wait_us(100);
spi_stop();
return status;
}
uint8_t spi_read_adv(uint8_t reg_addr) {
spi_start_adv();
// send adress of the register, with MSBit = 0 to indicate it's a read
spi_write(reg_addr & 0x7f);
uint8_t data = spi_read();
// tSCLK-NCS for read operation is 120ns
wait_us(1);
// tSRW/tSRR (=20us) minus tSCLK-NCS
wait_us(19);
spi_stop();
return data;
}
void pmw_set_cpi(uint16_t cpi) {
uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
spi_start_adv();
spi_write_adv(REG_Config1, cpival);
spi_stop();
}
uint16_t pmw_get_cpi(void) {
uint8_t cpival = spi_read_adv(REG_Config1);
return (uint16_t)(cpival & 0xFF) * 100;
}
bool pmw_spi_init(void) {
setPinOutput(PMW3360_CS_PIN);
spi_init();
_inBurst = false;
spi_stop();
spi_start_adv();
spi_stop();
spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first
wait_ms(300);
spi_start_adv();
wait_us(40);
spi_stop_adv();
wait_us(40);
spi_write_adv(REG_Power_Up_Reset, 0x5a);
wait_ms(50);
spi_read_adv(REG_Motion);
spi_read_adv(REG_Delta_X_L);
spi_read_adv(REG_Delta_X_H);
spi_read_adv(REG_Delta_Y_L);
spi_read_adv(REG_Delta_Y_H);
pmw_upload_firmware();
spi_stop_adv();
wait_ms(10);
pmw_set_cpi(PMW3360_CPI);
wait_ms(1);
spi_write_adv(REG_Config2, 0x00);
spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
bool init_success = pmw_check_signature();
writePinLow(PMW3360_CS_PIN);
return init_success;
}
void pmw_upload_firmware(void) {
spi_write_adv(REG_SROM_Enable, 0x1d);
wait_ms(10);
spi_write_adv(REG_SROM_Enable, 0x18);
spi_start_adv();
spi_write(REG_SROM_Load_Burst | 0x80);
wait_us(15);
unsigned char c;
for (int i = 0; i < firmware_length; i++) {
c = (unsigned char)pgm_read_byte(firmware_data + i);
spi_write(c);
wait_us(15);
}
wait_us(200);
spi_read_adv(REG_SROM_ID);
spi_write_adv(REG_Config2, 0x00);
spi_stop();
wait_ms(10);
}
bool pmw_check_signature(void) {
uint8_t pid = spi_read_adv(REG_Product_ID);
uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04
}
report_pmw_t pmw_read_burst(void) {
if (!_inBurst) {
dprintf("burst on");
spi_write_adv(REG_Motion_Burst, 0x00);
_inBurst = true;
}
spi_start_adv();
spi_write(REG_Motion_Burst);
wait_us(35); // waits for tSRAD
report_pmw_t data;
data.motion = 0;
data.dx = 0;
data.mdx = 0;
data.dy = 0;
data.mdx = 0;
data.motion = spi_read();
spi_write(0x00); // skip Observation
data.dx = spi_read();
data.mdx = spi_read();
data.dy = spi_read();
data.mdy = spi_read();
spi_stop();
if (debug_mouse) {
print_byte(data.motion);
print_byte(data.dx);
print_byte(data.mdx);
print_byte(data.dy);
print_byte(data.mdy);
dprintf("\n");
}
data.isMotion = (data.motion & 0x80) != 0;
data.isOnSurface = (data.motion & 0x08) == 0;
data.dx |= (data.mdx << 8);
data.dx = data.dx * -1;
data.dy |= (data.mdy << 8);
data.dy = data.dy * -1;
spi_stop();
if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
_inBurst = false;
}
return data;
}

85
drivers/sensors/pmw3360.h Normal file
View File

@@ -0,0 +1,85 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2019 Sunjun Kim
* Copyright 2020 Ploopy Corporation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "spi_master.h"
#ifndef PMW3360_CPI
# define PMW3360_CPI 1600
#endif
#ifndef PMW3360_CLOCK_SPEED
# define PMW3360_CLOCK_SPEED 70000000
#endif
#ifndef PMW3360_SPI_LSBFIRST
# define PMW3360_SPI_LSBFIRST false
#endif
#ifndef PMW3360_SPI_MODE
# define PMW3360_SPI_MODE 3
#endif
#ifndef PMW3360_SPI_DIVISOR
# ifdef __AVR__
# define PMW3360_SPI_DIVISOR (F_CPU / PMW3360_CLOCK_SPEED)
# else
# define PMW3360_SPI_DIVISOR 64
# endif
#endif
#ifndef ROTATIONAL_TRANSFORM_ANGLE
# define ROTATIONAL_TRANSFORM_ANGLE 0x00
#endif
#ifndef PMW3360_CS_PIN
# error "No chip select pin defined -- missing PMW3360_CS_PIN"
#endif
#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte);
#endif
typedef struct {
int8_t motion;
bool isMotion; // True if a motion is detected.
bool isOnSurface; // True when a chip is on a surface
int16_t dx; // displacement on x directions. Unit: Count. (CPI * Count = Inch value)
int8_t mdx;
int16_t dy; // displacement on y directions.
int8_t mdy;
} report_pmw_t;
bool spi_start_adv(void);
void spi_stop_adv(void);
spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
uint8_t spi_read_adv(uint8_t reg_addr);
bool pmw_spi_init(void);
void pmw_set_cpi(uint16_t cpi);
uint16_t pmw_get_cpi(void);
void pmw_upload_firmware(void);
bool pmw_check_signature(void);
report_pmw_t pmw_read_burst(void);
#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0)
#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI)
#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))

View File

@@ -0,0 +1,300 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* Copyright 2019 Sunjun Kim
* Copyright 2020 Ploopy Corporation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// clang-format off
// Firmware Blob foor PMW3360
const uint16_t firmware_length = 4094;
// clang-format off
const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
0xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
0x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
0x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
0x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
0xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
0x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
0x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
0x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
0xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
0x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
0x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
0x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
0x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
0xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
0x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
0xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
0xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
0x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
0x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
0x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
0x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
0x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
0x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
0x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
0x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
0x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
0xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
0x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
0x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
0x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
0x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
0xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
0xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
0xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
0x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
0xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
0xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
0xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
0x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
0xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
0xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
0xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
0x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
0xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
0x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
0x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
0x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
0x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
0x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
0x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
0x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
0xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
0x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
0x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
0x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
0x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
0x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
0xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
0x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
0x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
0x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
0xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
0xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
0x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
0x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
0xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
0x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
0xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
0x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
0x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
0xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
0x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
0xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
0x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
0x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
0x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
0x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
0x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
0x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
0xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
0xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
0x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
0x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
0x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
0xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
0xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
0x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
0xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
0x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
0x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
0x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
0x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
0xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
0xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
0x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
0x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
0x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
0x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
0x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
0xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
0xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
0xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
0xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
0x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
0xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
0x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
0xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
0xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
0xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
0xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
0xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
0x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
0xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
0x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
0x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
0xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
0x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
0x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
0xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
0xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
0x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
0x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
0x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
0x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
0x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
0x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
0xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
0x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
0xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
0xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
0xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
0x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
0x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
0xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
0xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
0x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
0x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
0x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
0xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
0xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
0xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
0xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
0xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
0xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
0xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
0xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
0xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
0x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
0x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
0x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
0x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
0xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
0x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
0xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
0x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
0xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
0xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
0x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
0x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
0xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
0xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
0x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
0xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
0xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
0xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
0x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
0x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
0xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
0xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
0xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
0x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
0x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
0x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
0x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
0x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
0x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
0xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
0xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
0x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
0x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
0x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
0x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
0x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
0x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
0x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
0xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
0x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
0x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
0x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
0xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
0x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
0x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
0x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
0x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
0xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
0xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
0xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
0x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
0xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
0x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
0xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
0xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
0xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
0xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
0x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
0xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
0x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
0x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
0xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
0xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
0x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
0xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
0x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
0x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
0xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
0x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
0xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
0x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
0x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
0xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
0x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
0xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
0xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
0x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
0x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
0xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
0x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
0x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
0xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
0xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
0x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
0xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
0xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
0xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
0x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
0x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
0x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
0xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
0x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
0x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
0x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
0xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
0x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
0x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
0x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
0xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
0x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
0x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
0xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
0x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
0x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
0x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
0x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
0xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
0x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
0x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
0x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
0xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
0x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
0x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
0xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
0xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };
// clang-format off

46
drivers/serial.h Normal file
View File

@@ -0,0 +1,46 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <transactions.h>
// initiator is transaction start side
void soft_serial_initiator_init(void);
// target is interrupt accept side
void soft_serial_target_init(void);
// initiator result
#define TRANSACTION_END 0
#define TRANSACTION_NO_RESPONSE 0x1
#define TRANSACTION_DATA_ERROR 0x2
#define TRANSACTION_TYPE_ERROR 0x4
int soft_serial_transaction(int sstd_index);
// target status
// *SSTD_t.status has
// initiator:
// TRANSACTION_END
// or TRANSACTION_NO_RESPONSE
// or TRANSACTION_DATA_ERROR
// target:
// TRANSACTION_DATA_ERROR
// or TRANSACTION_ACCEPTED
#define TRANSACTION_ACCEPTED 0x8
int soft_serial_get_and_clean_status(int sstd_index);

View File

@@ -125,7 +125,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define RGB_MATRIX_LED_PROCESS_LIMIT 5 #define RGB_MATRIX_LED_PROCESS_LIMIT 5
#define RGB_MATRIX_LED_FLUSH_LIMIT 26 #define RGB_MATRIX_LED_FLUSH_LIMIT 26
#define RGB_DISABLE_WHEN_USB_SUSPENDED true
#define RGB_DISABLE_WHEN_USB_SUSPENDED
// #define RGBLIGHT_COLOR_LAYER_0 0x00, 0x00, 0xFF // #define RGBLIGHT_COLOR_LAYER_0 0x00, 0x00, 0xFF
/* #define RGBLIGHT_COLOR_LAYER_1 0x00, 0x00, 0xFF */ /* #define RGBLIGHT_COLOR_LAYER_1 0x00, 0x00, 0xFF */

View File

@@ -53,20 +53,20 @@ void matrix_init_kb(void) {
TCCR1B = 0b00001001; // set and configure fast PWM TCCR1B = 0b00001001; // set and configure fast PWM
// (tied to Vcc for hardware convenience) // (tied to Vcc for hardware convenience)
DDRB &= ~(1<<4); // set B(4) as input DDRB &= ~(1 << 4); // set B(4) as input
PORTB &= ~(1<<4); // set B(4) internal pull-up disabled PORTB &= ~(1 << 4); // set B(4) internal pull-up disabled
// unused pins - C7, D4, D5, D7, E6 // unused pins - C7, D4, D5, D7, E6
// set as input with internal pull-up enabled // set as input with internal pull-up enabled
DDRC &= ~(1<<7); DDRC &= ~(1 << 7);
DDRD &= ~(1<<5 | 1<<4); DDRD &= ~(1 << 5 | 1 << 4);
DDRE &= ~(1<<6); DDRE &= ~(1 << 6);
PORTC |= (1<<7); PORTC |= (1 << 7);
PORTD |= (1<<5 | 1<<4); PORTD |= (1 << 5 | 1 << 4);
PORTE |= (1<<6); PORTE |= (1 << 6);
keyboard_config.raw = eeconfig_read_kb(); keyboard_config.raw = eeconfig_read_kb();
ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4 ); ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4);
#ifdef RGB_MATRIX_ENABLE #ifdef RGB_MATRIX_ENABLE
if (keyboard_config.rgb_matrix_enable) { if (keyboard_config.rgb_matrix_enable) {
rgb_matrix_set_flags(LED_FLAG_ALL); rgb_matrix_set_flags(LED_FLAG_ALL);
@@ -80,8 +80,7 @@ void matrix_init_kb(void) {
matrix_init_user(); matrix_init_user();
} }
void ergodox_blink_all_leds(void) void ergodox_blink_all_leds(void) {
{
ergodox_led_all_off(); ergodox_led_all_off();
ergodox_led_all_set(LED_BRIGHTNESS_DEFAULT); ergodox_led_all_set(LED_BRIGHTNESS_DEFAULT);
ergodox_right_led_1_on(); ergodox_right_led_1_on();
@@ -130,7 +129,7 @@ void ergodox_blink_all_leds(void)
} }
#endif #endif
//ergodox_led_all_on(); // ergodox_led_all_on();
//_delay_ms(333); //_delay_ms(333);
ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4 ); ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4 );
@@ -158,20 +157,28 @@ uint8_t init_mcp23018(void) {
// - unused : input : 1 // - unused : input : 1
// - input : input : 1 // - input : input : 1
// - driving : output : 0 // - driving : output : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT);
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
i2c_stop(); i2c_stop();
// set pull-up // set pull-up
// - unused : on : 1 // - unused : on : 1
// - input : on : 1 // - input : on : 1
// - driving : off : 0 // - driving : off : 0
mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT);
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b00111111, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out;
out: out:
i2c_stop(); i2c_stop();
@@ -190,9 +197,9 @@ uint8_t ergodox_left_leds_update(void) {
if (mcp23018_status) { // if there was an error if (mcp23018_status) { // if there was an error
return mcp23018_status; return mcp23018_status;
} }
#define LEFT_LED_1_SHIFT 7 // in MCP23018 port B # define LEFT_LED_1_SHIFT 7 // in MCP23018 port B
#define LEFT_LED_2_SHIFT 6 // in MCP23018 port B # define LEFT_LED_2_SHIFT 6 // in MCP23018 port B
#define LEFT_LED_3_SHIFT 7 // in MCP23018 port A # define LEFT_LED_3_SHIFT 7 // in MCP23018 port A
// set logical value (doesn't matter on inputs) // set logical value (doesn't matter on inputs)
// - unused : hi-Z : 1 // - unused : hi-Z : 1
@@ -202,49 +209,43 @@ uint8_t ergodox_left_leds_update(void) {
if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(OLATA, ERGODOX_EZ_I2C_TIMEOUT); mcp23018_status = i2c_write(OLATA, ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b11111111 mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT), ERGODOX_EZ_I2C_TIMEOUT);
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT),
ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out; if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0b11111111 mcp23018_status = i2c_write(0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT), ERGODOX_EZ_I2C_TIMEOUT);
& ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT)
& ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT),
ERGODOX_EZ_I2C_TIMEOUT);
if (mcp23018_status) goto out; if (mcp23018_status) goto out;
out: out:
i2c_stop(); i2c_stop();
return mcp23018_status; return mcp23018_status;
} }
#endif #endif
#ifdef SWAP_HANDS_ENABLE #ifdef SWAP_HANDS_ENABLE
__attribute__ ((weak)) __attribute__((weak))
// swap-hands action needs a matrix to define the swap // swap-hands action needs a matrix to define the swap
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
/* Left hand, matrix positions */ /* Left hand, matrix positions */
{{0,13}, {1,13}, {2,13}, {3,13}, {4,13}, {5,13}}, {{0, 13}, {1, 13}, {2, 13}, {3, 13}, {4, 13}, {5, 13}},
{{0,12}, {1,12}, {2,12}, {3,12}, {4,12}, {5,12}}, {{0, 12}, {1, 12}, {2, 12}, {3, 12}, {4, 12}, {5, 12}},
{{0,11}, {1,11}, {2,11}, {3,11}, {4,11}, {5,11}}, {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}, {5, 11}},
{{0,10}, {1,10}, {2,10}, {3,10}, {4,10}, {5,10}}, {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}, {5, 10}},
{{0,9}, {1,9}, {2,9}, {3,9}, {4,9}, {5,9}}, {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}, {5, 9}},
{{0,8}, {1,8}, {2,8}, {3,8}, {4,8}, {5,8}}, {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}, {5, 8}},
{{0,7}, {1,7}, {2,7}, {3,7}, {4,7}, {5,7}}, {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}},
/* Right hand, matrix positions */ /* Right hand, matrix positions */
{{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}},
{{0,5}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}},
{{0,4}, {1,4}, {2,4}, {3,4}, {4,4}, {5,4}}, {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}},
{{0,3}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}}, {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}},
{{0,2}, {1,2}, {2,2}, {3,2}, {4,2}, {5,2}}, {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}},
{{0,1}, {1,1}, {2,1}, {3,1}, {4,1}, {5,1}}, {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}},
{{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {5,0}}, {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}},
}; };
#endif #endif
#ifdef RGB_MATRIX_ENABLE #ifdef RGB_MATRIX_ENABLE
// clang-format off
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
/* driver /* driver
* | R location * | R location
* | | G location * | | G location
@@ -338,17 +339,7 @@ led_config_t g_led_config = { {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 1, 1, 1, 1 4, 4, 1, 1, 1, 1
} }; } };
// clang-format on
void suspend_power_down_kb(void) {
rgb_matrix_set_color_all(0, 0, 0);
rgb_matrix_set_suspend_state(true);
suspend_power_down_user();
}
void suspend_wakeup_init_kb(void) {
rgb_matrix_set_suspend_state(false);
suspend_wakeup_init_user();
}
# ifdef ORYX_CONFIGURATOR # ifdef ORYX_CONFIGURATOR
void keyboard_post_init_kb(void) { void keyboard_post_init_kb(void) {
@@ -367,17 +358,16 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
if (keyboard_config.led_level > 4) { if (keyboard_config.led_level > 4) {
keyboard_config.led_level = 0; keyboard_config.led_level = 0;
} }
ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4 ); ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4);
eeconfig_update_kb(keyboard_config.raw); eeconfig_update_kb(keyboard_config.raw);
layer_state_set_kb(layer_state); layer_state_set_kb(layer_state);
} }
break; break;
#ifdef RGB_MATRIX_ENABLE # ifdef RGB_MATRIX_ENABLE
case TOGGLE_LAYER_COLOR: case TOGGLE_LAYER_COLOR:
if (record->event.pressed) { if (record->event.pressed) {
keyboard_config.disable_layer_led ^= 1; keyboard_config.disable_layer_led ^= 1;
if (keyboard_config.disable_layer_led) if (keyboard_config.disable_layer_led) rgb_matrix_set_color_all(0, 0, 0);
rgb_matrix_set_color_all(0, 0, 0);
eeconfig_update_kb(keyboard_config.raw); eeconfig_update_kb(keyboard_config.raw);
} }
break; break;
@@ -388,18 +378,16 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
rgb_matrix_set_flags(LED_FLAG_NONE); rgb_matrix_set_flags(LED_FLAG_NONE);
keyboard_config.rgb_matrix_enable = false; keyboard_config.rgb_matrix_enable = false;
rgb_matrix_set_color_all(0, 0, 0); rgb_matrix_set_color_all(0, 0, 0);
} } break;
break;
default: { default: {
rgb_matrix_set_flags(LED_FLAG_ALL); rgb_matrix_set_flags(LED_FLAG_ALL);
keyboard_config.rgb_matrix_enable = true; keyboard_config.rgb_matrix_enable = true;
} } break;
break;
} }
eeconfig_update_kb(keyboard_config.raw); eeconfig_update_kb(keyboard_config.raw);
} }
return false; return false;
#endif # endif
} }
return process_record_user(keycode, record); return process_record_user(keycode, record);
} }

View File

@@ -2,9 +2,6 @@
"keyboard_name": "ErgoDox EZ", "keyboard_name": "ErgoDox EZ",
"url": "ergodox-ez.com", "url": "ergodox-ez.com",
"maintainer": "ZSA via Drashna", "maintainer": "ZSA via Drashna",
"width": 17,
"height": 8,
"layouts": { "layouts": {
"LAYOUT_ergodox": { "LAYOUT_ergodox": {
"layout": [ "layout": [

View File

@@ -13,9 +13,9 @@ enum custom_keycodes {
#else #else
VRSN = SAFE_RANGE, VRSN = SAFE_RANGE,
#endif #endif
RGB_SLD
}; };
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Basic layer /* Keymap 0: Basic layer
* *
@@ -77,7 +77,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV, KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS, KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV, KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_TRNS, KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS, KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_TRNS, KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
EEP_RST, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_DOT, KC_0, KC_EQL, KC_TRNS, EEP_RST, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_DOT, KC_0, KC_EQL, KC_TRNS,
RGB_MOD, KC_TRNS, RGB_TOG, RGB_SLD, RGB_MOD, KC_TRNS, RGB_TOG, RGB_M_P,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
RGB_VAD, RGB_VAI, KC_TRNS, KC_TRNS, RGB_HUD, RGB_HUI RGB_VAD, RGB_VAI, KC_TRNS, KC_TRNS, RGB_HUD, RGB_HUI
), ),
@@ -115,18 +115,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_WBAK KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_WBAK
), ),
}; };
// clang-format on
bool process_record_user(uint16_t keycode, keyrecord_t *record) { bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) { if (record->event.pressed) {
switch (keycode) { switch (keycode) {
case VRSN: case VRSN:
SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION); SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
return false; return false;
#ifdef RGBLIGHT_ENABLE
case RGB_SLD:
rgblight_mode(1);
return false;
#endif
} }
} }
return true; return true;
@@ -149,56 +145,56 @@ layer_state_t layer_state_set_user(layer_state_t state) {
uint8_t layer = get_highest_layer(state); uint8_t layer = get_highest_layer(state);
switch (layer) { switch (layer) {
case 0: case 0:
#ifdef RGBLIGHT_COLOR_LAYER_0 #ifdef RGBLIGHT_COLOR_LAYER_0
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_0); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_0);
#endif #endif
break; break;
case 1: case 1:
ergodox_right_led_1_on(); ergodox_right_led_1_on();
#ifdef RGBLIGHT_COLOR_LAYER_1 #ifdef RGBLIGHT_COLOR_LAYER_1
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_1); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_1);
#endif #endif
break; break;
case 2: case 2:
ergodox_right_led_2_on(); ergodox_right_led_2_on();
#ifdef RGBLIGHT_COLOR_LAYER_2 #ifdef RGBLIGHT_COLOR_LAYER_2
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_2); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_2);
#endif #endif
break; break;
case 3: case 3:
ergodox_right_led_3_on(); ergodox_right_led_3_on();
#ifdef RGBLIGHT_COLOR_LAYER_3 #ifdef RGBLIGHT_COLOR_LAYER_3
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_3); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_3);
#endif #endif
break; break;
case 4: case 4:
ergodox_right_led_1_on(); ergodox_right_led_1_on();
ergodox_right_led_2_on(); ergodox_right_led_2_on();
#ifdef RGBLIGHT_COLOR_LAYER_4 #ifdef RGBLIGHT_COLOR_LAYER_4
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_4); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_4);
#endif #endif
break; break;
case 5: case 5:
ergodox_right_led_1_on(); ergodox_right_led_1_on();
ergodox_right_led_3_on(); ergodox_right_led_3_on();
#ifdef RGBLIGHT_COLOR_LAYER_5 #ifdef RGBLIGHT_COLOR_LAYER_5
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_5); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_5);
#endif #endif
break; break;
case 6: case 6:
ergodox_right_led_2_on(); ergodox_right_led_2_on();
ergodox_right_led_3_on(); ergodox_right_led_3_on();
#ifdef RGBLIGHT_COLOR_LAYER_6 #ifdef RGBLIGHT_COLOR_LAYER_6
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_6); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_6);
#endif #endif
break; break;
case 7: case 7:
ergodox_right_led_1_on(); ergodox_right_led_1_on();
ergodox_right_led_2_on(); ergodox_right_led_2_on();
ergodox_right_led_3_on(); ergodox_right_led_3_on();
#ifdef RGBLIGHT_COLOR_LAYER_7 #ifdef RGBLIGHT_COLOR_LAYER_7
rgblight_setrgb(RGBLIGHT_COLOR_LAYER_7); rgblight_setrgb(RGBLIGHT_COLOR_LAYER_7);
#endif #endif
break; break;
default: default:
break; break;

View File

@@ -2,13 +2,6 @@
MCU = atmega32u4 MCU = atmega32u4
# Bootloader selection # Bootloader selection
# Teensy halfkay
# Pro Micro caterina
# Atmel DFU atmel-dfu
# LUFA DFU lufa-dfu
# QMK DFU qmk-dfu
# ATmega32A bootloadHID
# ATmega328P USBasp
BOOTLOADER = halfkay BOOTLOADER = halfkay
# If you have Left LEDs (see # If you have Left LEDs (see
@@ -19,7 +12,7 @@ BOOTLOADER = halfkay
# Build Options # Build Options
# comment out to disable the options. # comment out to disable the options.
# #
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug CONSOLE_ENABLE = no # Console for debug
@@ -30,19 +23,16 @@ NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: ht
UNICODE_ENABLE = no # Unicode UNICODE_ENABLE = no # Unicode
SWAP_HANDS_ENABLE= no # Allow swapping hands of keyboard SWAP_HANDS_ENABLE= no # Allow swapping hands of keyboard
SLEEP_LED_ENABLE = no SLEEP_LED_ENABLE = no
API_SYSEX_ENABLE = no
RGB_MATRIX_ENABLE = no # enable later RGB_MATRIX_ENABLE = no # enable later
RGB_MATRIX_DRIVER = IS31FL3731 RGB_MATRIX_DRIVER = IS31FL3731
DEBOUNCE_TYPE = eager_pr DEBOUNCE_TYPE = sym_eager_pr
# project specific files # project specific files
SRC += matrix.c \ SRC += matrix.c \
led_i2c.c led_i2c.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
LAYOUTS = ergodox
MOUSE_SHARED_EP = no MOUSE_SHARED_EP = no
# Disable unsupported hardware # Disable unsupported hardware

View File

@@ -584,11 +584,6 @@ def unicode_macro_cases(config):
for macro_id, uc_hex in config['unicode_macros'].items(): for macro_id, uc_hex in config['unicode_macros'].items():
hi = int(uc_hex, 16) >> 8 hi = int(uc_hex, 16) >> 8
lo = int(uc_hex, 16) & 0xFF lo = int(uc_hex, 16) & 0xFF
unimacro_keys = ", ".join(
"T({})".format(
"KP_" + digit if digit.isdigit() else digit
) for digit in uc_hex
)
yield UNICODE_MACRO_TEMPLATE.format( yield UNICODE_MACRO_TEMPLATE.format(
macro_id=macro_id, hi=hi, lo=lo macro_id=macro_id, hi=hi, lo=lo
) )

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa> /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
* Copyright 2020 Jack Humbert <jack.humb@gmail.com> * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -89,7 +89,7 @@
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 175 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 175
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS #define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define RGB_MATRIX_KEYPRESSES #define RGB_MATRIX_KEYPRESSES
#define RGB_DISABLE_WHEN_USB_SUSPENDED true #define RGB_DISABLE_WHEN_USB_SUSPENDED
// #define RGB_MATRIX_LED_PROCESS_LIMIT 5 // #define RGB_MATRIX_LED_PROCESS_LIMIT 5
// #define RGB_MATRIX_LED_FLUSH_LIMIT 26 // #define RGB_MATRIX_LED_FLUSH_LIMIT 26
@@ -111,8 +111,9 @@
#define FIRMWARE_VERSION_SIZE 17 #define FIRMWARE_VERSION_SIZE 17
#define DYNAMIC_KEYMAP_EEPROM_ADDR (EECONFIG_SIZE + FIRMWARE_VERSION_SIZE) #define DYNAMIC_KEYMAP_EEPROM_ADDR (EECONFIG_SIZE + FIRMWARE_VERSION_SIZE)
#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 16383 #define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 16383
#define DYNAMIC_KEYMAP_LAYER_COUNT 32 #define DYNAMIC_KEYMAP_LAYER_COUNT 8
#define EEPROM_I2C_24LC128 #define EEPROM_I2C_24LC128
#define AUDIO_PIN A5 #define AUDIO_PIN A5

View File

@@ -0,0 +1,22 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#define HAL_USE_I2C TRUE
#define HAL_USE_GPT TRUE
#define HAL_USE_DAC TRUE
#include_next <halconf.h>

View File

@@ -2,9 +2,6 @@
"keyboard_name": "Moonlander Mark I", "keyboard_name": "Moonlander Mark I",
"url": "zsa.io/moonlander", "url": "zsa.io/moonlander",
"maintainer": "ZSA via Drashna", "maintainer": "ZSA via Drashna",
"width": 17,
"height": 8,
"layouts": { "layouts": {
"LAYOUT_moonlander": { "LAYOUT_moonlander": {
"layout": [ "layout": [

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa> /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
* Copyright 2020 Jack Humbert <jack.humb@gmail.com> * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa> /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
* Copyright 2020 Jack Humbert <jack.humb@gmail.com> * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa> /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
* Copyright 2020 Jack Humbert <jack.humb@gmail.com> * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -16,53 +16,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <hal.h>
#include "timer.h"
#include "wait.h"
#include "print.h"
#include "matrix.h"
#include "action.h"
#include "keycode.h"
#include <string.h>
#include "moonlander.h" #include "moonlander.h"
#include "i2c_master.h" #include "i2c_master.h"
#include "debounce.h"
/* /*
#define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 } outputs #define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 } outputs
#define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 } inputs #define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 } inputs
*/ */
/* matrix state(1:on, 0:off) */ /* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS]; extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
static matrix_row_t matrix_debouncing_right[MATRIX_COLS]; static matrix_row_t raw_matrix_right[MATRIX_COLS];
static bool debouncing = false;
static uint16_t debouncing_time = 0;
static bool debouncing_right = false;
static uint16_t debouncing_time_right = 0;
#define ROWS_PER_HAND (MATRIX_ROWS / 2) #define ROWS_PER_HAND (MATRIX_ROWS / 2)
#ifndef MOONLANDER_I2C_TIMEOUT
#ifndef MATRIX_IO_DELAY # define MOONLANDER_I2C_TIMEOUT 100
# define MATRIX_IO_DELAY 20
#endif #endif
extern bool mcp23018_leds[3]; extern bool mcp23018_leds[3];
extern bool is_launching; extern bool is_launching;
__attribute__((weak)) void matrix_init_user(void) {}
__attribute__((weak)) void matrix_scan_user(void) {}
__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
__attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); }
bool mcp23018_initd = false; bool mcp23018_initd = false;
static uint8_t mcp23018_reset_loop; static uint8_t mcp23018_reset_loop;
@@ -79,14 +52,14 @@ void mcp23018_init(void) {
mcp23018_tx[1] = 0b00000000; // A is output mcp23018_tx[1] = 0b00000000; // A is output
mcp23018_tx[2] = 0b00111111; // B is inputs mcp23018_tx[2] = 0b00111111; // B is inputs
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) { if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error hori\n"); dprintf("error hori\n");
} else { } else {
mcp23018_tx[0] = 0x0C; // GPPUA mcp23018_tx[0] = 0x0C; // GPPUA
mcp23018_tx[1] = 0b10000000; // A is not pulled-up mcp23018_tx[1] = 0b10000000; // A is not pulled-up
mcp23018_tx[2] = 0b11111111; // B is pulled-up mcp23018_tx[2] = 0b11111111; // B is pulled-up
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) { if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error hori\n"); dprintf("error hori\n");
} else { } else {
mcp23018_initd = is_launching = true; mcp23018_initd = is_launching = true;
@@ -94,10 +67,9 @@ void mcp23018_init(void) {
} }
} }
void matrix_init(void) { void matrix_init_custom(void) {
dprintf("matrix init\n"); dprintf("matrix init\n");
// debug_matrix = true; // debug_matrix = true;
// outputs // outputs
setPinOutput(B10); setPinOutput(B10);
setPinOutput(B11); setPinOutput(B11);
@@ -115,66 +87,13 @@ void matrix_init(void) {
setPinInputLow(A7); setPinInputLow(A7);
setPinInputLow(B0); setPinInputLow(B0);
memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(matrix_debouncing, 0, MATRIX_ROWS * sizeof(matrix_row_t));
memset(matrix_debouncing_right, 0, MATRIX_COLS * sizeof(matrix_row_t));
mcp23018_init(); mcp23018_init();
matrix_init_quantum();
} }
uint8_t matrix_scan(void) { bool matrix_scan_custom(matrix_row_t current_matrix[]) {
bool changed = false; bool changed = false;
matrix_row_t data = 0; // Try to re-init right side
// actual matrix
for (uint8_t row = 0; row < ROWS_PER_HAND; row++) {
// strobe row
switch (row) {
case 0: writePinHigh(B10); break;
case 1: writePinHigh(B11); break;
case 2: writePinHigh(B12); break;
case 3: writePinHigh(B13); break;
case 4: writePinHigh(B14); break;
case 5: writePinHigh(B15); break;
}
// need wait to settle pin state
matrix_io_delay();
// read col data
data = (
(readPin(A0) << 0 ) |
(readPin(A1) << 1 ) |
(readPin(A2) << 2 ) |
(readPin(A3) << 3 ) |
(readPin(A6) << 4 ) |
(readPin(A7) << 5 ) |
(readPin(B0) << 6 )
);
// unstrobe row
switch (row) {
case 0: writePinLow(B10); break;
case 1: writePinLow(B11); break;
case 2: writePinLow(B12); break;
case 3: writePinLow(B13); break;
case 4: writePinLow(B14); break;
case 5: writePinLow(B15); break;
}
if (matrix_debouncing[row] != data) {
matrix_debouncing[row] = data;
debouncing = true;
debouncing_time = timer_read();
changed = true;
}
}
for (uint8_t row = 0; row <= ROWS_PER_HAND; row++) {
// right side
if (!mcp23018_initd) { if (!mcp23018_initd) {
if (++mcp23018_reset_loop == 0) { if (++mcp23018_reset_loop == 0) {
// if (++mcp23018_reset_loop >= 1300) { // if (++mcp23018_reset_loop >= 1300) {
@@ -193,16 +112,31 @@ uint8_t matrix_scan(void) {
} }
} }
matrix_row_t data = 0;
// actual matrix
for (uint8_t row = 0; row <= ROWS_PER_HAND; row++) {
// strobe row
switch (row) {
case 0: writePinHigh(B10); break;
case 1: writePinHigh(B11); break;
case 2: writePinHigh(B12); break;
case 3: writePinHigh(B13); break;
case 4: writePinHigh(B14); break;
case 5: writePinHigh(B15); break;
case 6: break; // Left hand has 6 rows
}
// right side
if (mcp23018_initd) {
// #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs // #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
// #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs // #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
// select row // select row
mcp23018_tx[0] = 0x12; // GPIOA mcp23018_tx[0] = 0x12; // GPIOA
mcp23018_tx[1] = (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7); // activate row mcp23018_tx[1] = (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7); // activate row
mcp23018_tx[2] = ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7); // activate row mcp23018_tx[2] = ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7); // activate row
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) { if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error hori\n"); dprintf("error hori\n");
mcp23018_initd = false; mcp23018_initd = false;
} }
@@ -210,87 +144,73 @@ uint8_t matrix_scan(void) {
// read col // read col
mcp23018_tx[0] = 0x13; // GPIOB mcp23018_tx[0] = 0x13; // GPIOB
if (MSG_OK != i2c_readReg(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx[0], &mcp23018_rx[0], 1, I2C_TIMEOUT)) { if (MSG_OK != i2c_readReg(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx[0], &mcp23018_rx[0], 1, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error vert\n"); dprintf("error vert\n");
mcp23018_initd = false; mcp23018_initd = false;
} }
data = ~(mcp23018_rx[0] & 0b00111111); data = ~(mcp23018_rx[0] & 0b00111111);
// data = 0x01; // data = 0x01;
} else {
data = 0;
}
if (matrix_debouncing_right[row] != data) { if (raw_matrix_right[row] != data) {
matrix_debouncing_right[row] = data; raw_matrix_right[row] = data;
debouncing_right = true; changed = true;
debouncing_time_right = timer_read(); }
// left side
if (row < ROWS_PER_HAND) {
// i2c comm incur enough wait time
if (!mcp23018_initd) {
// need wait to settle pin state
matrix_io_delay();
}
// read col data
data = (
(readPin(A0) << 0 ) |
(readPin(A1) << 1 ) |
(readPin(A2) << 2 ) |
(readPin(A3) << 3 ) |
(readPin(A6) << 4 ) |
(readPin(A7) << 5 ) |
(readPin(B0) << 6 )
);
// unstrobe row
switch (row) {
case 0: writePinLow(B10); break;
case 1: writePinLow(B11); break;
case 2: writePinLow(B12); break;
case 3: writePinLow(B13); break;
case 4: writePinLow(B14); break;
case 5: writePinLow(B15); break;
case 6: break;
}
if (current_matrix[row] != data) {
current_matrix[row] = data;
changed = true; changed = true;
} }
} }
if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
for (int row = 0; row < ROWS_PER_HAND; row++) {
matrix[row] = matrix_debouncing[row];
} }
debouncing = false; for (uint8_t row = 0; row < ROWS_PER_HAND; row++) {
} current_matrix[11 - row] = 0;
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
if (debouncing_right && timer_elapsed(debouncing_time_right) > DEBOUNCE && mcp23018_initd) { current_matrix[11 - row] |= ((raw_matrix_right[6 - col] & (1 << row) ? 1 : 0) << col);
for (int row = 0; row < ROWS_PER_HAND; row++) {
matrix[11 - row] = 0;
for (int col = 0; col < MATRIX_COLS; col++) {
matrix[11 - row] |= ((matrix_debouncing_right[6 - col] & (1 << row) ? 1 : 0) << col);
} }
} }
debouncing_right = false; return changed;
}
matrix_scan_quantum();
return (uint8_t)changed;
}
bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & (1 << col)); }
matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
void matrix_print(void) {
dprintf("\nr/c 01234567\n");
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
dprintf("%X0: ", row);
matrix_row_t data = matrix_get_row(row);
for (int col = 0; col < MATRIX_COLS; col++) {
if (data & (1 << col))
dprintf("1");
else
dprintf("0");
}
dprintf("\n");
}
} }
// DO NOT REMOVE // DO NOT REMOVE
// Needed for proper wake/sleep // Needed for proper wake/sleep
void matrix_power_up(void) { void matrix_power_up(void) {
bool temp_launching = is_launching; bool temp_launching = is_launching;
// outputs
setPinOutput(B10);
setPinOutput(B11);
setPinOutput(B12);
setPinOutput(B13);
setPinOutput(B14);
setPinOutput(B15);
wait_us(30); matrix_init_custom();
// inputs
setPinInputLow(A0);
setPinInputLow(A1);
setPinInputLow(A2);
setPinInputLow(A3);
setPinInputLow(A6);
setPinInputLow(A7);
setPinInputLow(B0);
mcp23018_init();
is_launching = temp_launching; is_launching = temp_launching;
if (!temp_launching) { if (!temp_launching) {
ML_LED_1(false); ML_LED_1(false);

View File

@@ -0,0 +1,39 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include_next "mcuconf.h"
// for i2c expander, and ISSI
#undef STM32_I2C_USE_I2C1
#define STM32_I2C_USE_I2C1 TRUE
// for future hardwar
#undef STM32_I2C_USE_I2C2
#define STM32_I2C_USE_I2C2 TRUE
// for audio
#undef STM32_DAC_USE_DAC1_CH1
#define STM32_DAC_USE_DAC1_CH1 TRUE
#undef STM32_DAC_USE_DAC1_CH2
#define STM32_DAC_USE_DAC1_CH2 TRUE
#undef STM32_GPT_USE_TIM6
#define STM32_GPT_USE_TIM6 TRUE
#undef STM32_GPT_USE_TIM7
#define STM32_GPT_USE_TIM7 TRUE
#undef STM32_GPT_USE_TIM8
#define STM32_GPT_USE_TIM8 TRUE

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa> /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
* Copyright 2020 Jack Humbert <jack.humb@gmail.com> * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -219,7 +219,7 @@ layer_state_t layer_state_set_kb(layer_state_t state) {
#ifdef RGB_MATRIX_ENABLE #ifdef RGB_MATRIX_ENABLE
// clang-format off // clang-format off
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location
@@ -356,15 +356,6 @@ led_config_t g_led_config = { {
} }; } };
// clang-format on // clang-format on
void suspend_power_down_kb(void) {
rgb_matrix_set_suspend_state(true);
suspend_power_down_user();
}
void suspend_wakeup_init_kb(void) {
rgb_matrix_set_suspend_state(false);
suspend_wakeup_init_user();
}
#endif #endif
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 ZSA Technology Labs, Inc <@zsa> /* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
* Copyright 2020 Jack Humbert <jack.humb@gmail.com> * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -19,7 +19,23 @@ Flashing example for this keyboard:
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Oryx Configuation
## Moonlander Customization
### Indicator LEDs
There are 6 functions for enabling and disabling the LEDs on the top of the boards. The functions are `ML_LED_1(bool)` through `ML_LED_6(bool)`, with the first LED being the left most LED on the left hand, and the sixth LED being the right most LED on the right side.
By default, the Indicator LEDs are used to indicate the layer state for the keyboard. If you wish to change this (and indicate caps/num/scroll lock status instead), then define `MOONLANDER_USER_LEDS` in your `config.h` file.
### Oryx Configuration
To enable the features from Oryx (ZSA's Configurator), either compile the the `default` keymap, or add `#define ORYX_CONFIGURATOR` to your `config.h` file.
This enables the front Indicator LEDs, and the `TOGGLE_LAYER_COLOR` keycode. The `TOGGLE_LAYER_COLOR` keycode toggles the customized LED map configured on Oryx.
### RGB Matrix Features
If you're using the Smart LED (layer indication) feature from the Oryx Configurator, you want to make sure that you enable these options by adding `#define ORYX_CONFIGURATOR` to your keymap's `config.h`. If you're using the Smart LED (layer indication) feature from the Oryx Configurator, you want to make sure that you enable these options by adding `#define ORYX_CONFIGURATOR` to your keymap's `config.h`.

View File

@@ -1,6 +1,5 @@
# MCU name # MCU name
MCU = STM32F303 MCU = STM32F303
BOARD = QMK_PROTON_C
# Bootloader selection # Bootloader selection
BOOTLOADER = stm32-dfu BOOTLOADER = stm32-dfu
@@ -8,7 +7,7 @@ BOOTLOADER = stm32-dfu
# Build Options # Build Options
# change yes to no to disable # change yes to no to disable
# #
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug CONSOLE_ENABLE = yes # Console for debug
@@ -19,10 +18,8 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
NKRO_ENABLE = yes # USB Nkey Rollover NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no # Enable Bluetooth
AUDIO_ENABLE = yes # Audio output AUDIO_ENABLE = yes # Audio output
CUSTOM_MATRIX = yes CUSTOM_MATRIX = lite
DEBOUNCE_TYPE = custom
SWAP_HANDS_ENABLE = yes SWAP_HANDS_ENABLE = yes
RGB_MATRIX_ENABLE = yes RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3731 RGB_MATRIX_DRIVER = IS31FL3731

View File

@@ -1,5 +1,6 @@
/* /* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
* Copyright 2018 Jack Humbert <jack.humb@gmail.com> * Copyright 2015 ZSA Technology Labs Inc (@zsa)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -106,26 +107,6 @@
//#define NO_ACTION_MACRO //#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION //#define NO_ACTION_FUNCTION
/*
* MIDI options
*/
/* enable basic MIDI features:
- MIDI notes can be sent when in Music mode is on
*/
//#define MIDI_BASIC
/* enable advanced MIDI features:
- MIDI notes can be added to the keymap
- Octave shift and transpose
- Virtual sustain, portamento, and modulation wheel
- etc.
*/
//#define MIDI_ADVANCED
/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
//#define MIDI_TONE_KEYCODE_OCTAVES 1
#define DRIVER_ADDR_1 0b1010000 #define DRIVER_ADDR_1 0b1010000
#define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons. #define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons.
@@ -135,7 +116,7 @@
#define RGB_MATRIX_KEYPRESSES #define RGB_MATRIX_KEYPRESSES
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS #define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define RGB_DISABLE_WHEN_USB_SUSPENDED true #define RGB_DISABLE_WHEN_USB_SUSPENDED
#define RGB_MATRIX_LED_PROCESS_LIMIT 5 #define RGB_MATRIX_LED_PROCESS_LIMIT 5
#define RGB_MATRIX_LED_FLUSH_LIMIT 26 #define RGB_MATRIX_LED_FLUSH_LIMIT 26

View File

@@ -1,4 +1,6 @@
/* Copyright 2018 Jack Humbert <jack.humb@gmail.com> /* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
* Copyright 2015 ZSA Technology Labs Inc (@zsa)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -19,7 +21,7 @@
keyboard_config_t keyboard_config; keyboard_config_t keyboard_config;
#ifdef RGB_MATRIX_ENABLE #ifdef RGB_MATRIX_ENABLE
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations /* Refer to IS31 manual for these locations
* driver * driver
* | R location * | R location

View File

@@ -1,4 +1,6 @@
/* Copyright 2018 Jack Humbert <jack.humb@gmail.com> /* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
* Copyright 2015 ZSA Technology Labs Inc (@zsa)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -1,5 +1,6 @@
/* /* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
* Copyright 2018 Jack Humbert <jack.humb@gmail.com> * Copyright 2015 ZSA Technology Labs Inc (@zsa)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -1 +1,19 @@
/* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
* Copyright 2015 ZSA Technology Labs Inc (@zsa)
* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "glow.h" #include "glow.h"

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