Remerge 0.16.x' into firmware21

This commit is contained in:
Drashna Jael're
2022-03-25 16:19:22 -07:00
548 changed files with 14528 additions and 7820 deletions

View File

@@ -5,6 +5,9 @@ AlignConsecutiveAssignments: 'true'
AlignConsecutiveDeclarations: 'true' AlignConsecutiveDeclarations: 'true'
AlignOperands: 'true' AlignOperands: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'false' AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: Empty
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'false' AlwaysBreakBeforeMultilineStrings: 'false'
@@ -20,6 +23,7 @@ SortIncludes: 'false'
SpaceBeforeAssignmentOperators: 'true' SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false' SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: 1
TabWidth: '4' TabWidth: '4'
UseTab: Never UseTab: Never

113
.gitattributes vendored
View File

@@ -2,69 +2,70 @@
* text=auto * text=auto
# sources # sources
*.c text *.c text eol=lf
*.cc text *.cc text eol=lf
*.cxx text *.cxx text eol=lf
*.cpp text *.cpp text eol=lf
*.c++ text *.c++ text eol=lf
*.hpp text *.hpp text eol=lf
*.h text *.h text eol=lf
*.h++ text *.h++ text eol=lf
*.hh text *.hh text eol=lf
*.bat text *.bat text eol=crlf
*.coffee text *.cmd text eol=crlf
*.css text *.coffee text eol=lf
*.htm text *.css text eol=lf
*.html text *.htm text eol=lf
*.inc text *.html text eol=lf
*.ini text *.inc text eol=lf
*.js text *.ini text eol=crlf
*.jsx text *.js text eol=lf
*.json text *.jsx text eol=lf
*.less text *.json text eol=lf
*.php text *.less text eol=lf
*.pl text *.php text eol=lf
*.py text *.pl text eol=lf
*.rb text *.py text eol=lf
*.sass text *.rb text eol=lf
*.scm text *.sass text eol=lf
*.scss text *.scm text eol=lf
*.sh text *.scss text eol=lf
*.sql text *.sh text eol=lf
*.styl text *.sql text eol=lf
*.ts text *.styl text eol=lf
*.xml text *.ts text eol=lf
*.xhtml text *.xml text eol=lf
*.xhtml text eol=lf
# make files (need to always use lf for compatibility with Windows 10 bash) # make files (need to always use lf for compatibility with Windows 10 bash)
Makefile eol=lf Makefile eol=lf
*.mk eol=lf *.mk eol=lf
# make files (need to always use lf for compatibility with Windows 10 bash) # make files (need to always use lf for compatibility with Windows 10 bash)
*.sh eol=lf *.sh eol=lf
# documentation # documentation
*.markdown text *.markdown text eol=lf
*.md text *.md text eol=lf
*.mdwn text *.mdwn text eol=lf
*.mdown text *.mdown text eol=lf
*.mkd text *.mkd text eol=lf
*.mkdn text *.mkdn text eol=lf
*.mdtxt text *.mdtxt text eol=lf
*.mdtext text *.mdtext text eol=lf
*.txt text *.txt text eol=lf
AUTHORS text AUTHORS text eol=lf
CHANGELOG text CHANGELOG text eol=lf
CHANGES text CHANGES text eol=lf
CONTRIBUTING text CONTRIBUTING text eol=lf
COPYING text COPYING text eol=lf
INSTALL text INSTALL text eol=lf
license text license text eol=lf
LICENSE text LICENSE text eol=lf
NEWS text NEWS text eol=lf
readme text readme text eol=lf
*README* text *README* text eol=lf
TODO text TODO text eol=lf
GRAPHICS GRAPHICS
*.ai binary *.ai binary
@@ -82,7 +83,7 @@ GRAPHICS
*.png binary *.png binary
*.psb binary *.psb binary
*.psd binary *.psd binary
*.svg text *.svg text eol=lf
*.svgz binary *.svgz binary
*.tif binary *.tif binary
*.tiff binary *.tiff binary

View File

@@ -18,19 +18,18 @@ assignees: ''
## System Information ## System Information
- Keyboard: **Keyboard:**
- Revision (if applicable): **Revision (if applicable):**
- Operating system: **Operating system:**
- AVR GCC version: **`qmk doctor` output:**
<!-- Run `avr-gcc --version` to find this out. --> ```
- ARM GCC version: (Paste output here)
<!-- Run `arm-none-eabi-gcc --version` to find this out. --> ```
- QMK Firmware version:
<!-- Run `git describe --abbrev=0 --tags` to find this out. --> **Any keyboard related software installed?**
- Any keyboard related software installed? - [ ] AutoHotKey (Windows)
- [ ] AutoHotKey - [ ] Karabiner (macOS)
- [ ] Karabiner - [ ] Other:
- [ ] Other:
## Additional Context ## Additional Context

30
.github/workflows/develop_update.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Update develop after master merge
on:
push:
branches:
- master
jobs:
develop_update:
runs-on: ubuntu-latest
if: github.repository == 'qmk/qmk_firmware'
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.QMK_BOT_TOKEN }}
fetch-depth: 0
- name: Checkout develop
run: |
git fetch origin master develop
git checkout develop
- name: Update develop from master
run: |
git config --global user.name "QMK Bot"
git config --global user.email "hello@qmk.fm"
git merge origin/master
git push origin develop

View File

@@ -0,0 +1,35 @@
name: Update feature branches after develop merge
on:
push:
branches:
- develop
jobs:
feature_branch_update:
runs-on: ubuntu-latest
if: github.repository == 'qmk/qmk_firmware'
strategy:
matrix:
branch:
- xap
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.QMK_BOT_TOKEN }}
fetch-depth: 0
- name: Checkout branch
run: |
git fetch origin develop ${{ matrix.branch }}
git checkout ${{ matrix.branch }}
- name: Update branch from develop
run: |
git config --global user.name "QMK Bot"
git config --global user.email "hello@qmk.fm"
git merge origin/develop
git push origin ${{ matrix.branch }}

View File

@@ -19,14 +19,14 @@ jobs:
container: qmkfm/qmk_cli container: qmkfm/qmk_cli
steps: steps:
- name: Install dependencies
run: |
apt-get update && apt-get install -y dos2unix
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install dependencies
run: |
pip3 install -r requirements-dev.txt
- uses: trilom/file-changes-action@v1.2.4 - uses: trilom/file-changes-action@v1.2.4
id: file_changes id: file_changes
with: with:

View File

@@ -12,14 +12,14 @@ jobs:
container: qmkfm/qmk_cli container: qmkfm/qmk_cli
steps: steps:
- name: Install dependencies
run: |
apt-get update && apt-get install -y dos2unix
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install dependencies
run: |
pip3 install -r requirements-dev.txt
- name: Run qmk formatters - name: Run qmk formatters
shell: 'bash {0}' shell: 'bash {0}'
run: | run: |

2
.gitignore vendored
View File

@@ -3,6 +3,7 @@
*.swp *.swp
*~ *~
.DS_Store .DS_Store
._*
# Build artifacts # Build artifacts
.clang_complete .clang_complete
@@ -18,7 +19,6 @@
# QMK-specific # QMK-specific
api_data/v1 api_data/v1
doxygen/
quantum/version.h quantum/version.h
*.bin *.bin
*.eep *.eep

View File

@@ -21,7 +21,7 @@ DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "QMK Firmware" PROJECT_NAME = "QMK Firmware"
PROJECT_NUMBER = https://github.com/qmk/qmk_firmware PROJECT_NUMBER = https://github.com/qmk/qmk_firmware
PROJECT_BRIEF = "Keyboard controller firmware for Atmel AVR and ARM USB families" PROJECT_BRIEF = "Keyboard controller firmware for Atmel AVR and ARM USB families"
OUTPUT_DIRECTORY = doxygen OUTPUT_DIRECTORY = .build/doxygen
ALLOW_UNICODE_NAMES = NO ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES BRIEF_MEMBER_DESC = YES
@@ -145,7 +145,7 @@ FILE_PATTERNS = *.c \
RECURSIVE = YES RECURSIVE = YES
EXCLUDE = EXCLUDE =
EXCLUDE_SYMLINKS = NO EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = EXCLUDE_PATTERNS = */protocol/arm_atsam/*
EXCLUDE_SYMBOLS = EXCLUDE_SYMBOLS =
EXAMPLE_PATH = EXAMPLE_PATH =
EXAMPLE_PATTERNS = * EXAMPLE_PATTERNS = *
@@ -209,7 +209,7 @@ EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES SEARCH_INCLUDES = YES
INCLUDE_PATH = INCLUDE_PATH =
INCLUDE_FILE_PATTERNS = INCLUDE_FILE_PATTERNS =
PREDEFINED = PREDEFINED = __DOXYGEN__ PROGMEM
EXPAND_AS_DEFINED = EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES SKIP_FUNCTION_MACROS = YES

135
Makefile
View File

@@ -19,6 +19,10 @@ endif
# Otherwise the [OK], [ERROR] and [WARN] messages won't be displayed correctly # Otherwise the [OK], [ERROR] and [WARN] messages won't be displayed correctly
override SILENT := false override SILENT := false
ifdef SKIP_VERSION
SKIP_GIT := yes
endif
ifndef SUB_IS_SILENT ifndef SUB_IS_SILENT
ifndef SKIP_GIT ifndef SKIP_GIT
QMK_VERSION := $(shell git describe --abbrev=0 --tags 2>/dev/null) QMK_VERSION := $(shell git describe --abbrev=0 --tags 2>/dev/null)
@@ -50,48 +54,12 @@ ABS_ROOT_MAKEFILE := $(abspath $(ROOT_MAKEFILE))
ABS_STARTING_DIR := $(dir $(ABS_STARTING_MAKEFILE)) ABS_STARTING_DIR := $(dir $(ABS_STARTING_MAKEFILE))
ABS_ROOT_DIR := $(dir $(ABS_ROOT_MAKEFILE)) ABS_ROOT_DIR := $(dir $(ABS_ROOT_MAKEFILE))
STARTING_DIR := $(subst $(ABS_ROOT_DIR),,$(ABS_STARTING_DIR)) STARTING_DIR := $(subst $(ABS_ROOT_DIR),,$(ABS_STARTING_DIR))
BUILD_DIR := $(ROOT_DIR)/.build
TEST_DIR := $(BUILD_DIR)/test include paths.mk
TEST_OUTPUT_DIR := $(BUILD_DIR)/test
ERROR_FILE := $(BUILD_DIR)/error_occurred ERROR_FILE := $(BUILD_DIR)/error_occurred
# Helper function to process the newt element of a space separated path
# It works a bit like the traditional functional head tail
# so the CURRENT_PATH_ELEMENT will become the new head
# and the PATH_ELEMENTS are the rest that are still unprocessed
define NEXT_PATH_ELEMENT
$$(eval CURRENT_PATH_ELEMENT := $$(firstword $$(PATH_ELEMENTS)))
$$(eval PATH_ELEMENTS := $$(wordlist 2,9999,$$(PATH_ELEMENTS)))
endef
# We change the / to spaces so that we more easily can work with the elements
# separately
PATH_ELEMENTS := $(subst /, ,$(STARTING_DIR))
# Initialize the path elements list for further processing
$(eval $(call NEXT_PATH_ELEMENT))
# Phony targets to enable a few simple make commands outside the main processing below.
.PHONY: list-keyboards
list-keyboards:
util/list_keyboards.sh | sort -u | tr '\n' ' '
.PHONY: generate-keyboards-file
generate-keyboards-file:
util/list_keyboards.sh | sort -u
.PHONY: clean
clean:
echo -n 'Deleting .build/ ... '
rm -rf $(BUILD_DIR)
echo 'done.'
.PHONY: distclean
distclean: clean
echo -n 'Deleting *.bin, *.hex, and *.uf2 ... '
rm -f *.bin *.hex *.uf2
echo 'done.'
.DEFAULT_GOAL := all:all .DEFAULT_GOAL := all:all
@@ -119,53 +87,20 @@ endef
# a function that returns the value # a function that returns the value
COMPARE_AND_REMOVE_FROM_RULE = $(eval $(call COMPARE_AND_REMOVE_FROM_RULE_HELPER,$1))$(RULE_FOUND) COMPARE_AND_REMOVE_FROM_RULE = $(eval $(call COMPARE_AND_REMOVE_FROM_RULE_HELPER,$1))$(RULE_FOUND)
# Try to find a match for the start of the rule to be checked
# Recursively try to find a match for the start of the rule to be checked
# $1 The list to be checked
# If a match is found, then RULE_FOUND is set to true
# and MATCHED_ITEM to the item that was matched
define TRY_TO_MATCH_RULE_FROM_LIST_HELPER3
ifneq ($1,)
ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,$$(firstword $1)),true)
MATCHED_ITEM := $$(firstword $1)
else
$$(eval $$(call TRY_TO_MATCH_RULE_FROM_LIST_HELPER3,$$(wordlist 2,9999,$1)))
endif
endif
endef
# A recursive helper function for finding the longest match
# $1 The list to be checked
# It works by always removing the currently matched item from the list
define TRY_TO_MATCH_RULE_FROM_LIST_HELPER2
# Stop the recursion when the list is empty
ifneq ($1,)
RULE_BEFORE := $$(RULE)
$$(eval $$(call TRY_TO_MATCH_RULE_FROM_LIST_HELPER3,$1))
# If a match is found in the current list, otherwise just return what we had before
ifeq ($$(RULE_FOUND),true)
# Save the best match so far and call itself recursively
BEST_MATCH := $$(MATCHED_ITEM)
BEST_MATCH_RULE := $$(RULE)
RULE_FOUND := false
RULE := $$(RULE_BEFORE)
$$(eval $$(call TRY_TO_MATCH_RULE_FROM_LIST_HELPER2,$$(filter-out $$(MATCHED_ITEM),$1)))
endif
endif
endef
# Recursively try to find the longest match for the start of the rule to be checked
# $1 The list to be checked # $1 The list to be checked
# If a match is found, then RULE_FOUND is set to true # If a match is found, then RULE_FOUND is set to true
# and MATCHED_ITEM to the item that was matched # and MATCHED_ITEM to the item that was matched
define TRY_TO_MATCH_RULE_FROM_LIST_HELPER define TRY_TO_MATCH_RULE_FROM_LIST_HELPER
BEST_MATCH := # Split on ":", padding with empty strings to avoid indexing issues
$$(eval $$(call TRY_TO_MATCH_RULE_FROM_LIST_HELPER2,$1)) TOKEN1:=$$(shell python3 -c "import sys; print((sys.argv[1].split(':',1)+[''])[0])" $$(RULE))
ifneq ($$(BEST_MATCH),) TOKENr:=$$(shell python3 -c "import sys; print((sys.argv[1].split(':',1)+[''])[1])" $$(RULE))
FOUNDx:=$$(shell echo $1 | tr " " "\n" | grep -Fx $$(TOKEN1))
ifneq ($$(FOUNDx),)
RULE := $$(TOKENr)
RULE_FOUND := true RULE_FOUND := true
RULE := $$(BEST_MATCH_RULE) MATCHED_ITEM := $$(TOKEN1)
MATCHED_ITEM := $$(BEST_MATCH)
else else
RULE_FOUND := false RULE_FOUND := false
MATCHED_ITEM := MATCHED_ITEM :=
@@ -352,7 +287,7 @@ define PARSE_KEYMAP
# Specify the variables that we are passing forward to submake # Specify the variables that we are passing forward to submake
MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY) QMK_BIN=$$(QMK_BIN) MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY) QMK_BIN=$$(QMK_BIN)
# And the first part of the make command # And the first part of the make command
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_keyboard.mk $$(MAKE_TARGET) MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_keyboard.mk $$(MAKE_TARGET)
# The message to display # The message to display
MAKE_MSG := $$(MSG_MAKE_KB) MAKE_MSG := $$(MSG_MAKE_KB)
# We run the command differently, depending on if we want more output or not # We run the command differently, depending on if we want more output or not
@@ -394,12 +329,12 @@ define BUILD_TEST
TEST_NAME := $$(notdir $$(TEST_PATH)) TEST_NAME := $$(notdir $$(TEST_PATH))
MAKE_TARGET := $2 MAKE_TARGET := $2
COMMAND := $1 COMMAND := $1
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_test.mk $$(MAKE_TARGET) MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_test.mk $$(MAKE_TARGET)
MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)" MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
MAKE_MSG := $$(MSG_MAKE_TEST) MAKE_MSG := $$(MSG_MAKE_TEST)
$$(eval $$(call BUILD)) $$(eval $$(call BUILD))
ifneq ($$(MAKE_TARGET),clean) ifneq ($$(MAKE_TARGET),clean)
TEST_EXECUTABLE := $$(TEST_DIR)/$$(TEST_NAME).elf TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_NAME).elf
TESTS += $$(TEST_NAME) TESTS += $$(TEST_NAME)
TEST_MSG := $$(MSG_TEST) TEST_MSG := $$(MSG_TEST)
$$(TEST_NAME)_COMMAND := \ $$(TEST_NAME)_COMMAND := \
@@ -416,6 +351,7 @@ define PARSE_TEST
TESTS := TESTS :=
TEST_NAME := $$(firstword $$(subst :, ,$$(RULE))) TEST_NAME := $$(firstword $$(subst :, ,$$(RULE)))
TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME):,,$$(RULE))) TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME):,,$$(RULE)))
include $(BUILDDEFS_PATH)/testlist.mk
ifeq ($$(TEST_NAME),all) ifeq ($$(TEST_NAME),all)
MATCHED_TESTS := $$(TEST_LIST) MATCHED_TESTS := $$(TEST_LIST)
else else
@@ -438,7 +374,6 @@ define SET_SILENT_MODE
endif endif
endef endef
include paths.mk
include $(BUILDDEFS_PATH)/message.mk include $(BUILDDEFS_PATH)/message.mk
ifeq ($(strip $(BREAK_ON_ERRORS)), yes) ifeq ($(strip $(BREAK_ON_ERRORS)), yes)
@@ -508,14 +443,22 @@ 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 .PHONY: list-keyboards
ifdef SKIP_GIT list-keyboards:
VERSION_H_FLAGS := --skip-git util/list_keyboards.sh | sort -u | tr '\n' ' '
endif
ifdef SKIP_VERSION
VERSION_H_FLAGS := --skip-all
SKIP_GIT := yes
endif
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o quantum/version.h)
include $(ROOT_DIR)/testlist.mk .PHONY: generate-keyboards-file
generate-keyboards-file:
util/list_keyboards.sh | sort -u
.PHONY: clean
clean:
echo -n 'Deleting .build/ ... '
rm -rf $(BUILD_DIR)
echo 'done.'
.PHONY: distclean
distclean: clean
echo -n 'Deleting *.bin, *.hex, and *.uf2 ... '
rm -f *.bin *.hex *.uf2
echo 'done.'

View File

@@ -1,46 +0,0 @@
{
"structure": {
"summary": "_summary.md"
},
"plugins" : [
"edit-link",
"forkmegithub",
"hints",
"page-toc",
"terminal",
"toolbar",
"bulk-redirect"
],
"pluginsConfig": {
"edit-link": {
"base": "https://github.com/qmk/qmk_firmware/edit/master/docs",
"label": "Suggest an edit"
},
"forkmegithub": {
"color": "red",
"url": "https://github.com/qmk/qmk_firmware"
},
"page-toc": {
"selector": ".markdown-section h1, .markdown-section h2"
},
"terminal": {
"copyButtons": true,
"fade": false,
"style": "flat"
},
"toolbar": {
"buttons": [
{
"label": "QMK Firmware",
"icon": "fa fa-github",
"url": "https://github.com/qmk/qmk_firmware"
}
]
},
"bulk-redirect": {
"basepath": "/",
"redirectsFile": "docs/redirects.json"
}
},
"root": "./docs/"
}

View File

@@ -30,6 +30,7 @@
# bootloadhid HIDBootFlash compatible (ATmega32A) # bootloadhid HIDBootFlash compatible (ATmega32A)
# usbasploader USBaspLoader (ATmega328P) # usbasploader USBaspLoader (ATmega328P)
# ARM: # ARM:
# halfkay PJRC Teensy
# 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)
# stm32-dfu STM32 USB DFU in ROM # stm32-dfu STM32 USB DFU in ROM
@@ -37,12 +38,23 @@
# RISC-V: # RISC-V:
# gd32v-dfu GD32V USB DFU in ROM # gd32v-dfu GD32V USB DFU in ROM
# #
# If you need to provide your own implementation, you can set inside `rules.mk`
# `BOOTLOADER = custom` -- you'll need to provide your own implementations. See
# the respective file under `platforms/<PLATFORM>/bootloaders/custom.c` to see
# which functions may be overridden.
#
# BOOTLOADER_SIZE can still be defined manually, but it's recommended # BOOTLOADER_SIZE can still be defined manually, but it's recommended
# you add any possible configuration to this list # you add any possible configuration to this list
ifeq ($(strip $(BOOTLOADER)), custom)
OPT_DEFS += -DBOOTLOADER_CUSTOM
BOOTLOADER_TYPE = custom
endif
ifeq ($(strip $(BOOTLOADER)), atmel-dfu) ifeq ($(strip $(BOOTLOADER)), atmel-dfu)
OPT_DEFS += -DBOOTLOADER_ATMEL_DFU OPT_DEFS += -DBOOTLOADER_ATMEL_DFU
OPT_DEFS += -DBOOTLOADER_DFU OPT_DEFS += -DBOOTLOADER_DFU
BOOTLOADER_TYPE = dfu
ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647)) ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif
@@ -53,6 +65,8 @@ endif
ifeq ($(strip $(BOOTLOADER)), lufa-dfu) ifeq ($(strip $(BOOTLOADER)), lufa-dfu)
OPT_DEFS += -DBOOTLOADER_LUFA_DFU OPT_DEFS += -DBOOTLOADER_LUFA_DFU
OPT_DEFS += -DBOOTLOADER_DFU OPT_DEFS += -DBOOTLOADER_DFU
BOOTLOADER_TYPE = dfu
ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647)) ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
BOOTLOADER_SIZE ?= 4096 BOOTLOADER_SIZE ?= 4096
endif endif
@@ -63,6 +77,8 @@ endif
ifeq ($(strip $(BOOTLOADER)), qmk-dfu) ifeq ($(strip $(BOOTLOADER)), qmk-dfu)
OPT_DEFS += -DBOOTLOADER_QMK_DFU OPT_DEFS += -DBOOTLOADER_QMK_DFU
OPT_DEFS += -DBOOTLOADER_DFU OPT_DEFS += -DBOOTLOADER_DFU
BOOTLOADER_TYPE = dfu
ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647)) ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647))
BOOTLOADER_SIZE ?= 4096 BOOTLOADER_SIZE ?= 4096
endif endif
@@ -73,10 +89,14 @@ endif
ifeq ($(strip $(BOOTLOADER)), qmk-hid) ifeq ($(strip $(BOOTLOADER)), qmk-hid)
OPT_DEFS += -DBOOTLOADER_QMK_HID OPT_DEFS += -DBOOTLOADER_QMK_HID
OPT_DEFS += -DBOOTLOADER_HID OPT_DEFS += -DBOOTLOADER_HID
BOOTLOADER_TYPE = dfu
BOOTLOADER_SIZE ?= 4096 BOOTLOADER_SIZE ?= 4096
endif endif
ifeq ($(strip $(BOOTLOADER)), halfkay) ifeq ($(strip $(BOOTLOADER)), halfkay)
OPT_DEFS += -DBOOTLOADER_HALFKAY OPT_DEFS += -DBOOTLOADER_HALFKAY
BOOTLOADER_TYPE = halfkay
ifeq ($(strip $(MCU)), atmega32u4) ifeq ($(strip $(MCU)), atmega32u4)
BOOTLOADER_SIZE = 512 BOOTLOADER_SIZE = 512
endif endif
@@ -86,18 +106,26 @@ ifeq ($(strip $(BOOTLOADER)), halfkay)
endif endif
ifeq ($(strip $(BOOTLOADER)), caterina) ifeq ($(strip $(BOOTLOADER)), caterina)
OPT_DEFS += -DBOOTLOADER_CATERINA OPT_DEFS += -DBOOTLOADER_CATERINA
BOOTLOADER_TYPE = caterina
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif
ifneq (,$(filter $(BOOTLOADER), bootloadhid bootloadHID)) ifneq (,$(filter $(BOOTLOADER), bootloadhid bootloadHID))
OPT_DEFS += -DBOOTLOADER_BOOTLOADHID OPT_DEFS += -DBOOTLOADER_BOOTLOADHID
BOOTLOADER_TYPE = bootloadhid
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif
ifneq (,$(filter $(BOOTLOADER), usbasploader USBasp)) ifneq (,$(filter $(BOOTLOADER), usbasploader USBasp))
OPT_DEFS += -DBOOTLOADER_USBASP OPT_DEFS += -DBOOTLOADER_USBASP
BOOTLOADER_TYPE = usbasploader
BOOTLOADER_SIZE = 4096 BOOTLOADER_SIZE = 4096
endif endif
ifeq ($(strip $(BOOTLOADER)), lufa-ms) ifeq ($(strip $(BOOTLOADER)), lufa-ms)
OPT_DEFS += -DBOOTLOADER_MS OPT_DEFS += -DBOOTLOADER_MS
BOOTLOADER_TYPE = dfu
BOOTLOADER_SIZE ?= 8192 BOOTLOADER_SIZE ?= 8192
FIRMWARE_FORMAT = bin FIRMWARE_FORMAT = bin
cpfirmware: lufa_warning cpfirmware: lufa_warning
@@ -115,6 +143,7 @@ endif
ifeq ($(strip $(BOOTLOADER)), stm32-dfu) ifeq ($(strip $(BOOTLOADER)), stm32-dfu)
OPT_DEFS += -DBOOTLOADER_STM32_DFU OPT_DEFS += -DBOOTLOADER_STM32_DFU
BOOTLOADER_TYPE = stm32_dfu
# Options to pass to dfu-util when flashing # Options to pass to dfu-util when flashing
DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
@@ -122,6 +151,7 @@ ifeq ($(strip $(BOOTLOADER)), stm32-dfu)
endif endif
ifeq ($(strip $(BOOTLOADER)), apm32-dfu) ifeq ($(strip $(BOOTLOADER)), apm32-dfu)
OPT_DEFS += -DBOOTLOADER_APM32_DFU OPT_DEFS += -DBOOTLOADER_APM32_DFU
BOOTLOADER_TYPE = stm32_dfu
# Options to pass to dfu-util when flashing # Options to pass to dfu-util when flashing
DFU_ARGS ?= -d 314B:0106 -a 0 -s 0x08000000:leave DFU_ARGS ?= -d 314B:0106 -a 0 -s 0x08000000:leave
@@ -129,6 +159,7 @@ ifeq ($(strip $(BOOTLOADER)), apm32-dfu)
endif endif
ifeq ($(strip $(BOOTLOADER)), gd32v-dfu) ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)
OPT_DEFS += -DBOOTLOADER_GD32V_DFU OPT_DEFS += -DBOOTLOADER_GD32V_DFU
BOOTLOADER_TYPE = gd32v_dfu
# Options to pass to dfu-util when flashing # Options to pass to dfu-util when flashing
DFU_ARGS ?= -d 28E9:0189 -a 0 -s 0x08000000:leave DFU_ARGS ?= -d 28E9:0189 -a 0 -s 0x08000000:leave
@@ -136,6 +167,8 @@ ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)
endif endif
ifeq ($(strip $(BOOTLOADER)), kiibohd) ifeq ($(strip $(BOOTLOADER)), kiibohd)
OPT_DEFS += -DBOOTLOADER_KIIBOHD OPT_DEFS += -DBOOTLOADER_KIIBOHD
BOOTLOADER_TYPE = kiibohd
ifeq ($(strip $(MCU_ORIG)), MK20DX128) ifeq ($(strip $(MCU_ORIG)), MK20DX128)
MCU_LDSCRIPT = MK20DX128BLDR4 MCU_LDSCRIPT = MK20DX128BLDR4
endif endif
@@ -151,8 +184,7 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino)
OPT_DEFS += -DBOOTLOADER_STM32DUINO OPT_DEFS += -DBOOTLOADER_STM32DUINO
MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
BOARD = STM32_F103_STM32DUINO BOARD = STM32_F103_STM32DUINO
# STM32F103 does NOT have an USB bootloader in ROM (only serial), so setting anything here does not make much sense BOOTLOADER_TYPE = stm32duino
STM32_BOOTLOADER_ADDRESS = 0x80000000
# Options to pass to dfu-util when flashing # Options to pass to dfu-util when flashing
DFU_ARGS = -d 1EAF:0003 -a 2 -R DFU_ARGS = -d 1EAF:0003 -a 2 -R
@@ -160,4 +192,17 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino)
endif endif
ifeq ($(strip $(BOOTLOADER)), tinyuf2) ifeq ($(strip $(BOOTLOADER)), tinyuf2)
OPT_DEFS += -DBOOTLOADER_TINYUF2 OPT_DEFS += -DBOOTLOADER_TINYUF2
BOOTLOADER_TYPE = tinyuf2
endif
ifeq ($(strip $(BOOTLOADER)), halfkay)
OPT_DEFS += -DBOOTLOADER_HALFKAY
BOOTLOADER_TYPE = halfkay
endif
ifeq ($(strip $(BOOTLOADER)), md-boot)
OPT_DEFS += -DBOOTLOADER_MD_BOOT
BOOTLOADER_TYPE = md_boot
endif
ifeq ($(strip $(BOOTLOADER_TYPE)),)
$(call CATASTROPHIC_ERROR,Invalid BOOTLOADER,No bootloader specified. Please set an appropriate 'BOOTLOADER' in your keyboard's 'rules.mk' file.)
endif endif

View File

@@ -14,7 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
$(TEST)_INC := \ $(TEST)_INC := \
tests\test_common\common_config.h tests/test_common/common_config.h
$(TEST)_SRC := \ $(TEST)_SRC := \
$(TMK_COMMON_SRC) \ $(TMK_COMMON_SRC) \
@@ -33,4 +33,4 @@ $(TEST)_DEFS := $(TMK_COMMON_DEFS) $(OPT_DEFS)
$(TEST)_CONFIG := $(TEST_PATH)/config.h $(TEST)_CONFIG := $(TEST_PATH)/config.h
VPATH += $(TOP_DIR)/tests/test_common VPATH += $(TOP_DIR)/tests/test_common

View File

@@ -37,6 +37,17 @@ ifdef SKIP_VERSION
OPT_DEFS += -DSKIP_VERSION OPT_DEFS += -DSKIP_VERSION
endif endif
# Generate the version.h file
ifdef SKIP_VERSION
VERSION_H_FLAGS := --skip-all
endif
ifdef SKIP_GIT
VERSION_H_FLAGS := --skip-git
endif
# Generate the board's version.h file.
$(shell $(QMK_BIN) generate-version-h $(VERSION_H_FLAGS) -q -o $(KEYMAP_OUTPUT)/src/version.h)
# Determine which subfolders exist. # Determine which subfolders exist.
KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD) KEYBOARD_FOLDER_PATH_1 := $(KEYBOARD)
KEYBOARD_FOLDER_PATH_2 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_1))) KEYBOARD_FOLDER_PATH_2 := $(patsubst %/,%,$(dir $(KEYBOARD_FOLDER_PATH_1)))
@@ -100,7 +111,7 @@ INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard
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
include build_json.mk include $(BUILDDEFS_PATH)/build_json.mk
# Pull in keymap level rules.mk # Pull in keymap level rules.mk
ifeq ("$(wildcard $(KEYMAP_PATH))", "") ifeq ("$(wildcard $(KEYMAP_PATH))", "")
@@ -127,9 +138,9 @@ ifeq ("$(wildcard $(KEYMAP_PATH))", "")
KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1) KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
else ifneq ($(LAYOUTS),) else ifneq ($(LAYOUTS),)
# If we haven't found a keymap yet fall back to community layouts # If we haven't found a keymap yet fall back to community layouts
include build_layout.mk include $(BUILDDEFS_PATH)/build_layout.mk
else else
$(error Could not find keymap) $(call CATASTROPHIC_ERROR,Invalid keymap,Could not find keymap)
# this state should never be reached # this state should never be reached
endif endif
endif endif
@@ -148,17 +159,21 @@ ifneq ("$(wildcard $(KEYMAP_JSON))", "")
# Add rules to generate the keymap files - indentation here is important # Add rules to generate the keymap files - indentation here is important
$(KEYMAP_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) $(KEYMAP_OUTPUT)/src/keymap.c: $(KEYMAP_JSON)
$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON))
@$(BUILD_CMD)
$(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON) $(KEYMAP_OUTPUT)/src/config.h: $(KEYMAP_JSON)
$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --keymap $(KEYMAP) --output $(KEYMAP_H) @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --keymap $(KEYMAP) --output $(KEYMAP_H))
@$(BUILD_CMD)
generated-files: $(KEYMAP_OUTPUT)/src/config.h $(KEYMAP_OUTPUT)/src/keymap.c generated-files: $(KEYMAP_OUTPUT)/src/config.h $(KEYMAP_OUTPUT)/src/keymap.c
endif 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)
@@ -315,13 +330,19 @@ endif
CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/layouts.h CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/layouts.h
$(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES) $(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES)
$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h)
@$(BUILD_CMD)
$(KEYBOARD_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES) $(KEYBOARD_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES)
$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h)
@$(BUILD_CMD)
$(KEYBOARD_OUTPUT)/src/layouts.h: $(INFO_JSON_FILES) $(KEYBOARD_OUTPUT)/src/layouts.h: $(INFO_JSON_FILES)
$(QMK_BIN) generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h)
@$(BUILD_CMD)
generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h
@@ -384,8 +405,10 @@ VPATH += $(KEYMAP_PATH)
VPATH += $(USER_PATH) VPATH += $(USER_PATH)
VPATH += $(KEYBOARD_PATHS) VPATH += $(KEYBOARD_PATHS)
VPATH += $(COMMON_VPATH) VPATH += $(COMMON_VPATH)
VPATH += $(KEYBOARD_OUTPUT)/src
VPATH += $(KEYMAP_OUTPUT)/src
include common_features.mk include $(BUILDDEFS_PATH)/common_features.mk
include $(BUILDDEFS_PATH)/generic_features.mk include $(BUILDDEFS_PATH)/generic_features.mk
include $(TMK_PATH)/protocol.mk include $(TMK_PATH)/protocol.mk
include $(PLATFORM_PATH)/common.mk include $(PLATFORM_PATH)/common.mk
@@ -425,8 +448,7 @@ OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT)
$(KEYMAP_OUTPUT)_SRC := $(SRC) $(KEYMAP_OUTPUT)_SRC := $(SRC)
$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \ $(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \
-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(QMK_KEYBOARD_H)\" \ -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(QMK_KEYBOARD_H)\" \
-DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\" \ -DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\"
-DQMK_SUBPROJECT -DQMK_SUBPROJECT_H -DQMK_SUBPROJECT_CONFIG_H
$(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS)
$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H) $(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H)
$(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC) $(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC)
@@ -448,7 +470,7 @@ check-md5: build
objs-size: build objs-size: build
include $(BUILDDEFS_PATH)/show_options.mk include $(BUILDDEFS_PATH)/show_options.mk
include $(TMK_PATH)/rules.mk include $(BUILDDEFS_PATH)/common_rules.mk
# Ensure we have generated files available for each of the objects # Ensure we have generated files available for each of the objects
define GEN_FILES define GEN_FILES

View File

@@ -25,7 +25,7 @@ ifneq ($(FORCE_LAYOUT),)
$(info Forcing layout: $(FORCE_LAYOUT)) $(info Forcing layout: $(FORCE_LAYOUT))
LAYOUTS := $(FORCE_LAYOUT) LAYOUTS := $(FORCE_LAYOUT)
else else
$(error Forced layout does not exist) $(call CATASTROPHIC_ERROR,Invalid layout,Forced layout does not exist)
endif endif
endif endif

View File

@@ -43,6 +43,7 @@ all: elf
VPATH += $(COMMON_VPATH) VPATH += $(COMMON_VPATH)
PLATFORM:=TEST PLATFORM:=TEST
PLATFORM_KEY:=test PLATFORM_KEY:=test
BOOTLOADER_TYPE:=none
ifeq ($(strip $(DEBUG)), 1) ifeq ($(strip $(DEBUG)), 1)
CONSOLE_ENABLE = yes CONSOLE_ENABLE = yes
@@ -53,7 +54,7 @@ include tests/test_common/build.mk
include $(TEST_PATH)/test.mk include $(TEST_PATH)/test.mk
endif endif
include common_features.mk include $(BUILDDEFS_PATH)/common_features.mk
include $(BUILDDEFS_PATH)/generic_features.mk include $(BUILDDEFS_PATH)/generic_features.mk
include $(PLATFORM_PATH)/common.mk include $(PLATFORM_PATH)/common.mk
include $(TMK_PATH)/protocol.mk include $(TMK_PATH)/protocol.mk
@@ -62,7 +63,7 @@ include $(QUANTUM_PATH)/encoder/tests/rules.mk
include $(QUANTUM_PATH)/sequencer/tests/rules.mk include $(QUANTUM_PATH)/sequencer/tests/rules.mk
include $(PLATFORM_PATH)/test/rules.mk include $(PLATFORM_PATH)/test/rules.mk
ifneq ($(filter $(FULL_TESTS),$(TEST)),) ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include build_full_test.mk include $(BUILDDEFS_PATH)/build_full_test.mk
endif endif
$(TEST)_SRC += \ $(TEST)_SRC += \
@@ -76,7 +77,7 @@ $(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG) $(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG)
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
include $(TMK_PATH)/rules.mk include $(BUILDDEFS_PATH)/common_rules.mk
$(shell mkdir -p $(BUILD_DIR)/test 2>/dev/null) $(shell mkdir -p $(BUILD_DIR)/test 2>/dev/null)

View File

@@ -20,7 +20,6 @@ QUANTUM_SRC += \
$(QUANTUM_DIR)/led.c \ $(QUANTUM_DIR)/led.c \
$(QUANTUM_DIR)/action.c \ $(QUANTUM_DIR)/action.c \
$(QUANTUM_DIR)/action_layer.c \ $(QUANTUM_DIR)/action_layer.c \
$(QUANTUM_DIR)/action_macro.c \
$(QUANTUM_DIR)/action_tapping.c \ $(QUANTUM_DIR)/action_tapping.c \
$(QUANTUM_DIR)/action_util.c \ $(QUANTUM_DIR)/action_util.c \
$(QUANTUM_DIR)/eeconfig.c \ $(QUANTUM_DIR)/eeconfig.c \
@@ -109,11 +108,10 @@ ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/mousekey.c SRC += $(QUANTUM_DIR)/mousekey.c
endif endif
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi pmw3360 pimoroni_trackball custom VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi pmw3360 pmw3389 pimoroni_trackball custom
POINTING_DEVICE_DRIVER ?= custom
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),) ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
$(error POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type) $(call CATASTROPHIC_ERROR,Invalid POINTING_DEVICE_DRIVER,POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
else else
OPT_DEFS += -DPOINTING_DEVICE_ENABLE OPT_DEFS += -DPOINTING_DEVICE_ENABLE
MOUSE_ENABLE := yes MOUSE_ENABLE := yes
@@ -144,6 +142,9 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3360) else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3360)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
QUANTUM_LIB_SRC += spi_master.c QUANTUM_LIB_SRC += spi_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3389)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
QUANTUM_LIB_SRC += spi_master.c
endif endif
endif endif
endif endif
@@ -151,56 +152,88 @@ endif
VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi
EEPROM_DRIVER ?= vendor EEPROM_DRIVER ?= vendor
ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),) ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),)
$(error EEPROM_DRIVER="$(EEPROM_DRIVER)" is not a valid EEPROM driver) $(call CATASTROPHIC_ERROR,Invalid EEPROM_DRIVER,EEPROM_DRIVER="$(EEPROM_DRIVER)" is not a valid EEPROM driver)
else else
OPT_DEFS += -DEEPROM_ENABLE OPT_DEFS += -DEEPROM_ENABLE
ifeq ($(strip $(EEPROM_DRIVER)), custom) ifeq ($(strip $(EEPROM_DRIVER)), custom)
# Custom EEPROM implementation -- only needs to implement init/erase/read_block/write_block
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_CUSTOM OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_CUSTOM
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c SRC += eeprom_driver.c
else ifeq ($(strip $(EEPROM_DRIVER)), i2c) else ifeq ($(strip $(EEPROM_DRIVER)), i2c)
# External I2C EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
SRC += eeprom_driver.c eeprom_i2c.c SRC += eeprom_driver.c eeprom_i2c.c
else ifeq ($(strip $(EEPROM_DRIVER)), spi) else ifeq ($(strip $(EEPROM_DRIVER)), spi)
# External SPI EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
QUANTUM_LIB_SRC += spi_master.c QUANTUM_LIB_SRC += spi_master.c
SRC += eeprom_driver.c eeprom_spi.c SRC += eeprom_driver.c eeprom_spi.c
else ifeq ($(strip $(EEPROM_DRIVER)), transient) else ifeq ($(strip $(EEPROM_DRIVER)), transient)
# Transient EEPROM implementation -- no data storage but provides runtime area for it
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c eeprom_transient.c SRC += eeprom_driver.c eeprom_transient.c
else ifeq ($(strip $(EEPROM_DRIVER)), vendor) else ifeq ($(strip $(EEPROM_DRIVER)), vendor)
# Vendor-implemented EEPROM
OPT_DEFS += -DEEPROM_VENDOR OPT_DEFS += -DEEPROM_VENDOR
ifeq ($(PLATFORM),AVR) ifeq ($(PLATFORM),AVR)
# Automatically provided by avr-libc, nothing required # Automatically provided by avr-libc, nothing required
else ifeq ($(PLATFORM),CHIBIOS) else ifeq ($(PLATFORM),CHIBIOS)
ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6 %_GD32VF103xB %_GD32VF103x8, $(MCU_SERIES)_$(MCU_LDSCRIPT)),) ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6 %_GD32VF103xB %_GD32VF103x8, $(MCU_SERIES)_$(MCU_LDSCRIPT)),)
OPT_DEFS += -DEEPROM_DRIVER # Emulated EEPROM
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_FLASH_EMULATED
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c SRC += eeprom_driver.c
SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),) else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
OPT_DEFS += -DEEPROM_DRIVER # True EEPROM on STM32L0xx, L1xx
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_L0_L1
COMMON_VPATH += $(DRIVER_PATH)/eeprom COMMON_VPATH += $(DRIVER_PATH)/eeprom
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom
SRC += eeprom_driver.c SRC += eeprom_driver.c
SRC += eeprom_stm32_L0_L1.c SRC += eeprom_stm32_L0_L1.c
else ifneq ($(filter $(MCU_SERIES),KL2x K20x),)
# Teensy EEPROM implementations
OPT_DEFS += -DEEPROM_TEENSY
SRC += eeprom_teensy.c
else else
# This will effectively work the same as "transient" if not supported by the chip # Fall back to transient, i.e. non-persistent
SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c eeprom_transient.c
endif endif
else ifeq ($(PLATFORM),ARM_ATSAM) else ifeq ($(PLATFORM),ARM_ATSAM)
SRC += $(PLATFORM_COMMON_DIR)/eeprom.c # arm_atsam EEPROM
OPT_DEFS += -DEEPROM_SAMD
SRC += $(PLATFORM_COMMON_DIR)/eeprom_samd.c
else ifeq ($(PLATFORM),TEST) else ifeq ($(PLATFORM),TEST)
# Test harness "EEPROM"
OPT_DEFS += -DEEPROM_TEST_HARNESS
SRC += $(PLATFORM_COMMON_DIR)/eeprom.c SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
endif endif
endif endif
endif endif
VALID_FLASH_DRIVER_TYPES := spi
FLASH_DRIVER ?= no
ifneq ($(strip $(FLASH_DRIVER)), no)
ifeq ($(filter $(FLASH_DRIVER),$(VALID_FLASH_DRIVER_TYPES)),)
$(error FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid FLASH driver)
else
OPT_DEFS += -DFLASH_ENABLE
ifeq ($(strip $(FLASH_DRIVER)), spi)
OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI
COMMON_VPATH += $(DRIVER_PATH)/flash
SRC += flash_spi.c
endif
endif
endif
RGBLIGHT_ENABLE ?= no RGBLIGHT_ENABLE ?= no
VALID_RGBLIGHT_TYPES := WS2812 APA102 custom VALID_RGBLIGHT_TYPES := WS2812 APA102 custom
@@ -212,7 +245,7 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
RGBLIGHT_DRIVER ?= WS2812 RGBLIGHT_DRIVER ?= WS2812
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) $(call CATASTROPHIC_ERROR,Invalid RGBLIGHT_DRIVER,RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type)
else else
COMMON_VPATH += $(QUANTUM_DIR)/rgblight COMMON_VPATH += $(QUANTUM_DIR)/rgblight
POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h POST_CONFIG_H += $(QUANTUM_DIR)/rgblight/rgblight_post_config.h
@@ -237,12 +270,12 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
endif endif
LED_MATRIX_ENABLE ?= no LED_MATRIX_ENABLE ?= no
VALID_LED_MATRIX_TYPES := IS31FL3731 custom VALID_LED_MATRIX_TYPES := IS31FL3731 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A custom
# TODO: IS31FL3733 IS31FL3737 IS31FL3741 # TODO: IS31FL3733 IS31FL3737 IS31FL3741
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),) ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
$(error "$(LED_MATRIX_DRIVER)" is not a valid matrix type) $(call CATASTROPHIC_ERROR,Invalid LED_MATRIX_DRIVER,LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type)
endif endif
OPT_DEFS += -DLED_MATRIX_ENABLE OPT_DEFS += -DLED_MATRIX_ENABLE
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
@@ -264,14 +297,43 @@ endif
SRC += is31fl3731-simple.c SRC += is31fl3731-simple.c
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3742A)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3743A)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3745)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3746A)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
endif endif
RGB_MATRIX_ENABLE ?= no RGB_MATRIX_ENABLE ?= no
VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 CKLED2001 WS2812 custom
VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 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)),)
$(error "$(RGB_MATRIX_DRIVER)" is not a valid matrix type) $(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
endif endif
OPT_DEFS += -DRGB_MATRIX_ENABLE OPT_DEFS += -DRGB_MATRIX_ENABLE
ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
@@ -323,6 +385,34 @@ endif
QUANTUM_LIB_SRC += i2c_master.c QUANTUM_LIB_SRC += i2c_master.c
endif endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3742A)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3742A -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3743A)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3743A -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3745)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3745 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3746A)
OPT_DEFS += -DIS31FLCOMMON -DIS31FL3746A -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31flcommon.c
QUANTUM_LIB_SRC += i2c_master.c
endif
ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001) ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001)
OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led COMMON_VPATH += $(DRIVER_PATH)/led
@@ -356,7 +446,7 @@ endif
ifeq ($(strip $(PRINTING_ENABLE)), yes) ifeq ($(strip $(PRINTING_ENABLE)), yes)
OPT_DEFS += -DPRINTING_ENABLE OPT_DEFS += -DPRINTING_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c
SRC += $(TMK_DIR)/protocol/serial_uart.c QUANTUM_LIB_SRC += uart.c
endif endif
VARIABLE_TRACE ?= no VARIABLE_TRACE ?= no
@@ -385,7 +475,7 @@ else
endif endif
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),) ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),)
$(error BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type) $(call CATASTROPHIC_ERROR,Invalid BACKLIGHT_DRIVER,BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type)
endif endif
COMMON_VPATH += $(QUANTUM_DIR)/backlight COMMON_VPATH += $(QUANTUM_DIR)/backlight
@@ -410,7 +500,7 @@ VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c
WS2812_DRIVER ?= bitbang WS2812_DRIVER ?= bitbang
ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes) ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),) ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),)
$(error WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver) $(call CATASTROPHIC_ERROR,Invalid WS2812_DRIVER,WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver)
endif endif
OPT_DEFS += -DWS2812_DRIVER_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]')) OPT_DEFS += -DWS2812_DRIVER_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]'))
@@ -471,7 +561,7 @@ VALID_MAGIC_TYPES := yes
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) $(call CATASTROPHIC_ERROR,Invalid BOOTMAGIC_ENABLE,BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic)
endif endif
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no) ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
OPT_DEFS += -DBOOTMAGIC_LITE OPT_DEFS += -DBOOTMAGIC_LITE
@@ -487,7 +577,7 @@ CUSTOM_MATRIX ?= no
ifneq ($(strip $(CUSTOM_MATRIX)), yes) ifneq ($(strip $(CUSTOM_MATRIX)), yes)
ifeq ($(filter $(CUSTOM_MATRIX),$(VALID_CUSTOM_MATRIX_TYPES)),) ifeq ($(filter $(CUSTOM_MATRIX),$(VALID_CUSTOM_MATRIX_TYPES)),)
$(error CUSTOM_MATRIX="$(CUSTOM_MATRIX)" is not a valid custom matrix type) $(call CATASTROPHIC_ERROR,Invalid CUSTOM_MATRIX,CUSTOM_MATRIX="$(CUSTOM_MATRIX)" is not a valid custom matrix type)
endif endif
# Include common stuff for all non custom matrix users # Include common stuff for all non custom matrix users
@@ -570,7 +660,7 @@ VALID_OLED_DRIVER_TYPES := SSD1306 custom
OLED_DRIVER ?= SSD1306 OLED_DRIVER ?= SSD1306
ifeq ($(strip $(OLED_ENABLE)), yes) ifeq ($(strip $(OLED_ENABLE)), yes)
ifeq ($(filter $(OLED_DRIVER),$(VALID_OLED_DRIVER_TYPES)),) ifeq ($(filter $(OLED_DRIVER),$(VALID_OLED_DRIVER_TYPES)),)
$(error OLED_DRIVER="$(OLED_DRIVER)" is not a valid OLED driver) $(call CATASTROPHIC_ERROR,Invalid OLED_DRIVER,OLED_DRIVER="$(OLED_DRIVER)" is not a valid OLED driver)
else else
OPT_DEFS += -DOLED_ENABLE OPT_DEFS += -DOLED_ENABLE
COMMON_VPATH += $(DRIVER_PATH)/oled COMMON_VPATH += $(DRIVER_PATH)/oled
@@ -610,6 +700,7 @@ ifeq ($(strip $(UNICODE_ENABLE)), yes)
endif endif
ifeq ($(strip $(UNICODE_COMMON)), yes) ifeq ($(strip $(UNICODE_COMMON)), yes)
OPT_DEFS += -DUNICODE_COMMON_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c
endif endif
@@ -637,7 +728,7 @@ endif
ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes) ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes)
PS2_ENABLE := yes PS2_ENABLE := yes
SRC += ps2_busywait.c SRC += ps2_busywait.c
SRC += ps2_io_avr.c SRC += ps2_io.c
OPT_DEFS += -DPS2_USE_BUSYWAIT OPT_DEFS += -DPS2_USE_BUSYWAIT
endif endif
@@ -666,7 +757,7 @@ VALID_JOYSTICK_TYPES := analog digital
JOYSTICK_DRIVER ?= analog JOYSTICK_DRIVER ?= analog
ifeq ($(strip $(JOYSTICK_ENABLE)), yes) ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
ifeq ($(filter $(JOYSTICK_DRIVER),$(VALID_JOYSTICK_TYPES)),) ifeq ($(filter $(JOYSTICK_DRIVER),$(VALID_JOYSTICK_TYPES)),)
$(error "$(JOYSTICK_DRIVER)" is not a valid joystick driver) $(call CATASTROPHIC_ERROR,Invalid JOYSTICK_DRIVER,JOYSTICK_DRIVER="$(JOYSTICK_DRIVER)" is not a valid joystick driver)
endif 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
@@ -686,7 +777,7 @@ VALID_USBPD_DRIVER_TYPES = custom vendor
USBPD_DRIVER ?= vendor USBPD_DRIVER ?= vendor
ifeq ($(strip $(USBPD_ENABLE)), yes) ifeq ($(strip $(USBPD_ENABLE)), yes)
ifeq ($(filter $(strip $(USBPD_DRIVER)),$(VALID_USBPD_DRIVER_TYPES)),) ifeq ($(filter $(strip $(USBPD_DRIVER)),$(VALID_USBPD_DRIVER_TYPES)),)
$(error USBPD_DRIVER="$(USBPD_DRIVER)" is not a valid USBPD driver) $(call CATASTROPHIC_ERROR,Invalid USBPD_DRIVER,USBPD_DRIVER="$(USBPD_DRIVER)" is not a valid USBPD driver)
else else
OPT_DEFS += -DUSBPD_ENABLE OPT_DEFS += -DUSBPD_ENABLE
ifeq ($(strip $(USBPD_DRIVER)), vendor) ifeq ($(strip $(USBPD_DRIVER)), vendor)
@@ -696,7 +787,7 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
OPT_DEFS += -DUSBPD_STM32G4 OPT_DEFS += -DUSBPD_STM32G4
SRC += usbpd_stm32g4.c SRC += usbpd_stm32g4.c
else else
$(error There is no vendor-provided USBPD driver available) $(call CATASTROPHIC_ERROR,Invalid USBPD_DRIVER,There is no vendor-provided USBPD driver available)
endif endif
else ifeq ($(strip $(USBPD_DRIVER)), custom) else ifeq ($(strip $(USBPD_DRIVER)), custom)
OPT_DEFS += -DUSBPD_CUSTOM OPT_DEFS += -DUSBPD_CUSTOM
@@ -706,25 +797,26 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
endif endif
BLUETOOTH_ENABLE ?= no BLUETOOTH_ENABLE ?= no
VALID_BLUETOOTH_DRIVER_TYPES := AdafruitBLE RN42 custom VALID_BLUETOOTH_DRIVER_TYPES := BluefruitLE RN42 custom
ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),) ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),)
$(error "$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type) $(call CATASTROPHIC_ERROR,Invalid BLUETOOTH_DRIVER,BLUETOOTH_DRIVER="$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type)
endif endif
OPT_DEFS += -DBLUETOOTH_ENABLE OPT_DEFS += -DBLUETOOTH_ENABLE
NO_USB_STARTUP_CHECK := yes NO_USB_STARTUP_CHECK := yes
COMMON_VPATH += $(DRIVER_PATH)/bluetooth COMMON_VPATH += $(DRIVER_PATH)/bluetooth
SRC += outputselect.c SRC += outputselect.c
ifeq ($(strip $(BLUETOOTH_DRIVER)), AdafruitBLE) ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE)
OPT_DEFS += -DMODULE_ADAFRUIT_BLE OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE
SRC += analog.c SRC += analog.c
SRC += $(DRIVER_PATH)/bluetooth/adafruit_ble.cpp SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp
QUANTUM_LIB_SRC += spi_master.c QUANTUM_LIB_SRC += spi_master.c
endif endif
ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42) ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42)
OPT_DEFS += -DMODULE_RN42 OPT_DEFS += -DBLUETOOTH_RN42
SRC += $(TMK_DIR)/protocol/serial_uart.c SRC += $(DRIVER_PATH)/bluetooth/rn42.c
QUANTUM_LIB_SRC += uart.c
endif endif
endif endif

View File

@@ -234,6 +234,7 @@ endif
# Define programs and commands. # Define programs and commands.
SHELL = sh SHELL = sh
SED = sed
REMOVE = rm -f REMOVE = rm -f
REMOVEDIR = rmdir REMOVEDIR = rmdir
COPY = cp COPY = cp
@@ -292,17 +293,15 @@ sym: $(BUILD_DIR)/$(TARGET).sym
LIBNAME=lib$(TARGET).a LIBNAME=lib$(TARGET).a
lib: $(LIBNAME) lib: $(LIBNAME)
# Display size of file. # Display size of file, modifying the output so people don't mistakenly grab the hex output
HEXSIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex BINARY_SIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(SED) -e 's/\.build\/.*$$/$(TARGET).$(FIRMWARE_FORMAT)/g'
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
ELFSIZE = $(SIZE) $(BUILD_DIR)/$(TARGET).elf
sizebefore: sizebefore:
@if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO) $(MSG_SIZE_BEFORE); $(SILENT) || $(HEXSIZE); \ @if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO) $(MSG_SIZE_BEFORE); $(SILENT) || $(BINARY_SIZE); \
2>/dev/null; $(SECHO); fi 2>/dev/null; $(SECHO); fi
sizeafter: $(BUILD_DIR)/$(TARGET).hex sizeafter: $(BUILD_DIR)/$(TARGET).hex
@if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO); $(SECHO) $(MSG_SIZE_AFTER); $(SILENT) || $(HEXSIZE); \ @if test -f $(BUILD_DIR)/$(TARGET).hex; then $(SECHO); $(SECHO) $(MSG_SIZE_AFTER); $(SILENT) || $(BINARY_SIZE); \
2>/dev/null; $(SECHO); fi 2>/dev/null; $(SECHO); fi
# Display compiler version information. # Display compiler version information.
@@ -479,7 +478,7 @@ ifeq ($(findstring avr-gcc,$(CC)),avr-gcc)
SIZE_MARGIN = 1024 SIZE_MARGIN = 1024
check-size: check-size:
$(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) platforms/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) platforms/avr/bootloader_size.c 2> /dev/null | $(SED) -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
$(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi)) $(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi))
$(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE))) $(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE)))
$(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE))) $(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE)))

View File

@@ -143,6 +143,9 @@ ifneq ($(findstring STM32F042, $(MCU)),)
# This ensures that the EEPROM page buffer fits into RAM # This ensures that the EEPROM page buffer fits into RAM
USE_PROCESS_STACKSIZE = 0x600 USE_PROCESS_STACKSIZE = 0x600
USE_EXCEPTIONS_STACKSIZE = 0x300 USE_EXCEPTIONS_STACKSIZE = 0x300
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFFC400
endif endif
ifneq ($(findstring STM32F072, $(MCU)),) ifneq ($(findstring STM32F072, $(MCU)),)
@@ -175,6 +178,9 @@ ifneq ($(findstring STM32F072, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32F0 UF2_FAMILY ?= STM32F0
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFFC800
endif endif
ifneq ($(findstring STM32F103, $(MCU)),) ifneq ($(findstring STM32F103, $(MCU)),)
@@ -239,6 +245,9 @@ ifneq ($(findstring STM32F303, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32F3 UF2_FAMILY ?= STM32F3
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFFD800
endif endif
ifneq ($(findstring STM32F401, $(MCU)),) ifneq ($(findstring STM32F401, $(MCU)),)
@@ -276,6 +285,9 @@ ifneq ($(findstring STM32F401, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32F4 UF2_FAMILY ?= STM32F4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring STM32F405, $(MCU)),) ifneq ($(findstring STM32F405, $(MCU)),)
@@ -308,6 +320,9 @@ ifneq ($(findstring STM32F405, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32F4 UF2_FAMILY ?= STM32F4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring STM32F407, $(MCU)),) ifneq ($(findstring STM32F407, $(MCU)),)
@@ -340,6 +355,9 @@ ifneq ($(findstring STM32F407, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32F4 UF2_FAMILY ?= STM32F4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring STM32F411, $(MCU)),) ifneq ($(findstring STM32F411, $(MCU)),)
@@ -377,6 +395,9 @@ ifneq ($(findstring STM32F411, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32F4 UF2_FAMILY ?= STM32F4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring STM32F446, $(MCU)),) ifneq ($(findstring STM32F446, $(MCU)),)
@@ -406,6 +427,9 @@ ifneq ($(findstring STM32F446, $(MCU)),)
BOARD ?= GENERIC_STM32_F446XE BOARD ?= GENERIC_STM32_F446XE
USE_FPU ?= yes USE_FPU ?= yes
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring STM32G431, $(MCU)),) ifneq ($(findstring STM32G431, $(MCU)),)
@@ -438,6 +462,9 @@ ifneq ($(findstring STM32G431, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32G4 UF2_FAMILY ?= STM32G4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring STM32G474, $(MCU)),) ifneq ($(findstring STM32G474, $(MCU)),)
@@ -470,6 +497,46 @@ ifneq ($(findstring STM32G474, $(MCU)),)
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32G4 UF2_FAMILY ?= STM32G4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif
ifneq (,$(filter $(MCU),STM32L432 STM32L442))
# Cortex version
MCU = cortex-m4
# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
ARMV = 7
## chip/board settings
# - the next two should match the directories in
# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
MCU_FAMILY = STM32
MCU_SERIES = STM32L4xx
# Linker script to use
# - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32L432xC
# Startup code to use
# - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
MCU_STARTUP ?= stm32l4xx
# Board: it should exist either in <chibios>/os/hal/boards/,
# <keyboard_dir>/boards/, or drivers/boards/
BOARD ?= GENERIC_STM32_L432XC
PLATFORM_NAME ?= platform_l432
USE_FPU ?= yes
# UF2 settings
UF2_FAMILY ?= STM32L4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq (,$(filter $(MCU),STM32L433 STM32L443)) ifneq (,$(filter $(MCU),STM32L433 STM32L443))
@@ -504,6 +571,9 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443))
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32L4 UF2_FAMILY ?= STM32L4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq (,$(filter $(MCU),STM32L412 STM32L422)) ifneq (,$(filter $(MCU),STM32L412 STM32L422))
@@ -538,6 +608,9 @@ ifneq (,$(filter $(MCU),STM32L412 STM32L422))
# UF2 settings # UF2 settings
UF2_FAMILY ?= STM32L4 UF2_FAMILY ?= STM32L4
# Bootloader address for STM32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFF0000
endif endif
ifneq ($(findstring WB32F3G71, $(MCU)),) ifneq ($(findstring WB32F3G71, $(MCU)),)
@@ -567,6 +640,10 @@ ifneq ($(findstring WB32F3G71, $(MCU)),)
BOARD ?= GENERIC_WB32_F3G71XX BOARD ?= GENERIC_WB32_F3G71XX
USE_FPU ?= no USE_FPU ?= no
# Bootloader address for WB32 DFU
STM32_BOOTLOADER_ADDRESS ?= 0x1FFFE000
WB32_BOOTLOADER_ADDRESS ?= 0x1FFFE000
endif endif
ifneq ($(findstring GD32VF103, $(MCU)),) ifneq ($(findstring GD32VF103, $(MCU)),)

View File

@@ -63,6 +63,7 @@ MSG_COMPILING_CXX = Compiling:
MSG_ASSEMBLING = Assembling: MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project: MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library: MSG_CREATING_LIBRARY = Creating library:
MSG_GENERATING = Generating:
MSG_SUBMODULE_DIRTY = $(WARN_COLOR)WARNING:$(NO_COLOR) Some git submodules are out of date or modified.\n\ MSG_SUBMODULE_DIRTY = $(WARN_COLOR)WARNING:$(NO_COLOR) Some git submodules are out of date or modified.\n\
Please consider running $(BOLD)make git-submodule$(NO_COLOR).\n\n Please consider running $(BOLD)make git-submodule$(NO_COLOR).\n\n
MSG_NO_CMP = $(ERROR_COLOR)Error:$(NO_COLOR)$(BOLD) cmp command not found, please install diffutils\n$(NO_COLOR) MSG_NO_CMP = $(ERROR_COLOR)Error:$(NO_COLOR)$(BOLD) cmp command not found, please install diffutils\n$(NO_COLOR)
@@ -87,6 +88,7 @@ define GENERATE_MSG_AVAILABLE_KEYMAPS
endef endef
MSG_AVAILABLE_KEYMAPS = $(eval $(call GENERATE_MSG_AVAILABLE_KEYMAPS))$(MSG_AVAILABLE_KEYMAPS_ACTUAL) MSG_AVAILABLE_KEYMAPS = $(eval $(call GENERATE_MSG_AVAILABLE_KEYMAPS))$(MSG_AVAILABLE_KEYMAPS_ACTUAL)
MSG_BOOTLOADER_NOT_FOUND_BASE = Bootloader not found. Make sure the board is in bootloader mode. See https://docs.qmk.fm/\#/newbs_flashing\n
MSG_CHECK_FILESIZE = Checking file size of $(TARGET).$(FIRMWARE_FORMAT) MSG_CHECK_FILESIZE = Checking file size of $(TARGET).$(FIRMWARE_FORMAT)
MSG_CHECK_FILESIZE_SKIPPED = (Firmware size check does not yet support $(MCU_ORIG); skipping) MSG_CHECK_FILESIZE_SKIPPED = (Firmware size check does not yet support $(MCU_ORIG); skipping)
MSG_FILE_TOO_BIG = $(ERROR_COLOR)The firmware is too large!$(NO_COLOR) $(CURRENT_SIZE)/$(MAX_SIZE) ($(OVER_SIZE) bytes over)\n MSG_FILE_TOO_BIG = $(ERROR_COLOR)The firmware is too large!$(NO_COLOR) $(CURRENT_SIZE)/$(MAX_SIZE) ($(OVER_SIZE) bytes over)\n
@@ -97,6 +99,11 @@ MSG_PYTHON_MISSING = $(ERROR_COLOR)ERROR:$(NO_COLOR) Cannot run \"qmk hello\"!\n
Please run $(BOLD)qmk setup$(NO_COLOR) to install all the dependencies QMK requires.\n\n Please run $(BOLD)qmk setup$(NO_COLOR) to install all the dependencies QMK requires.\n\n
MSG_FLASH_BOOTLOADER = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's bootloader is not specified or is not supported by the \":flash\" target at this time.\n\n MSG_FLASH_BOOTLOADER = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's bootloader is not specified or is not supported by the \":flash\" target at this time.\n\n
MSG_FLASH_ARCH = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's architecture is not supported by the \":flash\" target at this time.\n\n MSG_FLASH_ARCH = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's architecture is not supported by the \":flash\" target at this time.\n\n
MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) Bootloader not found. Trying again in 5s (Ctrl+C to cancel)\n MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) $(MSG_BOOTLOADER_NOT_FOUND_BASE) Trying again in 5s (Ctrl+C to cancel)\n
BOOTLOADER_RETRY_TIME ?= 0.5 BOOTLOADER_RETRY_TIME ?= 0.5
MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY = Bootloader not found. Trying again every $(BOOTLOADER_RETRY_TIME)s (Ctrl+C to cancel) MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY = $(MSG_BOOTLOADER_NOT_FOUND_BASE) Trying again every $(BOOTLOADER_RETRY_TIME)s (Ctrl+C to cancel)
define CATASTROPHIC_ERROR
$(shell printf "\n * %-99s $(ERROR_STRING)\n" "$2" >&2)
$(error $1)
endef

View File

@@ -8,7 +8,7 @@ include $(PLATFORM_PATH)/test/testlist.mk
define VALIDATE_TEST_LIST define VALIDATE_TEST_LIST
ifneq ($1,) ifneq ($1,)
ifeq ($$(findstring -,$1),-) ifeq ($$(findstring -,$1),-)
$$(error Test names can't contain '-', but '$1' does) $$(call CATASTROPHIC_ERROR,Invalid test name,Test names can't contain '-', but '$1' does.)
else else
$$(eval $$(call VALIDATE_TEST_LIST,$$(firstword $2),$$(wordlist 2,9999,$2))) $$(eval $$(call VALIDATE_TEST_LIST,$$(firstword $2),$$(wordlist 2,9999,$2)))
endif endif

View File

@@ -15,6 +15,8 @@
"COMBO_TERM": {"info_key": "combo.term", "value_type": "int"}, "COMBO_TERM": {"info_key": "combo.term", "value_type": "int"},
"DEBOUNCE": {"info_key": "debounce", "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"},
# TODO: Replace ^^^ with vvv
#"DEVICE_VER": {"info_key": "usb.device_version", "value_type": "bcd_version"},
"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"}, "FORCE_NKRO": {"info_key": "usb.force_nkro", "value_type": "bool"},

View File

@@ -41,8 +41,14 @@
'atom47/rev3': { 'atom47/rev3': {
target: 'maartenwut/atom47/rev3' target: 'maartenwut/atom47/rev3'
}, },
bakeneko60: {
target: 'kkatano/bakeneko60'
},
bakeneko65: { bakeneko65: {
target: 'bakeneko65/rev2' target: 'kkatano/bakeneko65/rev2'
},
bakeneko80: {
target: 'kkatano/bakeneko80'
}, },
bear_face: { bear_face: {
target: 'bear_face/v1' target: 'bear_face/v1'
@@ -215,6 +221,9 @@
LAYOUT: 'LAYOUT_all' LAYOUT: 'LAYOUT_all'
} }
}, },
idobo: {
target: 'idobao/id75'
},
'jj40': { 'jj40': {
target: 'kprepublic/jj40' target: 'kprepublic/jj40'
}, },
@@ -260,6 +269,9 @@
'lfkeyboards/smk65': { 'lfkeyboards/smk65': {
target: 'lfkeyboards/smk65/revb' target: 'lfkeyboards/smk65/revb'
}, },
m3v3van: {
target: 'matthewdias/m3n3van'
},
'maartenwut/atom47/rev2': { 'maartenwut/atom47/rev2': {
target: 'evyd13/atom47/rev2' target: 'evyd13/atom47/rev2'
}, },
@@ -344,15 +356,24 @@
'mechlovin/hannah65/mechlovin9': { 'mechlovin/hannah65/mechlovin9': {
target: 'mechlovin/mechlovin9/rev1' target: 'mechlovin/mechlovin9/rev1'
}, },
'mechlovin/hex4b': {
target: 'mechlovin/hex4b/rev1'
},
'melgeek/z70ultra': { 'melgeek/z70ultra': {
target: 'melgeek/z70ultra/rev1' target: 'melgeek/z70ultra/rev1'
}, },
'mechlovin/hannah65': { 'mechlovin/hannah65': {
target: 'mechlovin/hannah65/rev1' target: 'mechlovin/hannah65/rev1'
}, },
minim: {
target: 'matthewdias/minim'
},
model01: { model01: {
target: 'keyboardio/model01' target: 'keyboardio/model01'
}, },
model_v: {
target: 'matthewdias/model_v'
},
m0lly: { m0lly: {
target: 'tkc/m0lly' target: 'tkc/m0lly'
}, },
@@ -495,6 +516,9 @@
'tokyo60': { 'tokyo60': {
target: 'tokyokeyboard/tokyo60' target: 'tokyokeyboard/tokyo60'
}, },
'txuu': {
target: 'matthewdias/txuu'
},
underscore33: { underscore33: {
target: 'underscore33/rev1' target: 'underscore33/rev1'
}, },
@@ -547,7 +571,7 @@
target: 'xelus/valor/rev1' target: 'xelus/valor/rev1'
}, },
yd60mq: { yd60mq: {
target: 'yd60mq/12led' target: 'ymdk/yd60mq/12led'
}, },
ymd75: { ymd75: {
target: 'ymd75/rev1' target: 'ymd75/rev1'
@@ -560,5 +584,615 @@
}, },
zeal65: { zeal65: {
target: 'wilba_tech/zeal65' target: 'wilba_tech/zeal65'
},
# Moved during 2022 Q1 cycle
6ball: {
target: 'maple_computing/6ball'
},
7skb: {
target: 'salicylic_acid3/7skb'
},
7splus: {
target: 'salicylic_acid3/7splus'
},
acr60: {
target: 'mechkeys/acr60'
},
adalyn: {
target: 'tominabox1/adalyn'
},
ajisai74: {
target: 'salicylic_acid3/ajisai74'
},
aleth42: {
target: '25keys/aleth42'
},
alicia_cook: {
target: 'ibnuda/alicia_cook'
},
allison: {
target: 'prototypist/allison'
},
allison_numpad: {
target: 'prototypist/allison_numpad'
},
alu84: {
target: 'mechkeys/alu84'
},
angel17: {
target: 'kakunpc/angel17'
},
angel64/alpha: {
target: 'kakunpc/angel64/alpha'
},
angel64/rev1: {
target: 'kakunpc/angel64/rev1'
},
arch_36: {
target: 'obosob/arch_36'
},
bakeneko60: {
target: 'kkatano/bakeneko60'
},
bakeneko65/rev2: {
target: 'kkatano/bakeneko65/rev2'
},
bakeneko65/rev3: {
target: 'kkatano/bakeneko65/rev3'
},
bakeneko80: {
target: 'kkatano/bakeneko80'
},
barleycorn: {
target: 'yiancardesigns/barleycorn'
},
bat43/rev1: {
target: 'dailycraft/bat43/rev1'
},
bat43/rev2: {
target: 'dailycraft/bat43/rev2'
},
bigseries/1key: {
target: 'woodkeys/bigseries/1key'
},
bigseries/2key: {
target: 'woodkeys/bigseries/2key'
},
bigseries/3key: {
target: 'woodkeys/bigseries/3key'
},
bigseries/4key: {
target: 'woodkeys/bigseries/4key'
},
bkf: {
target: 'drhigsby/bkf'
},
business_card/alpha: {
target: 'kakunpc/business_card/alpha'
},
business_card/beta: {
target: 'kakunpc/business_card/beta'
},
butterstick: {
target: 'gboards/butterstick'
},
c39: {
target: 'maple_computing/c39'
},
cassette42: {
target: '25keys/cassette42'
},
chidori: {
target: 'kagizaraya/chidori'
},
chili: {
target: 'ydkb/chili'
},
chimera_ergo: {
target: 'glenpickle/chimera_ergo'
},
chimera_ls: {
target: 'glenpickle/chimera_ls'
},
chimera_ortho: {
target: 'glenpickle/chimera_ortho'
},
chimera_ortho_plus: {
target: 'glenpickle/chimera_ortho_plus'
},
choc_taro: {
target: 'kakunpc/choc_taro'
},
choco60: {
target: 'recompile_keys/choco60'
},
christmas_tree: {
target: 'maple_computing/christmas_tree'
},
claw44/rev1: {
target: 'dailycraft/claw44/rev1'
},
cocoa40: {
target: 'recompile_keys/cocoa40'
},
comet46: {
target: 'satt/comet46'
},
cu24: {
target: 'capsunlocked/cu24'
},
cu75: {
target: 'capsunlocked/cu75'
},
cu80: {
target: 'capsunlocked/cu80/v1'
},
delilah: {
target: 'rainkeebs/delilah'
},
diverge3: {
target: 'unikeyboard/diverge3'
},
divergetm2: {
target: 'unikeyboard/divergetm2'
},
dozen0: {
target: 'yynmt/dozen0'
},
dubba175: {
target: 'drhigsby/dubba175'
},
eggman: {
target: 'qpockets/eggman'
},
ergo42: {
target: 'biacco42/ergo42'
},
ergoarrows: {
target: 'salicylic_acid3/ergoarrows'
},
ergodash/mini: {
target: 'omkbd/ergodash/mini'
},
ergodash/rev1: {
target: 'omkbd/ergodash/rev1'
},
ergodox_infinity: {
target: 'input_club/ergodox_infinity'
},
ergotaco: {
target: 'gboards/ergotaco'
},
espectro: {
target: 'mechkeys/espectro'
},
felix: {
target: 'unikeyboard/felix'
},
four_banger: {
target: 'bpiphany/four_banger'
},
freyr: {
target: 'hnahkb/freyr'
},
geminate60: {
target: 'weirdo/geminate60'
},
georgi: {
target: 'gboards/georgi'
},
gergo: {
target: 'gboards/gergo'
},
getta25: {
target: 'salicylic_acid3/getta25'
},
gingham: {
target: 'yiancardesigns/gingham'
},
gurindam: {
target: 'ibnuda/gurindam'
},
halberd: {
target: 'kagizaraya/halberd'
},
hecomi/alpha: {
target: 'takashiski/hecomi/alpha'
},
hid_liber: {
target: 'bpiphany/hid_liber'
},
id67/default_rgb: {
target: 'idobao/id67/default_rgb'
},
id67/rgb: {
target: 'idobao/id67/rgb'
},
id80: {
target: 'idobao/id80/v1'
},
id87: {
target: 'idobao/id87/v1'
},
idobo: {
target: 'idobao/id75/v1'
},
infinity60: {
target: 'input_club/infinity60'
},
ivy/rev1: {
target: 'maple_computing/ivy/rev1'
},
jisplit89: {
target: 'salicylic_acid3/jisplit89'
},
jnao: {
target: 'maple_computing/jnao'
},
just60: {
target: 'ydkb/just60'
},
k_type: {
target: 'input_club/k_type'
},
kagamidget: {
target: 'yynmt/kagamidget'
},
kelowna/rgb64: {
target: 'weirdo/kelowna/rgb64'
},
kprepublic/bm65hsrgb_iso: {
target: 'kprepublic/bm65hsrgb_iso/rev1'
},
kprepublic/bm68hsrgb: {
target: 'kprepublic/bm68hsrgb/rev1'
},
latin17rgb: {
target: 'latincompass/latin17rgb'
},
latin47ble: {
target: 'latincompass/latin47ble'
},
latin60rgb: {
target: 'latincompass/latin60rgb'
},
latin64ble: {
target: 'latincompass/latin64ble'
},
latin6rgb: {
target: 'latincompass/latin6rgb'
},
latinpad: {
target: 'latincompass/latinpad'
},
latinpadble: {
target: 'latincompass/latinpadble'
},
launchpad/rev1: {
target: 'maple_computing/launchpad/rev1'
},
lck75: {
target: 'lyso1/lck75'
},
le_chiffre: {
target: 'tominabox1/le_chiffre'
},
lefishe: {
target: 'lyso1/lefishe'
},
lets_split_eh/eh: {
target: 'maple_computing/lets_split_eh/eh'
},
ls_60: {
target: 'weirdo/ls_60'
},
m3n3van: {
target: 'matthewdias/m3n3van'
},
mechmini/v1: {
target: 'mechkeys/mechmini/v1'
},
mechmini/v2: {
target: 'mechkeys/mechmini/v2'
},
meira: {
target: 'woodkeys/meira'
},
meishi: {
target: 'biacco42/meishi'
},
meishi2: {
target: 'biacco42/meishi2'
},
minidox/rev1: {
target: 'maple_computing/minidox/rev1'
},
minim: {
target: 'matthewdias/minim'
},
mio: {
target: 'recompile_keys/mio'
},
model_v: {
target: 'matthewdias/model_v'
},
montex: {
target: 'idobao/montex/v1'
},
nafuda: {
target: 'salicylic_acid3/nafuda'
},
naiping/np64: {
target: 'weirdo/naiping/np64'
},
naiping/nphhkb: {
target: 'weirdo/naiping/nphhkb'
},
naiping/npminila: {
target: 'weirdo/naiping/npminila'
},
naked48: {
target: 'salicylic_acid3/naked48'
},
naked60: {
target: 'salicylic_acid3/naked60'
},
naked64: {
target: 'salicylic_acid3/naked64'
},
namecard2x4: {
target: 'takashiski/namecard2x4'
},
nebula12: {
target: 'spaceholdings/nebula12'
},
nebula68: {
target: 'spaceholdings/nebula68'
},
nebula68b: {
target: 'spaceholdings/nebula68b'
},
niu_mini: {
target: 'kbdfans/niu_mini'
},
nk1: {
target: 'novelkeys/nk1'
},
nk65: {
target: 'novelkeys/nk65'
},
nk87: {
target: 'novelkeys/nk87'
},
nknl7en: {
target: 'salicylic_acid3/nknl7en'
},
nknl7jp: {
target: 'salicylic_acid3/nknl7jp'
},
nomu30: {
target: 'recompile_keys/nomu30'
},
novelpad: {
target: 'novelkeys/novelpad'
},
ogurec: {
target: 'drhigsby/ogurec'
},
otaku_split/rev0: {
target: 'takashiski/otaku_split/rev0'
},
otaku_split/rev1: {
target: 'takashiski/otaku_split/rev1'
},
owl8: {
target: 'dailycraft/owl8'
},
packrat: {
target: 'drhigsby/packrat'
},
pistachio: {
target: 'rate/pistachio'
},
pistachio_mp: {
target: 'rate/pistachio_mp'
},
pistachio_pro: {
target: 'rate/pistachio_pro'
},
plexus75: {
target: 'checkerboards/plexus75'
},
pursuit40: {
target: 'checkerboards/pursuit40'
},
qaz: {
target: 'tominabox1/qaz'
},
quark: {
target: 'checkerboards/quark'
},
rabbit_capture_plan: {
target: 'kakunpc/rabbit_capture_plan'
},
rainkeeb: {
target: 'rainkeebs/rainkeeb'
},
reviung33: {
target: 'reviung/reviung33'
},
reviung34: {
target: 'reviung/reviung34'
},
reviung39: {
target: 'reviung/reviung39'
},
reviung41: {
target: 'reviung/reviung41'
},
reviung5: {
target: 'reviung/reviung5'
},
reviung53: {
target: 'reviung/reviung53'
},
reviung61: {
target: 'reviung/reviung61'
},
runner3680/3x6: {
target: 'omkbd/runner3680/3x6'
},
runner3680/3x7: {
target: 'omkbd/runner3680/3x7'
},
runner3680/3x8: {
target: 'omkbd/runner3680/3x8'
},
runner3680/4x6: {
target: 'omkbd/runner3680/4x6'
},
runner3680/4x7: {
target: 'omkbd/runner3680/4x7'
},
runner3680/4x8: {
target: 'omkbd/runner3680/4x8'
},
runner3680/5x6: {
target: 'omkbd/runner3680/5x6'
},
runner3680/5x6_5x8: {
target: 'omkbd/runner3680/5x6_5x8'
},
runner3680/5x7: {
target: 'omkbd/runner3680/5x7'
},
runner3680/5x8: {
target: 'omkbd/runner3680/5x8'
},
scarletbandana: {
target: 'woodkeys/scarletbandana'
},
scythe: {
target: 'kagizaraya/scythe'
},
seigaiha: {
target: 'yiancardesigns/seigaiha'
},
setta21: {
target: 'salicylic_acid3/setta21'
},
space_space/rev1: {
target: 'qpockets/space_space/rev1'
},
space_space/rev2: {
target: 'qpockets/space_space/rev2'
},
spiderisland/winry25tc: {
target: 'winry/winry25tc'
},
splitreus62: {
target: 'nacly/splitreus62'
},
squiggle/rev1: {
target: 'ibnuda/squiggle/rev1'
},
standaside: {
target: 'edi/standaside'
},
steal_this_keyboard: {
target: 'obosob/steal_this_keyboard'
},
stella: {
target: 'hnahkb/stella'
},
suihankey/alpha: {
target: 'kakunpc/suihankey/alpha'
},
suihankey/rev1: {
target: 'kakunpc/suihankey/rev1'
},
suihankey/split: {
target: 'kakunpc/suihankey/split'
},
the_ruler: {
target: 'maple_computing/the_ruler'
},
thedogkeyboard: {
target: 'kakunpc/thedogkeyboard'
},
tiger910: {
target: 'weirdo/tiger910'
},
treadstone32: {
target: 'marksard/treadstone32'
},
treadstone48/rev1: {
target: 'marksard/treadstone48/rev1'
},
treadstone48/rev2: {
target: 'marksard/treadstone48/rev2'
},
txuu: {
target: 'matthewdias/txuu'
},
ua62: {
target: 'nacly/ua62'
},
underscore33/rev1: {
target: 'tominabox1/underscore33/rev1'
},
underscore33/rev2: {
target: 'tominabox1/underscore33/rev2'
},
vn66: {
target: 'hnahkb/vn66'
},
wallaby: {
target: 'kkatano/wallaby'
},
wanten: {
target: 'qpockets/wanten'
},
whitefox: {
target: 'input_club/whitefox'
},
wings42/rev1: {
target: 'dailycraft/wings42/rev1'
},
wings42/rev1_extkeys: {
target: 'dailycraft/wings42/rev1_extkeys'
},
wings42/rev2: {
target: 'dailycraft/wings42/rev2'
},
yasui: {
target: 'rainkeebs/yasui'
},
yd60mq: {
target: 'ymdk/yd60mq'
},
yd68: {
target: 'ydkb/yd68'
},
ymd75: {
target: 'ymdk/ymd75'
},
ymd96: {
target: 'ymdk/ymd96'
},
ymdk_np21: {
target: 'ymdk/np21'
},
yurei: {
target: 'kkatano/yurei'
},
zinc: {
target: '25keys/zinc'
},
zinc/rev1: {
target: '25keys/zinc/rev1'
},
zinc/reva: {
target: '25keys/zinc/reva'
} }
} }

View File

@@ -20,6 +20,10 @@
"type": "string", "type": "string",
"pattern": "^0x[0-9A-F]{4}$" "pattern": "^0x[0-9A-F]{4}$"
}, },
"bcd_version": {
"type": "string",
"pattern": "^[0-9]{1,2}\\.[0-9]\\.[0-9]$"
},
"text_identifier": { "text_identifier": {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
@@ -29,7 +33,33 @@
"oneOf": [ "oneOf": [
{ {
"type": "string", "type": "string",
"enum": ["LAYOUT", "LAYOUT_planck_1x2uC"] "enum": [
"LAYOUT",
"LAYOUT_1x2uC",
"LAYOUT_1x2uL",
"LAYOUT_1x2uR",
"LAYOUT_2x2uC",
"LAYOUT_2x3uC",
"LAYOUT_625uC",
"LAYOUT_ANSI_DEFAULT",
"LAYOUT_JP",
"LAYOUT_ortho_3x12_1x2uC",
"LAYOUT_ortho_4x12_1x2uC",
"LAYOUT_ortho_4x12_1x2uL",
"LAYOUT_ortho_4x12_1x2uR",
"LAYOUT_ortho_5x12_1x2uC",
"LAYOUT_ortho_5x12_2x2uC",
"LAYOUT_ortho_5x14_1x2uC",
"LAYOUT_ortho_5x14_1x2uL",
"LAYOUT_ortho_5x14_1x2uR",
"LAYOUT_planck_1x2uC",
"LAYOUT_planck_1x2uL",
"LAYOUT_planck_1x2uR",
"LAYOUT_preonic_1x2uC",
"LAYOUT_preonic_1x2uL",
"LAYOUT_preonic_1x2uR",
"LAYOUT_reviung34_2uL"
]
}, },
{ {
"type": "string", "type": "string",
@@ -47,6 +77,10 @@
}, },
"mcu_pin": { "mcu_pin": {
"oneOf": [ "oneOf": [
{
"type": "string",
"enum": ["NO_PIN"]
},
{ {
"type": "string", "type": "string",
"pattern": "^[A-K]\\d{1,2}$" "pattern": "^[A-K]\\d{1,2}$"
@@ -70,13 +104,13 @@
"signed_int": { "signed_int": {
"type": "number", "type": "number",
"multipleOf": 1 "multipleOf": 1
} },
"signed_int_8": { "signed_int_8": {
"type": "number", "type": "number",
"min": -127, "min": -127,
"max": 127, "max": 127,
"multipleOf": 1 "multipleOf": 1
} },
"string_array": { "string_array": {
"type": "array", "type": "array",
"items": { "items": {
@@ -97,7 +131,7 @@
"type": "number", "type": "number",
"min": 0, "min": 0,
"multipleOf": 1 "multipleOf": 1
} },
"unsigned_int_8": { "unsigned_int_8": {
"type": "number", "type": "number",
"min": 0, "min": 0,

View File

@@ -13,7 +13,7 @@
}, },
"processor": { "processor": {
"type": "string", "type": "string",
"enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66FX1M0", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L433", "STM32L443", "GD32VF103", "WB32F3G71", "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", "MK66FX1M0", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L432", "STM32L433", "STM32L442", "STM32L443", "GD32VF103", "WB32F3G71", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
}, },
"audio": { "audio": {
"type": "object", "type": "object",
@@ -45,7 +45,7 @@
"properties": { "properties": {
"driver": { "driver": {
"type": "string", "type": "string",
"enum": ["AdafruitBLE", "RN42"] "enum": ["BluefruitLE", "RN42"]
}, },
"lto": {"type": "boolean"}, "lto": {"type": "boolean"},
} }
@@ -57,7 +57,7 @@
}, },
"bootloader": { "bootloader": {
"type": "string", "type": "string",
"enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"], "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "custom", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "md-boot", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"],
}, },
"bootloader_instructions": { "bootloader_instructions": {
"type": "string", "type": "string",
@@ -69,7 +69,7 @@
"properties": { "properties": {
"debounce_type": { "debounce_type": {
"type": "string", "type": "string",
"enum": ["custom", "eager_pk", "eager_pr", "sym_defer_pk", "sym_eager_pk"] "enum": ["custom", "eager_pk", "eager_pr", "sym_defer_pk", "sym_defer_pr", "sym_eager_pk"]
}, },
"firmware_format": { "firmware_format": {
"type": "string", "type": "string",
@@ -109,6 +109,7 @@
}, },
"layouts": { "layouts": {
"type": "object", "type": "object",
"propertyNames": {"$ref": "qmk.definitions.v1#/layout_macro"},
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@@ -320,7 +321,8 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"device_ver": {"$ref": "qmk.definitions.v1#/hex_number_4d"}, "device_ver": {"$ref": "qmk.definitions.v1#/hex_number_4d"}, # Deprecated
"device_version": {"$ref": "qmk.definitions.v1#/bcd_version"},
"force_nkro": {"type": "boolean"}, "force_nkro": {"type": "boolean"},
"pid": {"$ref": "qmk.definitions.v1#/hex_number_4d"}, "pid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
"vid": {"$ref": "qmk.definitions.v1#/hex_number_4d"}, "vid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},

View File

@@ -53,5 +53,10 @@
"type": "string", "type": "string",
"description": "asdf" "description": "asdf"
} }
} },
"required": [
"keyboard",
"layout",
"layers"
]
} }

View File

@@ -1,138 +0,0 @@
// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "config_common.h"
/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0000
#define DEVICE_VER 0x0001
#define MANUFACTURER %(USER_NAME)s
#define PRODUCT %(KEYBOARD)s
/* key matrix size */
#define MATRIX_ROWS 2
#define MATRIX_COLS 3
/*
* Keyboard Matrix Assignments
*
* Change this to how you wired your keyboard
* COLS: AVR pins used for columns, left to right
* ROWS: AVR pins used for rows, top to bottom
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
*
*/
#define MATRIX_ROW_PINS { D0, D5 }
#define MATRIX_COL_PINS { F1, F0, B0 }
#define UNUSED_PINS
/* COL2ROW, ROW2COL */
#define DIODE_DIRECTION COL2ROW
/*
* Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN.
*/
#define SOFT_SERIAL_PIN D0 // or D1, D2, D3, E6
//#define LED_NUM_LOCK_PIN B0
//#define LED_CAPS_LOCK_PIN B1
//#define LED_SCROLL_LOCK_PIN B2
//#define LED_COMPOSE_PIN B3
//#define LED_KANA_PIN B4
//#define BACKLIGHT_PIN B7
//#define BACKLIGHT_LEVELS 3
//#define BACKLIGHT_BREATHING
//#define RGB_DI_PIN E2
//#ifdef RGB_DI_PIN
//# define RGBLED_NUM 16
//# define RGBLIGHT_HUE_STEP 8
//# define RGBLIGHT_SAT_STEP 8
//# define RGBLIGHT_VAL_STEP 8
//# define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */
//# define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */
/*== all animations enable ==*/
//# define RGBLIGHT_ANIMATIONS
/*== or choose animations ==*/
//# define RGBLIGHT_EFFECT_BREATHING
//# define RGBLIGHT_EFFECT_RAINBOW_MOOD
//# define RGBLIGHT_EFFECT_RAINBOW_SWIRL
//# define RGBLIGHT_EFFECT_SNAKE
//# define RGBLIGHT_EFFECT_KNIGHT
//# define RGBLIGHT_EFFECT_CHRISTMAS
//# define RGBLIGHT_EFFECT_STATIC_GRADIENT
//# define RGBLIGHT_EFFECT_RGB_TEST
//# define RGBLIGHT_EFFECT_ALTERNATING
/*== customize breathing effect ==*/
/*==== (DEFAULT) use fixed table instead of exp() and sin() ====*/
//# define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256(default) or 128 or 64
/*==== use exp() and sin() ====*/
//# define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85 // 1 to 2.7
//# define RGBLIGHT_EFFECT_BREATHE_MAX 255 // 0 to 255
//#endif
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/* If defined, GRAVE_ESC will always act as ESC when CTRL is held.
* This is useful for the Windows task manager shortcut (ctrl+shift+esc).
*/
//#define GRAVE_ESC_CTRL_OVERRIDE
/*
* Force NKRO
*
* Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
* state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
* makefile for this to work.)
*
* If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
* until the next keyboard reset.
*
* NKRO may prevent your keystrokes from being detected in the BIOS, but it is
* fully operational during normal computer usage.
*
* For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
* or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
* bootmagic, NKRO mode will always be enabled until it is toggled again during a
* power-up.
*
*/
//#define FORCE_NKRO
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
/* disable these deprecated features by default */
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
/* Bootmagic Lite key configuration */
//#define BOOTMAGIC_LITE_ROW 0
//#define BOOTMAGIC_LITE_COLUMN 0

View File

@@ -1,18 +0,0 @@
# MCU name
MCU = atmega32u4
# Bootloader selection
BOOTLOADER = atmel-dfu
# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = no # Enable N-Key Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output

View File

@@ -1,4 +0,0 @@
// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "%(KEYBOARD)s.h"

View File

@@ -1,22 +0,0 @@
// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "quantum.h"
/* This is a shortcut to help you visually see your layout.
*
* The first section contains all of the arguments representing the physical
* layout of the board and position of the keys.
*
* The second converts the arguments into a two-dimensional array which
* represents the switch matrix.
*/
#define LAYOUT( \
k00, k01, k02, \
k10, k12 \
) { \
{ k00, k01, k02 }, \
{ k10, KC_NO, k12 } \
}

View File

@@ -1,17 +0,0 @@
{
"keyboard_name": "%(KEYBOARD)s",
"url": "",
"maintainer": "%(USER_NAME)s",
"layouts": {
"LAYOUT": {
"layout": [
{"label": "k00", "x": 0, "y": 0},
{"label": "k01", "x": 1, "y": 0},
{"label": "k02", "x": 2, "y": 0},
{"label": "k10", "x": 0, "y": 1, "w": 1.5},
{"label": "k12", "x": 1.5, "y": 1, "w": 1.5}
]
}
}
}

View File

@@ -1,22 +0,0 @@
// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
// Defines names for use in layer keycodes and the keymap
enum layer_names {
_BASE,
_FN
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Base */
[_BASE] = LAYOUT(
KC_A, KC_1, MO(_FN),
KC_TAB, KC_SPC
),
[_FN] = LAYOUT(
_______, _______, _______,
RESET, XXXXXXX
)
};

View File

@@ -1 +0,0 @@
# The default keymap for %(KEYBOARD)s

View File

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

View File

@@ -0,0 +1,25 @@
{
"keyboard_name": "%KEYBOARD%",
"maintainer": "%USER_NAME%",
"manufacturer": "%REAL_NAME%",
"processor": "%MCU%",
"bootloader": "%BOOTLOADER%",
"diode_direction": "COL2ROW",
"matrix_pins": {
"cols": ["C2"],
"rows": ["D1"]
},
"usb": {
"vid": "0xFEED",
"pid": "0x0000",
"device_version": "1.0.0"
},
"features": {
"bootmagic": true,
"command": false,
"console": false,
"extrakey": true,
"mousekey": true,
"nkro": true
}
}

View File

@@ -1,20 +1,20 @@
# %(KEYBOARD)s # %KEYBOARD%
![%(KEYBOARD)s](imgur.com image replace me!) ![%KEYBOARD%](imgur.com image replace me!)
*A short description of the keyboard/project* *A short description of the keyboard/project*
* Keyboard Maintainer: [%(YOUR_NAME)s](https://github.com/%(USER_NAME)s) * Keyboard Maintainer: [%REAL_NAME%](https://github.com/%USER_NAME%)
* Hardware Supported: *The PCBs, controllers supported* * Hardware Supported: *The PCBs, controllers supported*
* Hardware Availability: *Links to where you can find this hardware* * Hardware Availability: *Links to where you can find this hardware*
Make example for this keyboard (after setting up your build environment): Make example for this keyboard (after setting up your build environment):
make %(KEYBOARD)s:default make %KEYBOARD%:default
Flashing example for this keyboard: Flashing example for this keyboard:
make %(KEYBOARD)s: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).

View File

@@ -0,0 +1 @@
# This file intentionally left blank

View File

@@ -1,128 +0,0 @@
// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "config_common.h"
/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0000
#define DEVICE_VER 0x0001
#define MANUFACTURER %(USER_NAME)s
#define PRODUCT %(KEYBOARD)s
/* key matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 15
/*
* Keyboard Matrix Assignments
*
* Change this to how you wired your keyboard
* COLS: AVR pins used for columns, left to right
* ROWS: AVR pins used for rows, top to bottom
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
*
*/
#define MATRIX_ROW_PINS { B0, B1, B2, B3, B4, B5, B6, B7 }
#define MATRIX_COL_PINS { A0, A1, A2, A3, A4, A5, A6, A7, C7, C6, C5, C4, C3, C2, D7 }
#define UNUSED_PINS
/* COL2ROW, ROW2COL */
#define DIODE_DIRECTION COL2ROW
//#define LED_NUM_LOCK_PIN D0
//#define LED_CAPS_LOCK_PIN D1
//#define LED_SCROLL_LOCK_PIN D6
#define BACKLIGHT_PIN D4
//#define BACKLIGHT_LEVELS 3
//#define BACKLIGHT_BREATHING
#define RGBLED_NUM 16
//#define RGBLIGHT_HUE_STEP 8
//#define RGBLIGHT_SAT_STEP 8
//#define RGBLIGHT_VAL_STEP 8
//#define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */
//#define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */
/*== all animations enable ==*/
//#define RGBLIGHT_ANIMATIONS
/*== or choose animations ==*/
//#define RGBLIGHT_EFFECT_BREATHING
//#define RGBLIGHT_EFFECT_RAINBOW_MOOD
//#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
//#define RGBLIGHT_EFFECT_SNAKE
//#define RGBLIGHT_EFFECT_KNIGHT
//#define RGBLIGHT_EFFECT_CHRISTMAS
//#define RGBLIGHT_EFFECT_STATIC_GRADIENT
//#define RGBLIGHT_EFFECT_RGB_TEST
//#define RGBLIGHT_EFFECT_ALTERNATING
/*== customize breathing effect ==*/
/*==== (DEFAULT) use fixed table instead of exp() and sin() ====*/
//#define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256(default) or 128 or 64
/*==== use exp() and sin() ====*/
//#define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85 // 1 to 2.7
//#define RGBLIGHT_EFFECT_BREATHE_MAX 255 // 0 to 255
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/* If defined, GRAVE_ESC will always act as ESC when CTRL is held.
* This is useful for the Windows task manager shortcut (ctrl+shift+esc).
*/
//#define GRAVE_ESC_CTRL_OVERRIDE
/*
* Force NKRO
*
* Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
* state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
* makefile for this to work.)
*
* If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
* until the next keyboard reset.
*
* NKRO may prevent your keystrokes from being detected in the BIOS, but it is
* fully operational during normal computer usage.
*
* For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
* or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
* bootmagic, NKRO mode will always be enabled until it is toggled again during a
* power-up.
*
*/
//#define FORCE_NKRO
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
/* disable these deprecated features by default */
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
/* Bootmagic Lite key configuration */
//#define BOOTMAGIC_LITE_ROW 0
//#define BOOTMAGIC_LITE_COLUMN 0

View File

@@ -1,28 +0,0 @@
# %(KEYBOARD)s
![%(KEYBOARD)s](imgur.com image replace me!)
*A short description of the keyboard/project*
* Keyboard Maintainer: [%(YOUR_NAME)s](https://github.com/yourusername)
* Hardware Supported: *The PCBs, controllers supported*
* Hardware Availability: *Links to where you can find this hardware*
Make example for this keyboard (after setting up your build environment):
make %(KEYBOARD)s:default
Flashing example for this keyboard ([after setting up the bootloadHID flashing environment](https://docs.qmk.fm/#/flashing_bootloadhid))
make %(KEYBOARD)s: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).
## 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

@@ -1,17 +0,0 @@
# MCU name
MCU = atmega32a
# Bootloader selection
BOOTLOADER = bootloadhid
# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
WS2812_DRIVER = i2c

View File

@@ -1,4 +1,4 @@
#include "adafruit_ble.h" #include "bluefruit_le.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -16,20 +16,20 @@
// These are the pin assignments for the 32u4 boards. // These are the pin assignments for the 32u4 boards.
// You may define them to something else in your config.h // You may define them to something else in your config.h
// if yours is wired up differently. // if yours is wired up differently.
#ifndef ADAFRUIT_BLE_RST_PIN #ifndef BLUEFRUIT_LE_RST_PIN
# define ADAFRUIT_BLE_RST_PIN D4 # define BLUEFRUIT_LE_RST_PIN D4
#endif #endif
#ifndef ADAFRUIT_BLE_CS_PIN #ifndef BLUEFRUIT_LE_CS_PIN
# define ADAFRUIT_BLE_CS_PIN B4 # define BLUEFRUIT_LE_CS_PIN B4
#endif #endif
#ifndef ADAFRUIT_BLE_IRQ_PIN #ifndef BLUEFRUIT_LE_IRQ_PIN
# define ADAFRUIT_BLE_IRQ_PIN E6 # define BLUEFRUIT_LE_IRQ_PIN E6
#endif #endif
#ifndef ADAFRUIT_BLE_SCK_DIVISOR #ifndef BLUEFRUIT_LE_SCK_DIVISOR
# define ADAFRUIT_BLE_SCK_DIVISOR 2 // 4MHz SCK/8MHz CPU, calculated for Feather 32U4 BLE # define BLUEFRUIT_LE_SCK_DIVISOR 2 // 4MHz SCK/8MHz CPU, calculated for Feather 32U4 BLE
#endif #endif
#define SAMPLE_BATTERY #define SAMPLE_BATTERY
@@ -77,10 +77,10 @@ struct sdep_msg {
// information here. // information here.
enum queue_type { enum queue_type {
QTKeyReport, // 1-byte modifier + 6-byte key report QTKeyReport, // 1-byte modifier + 6-byte key report
QTConsumer, // 16-bit key code QTConsumer, // 16-bit key code
#ifdef MOUSE_ENABLE #ifdef MOUSE_ENABLE
QTMouseMove, // 4-byte mouse report QTMouseMove, // 4-byte mouse report
#endif #endif
}; };
@@ -115,8 +115,8 @@ enum sdep_type {
SdepResponse = 0x20, SdepResponse = 0x20,
SdepAlert = 0x40, SdepAlert = 0x40,
SdepError = 0x80, SdepError = 0x80,
SdepSlaveNotReady = 0xFE, // Try again later SdepSlaveNotReady = 0xFE, // Try again later
SdepSlaveOverflow = 0xFF, // You read more data than is available SdepSlaveOverflow = 0xFF, // You read more data than is available
}; };
enum ble_cmd { enum ble_cmd {
@@ -143,7 +143,7 @@ static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool ver
// Send a single SDEP packet // Send a single SDEP packet
static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) { static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) {
spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR); spi_start(BLUEFRUIT_LE_CS_PIN, false, 0, BLUEFRUIT_LE_SCK_DIVISOR);
uint16_t timerStart = timer_read(); uint16_t timerStart = timer_read();
bool success = false; bool success = false;
bool ready = false; bool ready = false;
@@ -157,7 +157,7 @@ static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) {
// Release it and let it initialize // Release it and let it initialize
spi_stop(); spi_stop();
wait_us(SdepBackOff); wait_us(SdepBackOff);
spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR); spi_start(BLUEFRUIT_LE_CS_PIN, false, 0, BLUEFRUIT_LE_SCK_DIVISOR);
} while (timer_elapsed(timerStart) < timeout); } while (timer_elapsed(timerStart) < timeout);
if (ready) { if (ready) {
@@ -190,7 +190,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
bool ready = false; bool ready = false;
do { do {
ready = readPin(ADAFRUIT_BLE_IRQ_PIN); ready = readPin(BLUEFRUIT_LE_IRQ_PIN);
if (ready) { if (ready) {
break; break;
} }
@@ -198,7 +198,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
} while (timer_elapsed(timerStart) < timeout); } while (timer_elapsed(timerStart) < timeout);
if (ready) { if (ready) {
spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR); spi_start(BLUEFRUIT_LE_CS_PIN, false, 0, BLUEFRUIT_LE_SCK_DIVISOR);
do { do {
// Read the command type, waiting for the data to be ready // Read the command type, waiting for the data to be ready
@@ -207,7 +207,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
// Release it and let it initialize // Release it and let it initialize
spi_stop(); spi_stop();
wait_us(SdepBackOff); wait_us(SdepBackOff);
spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR); spi_start(BLUEFRUIT_LE_CS_PIN, false, 0, BLUEFRUIT_LE_SCK_DIVISOR);
continue; continue;
} }
@@ -233,7 +233,7 @@ static void resp_buf_read_one(bool greedy) {
return; return;
} }
if (readPin(ADAFRUIT_BLE_IRQ_PIN)) { if (readPin(BLUEFRUIT_LE_IRQ_PIN)) {
struct sdep_msg msg; struct sdep_msg msg;
again: again:
@@ -244,7 +244,7 @@ static void resp_buf_read_one(bool greedy) {
dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send)); dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send));
} }
if (greedy && resp_buf.peek(last_send) && readPin(ADAFRUIT_BLE_IRQ_PIN)) { if (greedy && resp_buf.peek(last_send) && readPin(BLUEFRUIT_LE_IRQ_PIN)) {
goto again; goto again;
} }
} }
@@ -295,24 +295,26 @@ static bool ble_init(void) {
state.configured = false; state.configured = false;
state.is_connected = false; state.is_connected = false;
setPinInput(ADAFRUIT_BLE_IRQ_PIN); setPinInput(BLUEFRUIT_LE_IRQ_PIN);
spi_init(); spi_init();
// Perform a hardware reset // Perform a hardware reset
setPinOutput(ADAFRUIT_BLE_RST_PIN); setPinOutput(BLUEFRUIT_LE_RST_PIN);
writePinHigh(ADAFRUIT_BLE_RST_PIN); writePinHigh(BLUEFRUIT_LE_RST_PIN);
writePinLow(ADAFRUIT_BLE_RST_PIN); writePinLow(BLUEFRUIT_LE_RST_PIN);
wait_ms(10); wait_ms(10);
writePinHigh(ADAFRUIT_BLE_RST_PIN); writePinHigh(BLUEFRUIT_LE_RST_PIN);
wait_ms(1000); // Give it a second to initialize wait_ms(1000); // Give it a second to initialize
state.initialized = true; state.initialized = true;
return state.initialized; return state.initialized;
} }
static inline uint8_t min(uint8_t a, uint8_t b) { return a < b ? a : b; } static inline uint8_t min(uint8_t a, uint8_t b) {
return a < b ? a : b;
}
static bool read_response(char *resp, uint16_t resplen, bool verbose) { static bool read_response(char *resp, uint16_t resplen, bool verbose) {
char *dest = resp; char *dest = resp;
@@ -424,9 +426,11 @@ bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose) {
return at_command(cmdbuf, resp, resplen, verbose); return at_command(cmdbuf, resp, resplen, verbose);
} }
bool adafruit_ble_is_connected(void) { return state.is_connected; } bool bluefruit_le_is_connected(void) {
return state.is_connected;
}
bool adafruit_ble_enable_keyboard(void) { bool bluefruit_le_enable_keyboard(void) {
char resbuf[128]; char resbuf[128];
if (!state.initialized && !ble_init()) { if (!state.initialized && !ble_init()) {
@@ -498,16 +502,16 @@ static void set_connected(bool connected) {
} }
} }
void adafruit_ble_task(void) { void bluefruit_le_task(void) {
char resbuf[48]; char resbuf[48];
if (!state.configured && !adafruit_ble_enable_keyboard()) { if (!state.configured && !bluefruit_le_enable_keyboard()) {
return; return;
} }
resp_buf_read_one(true); resp_buf_read_one(true);
send_buf_send_one(SdepShortTimeout); send_buf_send_one(SdepShortTimeout);
if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(ADAFRUIT_BLE_IRQ_PIN)) { if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(BLUEFRUIT_LE_IRQ_PIN)) {
// Must be an event update // Must be an event update
if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) { if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) {
uint32_t mask = strtoul(resbuf, NULL, 16); uint32_t mask = strtoul(resbuf, NULL, 16);
@@ -609,7 +613,7 @@ static bool process_queue_item(struct queue_item *item, uint16_t timeout) {
} }
} }
void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) { void bluefruit_le_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) {
struct queue_item item; struct queue_item item;
bool didWait = false; bool didWait = false;
@@ -643,7 +647,7 @@ void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nk
} }
} }
void adafruit_ble_send_consumer_key(uint16_t usage) { void bluefruit_le_send_consumer_key(uint16_t usage) {
struct queue_item item; struct queue_item item;
item.queue_type = QTConsumer; item.queue_type = QTConsumer;
@@ -655,7 +659,7 @@ void adafruit_ble_send_consumer_key(uint16_t usage) {
} }
#ifdef MOUSE_ENABLE #ifdef MOUSE_ENABLE
void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) { void bluefruit_le_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) {
struct queue_item item; struct queue_item item;
item.queue_type = QTMouseMove; item.queue_type = QTMouseMove;
@@ -671,9 +675,11 @@ void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan,
} }
#endif #endif
uint32_t adafruit_ble_read_battery_voltage(void) { return state.vbat; } uint32_t bluefruit_le_read_battery_voltage(void) {
return state.vbat;
}
bool adafruit_ble_set_mode_leds(bool on) { bool bluefruit_le_set_mode_leds(bool on) {
if (!state.configured) { if (!state.configured) {
return false; return false;
} }
@@ -689,7 +695,7 @@ bool adafruit_ble_set_mode_leds(bool on) {
} }
// https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel // https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel
bool adafruit_ble_set_power_level(int8_t level) { bool bluefruit_le_set_power_level(int8_t level) {
char cmd[46]; char cmd[46];
if (!state.configured) { if (!state.configured) {
return false; return false;

View File

@@ -16,43 +16,43 @@ extern "C" {
#endif #endif
/* Instruct the module to enable HID keyboard support and reset */ /* Instruct the module to enable HID keyboard support and reset */
extern bool adafruit_ble_enable_keyboard(void); extern bool bluefruit_le_enable_keyboard(void);
/* Query to see if the BLE module is connected */ /* Query to see if the BLE module is connected */
extern bool adafruit_ble_query_is_connected(void); extern bool bluefruit_le_query_is_connected(void);
/* Returns true if we believe that the BLE module is connected. /* Returns true if we believe that the BLE module is connected.
* This uses our cached understanding that is maintained by * This uses our cached understanding that is maintained by
* calling ble_task() periodically. */ * calling ble_task() periodically. */
extern bool adafruit_ble_is_connected(void); extern bool bluefruit_le_is_connected(void);
/* Call this periodically to process BLE-originated things */ /* Call this periodically to process BLE-originated things */
extern void adafruit_ble_task(void); extern void bluefruit_le_task(void);
/* Generates keypress events for a set of keys. /* Generates keypress events for a set of keys.
* The hid modifier mask specifies the state of the modifier keys for * The hid modifier mask specifies the state of the modifier keys for
* this set of keys. * this set of keys.
* Also sends a key release indicator, so that the keys do not remain * Also sends a key release indicator, so that the keys do not remain
* held down. */ * held down. */
extern void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys); extern void bluefruit_le_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys);
/* Send a consumer usage. /* Send a consumer usage.
* (milliseconds) */ * (milliseconds) */
extern void adafruit_ble_send_consumer_key(uint16_t usage); extern void bluefruit_le_send_consumer_key(uint16_t usage);
#ifdef MOUSE_ENABLE #ifdef MOUSE_ENABLE
/* Send a mouse/wheel movement report. /* Send a mouse/wheel movement report.
* The parameters are signed and indicate positive or negative direction * The parameters are signed and indicate positive or negative direction
* change. */ * change. */
extern void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons); extern void bluefruit_le_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons);
#endif #endif
/* Compute battery voltage by reading an analog pin. /* Compute battery voltage by reading an analog pin.
* Returns the integer number of millivolts */ * Returns the integer number of millivolts */
extern uint32_t adafruit_ble_read_battery_voltage(void); extern uint32_t bluefruit_le_read_battery_voltage(void);
extern bool adafruit_ble_set_mode_leds(bool on); extern bool bluefruit_le_set_mode_leds(bool on);
extern bool adafruit_ble_set_power_level(int8_t level); extern bool bluefruit_le_set_power_level(int8_t level);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -13,13 +13,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "outputselect.h" #include "outputselect.h"
#include "usb_util.h"
#if defined(PROTOCOL_LUFA) #ifdef BLUETOOTH_BLUEFRUIT_LE
# include "lufa.h" # include "bluefruit_le.h"
#endif
#ifdef MODULE_ADAFRUIT_BLE
# include "adafruit_ble.h"
#endif #endif
uint8_t desired_output = OUTPUT_DEFAULT; uint8_t desired_output = OUTPUT_DEFAULT;
@@ -39,29 +36,23 @@ void set_output(uint8_t output) {
*/ */
__attribute__((weak)) void set_output_user(uint8_t output) {} __attribute__((weak)) void set_output_user(uint8_t output) {}
static bool is_usb_configured(void) {
#if defined(PROTOCOL_LUFA)
return USB_DeviceState == DEVICE_STATE_Configured;
#endif
}
/** \brief Auto Detect Output /** \brief Auto Detect Output
* *
* FIXME: Needs doc * FIXME: Needs doc
*/ */
uint8_t auto_detect_output(void) { uint8_t auto_detect_output(void) {
if (is_usb_configured()) { if (usb_connected_state()) {
return OUTPUT_USB; return OUTPUT_USB;
} }
#ifdef MODULE_ADAFRUIT_BLE #ifdef BLUETOOTH_BLUEFRUIT_LE
if (adafruit_ble_is_connected()) { if (bluefruit_le_is_connected()) {
return OUTPUT_BLUETOOTH; return OUTPUT_BLUETOOTH;
} }
#endif #endif
#ifdef BLUETOOTH_ENABLE #ifdef BLUETOOTH_ENABLE
return OUTPUT_BLUETOOTH; // should check if BT is connected here return OUTPUT_BLUETOOTH; // should check if BT is connected here
#endif #endif
return OUTPUT_NONE; return OUTPUT_NONE;

101
drivers/bluetooth/rn42.c Normal file
View File

@@ -0,0 +1,101 @@
/* 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 "report.h"
#include "uart.h"
#ifndef RN42_BAUD_RATE
# define RN42_BAUD_RATE 115200
#endif
// https://cdn.sparkfun.com/datasheets/Wireless/Bluetooth/bluetooth_cr_UG-v1.0r.pdf#G7.663734
static inline uint16_t rn42_consumer_usage_to_bitmap(uint16_t usage) {
switch (usage) {
case AC_HOME:
return 0x0001;
case AL_EMAIL:
return 0x0002;
case AC_SEARCH:
return 0x0004;
case AL_KEYBOARD_LAYOUT:
return 0x0008;
case AUDIO_VOL_UP:
return 0x0010;
case AUDIO_VOL_DOWN:
return 0x0020;
case AUDIO_MUTE:
return 0x0040;
case TRANSPORT_PLAY_PAUSE:
return 0x0080;
case TRANSPORT_NEXT_TRACK:
return 0x0100;
case TRANSPORT_PREV_TRACK:
return 0x0200;
case TRANSPORT_STOP:
return 0x0400;
case TRANSPORT_EJECT:
return 0x0800;
case TRANSPORT_FAST_FORWARD:
return 0x1000;
case TRANSPORT_REWIND:
return 0x2000;
case TRANSPORT_STOP_EJECT:
return 0x4000;
case AL_LOCAL_BROWSER:
return 0x8000;
default:
return 0;
}
}
void rn42_init(void) {
uart_init(RN42_BAUD_RATE);
}
void rn42_send_keyboard(report_keyboard_t *report) {
uart_write(0xFD);
uart_write(0x09);
uart_write(0x01);
uart_write(report->mods);
uart_write(0x00);
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
uart_write(report->keys[i]);
}
}
void rn42_send_mouse(report_mouse_t *report) {
uart_write(0xFD);
uart_write(0x00);
uart_write(0x03);
uart_write(report->buttons);
uart_write(report->x);
uart_write(report->y);
uart_write(report->v); // should try sending the wheel v here
uart_write(report->h); // should try sending the wheel h here
uart_write(0x00);
}
void rn42_send_consumer(uint16_t data) {
static uint16_t last_data = 0;
if (data == last_data) return;
last_data = data;
uint16_t bitmap = rn42_consumer_usage_to_bitmap(data);
uart_write(0xFD);
uart_write(0x03);
uart_write(0x03);
uart_write(bitmap & 0xFF);
uart_write((bitmap >> 8) & 0xFF);
}

View File

@@ -1,4 +1,4 @@
/* Copyright 2018-2020 Nick Brassel (@tzarc) /* Copyright 2021
* *
* 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
@@ -14,10 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* Address for jumping to bootloader on STM32 chips. */ #include "report.h"
/* It is chip dependent, the correct number can be looked up here (page 175):
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf void rn42_init(void);
* This also requires a patch to chibios:
* <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch void rn42_send_keyboard(report_keyboard_t *report);
*/
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 void rn42_send_mouse(report_mouse_t *report);
void rn42_send_consumer(uint16_t data);

View File

@@ -37,11 +37,17 @@ uint32_t eeprom_read_dword(const uint32_t *addr) {
return ret; return ret;
} }
void eeprom_write_byte(uint8_t *addr, uint8_t value) { eeprom_write_block(&value, addr, 1); } void eeprom_write_byte(uint8_t *addr, uint8_t value) {
eeprom_write_block(&value, addr, 1);
}
void eeprom_write_word(uint16_t *addr, uint16_t value) { eeprom_write_block(&value, addr, 2); } void eeprom_write_word(uint16_t *addr, uint16_t value) {
eeprom_write_block(&value, addr, 2);
}
void eeprom_write_dword(uint32_t *addr, uint32_t value) { eeprom_write_block(&value, addr, 4); } void eeprom_write_dword(uint32_t *addr, uint32_t value) {
eeprom_write_block(&value, addr, 4);
}
void eeprom_update_block(const void *buf, void *addr, size_t len) { void eeprom_update_block(const void *buf, void *addr, size_t len) {
uint8_t read_buf[len]; uint8_t read_buf[len];

View File

@@ -43,7 +43,7 @@
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
# include "timer.h" # include "timer.h"
# include "debug.h" # include "debug.h"
#endif // DEBUG_EEPROM_OUTPUT #endif // DEBUG_EEPROM_OUTPUT
static inline void fill_target_address(uint8_t *buffer, const void *addr) { static inline void fill_target_address(uint8_t *buffer, const void *addr) {
uintptr_t p = (uintptr_t)addr; uintptr_t p = (uintptr_t)addr;
@@ -91,7 +91,7 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
dprintf(" %02X", (int)(((uint8_t *)buf)[i])); dprintf(" %02X", (int)(((uint8_t *)buf)[i]));
} }
dprintf("\n"); dprintf("\n");
#endif // DEBUG_EEPROM_OUTPUT #endif // DEBUG_EEPROM_OUTPUT
} }
void eeprom_write_block(const void *buf, void *addr, size_t len) { void eeprom_write_block(const void *buf, void *addr, size_t len) {
@@ -122,7 +122,7 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
dprintf(" %02X", (int)(read_buf[i])); dprintf(" %02X", (int)(read_buf[i]));
} }
dprintf("\n"); dprintf("\n");
#endif // DEBUG_EEPROM_OUTPUT #endif // DEBUG_EEPROM_OUTPUT
i2c_transmit(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), complete_packet, EXTERNAL_EEPROM_ADDRESS_SIZE + write_length, 100); i2c_transmit(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), complete_packet, EXTERNAL_EEPROM_ADDRESS_SIZE + write_length, 100);
wait_ms(EXTERNAL_EEPROM_WRITE_TIME); wait_ms(EXTERNAL_EEPROM_WRITE_TIME);

View File

@@ -52,7 +52,9 @@
# define EXTERNAL_EEPROM_SPI_TIMEOUT 100 # define EXTERNAL_EEPROM_SPI_TIMEOUT 100
#endif #endif
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) {
uint32_t deadline = timer_read32() + timeout; uint32_t deadline = timer_read32() + timeout;
@@ -80,7 +82,9 @@ static void spi_eeprom_transmit_address(uintptr_t addr) {
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void eeprom_driver_init(void) { spi_init(); } void eeprom_driver_init(void) {
spi_init();
}
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)
@@ -135,7 +139,7 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
dprintf(" %02X", (int)(((uint8_t *)buf)[i])); dprintf(" %02X", (int)(((uint8_t *)buf)[i]));
} }
dprintf("\n"); dprintf("\n");
#endif // DEBUG_EEPROM_OUTPUT #endif // DEBUG_EEPROM_OUTPUT
spi_stop(); spi_stop();
} }
@@ -192,7 +196,7 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
dprintf(" %02X", (int)(uint8_t)(read_buf[i])); dprintf(" %02X", (int)(uint8_t)(read_buf[i]));
} }
dprintf("\n"); dprintf("\n");
#endif // DEBUG_EEPROM_OUTPUT #endif // DEBUG_EEPROM_OUTPUT
spi_write(CMD_WRITE); spi_write(CMD_WRITE);
spi_eeprom_transmit_address(target_addr); spi_eeprom_transmit_address(target_addr);

View File

@@ -30,9 +30,13 @@ size_t clamp_length(intptr_t offset, size_t len) {
return len; return len;
} }
void eeprom_driver_init(void) { eeprom_driver_erase(); } void eeprom_driver_init(void) {
eeprom_driver_erase();
}
void eeprom_driver_erase(void) { memset(transientBuffer, 0x00, TRANSIENT_EEPROM_SIZE); } void eeprom_driver_erase(void) {
memset(transientBuffer, 0x00, TRANSIENT_EEPROM_SIZE);
}
void eeprom_read_block(void *buf, const void *addr, size_t len) { void eeprom_read_block(void *buf, const void *addr, size_t len) {
intptr_t offset = (intptr_t)addr; intptr_t offset = (intptr_t)addr;

View File

@@ -21,5 +21,5 @@
*/ */
#ifndef TRANSIENT_EEPROM_SIZE #ifndef TRANSIENT_EEPROM_SIZE
# include "eeconfig.h" # include "eeconfig.h"
# define TRANSIENT_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO # define TRANSIENT_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
#endif #endif

376
drivers/flash/flash_spi.c Normal file
View File

@@ -0,0 +1,376 @@
/*
Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "util.h"
#include "wait.h"
#include "debug.h"
#include "timer.h"
#include "flash_spi.h"
#include "spi_master.h"
/*
The time-out time of spi flash transmission.
*/
#ifndef EXTERNAL_FLASH_SPI_TIMEOUT
# define EXTERNAL_FLASH_SPI_TIMEOUT 1000
#endif
/* ID comands */
#define FLASH_CMD_RDID 0x9F /* RDID (Read Identification) */
#define FLASH_CMD_RES 0xAB /* RES (Read Electronic ID) */
#define FLASH_CMD_REMS 0x90 /* REMS (Read Electronic & Device ID) */
/* register comands */
#define FLASH_CMD_WRSR 0x01 /* WRSR (Write Status register) */
#define FLASH_CMD_RDSR 0x05 /* RDSR (Read Status register) */
/* READ comands */
#define FLASH_CMD_READ 0x03 /* READ (1 x I/O) */
#define FLASH_CMD_FASTREAD 0x0B /* FAST READ (Fast read data) */
#define FLASH_CMD_DREAD 0x3B /* DREAD (1In/2 Out fast read) */
/* Program comands */
#define FLASH_CMD_WREN 0x06 /* WREN (Write Enable) */
#define FLASH_CMD_WRDI 0x04 /* WRDI (Write Disable) */
#define FLASH_CMD_PP 0x02 /* PP (page program) */
/* Erase comands */
#define FLASH_CMD_SE 0x20 /* SE (Sector Erase) */
#define FLASH_CMD_BE 0xD8 /* BE (Block Erase) */
#define FLASH_CMD_CE 0x60 /* CE (Chip Erase) hex code: 60 or C7 */
/* Mode setting comands */
#define FLASH_CMD_DP 0xB9 /* DP (Deep Power Down) */
#define FLASH_CMD_RDP 0xAB /* RDP (Release form Deep Power Down) */
/* Status register */
#define FLASH_FLAG_WIP 0x01 /* Write in progress bit */
#define FLASH_FLAG_WEL 0x02 /* Write enable latch bit */
// #define DEBUG_FLASH_SPI_OUTPUT
static bool spi_flash_start(void) {
return spi_start(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN, EXTERNAL_FLASH_SPI_LSBFIRST, EXTERNAL_FLASH_SPI_MODE, EXTERNAL_FLASH_SPI_CLOCK_DIVISOR);
}
static flash_status_t spi_flash_wait_while_busy(void) {
uint32_t deadline = timer_read32() + EXTERNAL_FLASH_SPI_TIMEOUT;
flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t retval;
do {
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash wait while busy]\n");
return FLASH_STATUS_ERROR;
}
spi_write(FLASH_CMD_RDSR);
retval = (uint8_t)spi_read();
spi_stop();
if (timer_read32() >= deadline) {
response = FLASH_STATUS_TIMEOUT;
break;
}
} while (retval & FLASH_FLAG_WIP);
return response;
}
static flash_status_t spi_flash_write_enable(void) {
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash write enable]\n");
return FLASH_STATUS_ERROR;
}
spi_write(FLASH_CMD_WREN);
spi_stop();
return FLASH_STATUS_SUCCESS;
}
static flash_status_t spi_flash_write_disable(void) {
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash write disable]\n");
return FLASH_STATUS_ERROR;
}
spi_write(FLASH_CMD_WRDI);
spi_stop();
return FLASH_STATUS_SUCCESS;
}
/* This function is used for read transfer, write transfer and erase transfer. */
static flash_status_t spi_flash_transaction(uint8_t cmd, uint32_t addr, uint8_t *data, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t buffer[EXTERNAL_FLASH_ADDRESS_SIZE + 1];
buffer[0] = cmd;
for (int i = 0; i < EXTERNAL_FLASH_ADDRESS_SIZE; ++i) {
buffer[EXTERNAL_FLASH_ADDRESS_SIZE - i] = addr & 0xFF;
addr >>= 8;
}
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash transmit]\n");
return FLASH_STATUS_ERROR;
}
response = spi_transmit(buffer, sizeof(buffer));
if ((!response) && (data != NULL)) {
switch (cmd) {
case FLASH_CMD_READ:
response = spi_receive(data, len);
break;
case FLASH_CMD_PP:
response = spi_transmit(data, len);
break;
default:
response = FLASH_STATUS_ERROR;
break;
}
}
spi_stop();
return response;
}
void flash_init(void) {
spi_init();
}
flash_status_t flash_erase_chip(void) {
flash_status_t response = FLASH_STATUS_SUCCESS;
/* Wait for the write-in-progress bit to be cleared. */
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase chip]\n");
return response;
}
/* Enable writes. */
response = spi_flash_write_enable();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to write-enable! [spi flash erase chip]\n");
return response;
}
/* Erase Chip. */
bool res = spi_flash_start();
if (!res) {
dprint("Failed to start SPI! [spi flash erase chip]\n");
return FLASH_STATUS_ERROR;
}
spi_write(FLASH_CMD_CE);
spi_stop();
/* Wait for the write-in-progress bit to be cleared.*/
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase chip]\n");
return response;
}
return response;
}
flash_status_t flash_erase_sector(uint32_t addr) {
flash_status_t response = FLASH_STATUS_SUCCESS;
/* Check that the address exceeds the limit. */
if ((addr + (EXTERNAL_FLASH_SECTOR_SIZE)) >= (EXTERNAL_FLASH_SIZE) || ((addr % (EXTERNAL_FLASH_SECTOR_SIZE)) != 0)) {
dprintf("Flash erase sector address over limit! [addr:0x%x]\n", (uint32_t)addr);
return FLASH_STATUS_ERROR;
}
/* Wait for the write-in-progress bit to be cleared. */
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase sector]\n");
return response;
}
/* Enable writes. */
response = spi_flash_write_enable();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to write-enable! [spi flash erase sector]\n");
return response;
}
/* Erase Sector. */
response = spi_flash_transaction(FLASH_CMD_SE, addr, NULL, 0);
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to erase sector! [spi flash erase sector]\n");
return response;
}
/* Wait for the write-in-progress bit to be cleared.*/
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase sector]\n");
return response;
}
return response;
}
flash_status_t flash_erase_block(uint32_t addr) {
flash_status_t response = FLASH_STATUS_SUCCESS;
/* Check that the address exceeds the limit. */
if ((addr + (EXTERNAL_FLASH_BLOCK_SIZE)) >= (EXTERNAL_FLASH_SIZE) || ((addr % (EXTERNAL_FLASH_BLOCK_SIZE)) != 0)) {
dprintf("Flash erase block address over limit! [addr:0x%x]\n", (uint32_t)addr);
return FLASH_STATUS_ERROR;
}
/* Wait for the write-in-progress bit to be cleared. */
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase block]\n");
return response;
}
/* Enable writes. */
response = spi_flash_write_enable();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to write-enable! [spi flash erase block]\n");
return response;
}
/* Erase Block. */
response = spi_flash_transaction(FLASH_CMD_BE, addr, NULL, 0);
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to erase block! [spi flash erase block]\n");
return response;
}
/* Wait for the write-in-progress bit to be cleared.*/
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase block]\n");
return response;
}
return response;
}
flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t * read_buf = (uint8_t *)buf;
/* Wait for the write-in-progress bit to be cleared. */
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash read block]\n");
memset(read_buf, 0, len);
return response;
}
/* Perform read. */
response = spi_flash_transaction(FLASH_CMD_READ, addr, read_buf, len);
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to read block! [spi flash read block]\n");
memset(read_buf, 0, len);
return response;
}
#if defined(CONSOLE_ENABLE) && defined(DEBUG_FLASH_SPI_OUTPUT)
dprintf("[SPI FLASH R] 0x%08lX: ", addr);
for (size_t i = 0; i < len; ++i) {
dprintf(" %02X", (int)(((uint8_t *)read_buf)[i]));
}
dprintf("\n");
#endif // DEBUG_FLASH_SPI_OUTPUT
return response;
}
flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t * write_buf = (uint8_t *)buf;
while (len > 0) {
uint32_t page_offset = addr % EXTERNAL_FLASH_PAGE_SIZE;
size_t write_length = EXTERNAL_FLASH_PAGE_SIZE - page_offset;
if (write_length > len) {
write_length = len;
}
/* Wait for the write-in-progress bit to be cleared. */
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash write block]\n");
return response;
}
/* Enable writes. */
response = spi_flash_write_enable();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to write-enable! [spi flash write block]\n");
return response;
}
#if defined(CONSOLE_ENABLE) && defined(DEBUG_FLASH_SPI_OUTPUT)
dprintf("[SPI FLASH W] 0x%08lX: ", addr);
for (size_t i = 0; i < write_length; i++) {
dprintf(" %02X", (int)(uint8_t)(write_buf[i]));
}
dprintf("\n");
#endif // DEBUG_FLASH_SPI_OUTPUT
/* Perform the write. */
response = spi_flash_transaction(FLASH_CMD_PP, addr, write_buf, write_length);
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to write block! [spi flash write block]\n");
return response;
}
write_buf += write_length;
addr += write_length;
len -= write_length;
}
/* Wait for the write-in-progress bit to be cleared. */
response = spi_flash_wait_while_busy();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash write block]\n");
return response;
}
/* Disable writes. */
response = spi_flash_write_disable();
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to write-disable! [spi flash write block]\n");
return response;
}
return response;
}

136
drivers/flash/flash_spi.h Normal file
View File

@@ -0,0 +1,136 @@
/*
Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
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
/* All the following default configurations are based on MX25L4006E Nor FLASH. */
/*
The slave select pin of the FLASH.
This needs to be a normal GPIO pin_t value, such as B14.
*/
#ifndef EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN
# error "No chip select pin defined -- missing EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN"
#endif
/*
The clock divisor for SPI to ensure that the MCU is within the
specifications of the FLASH chip. Generally this will be PCLK divided by
the intended divisor -- check your clock settings and the datasheet of
your FLASH.
*/
#ifndef EXTERNAL_FLASH_SPI_CLOCK_DIVISOR
# ifdef __AVR__
# define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR 4
# else
# define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR 8
# endif
#endif
/*
The SPI mode to communicate with the FLASH.
*/
#ifndef EXTERNAL_FLASH_SPI_MODE
# define EXTERNAL_FLASH_SPI_MODE 0
#endif
/*
Whether or not the SPI communication between the MCU and FLASH should be
LSB-first.
*/
#ifndef EXTERNAL_FLASH_SPI_LSBFIRST
# define EXTERNAL_FLASH_SPI_LSBFIRST false
#endif
/*
The Flash address size in bytes, as specified in datasheet.
*/
#ifndef EXTERNAL_FLASH_ADDRESS_SIZE
# define EXTERNAL_FLASH_ADDRESS_SIZE 3
#endif
/*
The page size of the FLASH in bytes, as specified in the datasheet.
*/
#ifndef EXTERNAL_FLASH_PAGE_SIZE
# define EXTERNAL_FLASH_PAGE_SIZE 256
#endif
/*
The sector size of the FLASH in bytes, as specified in the datasheet.
*/
#ifndef EXTERNAL_FLASH_SECTOR_SIZE
# define EXTERNAL_FLASH_SECTOR_SIZE (4 * 1024)
#endif
/*
The block size of the FLASH in bytes, as specified in the datasheet.
*/
#ifndef EXTERNAL_FLASH_BLOCK_SIZE
# define EXTERNAL_FLASH_BLOCK_SIZE (64 * 1024)
#endif
/*
The total size of the FLASH in bytes, as specified in the datasheet.
*/
#ifndef EXTERNAL_FLASH_SIZE
# define EXTERNAL_FLASH_SIZE (512 * 1024)
#endif
/*
The block count of the FLASH, calculated by total FLASH size and block size.
*/
#define EXTERNAL_FLASH_BLOCK_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_BLOCK_SIZE))
/*
The sector count of the FLASH, calculated by total FLASH size and sector size.
*/
#define EXTERNAL_FLASH_SECTOR_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_SECTOR_SIZE))
/*
The page count of the FLASH, calculated by total FLASH size and page size.
*/
#define EXTERNAL_FLASH_PAGE_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_PAGE_SIZE))
typedef int16_t flash_status_t;
#define FLASH_STATUS_SUCCESS (0)
#define FLASH_STATUS_ERROR (-1)
#define FLASH_STATUS_TIMEOUT (-2)
#define FLASH_STATUS_BAD_ADDRESS (-3)
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void flash_init(void);
flash_status_t flash_erase_chip(void);
flash_status_t flash_erase_block(uint32_t addr);
flash_status_t flash_erase_sector(uint32_t addr);
flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len);
flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len);
#ifdef __cplusplus
}
#endif

108
drivers/gpio/mcp23018.c Normal file
View File

@@ -0,0 +1,108 @@
// Copyright 2022 zvecr<git@zvecr.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "mcp23018.h"
#include "i2c_master.h"
#include "wait.h"
#include "debug.h"
#define SLAVE_TO_ADDR(n) (n << 1)
#define TIMEOUT 100
enum {
CMD_IODIRA = 0x00, // i/o direction register
CMD_IODIRB = 0x01,
CMD_GPPUA = 0x0C, // GPIO pull-up resistor register
CMD_GPPUB = 0x0D,
CMD_GPIOA = 0x12, // general purpose i/o port register (write modifies OLAT)
CMD_GPIOB = 0x13,
};
void mcp23018_init(uint8_t addr) {
static uint8_t s_init = 0;
if (!s_init) {
i2c_init();
wait_ms(1000);
s_init = 1;
}
}
bool mcp23018_set_config(uint8_t slave_addr, mcp23018_port_t port, uint8_t conf) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t cmdDirection = port ? CMD_IODIRB : CMD_IODIRA;
uint8_t cmdPullup = port ? CMD_GPPUB : CMD_GPPUA;
i2c_status_t ret = i2c_writeReg(addr, cmdDirection, &conf, sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("mcp23018_set_config::directionFAILED::%u\n", ret);
return false;
}
ret = i2c_writeReg(addr, cmdPullup, &conf, sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("mcp23018_set_config::pullupFAILED::%u\n", ret);
return false;
}
return true;
}
bool mcp23018_set_output(uint8_t slave_addr, mcp23018_port_t port, uint8_t conf) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t cmd = port ? CMD_GPIOB : CMD_GPIOA;
i2c_status_t ret = i2c_writeReg(addr, cmd, &conf, sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("mcp23018_set_output::FAILED::%u\n", ret);
return false;
}
return true;
}
bool mcp23018_set_output_all(uint8_t slave_addr, uint8_t confA, uint8_t confB) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t conf[2] = {confA, confB};
i2c_status_t ret = i2c_writeReg(addr, CMD_GPIOA, &conf[0], sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("mcp23018_set_output::FAILED::%u\n", ret);
return false;
}
return true;
}
bool mcp23018_readPins(uint8_t slave_addr, mcp23018_port_t port, uint8_t* out) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t cmd = port ? CMD_GPIOB : CMD_GPIOA;
i2c_status_t ret = i2c_readReg(addr, cmd, out, sizeof(uint8_t), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("mcp23018_readPins::FAILED::%u\n", ret);
return false;
}
return true;
}
bool mcp23018_readPins_all(uint8_t slave_addr, uint16_t* out) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr);
typedef union {
uint8_t u8[2];
uint16_t u16;
} data16;
data16 data = {.u16 = 0};
i2c_status_t ret = i2c_readReg(addr, CMD_GPIOA, &data.u8[0], sizeof(data), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("mcp23018_readPins::FAILED::%u\n", ret);
return false;
}
*out = data.u16;
return true;
}

65
drivers/gpio/mcp23018.h Normal file
View File

@@ -0,0 +1,65 @@
// Copyright 2022 zvecr<git@zvecr.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stdint.h>
#include <stdbool.h>
/**
* Port ID
*/
typedef enum {
mcp23018_PORTA,
mcp23018_PORTB,
} mcp23018_port_t;
/**
* Helpers for set_config
*/
enum {
ALL_OUTPUT = 0,
ALL_INPUT = 0xFF,
};
/**
* Helpers for set_output
*/
enum {
ALL_LOW = 0,
ALL_HIGH = 0xFF,
};
/**
* Init expander and any other dependent drivers
*/
void mcp23018_init(uint8_t slave_addr);
/**
* Configure input/output to a given port
*/
bool mcp23018_set_config(uint8_t slave_addr, mcp23018_port_t port, uint8_t conf);
/**
* Write high/low to a given port
*/
bool mcp23018_set_output(uint8_t slave_addr, mcp23018_port_t port, uint8_t conf);
/**
* Write high/low to both ports sequentially
*
* - slightly faster than multiple set_output
*/
bool mcp23018_set_output_all(uint8_t slave_addr, uint8_t confA, uint8_t confB);
/**
* Read state of a given port
*/
bool mcp23018_readPins(uint8_t slave_addr, mcp23018_port_t port, uint8_t* ret);
/**
* Read state of both ports sequentially
*
* - slightly faster than multiple readPins
*/
bool mcp23018_readPins_all(uint8_t slave_addr, uint16_t* ret);

View File

@@ -1,18 +1,6 @@
/* Copyright 2019 // Copyright 2020 zvecr<git@zvecr.com>
* // SPDX-License-Identifier: GPL-2.0-or-later
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "i2c_master.h" #include "i2c_master.h"
#include "pca9555.h" #include "pca9555.h"
@@ -45,39 +33,59 @@ void pca9555_init(uint8_t slave_addr) {
// i2c_stop(); // i2c_stop();
} }
void pca9555_set_config(uint8_t slave_addr, uint8_t port, uint8_t conf) { bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr); uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t cmd = port ? CMD_CONFIG_1 : CMD_CONFIG_0; uint8_t cmd = port ? CMD_CONFIG_1 : CMD_CONFIG_0;
i2c_status_t ret = i2c_writeReg(addr, cmd, &conf, sizeof(conf), TIMEOUT); i2c_status_t ret = i2c_writeReg(addr, cmd, &conf, sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) { if (ret != I2C_STATUS_SUCCESS) {
print("pca9555_set_config::FAILED\n"); print("pca9555_set_config::FAILED\n");
return false;
} }
return true;
} }
void pca9555_set_output(uint8_t slave_addr, uint8_t port, uint8_t conf) { bool pca9555_set_output(uint8_t slave_addr, pca9555_port_t port, uint8_t conf) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr); uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t cmd = port ? CMD_OUTPUT_1 : CMD_OUTPUT_0; uint8_t cmd = port ? CMD_OUTPUT_1 : CMD_OUTPUT_0;
i2c_status_t ret = i2c_writeReg(addr, cmd, &conf, sizeof(conf), TIMEOUT); i2c_status_t ret = i2c_writeReg(addr, cmd, &conf, sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) { if (ret != I2C_STATUS_SUCCESS) {
print("pca9555_set_output::FAILED\n"); print("pca9555_set_output::FAILED\n");
return false;
} }
return true;
} }
uint8_t pca9555_readPins(uint8_t slave_addr, uint8_t port) { bool pca9555_set_output_all(uint8_t slave_addr, uint8_t confA, uint8_t confB) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t conf[2] = {confA, confB};
i2c_status_t ret = i2c_writeReg(addr, CMD_OUTPUT_0, &conf[0], sizeof(conf), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) {
dprintf("pca9555_set_output::FAILED::%u\n", ret);
return false;
}
return true;
}
bool pca9555_readPins(uint8_t slave_addr, pca9555_port_t port, uint8_t* out) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr); uint8_t addr = SLAVE_TO_ADDR(slave_addr);
uint8_t cmd = port ? CMD_INPUT_1 : CMD_INPUT_0; uint8_t cmd = port ? CMD_INPUT_1 : CMD_INPUT_0;
uint8_t data = 0; i2c_status_t ret = i2c_readReg(addr, cmd, out, sizeof(uint8_t), TIMEOUT);
i2c_status_t ret = i2c_readReg(addr, cmd, &data, sizeof(data), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) { if (ret != I2C_STATUS_SUCCESS) {
print("pca9555_readPins::FAILED\n"); print("pca9555_readPins::FAILED\n");
return false;
} }
return data;
return true;
} }
uint16_t pca9555_readAllPins(uint8_t slave_addr) { bool pca9555_readPins_all(uint8_t slave_addr, uint16_t* out) {
uint8_t addr = SLAVE_TO_ADDR(slave_addr); uint8_t addr = SLAVE_TO_ADDR(slave_addr);
typedef union { typedef union {
@@ -85,11 +93,14 @@ uint16_t pca9555_readAllPins(uint8_t slave_addr) {
uint16_t u16; uint16_t u16;
} data16; } data16;
data16 data; data16 data = {.u16 = 0};
i2c_status_t ret = i2c_readReg(addr, CMD_INPUT_0, &data.u8[0], sizeof(data), TIMEOUT); i2c_status_t ret = i2c_readReg(addr, CMD_INPUT_0, &data.u8[0], sizeof(data), TIMEOUT);
if (ret != I2C_STATUS_SUCCESS) { if (ret != I2C_STATUS_SUCCESS) {
print("pca9555_readAllPins::FAILED\n"); print("pca9555_readPins_all::FAILED\n");
return false;
} }
return data.u16;
*out = data.u16;
return true;
} }

View File

@@ -1,20 +1,11 @@
/* Copyright 2019 // Copyright 2020 zvecr<git@zvecr.com>
* // SPDX-License-Identifier: GPL-2.0-or-later
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <stdint.h>
#include <stdbool.h>
/* /*
PCA9555 PCA9555
,----------. ,----------.
@@ -38,20 +29,60 @@
`----------' `----------'
*/ */
#define PCA9555_PORT0 0 /**
#define PCA9555_PORT1 1 * Port ID
*/
typedef enum {
PCA9555_PORT0,
PCA9555_PORT1,
} pca9555_port_t;
#define ALL_OUTPUT 0 /**
#define ALL_INPUT 0xFF * Helpers for set_config
#define ALL_LOW 0 */
#define ALL_HIGH 0xFF enum {
ALL_OUTPUT = 0,
ALL_INPUT = 0xFF,
};
/**
* Helpers for set_output
*/
enum {
ALL_LOW = 0,
ALL_HIGH = 0xFF,
};
/**
* Init expander and any other dependent drivers
*/
void pca9555_init(uint8_t slave_addr); void pca9555_init(uint8_t slave_addr);
void pca9555_set_config(uint8_t slave_addr, uint8_t port, uint8_t conf); /**
* Configure input/output to a given port
*/
bool pca9555_set_config(uint8_t slave_addr, pca9555_port_t port, uint8_t conf);
void pca9555_set_output(uint8_t slave_addr, uint8_t port, uint8_t conf); /**
* Write high/low to a given port
*/
bool pca9555_set_output(uint8_t slave_addr, pca9555_port_t port, uint8_t conf);
uint8_t pca9555_readPins(uint8_t slave_addr, uint8_t port); /**
* Write high/low to both ports sequentially
*
* - slightly faster than multiple set_output
*/
bool pca9555_set_output_all(uint8_t slave_addr, uint8_t confA, uint8_t confB);
uint16_t pca9555_readAllPins(uint8_t slave_addr); /**
* Read state of a given port
*/
bool pca9555_readPins(uint8_t slave_addr, pca9555_port_t port, uint8_t* ret);
/**
* Read state of both ports sequentially
*
* - slightly faster than multiple readPins
*/
bool pca9555_readPins_all(uint8_t slave_addr, uint16_t* ret);

65
drivers/gpio/sn74x138.c Normal file
View File

@@ -0,0 +1,65 @@
/* Copyright 2022
*
* 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 "sn74x138.h"
#include "gpio.h"
#define ADDRESS_PIN_COUNT 3
#ifndef SN74X138_ADDRESS_PINS
# error sn74x138: no address pins defined!
#endif
static const pin_t address_pins[ADDRESS_PIN_COUNT] = SN74X138_ADDRESS_PINS;
void sn74x138_init(void) {
for (int i = 0; i < ADDRESS_PIN_COUNT; i++) {
setPinOutput(address_pins[i]);
writePinLow(address_pins[i]);
}
#if defined(SN74X138_E1_PIN)
setPinOutput(SN74X138_E1_PIN);
writePinHigh(SN74X138_E1_PIN);
#endif
#if defined(SN74X138_E2_PIN)
setPinOutput(SN74X138_E2_PIN);
writePinHigh(SN74X138_E2_PIN);
#endif
#if defined(SN74X138_E3_PIN)
setPinOutput(SN74X138_E3_PIN);
writePinLow(SN74X138_E3_PIN);
#endif
}
void sn74x138_set_enabled(bool enabled) {
#if defined(SN74X138_E1_PIN)
writePin(SN74X138_E1_PIN, !enabled);
#endif
#if defined(SN74X138_E2_PIN)
writePin(SN74X138_E2_PIN, !enabled);
#endif
#if defined(SN74X138_E3_PIN)
writePin(SN74X138_E3_PIN, enabled);
#endif
}
void sn74x138_set_addr(uint8_t address) {
for (int i = 0; i < ADDRESS_PIN_COUNT; i++) {
writePin(address_pins[i], address & (1 << i));
}
}

48
drivers/gpio/sn74x138.h Normal file
View File

@@ -0,0 +1,48 @@
/* Copyright 2022
*
* 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>
/**
* Driver for 74x138 3-to-8 decoder/demultiplexer with inverting outputs
* https://assets.nexperia.com/documents/data-sheet/74HC_HCT138.pdf
*/
/**
* Initialize the address and output enable pins.
*/
void sn74x138_init(void);
/**
* Set the enabled state.
*
* When enabled is true, pulls the E1 and E2 pins low, and the E3 pin high.
*
* \param enabled The enable state to set.
*/
void sn74x138_set_enabled(bool enabled);
/**
* Set the output pin address.
*
* The selected output pin will be pulled low, while the remaining output pins will be high.
*
* \param address The address to set, from 0 to 7.
*/
void sn74x138_set_addr(uint8_t address);

View File

@@ -106,12 +106,14 @@ void DRV_init(void) {
void DRV_rtp_init(void) { void DRV_rtp_init(void) {
DRV_write(DRV_GO, 0x00); DRV_write(DRV_GO, 0x00);
DRV_write(DRV_RTP_INPUT, 20); // 20 is the lowest value I've found where haptics can still be felt. DRV_write(DRV_RTP_INPUT, 20); // 20 is the lowest value I've found where haptics can still be felt.
DRV_write(DRV_MODE, 0x05); DRV_write(DRV_MODE, 0x05);
DRV_write(DRV_GO, 0x01); DRV_write(DRV_GO, 0x01);
} }
void DRV_amplitude(uint8_t amplitude) { DRV_write(DRV_RTP_INPUT, amplitude); } void DRV_amplitude(uint8_t amplitude) {
DRV_write(DRV_RTP_INPUT, amplitude);
}
void DRV_pulse(uint8_t sequence) { void DRV_pulse(uint8_t sequence) {
DRV_write(DRV_GO, 0x00); DRV_write(DRV_GO, 0x00);

View File

@@ -28,13 +28,21 @@ uint8_t solenoid_dwell = SOLENOID_DEFAULT_DWELL;
extern haptic_config_t haptic_config; extern haptic_config_t haptic_config;
void solenoid_buzz_on(void) { haptic_set_buzz(1); } void solenoid_buzz_on(void) {
haptic_set_buzz(1);
}
void solenoid_buzz_off(void) { haptic_set_buzz(0); } void solenoid_buzz_off(void) {
haptic_set_buzz(0);
}
void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); } void solenoid_set_buzz(int buzz) {
haptic_set_buzz(buzz);
}
void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; } void solenoid_set_dwell(uint8_t dwell) {
solenoid_dwell = dwell;
}
void solenoid_stop(void) { void solenoid_stop(void) {
SOLENOID_PIN_WRITE_INACTIVE(); SOLENOID_PIN_WRITE_INACTIVE();
@@ -89,4 +97,6 @@ void solenoid_setup(void) {
} }
} }
void solenoid_shutdown(void) { SOLENOID_PIN_WRITE_INACTIVE(); } void solenoid_shutdown(void) {
SOLENOID_PIN_WRITE_INACTIVE();
}

View File

@@ -39,7 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Addressing Setting Commands // Addressing Setting Commands
#define PAM_SETCOLUMN_LSB 0x00 #define PAM_SETCOLUMN_LSB 0x00
#define PAM_SETCOLUMN_MSB 0x10 #define PAM_SETCOLUMN_MSB 0x10
#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 #define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
// Hardware Configuration Commands // Hardware Configuration Commands
#define DISPLAY_START_LINE 0x40 #define DISPLAY_START_LINE 0x40
@@ -138,7 +138,9 @@ bool st7565_init(display_rotation_t rotation) {
return true; return true;
} }
__attribute__((weak)) display_rotation_t st7565_init_user(display_rotation_t rotation) { return rotation; } __attribute__((weak)) display_rotation_t st7565_init_user(display_rotation_t rotation) {
return rotation;
}
void st7565_clear(void) { void st7565_clear(void) {
memset(st7565_buffer, 0, sizeof(st7565_buffer)); memset(st7565_buffer, 0, sizeof(st7565_buffer));
@@ -212,7 +214,8 @@ void st7565_advance_page(bool clearPageRemainder) {
remaining = remaining / ST7565_FONT_WIDTH; remaining = remaining / ST7565_FONT_WIDTH;
// Write empty character until next line // Write empty character until next line
while (remaining--) st7565_write_char(' ', false); while (remaining--)
st7565_write_char(' ', false);
} else { } else {
// Next page index out of bounds? // Next page index out of bounds?
if (index + remaining >= ST7565_MATRIX_SIZE) { if (index + remaining >= ST7565_MATRIX_SIZE) {
@@ -263,7 +266,7 @@ void st7565_write_char(const char data, bool invert) {
_Static_assert(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array"); _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 // set the reder buffer data
uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index 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) { if (cast_data < ST7565_FONT_START || cast_data > ST7565_FONT_END) {
memset(st7565_cursor, 0x00, ST7565_FONT_WIDTH); memset(st7565_cursor, 0x00, ST7565_FONT_WIDTH);
} else { } else {
@@ -389,7 +392,7 @@ void st7565_write_raw_P(const char *data, uint16_t size) {
st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE)); st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
} }
} }
#endif // defined(__AVR__) #endif // defined(__AVR__)
bool st7565_on(void) { bool st7565_on(void) {
if (!st7565_initialized) { if (!st7565_initialized) {
@@ -429,7 +432,9 @@ bool st7565_off(void) {
__attribute__((weak)) void st7565_off_user(void) {} __attribute__((weak)) void st7565_off_user(void) {}
bool st7565_is_on(void) { return st7565_active; } bool st7565_is_on(void) {
return st7565_active;
}
bool st7565_invert(bool invert) { bool st7565_invert(bool invert) {
if (!st7565_initialized) { if (!st7565_initialized) {
@@ -445,9 +450,13 @@ bool st7565_invert(bool invert) {
return st7565_inverted; return st7565_inverted;
} }
uint8_t st7565_max_chars(void) { return ST7565_DISPLAY_WIDTH / ST7565_FONT_WIDTH; } 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; } uint8_t st7565_max_lines(void) {
return ST7565_DISPLAY_HEIGHT / ST7565_FONT_HEIGHT;
}
void st7565_task(void) { void st7565_task(void) {
if (!st7565_initialized) { if (!st7565_initialized) {

View File

@@ -29,16 +29,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define ST7565_DISPLAY_HEIGHT 32 # define ST7565_DISPLAY_HEIGHT 32
#endif #endif
#ifndef ST7565_MATRIX_SIZE #ifndef ST7565_MATRIX_SIZE
# define ST7565_MATRIX_SIZE (ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH) // 1024 (compile time mathed) # define ST7565_MATRIX_SIZE (ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH) // 1024 (compile time mathed)
#endif #endif
#ifndef ST7565_BLOCK_TYPE #ifndef ST7565_BLOCK_TYPE
# define ST7565_BLOCK_TYPE uint16_t # define ST7565_BLOCK_TYPE uint16_t
#endif #endif
#ifndef ST7565_BLOCK_COUNT #ifndef ST7565_BLOCK_COUNT
# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) // 32 (compile time mathed) # define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) // 32 (compile time mathed)
#endif #endif
#ifndef ST7565_BLOCK_SIZE #ifndef ST7565_BLOCK_SIZE
# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) // 32 (compile time mathed) # define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) // 32 (compile time mathed)
#endif #endif
// the column address corresponding to the first column in the display hardware // the column address corresponding to the first column in the display hardware
@@ -174,7 +174,7 @@ void st7565_write_raw_P(const char *data, uint16_t size);
# define st7565_write_P(data, invert) st7565_write(data, invert) # 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_ln_P(data, invert) st7565_write_ln(data, invert)
# define st7565_write_raw_P(data, size) st7565_write_raw(data, size) # define st7565_write_raw_P(data, size) st7565_write_raw(data, size)
#endif // defined(__AVR__) #endif // defined(__AVR__)
// Can be used to manually turn on the screen if it is off // Can be used to manually turn on the screen if it is off
// Returns true if the screen was on or turns on // Returns true if the screen was on or turns on

View File

@@ -20,15 +20,15 @@
#ifndef APA102_NOPS #ifndef APA102_NOPS
# if defined(__AVR__) # if defined(__AVR__)
# define APA102_NOPS 0 // AVR at 16 MHz already spends 62.5 ns per clock, so no extra delay is needed # define APA102_NOPS 0 // AVR at 16 MHz already spends 62.5 ns per clock, so no extra delay is needed
# elif defined(PROTOCOL_CHIBIOS) # elif defined(PROTOCOL_CHIBIOS)
# include "hal.h" # include "hal.h"
# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(GD32VF103) # if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(GD32VF103)
# define APA102_NOPS (100 / (1000000000L / (CPU_CLOCK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns # define APA102_NOPS (100 / (1000000000L / (CPU_CLOCK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns
# else # else
# error("APA102_NOPS configuration required") # error("APA102_NOPS configuration required")
# define APA102_NOPS 0 // this just pleases the compile so the above error is easier to spot # define APA102_NOPS 0 // this just pleases the compile so the above error is easier to spot
# endif # endif
# endif # endif
#endif #endif
@@ -72,7 +72,9 @@ void apa102_setleds(LED_TYPE *start_led, uint16_t num_leds) {
} }
// Overwrite the default rgblight_call_driver to use apa102 driver // Overwrite the default rgblight_call_driver to use apa102 driver
void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { apa102_setleds(start_led, num_leds); } void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) {
apa102_setleds(start_led, num_leds);
}
void static apa102_init(void) { void static apa102_init(void) {
setPinOutput(RGB_DI_PIN); setPinOutput(RGB_DI_PIN);

View File

@@ -23,17 +23,17 @@
*/ */
#define AWINIC_ID 0b1010 << 4 #define AWINIC_ID 0b1010 << 4
#define AW_PAGE_FUNCTION 0x00 << 1 // PG0, Function registers #define AW_PAGE_FUNCTION 0x00 << 1 // PG0, Function registers
#define AW_PAGE_PWM 0x01 << 1 // PG1, LED PWM control #define AW_PAGE_PWM 0x01 << 1 // PG1, LED PWM control
#define AW_PAGE_SCALING 0x02 << 1 // PG2, LED current scaling control #define AW_PAGE_SCALING 0x02 << 1 // PG2, LED current scaling control
#define AW_PAGE_PATCHOICE 0x03 << 1 // PG3, Pattern choice? #define AW_PAGE_PATCHOICE 0x03 << 1 // PG3, Pattern choice?
#define AW_PAGE_PWMSCALING 0x04 << 1 // PG4, LED PWM + Scaling control? #define AW_PAGE_PWMSCALING 0x04 << 1 // PG4, LED PWM + Scaling control?
#define AW_WRITE 0 #define AW_WRITE 0
#define AW_READ 1 #define AW_READ 1
#define AW_REG_CONFIGURATION 0x00 // PG0 #define AW_REG_CONFIGURATION 0x00 // PG0
#define AW_REG_GLOBALCURRENT 0x01 // PG0 #define AW_REG_GLOBALCURRENT 0x01 // PG0
// Default value of AW_REG_CONFIGURATION // Default value of AW_REG_CONFIGURATION
// D7:D4 = 1011, SWSEL (SW1~SW12 active) // D7:D4 = 1011, SWSEL (SW1~SW12 active)

View File

@@ -125,7 +125,16 @@ void CKLED2001_init(uint8_t addr) {
// Set CURRENT PAGE (Page 4) // Set CURRENT PAGE (Page 4)
CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, CURRENT_TUNE_PAGE); CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, CURRENT_TUNE_PAGE);
for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) { for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) {
CKLED2001_write_register(addr, i, 0xFF); switch (i) {
case 2:
case 5:
case 8:
case 11:
CKLED2001_write_register(addr, i, 0xA0);
break;
default:
CKLED2001_write_register(addr, i, 0xFF);
}
} }
// Enable LEDs ON/OFF // Enable LEDs ON/OFF

View File

@@ -42,13 +42,13 @@
#define ISSI_REG_PICTUREFRAME 0x01 #define ISSI_REG_PICTUREFRAME 0x01
// Not defined in the datasheet -- See AN for IC // Not defined in the datasheet -- See AN for IC
#define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting #define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting
#define ISSI_REG_SHUTDOWN 0x0A #define ISSI_REG_SHUTDOWN 0x0A
#define ISSI_REG_AUDIOSYNC 0x06 #define ISSI_REG_AUDIOSYNC 0x06
#define ISSI_COMMANDREGISTER 0xFD #define ISSI_COMMANDREGISTER 0xFD
#define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine' #define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine'
#ifndef ISSI_TIMEOUT #ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100 # define ISSI_TIMEOUT 100
@@ -148,7 +148,7 @@ void IS31FL3731_init(uint8_t addr) {
// enable software shutdown // enable software shutdown
IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00); IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
#ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array #ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array
IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10); IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10);
#endif #endif

View File

@@ -41,13 +41,13 @@
#define ISSI_REG_PICTUREFRAME 0x01 #define ISSI_REG_PICTUREFRAME 0x01
// Not defined in the datasheet -- See AN for IC // Not defined in the datasheet -- See AN for IC
#define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting #define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting
#define ISSI_REG_SHUTDOWN 0x0A #define ISSI_REG_SHUTDOWN 0x0A
#define ISSI_REG_AUDIOSYNC 0x06 #define ISSI_REG_AUDIOSYNC 0x06
#define ISSI_COMMANDREGISTER 0xFD #define ISSI_COMMANDREGISTER 0xFD
#define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine' #define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine'
#ifndef ISSI_TIMEOUT #ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100 # define ISSI_TIMEOUT 100
@@ -136,7 +136,7 @@ void IS31FL3731_init(uint8_t addr) {
// enable software shutdown // enable software shutdown
IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00); IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
#ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array #ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array
IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10); IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10);
#endif #endif

View File

@@ -0,0 +1,248 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2021 Doni Crosby
* Copyright 2021 Leo Deng
*
* 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 "is31fl3733-simple.h"
#include "i2c_master.h"
#include "wait.h"
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 <-> GND
// 01 <-> SCL
// 10 <-> SDA
// 11 <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b101(ADDR2)(ADDR1)
#define ISSI_ADDR_DEFAULT 0x50
#define ISSI_COMMANDREGISTER 0xFD
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
#define ISSI_INTERRUPTMASKREGISTER 0xF0
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1
#define ISSI_PAGE_LEDCONTROL 0x00 // PG0
#define ISSI_PAGE_PWM 0x01 // PG1
#define ISSI_PAGE_AUTOBREATH 0x02 // PG2
#define ISSI_PAGE_FUNCTION 0x03 // PG3
#define ISSI_REG_CONFIGURATION 0x00 // PG3
#define ISSI_REG_GLOBALCURRENT 0x01 // PG3
#define ISSI_REG_RESET 0x11 // PG3
#define ISSI_REG_SWPULLUP 0x0F // PG3
#define ISSI_REG_CSPULLUP 0x10 // PG3
#ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100
#endif
#ifndef ISSI_PERSISTENCE
# define ISSI_PERSISTENCE 0
#endif
#ifndef ISSI_PWM_FREQUENCY
# define ISSI_PWM_FREQUENCY 0b000 // PFS - IS31FL3733B only
#endif
#ifndef ISSI_SWPULLUP
# define ISSI_SWPULLUP PUR_0R
#endif
#ifndef ISSI_CSPULLUP
# define ISSI_CSPULLUP PUR_0R
#endif
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
// These buffers match the IS31FL3733 PWM registers.
// The control buffers match the PG0 LED On/Off registers.
// Storing them like this is optimal for I2C transfers to the registers.
// We could optimize this and take out the unused registers from these
// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's
// probably not worth the extra complexity.
uint8_t g_pwm_buffer[LED_DRIVER_COUNT][192];
bool g_pwm_buffer_update_required[LED_DRIVER_COUNT] = {false};
/* There's probably a better way to init this... */
#if LED_DRIVER_COUNT == 1
uint8_t g_led_control_registers[LED_DRIVER_COUNT][24] = {{0}};
#elif LED_DRIVER_COUNT == 2
uint8_t g_led_control_registers[LED_DRIVER_COUNT][24] = {{0}, {0}};
#elif LED_DRIVER_COUNT == 3
uint8_t g_led_control_registers[LED_DRIVER_COUNT][24] = {{0}, {0}, {0}};
#elif LED_DRIVER_COUNT == 4
uint8_t g_led_control_registers[LED_DRIVER_COUNT][24] = {{0}, {0}, {0}, {0}};
#endif
bool g_led_control_registers_update_required[LED_DRIVER_COUNT] = {false};
bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
// If the transaction fails function returns false.
g_twi_transfer_buffer[0] = reg;
g_twi_transfer_buffer[1] = data;
#if ISSI_PERSISTENCE > 0
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) {
return false;
}
}
#else
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) {
return false;
}
#endif
return true;
}
bool IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
// Assumes PG1 is already selected.
// If any of the transactions fails function returns false.
// Transmit PWM registers in 12 transfers of 16 bytes.
// g_twi_transfer_buffer[] is 20 bytes
// Iterate over the pwm_buffer contents at 16 byte intervals.
for (int i = 0; i < 192; i += 16) {
g_twi_transfer_buffer[0] = i;
// Copy the data from i to i+15.
// Device will auto-increment register for data after the first byte
// Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
for (int j = 0; j < 16; j++) {
g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
}
#if ISSI_PERSISTENCE > 0
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) {
return false;
}
}
#else
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) {
return false;
}
#endif
}
return true;
}
void IS31FL3733_init(uint8_t addr, uint8_t sync) {
// In order to avoid the LEDs being driven with garbage data
// in the LED driver's PWM registers, shutdown is enabled last.
// Set up the mode and other settings, clear the PWM registers,
// then disable software shutdown.
// Sync is passed so set it according to the datasheet.
// Unlock the command register.
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
// Select PG0
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
// Turn off all LEDs.
for (int i = 0x00; i <= 0x17; i++) {
IS31FL3733_write_register(addr, i, 0x00);
}
// Unlock the command register.
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
// Select PG1
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
// Set PWM on all LEDs to 0
// No need to setup Breath registers to PWM as that is the default.
for (int i = 0x00; i <= 0xBF; i++) {
IS31FL3733_write_register(addr, i, 0x00);
}
// Unlock the command register.
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
// Select PG3
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
// Set de-ghost pull-up resistors (SWx)
IS31FL3733_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP);
// Set de-ghost pull-down resistors (CSx)
IS31FL3733_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
// Disable software shutdown.
IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((ISSI_PWM_FREQUENCY & 0b111) << 3) | 0x01);
// Wait 10ms to ensure the device has woken up.
wait_ms(10);
}
void IS31FL3733_set_value(int index, uint8_t value) {
if (index >= 0 && index < DRIVER_LED_TOTAL) {
is31_led led = g_is31_leds[index];
g_pwm_buffer[led.driver][led.v] = value;
g_pwm_buffer_update_required[led.driver] = true;
}
}
void IS31FL3733_set_value_all(uint8_t value) {
for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
IS31FL3733_set_value(i, value);
}
}
void IS31FL3733_set_led_control_register(uint8_t index, bool value) {
is31_led led = g_is31_leds[index];
uint8_t control_register = led.v / 8;
uint8_t bit_value = led.v % 8;
if (value) {
g_led_control_registers[led.driver][control_register] |= (1 << bit_value);
} else {
g_led_control_registers[led.driver][control_register] &= ~(1 << bit_value);
}
g_led_control_registers_update_required[led.driver] = true;
}
void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index) {
if (g_pwm_buffer_update_required[index]) {
// Firstly we need to unlock the command register and select PG1.
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
// If any of the transactions fail we risk writing dirty PG0,
// refresh page 0 just in case.
if (!IS31FL3733_write_pwm_buffer(addr, g_pwm_buffer[index])) {
g_led_control_registers_update_required[index] = true;
}
g_pwm_buffer_update_required[index] = false;
}
}
void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index) {
if (g_led_control_registers_update_required[index]) {
// Firstly we need to unlock the command register and select PG0
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
for (int i = 0; i < 24; i++) {
IS31FL3733_write_register(addr, i, g_led_control_registers[index][i]);
}
g_led_control_registers_update_required[index] = false;
}
}

View File

@@ -0,0 +1,260 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2021 Doni Crosby
* Copyright 2021 Leo Deng
*
* 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"
typedef struct is31_led {
uint8_t driver : 2;
uint8_t v;
} __attribute__((packed)) is31_led;
extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
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_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
void IS31FL3733_set_value(int index, uint8_t value);
void IS31FL3733_set_value_all(uint8_t value);
void IS31FL3733_set_led_control_register(uint8_t index, bool value);
// This should not be called from an interrupt
// (eg. from a timer interrupt).
// Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer.
void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index);
void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index);
#define PUR_0R 0x00 // No PUR resistor
#define PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL
#define PUR_3KR 0x03 // 3.0k Ohm resistor on all the time
#define PUR_4KR 0x04 // 4.0k Ohm resistor on all the time
#define PUR_8KR 0x05 // 8.0k Ohm resistor on all the time
#define PUR_16KR 0x06 // 16k Ohm resistor on all the time
#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
#define A_1 0x00
#define A_2 0x01
#define A_3 0x02
#define A_4 0x03
#define A_5 0x04
#define A_6 0x05
#define A_7 0x06
#define A_8 0x07
#define A_9 0x08
#define A_10 0x09
#define A_11 0x0A
#define A_12 0x0B
#define A_13 0x0C
#define A_14 0x0D
#define A_15 0x0E
#define A_16 0x0F
#define B_1 0x10
#define B_2 0x11
#define B_3 0x12
#define B_4 0x13
#define B_5 0x14
#define B_6 0x15
#define B_7 0x16
#define B_8 0x17
#define B_9 0x18
#define B_10 0x19
#define B_11 0x1A
#define B_12 0x1B
#define B_13 0x1C
#define B_14 0x1D
#define B_15 0x1E
#define B_16 0x1F
#define C_1 0x20
#define C_2 0x21
#define C_3 0x22
#define C_4 0x23
#define C_5 0x24
#define C_6 0x25
#define C_7 0x26
#define C_8 0x27
#define C_9 0x28
#define C_10 0x29
#define C_11 0x2A
#define C_12 0x2B
#define C_13 0x2C
#define C_14 0x2D
#define C_15 0x2E
#define C_16 0x2F
#define D_1 0x30
#define D_2 0x31
#define D_3 0x32
#define D_4 0x33
#define D_5 0x34
#define D_6 0x35
#define D_7 0x36
#define D_8 0x37
#define D_9 0x38
#define D_10 0x39
#define D_11 0x3A
#define D_12 0x3B
#define D_13 0x3C
#define D_14 0x3D
#define D_15 0x3E
#define D_16 0x3F
#define E_1 0x40
#define E_2 0x41
#define E_3 0x42
#define E_4 0x43
#define E_5 0x44
#define E_6 0x45
#define E_7 0x46
#define E_8 0x47
#define E_9 0x48
#define E_10 0x49
#define E_11 0x4A
#define E_12 0x4B
#define E_13 0x4C
#define E_14 0x4D
#define E_15 0x4E
#define E_16 0x4F
#define F_1 0x50
#define F_2 0x51
#define F_3 0x52
#define F_4 0x53
#define F_5 0x54
#define F_6 0x55
#define F_7 0x56
#define F_8 0x57
#define F_9 0x58
#define F_10 0x59
#define F_11 0x5A
#define F_12 0x5B
#define F_13 0x5C
#define F_14 0x5D
#define F_15 0x5E
#define F_16 0x5F
#define G_1 0x60
#define G_2 0x61
#define G_3 0x62
#define G_4 0x63
#define G_5 0x64
#define G_6 0x65
#define G_7 0x66
#define G_8 0x67
#define G_9 0x68
#define G_10 0x69
#define G_11 0x6A
#define G_12 0x6B
#define G_13 0x6C
#define G_14 0x6D
#define G_15 0x6E
#define G_16 0x6F
#define H_1 0x70
#define H_2 0x71
#define H_3 0x72
#define H_4 0x73
#define H_5 0x74
#define H_6 0x75
#define H_7 0x76
#define H_8 0x77
#define H_9 0x78
#define H_10 0x79
#define H_11 0x7A
#define H_12 0x7B
#define H_13 0x7C
#define H_14 0x7D
#define H_15 0x7E
#define H_16 0x7F
#define I_1 0x80
#define I_2 0x81
#define I_3 0x82
#define I_4 0x83
#define I_5 0x84
#define I_6 0x85
#define I_7 0x86
#define I_8 0x87
#define I_9 0x88
#define I_10 0x89
#define I_11 0x8A
#define I_12 0x8B
#define I_13 0x8C
#define I_14 0x8D
#define I_15 0x8E
#define I_16 0x8F
#define J_1 0x90
#define J_2 0x91
#define J_3 0x92
#define J_4 0x93
#define J_5 0x94
#define J_6 0x95
#define J_7 0x96
#define J_8 0x97
#define J_9 0x98
#define J_10 0x99
#define J_11 0x9A
#define J_12 0x9B
#define J_13 0x9C
#define J_14 0x9D
#define J_15 0x9E
#define J_16 0x9F
#define K_1 0xA0
#define K_2 0xA1
#define K_3 0xA2
#define K_4 0xA3
#define K_5 0xA4
#define K_6 0xA5
#define K_7 0xA6
#define K_8 0xA7
#define K_9 0xA8
#define K_10 0xA9
#define K_11 0xAA
#define K_12 0xAB
#define K_13 0xAC
#define K_14 0xAD
#define K_15 0xAE
#define K_16 0xAF
#define L_1 0xB0
#define L_2 0xB1
#define L_3 0xB2
#define L_4 0xB3
#define L_5 0xB4
#define L_6 0xB5
#define L_7 0xB6
#define L_8 0xB7
#define L_9 0xB8
#define L_10 0xB9
#define L_11 0xBA
#define L_12 0xBB
#define L_13 0xBC
#define L_14 0xBD
#define L_15 0xBE
#define L_16 0xBF

View File

@@ -38,16 +38,16 @@
#define ISSI_INTERRUPTMASKREGISTER 0xF0 #define ISSI_INTERRUPTMASKREGISTER 0xF0
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 #define ISSI_INTERRUPTSTATUSREGISTER 0xF1
#define ISSI_PAGE_LEDCONTROL 0x00 // PG0 #define ISSI_PAGE_LEDCONTROL 0x00 // PG0
#define ISSI_PAGE_PWM 0x01 // PG1 #define ISSI_PAGE_PWM 0x01 // PG1
#define ISSI_PAGE_AUTOBREATH 0x02 // PG2 #define ISSI_PAGE_AUTOBREATH 0x02 // PG2
#define ISSI_PAGE_FUNCTION 0x03 // PG3 #define ISSI_PAGE_FUNCTION 0x03 // PG3
#define ISSI_REG_CONFIGURATION 0x00 // PG3 #define ISSI_REG_CONFIGURATION 0x00 // PG3
#define ISSI_REG_GLOBALCURRENT 0x01 // PG3 #define ISSI_REG_GLOBALCURRENT 0x01 // PG3
#define ISSI_REG_RESET 0x11 // PG3 #define ISSI_REG_RESET 0x11 // PG3
#define ISSI_REG_SWPULLUP 0x0F // PG3 #define ISSI_REG_SWPULLUP 0x0F // PG3
#define ISSI_REG_CSPULLUP 0x10 // PG3 #define ISSI_REG_CSPULLUP 0x10 // PG3
#ifndef ISSI_TIMEOUT #ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100 # define ISSI_TIMEOUT 100
@@ -58,7 +58,7 @@
#endif #endif
#ifndef ISSI_PWM_FREQUENCY #ifndef ISSI_PWM_FREQUENCY
# define ISSI_PWM_FREQUENCY 0b000 // PFS - IS31FL3733B only # define ISSI_PWM_FREQUENCY 0b000 // PFS - IS31FL3733B only
#endif #endif
#ifndef ISSI_SWPULLUP #ifndef ISSI_SWPULLUP

View File

@@ -48,13 +48,13 @@ void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bo
void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index); void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index);
void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index); void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index);
#define PUR_0R 0x00 // No PUR resistor #define PUR_0R 0x00 // No PUR resistor
#define PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL #define PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL
#define PUR_3KR 0x03 // 3.0k Ohm resistor on all the time #define PUR_3KR 0x03 // 3.0k Ohm resistor on all the time
#define PUR_4KR 0x04 // 4.0k Ohm resistor on all the time #define PUR_4KR 0x04 // 4.0k Ohm resistor on all the time
#define PUR_8KR 0x05 // 8.0k Ohm resistor on all the time #define PUR_8KR 0x05 // 8.0k Ohm resistor on all the time
#define PUR_16KR 0x06 // 16k Ohm resistor on all the time #define PUR_16KR 0x06 // 16k Ohm resistor on all the time
#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL #define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
#define A_1 0x00 #define A_1 0x00
#define A_2 0x01 #define A_2 0x01

View File

@@ -36,16 +36,16 @@
#define ISSI_INTERRUPTMASKREGISTER 0xF0 #define ISSI_INTERRUPTMASKREGISTER 0xF0
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 #define ISSI_INTERRUPTSTATUSREGISTER 0xF1
#define ISSI_PAGE_LEDCONTROL 0x00 // PG0 #define ISSI_PAGE_LEDCONTROL 0x00 // PG0
#define ISSI_PAGE_PWM 0x01 // PG1 #define ISSI_PAGE_PWM 0x01 // PG1
#define ISSI_PAGE_AUTOBREATH 0x02 // PG2 #define ISSI_PAGE_AUTOBREATH 0x02 // PG2
#define ISSI_PAGE_FUNCTION 0x03 // PG3 #define ISSI_PAGE_FUNCTION 0x03 // PG3
#define ISSI_REG_CONFIGURATION 0x00 // PG3 #define ISSI_REG_CONFIGURATION 0x00 // PG3
#define ISSI_REG_GLOBALCURRENT 0x01 // PG3 #define ISSI_REG_GLOBALCURRENT 0x01 // PG3
#define ISSI_REG_RESET 0x11 // PG3 #define ISSI_REG_RESET 0x11 // PG3
#define ISSI_REG_SWPULLUP 0x0F // PG3 #define ISSI_REG_SWPULLUP 0x0F // PG3
#define ISSI_REG_CSPULLUP 0x10 // PG3 #define ISSI_REG_CSPULLUP 0x10 // PG3
#ifndef ISSI_TIMEOUT #ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100 # define ISSI_TIMEOUT 100

View File

@@ -61,14 +61,14 @@ void IS31FL3736_mono_set_led_control_register(uint8_t index, bool enabled);
void IS31FL3736_update_pwm_buffers(uint8_t addr1, uint8_t addr2); void IS31FL3736_update_pwm_buffers(uint8_t addr1, uint8_t addr2);
void IS31FL3736_update_led_control_registers(uint8_t addr1, uint8_t addr2); void IS31FL3736_update_led_control_registers(uint8_t addr1, uint8_t addr2);
#define PUR_0R 0x00 // No PUR resistor #define PUR_0R 0x00 // No PUR resistor
#define PUR_05KR 0x01 // 0.5k Ohm resistor #define PUR_05KR 0x01 // 0.5k Ohm resistor
#define PUR_1KR 0x02 // 1.0k Ohm resistor #define PUR_1KR 0x02 // 1.0k Ohm resistor
#define PUR_2KR 0x03 // 2.0k Ohm resistor #define PUR_2KR 0x03 // 2.0k Ohm resistor
#define PUR_4KR 0x04 // 4.0k Ohm resistor #define PUR_4KR 0x04 // 4.0k Ohm resistor
#define PUR_8KR 0x05 // 8.0k Ohm resistor #define PUR_8KR 0x05 // 8.0k Ohm resistor
#define PUR_16KR 0x06 // 16k Ohm resistor #define PUR_16KR 0x06 // 16k Ohm resistor
#define PUR_32KR 0x07 // 32k Ohm resistor #define PUR_32KR 0x07 // 32k Ohm resistor
#define A_1 0x00 #define A_1 0x00
#define A_2 0x02 #define A_2 0x02

View File

@@ -38,16 +38,16 @@
#define ISSI_INTERRUPTMASKREGISTER 0xF0 #define ISSI_INTERRUPTMASKREGISTER 0xF0
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 #define ISSI_INTERRUPTSTATUSREGISTER 0xF1
#define ISSI_PAGE_LEDCONTROL 0x00 // PG0 #define ISSI_PAGE_LEDCONTROL 0x00 // PG0
#define ISSI_PAGE_PWM 0x01 // PG1 #define ISSI_PAGE_PWM 0x01 // PG1
#define ISSI_PAGE_AUTOBREATH 0x02 // PG2 #define ISSI_PAGE_AUTOBREATH 0x02 // PG2
#define ISSI_PAGE_FUNCTION 0x03 // PG3 #define ISSI_PAGE_FUNCTION 0x03 // PG3
#define ISSI_REG_CONFIGURATION 0x00 // PG3 #define ISSI_REG_CONFIGURATION 0x00 // PG3
#define ISSI_REG_GLOBALCURRENT 0x01 // PG3 #define ISSI_REG_GLOBALCURRENT 0x01 // PG3
#define ISSI_REG_RESET 0x11 // PG3 #define ISSI_REG_RESET 0x11 // PG3
#define ISSI_REG_SWPULLUP 0x0F // PG3 #define ISSI_REG_SWPULLUP 0x0F // PG3
#define ISSI_REG_CSPULLUP 0x10 // PG3 #define ISSI_REG_CSPULLUP 0x10 // PG3
#ifndef ISSI_TIMEOUT #ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100 # define ISSI_TIMEOUT 100

View File

@@ -48,14 +48,14 @@ void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bo
void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2); void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2);
void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2); void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2);
#define PUR_0R 0x00 // No PUR resistor #define PUR_0R 0x00 // No PUR resistor
#define PUR_05KR 0x01 // 0.5k Ohm resistor in t_NOL #define PUR_05KR 0x01 // 0.5k Ohm resistor in t_NOL
#define PUR_1KR 0x02 // 1.0k Ohm resistor in t_NOL #define PUR_1KR 0x02 // 1.0k Ohm resistor in t_NOL
#define PUR_2KR 0x03 // 2.0k Ohm resistor in t_NOL #define PUR_2KR 0x03 // 2.0k Ohm resistor in t_NOL
#define PUR_4KR 0x04 // 4.0k Ohm resistor in t_NOL #define PUR_4KR 0x04 // 4.0k Ohm resistor in t_NOL
#define PUR_8KR 0x05 // 8.0k Ohm resistor in t_NOL #define PUR_8KR 0x05 // 8.0k Ohm resistor in t_NOL
#define PUR_16KR 0x06 // 16k Ohm resistor in t_NOL #define PUR_16KR 0x06 // 16k Ohm resistor in t_NOL
#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL #define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
#define A_1 0x00 #define A_1 0x00
#define A_2 0x01 #define A_2 0x01

View File

@@ -42,16 +42,16 @@
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 #define ISSI_INTERRUPTSTATUSREGISTER 0xF1
#define ISSI_IDREGISTER 0xFC #define ISSI_IDREGISTER 0xFC
#define ISSI_PAGE_PWM0 0x00 // PG0 #define ISSI_PAGE_PWM0 0x00 // PG0
#define ISSI_PAGE_PWM1 0x01 // PG1 #define ISSI_PAGE_PWM1 0x01 // PG1
#define ISSI_PAGE_SCALING_0 0x02 // PG2 #define ISSI_PAGE_SCALING_0 0x02 // PG2
#define ISSI_PAGE_SCALING_1 0x03 // PG3 #define ISSI_PAGE_SCALING_1 0x03 // PG3
#define ISSI_PAGE_FUNCTION 0x04 // PG4 #define ISSI_PAGE_FUNCTION 0x04 // PG4
#define ISSI_REG_CONFIGURATION 0x00 // PG4 #define ISSI_REG_CONFIGURATION 0x00 // PG4
#define ISSI_REG_GLOBALCURRENT 0x01 // PG4 #define ISSI_REG_GLOBALCURRENT 0x01 // PG4
#define ISSI_REG_PULLDOWNUP 0x02 // PG4 #define ISSI_REG_PULLDOWNUP 0x02 // PG4
#define ISSI_REG_RESET 0x3F // PG4 #define ISSI_REG_RESET 0x3F // PG4
#ifndef ISSI_TIMEOUT #ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100 # define ISSI_TIMEOUT 100

View File

@@ -51,14 +51,14 @@ void IS31FL3741_set_scaling_registers(const is31_led *pled, uint8_t red, uint8_t
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);
#define PUR_0R 0x00 // No PUR resistor #define PUR_0R 0x00 // No PUR resistor
#define PUR_05KR 0x01 // 0.5k Ohm resistor #define PUR_05KR 0x01 // 0.5k Ohm resistor
#define PUR_1KR 0x02 // 1.0k Ohm resistor #define PUR_1KR 0x02 // 1.0k Ohm resistor
#define PUR_2KR 0x03 // 2.0k Ohm resistor #define PUR_2KR 0x03 // 2.0k Ohm resistor
#define PUR_4KR 0x04 // 4.0k Ohm resistor #define PUR_4KR 0x04 // 4.0k Ohm resistor
#define PUR_8KR 0x05 // 8.0k Ohm resistor #define PUR_8KR 0x05 // 8.0k Ohm resistor
#define PUR_16KR 0x06 // 16k Ohm resistor #define PUR_16KR 0x06 // 16k Ohm resistor
#define PUR_32KR 0x07 // 32k Ohm resistor #define PUR_32KR 0x07 // 32k Ohm resistor
#define CS1_SW1 0x00 #define CS1_SW1 0x00
#define CS2_SW1 0x01 #define CS2_SW1 0x01

View File

@@ -0,0 +1,299 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2020 MelGeek
* Copyright 2021 MasterSpoon
*
* 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
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 <-> GND
// 01 <-> SCL
// 10 <-> SDA
// 11 <-> VCC
// ADDR represents A1:A0 of the 7-bit address.
// The result is: 0b01100(ADDR)
#ifndef DRIVER_ADDR_1
# define DRIVER_ADDR_1 0b0110000
#endif
// Command Registers
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
#define ISSI_COMMANDREGISTER 0xFD
#define ISSI_IDREGISTER 0xFC
#define ISSI_REGISTER_UNLOCK 0xC5
// Response Registers
#define ISSI_PAGE_PWM 0x00
#define ISSI_PAGE_SCALING 0x02
#define ISSI_PAGE_FUNCTION 0x04
// Registers under Function Register
#define ISSI_REG_CONFIGURATION 0x00
#define ISSI_REG_GLOBALCURRENT 0x01
#define ISSI_REG_PULLDOWNUP 0x02
#define ISSI_REG_SSR 0x41
#define ISSI_REG_RESET 0x3F
#define ISSI_REG_PWM_SET 0x36
// Set defaults for Function Registers
#ifndef ISSI_CONFIGURATION
# define ISSI_CONFIGURATION 0x31
#endif
#ifndef ISSI_GLOBALCURRENT
# define ISSI_GLOBALCURRENT 0xFF
#endif
#ifndef ISSI_PULLDOWNUP
# define ISSI_PULLDOWNUP 0x55
#endif
#ifndef ISSI_PWM_SET
# define ISSI_PWM_SET 0x00
#endif
// Set defaults for Spread Spectrum Register
#ifndef ISSI_SSR_1
# define ISSI_SSR_1 0x00
#endif
#ifndef ISSI_SSR_2
# define ISSI_SSR_2 0x00
#endif
#ifndef ISSI_SSR_3
# define ISSI_SSR_3 0x00
#endif
#ifndef ISSI_SSR_4
# define ISSI_SSR_4 0x00
#endif
// Set defaults for Scaling registers
#ifndef ISSI_SCAL_RED
# define ISSI_SCAL_RED 0xFF
#endif
#ifndef ISSI_SCAL_BLUE
# define ISSI_SCAL_BLUE 0xFF
#endif
#ifndef ISSI_SCAL_GREEN
# define ISSI_SCAL_GREEN 0xFF
#endif
#define ISSI_SCAL_RED_OFF 0x00
#define ISSI_SCAL_GREEN_OFF 0x00
#define ISSI_SCAL_BLUE_OFF 0x00
#ifndef ISSI_SCAL_LED
# define ISSI_SCAL_LED 0xFF
#endif
#define ISSI_SCAL_LED_OFF 0x00
// Set buffer sizes
#define ISSI_MAX_LEDS 180
#define ISSI_SCALING_SIZE 180
#define ISSI_PWM_TRF_SIZE 18
#define ISSI_SCALING_TRF_SIZE 18
// Location of 1st bit for PWM and Scaling registers
#define ISSI_PWM_REG_1ST 0x00
#define ISSI_SCL_REG_1ST 0x00
// Map CS SW locations to order in PWM / Scaling buffers
// This matches the ORDER in the Datasheet Register not the POSITION
// It will always count from 0x00 to (ISSI_MAX_LEDS - 1)
#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 CS19_SW1 0x12
#define CS20_SW1 0x13
#define CS21_SW1 0x14
#define CS22_SW1 0x15
#define CS23_SW1 0x16
#define CS24_SW1 0x17
#define CS25_SW1 0x18
#define CS26_SW1 0x19
#define CS27_SW1 0x1A
#define CS28_SW1 0x1B
#define CS29_SW1 0x1C
#define CS30_SW1 0x1D
#define CS1_SW2 0x1E
#define CS2_SW2 0x1F
#define CS3_SW2 0x20
#define CS4_SW2 0x21
#define CS5_SW2 0x22
#define CS6_SW2 0x23
#define CS7_SW2 0x24
#define CS8_SW2 0x25
#define CS9_SW2 0x26
#define CS10_SW2 0x27
#define CS11_SW2 0x28
#define CS12_SW2 0x29
#define CS13_SW2 0x2A
#define CS14_SW2 0x2B
#define CS15_SW2 0x2C
#define CS16_SW2 0x2D
#define CS17_SW2 0x2E
#define CS18_SW2 0x2F
#define CS19_SW2 0x30
#define CS20_SW2 0x31
#define CS21_SW2 0x32
#define CS22_SW2 0x33
#define CS23_SW2 0x34
#define CS24_SW2 0x35
#define CS25_SW2 0x36
#define CS26_SW2 0x37
#define CS27_SW2 0x38
#define CS28_SW2 0x39
#define CS29_SW2 0x3A
#define CS30_SW2 0x3B
#define CS1_SW3 0x3C
#define CS2_SW3 0x3D
#define CS3_SW3 0x3E
#define CS4_SW3 0x3F
#define CS5_SW3 0x40
#define CS6_SW3 0x41
#define CS7_SW3 0x42
#define CS8_SW3 0x43
#define CS9_SW3 0x44
#define CS10_SW3 0x45
#define CS11_SW3 0x46
#define CS12_SW3 0x47
#define CS13_SW3 0x48
#define CS14_SW3 0x49
#define CS15_SW3 0x4A
#define CS16_SW3 0x4B
#define CS17_SW3 0x4C
#define CS18_SW3 0x4D
#define CS19_SW3 0x4E
#define CS20_SW3 0x4F
#define CS21_SW3 0x50
#define CS22_SW3 0x51
#define CS23_SW3 0x52
#define CS24_SW3 0x53
#define CS25_SW3 0x54
#define CS26_SW3 0x55
#define CS27_SW3 0x56
#define CS28_SW3 0x57
#define CS29_SW3 0x58
#define CS30_SW3 0x59
#define CS1_SW4 0x5A
#define CS2_SW4 0x5B
#define CS3_SW4 0x5C
#define CS4_SW4 0x5D
#define CS5_SW4 0x5E
#define CS6_SW4 0x5F
#define CS7_SW4 0x60
#define CS8_SW4 0x61
#define CS9_SW4 0x62
#define CS10_SW4 0x63
#define CS11_SW4 0x64
#define CS12_SW4 0x65
#define CS13_SW4 0x66
#define CS14_SW4 0x67
#define CS15_SW4 0x68
#define CS16_SW4 0x69
#define CS17_SW4 0x6A
#define CS18_SW4 0x6B
#define CS19_SW4 0x6C
#define CS20_SW4 0x6D
#define CS21_SW4 0x6E
#define CS22_SW4 0x6F
#define CS23_SW4 0x70
#define CS24_SW4 0x71
#define CS25_SW4 0x72
#define CS26_SW4 0x73
#define CS27_SW4 0x74
#define CS28_SW4 0x75
#define CS29_SW4 0x76
#define CS30_SW4 0x77
#define CS1_SW5 0x78
#define CS2_SW5 0x79
#define CS3_SW5 0x7A
#define CS4_SW5 0x7B
#define CS5_SW5 0x7C
#define CS6_SW5 0x7D
#define CS7_SW5 0x7E
#define CS8_SW5 0x7F
#define CS9_SW5 0x80
#define CS10_SW5 0x81
#define CS11_SW5 0x82
#define CS12_SW5 0x83
#define CS13_SW5 0x84
#define CS14_SW5 0x85
#define CS15_SW5 0x86
#define CS16_SW5 0x87
#define CS17_SW5 0x88
#define CS18_SW5 0x89
#define CS19_SW5 0x8A
#define CS20_SW5 0x8B
#define CS21_SW5 0x8C
#define CS22_SW5 0x8D
#define CS23_SW5 0x8E
#define CS24_SW5 0x8F
#define CS25_SW5 0x90
#define CS26_SW5 0x91
#define CS27_SW5 0x92
#define CS28_SW5 0x93
#define CS29_SW5 0x94
#define CS30_SW5 0x95
#define CS1_SW6 0x96
#define CS2_SW6 0x97
#define CS3_SW6 0x98
#define CS4_SW6 0x99
#define CS5_SW6 0x9A
#define CS6_SW6 0x9B
#define CS7_SW6 0x9C
#define CS8_SW6 0x9D
#define CS9_SW6 0x9E
#define CS10_SW6 0x9F
#define CS11_SW6 0xA0
#define CS12_SW6 0xA1
#define CS13_SW6 0xA2
#define CS14_SW6 0xA3
#define CS15_SW6 0xA4
#define CS16_SW6 0xA5
#define CS17_SW6 0xA6
#define CS18_SW6 0xA7
#define CS19_SW6 0xA8
#define CS20_SW6 0xA9
#define CS21_SW6 0xAA
#define CS22_SW6 0xAB
#define CS23_SW6 0xAC
#define CS24_SW6 0xAD
#define CS25_SW6 0xAE
#define CS26_SW6 0xAF
#define CS27_SW6 0xB0
#define CS28_SW6 0xB1
#define CS29_SW6 0xB2
#define CS30_SW6 0xB3

View File

@@ -0,0 +1,327 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2020 MelGeek
* Copyright 2021 MasterSpoon
*
* 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
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 <-> GND
// 01 <-> SCL
// 10 <-> SDA
// 11 <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b010(ADDR2)(ADDR1)
#ifndef DRIVER_ADDR_1
# define DRIVER_ADDR_1 0b0100000
#endif
// Set defaults for Spread Spectrum Register
#ifndef ISSI_SSR_1
# if DRIVER_COUNT == 1
# define ISSI_SSR_1 0x00
# else
# define ISSI_SSR_1 0xC0
# endif
#endif
#ifndef ISSI_SSR_2
# define ISSI_SSR_2 0x80
#endif
#ifndef ISSI_SSR_3
# define ISSI_SSR_3 0x80
#endif
#ifndef ISSI_SSR_4
# define ISSI_SSR_4 0x80
#endif
// Command Registers
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
#define ISSI_COMMANDREGISTER 0xFD
#define ISSI_IDREGISTER 0xFC
#define ISSI_REGISTER_UNLOCK 0xC5
// Response Registers
#define ISSI_PAGE_PWM 0x00
#define ISSI_PAGE_SCALING 0x01
#define ISSI_PAGE_FUNCTION 0x02
// Registers under Function Register
#define ISSI_REG_CONFIGURATION 0x00
#define ISSI_REG_GLOBALCURRENT 0x01
#define ISSI_REG_PULLDOWNUP 0x02
#define ISSI_REG_TEMP 0x24
#define ISSI_REG_SSR 0x25
#define ISSI_REG_RESET 0x2F
// Set defaults for Function Registers
#ifndef ISSI_CONFIGURATION
# define ISSI_CONFIGURATION 0x01
#endif
#ifndef ISSI_GLOBALCURRENT
# define ISSI_GLOBALCURRENT 0xFF
#endif
#ifndef ISSI_PULLDOWNUP
# define ISSI_PULLDOWNUP 0x33
#endif
#ifndef ISSI_TEMP
# define ISSI_TEMP 0x00
#endif
// Set defaults for Scaling registers
#ifndef ISSI_SCAL_RED
# define ISSI_SCAL_RED 0xFF
#endif
#ifndef ISSI_SCAL_BLUE
# define ISSI_SCAL_BLUE 0xFF
#endif
#ifndef ISSI_SCAL_GREEN
# define ISSI_SCAL_GREEN 0xFF
#endif
#define ISSI_SCAL_RED_OFF 0x00
#define ISSI_SCAL_GREEN_OFF 0x00
#define ISSI_SCAL_BLUE_OFF 0x00
#ifndef ISSI_SCAL_LED
# define ISSI_SCAL_LED 0xFF
#endif
#define ISSI_SCAL_LED_OFF 0x00
// Set buffer sizes
#define ISSI_MAX_LEDS 198
#define ISSI_SCALING_SIZE 198
#define ISSI_PWM_TRF_SIZE 18
#define ISSI_SCALING_TRF_SIZE 18
// Location of 1st bit for PWM and Scaling registers
#define ISSI_PWM_REG_1ST 0x01
#define ISSI_SCL_REG_1ST 0x01
// Map CS SW locations to order in PWM / Scaling buffers
// This matches the ORDER in the Datasheet Register not the POSITION
// It will always count from 0x00 to (ISSI_MAX_LEDS - 1)
#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

View File

@@ -0,0 +1,270 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2020 MelGeek
* Copyright 2021 MasterSpoon
*
* 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
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 <-> GND
// 01 <-> SCL
// 10 <-> SDA
// 11 <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b010(ADDR2)(ADDR1)
#ifndef DRIVER_ADDR_1
# define DRIVER_ADDR_1 0b0100000
#endif
// Set defaults for Spread Spectrum Register
#ifndef ISSI_SSR_1
# if DRIVER_COUNT == 1
# define ISSI_SSR_1 0x00
# else
# define ISSI_SSR_1 0xC0
# endif
#endif
#ifndef ISSI_SSR_2
# define ISSI_SSR_2 0x80
#endif
#ifndef ISSI_SSR_3
# define ISSI_SSR_3 0x80
#endif
#ifndef ISSI_SSR_4
# define ISSI_SSR_4 0x80
#endif
// Command Registers
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
#define ISSI_COMMANDREGISTER 0xFD
#define ISSI_IDREGISTER 0xFC
#define ISSI_REGISTER_UNLOCK 0xC5
// Response Registers
#define ISSI_PAGE_PWM 0x00
#define ISSI_PAGE_SCALING 0x01
#define ISSI_PAGE_FUNCTION 0x02
// Registers under Function Register
#define ISSI_REG_CONFIGURATION 0x00
#define ISSI_REG_GLOBALCURRENT 0x01
#define ISSI_REG_PULLDOWNUP 0x02
#define ISSI_REG_TEMP 0x24
#define ISSI_REG_SSR 0x25
#define ISSI_REG_RESET 0x2F
// Set defaults for Function Registers
#ifndef ISSI_CONFIGURATION
# define ISSI_CONFIGURATION 0x31
#endif
#ifndef ISSI_GLOBALCURRENT
# define ISSI_GLOBALCURRENT 0xFF
#endif
#ifndef ISSI_PULLDOWNUP
# define ISSI_PULLDOWNUP 0x33
#endif
#ifndef ISSI_TEMP
# define ISSI_TEMP 0x00
#endif
// Set defaults for Scaling registers
#ifndef ISSI_SCAL_RED
# define ISSI_SCAL_RED 0xFF
#endif
#ifndef ISSI_SCAL_BLUE
# define ISSI_SCAL_BLUE 0xFF
#endif
#ifndef ISSI_SCAL_GREEN
# define ISSI_SCAL_GREEN 0xFF
#endif
#define ISSI_SCAL_RED_OFF 0x00
#define ISSI_SCAL_GREEN_OFF 0x00
#define ISSI_SCAL_BLUE_OFF 0x00
#ifndef ISSI_SCAL_LED
# define ISSI_SCAL_LED 0xFF
#endif
#define ISSI_SCAL_LED_OFF 0x00
// Set buffer sizes
#define ISSI_MAX_LEDS 144
#define ISSI_SCALING_SIZE 144
#define ISSI_PWM_TRF_SIZE 18
#define ISSI_SCALING_TRF_SIZE 18
// Location of 1st bit for PWM and Scaling registers
#define ISSI_PWM_REG_1ST 0x01
#define ISSI_SCL_REG_1ST 0x01
// Map CS SW locations to order in PWM / Scaling buffers
// This matches the ORDER in the Datasheet Register not the POSITION
// It will always count from 0x00 to (ISSI_MAX_LEDS - 1)
#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

View File

@@ -0,0 +1,198 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2020 MelGeek
* Copyright 2021 MasterSpoon
*
* 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
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
// 00 <-> GND
// 01 <-> SCL
// 10 <-> SDA
// 11 <-> VCC
// ADDR1 represents A1:A0 of the 7-bit address.
// ADDR2 represents A3:A2 of the 7-bit address.
// The result is: 0b110(ADDR2)(ADDR1)
#ifndef DRIVER_ADDR_1
# define DRIVER_ADDR_1 0b1100000
#endif
// Set defaults for Spread Spectrum Register
#ifndef ISSI_SSR_1
# define ISSI_SSR_1 0x00
#endif
#ifndef ISSI_SSR_2
# define ISSI_SSR_2 0x00
#endif
#ifndef ISSI_SSR_3
# define ISSI_SSR_3 0x00
#endif
#ifndef ISSI_SSR_4
# define ISSI_SSR_4 0x00
#endif
// Command Registers
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
#define ISSI_COMMANDREGISTER 0xFD
#define ISSI_IDREGISTER 0xFC
#define ISSI_REGISTER_UNLOCK 0xC5
// Response Registers
#define ISSI_PAGE_PWM 0x00
#define ISSI_PAGE_SCALING 0x01
#define ISSI_PAGE_FUNCTION 0x01
// Registers under Function Register
#define ISSI_REG_CONFIGURATION 0x50
#define ISSI_REG_GLOBALCURRENT 0x51
#define ISSI_REG_PULLDOWNUP 0x52
#define ISSI_REG_TEMP 0x5F
#define ISSI_REG_SSR 0x60
#define ISSI_REG_RESET 0x8F
#define ISSI_REG_PWM_ENABLE 0xE0
#define ISSI_REG_PWM_SET 0xE2
// Set defaults for Function Registers
#ifndef ISSI_CONFIGURATION
# define ISSI_CONFIGURATION 0x01
#endif
#ifndef ISSI_GLOBALCURRENT
# define ISSI_GLOBALCURRENT 0xFF
#endif
#ifndef ISSI_PULLDOWNUP
# define ISSI_PULLDOWNUP 0x33
#endif
#ifndef ISSI_TEMP
# define ISSI_TEMP 0x00
#endif
#ifndef ISSI_PWM_ENABLE
# define ISSI_PWM_ENABLE 0x00
#endif
#ifndef ISSI_PWM_SET
# define ISSI_PWM_SET 0x00
#endif
// Set defaults for Scaling registers
#ifndef ISSI_SCAL_RED
# define ISSI_SCAL_RED 0xFF
#endif
#ifndef ISSI_SCAL_BLUE
# define ISSI_SCAL_BLUE 0xFF
#endif
#ifndef ISSI_SCAL_GREEN
# define ISSI_SCAL_GREEN 0xFF
#endif
#define ISSI_SCAL_RED_OFF 0x00
#define ISSI_SCAL_GREEN_OFF 0x00
#define ISSI_SCAL_BLUE_OFF 0x00
#ifndef ISSI_SCAL_LED
# define ISSI_SCAL_LED 0xFF
#endif
#define ISSI_SCAL_LED_OFF 0x00
// Set buffer sizes
#define ISSI_MAX_LEDS 72
#define ISSI_SCALING_SIZE 72
#define ISSI_PWM_TRF_SIZE 18
#define ISSI_SCALING_TRF_SIZE 18
// Location of 1st bit for PWM and Scaling registers
#define ISSI_PWM_REG_1ST 0x01
#define ISSI_SCL_REG_1ST 0x01
// Map CS SW locations to order in PWM / Scaling buffers
// This matches the ORDER in the Datasheet Register not the POSITION
// It will always count from 0x00 to (ISSI_MAX_LEDS - 1)
#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

View File

@@ -0,0 +1,230 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2020 MelGeek
* Copyright 2021 MasterSpoon
*
* 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 "is31flcommon.h"
#include "i2c_master.h"
#include "wait.h"
#include <string.h>
// Set defaults for Timeout and Persistence
#ifndef ISSI_TIMEOUT
# define ISSI_TIMEOUT 100
#endif
#ifndef ISSI_PERSISTENCE
# define ISSI_PERSISTENCE 0
#endif
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
// These buffers match the PWM & scaling registers.
// Storing them like this is optimal for I2C transfers to the registers.
uint8_t g_pwm_buffer[DRIVER_COUNT][ISSI_MAX_LEDS];
bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
uint8_t g_scaling_buffer[DRIVER_COUNT][ISSI_SCALING_SIZE];
bool g_scaling_buffer_update_required[DRIVER_COUNT] = {false};
// For writing of single register entry
void IS31FL_write_single_register(uint8_t addr, uint8_t reg, uint8_t data) {
// Set register address and register data ready to write
g_twi_transfer_buffer[0] = reg;
g_twi_transfer_buffer[1] = data;
#if ISSI_PERSISTENCE > 0
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) break;
}
#else
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
#endif
}
// For writing of mulitple register entries to make use of address auto increment
// Once the controller has been called and we have written the first bit of data
// the controller will move to the next register meaning we can write sequential blocks.
bool IS31FL_write_multi_registers(uint8_t addr, uint8_t *source_buffer, uint8_t buffer_size, uint8_t transfer_size, uint8_t start_reg_addr) {
// Split the buffer into chunks to transfer
for (int i = 0; i < buffer_size; i += transfer_size) {
// Set the first entry of transfer buffer to the first register we want to write
g_twi_transfer_buffer[0] = i + start_reg_addr;
// Copy the section of our source buffer into the transfer buffer after first register address
memcpy(g_twi_transfer_buffer + 1, source_buffer + i, transfer_size);
#if ISSI_PERSISTENCE > 0
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, transfer_size + 1, ISSI_TIMEOUT) != 0) {
return false;
}
}
#else
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, transfer_size + 1, ISSI_TIMEOUT) != 0) {
return false;
}
#endif
}
return true;
}
void IS31FL_unlock_register(uint8_t addr, uint8_t page) {
// unlock the command register and select Page to write
IS31FL_write_single_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, ISSI_REGISTER_UNLOCK);
IS31FL_write_single_register(addr, ISSI_COMMANDREGISTER, page);
}
void IS31FL_common_init(uint8_t addr, uint8_t ssr) {
// Setup phase, need to take out of software shutdown and configure
// ISSI_SSR_x is passed to allow Master / Slave setting where applicable
// Unlock the command register & select Function Register
IS31FL_unlock_register(addr, ISSI_PAGE_FUNCTION);
// Set Configuration Register to remove Software shutdown
IS31FL_write_single_register(addr, ISSI_REG_CONFIGURATION, ISSI_CONFIGURATION);
// Set Golbal Current Control Register
IS31FL_write_single_register(addr, ISSI_REG_GLOBALCURRENT, ISSI_GLOBALCURRENT);
// Set Pull up & Down for SWx CSy
IS31FL_write_single_register(addr, ISSI_REG_PULLDOWNUP, ISSI_PULLDOWNUP);
// Set Tempature Status
#ifdef ISSI_REG_TEMP
IS31FL_write_single_register(addr, ISSI_REG_TEMP, ISSI_TEMP);
#endif
// Set Spread Spectrum Register, passed through as sets SYNC function
IS31FL_write_single_register(addr, ISSI_REG_SSR, ssr);
// Set PWM Frequency Enable Register if applicable
#ifdef ISSI_REG_PWM_ENABLE
IS31FL_write_single_register(addr, ISSI_REG_PWM_ENABLE, ISSI_PWM_ENABLE);
#endif
// Set PWM Frequency Register if applicable
#ifdef ISSI_REG_PWM_SET
IS31FL_write_single_register(addr, ISSI_REG_PWM_SET, ISSI_PWM_SET);
#endif
// Wait 10ms to ensure the device has woken up.
wait_ms(10);
}
void IS31FL_common_update_pwm_register(uint8_t addr, uint8_t index) {
if (g_pwm_buffer_update_required[index]) {
// Queue up the correct page
IS31FL_unlock_register(addr, ISSI_PAGE_PWM);
// Hand off the update to IS31FL_write_multi_registers
IS31FL_write_multi_registers(addr, g_pwm_buffer[index], ISSI_MAX_LEDS, ISSI_PWM_TRF_SIZE, ISSI_PWM_REG_1ST);
// Update flags that pwm_buffer has been updated
g_pwm_buffer_update_required[index] = false;
}
}
#ifdef ISSI_MANUAL_SCALING
void IS31FL_set_manual_scaling_buffer(void) {
for (int i = 0; i < ISSI_MANUAL_SCALING; i++) {
is31_led scale = g_is31_scaling[i];
if (scale.driver >= 0 && scale.driver < DRIVER_LED_TOTAL) {
is31_led led = g_is31_leds[scale.driver];
# ifdef RGB_MATRIX_ENABLE
g_scaling_buffer[led.driver][led.r] = scale.r;
g_scaling_buffer[led.driver][led.g] = scale.g;
g_scaling_buffer[led.driver][led.b] = scale.b;
# elif defined(LED_MATRIX_ENABLE)
g_scaling_buffer[led.driver][led.v] = scale.v;
# endif
g_scaling_buffer_update_required[led.driver] = true;
}
}
}
#endif
void IS31FL_common_update_scaling_register(uint8_t addr, uint8_t index) {
if (g_scaling_buffer_update_required[index]) {
// Queue up the correct page
IS31FL_unlock_register(addr, ISSI_PAGE_SCALING);
// Hand off the update to IS31FL_write_multi_registers
IS31FL_write_multi_registers(addr, g_scaling_buffer[index], ISSI_SCALING_SIZE, ISSI_SCALING_TRF_SIZE, ISSI_SCL_REG_1ST);
// Update flags that scaling_buffer has been updated
g_scaling_buffer_update_required[index] = false;
}
}
#ifdef RGB_MATRIX_ENABLE
// Colour is set by adjusting PWM register
void IS31FL_RGB_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index >= 0 && index < DRIVER_LED_TOTAL) {
is31_led led = g_is31_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 IS31FL_RGB_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
IS31FL_RGB_set_color(i, red, green, blue);
}
}
// Setup Scaling register that decides the peak current of each LED
void IS31FL_RGB_set_scaling_buffer(uint8_t index, bool red, bool green, bool blue) {
is31_led led = g_is31_leds[index];
if (red) {
g_scaling_buffer[led.driver][led.r] = ISSI_SCAL_RED;
} else {
g_scaling_buffer[led.driver][led.r] = ISSI_SCAL_RED_OFF;
}
if (green) {
g_scaling_buffer[led.driver][led.g] = ISSI_SCAL_GREEN;
} else {
g_scaling_buffer[led.driver][led.g] = ISSI_SCAL_GREEN_OFF;
}
if (blue) {
g_scaling_buffer[led.driver][led.b] = ISSI_SCAL_BLUE;
} else {
g_scaling_buffer[led.driver][led.b] = ISSI_SCAL_BLUE_OFF;
}
g_scaling_buffer_update_required[led.driver] = true;
}
#elif defined(LED_MATRIX_ENABLE)
// LED Matrix Specific scripts
void IS31FL_simple_set_scaling_buffer(uint8_t index, bool value) {
is31_led led = g_is31_leds[index];
if (value) {
g_scaling_buffer[led.driver][led.v] = ISSI_SCAL_LED;
} else {
g_scaling_buffer[led.driver][led.v] = ISSI_SCAL_LED_OFF;
}
g_scaling_buffer_update_required[led.driver] = true;
}
void IS31FL_simple_set_brightness(int index, uint8_t value) {
if (index >= 0 && index < DRIVER_LED_TOTAL) {
is31_led led = g_is31_leds[index];
g_pwm_buffer[led.driver][led.v] = value;
g_pwm_buffer_update_required[led.driver] = true;
}
}
void IS31FL_simple_set_brigntness_all(uint8_t value) {
for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
IS31FL_simple_set_brightness(i, value);
}
}
#endif

View File

@@ -0,0 +1,78 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
* Copyright 2020 MelGeek
* Copyright 2021 MasterSpoon
*
* 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"
// Which variant header file to use
#ifdef IS31FL3742A
# include "is31fl3742.h"
#elif defined(IS31FL3743A)
# include "is31fl3743.h"
#elif defined(IS31FL3745)
# include "is31fl3745.h"
#elif defined(IS31FL3746A)
# include "is31fl3746.h"
#endif
#ifdef RGB_MATRIX_ENABLE
typedef struct is31_led {
uint8_t driver;
uint8_t r;
uint8_t g;
uint8_t b;
} __attribute__((packed)) is31_led;
#elif defined(LED_MATRIX_ENABLE)
typedef struct is31_led {
uint8_t driver;
uint8_t v;
} __attribute__((packed)) is31_led;
#endif
#ifdef ISSI_MANUAL_SCALING
extern const is31_led __flash g_is31_scaling[];
void IS31FL_set_manual_scaling_buffer(void);
#endif
extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL_write_single_register(uint8_t addr, uint8_t reg, uint8_t data);
bool IS31FL_write_multi_registers(uint8_t addr, uint8_t *source_buffer, uint8_t buffer_size, uint8_t transfer_size, uint8_t start_reg_addr);
void IS31FL_unlock_register(uint8_t addr, uint8_t page);
void IS31FL_common_init(uint8_t addr, uint8_t ssr);
void IS31FL_common_update_pwm_register(uint8_t addr, uint8_t index);
void IS31FL_common_update_scaling_register(uint8_t addr, uint8_t index);
#ifdef RGB_MATRIX_ENABLE
// RGB Matrix Specific scripts
void IS31FL_RGB_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
void IS31FL_RGB_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
void IS31FL_RGB_set_scaling_buffer(uint8_t index, bool red, bool green, bool blue);
#elif defined(LED_MATRIX_ENABLE)
// LED Matrix Specific scripts
void IS31FL_simple_set_scaling_buffer(uint8_t index, bool value);
void IS31FL_simple_set_brightness(int index, uint8_t value);
void IS31FL_simple_set_brigntness_all(uint8_t value);
#endif

View File

@@ -34,16 +34,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define OLED_DISPLAY_HEIGHT 64 # define OLED_DISPLAY_HEIGHT 64
# endif # endif
# ifndef OLED_MATRIX_SIZE # ifndef OLED_MATRIX_SIZE
# define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 1024 (compile time mathed) # define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 1024 (compile time mathed)
# endif # endif
# ifndef OLED_BLOCK_TYPE # ifndef OLED_BLOCK_TYPE
# define OLED_BLOCK_TYPE uint16_t # define OLED_BLOCK_TYPE uint16_t
# endif # endif
# ifndef OLED_BLOCK_COUNT # ifndef OLED_BLOCK_COUNT
# define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 32 (compile time mathed) # define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 32 (compile time mathed)
# endif # endif
# ifndef OLED_BLOCK_SIZE # ifndef OLED_BLOCK_SIZE
# define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) # define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed)
# endif # endif
# ifndef OLED_COM_PINS # ifndef OLED_COM_PINS
# define OLED_COM_PINS COM_PINS_ALT # define OLED_COM_PINS COM_PINS_ALT
@@ -68,7 +68,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// If OLED_BLOCK_TYPE is uint8_t, these tables would look like: // If OLED_BLOCK_TYPE is uint8_t, these tables would look like:
// #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 } // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }
// #define OLED_TARGET_MAP { 56, 120, 48, 112, 40, 104, 32, 96, 24, 88, 16, 80, 8, 72, 0, 64 } // #define OLED_TARGET_MAP { 56, 120, 48, 112, 40, 104, 32, 96, 24, 88, 16, 80, 8, 72, 0, 64 }
#else // defined(OLED_DISPLAY_128X64) #else // defined(OLED_DISPLAY_128X64)
// Default 128x32 // Default 128x32
# ifndef OLED_DISPLAY_WIDTH # ifndef OLED_DISPLAY_WIDTH
# define OLED_DISPLAY_WIDTH 128 # define OLED_DISPLAY_WIDTH 128
@@ -77,16 +77,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define OLED_DISPLAY_HEIGHT 32 # define OLED_DISPLAY_HEIGHT 32
# endif # endif
# ifndef OLED_MATRIX_SIZE # ifndef OLED_MATRIX_SIZE
# define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 512 (compile time mathed) # define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 512 (compile time mathed)
# endif # endif
# ifndef OLED_BLOCK_TYPE # ifndef OLED_BLOCK_TYPE
# define OLED_BLOCK_TYPE uint16_t // Type to use for segmenting the oled display for smart rendering, use unsigned types only # define OLED_BLOCK_TYPE uint16_t // Type to use for segmenting the oled display for smart rendering, use unsigned types only
# endif # endif
# ifndef OLED_BLOCK_COUNT # ifndef OLED_BLOCK_COUNT
# define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 16 (compile time mathed) # define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 16 (compile time mathed)
# endif # endif
# ifndef OLED_BLOCK_SIZE # ifndef OLED_BLOCK_SIZE
# define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) # define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed)
# endif # endif
# ifndef OLED_COM_PINS # ifndef OLED_COM_PINS
# define OLED_COM_PINS COM_PINS_SEQ # define OLED_COM_PINS COM_PINS_SEQ
@@ -105,7 +105,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// If OLED_BLOCK_TYPE is uint8_t, these tables would look like: // If OLED_BLOCK_TYPE is uint8_t, these tables would look like:
// #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 }
// #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 }
#endif // defined(OLED_DISPLAY_CUSTOM) #endif // defined(OLED_DISPLAY_CUSTOM)
#if !defined(OLED_IC) #if !defined(OLED_IC)
# define OLED_IC OLED_IC_SSD1306 # define OLED_IC OLED_IC_SSD1306
@@ -180,7 +180,7 @@ typedef enum {
OLED_ROTATION_0 = 0, OLED_ROTATION_0 = 0,
OLED_ROTATION_90 = 1, OLED_ROTATION_90 = 1,
OLED_ROTATION_180 = 2, OLED_ROTATION_180 = 2,
OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180 OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180
} oled_rotation_t; } oled_rotation_t;
// Initialize the oled display, rotating the rendered output based on the define passed in. // Initialize the oled display, rotating the rendered output based on the define passed in.
@@ -262,7 +262,7 @@ void oled_write_raw_P(const char *data, uint16_t size);
# define oled_write_P(data, invert) oled_write(data, invert) # define oled_write_P(data, invert) oled_write(data, invert)
# define oled_write_ln_P(data, invert) oled_write(data, invert) # define oled_write_ln_P(data, invert) oled_write(data, invert)
# define oled_write_raw_P(data, size) oled_write_raw(data, size) # define oled_write_raw_P(data, size) oled_write_raw(data, size)
#endif // defined(__AVR__) #endif // defined(__AVR__)
// Can be used to manually turn on the screen if it is off // Can be used to manually turn on the screen if it is off
// Returns true if the screen was on or turns on // Returns true if the screen was on or turns on

View File

@@ -53,7 +53,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define PAGE_ADDR 0x22 #define PAGE_ADDR 0x22
#define PAM_SETCOLUMN_LSB 0x00 #define PAM_SETCOLUMN_LSB 0x00
#define PAM_SETCOLUMN_MSB 0x10 #define PAM_SETCOLUMN_MSB 0x10
#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 #define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
// Hardware Configuration Commands // Hardware Configuration Commands
#define DISPLAY_START_LINE 0x40 #define DISPLAY_START_LINE 0x40
@@ -97,9 +97,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define I2C_DATA 0x40 #define I2C_DATA 0x40
#if defined(__AVR__) #if defined(__AVR__)
# define I2C_TRANSMIT_P(data) i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT) # define I2C_TRANSMIT_P(data) i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT)
#else // defined(__AVR__) #else // defined(__AVR__)
# define I2C_TRANSMIT_P(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT) # define I2C_TRANSMIT_P(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT)
#endif // defined(__AVR__) #endif // defined(__AVR__)
#define I2C_TRANSMIT(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT) #define I2C_TRANSMIT(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT)
#define I2C_WRITE_REG(mode, data, size) i2c_writeReg((OLED_DISPLAY_ADDRESS << 1), mode, data, size, OLED_I2C_TIMEOUT) #define I2C_WRITE_REG(mode, data, size) i2c_writeReg((OLED_DISPLAY_ADDRESS << 1), mode, data, size, OLED_I2C_TIMEOUT)
@@ -119,7 +119,7 @@ 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;
uint8_t oled_scroll_speed = 0; // this holds the speed after being remapped to ssd1306 internal values uint8_t oled_scroll_speed = 0; // this holds the speed after being remapped to ssd1306 internal values
uint8_t oled_scroll_start = 0; uint8_t oled_scroll_start = 0;
uint8_t oled_scroll_end = 7; uint8_t oled_scroll_end = 7;
#if OLED_TIMEOUT > 0 #if OLED_TIMEOUT > 0
@@ -190,7 +190,7 @@ bool oled_init(oled_rotation_t rotation) {
#if (OLED_IC != OLED_IC_SH1106) #if (OLED_IC != OLED_IC_SH1106)
// MEMORY_MODE is unsupported on SH1106 (Page Addressing only) // MEMORY_MODE is unsupported on SH1106 (Page Addressing only)
MEMORY_MODE, MEMORY_MODE,
0x00, // Horizontal addressing mode 0x00, // Horizontal addressing mode
#endif #endif
}; };
if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) {
@@ -232,8 +232,12 @@ bool oled_init(oled_rotation_t rotation) {
return true; return true;
} }
__attribute__((weak)) oled_rotation_t oled_init_kb(oled_rotation_t rotation) { return rotation; } __attribute__((weak)) oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
__attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return rotation; } return rotation;
}
__attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) {
return rotation;
}
void oled_clear(void) { void oled_clear(void) {
memset(oled_buffer, 0, sizeof(oled_buffer)); memset(oled_buffer, 0, sizeof(oled_buffer));
@@ -306,9 +310,9 @@ void oled_render(void) {
// Set column & page position // Set column & page position
static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1}; static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1};
if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start
} else { } else {
calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start
} }
// Send column & page position // Send column & page position
@@ -368,7 +372,8 @@ void oled_advance_page(bool clearPageRemainder) {
remaining = remaining / OLED_FONT_WIDTH; remaining = remaining / OLED_FONT_WIDTH;
// Write empty character until next line // Write empty character until next line
while (remaining--) oled_write_char(' ', false); while (remaining--)
oled_write_char(' ', false);
} else { } else {
// Next page index out of bounds? // Next page index out of bounds?
if (index + remaining >= OLED_MATRIX_SIZE) { if (index + remaining >= OLED_MATRIX_SIZE) {
@@ -419,7 +424,7 @@ void oled_write_char(const char data, bool invert) {
_Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array"); _Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array");
// set the reder buffer data // set the reder buffer data
uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index
if (cast_data < OLED_FONT_START || cast_data > OLED_FONT_END) { if (cast_data < OLED_FONT_START || cast_data > OLED_FONT_END) {
memset(oled_cursor, 0x00, OLED_FONT_WIDTH); memset(oled_cursor, 0x00, OLED_FONT_WIDTH);
} else { } else {
@@ -545,7 +550,7 @@ void oled_write_raw_P(const char *data, uint16_t size) {
oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
} }
} }
#endif // defined(__AVR__) #endif // defined(__AVR__)
bool oled_on(void) { bool oled_on(void) {
if (!oled_initialized) { if (!oled_initialized) {
@@ -595,7 +600,9 @@ bool oled_off(void) {
return !oled_active; return !oled_active;
} }
bool is_oled_on(void) { return oled_active; } bool is_oled_on(void) {
return oled_active;
}
uint8_t oled_set_brightness(uint8_t level) { uint8_t oled_set_brightness(uint8_t level) {
if (!oled_initialized) { if (!oled_initialized) {
@@ -613,7 +620,9 @@ uint8_t oled_set_brightness(uint8_t level) {
return oled_brightness; return oled_brightness;
} }
uint8_t oled_get_brightness(void) { return oled_brightness; } uint8_t oled_get_brightness(void) {
return oled_brightness;
}
// Set the specific 8 lines rows of the screen to scroll. // Set the specific 8 lines rows of the screen to scroll.
// 0 is the default for start, and 7 for end, which is the entire // 0 is the default for start, and 7 for end, which is the entire
@@ -693,7 +702,9 @@ bool oled_scroll_off(void) {
return !oled_scrolling; return !oled_scrolling;
} }
bool is_oled_scrolling(void) { return oled_scrolling; } bool is_oled_scrolling(void) {
return oled_scrolling;
}
bool oled_invert(bool invert) { bool oled_invert(bool invert) {
if (!oled_initialized) { if (!oled_initialized) {
@@ -777,5 +788,9 @@ void oled_task(void) {
#endif #endif
} }
__attribute__((weak)) bool oled_task_kb(void) { return oled_task_user(); } __attribute__((weak)) bool oled_task_kb(void) {
__attribute__((weak)) bool oled_task_user(void) { return true; } return oled_task_user();
}
__attribute__((weak)) bool oled_task_user(void) {
return true;
}

View File

@@ -71,12 +71,12 @@ uint8_t ps2_host_send(uint8_t data) {
/* terminate a transmission if we have */ /* terminate a transmission if we have */
inhibit(); inhibit();
wait_us(100); // 100us [4]p.13, [5]p.50 wait_us(100); // 100us [4]p.13, [5]p.50
/* 'Request to Send' and Start bit */ /* 'Request to Send' and Start bit */
data_lo(); data_lo();
clock_hi(); clock_hi();
WAIT(clock_lo, 10000, 10); // 10ms [5]p.50 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
/* Data bit */ /* Data bit */
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
@@ -125,11 +125,10 @@ uint8_t ps2_host_recv_response(void) {
// Command may take 25ms/20ms at most([5]p.46, [3]p.21) // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
// 250 * 100us(wait for start bit in ps2_host_recv) // 250 * 100us(wait for start bit in ps2_host_recv)
uint8_t data = 0; uint8_t data = 0;
uint8_t try uint8_t try = 250;
= 250;
do { do {
data = ps2_host_recv(); data = ps2_host_recv();
} while (try --&&ps2_error); } while (try-- && ps2_error);
return data; return data;
} }
@@ -143,7 +142,7 @@ uint8_t ps2_host_recv(void) {
idle(); idle();
/* start bit [1] */ /* start bit [1] */
WAIT(clock_lo, 100, 1); // TODO: this is enough? WAIT(clock_lo, 100, 1); // TODO: this is enough?
WAIT(data_lo, 1, 2); WAIT(data_lo, 1, 2);
WAIT(clock_hi, 50, 3); WAIT(clock_hi, 50, 3);

View File

@@ -43,7 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#if defined(__AVR__) #if defined(__AVR__)
# include <avr/interrupt.h> # include <avr/interrupt.h>
#elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ? #elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ?
// chibiOS headers // chibiOS headers
# include "ch.h" # include "ch.h"
# include "hal.h" # include "hal.h"
@@ -71,7 +71,9 @@ static inline void pbuf_clear(void);
#if defined(PROTOCOL_CHIBIOS) #if defined(PROTOCOL_CHIBIOS)
void ps2_interrupt_service_routine(void); void ps2_interrupt_service_routine(void);
void palCallback(void *arg) { ps2_interrupt_service_routine(); } void palCallback(void *arg) {
ps2_interrupt_service_routine();
}
# define PS2_INT_INIT() \ # define PS2_INT_INIT() \
{ palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT); } \ { palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT); } \
@@ -85,7 +87,7 @@ void palCallback(void *arg) { ps2_interrupt_service_routine(); }
# define PS2_INT_OFF() \ # define PS2_INT_OFF() \
{ palDisableLineEvent(PS2_CLOCK_PIN); } \ { palDisableLineEvent(PS2_CLOCK_PIN); } \
while (0) while (0)
#endif // PROTOCOL_CHIBIOS #endif // PROTOCOL_CHIBIOS
void ps2_host_init(void) { void ps2_host_init(void) {
idle(); idle();
@@ -103,12 +105,12 @@ uint8_t ps2_host_send(uint8_t data) {
/* terminate a transmission if we have */ /* terminate a transmission if we have */
inhibit(); inhibit();
wait_us(100); // 100us [4]p.13, [5]p.50 wait_us(100); // 100us [4]p.13, [5]p.50
/* 'Request to Send' and Start bit */ /* 'Request to Send' and Start bit */
data_lo(); data_lo();
clock_hi(); clock_hi();
WAIT(clock_lo, 10000, 10); // 10ms [5]p.50 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
/* Data bit[2-9] */ /* Data bit[2-9] */
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
@@ -244,7 +246,9 @@ RETURN:
} }
#if defined(__AVR__) #if defined(__AVR__)
ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); } ISR(PS2_INT_VECT) {
ps2_interrupt_service_routine();
}
#endif #endif
/* send LED state to keyboard */ /* send LED state to keyboard */

View File

@@ -42,7 +42,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report);
void ps2_mouse_init(void) { void ps2_mouse_init(void) {
ps2_host_init(); ps2_host_init();
wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up
PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset"); PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset");
@@ -113,9 +113,13 @@ void ps2_mouse_task(void) {
ps2_mouse_clear_report(&mouse_report); ps2_mouse_clear_report(&mouse_report);
} }
void ps2_mouse_disable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); } void ps2_mouse_disable_data_reporting(void) {
PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting");
}
void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); } void ps2_mouse_enable_data_reporting(void) {
PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting");
}
void ps2_mouse_set_remote_mode(void) { void ps2_mouse_set_remote_mode(void) {
PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode");
@@ -127,13 +131,21 @@ void ps2_mouse_set_stream_mode(void) {
ps2_mouse_mode = PS2_MOUSE_STREAM_MODE; ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
} }
void ps2_mouse_set_scaling_2_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); } void ps2_mouse_set_scaling_2_1(void) {
PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1");
}
void ps2_mouse_set_scaling_1_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); } void ps2_mouse_set_scaling_1_1(void) {
PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1");
}
void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution"); } void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) {
PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution");
}
void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_SAMPLE_RATE, sample_rate, "ps2 mouse set sample rate"); } void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) {
PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_SAMPLE_RATE, sample_rate, "ps2 mouse set sample rate");
}
/* ============================= HELPERS ============================ */ /* ============================= HELPERS ============================ */
@@ -165,7 +177,7 @@ static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report)
#ifdef PS2_MOUSE_INVERT_X #ifdef PS2_MOUSE_INVERT_X
mouse_report->x = -mouse_report->x; mouse_report->x = -mouse_report->x;
#endif #endif
#ifndef PS2_MOUSE_INVERT_Y // NOTE if not! #ifndef PS2_MOUSE_INVERT_Y // NOTE if not!
// invert coordinate of y to conform to USB HID mouse // invert coordinate of y to conform to USB HID mouse
mouse_report->y = -mouse_report->y; mouse_report->y = -mouse_report->y;
#endif #endif

View File

@@ -74,9 +74,13 @@ void adns5050_sync(void) {
writePinHigh(ADNS5050_CS_PIN); writePinHigh(ADNS5050_CS_PIN);
} }
void adns5050_cs_select(void) { writePinLow(ADNS5050_CS_PIN); } void adns5050_cs_select(void) {
writePinLow(ADNS5050_CS_PIN);
}
void adns5050_cs_deselect(void) { writePinHigh(ADNS5050_CS_PIN); } void adns5050_cs_deselect(void) {
writePinHigh(ADNS5050_CS_PIN);
}
uint8_t adns5050_serial_read(void) { uint8_t adns5050_serial_read(void) {
setPinInput(ADNS5050_SDIO_PIN); setPinInput(ADNS5050_SDIO_PIN);
@@ -190,7 +194,7 @@ int8_t convert_twoscomp(uint8_t data) {
// Don't forget to use the definitions for CPI in the header file. // Don't forget to use the definitions for CPI in the header file.
void adns5050_set_cpi(uint16_t cpi) { void adns5050_set_cpi(uint16_t cpi) {
uint8_t cpival = constrain((cpi / 125), 0x1, 0xD); // limits to 0--119 uint8_t cpival = constrain((cpi / 125), 0x1, 0xD); // limits to 0--119
adns5050_write_reg(REG_MOUSE_CONTROL2, 0b10000 | cpival); adns5050_write_reg(REG_MOUSE_CONTROL2, 0b10000 | cpival);
} }

View File

@@ -77,7 +77,9 @@
#define MSB1 0x80 #define MSB1 0x80
// clang-format on // clang-format on
void adns9800_spi_start(void) { spi_start(ADNS9800_CS_PIN, false, ADNS9800_SPI_MODE, ADNS9800_SPI_DIVISOR); } void adns9800_spi_start(void) {
spi_start(ADNS9800_CS_PIN, false, ADNS9800_SPI_MODE, ADNS9800_SPI_DIVISOR);
}
void adns9800_write(uint8_t reg_addr, uint8_t data) { void adns9800_write(uint8_t reg_addr, uint8_t data) {
adns9800_spi_start(); adns9800_spi_start();
@@ -135,10 +137,8 @@ void adns9800_init() {
wait_us(15); wait_us(15);
// send all bytes of the firmware // send all bytes of the firmware
unsigned char c; for (uint16_t i = 0; i < FIRMWARE_LENGTH; i++) {
for (int i = 0; i < FIRMWARE_LENGTH; i++) { spi_write(pgm_read_byte(firmware_data + i));
c = (unsigned char)pgm_read_byte(adns9800_firmware_data + i);
spi_write(c);
wait_us(15); wait_us(15);
} }
@@ -154,8 +154,8 @@ void adns9800_init() {
} }
config_adns9800_t adns9800_get_config(void) { config_adns9800_t adns9800_get_config(void) {
uint8_t config_1 = adns9800_read(REG_Configuration_I); uint8_t cpival = adns9800_read(REG_Configuration_I);
return (config_adns9800_t){(config_1 & 0xFF) * CPI_STEP}; return (config_adns9800_t){(cpival & 0xFF) * CPI_STEP};
} }
void adns9800_set_config(config_adns9800_t config) { void adns9800_set_config(config_adns9800_t config) {
@@ -164,8 +164,8 @@ void adns9800_set_config(config_adns9800_t config) {
} }
uint16_t adns9800_get_cpi(void) { uint16_t adns9800_get_cpi(void) {
uint8_t config_1 = adns9800_read(REG_Configuration_I); uint8_t cpival = adns9800_read(REG_Configuration_I);
return (uint16_t){(config_1 & 0xFF) * CPI_STEP}; return (uint16_t)(cpival & 0xFF) * CPI_STEP;
} }
void adns9800_set_cpi(uint16_t cpi) { void adns9800_set_cpi(uint16_t cpi) {
@@ -184,7 +184,7 @@ static int16_t convertDeltaToInt(uint8_t high, uint8_t low) {
} }
report_adns9800_t adns9800_get_report(void) { report_adns9800_t adns9800_get_report(void) {
report_adns9800_t report = {0, 0}; report_adns9800_t report = {0};
adns9800_spi_start(); adns9800_spi_start();

View File

@@ -6,7 +6,7 @@
// clang-format off // clang-format off
const uint8_t adns9800_firmware_data[FIRMWARE_LENGTH] PROGMEM = { const uint8_t firmware_data[FIRMWARE_LENGTH] PROGMEM = {
0x03, 0xA6, 0x68, 0x1E, 0x7D, 0x10, 0x7E, 0x7E, 0x5F, 0x1C, 0xB8, 0xF2, 0x47, 0x0C, 0x7B, 0x74, 0x03, 0xA6, 0x68, 0x1E, 0x7D, 0x10, 0x7E, 0x7E, 0x5F, 0x1C, 0xB8, 0xF2, 0x47, 0x0C, 0x7B, 0x74,
0x4B, 0x14, 0x8B, 0x75, 0x66, 0x51, 0x0B, 0x8C, 0x76, 0x74, 0x4B, 0x14, 0xAA, 0xD6, 0x0F, 0x9C, 0x4B, 0x14, 0x8B, 0x75, 0x66, 0x51, 0x0B, 0x8C, 0x76, 0x74, 0x4B, 0x14, 0xAA, 0xD6, 0x0F, 0x9C,
0xBA, 0xF6, 0x6E, 0x3F, 0xDD, 0x38, 0xD5, 0x02, 0x80, 0x9B, 0x82, 0x6D, 0x58, 0x13, 0xA4, 0xAB, 0xBA, 0xF6, 0x6E, 0x3F, 0xDD, 0x38, 0xD5, 0x02, 0x80, 0x9B, 0x82, 0x6D, 0x58, 0x13, 0xA4, 0xAB,

View File

@@ -18,19 +18,21 @@
#include "analog.h" #include "analog.h"
#include "gpio.h" #include "gpio.h"
#include "wait.h" #include "wait.h"
#include "timer.h"
#include <stdlib.h>
// Set Parameters // Set Parameters
uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN; uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX; uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX; uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
int16_t xOrigin, yOrigin; int16_t xOrigin, yOrigin;
uint16_t lastCursor = 0; uint16_t lastCursor = 0;
int16_t axisCoordinate(uint8_t pin, uint16_t origin) { int16_t axisCoordinate(pin_t pin, uint16_t origin) {
int8_t direction; int8_t direction;
int16_t distanceFromOrigin; int16_t distanceFromOrigin;
int16_t range; int16_t range;
@@ -60,7 +62,7 @@ int16_t axisCoordinate(uint8_t pin, uint16_t origin) {
} }
} }
int8_t axisToMouseComponent(uint8_t pin, int16_t origin, uint8_t maxSpeed) { int8_t axisToMouseComponent(pin_t pin, int16_t origin, uint8_t maxSpeed) {
int16_t coordinate = axisCoordinate(pin, origin); int16_t coordinate = axisCoordinate(pin, origin);
if (coordinate != 0) { if (coordinate != 0) {
float percent = (float)coordinate / 100; float percent = (float)coordinate / 100;

View File

@@ -54,7 +54,9 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count);
void RAP_Write(uint8_t address, uint8_t data); void RAP_Write(uint8_t address, uint8_t data);
#ifdef CONSOLE_ENABLE #ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte) { xprintf("%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')); } void print_byte(uint8_t byte) {
xprintf("%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 #endif
/* Logical Scaling Functions */ /* Logical Scaling Functions */
@@ -73,8 +75,12 @@ void ClipCoordinates(pinnacle_data_t* coordinates) {
} }
} }
uint16_t cirque_pinnacle_get_scale(void) { return scale_data; } uint16_t cirque_pinnacle_get_scale(void) {
void cirque_pinnacle_set_scale(uint16_t scale) { scale_data = scale; } return scale_data;
}
void cirque_pinnacle_set_scale(uint16_t scale) {
scale_data = scale;
}
// Scales data to desired X & Y resolution // Scales data to desired X & Y resolution
void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution) { void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution) {
@@ -105,13 +111,13 @@ void cirque_pinnacle_clear_flags() {
void cirque_pinnacle_enable_feed(bool feedEnable) { void cirque_pinnacle_enable_feed(bool feedEnable) {
uint8_t temp; uint8_t temp;
RAP_ReadBytes(FEEDCONFIG_1, &temp, 1); // Store contents of FeedConfig1 register RAP_ReadBytes(FEEDCONFIG_1, &temp, 1); // Store contents of FeedConfig1 register
if (feedEnable) { if (feedEnable) {
temp |= 0x01; // Set Feed Enable bit temp |= 0x01; // Set Feed Enable bit
RAP_Write(0x04, temp); RAP_Write(0x04, temp);
} else { } else {
temp &= ~0x01; // Clear Feed Enable bit temp &= ~0x01; // Clear Feed Enable bit
RAP_Write(0x04, temp); RAP_Write(0x04, temp);
} }
} }
@@ -122,13 +128,13 @@ void cirque_pinnacle_enable_feed(bool feedEnable) {
void ERA_ReadBytes(uint16_t address, uint8_t* data, uint16_t count) { void ERA_ReadBytes(uint16_t address, uint8_t* data, uint16_t count) {
uint8_t ERAControlValue = 0xFF; uint8_t ERAControlValue = 0xFF;
cirque_pinnacle_enable_feed(false); // Disable feed cirque_pinnacle_enable_feed(false); // Disable feed
RAP_Write(ERA_HIGH_BYTE, (uint8_t)(address >> 8)); // Send upper byte of ERA address RAP_Write(ERA_HIGH_BYTE, (uint8_t)(address >> 8)); // Send upper byte of ERA address
RAP_Write(ERA_LOW_BYTE, (uint8_t)(address & 0x00FF)); // Send lower byte of ERA address RAP_Write(ERA_LOW_BYTE, (uint8_t)(address & 0x00FF)); // Send lower byte of ERA address
for (uint16_t i = 0; i < count; i++) { for (uint16_t i = 0; i < count; i++) {
RAP_Write(ERA_CONTROL, 0x05); // Signal ERA-read (auto-increment) to Pinnacle RAP_Write(ERA_CONTROL, 0x05); // Signal ERA-read (auto-increment) to Pinnacle
// Wait for status register 0x1E to clear // Wait for status register 0x1E to clear
do { do {
@@ -145,14 +151,14 @@ void ERA_ReadBytes(uint16_t address, uint8_t* data, uint16_t count) {
void ERA_WriteByte(uint16_t address, uint8_t data) { void ERA_WriteByte(uint16_t address, uint8_t data) {
uint8_t ERAControlValue = 0xFF; uint8_t ERAControlValue = 0xFF;
cirque_pinnacle_enable_feed(false); // Disable feed cirque_pinnacle_enable_feed(false); // Disable feed
RAP_Write(ERA_VALUE, data); // Send data byte to be written RAP_Write(ERA_VALUE, data); // Send data byte to be written
RAP_Write(ERA_HIGH_BYTE, (uint8_t)(address >> 8)); // Upper byte of ERA address RAP_Write(ERA_HIGH_BYTE, (uint8_t)(address >> 8)); // Upper byte of ERA address
RAP_Write(ERA_LOW_BYTE, (uint8_t)(address & 0x00FF)); // Lower byte of ERA address RAP_Write(ERA_LOW_BYTE, (uint8_t)(address & 0x00FF)); // Lower byte of ERA address
RAP_Write(ERA_CONTROL, 0x02); // Signal an ERA-write to Pinnacle RAP_Write(ERA_CONTROL, 0x02); // Signal an ERA-write to Pinnacle
// Wait for status register 0x1E to clear // Wait for status register 0x1E to clear
do { do {
@@ -166,7 +172,7 @@ void cirque_pinnacle_set_adc_attenuation(uint8_t adcGain) {
uint8_t temp = 0x00; uint8_t temp = 0x00;
ERA_ReadBytes(0x0187, &temp, 1); ERA_ReadBytes(0x0187, &temp, 1);
temp &= 0x3F; // clear top two bits temp &= 0x3F; // clear top two bits
temp |= adcGain; temp |= adcGain;
ERA_WriteByte(0x0187, temp); ERA_WriteByte(0x0187, temp);
ERA_ReadBytes(0x0187, &temp, 1); ERA_ReadBytes(0x0187, &temp, 1);

View File

@@ -26,16 +26,16 @@ void cirque_pinnacle_set_scale(uint16_t scale);
// Coordinate scaling values // Coordinate scaling values
#ifndef CIRQUE_PINNACLE_X_LOWER #ifndef CIRQUE_PINNACLE_X_LOWER
# define CIRQUE_PINNACLE_X_LOWER 127 // min "reachable" X value # define CIRQUE_PINNACLE_X_LOWER 127 // min "reachable" X value
#endif #endif
#ifndef CIRQUE_PINNACLE_X_UPPER #ifndef CIRQUE_PINNACLE_X_UPPER
# define CIRQUE_PINNACLE_X_UPPER 1919 // max "reachable" X value # define CIRQUE_PINNACLE_X_UPPER 1919 // max "reachable" X value
#endif #endif
#ifndef CIRQUE_PINNACLE_Y_LOWER #ifndef CIRQUE_PINNACLE_Y_LOWER
# define CIRQUE_PINNACLE_Y_LOWER 63 // min "reachable" Y value # define CIRQUE_PINNACLE_Y_LOWER 63 // min "reachable" Y value
#endif #endif
#ifndef CIRQUE_PINNACLE_Y_UPPER #ifndef CIRQUE_PINNACLE_Y_UPPER
# define CIRQUE_PINNACLE_Y_UPPER 1471 // max "reachable" Y value # define CIRQUE_PINNACLE_Y_UPPER 1471 // max "reachable" Y value
#endif #endif
#ifndef CIRQUE_PINNACLE_X_RANGE #ifndef CIRQUE_PINNACLE_X_RANGE
# define CIRQUE_PINNACLE_X_RANGE (CIRQUE_PINNACLE_X_UPPER - CIRQUE_PINNACLE_X_LOWER) # define CIRQUE_PINNACLE_X_RANGE (CIRQUE_PINNACLE_X_UPPER - CIRQUE_PINNACLE_X_LOWER)

View File

@@ -14,7 +14,7 @@ extern bool touchpad_init;
/* RAP Functions */ /* RAP Functions */
// Reads <count> Pinnacle registers starting at <address> // Reads <count> Pinnacle registers starting at <address>
void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) { void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
uint8_t cmdByte = READ_MASK | address; // Form the READ command byte uint8_t cmdByte = READ_MASK | address; // Form the READ command byte
if (touchpad_init) { if (touchpad_init) {
i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, NULL, 0, CIRQUE_PINNACLE_TIMEOUT); i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, NULL, 0, CIRQUE_PINNACLE_TIMEOUT);
if (i2c_readReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, data, count, CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) { if (i2c_readReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, data, count, CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
@@ -29,7 +29,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
// Writes single-byte <data> to <address> // Writes single-byte <data> to <address>
void RAP_Write(uint8_t address, uint8_t data) { void RAP_Write(uint8_t address, uint8_t data) {
uint8_t cmdByte = WRITE_MASK | address; // Form the WRITE command byte uint8_t cmdByte = WRITE_MASK | address; // Form the WRITE command byte
if (touchpad_init) { if (touchpad_init) {
if (i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, &data, sizeof(data), CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) { if (i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, &data, sizeof(data), CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {

View File

@@ -13,14 +13,14 @@ extern bool touchpad_init;
/* RAP Functions */ /* RAP Functions */
// Reads <count> Pinnacle registers starting at <address> // Reads <count> Pinnacle registers starting at <address>
void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) { void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
uint8_t cmdByte = READ_MASK | address; // Form the READ command byte uint8_t cmdByte = READ_MASK | address; // Form the READ command byte
if (touchpad_init) { if (touchpad_init) {
if (spi_start(CIRQUE_PINNACLE_SPI_CS_PIN, CIRQUE_PINNACLE_SPI_LSBFIRST, CIRQUE_PINNACLE_SPI_MODE, CIRQUE_PINNACLE_SPI_DIVISOR)) { if (spi_start(CIRQUE_PINNACLE_SPI_CS_PIN, CIRQUE_PINNACLE_SPI_LSBFIRST, CIRQUE_PINNACLE_SPI_MODE, CIRQUE_PINNACLE_SPI_DIVISOR)) {
spi_write(cmdByte); spi_write(cmdByte);
spi_read(); // filler spi_read(); // filler
spi_read(); // filler spi_read(); // filler
for (uint8_t i = 0; i < count; i++) { for (uint8_t i = 0; i < count; i++) {
data[i] = spi_read(); // each sepsequent read gets another register's contents data[i] = spi_read(); // each sepsequent read gets another register's contents
} }
} else { } else {
#ifdef CONSOLE_ENABLE #ifdef CONSOLE_ENABLE
@@ -34,7 +34,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
// Writes single-byte <data> to <address> // Writes single-byte <data> to <address>
void RAP_Write(uint8_t address, uint8_t data) { void RAP_Write(uint8_t address, uint8_t data) {
uint8_t cmdByte = WRITE_MASK | address; // Form the WRITE command byte uint8_t cmdByte = WRITE_MASK | address; // Form the WRITE command byte
if (touchpad_init) { if (touchpad_init) {
if (spi_start(CIRQUE_PINNACLE_SPI_CS_PIN, CIRQUE_PINNACLE_SPI_LSBFIRST, CIRQUE_PINNACLE_SPI_MODE, CIRQUE_PINNACLE_SPI_DIVISOR)) { if (spi_start(CIRQUE_PINNACLE_SPI_CS_PIN, CIRQUE_PINNACLE_SPI_LSBFIRST, CIRQUE_PINNACLE_SPI_MODE, CIRQUE_PINNACLE_SPI_DIVISOR)) {

View File

@@ -33,8 +33,26 @@
static uint16_t precision = 128; static uint16_t precision = 128;
float pimoroni_trackball_get_precision(void) { return ((float)precision / 128); } uint16_t pimoroni_trackball_get_cpi(void) {
void pimoroni_trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); } return (precision * 125);
}
/**
* @brief Sets the scaling value for pimoroni trackball
*
* Sets a scaling value for pimoroni trackball to allow runtime adjustment. This isn't used by the sensor and is an
* approximation so the functions are consistent across drivers.
*
* NOTE: This rounds down to the nearest number divisable by 125 that's a positive integer, values below 125 are clamped to 125.
*
* @param cpi uint16_t
*/
void pimoroni_trackball_set_cpi(uint16_t cpi) {
if (cpi < 249) {
precision = 1;
} else {
precision = (cpi - (cpi % 125)) / 125;
}
}
void pimoroni_trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { void pimoroni_trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
uint8_t data[4] = {r, g, b, w}; uint8_t data[4] = {r, g, b, w};
@@ -60,7 +78,7 @@ i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data) {
return status; return status;
} }
__attribute__((weak)) void pimironi_trackball_device_init(void) { __attribute__((weak)) void pimoroni_trackball_device_init(void) {
i2c_init(); i2c_init();
pimoroni_trackball_set_rgbw(0x00, 0x00, 0x00, 0x00); pimoroni_trackball_set_rgbw(0x00, 0x00, 0x00, 0x00);
} }

View File

@@ -23,9 +23,6 @@
#ifndef PIMORONI_TRACKBALL_ADDRESS #ifndef PIMORONI_TRACKBALL_ADDRESS
# define PIMORONI_TRACKBALL_ADDRESS 0x0A # define PIMORONI_TRACKBALL_ADDRESS 0x0A
#endif #endif
#ifndef PIMORONI_TRACKBALL_INTERVAL_MS
# define PIMORONI_TRACKBALL_INTERVAL_MS 8
#endif
#ifndef PIMORONI_TRACKBALL_SCALE #ifndef PIMORONI_TRACKBALL_SCALE
# define PIMORONI_TRACKBALL_SCALE 5 # define PIMORONI_TRACKBALL_SCALE 5
#endif #endif
@@ -52,10 +49,10 @@ typedef struct {
uint8_t click; uint8_t click;
} pimoroni_data_t; } pimoroni_data_t;
void pimironi_trackball_device_init(void); void pimoroni_trackball_device_init(void);
void pimoroni_trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white); void pimoroni_trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale); int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset); void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset);
float pimoroni_trackball_get_precision(void); uint16_t pimoroni_trackball_get_cpi(void);
void pimoroni_trackball_set_precision(float precision); void pimoroni_trackball_set_cpi(uint16_t cpi);
i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data); i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data);

View File

@@ -16,136 +16,126 @@
* 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 "spi_master.h"
#include "pmw3360.h" #include "pmw3360.h"
#include "wait.h" #include "wait.h"
#include "debug.h" #include "debug.h"
#include "print.h" #include "print.h"
#include PMW3360_FIRMWARE_H #include "pmw3360_firmware.h"
// Registers // Registers
// clang-format off // clang-format off
#define REG_Product_ID 0x00 #define REG_Product_ID 0x00
#define REG_Revision_ID 0x01 #define REG_Revision_ID 0x01
#define REG_Motion 0x02 #define REG_Motion 0x02
#define REG_Delta_X_L 0x03 #define REG_Delta_X_L 0x03
#define REG_Delta_X_H 0x04 #define REG_Delta_X_H 0x04
#define REG_Delta_Y_L 0x05 #define REG_Delta_Y_L 0x05
#define REG_Delta_Y_H 0x06 #define REG_Delta_Y_H 0x06
#define REG_SQUAL 0x07 #define REG_SQUAL 0x07
#define REG_Raw_Data_Sum 0x08 #define REG_Raw_Data_Sum 0x08
#define REG_Maximum_Raw_data 0x09 #define REG_Maximum_Raw_data 0x09
#define REG_Minimum_Raw_data 0x0A #define REG_Minimum_Raw_data 0x0a
#define REG_Shutter_Lower 0x0B #define REG_Shutter_Lower 0x0b
#define REG_Shutter_Upper 0x0C #define REG_Shutter_Upper 0x0c
#define REG_Control 0x0D #define REG_Control 0x0d
#define REG_Config1 0x0F #define REG_Config1 0x0f
#define REG_Config2 0x10 #define REG_Config2 0x10
#define REG_Angle_Tune 0x11 #define REG_Angle_Tune 0x11
#define REG_Frame_Capture 0x12 #define REG_Frame_Capture 0x12
#define REG_SROM_Enable 0x13 #define REG_SROM_Enable 0x13
#define REG_Run_Downshift 0x14 #define REG_Run_Downshift 0x14
#define REG_Rest1_Rate_Lower 0x15 #define REG_Rest1_Rate_Lower 0x15
#define REG_Rest1_Rate_Upper 0x16 #define REG_Rest1_Rate_Upper 0x16
#define REG_Rest1_Downshift 0x17 #define REG_Rest1_Downshift 0x17
#define REG_Rest2_Rate_Lower 0x18 #define REG_Rest2_Rate_Lower 0x18
#define REG_Rest2_Rate_Upper 0x19 #define REG_Rest2_Rate_Upper 0x19
#define REG_Rest2_Downshift 0x1A #define REG_Rest2_Downshift 0x1a
#define REG_Rest3_Rate_Lower 0x1B #define REG_Rest3_Rate_Lower 0x1b
#define REG_Rest3_Rate_Upper 0x1C #define REG_Rest3_Rate_Upper 0x1c
#define REG_Observation 0x24 #define REG_Observation 0x24
#define REG_Data_Out_Lower 0x25 #define REG_Data_Out_Lower 0x25
#define REG_Data_Out_Upper 0x26 #define REG_Data_Out_Upper 0x26
#define REG_Raw_Data_Dump 0x29 #define REG_Raw_Data_Dump 0x29
#define REG_SROM_ID 0x2A #define REG_SROM_ID 0x2a
#define REG_Min_SQ_Run 0x2B #define REG_Min_SQ_Run 0x2b
#define REG_Raw_Data_Threshold 0x2C #define REG_Raw_Data_Threshold 0x2c
#define REG_Config5 0x2F #define REG_Config5 0x2f
#define REG_Power_Up_Reset 0x3A #define REG_Power_Up_Reset 0x3a
#define REG_Shutdown 0x3B #define REG_Shutdown 0x3b
#define REG_Inverse_Product_ID 0x3F #define REG_Inverse_Product_ID 0x3f
#define REG_LiftCutoff_Tune3 0x41 #define REG_LiftCutoff_Tune3 0x41
#define REG_Angle_Snap 0x42 #define REG_Angle_Snap 0x42
#define REG_LiftCutoff_Tune1 0x4A #define REG_LiftCutoff_Tune1 0x4a
#define REG_Motion_Burst 0x50 #define REG_Motion_Burst 0x50
#define REG_LiftCutoff_Tune_Timeout 0x58 #define REG_LiftCutoff_Tune_Timeout 0x58
#define REG_LiftCutoff_Tune_Min_Length 0x5A #define REG_LiftCutoff_Tune_Min_Length 0x5a
#define REG_SROM_Load_Burst 0x62 #define REG_SROM_Load_Burst 0x62
#define REG_Lift_Config 0x63 #define REG_Lift_Config 0x63
#define REG_Raw_Data_Burst 0x64 #define REG_Raw_Data_Burst 0x64
#define REG_LiftCutoff_Tune2 0x65 #define REG_LiftCutoff_Tune2 0x65
#define CPI_STEP 100
// clang-format on // clang-format on
// limits to 0--119, resulting in a CPI range of 100 -- 12000 (as only steps of 100 are possible).
#ifndef MAX_CPI #ifndef MAX_CPI
# define MAX_CPI 0x77 // limits to 0--119, should be max cpi/100 # define MAX_CPI 0x77
#endif #endif
bool _inBurst = false; bool _inBurst = false;
#ifdef CONSOLE_ENABLE #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')); } 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 #endif
#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) #define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
bool spi_start_adv(void) { bool pmw3360_spi_start(void) {
bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR); bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR);
// tNCS-SCLK, 120ns
wait_us(1); wait_us(1);
return status; return status;
} }
void spi_stop_adv(void) { spi_status_t pmw3360_write(uint8_t reg_addr, uint8_t data) {
wait_us(1); pmw3360_spi_start();
spi_stop();
}
spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
if (reg_addr != REG_Motion_Burst) { if (reg_addr != REG_Motion_Burst) {
_inBurst = false; _inBurst = false;
} }
spi_start_adv();
// send address of the register, with MSBit = 1 to indicate it's a write // send address of the register, with MSBit = 1 to indicate it's a write
spi_status_t status = spi_write(reg_addr | 0x80); spi_status_t status = spi_write(reg_addr | 0x80);
status = spi_write(data); status = spi_write(data);
// tSCLK-NCS for write operation // tSCLK-NCS for write operation is 35us
wait_us(20); wait_us(35);
// tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
wait_us(100);
spi_stop(); spi_stop();
// tSWW/tSWR (=180us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
wait_us(145);
return status; return status;
} }
uint8_t spi_read_adv(uint8_t reg_addr) { uint8_t pmw3360_read(uint8_t reg_addr) {
spi_start_adv(); pmw3360_spi_start();
// send adress of the register, with MSBit = 0 to indicate it's a read // send adress of the register, with MSBit = 0 to indicate it's a read
spi_write(reg_addr & 0x7f); spi_write(reg_addr & 0x7f);
// tSRAD (=160us)
wait_us(160);
uint8_t data = spi_read(); uint8_t data = spi_read();
// tSCLK-NCS for read operation is 120ns // tSCLK-NCS for read operation is 120ns
wait_us(1); wait_us(1);
spi_stop();
// tSRW/tSRR (=20us) minus tSCLK-NCS // tSRW/tSRR (=20us) minus tSCLK-NCS
wait_us(19); wait_us(19);
spi_stop();
return data; return data;
} }
void pmw3360_set_cpi(uint16_t cpi) {
uint8_t cpival = constrain((cpi / 100) - 1, 0, MAX_CPI);
spi_start_adv();
spi_write_adv(REG_Config1, cpival);
spi_stop();
}
uint16_t pmw3360_get_cpi(void) {
uint8_t cpival = spi_read_adv(REG_Config1);
return (uint16_t)((cpival + 1) & 0xFF) * 100;
}
bool pmw3360_init(void) { bool pmw3360_init(void) {
setPinOutput(PMW3360_CS_PIN); setPinOutput(PMW3360_CS_PIN);
@@ -153,42 +143,51 @@ bool pmw3360_init(void) {
_inBurst = false; _inBurst = false;
spi_stop(); spi_stop();
spi_start_adv(); pmw3360_spi_start();
spi_stop(); spi_stop();
spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first pmw3360_write(REG_Shutdown, 0xb6); // Shutdown first
wait_ms(300); wait_ms(300);
spi_start_adv(); pmw3360_spi_start();
wait_us(40); wait_us(40);
spi_stop_adv(); spi_stop();
wait_us(40); wait_us(40);
spi_write_adv(REG_Power_Up_Reset, 0x5a); // power up, need to first drive NCS high then low, see above.
pmw3360_write(REG_Power_Up_Reset, 0x5a);
wait_ms(50); wait_ms(50);
spi_read_adv(REG_Motion); // read registers and discard
spi_read_adv(REG_Delta_X_L); pmw3360_read(REG_Motion);
spi_read_adv(REG_Delta_X_H); pmw3360_read(REG_Delta_X_L);
spi_read_adv(REG_Delta_Y_L); pmw3360_read(REG_Delta_X_H);
spi_read_adv(REG_Delta_Y_H); pmw3360_read(REG_Delta_Y_L);
pmw3360_read(REG_Delta_Y_H);
pmw3360_upload_firmware(); pmw3360_upload_firmware();
spi_stop_adv(); spi_stop();
wait_ms(10); wait_ms(10);
pmw3360_set_cpi(PMW3360_CPI); pmw3360_set_cpi(PMW3360_CPI);
wait_ms(1); wait_ms(1);
spi_write_adv(REG_Config2, 0x00); pmw3360_write(REG_Config2, 0x00);
spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30)); pmw3360_write(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -127, 127));
spi_write_adv(REG_Lift_Config, PMW3360_LIFTOFF_DISTANCE); pmw3360_write(REG_Lift_Config, PMW3360_LIFTOFF_DISTANCE);
bool init_success = pmw3360_check_signature(); bool init_success = pmw3360_check_signature();
#ifdef CONSOLE_ENABLE
if (init_success) {
dprintf("pmw3360 signature verified");
} else {
dprintf("pmw3360 signature verification failed!");
}
#endif
writePinLow(PMW3360_CS_PIN); writePinLow(PMW3360_CS_PIN);
@@ -196,86 +195,94 @@ bool pmw3360_init(void) {
} }
void pmw3360_upload_firmware(void) { void pmw3360_upload_firmware(void) {
spi_write_adv(REG_SROM_Enable, 0x1d); // Datasheet claims we need to disable REST mode first, but during startup
// it's already disabled and we're not turning it on ...
// pmw3360_write(REG_Config2, 0x00); // disable REST mode
pmw3360_write(REG_SROM_Enable, 0x1d);
wait_ms(10); wait_ms(10);
spi_write_adv(REG_SROM_Enable, 0x18); pmw3360_write(REG_SROM_Enable, 0x18);
spi_start_adv(); pmw3360_spi_start();
spi_write(REG_SROM_Load_Burst | 0x80); spi_write(REG_SROM_Load_Burst | 0x80);
wait_us(15); wait_us(15);
unsigned char c; for (uint16_t i = 0; i < FIRMWARE_LENGTH; i++) {
for (int i = 0; i < FIRMWARE_LENGTH; i++) { spi_write(pgm_read_byte(firmware_data + i));
c = (unsigned char)pgm_read_byte(firmware_data + i); #ifndef PMW3360_FIRMWARE_UPLOAD_FAST
spi_write(c);
wait_us(15); wait_us(15);
#endif
} }
wait_us(200); wait_us(200);
spi_read_adv(REG_SROM_ID); pmw3360_read(REG_SROM_ID);
pmw3360_write(REG_Config2, 0x00);
spi_write_adv(REG_Config2, 0x00);
spi_stop();
wait_ms(10);
} }
bool pmw3360_check_signature(void) { bool pmw3360_check_signature(void) {
uint8_t pid = spi_read_adv(REG_Product_ID); uint8_t pid = pmw3360_read(REG_Product_ID);
uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID); uint8_t iv_pid = pmw3360_read(REG_Inverse_Product_ID);
uint8_t SROM_ver = spi_read_adv(REG_SROM_ID); uint8_t SROM_ver = pmw3360_read(REG_SROM_ID);
return (pid == firmware_signature[0] && iv_pid == firmware_signature[1] && SROM_ver == firmware_signature[2]); // signature for SROM 0x04 return (pid == firmware_signature[0] && iv_pid == firmware_signature[1] && SROM_ver == firmware_signature[2]); // signature for SROM 0x04
}
uint16_t pmw3360_get_cpi(void) {
uint8_t cpival = pmw3360_read(REG_Config1);
return (uint16_t)((cpival + 1) & 0xFF) * CPI_STEP;
}
void pmw3360_set_cpi(uint16_t cpi) {
uint8_t cpival = constrain((cpi / CPI_STEP) - 1, 0, MAX_CPI);
pmw3360_write(REG_Config1, cpival);
} }
report_pmw3360_t pmw3360_read_burst(void) { report_pmw3360_t pmw3360_read_burst(void) {
report_pmw3360_t report = {0};
if (!_inBurst) { if (!_inBurst) {
#ifdef CONSOLE_ENABLE #ifdef CONSOLE_ENABLE
dprintf("burst on"); dprintf("burst on");
#endif #endif
spi_write_adv(REG_Motion_Burst, 0x00); pmw3360_write(REG_Motion_Burst, 0x00);
_inBurst = true; _inBurst = true;
} }
spi_start_adv(); pmw3360_spi_start();
spi_write(REG_Motion_Burst); spi_write(REG_Motion_Burst);
wait_us(35); // waits for tSRAD wait_us(35); // waits for tSRAD_MOTBR
report_pmw3360_t data = {0}; report.motion = spi_read();
spi_read(); // skip Observation
// delta registers
report.dx = spi_read();
report.mdx = spi_read();
report.dy = spi_read();
report.mdy = spi_read();
data.motion = spi_read(); if (report.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
spi_write(0x00); // skip Observation _inBurst = false;
data.dx = spi_read(); }
data.mdx = spi_read();
data.dy = spi_read();
data.mdy = spi_read();
spi_stop(); spi_stop();
#ifdef CONSOLE_ENABLE #ifdef CONSOLE_ENABLE
if (debug_mouse) { if (debug_mouse) {
print_byte(data.motion); print_byte(report.motion);
print_byte(data.dx); print_byte(report.dx);
print_byte(data.mdx); print_byte(report.mdx);
print_byte(data.dy); print_byte(report.dy);
print_byte(data.mdy); print_byte(report.mdy);
dprintf("\n"); dprintf("\n");
} }
#endif #endif
data.isMotion = (data.motion & 0x80) != 0; report.isMotion = (report.motion & 0x80) != 0;
data.isOnSurface = (data.motion & 0x08) == 0; report.isOnSurface = (report.motion & 0x08) == 0;
data.dx |= (data.mdx << 8); report.dx |= (report.mdx << 8);
data.dx = data.dx * -1; report.dx = report.dx * -1;
data.dy |= (data.mdy << 8); report.dy |= (report.mdy << 8);
data.dy = data.dy * -1; report.dy = report.dy * -1;
spi_stop(); return report;
if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
_inBurst = false;
}
return data;
} }

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