diff options
Diffstat (limited to 'tmk_core')
92 files changed, 1649 insertions, 6467 deletions
| diff --git a/tmk_core/arm_atsam.mk b/tmk_core/arm_atsam.mk index b29de9132b..b49bf764d7 100644 --- a/tmk_core/arm_atsam.mk +++ b/tmk_core/arm_atsam.mk @@ -2,7 +2,7 @@  ##############################################################################  # Compiler settings  # -CC = arm-none-eabi-gcc +CC = $(CC_PREFIX) arm-none-eabi-gcc  OBJCOPY = arm-none-eabi-objcopy  OBJDUMP = arm-none-eabi-objdump  SIZE = arm-none-eabi-size diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index 940e95397b..c52262273e 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -2,7 +2,7 @@  ##############################################################################  # Compiler settings  # -CC = avr-gcc +CC = $(CC_PREFIX) avr-gcc  OBJCOPY = avr-objcopy  OBJDUMP = avr-objdump  SIZE = avr-size diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 18839710be..6b298732c2 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -27,29 +27,76 @@ endif  OPT_OS = chibios  CHIBIOS = $(TOP_DIR)/lib/chibios  CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib -# Startup files. Try a few different locations, for compability with old versions and -# for things hardware in the contrib repository -STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk -ifeq ("$(wildcard $(STARTUP_MK))","") -	STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk -	ifeq ("$(wildcard $(STARTUP_MK))","") -		STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk -	endif + +# +# Startup, Port and Platform support selection +############################################################################## + +ifeq ($(strip $(MCU)), risc-v) +    # RISC-V Support +    # As of 7.4.2021 there is only one supported RISC-V platform in Chibios-Contrib, +    # therefore all required settings are hard-coded +    STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/startup_$(MCU_STARTUP).mk +    PORT_V = $(CHIBIOS_CONTRIB)/os/common/ports/RISCV-ECLIC/compilers/GCC/mk/port.mk +    RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC +    PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/GD/GD32VF103/platform.mk +else +    # ARM Support +    CHIBIOS_PORT ?= +    ifeq ("$(CHIBIOS_PORT)","") +        CHIBIOS_PORT = ARMv$(ARMV)-M +    endif + +    # Startup files. Try a few different locations, for compability with old versions and +    # for things hardware in the contrib repository +    STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk +    ifeq ("$(wildcard $(STARTUP_MK))","") +        STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk +        ifeq ("$(wildcard $(STARTUP_MK))","") +            STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk +        endif +    endif + +    # Port files. Try a few different locations, for compability with old versions and +    # for things hardware in the contrib repository +    PORT_V = $(CHIBIOS)/os/common/ports/$(CHIBIOS_PORT)/compilers/GCC/mk/port.mk +    ifeq ("$(wildcard $(PORT_V))","") +        PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk +        ifeq ("$(wildcard $(PORT_V))","") +            PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk +        endif +    endif + +    # Rules location. Try a few different locations, for compability with old versions and +    # for things hardware in the contrib repository +    RULESPATH = $(CHIBIOS)/os/common/ports/$(CHIBIOS_PORT)/compilers/GCC +    ifeq ("$(wildcard $(RULESPATH)/rules.mk)","") +        RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC +        ifeq ("$(wildcard $(RULESPATH)/rules.mk)","") +            RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC +        endif +    endif  endif -include $(STARTUP_MK) -# HAL-OSAL files (optional). -include $(CHIBIOS)/os/hal/hal.mk  ifeq ("$(PLATFORM_NAME)","") -	PLATFORM_NAME = platform +    PLATFORM_NAME = platform  endif -PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk  ifeq ("$(wildcard $(PLATFORM_MK))","") -PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk +    PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk +    ifeq ("$(wildcard $(PLATFORM_MK))","") +        PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk +    endif  endif + +include $(STARTUP_MK) +include $(PORT_V)  include $(PLATFORM_MK) +# +# Board support selection. +############################################################################## +  BOARD_MK :=  ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/board.mk)","") @@ -77,13 +124,19 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/board/board  endif  ifeq ("$(wildcard $(BOARD_MK))","") -	BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk -	ifeq ("$(wildcard $(BOARD_MK))","") -		BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk -	endif +    BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk +    ifeq ("$(wildcard $(BOARD_MK))","") +        BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk +    endif  endif -# Bootloader address +include $(BOARD_MK) + +# +# Bootloader selection. +############################################################################## + +# Set bootloader address if supplied.  ifdef STM32_BOOTLOADER_ADDRESS      OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)  endif @@ -113,6 +166,10 @@ else ifneq ("$(wildcard $(BOARD_PATH)/configs/bootloader_defs.h)","")      OPT_DEFS += -include $(BOARD_PATH)/configs/bootloader_defs.h  endif +# +# ChibiOS config selection. +############################################################################## +  # Work out the config file directories  ifneq ("$(wildcard $(KEYBOARD_PATH_5)/chconf.h)","")      CHCONFDIR = $(KEYBOARD_PATH_5) @@ -130,6 +187,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/boards/chibios/common/configs/chcon      CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs  endif +# +# HAL config selection. +############################################################################## +  ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","")      HALCONFDIR = $(KEYBOARD_PATH_5)  else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/halconf.h)","") @@ -146,40 +207,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/common/configs/halco      HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs  endif -# HAL-OSAL files (optional). -include $(CHIBIOS)/os/hal/hal.mk - -ifeq ("$(PLATFORM_NAME)","") -	PLATFORM_NAME = platform -endif - -PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk -ifeq ("$(wildcard $(PLATFORM_MK))","") -PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk -endif -include $(PLATFORM_MK) - - -include $(BOARD_MK) --include $(CHIBIOS)/os/hal/osal/rt/osal.mk         # ChibiOS <= 19.x --include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk     # ChibiOS >= 20.x -# RTOS files (optional). -include $(CHIBIOS)/os/rt/rt.mk -# Compability with old version -PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk -ifeq ("$(wildcard $(PORT_V))","") -PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk -endif -include $(PORT_V) -# Other files (optional). -include $(CHIBIOS)/os/hal/lib/streams/streams.mk - -RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC -ifeq ("$(wildcard $(RULESPATH)/rules.mk)","") -RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC -endif +# +# Linker script selection. +############################################################################## -# Define linker script file here  ifneq ("$(wildcard $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld)","")      LDSCRIPT = $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld  else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/ld/$(MCU_LDSCRIPT).ld)","") @@ -202,22 +233,36 @@ else      LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld  endif -CHIBISRC = $(STARTUPSRC) \ -       $(KERNSRC) \ -       $(PORTSRC) \ -       $(OSALSRC) \ -       $(HALSRC) \ -       $(PLATFORMSRC) \ -       $(BOARDSRC) \ -       $(STREAMSSRC) \ -       $(CHIBIOS)/os/various/syscalls.c \ -       $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \ -       $(PLATFORM_COMMON_DIR)/wait.c +# +# Include ChibiOS makefiles. +############################################################################## + +# HAL-OSAL files (optional). +include $(CHIBIOS)/os/hal/hal.mk +-include $(CHIBIOS)/os/hal/osal/rt/osal.mk         # ChibiOS <= 19.x +-include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk     # ChibiOS >= 20.x +# RTOS files (optional). +include $(CHIBIOS)/os/rt/rt.mk +# Other files (optional). +include $(CHIBIOS)/os/hal/lib/streams/streams.mk + +PLATFORM_SRC = \ +        $(STARTUPSRC) \ +        $(KERNSRC) \ +        $(PORTSRC) \ +        $(OSALSRC) \ +        $(HALSRC) \ +        $(PLATFORMSRC) \ +        $(BOARDSRC) \ +        $(STREAMSSRC) \ +        $(CHIBIOS)/os/various/syscalls.c \ +        $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \ +        $(PLATFORM_COMMON_DIR)/wait.c  # Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise.  QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) -CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC)) +PLATFORM_SRC := $(patsubst $(TOP_DIR)/%,%,$(PLATFORM_SRC))  EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \           $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs \ @@ -247,9 +292,9 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/hal  endif  ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes) -	include $(CHIBIOS_CONTRIB)/os/hal/hal.mk -	CHIBISRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB) -	EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various +    include $(CHIBIOS_CONTRIB)/os/hal/hal.mk +    PLATFORM_SRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB) +    EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various  endif  # @@ -267,61 +312,120 @@ ifneq ("$(wildcard $(BOARD_PATH)/configs/post_config.h)","")  endif  ############################################################################## -# Compiler settings +# Compiler and Linker configuration  # -CC = arm-none-eabi-gcc -OBJCOPY = arm-none-eabi-objcopy -OBJDUMP = arm-none-eabi-objdump -SIZE = arm-none-eabi-size -AR = arm-none-eabi-ar -NM = arm-none-eabi-nm -HEX = $(OBJCOPY) -O $(FORMAT) -EEP = -BIN = $(OBJCOPY) -O binary - -THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB - -COMPILEFLAGS += -fomit-frame-pointer -COMPILEFLAGS += -falign-functions=16 -COMPILEFLAGS += -ffunction-sections -COMPILEFLAGS += -fdata-sections -COMPILEFLAGS += -fno-common -COMPILEFLAGS += -fshort-wchar -COMPILEFLAGS += $(THUMBFLAGS) - -# FPU options default (Cortex-M4 and Cortex-M7 single precision). -USE_FPU_OPT ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant - -# FPU-related options -USE_FPU ?= no -ifneq ($(USE_FPU),no) -  COMPILEFLAGS += $(USE_FPU_OPT) -  OPT_DEFS += -DCORTEX_USE_FPU=TRUE + +# Use defined stack sizes of the main thread in linker scripts +LDSYMBOLS =--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE) + +# Shared Compiler flags for all toolchains +SHARED_CFLAGS = -fomit-frame-pointer \ +                -ffunction-sections \ +                -fdata-sections \ +                -fno-common \ +                -fshort-wchar + +# Shared Linker flags for all toolchains +SHARED_LDFLAGS = -T $(LDSCRIPT) \ +                 -Wl,$(LDSYMBOLS) \ +                 -Wl,--gc-sections \ +                 -nostartfiles + +ifeq ($(strip $(MCU)), risc-v) +    # RISC-V toolchain specific configuration +    # Find suitable GCC compiler +    ifeq ($(strip $(TOOLCHAIN)),) +        ifneq ($(shell which riscv32-unknown-elf-gcc 2>/dev/null),) +            TOOLCHAIN = riscv32-unknown-elf- +        else +            ifneq ($(shell which riscv64-unknown-elf-gcc 2>/dev/null),) +                TOOLCHAIN = riscv64-unknown-elf- +            else +                $(error "No RISC-V toolchain found. Can't find riscv32-unknown-elf-gcc or riscv64-unknown-elf-gcc found in your systems PATH variable. Please install a valid toolchain and make it accessible!") +            endif +        endif +    endif + +    # Default to compiling with picolibc for RISC-V targets if available, +    # which is available by default on current (bullseye) debian based systems. +    ifeq ($(shell $(TOOLCHAIN)gcc --specs=picolibc.specs -E - 2>/dev/null >/dev/null </dev/null ; echo $$?),0) +        # Toolchain specific Compiler flags +        # Note that we still link with our own linker script +        # by providing it via the -T flag above. +        TOOLCHAIN_CFLAGS = --specs=picolibc.specs + +        # Tell QMK that we are compiling with picolibc. +        OPT_DEFS += -DUSE_PICOLIBC +    endif + +    # MCU architecture flags +    MCUFLAGS = -march=$(MCU_ARCH) \ +               -mabi=$(MCU_ABI) \ +               -mcmodel=$(MCU_CMODEL) \ +               -mstrict-align  else -  OPT_DEFS += -DCORTEX_USE_FPU=FALSE +    # ARM toolchain specific configuration +    TOOLCHAIN ?= arm-none-eabi- + +    # Toolchain specific Linker flags +    TOOLCHAIN_LDFLAGS = -Wl,--no-wchar-size-warning \ +                        --specs=nano.specs + +    # MCU architecture flags +    MCUFLAGS = -mcpu=$(MCU) \ +               -mthumb -DTHUMB_PRESENT \ +               -mno-thumb-interwork -DTHUMB_NO_INTERWORKING \ +               -mno-unaligned-access + +    # Some ARM cores like the M4 and M7 have floating point units which can be enabled +    USE_FPU ?= no + +    ifneq ($(USE_FPU),no) +        OPT_DEFS += -DCORTEX_USE_FPU=TRUE + +        # Default is single precision floats +        USE_FPU_OPT ?= -mfloat-abi=hard \ +                       -mfpu=fpv4-sp-d16 \ +                       -fsingle-precision-constant + +        MCUFLAGS += $(USE_FPU_OPT) +    else +        OPT_DEFS += -DCORTEX_USE_FPU=FALSE +    endif  endif -CFLAGS += $(COMPILEFLAGS) +# Assembler flags +ASFLAGS  += $(SHARED_ASFLAGS) $(TOOLCHAIN_ASFLAGS) -ASFLAGS += $(THUMBFLAGS) +# C Compiler flags +CFLAGS   += $(SHARED_CFLAGS) $(TOOLCHAIN_CFLAGS) -CXXFLAGS += $(COMPILEFLAGS) -CXXFLAGS += -fno-rtti +# C++ Compiler flags +CXXFLAGS += $(CFLAGS) $(SHARED_CXXFLAGS) $(TOOLCHAIN_CXXFLAGS) -fno-rtti -LDFLAGS +=-Wl,--gc-sections -LDFLAGS +=-Wl,--no-wchar-size-warning -LDFLAGS += -mno-thumb-interwork -mthumb -LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE) -LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE) -LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS) -LDFLAGS += --specs=nano.specs +# Linker flags +LDFLAGS  += $(SHARED_LDFLAGS) $(TOOLCHAIN_LDFLAGS) $(MCUFLAGS) +# Tell QMK that we are hosting it on ChibiOS.  OPT_DEFS += -DPROTOCOL_CHIBIOS  # Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already  OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1 -MCUFLAGS = -mcpu=$(MCU) +# Construct GCC toolchain +CC      = $(CC_PREFIX) $(TOOLCHAIN)gcc +OBJCOPY = $(TOOLCHAIN)objcopy +OBJDUMP = $(TOOLCHAIN)objdump +SIZE    = $(TOOLCHAIN)size +AR      = $(TOOLCHAIN)ar +NM      = $(TOOLCHAIN)nm +HEX     = $(OBJCOPY) -O $(FORMAT) +EEP     = +BIN     = $(OBJCOPY) -O binary + +############################################################################## +# Make targets +#  DEBUG = gdb diff --git a/tmk_core/common.mk b/tmk_core/common.mk index e44ff2f0ab..555b942c9d 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -2,10 +2,6 @@ COMMON_DIR = common  PLATFORM_COMMON_DIR = $(COMMON_DIR)/$(PLATFORM_KEY)  TMK_COMMON_SRC +=	\ -	$(COMMON_DIR)/host.c \ -	$(COMMON_DIR)/report.c \ -	$(COMMON_DIR)/sync_timer.c \ -	$(COMMON_DIR)/usb_util.c \  	$(PLATFORM_COMMON_DIR)/platform.c \  	$(PLATFORM_COMMON_DIR)/suspend.c \  	$(PLATFORM_COMMON_DIR)/timer.c \ @@ -14,123 +10,6 @@ TMK_COMMON_SRC +=	\  # Use platform provided print if it exists  -include $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk -SHARED_EP_ENABLE = no -MOUSE_SHARED_EP ?= yes -ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes) -    TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP -    SHARED_EP_ENABLE = yes -    # With the current usb_descriptor.c code, -    # you can't share kbd without sharing mouse; -    # that would be a very unexpected use case anyway -    MOUSE_SHARED_EP = yes -endif - -ifeq ($(strip $(MOUSE_ENABLE)), yes) -    OPT_DEFS += -DMOUSE_ENABLE -    ifeq ($(strip $(MOUSE_SHARED_EP)), yes) -        TMK_COMMON_DEFS += -DMOUSE_SHARED_EP -        SHARED_EP_ENABLE = yes -    endif -endif - -ifeq ($(strip $(EXTRAKEY_ENABLE)), yes) -    TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE -    SHARED_EP_ENABLE = yes -endif - -ifeq ($(strip $(RAW_ENABLE)), yes) -    TMK_COMMON_DEFS += -DRAW_ENABLE -endif - -ifeq ($(strip $(CONSOLE_ENABLE)), yes) -    TMK_COMMON_DEFS += -DCONSOLE_ENABLE -else -    # TODO: decouple this so other print backends can exist -    TMK_COMMON_DEFS += -DNO_PRINT -    TMK_COMMON_DEFS += -DNO_DEBUG -endif - -ifeq ($(strip $(NKRO_ENABLE)), yes) -    ifeq ($(PROTOCOL), VUSB) -        $(info NKRO is not currently supported on V-USB, and has been disabled.) -    else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) -        $(info NKRO is not currently supported with Bluetooth, and has been disabled.) -    else ifneq ($(BLUETOOTH),) -        $(info NKRO is not currently supported with Bluetooth, and has been disabled.) -    else -        TMK_COMMON_DEFS += -DNKRO_ENABLE -        SHARED_EP_ENABLE = yes -    endif -endif - -ifeq ($(strip $(RING_BUFFERED_6KRO_REPORT_ENABLE)), yes) -    TMK_COMMON_DEFS += -DRING_BUFFERED_6KRO_REPORT_ENABLE -endif - -ifeq ($(strip $(SLEEP_LED_ENABLE)), yes) -    TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c -    TMK_COMMON_DEFS += -DSLEEP_LED_ENABLE -    TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN -endif - -ifeq ($(strip $(NO_SUSPEND_POWER_DOWN)), yes) -    TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN -endif - -ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) -    TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE -	TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK -endif - -ifeq ($(strip $(BLUETOOTH)), AdafruitBLE) -	TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE -	TMK_COMMON_DEFS += -DMODULE_ADAFRUIT_BLE -	TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK -endif - -ifeq ($(strip $(BLUETOOTH)), RN42) -	TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE -	TMK_COMMON_DEFS += -DMODULE_RN42 -	TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK -endif - -ifeq ($(strip $(SWAP_HANDS_ENABLE)), yes) -    TMK_COMMON_DEFS += -DSWAP_HANDS_ENABLE -endif - -ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes) -    TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK -endif - -ifeq ($(strip $(DIGITIZER_SHARED_EP)), yes) -    TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP -    SHARED_EP_ENABLE = yes -endif - -ifeq ($(strip $(DIGITIZER_ENABLE)), yes) -    TMK_COMMON_DEFS += -DDIGITIZER_ENABLE -    ifeq ($(strip $(SHARED_EP_ENABLE)), yes) -        TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP -        SHARED_EP_ENABLE = yes -    endif -endif - -ifeq ($(strip $(SHARED_EP_ENABLE)), yes) -    TMK_COMMON_DEFS += -DSHARED_EP_ENABLE -endif - -ifeq ($(strip $(LTO_ENABLE)), yes) -    ifeq ($(PLATFORM),CHIBIOS) -        $(info Enabling LTO on ChibiOS-targeting boards is known to have a high likelihood of failure.) -        $(info If unsure, set LTO_ENABLE = no.) -    endif -    EXTRAFLAGS += -flto -    TMK_COMMON_DEFS += -DLTO_ENABLE -    TMK_COMMON_DEFS += -DLINK_TIME_OPTIMIZATON_ENABLE -else ifdef LINK_TIME_OPTIMIZATION_ENABLE -    $(error The LINK_TIME_OPTIMIZATION_ENABLE flag has been renamed to LTO_ENABLE.) -endif -  # Search Path  VPATH += $(TMK_PATH)/$(COMMON_DIR)  VPATH += $(TMK_PATH)/$(PLATFORM_COMMON_DIR) diff --git a/tmk_core/common/arm_atsam/eeprom.c b/tmk_core/common/arm_atsam/eeprom.c index ccd5d15a54..ff1a692623 100644 --- a/tmk_core/common/arm_atsam/eeprom.c +++ b/tmk_core/common/arm_atsam/eeprom.c @@ -13,24 +13,110 @@   * 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 "eeprom.h" +#include "debug.h" +#include "samd51j18a.h" +#include "core_cm4.h" +#include "component/nvmctrl.h"  #ifndef EEPROM_SIZE  #    include "eeconfig.h"  #    define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4)  // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO  #endif -__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE]; +#ifndef MAX +#    define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif + +#ifndef BUSY_RETRIES +#    define BUSY_RETRIES 10000 +#endif + +// #define DEBUG_EEPROM_OUTPUT + +/* + * Debug print utils + */ +#if defined(DEBUG_EEPROM_OUTPUT) +#    define eeprom_printf(fmt, ...) xprintf(fmt, ##__VA_ARGS__); +#else /* NO_DEBUG */ +#    define eeprom_printf(fmt, ...) +#endif /* NO_DEBUG */ + +__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE] = {0}; +volatile uint8_t *                         SmartEEPROM8        = (uint8_t *)SEEPROM_ADDR; + +static inline bool eeprom_is_busy(void) { +    int timeout = BUSY_RETRIES; +    while (NVMCTRL->SEESTAT.bit.BUSY && timeout-- > 0) +        ; + +    return NVMCTRL->SEESTAT.bit.BUSY; +} + +static uint32_t get_virtual_eeprom_size(void) { +    // clang-format off +    static const uint32_t VIRTUAL_EEPROM_MAP[11][8] = { +    /*          4    8    16    32    64    128    256    512 */ +    /* 0*/ {   0,    0,    0,    0,    0,     0,     0,     0 }, +    /* 1*/ { 512, 1024, 2048, 4096, 4096,  4096,  4096,  4096 }, +    /* 2*/ { 512, 1024, 2048, 4096, 8192,  8192,  8192,  8192 }, +    /* 3*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 }, +    /* 4*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 }, +    /* 5*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 }, +    /* 6*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 }, +    /* 7*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 }, +    /* 8*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 }, +    /* 9*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 }, +    /*10*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 }, +    }; +    // clang-format on + +    static uint32_t virtual_eeprom_size = UINT32_MAX; +    if (virtual_eeprom_size == UINT32_MAX) { +        virtual_eeprom_size = VIRTUAL_EEPROM_MAP[NVMCTRL->SEESTAT.bit.PSZ][NVMCTRL->SEESTAT.bit.SBLK]; +    } +    // eeprom_printf("get_virtual_eeprom_size:: %d:%d:%d\n", NVMCTRL->SEESTAT.bit.PSZ, NVMCTRL->SEESTAT.bit.SBLK, virtual_eeprom_size); +    return virtual_eeprom_size; +}  uint8_t eeprom_read_byte(const uint8_t *addr) {      uintptr_t offset = (uintptr_t)addr; -    return buffer[offset]; +    if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) { +        eeprom_printf("eeprom_read_byte:: out of bounds\n"); +        return 0x0; +    } + +    if (get_virtual_eeprom_size() == 0) { +        return buffer[offset]; +    } + +    if (eeprom_is_busy()) { +        eeprom_printf("eeprom_write_byte:: timeout\n"); +        return 0x0; +    } + +    return SmartEEPROM8[offset];  }  void eeprom_write_byte(uint8_t *addr, uint8_t value) {      uintptr_t offset = (uintptr_t)addr; -    buffer[offset]   = value; +    if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) { +        eeprom_printf("eeprom_write_byte:: out of bounds\n"); +        return; +    } + +    if (get_virtual_eeprom_size() == 0) { +        buffer[offset] = value; +        return; +    } + +    if (eeprom_is_busy()) { +        eeprom_printf("eeprom_write_byte:: timeout\n"); +        return; +    } + +    SmartEEPROM8[offset] = value;  }  uint16_t eeprom_read_word(const uint16_t *addr) { diff --git a/tmk_core/common/arm_atsam/gpio.h b/tmk_core/common/arm_atsam/gpio.h index c2d5a30889..915ed0ef4f 100644 --- a/tmk_core/common/arm_atsam/gpio.h +++ b/tmk_core/common/arm_atsam/gpio.h @@ -64,7 +64,13 @@ typedef uint8_t pin_t;          PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \      } while (0) -#define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin))) +#define writePin(pin, level)                                             \ +    do {                                                                 \ +        if (level)                                                       \ +            PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ +        else                                                             \ +            PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ +    } while (0)  #define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0) diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 690d7f38ca..b614746e6c 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -16,25 +16,6 @@  #    include "vusb.h"  #endif -#ifdef BACKLIGHT_ENABLE -#    include "backlight.h" -#endif - -#ifdef AUDIO_ENABLE -#    include "audio.h" -#endif /* AUDIO_ENABLE */ - -#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) -#    include "rgblight.h" -#endif - -#ifdef LED_MATRIX_ENABLE -#    include "led_matrix.h" -#endif -#ifdef RGB_MATRIX_ENABLE -#    include "rgb_matrix.h" -#endif -  /** \brief Suspend idle   *   * FIXME: needs doc @@ -50,17 +31,6 @@ void suspend_idle(uint8_t time) {  // TODO: This needs some cleanup -/** \brief Run keyboard level Power down - * - * FIXME: needs doc - */ -__attribute__((weak)) void suspend_power_down_user(void) {} -/** \brief Run keyboard level Power down - * - * FIXME: needs doc - */ -__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); } -  #if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)  // clang-format off @@ -135,41 +105,9 @@ void suspend_power_down(void) {      if (!vusb_suspended) return;  #endif -    suspend_power_down_kb(); +    suspend_power_down_quantum();  #ifndef NO_SUSPEND_POWER_DOWN -    // Turn off backlight -#    ifdef BACKLIGHT_ENABLE -    backlight_set(0); -#    endif - -    // Turn off LED indicators -    uint8_t leds_off = 0; -#    if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) -    if (is_backlight_enabled()) { -        // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off -        leds_off |= (1 << USB_LED_CAPS_LOCK); -    } -#    endif -    led_set(leds_off); - -    // Turn off audio -#    ifdef AUDIO_ENABLE -    stop_all_notes(); -#    endif - -    // Turn off underglow -#    if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) -    rgblight_suspend(); -#    endif - -#    if defined(LED_MATRIX_ENABLE) -    led_matrix_set_suspend_state(true); -#    endif -#    if defined(RGB_MATRIX_ENABLE) -    rgb_matrix_set_suspend_state(true); -#    endif -      // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt)  #    if defined(WDT_vect)      power_down(WDTO_15MS); @@ -189,18 +127,6 @@ bool                       suspend_wakeup_condition(void) {      return false;  } -/** \brief run user level code immediately after wakeup - * - * FIXME: needs doc - */ -__attribute__((weak)) void suspend_wakeup_init_user(void) {} - -/** \brief run keyboard level code immediately after wakeup - * - * FIXME: needs doc - */ -__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); } -  /** \brief run immediately after wakeup   *   * FIXME: needs doc @@ -209,27 +135,7 @@ void suspend_wakeup_init(void) {      // clear keyboard state      clear_keyboard(); -    // Turn on backlight -#ifdef BACKLIGHT_ENABLE -    backlight_init(); -#endif - -    // Restore LED indicators -    led_set(host_keyboard_leds()); - -    // Wake up underglow -#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) -    rgblight_wakeup(); -#endif - -#if defined(LED_MATRIX_ENABLE) -    led_matrix_set_suspend_state(false); -#endif -#if defined(RGB_MATRIX_ENABLE) -    rgb_matrix_set_suspend_state(false); -#endif - -    suspend_wakeup_init_kb(); +    suspend_wakeup_init_quantum();  }  #if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h index b740afbd24..2f36c64a2e 100644 --- a/tmk_core/common/chibios/_wait.h +++ b/tmk_core/common/chibios/_wait.h @@ -43,8 +43,6 @@ void wait_us(uint16_t duration);  #include "_wait.c" -#define CPU_CLOCK STM32_SYSCLK -  /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus   * to which the GPIO is connected.   * The connected buses differ depending on the various series of MCUs. diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index f9514ee5f3..5cadadeeeb 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -95,6 +95,28 @@ void enter_bootloader_mode_if_requested(void) {      }  } +#elif defined(GD32VF103) + +#    define DBGMCU_KEY_UNLOCK 0x4B5A6978 +#    define DBGMCU_CMD_RESET 0x1 + +__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU; +__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U; + +__attribute__((weak)) void bootloader_jump(void) { +    /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST +     * register to generate a software reset request. +     * BUT instead two undocumented registers in the debug peripheral +     * that allow issueing a software reset. WHO would need the MSFRST +     * register anyway? Source: +     * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */ +    *DBGMCU_KEY = DBGMCU_KEY_UNLOCK; +    *DBGMCU_CMD = DBGMCU_CMD_RESET; +} + +void enter_bootloader_mode_if_requested(void) { /* Jumping to bootloader is not possible from user code. */ +} +  #elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062)  // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS  /* Kinetis */ diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index 23c65f9428..ad2f808a95 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -19,22 +19,60 @@  #    define SPLIT_USB_DETECT  // Force this on when dedicated pin is not used  #endif -#if defined(STM32F1XX) -#    define USE_GPIOV1 +// STM32 compatibility +#if defined(MCU_STM32) +#    define CPU_CLOCK STM32_SYSCLK + +#    if defined(STM32F1XX) +#        define USE_GPIOV1 +#        define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_STM32_ALTERNATE_OPENDRAIN +#        define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_STM32_ALTERNATE_PUSHPULL +#    else +#        define PAL_OUTPUT_TYPE_OPENDRAIN PAL_STM32_OTYPE_OPENDRAIN +#        define PAL_OUTPUT_TYPE_PUSHPULL PAL_STM32_OTYPE_PUSHPULL +#        define PAL_OUTPUT_SPEED_HIGHEST PAL_STM32_OSPEED_HIGHEST +#        define PAL_PUPDR_FLOATING PAL_STM32_PUPDR_FLOATING +#    endif + +#    if defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32L1XX) +#        define USE_I2CV1 +#    endif +#endif + +// GD32 compatibility +#if defined(MCU_GD32V) +#    define CPU_CLOCK GD32_SYSCLK + +#    if defined(GD32VF103) +#        define USE_GPIOV1 +#        define USE_I2CV1 +#        define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN +#        define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL +#    endif  #endif -#if defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32L1XX) -#    define USE_I2CV1 +#if defined(GD32VF103) +/* This chip has the same API as STM32F103, but uses different names for literally the same thing. + * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake + * we just redefine the GD32 names. */ +#    include "gd32v_compatibility.h"  #endif -// teensy -#if defined(K20x) || defined(KL2x) -#    define USE_I2CV1 -#    define USE_I2CV1_CONTRIB  // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed -#    define USE_GPIOV1 -#    define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY +// teensy compatibility +#if defined(MCU_KINETIS) +#    define CPU_CLOCK KINETIS_SYSCLK_FREQUENCY + +#    if defined(K20x) || defined(KL2x) +#        define USE_I2CV1 +#        define USE_I2CV1_CONTRIB  // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed +#        define USE_GPIOV1 +#    endif  #endif -#if defined(MK66F18) -#    define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY +#if defined(HT32) +#    define CPU_CLOCK HT32_CK_SYS_FREQUENCY +#    define PAL_MODE_ALTERNATE PAL_HT32_MODE_AF +#    define PAL_OUTPUT_TYPE_OPENDRAIN (PAL_HT32_MODE_OD | PAL_HT32_MODE_DIR) +#    define PAL_OUTPUT_TYPE_PUSHPULL PAL_HT32_MODE_DIR +#    define PAL_OUTPUT_SPEED_HIGHEST 0  #endif diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index 1fdf8c1e29..acc6a48516 100644 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -620,48 +620,11 @@ uint16_t EEPROM_ReadDataWord(uint16_t Address) {  }  /***************************************************************************** - *  Wrap library in AVR style functions. + *  Bind to eeprom_driver.c   *******************************************************************************/ -uint8_t eeprom_read_byte(const uint8_t *Address) { return EEPROM_ReadDataByte((const uintptr_t)Address); } +void eeprom_driver_init(void) { EEPROM_Init(); } -void eeprom_write_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } - -void eeprom_update_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } - -uint16_t eeprom_read_word(const uint16_t *Address) { return EEPROM_ReadDataWord((const uintptr_t)Address); } - -void eeprom_write_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); } - -void eeprom_update_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); } - -uint32_t eeprom_read_dword(const uint32_t *Address) { -    const uint16_t p = (const uintptr_t)Address; -    /* Check word alignment */ -    if (p % 2) { -        /* Not aligned */ -        return (uint32_t)EEPROM_ReadDataByte(p) | (uint32_t)(EEPROM_ReadDataWord(p + 1) << 8) | (uint32_t)(EEPROM_ReadDataByte(p + 3) << 24); -    } else { -        /* Aligned */ -        return EEPROM_ReadDataWord(p) | (EEPROM_ReadDataWord(p + 2) << 16); -    } -} - -void eeprom_write_dword(uint32_t *Address, uint32_t Value) { -    uint16_t p = (const uintptr_t)Address; -    /* Check word alignment */ -    if (p % 2) { -        /* Not aligned */ -        EEPROM_WriteDataByte(p, (uint8_t)Value); -        EEPROM_WriteDataWord(p + 1, (uint16_t)(Value >> 8)); -        EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24)); -    } else { -        /* Aligned */ -        EEPROM_WriteDataWord(p, (uint16_t)Value); -        EEPROM_WriteDataWord(p + 2, (uint16_t)(Value >> 16)); -    } -} - -void eeprom_update_dword(uint32_t *Address, uint32_t Value) { eeprom_write_dword(Address, Value); } +void eeprom_driver_erase(void) { EEPROM_Erase(); }  void eeprom_read_block(void *buf, const void *addr, size_t len) {      const uint8_t *src  = (const uint8_t *)addr; @@ -670,14 +633,14 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {      /* Check word alignment */      if (len && (uintptr_t)src % 2) {          /* Read the unaligned first byte */ -        *dest++ = eeprom_read_byte(src++); +        *dest++ = EEPROM_ReadDataByte((const uintptr_t)src++);          --len;      }      uint16_t value;      bool     aligned = ((uintptr_t)dest % 2 == 0);      while (len > 1) { -        value = eeprom_read_word((uint16_t *)src); +        value = EEPROM_ReadDataWord((const uintptr_t)((uint16_t *)src));          if (aligned) {              *(uint16_t *)dest = value;              dest += 2; @@ -689,7 +652,7 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {          len -= 2;      }      if (len) { -        *dest = eeprom_read_byte(src); +        *dest = EEPROM_ReadDataByte((const uintptr_t)src);      }  } @@ -700,7 +663,7 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {      /* Check word alignment */      if (len && (uintptr_t)dest % 2) {          /* Write the unaligned first byte */ -        eeprom_write_byte(dest++, *src++); +        EEPROM_WriteDataByte((uintptr_t)dest++, *src++);          --len;      } @@ -712,15 +675,13 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {          } else {              value = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8);          } -        eeprom_write_word((uint16_t *)dest, value); +        EEPROM_WriteDataWord((uintptr_t)((uint16_t *)dest), value);          dest += 2;          src += 2;          len -= 2;      }      if (len) { -        eeprom_write_byte(dest, *src); +        EEPROM_WriteDataByte((uintptr_t)dest, *src);      }  } - -void eeprom_update_block(const void *buf, void *addr, size_t len) { eeprom_write_block(buf, addr, len); } diff --git a/tmk_core/common/chibios/eeprom_stm32_defs.h b/tmk_core/common/chibios/eeprom_stm32_defs.h index 22b4ab858e..66904f247f 100644 --- a/tmk_core/common/chibios/eeprom_stm32_defs.h +++ b/tmk_core/common/chibios/eeprom_stm32_defs.h @@ -18,7 +18,7 @@  #include <hal.h>  #if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) -#    if defined(STM32F103xB) || defined(STM32F042x6) +#    if defined(STM32F103xB) || defined(STM32F042x6) || defined(GD32VF103C8) || defined(GD32VF103CB)  #        ifndef FEE_PAGE_SIZE  #            define FEE_PAGE_SIZE 0x400  // Page size = 1KByte  #        endif @@ -32,25 +32,38 @@  #        ifndef FEE_PAGE_COUNT  #            define FEE_PAGE_COUNT 4  // How many pages are used  #        endif +#    elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE) +#        ifndef FEE_PAGE_SIZE +#            define FEE_PAGE_SIZE 0x4000  // Page size = 16KByte +#        endif +#        ifndef FEE_PAGE_COUNT +#            define FEE_PAGE_COUNT 1  // How many pages are used +#        endif  #    endif  #endif  #if !defined(FEE_MCU_FLASH_SIZE)  #    if defined(STM32F042x6)  #        define FEE_MCU_FLASH_SIZE 32  // Size in Kb -#    elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) +#    elif defined(GD32VF103C8) +#        define FEE_MCU_FLASH_SIZE 64  // Size in Kb +#    elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(GD32VF103CB)  #        define FEE_MCU_FLASH_SIZE 128  // Size in Kb -#    elif defined(STM32F303xC) +#    elif defined(STM32F303xC) || defined(STM32F401xC)  #        define FEE_MCU_FLASH_SIZE 256  // Size in Kb -#    elif defined(STM32F103xE) +#    elif defined(STM32F103xE) || defined(STM32F401xE) || defined(STM32F411xE)  #        define FEE_MCU_FLASH_SIZE 512  // Size in Kb +#    elif defined(STM32F405xG) +#        define FEE_MCU_FLASH_SIZE 1024  // Size in Kb  #    endif  #endif  /* Start of the emulated eeprom */  #if !defined(FEE_PAGE_BASE_ADDRESS) -#    if 0 -/* TODO: Add support for F4 */ +#    if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE) +#        ifndef FEE_PAGE_BASE_ADDRESS +#            define FEE_PAGE_BASE_ADDRESS 0x08004000  // bodge to force 2nd 16k page +#        endif  #    else  #        ifndef FEE_FLASH_BASE  #            define FEE_FLASH_BASE 0x8000000 diff --git a/tmk_core/common/chibios/eeprom_teensy.c b/tmk_core/common/chibios/eeprom_teensy.c index 4aaf665269..97da6f9e14 100644 --- a/tmk_core/common/chibios/eeprom_teensy.c +++ b/tmk_core/common/chibios/eeprom_teensy.c @@ -39,7 +39,126 @@   * SOFTWARE.   */ -#if defined(K20x) /* chip selection */ +#define SMC_PMSTAT_RUN ((uint8_t)0x01) +#define SMC_PMSTAT_HSRUN ((uint8_t)0x80) + +#define F_CPU KINETIS_SYSCLK_FREQUENCY + +static inline int kinetis_hsrun_disable(void) { +#if defined(MK66F18) +    if (SMC->PMSTAT == SMC_PMSTAT_HSRUN) { +// First, reduce the CPU clock speed, but do not change +// the peripheral speed (F_BUS).  Serial1 & Serial2 baud +// rates will be impacted, but most other peripherals +// will continue functioning at the same speed. +#    if F_CPU == 256000000 && F_BUS == 64000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7);  // TODO: TEST +#    elif F_CPU == 256000000 && F_BUS == 128000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7);  // TODO: TEST +#    elif F_CPU == 240000000 && F_BUS == 60000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7);  // ok +#    elif F_CPU == 240000000 && F_BUS == 80000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8);  // ok +#    elif F_CPU == 240000000 && F_BUS == 120000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7);  // ok +#    elif F_CPU == 216000000 && F_BUS == 54000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7);  // ok +#    elif F_CPU == 216000000 && F_BUS == 72000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8);  // ok +#    elif F_CPU == 216000000 && F_BUS == 108000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7);  // ok +#    elif F_CPU == 192000000 && F_BUS == 48000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7);  // ok +#    elif F_CPU == 192000000 && F_BUS == 64000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8);  // ok +#    elif F_CPU == 192000000 && F_BUS == 96000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7);  // ok +#    elif F_CPU == 180000000 && F_BUS == 60000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8);  // ok +#    elif F_CPU == 180000000 && F_BUS == 90000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7);  // ok +#    elif F_CPU == 168000000 && F_BUS == 56000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5);  // ok +#    elif F_CPU == 144000000 && F_BUS == 48000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5);  // ok +#    elif F_CPU == 144000000 && F_BUS == 72000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 5);  // ok +#    elif F_CPU == 120000000 && F_BUS == 60000000 +        SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) | +#        if defined(MK66F18) +                       SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) | +#        endif +                       SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1); +#    else +        return 0; +#    endif +        // Then turn off HSRUN mode +        SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(0); +        while (SMC->PMSTAT == SMC_PMSTAT_HSRUN) +            ;  // wait +        return 1; +    } +#endif +    return 0; +} + +static inline int kinetis_hsrun_enable(void) { +#if defined(MK66F18) +    if (SMC->PMSTAT == SMC_PMSTAT_RUN) { +        // Turn HSRUN mode on +        SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(3); +        while (SMC->PMSTAT != SMC_PMSTAT_HSRUN) { +            ; +        }  // wait +// Then configure clock for full speed +#    if F_CPU == 256000000 && F_BUS == 64000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); +#    elif F_CPU == 256000000 && F_BUS == 128000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7); +#    elif F_CPU == 240000000 && F_BUS == 60000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); +#    elif F_CPU == 240000000 && F_BUS == 80000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7); +#    elif F_CPU == 240000000 && F_BUS == 120000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7); +#    elif F_CPU == 216000000 && F_BUS == 54000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); +#    elif F_CPU == 216000000 && F_BUS == 72000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7); +#    elif F_CPU == 216000000 && F_BUS == 108000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7); +#    elif F_CPU == 192000000 && F_BUS == 48000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 6); +#    elif F_CPU == 192000000 && F_BUS == 64000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6); +#    elif F_CPU == 192000000 && F_BUS == 96000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6); +#    elif F_CPU == 180000000 && F_BUS == 60000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6); +#    elif F_CPU == 180000000 && F_BUS == 90000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6); +#    elif F_CPU == 168000000 && F_BUS == 56000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 5); +#    elif F_CPU == 144000000 && F_BUS == 48000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 4); +#    elif F_CPU == 144000000 && F_BUS == 72000000 +        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 4); +#    elif F_CPU == 120000000 && F_BUS == 60000000 +        SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) | +#        if defined(MK66F18) +                       SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) | +#        endif +                       SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1); +#    else +        return 0; +#    endif +        return 1; +    } +#endif +    return 0; +} + +#if defined(K20x) || defined(MK66F18) /* chip selection */  /* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */  // The EEPROM is really RAM with a hardware-based backup system to @@ -69,22 +188,34 @@  //  #    define HANDLE_UNALIGNED_WRITES +#    if defined(K20x) +#        define EEPROM_MAX 2048 +#        define EEPARTITION 0x03  // all 32K dataflash for EEPROM, none for Data +#        define EEESPLIT 0x30     // must be 0x30 on these chips +#    elif defined(MK66F18) +#        define EEPROM_MAX 4096 +#        define EEPARTITION 0x05  // 128K dataflash for EEPROM, 128K for Data +#        define EEESPLIT 0x10     // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal +#    endif +  // Minimum EEPROM Endurance  // ------------------------ -#    if (EEPROM_SIZE == 2048)  // 35000 writes/byte or 70000 writes/word -#        define EEESIZE 0x33 +#    if (EEPROM_SIZE == 4096) +#        define EEESIZE 0x02 +#    elif (EEPROM_SIZE == 2048)  // 35000 writes/byte or 70000 writes/word +#        define EEESIZE 0x03  #    elif (EEPROM_SIZE == 1024)  // 75000 writes/byte or 150000 writes/word -#        define EEESIZE 0x34 +#        define EEESIZE 0x04  #    elif (EEPROM_SIZE == 512)  // 155000 writes/byte or 310000 writes/word -#        define EEESIZE 0x35 +#        define EEESIZE 0x05  #    elif (EEPROM_SIZE == 256)  // 315000 writes/byte or 630000 writes/word -#        define EEESIZE 0x36 +#        define EEESIZE 0x06  #    elif (EEPROM_SIZE == 128)  // 635000 writes/byte or 1270000 writes/word -#        define EEESIZE 0x37 +#        define EEESIZE 0x07  #    elif (EEPROM_SIZE == 64)  // 1275000 writes/byte or 2550000 writes/word -#        define EEESIZE 0x38 +#        define EEESIZE 0x08  #    elif (EEPROM_SIZE == 32)  // 2555000 writes/byte or 5110000 writes/word -#        define EEESIZE 0x39 +#        define EEESIZE 0x09  #    endif  /** \brief eeprom initialization @@ -97,15 +228,21 @@ void eeprom_initialize(void) {      uint8_t  status;      if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) { +        uint8_t stat = FTFL->FSTAT & 0x70; +        if (stat) FTFL->FSTAT = stat; +          // FlexRAM is configured as traditional RAM          // We need to reconfigure for EEPROM usage -        FTFL->FCCOB0 = 0x80;     // PGMPART = Program Partition Command -        FTFL->FCCOB4 = EEESIZE;  // EEPROM Size -        FTFL->FCCOB5 = 0x03;     // 0K for Dataflash, 32K for EEPROM backup +        kinetis_hsrun_disable(); +        FTFL->FCCOB0 = 0x80;  // PGMPART = Program Partition Command +        FTFL->FCCOB3 = 0; +        FTFL->FCCOB4 = EEESPLIT | EEESIZE; +        FTFL->FCCOB5 = EEPARTITION;          __disable_irq();          // do_flash_cmd() must execute from RAM.  Luckily the C syntax is simple...          (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));          __enable_irq(); +        kinetis_hsrun_enable();          status = FTFL->FSTAT;          if (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)) {              FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)); @@ -114,11 +251,11 @@ void eeprom_initialize(void) {      }      // wait for eeprom to become ready (is this really necessary?)      while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { -        if (++count > 20000) break; +        if (++count > 200000) break;      }  } -#    define FlexRAM ((uint8_t *)0x14000000) +#    define FlexRAM ((volatile uint8_t *)0x14000000)  /** \brief eeprom read byte   * @@ -195,8 +332,12 @@ void eeprom_write_byte(uint8_t *addr, uint8_t value) {      if (offset >= EEPROM_SIZE) return;      if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();      if (FlexRAM[offset] != value) { +        kinetis_hsrun_disable(); +        uint8_t stat = FTFL->FSTAT & 0x70; +        if (stat) FTFL->FSTAT = stat;          FlexRAM[offset] = value;          flexram_wait(); +        kinetis_hsrun_enable();      }  } @@ -213,18 +354,30 @@ void eeprom_write_word(uint16_t *addr, uint16_t value) {      if ((offset & 1) == 0) {  #    endif          if (*(uint16_t *)(&FlexRAM[offset]) != value) { +            kinetis_hsrun_disable(); +            uint8_t stat = FTFL->FSTAT & 0x70; +            if (stat) FTFL->FSTAT = stat;              *(uint16_t *)(&FlexRAM[offset]) = value;              flexram_wait(); +            kinetis_hsrun_enable();          }  #    ifdef HANDLE_UNALIGNED_WRITES      } else {          if (FlexRAM[offset] != value) { +            kinetis_hsrun_disable(); +            uint8_t stat = FTFL->FSTAT & 0x70; +            if (stat) FTFL->FSTAT = stat;              FlexRAM[offset] = value;              flexram_wait(); +            kinetis_hsrun_enable();          }          if (FlexRAM[offset + 1] != (value >> 8)) { +            kinetis_hsrun_disable(); +            uint8_t stat = FTFL->FSTAT & 0x70; +            if (stat) FTFL->FSTAT = stat;              FlexRAM[offset + 1] = value >> 8;              flexram_wait(); +            kinetis_hsrun_enable();          }      }  #    endif @@ -244,33 +397,57 @@ void eeprom_write_dword(uint32_t *addr, uint32_t value) {          case 0:  #    endif              if (*(uint32_t *)(&FlexRAM[offset]) != value) { +                kinetis_hsrun_disable(); +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  *(uint32_t *)(&FlexRAM[offset]) = value;                  flexram_wait(); +                kinetis_hsrun_enable();              }              return;  #    ifdef HANDLE_UNALIGNED_WRITES          case 2:              if (*(uint16_t *)(&FlexRAM[offset]) != value) { +                kinetis_hsrun_disable(); +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  *(uint16_t *)(&FlexRAM[offset]) = value;                  flexram_wait(); +                kinetis_hsrun_enable();              }              if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { +                kinetis_hsrun_disable(); +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;                  flexram_wait(); +                kinetis_hsrun_enable();              }              return;          default:              if (FlexRAM[offset] != value) { +                kinetis_hsrun_disable(); +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  FlexRAM[offset] = value;                  flexram_wait(); +                kinetis_hsrun_enable();              }              if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { +                kinetis_hsrun_disable(); +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;                  flexram_wait(); +                kinetis_hsrun_enable();              }              if (FlexRAM[offset + 3] != (value >> 24)) { +                kinetis_hsrun_disable(); +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  FlexRAM[offset + 3] = value >> 24;                  flexram_wait(); +                kinetis_hsrun_enable();              }      }  #    endif @@ -288,6 +465,7 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {      if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();      if (len >= EEPROM_SIZE) len = EEPROM_SIZE;      if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; +    kinetis_hsrun_disable();      while (len > 0) {          uint32_t lsb = offset & 3;          if (lsb == 0 && len >= 4) { @@ -298,6 +476,8 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {              val32 |= (*src++ << 16);              val32 |= (*src++ << 24);              if (*(uint32_t *)(&FlexRAM[offset]) != val32) { +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  *(uint32_t *)(&FlexRAM[offset]) = val32;                  flexram_wait();              } @@ -309,6 +489,8 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {              val16 = *src++;              val16 |= (*src++ << 8);              if (*(uint16_t *)(&FlexRAM[offset]) != val16) { +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  *(uint16_t *)(&FlexRAM[offset]) = val16;                  flexram_wait();              } @@ -318,6 +500,8 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {              // write 8 bits              uint8_t val8 = *src++;              if (FlexRAM[offset] != val8) { +                uint8_t stat = FTFL->FSTAT & 0x70; +                if (stat) FTFL->FSTAT = stat;                  FlexRAM[offset] = val8;                  flexram_wait();              } @@ -325,6 +509,7 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {              len--;          }      } +    kinetis_hsrun_enable();  }  /* diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c index 6b80ff71c3..72c41b8b78 100644 --- a/tmk_core/common/chibios/flash_stm32.c +++ b/tmk_core/common/chibios/flash_stm32.c @@ -19,10 +19,38 @@  #include <hal.h>  #include "flash_stm32.h" -#if defined(EEPROM_EMU_STM32F103xB) +#if defined(STM32F1XX)  #    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR  #endif +#if defined(MCU_GD32V) +/* GigaDevice GD32VF103 is a STM32F103 clone at heart. */ +#    include "gd32v_compatibility.h" +#endif + +#if defined(STM32F4XX) +#    define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR) + +#    define FLASH_KEY1 0x45670123U +#    define FLASH_KEY2 0xCDEF89ABU + +static uint8_t ADDR2PAGE(uint32_t Page_Address) { +    switch (Page_Address) { +        case 0x08000000 ... 0x08003FFF: +            return 0; +        case 0x08004000 ... 0x08007FFF: +            return 1; +        case 0x08008000 ... 0x0800BFFF: +            return 2; +        case 0x0800C000 ... 0x0800FFFF: +            return 3; +    } + +    // TODO: bad times... +    return 7; +} +#endif +  /* Delay definition */  #define EraseTimeout ((uint32_t)0x00000FFF)  #define ProgramTimeout ((uint32_t)0x0000001F) @@ -53,7 +81,9 @@ FLASH_Status FLASH_GetStatus(void) {      if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP; +#if defined(FLASH_OBR_OPTERR)      if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT; +#endif      return FLASH_COMPLETE;  } @@ -95,15 +125,24 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {      if (status == FLASH_COMPLETE) {          /* if the previous operation is completed, proceed to erase the page */ +#if defined(FLASH_CR_SNB) +        FLASH->CR &= ~FLASH_CR_SNB; +        FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos); +#else          FLASH->CR |= FLASH_CR_PER;          FLASH->AR = Page_Address; +#endif          FLASH->CR |= FLASH_CR_STRT;          /* Wait for last operation to be completed */          status = FLASH_WaitForLastOperation(EraseTimeout);          if (status != FLASH_TIMEOUT) { -            /* if the erase operation is completed, disable the PER Bit */ +            /* if the erase operation is completed, disable the configured Bits */ +#if defined(FLASH_CR_SNB) +            FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB); +#else              FLASH->CR &= ~FLASH_CR_PER; +#endif          }          FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);      } @@ -126,6 +165,11 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {          status = FLASH_WaitForLastOperation(ProgramTimeout);          if (status == FLASH_COMPLETE) {              /* if the previous operation is completed, proceed to program the new data */ + +#if defined(FLASH_CR_PSIZE) +            FLASH->CR &= ~FLASH_CR_PSIZE; +            FLASH->CR |= FLASH_CR_PSIZE_0; +#endif              FLASH->CR |= FLASH_CR_PG;              *(__IO uint16_t*)Address = Data;              /* Wait for last operation to be completed */ diff --git a/tmk_core/common/chibios/gd32v_compatibility.h b/tmk_core/common/chibios/gd32v_compatibility.h new file mode 100644 index 0000000000..f4dcfd8c55 --- /dev/null +++ b/tmk_core/common/chibios/gd32v_compatibility.h @@ -0,0 +1,120 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +/* GD32VF103 has the same API as STM32F103, but uses different names for literally the same thing. + * As of 23.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake + * we just redefine the GD32 names. */ + +/* Close your eyes kids. */ +#define MCU_STM32 + +/* AFIO redefines */ +#define MAPR PCF0 +#define AFIO_MAPR_USART1_REMAP AFIO_PCF0_USART0_REMAP +#define AFIO_MAPR_USART2_REMAP AFIO_PCF0_USART1_REMAP +#define AFIO_MAPR_USART3_REMAP_PARTIALREMAP AFIO_PCF0_USART2_REMAP_PARTIALREMAP +#define AFIO_MAPR_USART3_REMAP_FULLREMAP AFIO_PCF0_USART2_REMAP_FULLREMAP + +/* DMA redefines. */ +#define STM32_DMA_STREAM(stream) GD32_DMA_STREAM(stream) +#define STM32_DMA_STREAM_ID(peripheral, channel) GD32_DMA_STREAM_ID(peripheral - 1, channel - 1) +#define STM32_DMA_CR_DIR_M2P GD32_DMA_CTL_DIR_M2P +#define STM32_DMA_CR_PSIZE_WORD GD32_DMA_CTL_PWIDTH_WORD +#define STM32_DMA_CR_MSIZE_WORD GD32_DMA_CTL_MWIDTH_WORD +#define STM32_DMA_CR_MINC GD32_DMA_CTL_MNAGA +#define STM32_DMA_CR_CIRC GD32_DMA_CTL_CMEN +#define STM32_DMA_CR_PL GD32_DMA_CTL_PRIO +#define STM32_DMA_CR_CHSEL GD32_DMA_CTL_CHSEL +#define cr1 ctl0 +#define cr2 ctl1 +#define cr3 ctl2 +#define dier dmainten + +/* ADC redefines */ +#if HAL_USE_ADC +#    define STM32_ADC_USE_ADC1 GD32_ADC_USE_ADC0 + +#    define smpr1 sampt0 +#    define smpr2 sampt1 +#    define sqr1 rsq0 +#    define sqr2 rsq1 +#    define sqr3 rsq2 + +#    define ADC_SMPR2_SMP_AN0 ADC_SAMPT1_SMP_SPT0 +#    define ADC_SMPR2_SMP_AN1 ADC_SAMPT1_SMP_SPT1 +#    define ADC_SMPR2_SMP_AN2 ADC_SAMPT1_SMP_SPT2 +#    define ADC_SMPR2_SMP_AN3 ADC_SAMPT1_SMP_SPT3 +#    define ADC_SMPR2_SMP_AN4 ADC_SAMPT1_SMP_SPT4 +#    define ADC_SMPR2_SMP_AN5 ADC_SAMPT1_SMP_SPT5 +#    define ADC_SMPR2_SMP_AN6 ADC_SAMPT1_SMP_SPT6 +#    define ADC_SMPR2_SMP_AN7 ADC_SAMPT1_SMP_SPT7 +#    define ADC_SMPR2_SMP_AN8 ADC_SAMPT1_SMP_SPT8 +#    define ADC_SMPR2_SMP_AN9 ADC_SAMPT1_SMP_SPT9 + +#    define ADC_SMPR1_SMP_AN10 ADC_SAMPT0_SMP_SPT10 +#    define ADC_SMPR1_SMP_AN11 ADC_SAMPT0_SMP_SPT11 +#    define ADC_SMPR1_SMP_AN12 ADC_SAMPT0_SMP_SPT12 +#    define ADC_SMPR1_SMP_AN13 ADC_SAMPT0_SMP_SPT13 +#    define ADC_SMPR1_SMP_AN14 ADC_SAMPT0_SMP_SPT14 +#    define ADC_SMPR1_SMP_AN15 ADC_SAMPT0_SMP_SPT15 + +#    define ADC_SQR3_SQ1_N ADC_RSQ2_RSQ1_N +#endif + +/* FLASH redefines */ +#if defined(EEPROM_ENABLE) +#    define SR STAT +#    define FLASH_SR_BSY FLASH_STAT_BUSY +#    define FLASH_SR_PGERR FLASH_STAT_PGERR +#    define FLASH_SR_EOP FLASH_STAT_ENDF +#    define FLASH_SR_WRPRTERR FLASH_STAT_WPERR +#    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR +#    define FLASH_OBR_OPTERR FLASH_OBSTAT_OBERR +#    define AR ADDR +#    define CR CTL +#    define FLASH_CR_PER FLASH_CTL_PER +#    define FLASH_CR_STRT FLASH_CTL_START +#    define FLASH_CR_LOCK FLASH_CTL_LK +#    define FLASH_CR_PG FLASH_CTL_PG +#    define KEYR KEY +#endif + +/* Serial USART redefines. */ +#if HAL_USE_SERIAL +#    if !defined(SERIAL_USART_CR1) +#        define SERIAL_USART_CR1 (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL)  // parity enable, odd parity, 9 bit length +#    endif +#    if !defined(SERIAL_USART_CR2) +#        define SERIAL_USART_CR2 (USART_CTL1_STB_1)  // 2 stop bits +#    endif +#    if !defined(SERIAL_USART_CR3) +#        define SERIAL_USART_CR3 0x0 +#    endif +#    define USART_CR3_HDSEL USART_CTL2_HDEN +#    define CCR CHCV +#endif + +/* SPI redefines. */ +#if HAL_USE_SPI +#    define SPI_CR1_LSBFIRST SPI_CTL0_LF +#    define SPI_CR1_CPHA SPI_CTL0_CKPH +#    define SPI_CR1_CPOL SPI_CTL0_CKPL +#    define SPI_CR1_BR_0 SPI_CTL0_PSC_0 +#    define SPI_CR1_BR_1 SPI_CTL0_PSC_1 +#    define SPI_CR1_BR_2 SPI_CTL0_PSC_2 +#endif diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 1c65016a42..477056a454 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -65,7 +65,7 @@ void sleep_led_timer_callback(void) {  /* LPTMR clock options */  #    define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ -#    define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ +#    define LPTMR_CLOCK_LPO 1      /* 1kHz clock */  #    define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */  #    define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */ @@ -121,7 +121,7 @@ void sleep_led_init(void) {      MCG->C2 |= MCG_C2_IRCS;  // fast (4MHz) internal ref clock  #        if defined(KL27)    // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others      MCG->MC |= MCG_MC_LIRC_DIV2_DIV2; -#        endif /* KL27 */ +#        endif                  /* KL27 */      MCG->C1 |= MCG_C1_IRCLKEN;  // enable internal ref clock      //  to work in stop mode, also MCG_C1_IREFSTEN      //  Divide 4MHz by 2^N (N=6) => 62500 irqs/sec => diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 38517e06f0..9310a99920 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -7,30 +7,12 @@  #include "action.h"  #include "action_util.h"  #include "mousekey.h" +#include "programmable_button.h"  #include "host.h"  #include "suspend.h"  #include "led.h"  #include "wait.h" -#ifdef AUDIO_ENABLE -#    include "audio.h" -#endif /* AUDIO_ENABLE */ - -#ifdef BACKLIGHT_ENABLE -#    include "backlight.h" -#endif - -#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) -#    include "rgblight.h" -#endif - -#ifdef LED_MATRIX_ENABLE -#    include "led_matrix.h" -#endif -#ifdef RGB_MATRIX_ENABLE -#    include "rgb_matrix.h" -#endif -  /** \brief suspend idle   *   * FIXME: needs doc @@ -40,61 +22,12 @@ void suspend_idle(uint8_t time) {      wait_ms(time);  } -/** \brief Run keyboard level Power down - * - * FIXME: needs doc - */ -__attribute__((weak)) void suspend_power_down_user(void) {} -/** \brief Run keyboard level Power down - * - * FIXME: needs doc - */ -__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); } -  /** \brief suspend power down   *   * FIXME: needs doc   */  void suspend_power_down(void) { -#ifdef BACKLIGHT_ENABLE -    backlight_set(0); -#endif - -#ifdef LED_MATRIX_ENABLE -    led_matrix_task(); -#endif -#ifdef RGB_MATRIX_ENABLE -    rgb_matrix_task(); -#endif - -    // Turn off LED indicators -    uint8_t leds_off = 0; -#if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) -    if (is_backlight_enabled()) { -        // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off -        leds_off |= (1 << USB_LED_CAPS_LOCK); -    } -#endif -    led_set(leds_off); - -    // TODO: figure out what to power down and how -    // shouldn't power down TPM/FTM if we want a breathing LED -    // also shouldn't power down USB -#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) -    rgblight_suspend(); -#endif - -#if defined(LED_MATRIX_ENABLE) -    led_matrix_set_suspend_state(true); -#endif -#if defined(RGB_MATRIX_ENABLE) -    rgb_matrix_set_suspend_state(true); -#endif -#ifdef AUDIO_ENABLE -    stop_all_notes(); -#endif /* AUDIO_ENABLE */ - -    suspend_power_down_kb(); +    suspend_power_down_quantum();      // on AVR, this enables the watchdog for 15ms (max), and goes to      // SLEEP_MODE_PWR_DOWN @@ -147,23 +80,13 @@ void suspend_wakeup_init(void) {  #ifdef MOUSEKEY_ENABLE      mousekey_clear();  #endif /* MOUSEKEY_ENABLE */ +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    programmable_button_clear(); +#endif /* PROGRAMMABLE_BUTTON_ENABLE */  #ifdef EXTRAKEY_ENABLE      host_system_send(0);      host_consumer_send(0);  #endif /* EXTRAKEY_ENABLE */ -#ifdef BACKLIGHT_ENABLE -    backlight_init(); -#endif /* BACKLIGHT_ENABLE */ -    led_set(host_keyboard_leds()); -#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) -    rgblight_wakeup(); -#endif -#if defined(LED_MATRIX_ENABLE) -    led_matrix_set_suspend_state(false); -#endif -#if defined(RGB_MATRIX_ENABLE) -    rgb_matrix_set_suspend_state(false); -#endif -    suspend_wakeup_init_kb(); +    suspend_wakeup_init_quantum();  } diff --git a/tmk_core/common/chibios/syscall-fallbacks.c b/tmk_core/common/chibios/syscall-fallbacks.c index 739017ae1d..4569879c7c 100644 --- a/tmk_core/common/chibios/syscall-fallbacks.c +++ b/tmk_core/common/chibios/syscall-fallbacks.c @@ -18,6 +18,12 @@  #include <sys/stat.h>  #include <sys/types.h> +/* To compile the ChibiOS syscall stubs with picolibc + * the _reent struct has to be defined. */ +#if defined(USE_PICOLIBC) +struct _reent; +#endif +  #pragma GCC diagnostic ignored "-Wmissing-prototypes"  __attribute__((weak, used)) int _open_r(struct _reent *r, const char *path, int flag, int m) { diff --git a/tmk_core/common/raw_hid.h b/tmk_core/common/raw_hid.h deleted file mode 100644 index 6d60ab2bff..0000000000 --- a/tmk_core/common/raw_hid.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -void raw_hid_receive(uint8_t *data, uint8_t length); - -void raw_hid_send(uint8_t *data, uint8_t length); diff --git a/tmk_core/common/suspend.h b/tmk_core/common/suspend.h index 95845e4b63..081735f90e 100644 --- a/tmk_core/common/suspend.h +++ b/tmk_core/common/suspend.h @@ -10,8 +10,10 @@ void suspend_wakeup_init(void);  void suspend_wakeup_init_user(void);  void suspend_wakeup_init_kb(void); +void suspend_wakeup_init_quantum(void);  void suspend_power_down_user(void);  void suspend_power_down_kb(void); +void suspend_power_down_quantum(void);  #ifndef USB_SUSPEND_WAKEUP_DELAY  #    define USB_SUSPEND_WAKEUP_DELAY 0 diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c deleted file mode 100644 index 68b92d8b43..0000000000 --- a/tmk_core/common/sync_timer.c +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -If you happen to meet one of the copyright holders in a bar you are obligated -to buy them one pint of beer. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "sync_timer.h" -#include "keyboard.h" - -#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) -volatile int32_t sync_timer_ms; - -void sync_timer_init(void) { sync_timer_ms = 0; } - -void sync_timer_update(uint32_t time) { -    if (is_keyboard_master()) return; -    sync_timer_ms = time - timer_read32(); -} - -uint16_t sync_timer_read(void) { -    if (is_keyboard_master()) return timer_read(); -    return sync_timer_read32(); -} - -uint32_t sync_timer_read32(void) { -    if (is_keyboard_master()) return timer_read32(); -    return sync_timer_ms + timer_read32(); -} - -uint16_t sync_timer_elapsed(uint16_t last) { -    if (is_keyboard_master()) return timer_elapsed(last); -    return TIMER_DIFF_16(sync_timer_read(), last); -} - -uint32_t sync_timer_elapsed32(uint32_t last) { -    if (is_keyboard_master()) return timer_elapsed32(last); -    return TIMER_DIFF_32(sync_timer_read32(), last); -} -#endif diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h deleted file mode 100644 index 744e2b50d5..0000000000 --- a/tmk_core/common/sync_timer.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -If you happen to meet one of the copyright holders in a bar you are obligated -to buy them one pint of beer. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include <stdint.h> -#include "timer.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) -void     sync_timer_init(void); -void     sync_timer_update(uint32_t time); -uint16_t sync_timer_read(void); -uint32_t sync_timer_read32(void); -uint16_t sync_timer_elapsed(uint16_t last); -uint32_t sync_timer_elapsed32(uint32_t last); -#else -#    define sync_timer_init() -#    define sync_timer_clear() -#    define sync_timer_update(t) -#    define sync_timer_read() timer_read() -#    define sync_timer_read32() timer_read32() -#    define sync_timer_elapsed(t) timer_elapsed(t) -#    define sync_timer_elapsed32(t) timer_elapsed32(t) -#endif - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/test/rules.mk b/tmk_core/common/test/rules.mk index 48632a095b..73d2302da7 100644 --- a/tmk_core/common/test/rules.mk +++ b/tmk_core/common/test/rules.mk @@ -16,6 +16,7 @@ eeprom_stm32_tiny_INC := $(eeprom_stm32_INC)  eeprom_stm32_large_INC := $(eeprom_stm32_INC)  eeprom_stm32_SRC := \ +	$(TOP_DIR)/drivers/eeprom/eeprom_driver.c \  	$(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \  	$(TMK_PATH)/common/test/flash_stm32_mock.c \  	$(TMK_PATH)/common/chibios/eeprom_stm32.c diff --git a/tmk_core/common/virtser.h b/tmk_core/common/virtser.h deleted file mode 100644 index a0645f9e03..0000000000 --- a/tmk_core/common/virtser.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -/* Define this function in your code to process incoming bytes */ -void virtser_recv(const uint8_t ch); - -/* Call this to send a character over the Virtual Serial Device */ -void virtser_send(const uint8_t byte); diff --git a/tmk_core/native.mk b/tmk_core/native.mk index f609fd0e6f..eb2424ec5c 100644 --- a/tmk_core/native.mk +++ b/tmk_core/native.mk @@ -1,7 +1,7 @@  SYSTEM_TYPE := $(shell gcc -dumpmachine)  GCC_VERSION := $(shell gcc --version 2>/dev/null) -CC = gcc +CC = $(CC_PREFIX) gcc  OBJCOPY =  OBJDUMP =  SIZE = diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index b61f2f5463..a8723e6b2e 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -1,57 +1,85 @@  PROTOCOL_DIR = protocol -ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes) -    SRC += $(PROTOCOL_DIR)/ps2_mouse.c -    OPT_DEFS += -DPS2_MOUSE_ENABLE +TMK_COMMON_SRC +=	\ +	$(PROTOCOL_DIR)/host.c \ +	$(PROTOCOL_DIR)/report.c \ +	$(PROTOCOL_DIR)/usb_device_state.c \ +	$(PROTOCOL_DIR)/usb_util.c \ + +SHARED_EP_ENABLE = no +MOUSE_SHARED_EP ?= yes +ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes) +    TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP +    SHARED_EP_ENABLE = yes +    # With the current usb_descriptor.c code, +    # you can't share kbd without sharing mouse; +    # that would be a very unexpected use case anyway +    MOUSE_SHARED_EP = yes +endif + +ifeq ($(strip $(MOUSE_ENABLE)), yes)      OPT_DEFS += -DMOUSE_ENABLE +    ifeq ($(strip $(MOUSE_SHARED_EP)), yes) +        TMK_COMMON_DEFS += -DMOUSE_SHARED_EP +        SHARED_EP_ENABLE = yes +    endif  endif -ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes) -    SRC += protocol/ps2_busywait.c -    SRC += protocol/ps2_io_avr.c -    OPT_DEFS += -DPS2_USE_BUSYWAIT +ifeq ($(strip $(EXTRAKEY_ENABLE)), yes) +    TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE +    SHARED_EP_ENABLE = yes  endif -ifeq ($(strip $(PS2_USE_INT)), yes) -    SRC += protocol/ps2_interrupt.c -    SRC += protocol/ps2_io_$(PLATFORM_KEY).c -    OPT_DEFS += -DPS2_USE_INT +ifeq ($(strip $(RAW_ENABLE)), yes) +    TMK_COMMON_DEFS += -DRAW_ENABLE  endif -ifeq ($(strip $(PS2_USE_USART)), yes) -    SRC += protocol/ps2_usart.c -    SRC += protocol/ps2_io_$(PLATFORM_KEY).c -    OPT_DEFS += -DPS2_USE_USART +ifeq ($(strip $(CONSOLE_ENABLE)), yes) +    TMK_COMMON_DEFS += -DCONSOLE_ENABLE +else +    # TODO: decouple this so other print backends can exist +    TMK_COMMON_DEFS += -DNO_PRINT +    TMK_COMMON_DEFS += -DNO_DEBUG  endif +ifeq ($(strip $(NKRO_ENABLE)), yes) +    ifeq ($(PROTOCOL), VUSB) +        $(info NKRO is not currently supported on V-USB, and has been disabled.) +    else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) +        $(info NKRO is not currently supported with Bluetooth, and has been disabled.) +    else +        TMK_COMMON_DEFS += -DNKRO_ENABLE +        SHARED_EP_ENABLE = yes +    endif +endif -ifeq ($(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)), yes) -    SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c -    OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \ -                -DMOUSE_ENABLE +ifeq ($(strip $(RING_BUFFERED_6KRO_REPORT_ENABLE)), yes) +    TMK_COMMON_DEFS += -DRING_BUFFERED_6KRO_REPORT_ENABLE  endif -ifeq ($(strip $(SERIAL_MOUSE_MOUSESYSTEMS_ENABLE)), yes) -    SRC += $(PROTOCOL_DIR)/serial_mouse_mousesystems.c -    OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MOUSESYSTEMS \ -                -DMOUSE_ENABLE +ifeq ($(strip $(NO_SUSPEND_POWER_DOWN)), yes) +    TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN  endif -ifeq ($(strip $(SERIAL_MOUSE_USE_SOFT)), yes) -    SRC += $(PROTOCOL_DIR)/serial_soft.c +ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes) +    TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK  endif -ifeq ($(strip $(SERIAL_MOUSE_USE_UART)), yes) -    SRC += $(PROTOCOL_DIR)/serial_uart.c +ifeq ($(strip $(DIGITIZER_SHARED_EP)), yes) +    TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP +    SHARED_EP_ENABLE = yes  endif -ifeq ($(strip $(ADB_MOUSE_ENABLE)), yes) -    OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE +ifeq ($(strip $(DIGITIZER_ENABLE)), yes) +    TMK_COMMON_DEFS += -DDIGITIZER_ENABLE +    ifeq ($(strip $(SHARED_EP_ENABLE)), yes) +        TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP +        SHARED_EP_ENABLE = yes +    endif  endif -ifeq ($(strip $(XT_ENABLE)), yes) -    SRC += $(PROTOCOL_DIR)/xt_interrupt.c -    OPT_DEFS += -DXT_ENABLE +ifeq ($(strip $(SHARED_EP_ENABLE)), yes) +    TMK_COMMON_DEFS += -DSHARED_EP_ENABLE  endif  ifeq ($(strip $(USB_HID_ENABLE)), yes) diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c deleted file mode 100644 index 367f1b09fa..0000000000 --- a/tmk_core/protocol/adb.c +++ /dev/null @@ -1,535 +0,0 @@ -/* -Copyright 2011-19 Jun WAKO <[email protected]> -Copyright 2013 Shay Green <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <stdbool.h> -#include <util/delay.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include "adb.h" -#include "print.h" - -// GCC doesn't inline functions normally -#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT)) -#define data_hi() (ADB_DDR &= ~(1 << ADB_DATA_BIT)) -#define data_in() (ADB_PIN & (1 << ADB_DATA_BIT)) - -#ifdef ADB_PSW_BIT -static inline void psw_lo(void); -static inline void psw_hi(void); -static inline bool psw_in(void); -#endif - -static inline void     attention(void); -static inline void     place_bit0(void); -static inline void     place_bit1(void); -static inline void     send_byte(uint8_t data); -static inline uint16_t wait_data_lo(uint16_t us); -static inline uint16_t wait_data_hi(uint16_t us); - -void adb_host_init(void) { -    ADB_PORT &= ~(1 << ADB_DATA_BIT); -    data_hi(); -#ifdef ADB_PSW_BIT -    psw_hi(); -#endif -} - -#ifdef ADB_PSW_BIT -bool adb_host_psw(void) { return psw_in(); } -#endif - -/* - * Don't call this in a row without the delay, otherwise it makes some of poor controllers - * overloaded and misses strokes. Recommended interval is 12ms. - * - * Thanks a lot, blargg! - * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> - * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> - */ -uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); } - -#ifdef ADB_MOUSE_ENABLE -__attribute__((weak)) void adb_mouse_init(void) { return; } - -__attribute__((weak)) void adb_mouse_task(void) { return; } - -uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); } -#endif - -// This sends Talk command to read data from register and returns length of the data. -uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { -    for (int8_t i = 0; i < len; i++) buf[i] = 0; - -    cli(); -    attention(); -    send_byte((addr << 4) | ADB_CMD_TALK | reg); -    place_bit0();  // Stopbit(0) -    // TODO: Service Request(Srq): -    // Device holds low part of comannd stopbit for 140-260us -    // -    // Command: -    // ......._     ______________________    ___ ............_     ------- -    //         |   |                      |  |   |             |   | -    // Command |   |                      |  |   | Data bytes  |   | -    // ........|___|  |     140-260       |__|   |_............|___| -    //         |stop0 | Tlt Stop-to-Start |start1|             |stop0 | -    // -    // Command without data: -    // ......._     __________________________ -    //         |   | -    // Command |   | -    // ........|___|  |     140-260       | -    //         |stop0 | Tlt Stop-to-Start | -    // -    // Service Request: -    // ......._                     ______    ___ ............_     ------- -    //         |     140-260       |      |  |   |             |   | -    // Command |  Service Request  |      |  |   | Data bytes  |   | -    // ........|___________________|      |__|   |_............|___| -    //         |stop0 |                   |start1|             |stop0 | -    // ......._                     __________ -    //         |     140-260       | -    // Command |  Service Request  | -    // ........|___________________| -    //         |stop0 | -    // This can be happened? -    // ......._     ______________________    ___ ............_                   ----- -    //         |   |                      |  |   |             |    140-260      | -    // Command |   |                      |  |   | Data bytes  | Service Request | -    // ........|___|  |     140-260       |__|   |_............|_________________| -    //         |stop0 | Tlt Stop-to-Start |start1|             |stop0 | -    // -    // "Service requests are issued by the devices during a very specific time at the -    // end of the reception of the command packet. -    // If a device in need of service issues a service request, it must do so within -    // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs." -    // -    // "A device sends a Service Request signal by holding the bus low during the low -    // portion of the stop bit of any command or data transaction. The device must lengthen -    // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15." -    // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf -    if (!wait_data_hi(500)) {  // Service Request(310us Adjustable Keyboard): just ignored -        xprintf("R"); -        sei(); -        return 0; -    } -    if (!wait_data_lo(500)) {  // Tlt/Stop to Start(140-260us) -        sei(); -        return 0;  // No data from device(not error); -    } - -    // start bit(1) -    if (!wait_data_hi(40)) { -        xprintf("S"); -        sei(); -        return 0; -    } -    if (!wait_data_lo(100)) { -        xprintf("s"); -        sei(); -        return 0; -    } - -    uint8_t n = 0;  // bit count -    do { -        // -        // |<- bit_cell_max(130) ->| -        // |        |<-   lo     ->| -        // |        |       |<-hi->| -        //           _______ -        // |        |       | -        // | 130-lo | lo-hi | -        // |________|       | -        // -        uint8_t lo = (uint8_t)wait_data_hi(130); -        if (!lo) goto error;  // no more bit or after stop bit - -        uint8_t hi = (uint8_t)wait_data_lo(lo); -        if (!hi) goto error;  // stop bit extedned by Srq? - -        if (n / 8 >= len) continue;  // can't store in buf - -        buf[n / 8] <<= 1; -        if ((130 - lo) < (lo - hi)) { -            buf[n / 8] |= 1; -        } -    } while (++n); - -error: -    sei(); -    return n / 8; -} - -uint16_t adb_host_talk(uint8_t addr, uint8_t reg) { -    uint8_t len; -    uint8_t buf[8]; -    len = adb_host_talk_buf(addr, reg, buf, 8); -    if (len != 2) return 0; -    return (buf[0] << 8 | buf[1]); -} - -void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { -    cli(); -    attention(); -    send_byte((addr << 4) | ADB_CMD_LISTEN | reg); -    place_bit0();  // Stopbit(0) -    // TODO: Service Request -    _delay_us(200);  // Tlt/Stop to Start -    place_bit1();    // Startbit(1) -    for (int8_t i = 0; i < len; i++) { -        send_byte(buf[i]); -        // xprintf("%02X ", buf[i]); -    } -    place_bit0();  // Stopbit(0); -    sei(); -} - -void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) { -    uint8_t buf[2] = {data_h, data_l}; -    adb_host_listen_buf(addr, reg, buf, 2); -} - -void adb_host_flush(uint8_t addr) { -    cli(); -    attention(); -    send_byte((addr << 4) | ADB_CMD_FLUSH); -    place_bit0();    // Stopbit(0) -    _delay_us(200);  // Tlt/Stop to Start -    sei(); -} - -// send state of LEDs -void adb_host_kbd_led(uint8_t led) { -    // Listen Register2 -    //  upper byte: not used -    //  lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock -    adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07); -} - -#ifdef ADB_PSW_BIT -static inline void psw_lo() { -    ADB_DDR |= (1 << ADB_PSW_BIT); -    ADB_PORT &= ~(1 << ADB_PSW_BIT); -} -static inline void psw_hi() { -    ADB_PORT |= (1 << ADB_PSW_BIT); -    ADB_DDR &= ~(1 << ADB_PSW_BIT); -} -static inline bool psw_in() { -    ADB_PORT |= (1 << ADB_PSW_BIT); -    ADB_DDR &= ~(1 << ADB_PSW_BIT); -    return ADB_PIN & (1 << ADB_PSW_BIT); -} -#endif - -static inline void attention(void) { -    data_lo(); -    _delay_us(800 - 35);  // bit1 holds lo for 35 more -    place_bit1(); -} - -static inline void place_bit0(void) { -    data_lo(); -    _delay_us(65); -    data_hi(); -    _delay_us(35); -} - -static inline void place_bit1(void) { -    data_lo(); -    _delay_us(35); -    data_hi(); -    _delay_us(65); -} - -static inline void send_byte(uint8_t data) { -    for (int i = 0; i < 8; i++) { -        if (data & (0x80 >> i)) -            place_bit1(); -        else -            place_bit0(); -    } -} - -// These are carefully coded to take 6 cycles of overhead. -// inline asm approach became too convoluted -static inline uint16_t wait_data_lo(uint16_t us) { -    do { -        if (!data_in()) break; -        _delay_us(1 - (6 * 1000000.0 / F_CPU)); -    } while (--us); -    return us; -} - -static inline uint16_t wait_data_hi(uint16_t us) { -    do { -        if (data_in()) break; -        _delay_us(1 - (6 * 1000000.0 / F_CPU)); -    } while (--us); -    return us; -} - -/* -ADB Protocol -============ - -Resources ---------- -ADB - The Untold Story: Space Aliens Ate My Mouse -    http://developer.apple.com/legacy/mac/library/#technotes/hw/hw_01.html -ADB Manager -    http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Devices/ADB_Manager.pdf -    Service request(5-17) -Apple IIgs Hardware Reference Second Edition [Chapter6 p121] -    ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf -ADB Keycode -    http://72.0.193.250/Documentation/macppc/adbkeycodes/ -    http://m0115.web.fc2.com/m0115.jpg -    [Inside Macintosh volume V, pages 191-192] -    http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-421.18.3/IOHIDFamily/Cosmo_USB2ADB.c -ADB Signaling -    http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf -ADB Overview & History -    http://en.wikipedia.org/wiki/Apple_Desktop_Bus -Microchip Application Note: ADB device(with code for PIC16C) -    http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062 -AVR ATtiny2131 ADB to PS/2 converter(Japanese) -    http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html - - -Pinouts -------- -    ADB female socket from the front: -    __________ -    |        | <--- top -    | 4o  o3 | -    |2o    o1| -    |   ==   | -    |________| <--- bottom -      |    |   <--- 4pins - - -    ADB female socket from bottom: - -    ========== <--- front -    |        | -    |        | -    |2o    o1| -    |4o    o3| -    ---------- <--- back - -    1: Data -    2: Power SW(low when press Power key) -    3: Vcc(5V) -    4: GND - - -Commands --------- -    ADB command is 1byte and consists of 4bit-address, 2bit-command -    type and 2bit-register. The commands are always sent by Host. - -    Command format: -    7 6 5 4 3 2 1 0 -    | | | |------------ address -            | |-------- command type -                | |---- register - -    bits                commands -    ------------------------------------------------------ -    - - - - 0 0 0 0     Send Reset(reset all devices) -    A A A A 0 0 0 1     Flush(reset a device) -    - - - - 0 0 1 0     Reserved -    - - - - 0 0 1 1     Reserved -    - - - - 0 1 - -     Reserved -    A A A A 1 0 R R     Listen(write to a device) -    A A A A 1 1 R R     Talk(read from a device) - -    The command to read keycodes from keyboard is 0x2C which -    consist of keyboard address 2 and Talk against register 0. - -    Address: -    2:  keyboard -    3:  mice - -    Registers: -    0: application(keyboard uses this to store its data.) -    1: application -    2: application(keyboard uses this for LEDs and state of modifiers) -    3: status and command - - -Communication -------------- -    This is a minimum information for keyboard communication. -    See "Resources" for detail. - -    Signaling: - -    ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~ - -        |800us     |  |7 Command 0|  |   |  |15-64  Data  0|Stopbit(0) -        +Attention |              |  |   +Startbit(1) -                   +Startbit(1)   |  +Tlt(140-260us) -                                  +stopbit(0) - -    Bit cells: - -    bit0: ______~~~ -          65    :35us - -    bit1: ___~~~~~~ -          35 :65us - -    bit0 low time: 60-70% of bit cell(42-91us) -    bit1 low time: 30-40% of bit cell(21-52us) -    bit cell time: 70-130us -    [from Apple IIgs Hardware Reference Second Edition] - -    Criterion for bit0/1: -    After 55us if line is low/high then bit is 0/1. - -    Attention & start bit: -    Host asserts low in 560-1040us then places start bit(1). - -    Tlt(Stop to Start): -    Bus stays high in 140-260us then device places start bit(1). - -    Global reset: -    Host asserts low in 2.8-5.2ms. All devices are forced to reset. - -    Service request from device(Srq): -    Device can request to send at commad(Global only?) stop bit. -    Requesting device keeps low for 140-260us at stop bit of command. - - -Keyboard Data(Register0) -    This 16bit data can contains two keycodes and two released flags. -    First keycode is palced in upper byte. When one keyocode is sent, -    lower byte is 0xFF. -    Release flag is 1 when key is released. - -    1514 . . . . . 8 7 6 . . . . . 0 -     | | | | | | | | | +-+-+-+-+-+-+-   Keycode2 -     | | | | | | | | +---------------   Released2(1 when the key is released) -     | +-+-+-+-+-+-+-----------------   Keycode1 -     +-------------------------------   Released1(1 when the key is released) - -    Keycodes: -    Scancode consists of 7bit keycode and 1bit release flag. -    Device can send two keycodes at once. If just one keycode is sent -    keycode1 contains it and keyocode2 is 0xFF. - -    Power switch: -    You can read the state from PSW line(active low) however -    the switch has a special scancode 0x7F7F, so you can -    also read from Data line. It uses 0xFFFF for release scancode. - -Keyboard LEDs & state of keys(Register2) -    This register hold current state of three LEDs and nine keys. -    The state of LEDs can be changed by sending Listen command. - -    1514 . . . . . . 7 6 5 . 3 2 1 0 -     | | | | | | | | | | | | | | | +-   LED1(NumLock) -     | | | | | | | | | | | | | | +---   LED2(CapsLock) -     | | | | | | | | | | | | | +-----   LED3(ScrollLock) -     | | | | | | | | | | +-+-+-------   Reserved -     | | | | | | | | | +-------------   ScrollLock -     | | | | | | | | +---------------   NumLock -     | | | | | | | +-----------------   Apple/Command -     | | | | | | +-------------------   Option -     | | | | | +---------------------   Shift -     | | | | +-----------------------   Control -     | | | +-------------------------   Reset/Power -     | | +---------------------------   CapsLock -     | +-----------------------------   Delete -     +-------------------------------   Reserved - -Address, Handler ID and bits(Register3) -    1514131211 . . 8 7 . . . . . . 0 -     | | | | | | | | | | | | | | | | -     | | | | | | | | +-+-+-+-+-+-+-+-   Handler ID -     | | | | +-+-+-+-----------------   Address -     | | | +-------------------------   0 -     | | +---------------------------   Service request enable(1 = enabled) -     | +-----------------------------   Exceptional event(alwyas 1 if not used) -     +-------------------------------   0 - -ADB Bit Cells -    bit cell time: 70-130us -    low part of bit0: 60-70% of bit cell -    low part of bit1: 30-40% of bit cell - -       bit cell time         70us        130us -       -------------------------------------------- -       low  part of bit0     42-49       78-91 -       high part of bit0     21-28       39-52 -       low  part of bit1     21-28       39-52 -       high part of bit1     42-49       78-91 - - -    bit0: -       70us bit cell: -         ____________~~~~~~ -         42-49        21-28 - -       130us bit cell: -         ____________~~~~~~ -         78-91        39-52 - -    bit1: -       70us bit cell: -         ______~~~~~~~~~~~~ -         21-28        42-49 - -       130us bit cell: -         ______~~~~~~~~~~~~ -         39-52        78-91 - -    [from Apple IIgs Hardware Reference Second Edition] - -Keyboard Handle ID -    Apple Standard Keyboard M0116:      0x01 -    Apple Extended Keyboard M0115:      0x02 -    Apple Extended Keyboard II M3501:   0x02 -    Apple Adjustable Keybaord:          0x10 - -    http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802 - -END_OF_ADB -*/ diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h deleted file mode 100644 index fe8becc2d5..0000000000 --- a/tmk_core/protocol/adb.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright 2011-19 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include <stdint.h> -#include <stdbool.h> - -#if !(defined(ADB_PORT) && defined(ADB_PIN) && defined(ADB_DDR) && defined(ADB_DATA_BIT)) -#    error "ADB port setting is required in config.h" -#endif - -#define ADB_POWER 0x7F -#define ADB_CAPS 0x39 - -/* ADB commands */ -// Default Address -#define ADB_ADDR_0 0 -#define ADB_ADDR_DONGLE 1 -#define ADB_ADDR_KEYBOARD 2 -#define ADB_ADDR_MOUSE 3 -#define ADB_ADDR_TABLET 4 -#define ADB_ADDR_APPLIANCE 7 -#define ADB_ADDR_8 8 -#define ADB_ADDR_9 9 -#define ADB_ADDR_10 10 -#define ADB_ADDR_11 11 -#define ADB_ADDR_12 12 -#define ADB_ADDR_13 13 -#define ADB_ADDR_14 14 -#define ADB_ADDR_15 15 -// for temporary purpose, do not use for polling -#define ADB_ADDR_TMP 15 -#define ADB_ADDR_MOUSE_POLL 10 -// Command Type -#define ADB_CMD_RESET 0 -#define ADB_CMD_FLUSH 1 -#define ADB_CMD_LISTEN 8 -#define ADB_CMD_TALK 12 -// Register -#define ADB_REG_0 0 -#define ADB_REG_1 1 -#define ADB_REG_2 2 -#define ADB_REG_3 3 - -/* ADB keyboard handler id */ -#define ADB_HANDLER_STD 0x01        /* IIGS, M0116 */ -#define ADB_HANDLER_AEK 0x02        /* M0115, M3501 */ -#define ADB_HANDLER_AEK_RMOD 0x03   /* M0115, M3501, alternate mode enableing right modifiers */ -#define ADB_HANDLER_STD_ISO 0x04    /* M0118, ISO swapping keys */ -#define ADB_HANDLER_AEK_ISO 0x05    /* M0115, M3501, ISO swapping keys */ -#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */ -#define ADB_HANDLER_CLASSIC1_MOUSE 0x01 -#define ADB_HANDLER_CLASSIC2_MOUSE 0x02 -#define ADB_HANDLER_EXTENDED_MOUSE 0x04 -#define ADB_HANDLER_TURBO_MOUSE 0x32 - -// ADB host -void     adb_host_init(void); -bool     adb_host_psw(void); -uint16_t adb_host_talk(uint8_t addr, uint8_t reg); -uint8_t  adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); -void     adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l); -void     adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); -void     adb_host_flush(uint8_t addr); -void     adb_host_kbd_led(uint8_t led); -uint16_t adb_host_kbd_recv(void); -uint16_t adb_host_mouse_recv(void); - -// ADB Mouse -void adb_mouse_task(void); -void adb_mouse_init(void); diff --git a/tmk_core/protocol/arm_atsam.mk b/tmk_core/protocol/arm_atsam.mk index 5bb45d658e..ffd1fa9f50 100644 --- a/tmk_core/protocol/arm_atsam.mk +++ b/tmk_core/protocol/arm_atsam.mk @@ -9,7 +9,8 @@ ifeq ($(RGB_MATRIX_DRIVER),custom)    SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c  endif  SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c -SRC += $(ARM_ATSAM_DIR)/spi.c +SRC += $(ARM_ATSAM_DIR)/shift_register.c +SRC += $(ARM_ATSAM_DIR)/spi_master.c  SRC += $(ARM_ATSAM_DIR)/startup.c  SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c @@ -19,10 +20,12 @@ SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c  SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c  SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c  SRC += $(ARM_ATSAM_DIR)/usb/ui.c -SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c  SRC += $(ARM_ATSAM_DIR)/usb/usb.c  SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c +SRC += $(ARM_ATSAM_DIR)/usb/usb_hub.c  SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c +SRC += $(DRIVER_PATH)/usb2422.c +  # Search Path  VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR) diff --git a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h index d126c66e7d..e1749f872d 100644 --- a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h +++ b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h @@ -27,9 +27,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "wait.h"  #include "adc.h"  #include "i2c_master.h" -#include "spi.h" +#include "shift_register.h" -#include "./usb/usb2422.h" +#include "./usb/usb_hub.h"  #ifndef MD_BOOTLOADER diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c index dda2f85b00..af046625f4 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.c +++ b/tmk_core/protocol/arm_atsam/i2c_master.c @@ -564,4 +564,23 @@ uint8_t i2c_led_q_run(void) {      return 1;  } + +__attribute__((weak)) void i2c_init(void) { +    static bool is_initialised = false; +    if (!is_initialised) { +        is_initialised = true; + +        i2c0_init(); +    } +} + +i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) { +    uint8_t ret                 = i2c0_transmit(address, (uint8_t *)data, length, timeout); +    SERCOM0->I2CM.CTRLB.bit.CMD = 0x03; +    while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { +        DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); +    } +    return ret ? I2C_STATUS_SUCCESS : I2C_STATUS_ERROR; +} +  #endif  // !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE) diff --git a/tmk_core/protocol/arm_atsam/i2c_master.h b/tmk_core/protocol/arm_atsam/i2c_master.h index 68773f213f..e11235d447 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.h +++ b/tmk_core/protocol/arm_atsam/i2c_master.h @@ -101,4 +101,13 @@ void    i2c0_init(void);  uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);  void    i2c0_stop(void); +// Terrible interface compatiblity... +#define I2C_STATUS_SUCCESS (0) +#define I2C_STATUS_ERROR (-1) + +typedef int16_t i2c_status_t; + +void         i2c_init(void); +i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout); +  #endif  // _I2C_MASTER_H_ diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index 858b4cd9fc..1df5112ed8 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -296,7 +296,7 @@ int main(void) {      matrix_init(); -    USB2422_init(); +    USB_Hub_init();      DBGC(DC_MAIN_UDC_START_BEGIN);      udc_start(); @@ -306,7 +306,7 @@ int main(void) {      CDC_init();      DBGC(DC_MAIN_CDC_INIT_COMPLETE); -    while (USB2422_Port_Detect_Init() == 0) { +    while (USB_Hub_Port_Detect_Init() == 0) {      }      DBG_LED_OFF; diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c index 98967aac88..0741584439 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c @@ -15,6 +15,10 @@ You should have received a copy of the GNU General Public License  along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ +#define FLUSH_TIMEOUT 5000 +#define EECONFIG_MD_LED ((uint8_t*)(EECONFIG_SIZE + 64)) +#define MD_LED_CONFIG_VERSION 1 +  #ifdef RGB_MATRIX_ENABLE  #    include "arm_atsam_protocol.h"  #    include "led.h" @@ -23,8 +27,41 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    include <math.h>  #    ifdef USE_MASSDROP_CONFIGURATOR +// TODO?: wire these up to keymap.c +md_led_config_t md_led_config = {0}; + +EECONFIG_DEBOUNCE_HELPER(md_led, EECONFIG_MD_LED, md_led_config); + +void eeconfig_update_md_led_default(void) { +    md_led_config.ver = MD_LED_CONFIG_VERSION; + +    gcr_desired               = LED_GCR_MAX; +    led_animation_orientation = 0; +    led_animation_direction   = 0; +    led_animation_breathing   = 0; +    led_animation_id          = 0; +    led_animation_speed       = 4.0f; +    led_lighting_mode         = LED_MODE_NORMAL; +    led_enabled               = 1; +    led_animation_breathe_cur = BREATHE_MIN_STEP; +    breathe_dir               = 1; +    led_animation_circular    = 0; +    led_edge_brightness       = 1.0f; +    led_ratio_brightness      = 1.0f; +    led_edge_mode             = LED_EDGE_MODE_ALL; + +    eeconfig_flush_md_led(true); +} + +void md_led_changed(void) { eeconfig_flag_md_led(true); } + +// todo: use real task rather than this bodge +void housekeeping_task_kb(void) { eeconfig_flush_md_led_task(FLUSH_TIMEOUT); } +  __attribute__((weak)) led_instruction_t led_instructions[] = {{.end = 1}};  static void                             md_rgb_matrix_config_override(int i); +#    else +uint8_t gcr_desired;  #    endif  // USE_MASSDROP_CONFIGURATOR  void SERCOM1_0_Handler(void) { @@ -56,7 +93,6 @@ issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];  issi3733_led_t led_map[ISSI3733_LED_COUNT] = ISSI3733_LED_MAP;  RGB            led_buffer[ISSI3733_LED_COUNT]; -uint8_t gcr_desired;  uint8_t gcr_actual;  uint8_t gcr_actual_last;  #    ifdef USE_MASSDROP_CONFIGURATOR @@ -218,6 +254,13 @@ static void led_set_all(uint8_t r, uint8_t g, uint8_t b) {  static void init(void) {      DBGC(DC_LED_MATRIX_INIT_BEGIN); +#    ifdef USE_MASSDROP_CONFIGURATOR +    eeconfig_init_md_led(); +    if (md_led_config.ver != MD_LED_CONFIG_VERSION) { +        eeconfig_update_md_led_default(); +    } +#    endif +      issi3733_prepare_arrays();      md_rgb_matrix_prepare(); @@ -331,17 +374,6 @@ const rgb_matrix_driver_t rgb_matrix_driver = {.init = init, .flush = flush, .se  #    ifdef USE_MASSDROP_CONFIGURATOR  // Ported from Massdrop QMK GitHub Repo -// TODO?: wire these up to keymap.c -uint8_t led_animation_orientation = 0; -uint8_t led_animation_direction   = 0; -uint8_t led_animation_breathing   = 0; -uint8_t led_animation_id          = 0; -float   led_animation_speed       = 4.0f; -uint8_t led_lighting_mode         = LED_MODE_NORMAL; -uint8_t led_enabled               = 1; -uint8_t led_animation_breathe_cur = BREATHE_MIN_STEP; -uint8_t breathe_dir               = 1; -  static void led_run_pattern(led_setup_t* f, float* ro, float* go, float* bo, float pos) {      float po; @@ -398,16 +430,32 @@ static void led_run_pattern(led_setup_t* f, float* ro, float* go, float* bo, flo      }  } +#        define RGB_MAX_DISTANCE 232.9635f +  static void md_rgb_matrix_config_override(int i) {      float ro = 0;      float go = 0;      float bo = 0; - -    float po = (led_animation_orientation) ? (float)g_led_config.point[i].y / 64.f * 100 : (float)g_led_config.point[i].x / 224.f * 100; +    float po;      uint8_t highest_active_layer = biton32(layer_state); -    if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) { +    if (led_animation_circular) { +        // TODO: should use min/max values from LED configuration instead of +        // hard-coded 224, 64 +        // po = sqrtf((powf(fabsf((disp.width / 2) - (led_cur->x - disp.left)), 2) + powf(fabsf((disp.height / 2) - (led_cur->y - disp.bottom)), 2))) / disp.max_distance * 100; +        po = sqrtf((powf(fabsf((224 / 2) - (float)g_led_config.point[i].x), 2) + powf(fabsf((64 / 2) - (float)g_led_config.point[i].y), 2))) / RGB_MAX_DISTANCE * 100; +    } else { +        if (led_animation_orientation) { +            po = (float)g_led_config.point[i].y / 64.f * 100; +        } else { +            po = (float)g_led_config.point[i].x / 224.f * 100; +        } +    } + +    if (led_edge_mode == LED_EDGE_MODE_ALTERNATE && LED_IS_EDGE_ALT(led_map[i].scan)) { +        // Do not act on this LED (Edge alternate lighting mode) +    } else if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {          // Do not act on this LED      } else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {          // Do not act on this LED @@ -465,10 +513,30 @@ static void md_rgb_matrix_config_override(int i) {          }      } +    // Adjust edge LED brightness +    if (led_edge_brightness != 1 && LED_IS_EDGE(led_map[i].scan)) { +        ro *= led_edge_brightness; +        go *= led_edge_brightness; +        bo *= led_edge_brightness; +    } + +    // Adjust ratio of key vs. underglow (edge) LED brightness +    if (LED_IS_EDGE(led_map[i].scan) && led_ratio_brightness > 1.0) { +        // Decrease edge (underglow) LEDs +        ro *= (2.0 - led_ratio_brightness); +        go *= (2.0 - led_ratio_brightness); +        bo *= (2.0 - led_ratio_brightness); +    } else if (LED_IS_KEY(led_map[i].scan) && led_ratio_brightness < 1.0) { +        // Decrease KEY LEDs +        ro *= led_ratio_brightness; +        go *= led_ratio_brightness; +        bo *= led_ratio_brightness; +    } +      led_buffer[i].r = (uint8_t)ro;      led_buffer[i].g = (uint8_t)go;      led_buffer[i].b = (uint8_t)bo;  }  #    endif  // USE_MASSDROP_CONFIGURATOR -#endif      // RGB_MATRIX_ENABLE
\ No newline at end of file +#endif      // RGB_MATRIX_ENABLE diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.h b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h index 76ccaa678b..deea12b888 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.h +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h @@ -19,6 +19,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define _LED_MATRIX_H_  #include "quantum.h" +#include "eeprom.h"  // From keyboard  #include "config_led.h" @@ -79,7 +80,6 @@ typedef struct issi3733_led_s {  extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT]; -extern uint8_t gcr_desired;  extern uint8_t gcr_breathe;  extern uint8_t gcr_actual;  extern uint8_t gcr_actual_last; @@ -128,6 +128,8 @@ typedef struct led_instruction_s {      uint32_t id1;    // Bitwise id, IDs 32-63      uint32_t id2;    // Bitwise id, IDs 64-95      uint32_t id3;    // Bitwise id, IDs 96-127 +    uint32_t id4;    // Bitwise id, IDs 128-159 +    uint32_t id5;    // Bitwise id, IDs 160-191      uint8_t  layer;      uint8_t  r;      uint8_t  g; @@ -138,14 +140,43 @@ typedef struct led_instruction_s {  extern led_instruction_t led_instructions[]; -extern uint8_t led_animation_breathing; -extern uint8_t led_animation_id; -extern float   led_animation_speed; -extern uint8_t led_lighting_mode; -extern uint8_t led_enabled; -extern uint8_t led_animation_breathe_cur; -extern uint8_t led_animation_direction; -extern uint8_t breathe_dir; +typedef struct led_config_s { +    uint8_t ver;  // assumed to be zero on eeprom reset + +    uint8_t desired_gcr; +    uint8_t animation_breathing; +    uint8_t animation_id; +    float   animation_speed; +    uint8_t lighting_mode; +    uint8_t enabled; +    uint8_t animation_breathe_cur; +    uint8_t animation_direction; +    uint8_t animation_breathe_dir; +    uint8_t animation_orientation; +    uint8_t animation_circular; +    float   edge_brightness; +    float   ratio_brightness; +    uint8_t edge_mode; +} md_led_config_t; + +extern md_led_config_t md_led_config; + +void md_led_changed(void); + +#    define gcr_desired md_led_config.desired_gcr +#    define led_animation_breathing md_led_config.animation_breathing +#    define led_animation_id md_led_config.animation_id +#    define led_animation_speed md_led_config.animation_speed +#    define led_lighting_mode md_led_config.lighting_mode +#    define led_enabled md_led_config.enabled +#    define led_animation_breathe_cur md_led_config.animation_breathe_cur +#    define led_animation_direction md_led_config.animation_direction +#    define breathe_dir md_led_config.animation_breathe_dir +#    define led_animation_orientation md_led_config.animation_orientation +#    define led_animation_circular md_led_config.animation_circular +#    define led_edge_brightness md_led_config.edge_brightness +#    define led_ratio_brightness md_led_config.ratio_brightness +#    define led_edge_mode md_led_config.edge_mode  #    define LED_MODE_NORMAL 0  // Must be 0  #    define LED_MODE_KEYS_ONLY 1 @@ -153,6 +184,21 @@ extern uint8_t breathe_dir;  #    define LED_MODE_INDICATORS_ONLY 3  #    define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY  // Must be highest value +#    define LED_EDGE_MODE_ALL 0                        // All edge LEDs are active (Must be 0) +#    define LED_EDGE_MODE_ALTERNATE 1                  // Alternate mode of edge LEDs are active (Intention is for 'only every other edge LED' to be active) +#    define LED_EDGE_MODE_MAX LED_EDGE_MODE_ALTERNATE  // Must be the highest valued LED edge mode + +#    define LED_EDGE_FULL_MODE 255  // LEDs configured with this scan code will always be on for edge lighting modes +#    define LED_EDGE_ALT_MODE 254   // LEDs configured with this scan code will turn off in edge alternating mode +#    define LED_EDGE_MIN_SCAN 254   // LEDs configured with scan code >= to this are assigned as edge LEDs +#    define LED_INDICATOR_SCAN 253  // LEDs configured as dedicated indicators + +#    define LED_IS_KEY(scan) (scan < LED_INDICATOR_SCAN)         // Return true if an LED's scan value indicates it is a key LED +#    define LED_IS_EDGE(scan) (scan >= LED_EDGE_MIN_SCAN)        // Return true if an LED's scan value indicates an edge LED +#    define LED_IS_EDGE_ALT(scan) (scan == LED_EDGE_ALT_MODE)    // Return true if an LED's scan value indicates an alternate edge mode LED +#    define LED_IS_INDICATOR(scan) (scan == LED_INDICATOR_SCAN)  // Return true if an LED's scan value indicates it is a dedicated Indicator +#else +extern uint8_t gcr_desired;  #endif  // USE_MASSDROP_CONFIGURATOR  #endif  //_LED_MATRIX_H_ diff --git a/tmk_core/protocol/arm_atsam/shift_register.c b/tmk_core/protocol/arm_atsam/shift_register.c new file mode 100644 index 0000000000..8d63af1b59 --- /dev/null +++ b/tmk_core/protocol/arm_atsam/shift_register.c @@ -0,0 +1,118 @@ +/* +Copyright 2018 Massdrop Inc. + +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 "arm_atsam_protocol.h" + +#include "spi_master.h" +#include "wait.h" +#include "gpio.h" + +// #define SR_USE_BITBANG + +// Bodge for when spi_master is not available +#ifdef SR_USE_BITBANG +#    define CLOCK_DELAY 10 + +void shift_init_impl(void) { +    setPinOutput(SR_EXP_RCLK_PIN); +    setPinOutput(SPI_DATAOUT_PIN); +    setPinOutput(SPI_SCLK_PIN); +} + +void shift_out_impl(const uint8_t *data, uint16_t length) { +    writePinLow(SR_EXP_RCLK_PIN); +    for (uint16_t i = 0; i < length; i++) { +        uint8_t val = data[i]; + +        // shift out lsb first +        for (uint8_t bit = 0; bit < 8; bit++) { +            writePin(SPI_DATAOUT_PIN, !!(val & (1 << bit))); +            writePin(SPI_SCLK_PIN, true); +            wait_us(CLOCK_DELAY); + +            writePin(SPI_SCLK_PIN, false); +            wait_us(CLOCK_DELAY); +        } +    } +    writePinHigh(SR_EXP_RCLK_PIN); +    return SPI_STATUS_SUCCESS; +} + +#else + +void shift_init_impl(void) { spi_init(); } + +void shift_out_impl(const uint8_t *data, uint16_t length) { +    spi_start(SR_EXP_RCLK_PIN, true, 0, 0); + +    spi_transmit(data, length); + +    spi_stop(); +} +#endif + +// *************************************************************** + +void shift_out(const uint8_t *data, uint16_t length) { shift_out_impl(data, length); } + +void shift_enable(void) { +    setPinOutput(SR_EXP_OE_PIN); +    writePinLow(SR_EXP_OE_PIN); +} + +void shift_disable(void) { +    setPinOutput(SR_EXP_OE_PIN); +    writePinHigh(SR_EXP_OE_PIN); +} + +void shift_init(void) { +    shift_disable(); +    shift_init_impl(); +} + +// *************************************************************** + +sr_exp_t sr_exp_data; + +void SR_EXP_WriteData(void) { +    uint8_t data[2] = { +        sr_exp_data.reg & 0xFF,         // Shift in bits 7-0 +        (sr_exp_data.reg >> 8) & 0xFF,  // Shift in bits 15-8 +    }; +    shift_out(data, 2); +} + +void SR_EXP_Init(void) { +    shift_init(); + +    sr_exp_data.reg             = 0; +    sr_exp_data.bit.HUB_CONNECT = 0; +    sr_exp_data.bit.HUB_RESET_N = 0; +    sr_exp_data.bit.S_UP        = 0; +    sr_exp_data.bit.E_UP_N      = 1; +    sr_exp_data.bit.S_DN1       = 1; +    sr_exp_data.bit.E_DN1_N     = 1; +    sr_exp_data.bit.E_VBUS_1    = 0; +    sr_exp_data.bit.E_VBUS_2    = 0; +    sr_exp_data.bit.SRC_1       = 1; +    sr_exp_data.bit.SRC_2       = 1; +    sr_exp_data.bit.IRST        = 1; +    sr_exp_data.bit.SDB_N       = 0; +    SR_EXP_WriteData(); + +    shift_enable(); +} diff --git a/tmk_core/protocol/arm_atsam/spi.h b/tmk_core/protocol/arm_atsam/shift_register.h index dcd45f31af..56a8c7f717 100644 --- a/tmk_core/protocol/arm_atsam/spi.h +++ b/tmk_core/protocol/arm_atsam/shift_register.h @@ -15,28 +15,9 @@ You should have received a copy of the GNU General Public License  along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ -#ifndef _SPI_H_ -#define _SPI_H_ +#pragma once -/* Macros for Shift Register control */ -#define SR_EXP_RCLK_LO PORT->Group[SR_EXP_RCLK_PORT].OUTCLR.reg = (1 << SR_EXP_RCLK_PIN) -#define SR_EXP_RCLK_HI PORT->Group[SR_EXP_RCLK_PORT].OUTSET.reg = (1 << SR_EXP_RCLK_PIN) -#define SR_EXP_OE_N_ENA PORT->Group[SR_EXP_OE_N_PORT].OUTCLR.reg = (1 << SR_EXP_OE_N_PIN) -#define SR_EXP_OE_N_DIS PORT->Group[SR_EXP_OE_N_PORT].OUTSET.reg = (1 << SR_EXP_OE_N_PIN) - -/* Determine bits to set for mux selection */ -#if SR_EXP_DATAOUT_PIN % 2 == 0 -#    define SR_EXP_DATAOUT_MUX_SEL PMUXE -#else -#    define SR_EXP_DATAOUT_MUX_SEL PMUXO -#endif - -/* Determine bits to set for mux selection */ -#if SR_EXP_SCLK_PIN % 2 == 0 -#    define SR_EXP_SCLK_MUX_SEL PMUXE -#else -#    define SR_EXP_SCLK_MUX_SEL PMUXO -#endif +#include <stdint.h>  /* Data structure to define Shift Register output expander hardware */  /* This structure gets shifted into registers LSB first */ @@ -66,5 +47,3 @@ extern sr_exp_t sr_exp_data;  void SR_EXP_WriteData(void);  void SR_EXP_Init(void); - -#endif  //_SPI_H_ diff --git a/tmk_core/protocol/arm_atsam/spi.c b/tmk_core/protocol/arm_atsam/spi.c deleted file mode 100644 index 3b118bc1f1..0000000000 --- a/tmk_core/protocol/arm_atsam/spi.c +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2018 Massdrop Inc. - -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 "arm_atsam_protocol.h" - -sr_exp_t sr_exp_data; - -void SR_EXP_WriteData(void) { -    SR_EXP_RCLK_LO; - -    while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) { -        DBGC(DC_SPI_WRITE_DRE); -    } - -    SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF;  // Shift in bits 7-0 -    while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { -        DBGC(DC_SPI_WRITE_TXC_1); -    } - -    SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF;  // Shift in bits 15-8 -    while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { -        DBGC(DC_SPI_WRITE_TXC_2); -    } - -    SR_EXP_RCLK_HI; -} - -void SR_EXP_Init(void) { -    DBGC(DC_SPI_INIT_BEGIN); - -    CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT); - -    // Set up MCU Shift Register pins -    PORT->Group[SR_EXP_RCLK_PORT].DIRSET.reg = (1 << SR_EXP_RCLK_PIN); -    PORT->Group[SR_EXP_OE_N_PORT].DIRSET.reg = (1 << SR_EXP_OE_N_PIN); - -    // Set up MCU SPI pins -    PORT->Group[SR_EXP_DATAOUT_PORT].PMUX[SR_EXP_DATAOUT_PIN / 2].bit.SR_EXP_DATAOUT_MUX_SEL = SR_EXP_DATAOUT_MUX;  // MUX select for sercom -    PORT->Group[SR_EXP_SCLK_PORT].PMUX[SR_EXP_SCLK_PIN / 2].bit.SR_EXP_SCLK_MUX_SEL          = SR_EXP_SCLK_MUX;     // MUX select for sercom -    PORT->Group[SR_EXP_DATAOUT_PORT].PINCFG[SR_EXP_DATAOUT_PIN].bit.PMUXEN                   = 1;                   // MUX Enable -    PORT->Group[SR_EXP_SCLK_PORT].PINCFG[SR_EXP_SCLK_PIN].bit.PMUXEN                         = 1;                   // MUX Enable - -    // Initialize Shift Register -    SR_EXP_OE_N_DIS; -    SR_EXP_RCLK_HI; - -    SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1;  // Data Order - LSB is transferred first -    SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1;  // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising. -    SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1;  // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample -    SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3;  // Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.) -    SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0;  // Data Output PAD[0], Serial Clock PAD[1] -    SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3;  // Operating Mode - Master operation - -    SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1;  // Enable - Peripheral is enabled or being enabled -    while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { -        DBGC(DC_SPI_SYNC_ENABLING); -    } - -    sr_exp_data.reg             = 0; -    sr_exp_data.bit.HUB_CONNECT = 0; -    sr_exp_data.bit.HUB_RESET_N = 0; -    sr_exp_data.bit.S_UP        = 0; -    sr_exp_data.bit.E_UP_N      = 1; -    sr_exp_data.bit.S_DN1       = 1; -    sr_exp_data.bit.E_DN1_N     = 1; -    sr_exp_data.bit.E_VBUS_1    = 0; -    sr_exp_data.bit.E_VBUS_2    = 0; -    sr_exp_data.bit.SRC_1       = 1; -    sr_exp_data.bit.SRC_2       = 1; -    sr_exp_data.bit.IRST        = 1; -    sr_exp_data.bit.SDB_N       = 0; -    SR_EXP_WriteData(); - -    // Enable Shift Register output -    SR_EXP_OE_N_ENA; - -    DBGC(DC_SPI_INIT_COMPLETE); -} diff --git a/tmk_core/protocol/arm_atsam/spi_master.c b/tmk_core/protocol/arm_atsam/spi_master.c new file mode 100644 index 0000000000..9781d45b1e --- /dev/null +++ b/tmk_core/protocol/arm_atsam/spi_master.c @@ -0,0 +1,109 @@ +/* +Copyright 2018 Massdrop Inc. + +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 "arm_atsam_protocol.h" +#include "spi_master.h" +#include "gpio.h" + +/* Determine bits to set for mux selection */ +#if SPI_DATAOUT_PIN % 2 == 0 +#    define SPI_DATAOUT_MUX_SEL PMUXE +#else +#    define SPI_DATAOUT_MUX_SEL PMUXO +#endif + +/* Determine bits to set for mux selection */ +#if SPI_SCLK_PIN % 2 == 0 +#    define SPI_SCLK_MUX_SEL PMUXE +#else +#    define SPI_SCLK_MUX_SEL PMUXO +#endif + +static pin_t currentSelectPin = NO_PIN; + +__attribute__((weak)) void spi_init(void) { +    static bool is_initialised = false; +    if (!is_initialised) { +        is_initialised = true; + +        DBGC(DC_SPI_INIT_BEGIN); + +        CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT); + +        // Set up MCU SPI pins +        PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PMUX[SAMD_PIN(SPI_DATAOUT_PIN) / 2].bit.SPI_DATAOUT_MUX_SEL = SPI_DATAOUT_MUX;  // MUX select for sercom +        PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PMUX[SAMD_PIN(SPI_SCLK_PIN) / 2].bit.SPI_SCLK_MUX_SEL          = SPI_SCLK_MUX;     // MUX select for sercom +        PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PINCFG[SAMD_PIN(SPI_DATAOUT_PIN)].bit.PMUXEN                = 1;                // MUX Enable +        PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PINCFG[SAMD_PIN(SPI_SCLK_PIN)].bit.PMUXEN                      = 1;                // MUX Enable + +        DBGC(DC_SPI_INIT_COMPLETE); +    } +} + +bool spi_start(pin_t csPin, bool lsbFirst, uint8_t mode, uint16_t divisor) { +    if (currentSelectPin != NO_PIN || csPin == NO_PIN) { +        return false; +    } + +    currentSelectPin = csPin; +    setPinOutput(currentSelectPin); +    writePinLow(currentSelectPin); + +    SPI_SERCOM->SPI.CTRLA.bit.DORD = lsbFirst;  // Data Order - LSB is transferred first +    SPI_SERCOM->SPI.CTRLA.bit.CPOL = 1;         // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising. +    SPI_SERCOM->SPI.CTRLA.bit.CPHA = 1;         // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample +    SPI_SERCOM->SPI.CTRLA.bit.DIPO = 3;         // Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.) +    SPI_SERCOM->SPI.CTRLA.bit.DOPO = 0;         // Data Output PAD[0], Serial Clock PAD[1] +    SPI_SERCOM->SPI.CTRLA.bit.MODE = 3;         // Operating Mode - Master operation + +    SPI_SERCOM->SPI.CTRLA.bit.ENABLE = 1;  // Enable - Peripheral is enabled or being enabled +    while (SPI_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { +        DBGC(DC_SPI_SYNC_ENABLING); +    } +    return true; +} + +spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { +    while (!(SPI_SERCOM->SPI.INTFLAG.bit.DRE)) { +        DBGC(DC_SPI_WRITE_DRE); +    } + +    for (uint16_t i = 0; i < length; i++) { +        SPI_SERCOM->SPI.DATA.bit.DATA = data[i]; +        while (!(SPI_SERCOM->SPI.INTFLAG.bit.TXC)) { +            DBGC(DC_SPI_WRITE_TXC_1); +        } +    } + +    return SPI_STATUS_SUCCESS; +} + +void spi_stop(void) { +    if (currentSelectPin != NO_PIN) { +        setPinOutput(currentSelectPin); +        writePinHigh(currentSelectPin); +        currentSelectPin = NO_PIN; +    } +} + +// Not implemented yet.... + +spi_status_t spi_write(uint8_t data); + +spi_status_t spi_read(void); + +spi_status_t spi_receive(uint8_t *data, uint16_t length); diff --git a/tmk_core/protocol/arm_atsam/spi_master.h b/tmk_core/protocol/arm_atsam/spi_master.h new file mode 100644 index 0000000000..26c55128be --- /dev/null +++ b/tmk_core/protocol/arm_atsam/spi_master.h @@ -0,0 +1,48 @@ +/* Copyright 2021 QMK + * + *  This program is free software: you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation, either version 3 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdbool.h> + +typedef int16_t spi_status_t; + +#define SPI_STATUS_SUCCESS (0) +#define SPI_STATUS_ERROR (-1) +#define SPI_STATUS_TIMEOUT (-2) + +#define SPI_TIMEOUT_IMMEDIATE (0) +#define SPI_TIMEOUT_INFINITE (0xFFFF) + +#ifdef __cplusplus +extern "C" { +#endif +void spi_init(void); + +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); + +spi_status_t spi_write(uint8_t data); + +spi_status_t spi_read(void); + +spi_status_t spi_transmit(const uint8_t *data, uint16_t length); + +spi_status_t spi_receive(uint8_t *data, uint16_t length); + +void spi_stop(void); +#ifdef __cplusplus +} +#endif diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.h b/tmk_core/protocol/arm_atsam/usb/usb2422.h deleted file mode 100644 index b4830b5bc8..0000000000 --- a/tmk_core/protocol/arm_atsam/usb/usb2422.h +++ /dev/null @@ -1,402 +0,0 @@ -/* -Copyright 2018 Massdrop Inc. - -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/>. -*/ - -#ifndef _USB2422_H_ -#define _USB2422_H_ - -#define REV_USB2422 0x100 - -#define USB2422_ADDR 0x58  // I2C device address, one instance - -#define USB2422_HUB_ACTIVE_GROUP 0  // PA -#define USB2422_HUB_ACTIVE_PIN 18   // 18 - -/* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint16_t VID_LSB : 8; -        uint16_t VID_MSB : 8; -    } bit;        /*!< Structure used for bit  access                  */ -    uint16_t reg; /*!< Type      used for register access              */ -} USB2422_VID_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint16_t PID_LSB : 8; -        uint16_t PID_MSB : 8; -    } bit;        /*!< Structure used for bit  access                  */ -    uint16_t reg; /*!< Type      used for register access              */ -} USB2422_PID_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint16_t DID_LSB : 8; -        uint16_t DID_MSB : 8; -    } bit;        /*!< Structure used for bit  access                  */ -    uint16_t reg; /*!< Type      used for register access              */ -} USB2422_DID_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t PORT_PWR : 1; -        uint8_t CURRENT_SNS : 2; -        uint8_t EOP_DISABLE : 1; -        uint8_t MTT_ENABLE : 1; -        uint8_t HS_DISABLE : 1; -        uint8_t : 1; -        uint8_t SELF_BUS_PWR : 1; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_CFG1_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t : 3; -        uint8_t COMPOUND : 1; -        uint8_t OC_TIMER : 2; -        uint8_t : 1; -        uint8_t DYNAMIC : 1; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_CFG2_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t STRING_EN : 1; -        uint8_t : 2; -        uint8_t PRTMAP_EN : 1; -        uint8_t : 4; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_CFG3_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t : 5; -        uint8_t PORT2_NR : 1; -        uint8_t PORT1_NR : 1; -        uint8_t : 1; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_NRD_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t : 1; -        uint8_t PORT1_DIS : 1; -        uint8_t PORT2_DIS : 1; -        uint8_t : 5; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_PDS_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t : 1; -        uint8_t PORT1_DIS : 1; -        uint8_t PORT2_DIS : 1; -        uint8_t : 5; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_PDB_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t MAX_PWR_SP : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_MAXPS_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t MAX_PWR_BP : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_MAXPB_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t HC_MAX_C_SP : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_HCMCS_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t HC_MAX_C_BP : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_HCMCB_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t POWER_ON_TIME : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_PWRT_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t LANGID_LSB : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_LANGID_LSB_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t LANGID_MSB : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_LANGID_MSB_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t MFR_STR_LEN : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_MFRSL_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t PRD_STR_LEN : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_PRDSL_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t SER_STR_LEN : 8; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_SERSL_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef uint16_t USB2422_MFRSTR_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef uint16_t USB2422_PRDSTR_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef uint16_t USB2422_SERSTR_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t : 1; -        uint8_t PORT1_BCE : 1; -        uint8_t PORT2_BCE : 1; -        uint8_t : 5; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_BCEN_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t BOOST : 2; -        uint8_t : 6; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_BOOSTUP_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t BOOST1 : 2; -        uint8_t BOOST2 : 2; -        uint8_t : 4; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_BOOSTDOWN_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t : 1; -        uint8_t PORT1_SP : 1; -        uint8_t PORT2_SP : 1; -        uint8_t : 5; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_PRTSP_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t PORT1_REMAP : 4; -        uint8_t PORT2_REMAP : 4; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_PRTR12_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ -#define USB2422_PRTR12_DISABLE 0 -#define USB2422_PRT12_P2TOL1 1 -#define USB2422_PRT12_P2XTOL2 2 -#define USB2422_PRT12_P1TOL1 1 -#define USB2422_PRT12_P1XTOL2 2 - -/* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef union { -    struct { -        uint8_t USB_ATTACH : 1; -        uint8_t RESET : 1; -        uint8_t INTF_PWRDN : 1; -        uint8_t : 5; -    } bit;       /*!< Structure used for bit  access                  */ -    uint8_t reg; /*!< Type      used for register access              */ -} USB2422_STCD_Type; -#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ - -/** \brief USB2422 device hardware registers */ -#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) -typedef struct { -    USB2422_VID_Type        VID;        /**< \brief Offset: 0x00*/ -    USB2422_PID_Type        PID;        /**< \brief Offset: 0x02*/ -    USB2422_DID_Type        DID;        /**< \brief Offset: 0x04*/ -    USB2422_CFG1_Type       CFG1;       /**< \brief Offset: 0x06*/ -    USB2422_CFG2_Type       CFG2;       /**< \brief Offset: 0x07*/ -    USB2422_CFG3_Type       CFG3;       /**< \brief Offset: 0x08*/ -    USB2422_NRD_Type        NRD;        /**< \brief Offset: 0x09*/ -    USB2422_PDS_Type        PDS;        /**< \brief Offset: 0x0A*/ -    USB2422_PDB_Type        PDB;        /**< \brief Offset: 0x0B*/ -    USB2422_MAXPS_Type      MAXPS;      /**< \brief Offset: 0x0C*/ -    USB2422_MAXPB_Type      MAXPB;      /**< \brief Offset: 0x0D*/ -    USB2422_HCMCS_Type      HCMCS;      /**< \brief Offset: 0x0E*/ -    USB2422_HCMCB_Type      HCMCB;      /**< \brief Offset: 0x0F*/ -    USB2422_PWRT_Type       PWRT;       /**< \brief Offset: 0x10*/ -    USB2422_LANGID_LSB_Type LANGID_LSB; /**< \brief Offset: 0x11*/ -    USB2422_LANGID_MSB_Type LANGID_MSB; /**< \brief Offset: 0x12*/ -    USB2422_MFRSL_Type      MFRSL;      /**< \brief Offset: 0x13*/ -    USB2422_PRDSL_Type      PRDSL;      /**< \brief Offset: 0x14*/ -    USB2422_SERSL_Type      SERSL;      /**< \brief Offset: 0x15*/ -    USB2422_MFRSTR_Type     MFRSTR[31]; /**< \brief Offset: 0x16*/ -    USB2422_PRDSTR_Type     PRDSTR[31]; /**< \brief Offset: 0x54*/ -    USB2422_SERSTR_Type     SERSTR[31]; /**< \brief Offset: 0x92*/ -    USB2422_BCEN_Type       BCEN;       /**< \brief Offset: 0xD0*/ -    uint8_t                 Reserved1[0x25]; -    USB2422_BOOSTUP_Type    BOOSTUP; /**< \brief Offset: 0xF6*/ -    uint8_t                 Reserved2[0x1]; -    USB2422_BOOSTDOWN_Type  BOOSTDOWN; /**< \brief Offset: 0xF8*/ -    uint8_t                 Reserved3[0x1]; -    USB2422_PRTSP_Type      PRTSP;  /**< \brief Offset: 0xFA*/ -    USB2422_PRTR12_Type     PRTR12; /**< \brief Offset: 0xFB*/ -    uint8_t                 Reserved4[0x3]; -    USB2422_STCD_Type       STCD; /**< \brief Offset: 0xFF*/ -} Usb2422; -#endif - -#define PORT_DETECT_RETRY_INTERVAL 2000 - -#define USB_EXTRA_ADC_THRESHOLD 900 - -#define USB_EXTRA_STATE_DISABLED 0 -#define USB_EXTRA_STATE_ENABLED 1 -#define USB_EXTRA_STATE_UNKNOWN 2 -#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3 - -#define USB_HOST_PORT_1 0 -#define USB_HOST_PORT_2 1 -#define USB_HOST_PORT_UNKNOWN 2 - -extern uint8_t usb_host_port; -extern uint8_t usb_extra_state; -extern uint8_t usb_extra_manual; -extern uint8_t usb_gcr_auto; - -void     USB2422_init(void); -void     USB_reset(void); -void     USB_configure(void); -uint16_t USB_active(void); -void     USB_set_host_by_voltage(void); -uint16_t adc_get(uint8_t muxpos); -uint8_t  USB2422_Port_Detect_Init(void); -void     USB_HandleExtraDevice(void); -void     USB_ExtraSetState(uint8_t state); - -#endif  //_USB2422_H_ diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.c b/tmk_core/protocol/arm_atsam/usb/usb_hub.c index a878cb6b7c..c5fd284aab 100644 --- a/tmk_core/protocol/arm_atsam/usb/usb2422.c +++ b/tmk_core/protocol/arm_atsam/usb/usb_hub.c @@ -16,25 +16,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  #include "arm_atsam_protocol.h" +#include "drivers/usb2422.h"  #include <string.h> -Usb2422       USB2422_shadow; -unsigned char i2c0_buf[34]; - -const uint16_t MFRNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'I', 'n', 'c', '.'};  // Massdrop Inc. -const uint16_t PRDNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'H', 'u', 'b'};       // Massdrop Hub -#ifndef MD_BOOTLOADER -// Serial number reported stops before first found space character or at last found character -const uint16_t SERNAME[] = {'U', 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e'};  // Unavailable -#else -// In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space -// The offset allows the application to use the factory programmed serial (which may differ from the physical serial label) -// Serial number reported stops before first found space character or when max size is reached -__attribute__((__aligned__(4))) const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = {'M', 'D', 'H', 'U', 'B', 'B', 'O', 'O', 'T', 'L', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'}; -// NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough -//      space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given -#endif  // MD_BOOTLOADER -  uint8_t usb_host_port;  #ifndef MD_BOOTLOADER @@ -47,29 +31,7 @@ uint8_t usb_gcr_auto;  uint16_t adc_extra; -void USB_write2422_block(void) { -    unsigned char *dest = i2c0_buf; -    unsigned char *src; -    unsigned char *base = (unsigned char *)&USB2422_shadow; - -    DBGC(DC_USB_WRITE2422_BLOCK_BEGIN); - -    for (src = base; src < base + 256; src += 32) { -        dest[0] = src - base; -        dest[1] = 32; -        memcpy(&dest[2], src, 32); -        i2c0_transmit(USB2422_ADDR, dest, 34, 50000); -        SERCOM0->I2CM.CTRLB.bit.CMD = 0x03; -        while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { -            DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); -        } -        wait_us(100); -    } - -    DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE); -} - -void USB2422_init(void) { +void USB_Hub_init(void) {      Gclk *   pgclk = GCLK;      Mclk *   pmclk = MCLK;      Port *   pport = PORT; @@ -147,9 +109,7 @@ void USB2422_init(void) {      pusb->DEVICE.QOSCTRL.bit.DQOS = 2;      pusb->DEVICE.QOSCTRL.bit.CQOS = 2; -    pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1; - -    i2c0_init();  // IC2 clk must be high at USB2422 reset release time to signal SMB configuration +    USB2422_init();      sr_exp_data.bit.HUB_CONNECT = 1;  // connect signal      sr_exp_data.bit.HUB_RESET_N = 1;  // reset high @@ -181,62 +141,16 @@ void USB_reset(void) {  }  void USB_configure(void) { -    Usb2422 *pusb2422 = &USB2422_shadow; -    memset(pusb2422, 0, sizeof(Usb2422)); - -    uint16_t *serial_use    = (uint16_t *)SERNAME;                 // Default to use SERNAME from this file -    uint8_t   serial_length = sizeof(SERNAME) / sizeof(uint16_t);  // Default to use SERNAME from this file -#ifndef MD_BOOTLOADER -    uint32_t serial_ptrloc = (uint32_t)&_srom - 4; -#else                                                      // MD_BOOTLOADER -    uint32_t serial_ptrloc = (uint32_t)&_erom - 4; -#endif                                                     // MD_BOOTLOADER -    uint32_t serial_address = *(uint32_t *)serial_ptrloc;  // Address of bootloader's serial number if available -      DBGC(DC_USB_CONFIGURE_BEGIN); -    if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc)  // Check for factory programmed serial address -    { -        if ((serial_address & 0xFF) % 4 == 0)  // Check alignment -        { -            serial_use    = (uint16_t *)(serial_address); -            serial_length = 0; -            while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) && serial_length < BOOTLOADER_SERIAL_MAX_SIZE) { -                serial_length++; -                DBGC(DC_USB_CONFIGURE_GET_SERIAL); -            } -        } -    } - -    // configure Usb2422 registers -    pusb2422->VID.reg               = 0x04D8;  // from Microchip 4/19/2018 -    pusb2422->PID.reg               = 0xEEC5;  // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub -    pusb2422->DID.reg               = 0x0101;  // BCD 01.01 -    pusb2422->CFG1.bit.SELF_BUS_PWR = 1;       // self powered for now -    pusb2422->CFG1.bit.HS_DISABLE   = 1;       // full or high speed -    // pusb2422->CFG2.bit.COMPOUND = 0; // compound device -    pusb2422->CFG3.bit.STRING_EN = 1;  // strings enabled -    // pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable -    pusb2422->MAXPB.reg = 20;  // 0mA -    pusb2422->HCMCB.reg = 20;  // 0mA -    pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t); -    pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t); -    pusb2422->SERSL.reg = serial_length; -    memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME)); -    memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME)); -    memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t)); -    // pusb2422->BOOSTUP.bit.BOOST=3;    //upstream port -    // pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port -    // pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close -    pusb2422->STCD.bit.USB_ATTACH = 1; -    USB_write2422_block(); +    USB2422_configure();      adc_extra = 0;      DBGC(DC_USB_CONFIGURE_COMPLETE);  } -uint16_t USB_active(void) { return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0; } +uint16_t USB_active(void) { return USB2422_active(); }  void USB_set_host_by_voltage(void) {      // UP is upstream device (HOST) @@ -314,7 +228,7 @@ void USB_set_host_by_voltage(void) {      DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);  } -uint8_t USB2422_Port_Detect_Init(void) { +uint8_t USB_Hub_Port_Detect_Init(void) {      uint32_t port_detect_retry_ms;      uint32_t tmod; diff --git a/tmk_core/protocol/arm_atsam/usb/usb_hub.h b/tmk_core/protocol/arm_atsam/usb/usb_hub.h new file mode 100644 index 0000000000..76b1e0a326 --- /dev/null +++ b/tmk_core/protocol/arm_atsam/usb/usb_hub.h @@ -0,0 +1,51 @@ +/* +Copyright 2018 Massdrop Inc. + +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/>. +*/ + +#ifndef _USB2422_H_ +#define _USB2422_H_ + +#define REV_USB2422 0x100 + +#define PORT_DETECT_RETRY_INTERVAL 2000 + +#define USB_EXTRA_ADC_THRESHOLD 900 + +#define USB_EXTRA_STATE_DISABLED 0 +#define USB_EXTRA_STATE_ENABLED 1 +#define USB_EXTRA_STATE_UNKNOWN 2 +#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3 + +#define USB_HOST_PORT_1 0 +#define USB_HOST_PORT_2 1 +#define USB_HOST_PORT_UNKNOWN 2 + +extern uint8_t usb_host_port; +extern uint8_t usb_extra_state; +extern uint8_t usb_extra_manual; +extern uint8_t usb_gcr_auto; + +void     USB_Hub_init(void); +uint8_t  USB_Hub_Port_Detect_Init(void); +void     USB_reset(void); +void     USB_configure(void); +uint16_t USB_active(void); +void     USB_set_host_by_voltage(void); +uint16_t adc_get(uint8_t muxpos); +void     USB_HandleExtraDevice(void); +void     USB_ExtraSetState(uint8_t state); + +#endif  //_USB2422_H_ diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c index 78a2e3fcbb..41752b2130 100644 --- a/tmk_core/protocol/chibios/chibios.c +++ b/tmk_core/protocol/chibios/chibios.c @@ -27,6 +27,7 @@  #include "keyboard.h"  #include "action.h"  #include "action_util.h" +#include "usb_device_state.h"  #include "mousekey.h"  #include "led.h"  #include "sendchar.h" @@ -42,12 +43,6 @@  #ifdef SLEEP_LED_ENABLE  #    include "sleep_led.h"  #endif -#ifdef SERIAL_LINK_ENABLE -#    include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -#    include "visualizer/visualizer.h" -#endif  #ifdef MIDI_ENABLE  #    include "qmk_midi.h"  #endif @@ -139,13 +134,15 @@ void boardInit(void) {  }  void protocol_setup(void) { +    usb_device_state_init(); +      // TESTING      // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); - -    keyboard_setup();  } -void protocol_init(void) { +static host_driver_t *driver = NULL; + +void protocol_pre_init(void) {      /* Init USB */      usb_event_queue_init();      init_usb_driver(&USB_DRIVER); @@ -154,19 +151,9 @@ void protocol_init(void) {      setup_midi();  #endif -#ifdef SERIAL_LINK_ENABLE -    init_serial_link(); -#endif - -#ifdef VISUALIZER_ENABLE -    visualizer_init(); -#endif - -    host_driver_t *driver = NULL; - -    /* Wait until the USB or serial link is active */ +    /* Wait until USB is active */      while (true) { -#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE) +#if defined(WAIT_FOR_USB)          if (USB_DRIVER.state == USB_ACTIVE) {              driver = &chibios_driver;              break; @@ -175,13 +162,6 @@ void protocol_init(void) {          driver = &chibios_driver;          break;  #endif -#ifdef SERIAL_LINK_ENABLE -        if (is_serial_link_connected()) { -            driver = get_serial_link_driver(); -            break; -        } -        serial_link_update(); -#endif          wait_ms(50);      } @@ -193,32 +173,18 @@ void protocol_init(void) {      wait_ms(50);      print("USB configured.\n"); - -    /* init TMK modules */ -    keyboard_init(); -    host_set_driver(driver); - -#ifdef SLEEP_LED_ENABLE -    sleep_led_init(); -#endif - -    print("Keyboard start.\n");  } -void protocol_task(void) { +void protocol_post_init(void) { host_set_driver(driver); } + +void protocol_pre_task(void) {      usb_event_queue_task();  #if !defined(NO_USB_STARTUP_CHECK)      if (USB_DRIVER.state == USB_SUSPENDED) {          print("[s]"); -#    ifdef VISUALIZER_ENABLE -        visualizer_suspend(); -#    endif          while (USB_DRIVER.state == USB_SUSPENDED) {              /* Do this in the suspended state */ -#    ifdef SERIAL_LINK_ENABLE -            serial_link_update(); -#    endif              suspend_power_down();  // on AVR this deep sleeps for 15ms              /* Remote wakeup */              if (suspend_wakeup_condition()) { @@ -232,14 +198,11 @@ void protocol_task(void) {  #    ifdef MOUSEKEY_ENABLE          mousekey_send();  #    endif /* MOUSEKEY_ENABLE */ - -#    ifdef VISUALIZER_ENABLE -        visualizer_resume(); -#    endif      }  #endif +} -    keyboard_task(); +void protocol_post_task(void) {  #ifdef CONSOLE_ENABLE      console_task();  #endif diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 04049c1a9a..a7db3e3ab1 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -39,6 +39,7 @@  #    include "led.h"  #endif  #include "wait.h" +#include "usb_device_state.h"  #include "usb_descriptor.h"  #include "usb_driver.h" @@ -70,7 +71,12 @@ uint8_t                keyboard_protocol __attribute__((aligned(2))) = 1;  uint8_t                keyboard_led_state                            = 0;  volatile uint16_t      keyboard_idle_count                           = 0;  static virtual_timer_t keyboard_idle_timer; -static void            keyboard_idle_timer_cb(void *arg); + +#if CH_KERNEL_MAJOR >= 7 +static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg); +#elif CH_KERNEL_MAJOR <= 6 +static void keyboard_idle_timer_cb(void *arg); +#endif  report_keyboard_t keyboard_report_sent = {{0}};  #ifdef MOUSE_ENABLE @@ -412,6 +418,7 @@ static inline bool usb_event_queue_dequeue(usbevent_t *event) {  }  static inline void usb_event_suspend_handler(void) { +    usb_device_state_set_suspend(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);  #ifdef SLEEP_LED_ENABLE      sleep_led_enable();  #endif /* SLEEP_LED_ENABLE */ @@ -419,6 +426,7 @@ static inline void usb_event_suspend_handler(void) {  static inline void usb_event_wakeup_handler(void) {      suspend_wakeup_init(); +    usb_device_state_set_resume(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);  #ifdef SLEEP_LED_ENABLE      sleep_led_disable();      // NOTE: converters may not accept this @@ -440,6 +448,15 @@ void usb_event_queue_task(void) {                  last_suspend_state = false;                  usb_event_wakeup_handler();                  break; +            case USB_EVENT_CONFIGURED: +                usb_device_state_set_configuration(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); +                break; +            case USB_EVENT_UNCONFIGURED: +                usb_device_state_set_configuration(false, 0); +                break; +            case USB_EVENT_RESET: +                usb_device_state_set_reset(); +                break;              default:                  // Nothing to do, we don't handle it.                  break; @@ -482,13 +499,14 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {              if (last_suspend_state) {                  usb_event_queue_enqueue(USB_EVENT_WAKEUP);              } +            usb_event_queue_enqueue(USB_EVENT_CONFIGURED);              return;          case USB_EVENT_SUSPEND: -            usb_event_queue_enqueue(USB_EVENT_SUSPEND);              /* Falls into.*/          case USB_EVENT_UNCONFIGURED:              /* Falls into.*/          case USB_EVENT_RESET: +            usb_event_queue_enqueue(event);              for (int i = 0; i < NUM_USB_DRIVERS; i++) {                  chSysLockFromISR();                  /* Disconnection event on suspend.*/ @@ -761,7 +779,12 @@ void kbd_sof_cb(USBDriver *usbp) { (void)usbp; }  /* Idle requests timer code   * callback (called from ISR, unlocked state) */ +#if CH_KERNEL_MAJOR >= 7 +static void keyboard_idle_timer_cb(struct ch_virtual_timer *timer, void *arg) { +    (void)timer; +#elif CH_KERNEL_MAJOR <= 6  static void keyboard_idle_timer_cb(void *arg) { +#endif      USBDriver *usbp = (USBDriver *)arg;      osalSysLockFromISR(); diff --git a/tmk_core/common/host.c b/tmk_core/protocol/host.c index f0c396b189..56d4bb0847 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/protocol/host.c @@ -30,8 +30,9 @@ extern keymap_config_t keymap_config;  #endif  static host_driver_t *driver; -static uint16_t       last_system_report   = 0; -static uint16_t       last_consumer_report = 0; +static uint16_t       last_system_report              = 0; +static uint16_t       last_consumer_report            = 0; +static uint32_t       last_programmable_button_report = 0;  void host_set_driver(host_driver_t *d) { driver = d; } @@ -122,6 +123,16 @@ void host_digitizer_send(digitizer_t *digitizer) {  __attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} +void host_programmable_button_send(uint32_t report) { +    if (report == last_programmable_button_report) return; +    last_programmable_button_report = report; + +    if (!driver) return; +    (*driver->send_programmable_button)(report); +} +  uint16_t host_last_system_report(void) { return last_system_report; }  uint16_t host_last_consumer_report(void) { return last_consumer_report; } + +uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; } diff --git a/tmk_core/common/host.h b/tmk_core/protocol/host.h index 2cffef6e15..6b15f0d0c1 100644 --- a/tmk_core/common/host.h +++ b/tmk_core/protocol/host.h @@ -47,9 +47,11 @@ void    host_keyboard_send(report_keyboard_t *report);  void    host_mouse_send(report_mouse_t *report);  void    host_system_send(uint16_t data);  void    host_consumer_send(uint16_t data); +void    host_programmable_button_send(uint32_t data);  uint16_t host_last_system_report(void);  uint16_t host_last_consumer_report(void); +uint32_t host_last_programmable_button_report(void);  #ifdef __cplusplus  } diff --git a/tmk_core/common/host_driver.h b/tmk_core/protocol/host_driver.h index 2aebca043d..affd0dcb34 100644 --- a/tmk_core/common/host_driver.h +++ b/tmk_core/protocol/host_driver.h @@ -29,6 +29,7 @@ typedef struct {      void (*send_mouse)(report_mouse_t *);      void (*send_system)(uint16_t);      void (*send_consumer)(uint16_t); +    void (*send_programmable_button)(uint32_t);  } host_driver_t;  void send_digitizer(report_digitizer_t *report);
\ No newline at end of file diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c deleted file mode 100644 index a19443976e..0000000000 --- a/tmk_core/protocol/ibm4704.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> -*/ -#include <stdbool.h> -#include <util/delay.h> -#include "debug.h" -#include "ring_buffer.h" -#include "ibm4704.h" - -#define WAIT(stat, us, err)      \ -    do {                         \ -        if (!wait_##stat(us)) {  \ -            ibm4704_error = err; \ -            goto ERROR;          \ -        }                        \ -    } while (0) - -uint8_t ibm4704_error = 0; - -void ibm4704_init(void) { -    inhibit();  // keep keyboard from sending -    IBM4704_INT_INIT(); -    IBM4704_INT_ON(); -    idle();  // allow keyboard sending -} - -/* -Host to Keyboard ----------------- -Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. - -        ____        __   __   __   __   __   __   __   __   __   ________ -Clock       \______/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/ -            ^   ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___ -Data    ____|__/    X____X____X____X____X____X____X____X____X____X   \___ -            |  Start   0    1    2    3    4    5    6    7    P   Stop -            Request by host - -Start bit:  can be long as 300-350us. -Request:    Host pulls Clock line down to request to send a command. -Timing:     After Request keyboard pull up Data and down Clock line to low for start bit. -            After request host release Clock line once Data line becomes hi. -            Host writes a bit while Clock is hi and Keyboard reads while low. -Stop bit:   Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo. -*/ -uint8_t ibm4704_send(uint8_t data) { -    bool parity   = true;  // odd parity -    ibm4704_error = 0; - -    IBM4704_INT_OFF(); - -    /* Request to send */ -    idle(); -    clock_lo(); - -    /* wait for Start bit(Clock:lo/Data:hi) */ -    WAIT(data_hi, 300, 0x30); - -    /* Data bit */ -    for (uint8_t i = 0; i < 8; i++) { -        WAIT(clock_hi, 100, 0x40 + i); -        if (data & (1 << i)) { -            parity = !parity; -            data_hi(); -        } else { -            data_lo(); -        } -        WAIT(clock_lo, 100, 0x48 + i); -    } - -    /* Parity bit */ -    WAIT(clock_hi, 100, 0x34); -    if (parity) { -        data_hi(); -    } else { -        data_lo(); -    } -    WAIT(clock_lo, 100, 0x35); - -    /* Stop bit */ -    WAIT(clock_hi, 100, 0x34); -    data_hi(); - -    /* End */ -    WAIT(data_lo, 100, 0x36); - -    idle(); -    IBM4704_INT_ON(); -    return 0; -ERROR: -    idle(); -    if (ibm4704_error > 0x30) { -        xprintf("S:%02X ", ibm4704_error); -    } -    IBM4704_INT_ON(); -    return -1; -} - -/* wait forever to receive data */ -uint8_t ibm4704_recv_response(void) { -    while (!rbuf_has_data()) { -        _delay_ms(1); -    } -    return rbuf_dequeue(); -} - -uint8_t ibm4704_recv(void) { -    if (rbuf_has_data()) { -        return rbuf_dequeue(); -    } else { -        return -1; -    } -} - -/* -Keyboard to Host ----------------- -Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. - -        ____       __   __   __   __   __   __   __   __   __   _______ -Clock       \_____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/ -             ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ -Data    ____/    X____X____X____X____X____X____X____X____X____X________ -            Start   0    1    2    3    4    5    6    7    P  Stop - -Start bit:  can be long as 300-350us. -Inhibit:    Pull Data line down to inhibit keyboard to send. -Timing:     Host reads bit while Clock is hi.(rising edge) -Stop bit:   Keyboard pulls down Data line to lo after 9th clock. -*/ -ISR(IBM4704_INT_VECT) { -    static enum { BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP } state = BIT0; -    // LSB first -    static uint8_t data = 0; -    // Odd parity -    static uint8_t parity = false; - -    ibm4704_error = 0; - -    switch (state) { -        case BIT0: -        case BIT1: -        case BIT2: -        case BIT3: -        case BIT4: -        case BIT5: -        case BIT6: -        case BIT7: -            data >>= 1; -            if (data_in()) { -                data |= 0x80; -                parity = !parity; -            } -            break; -        case PARITY: -            if (data_in()) { -                parity = !parity; -            } -            if (!parity) goto ERROR; -            break; -        case STOP: -            // Data:Low -            WAIT(data_lo, 100, state); -            if (!rbuf_enqueue(data)) { -                print("rbuf: full\n"); -            } -            ibm4704_error = IBM4704_ERR_NONE; -            goto DONE; -            break; -        default: -            goto ERROR; -    } -    state++; -    goto RETURN; -ERROR: -    ibm4704_error = state; -    while (ibm4704_send(0xFE)) _delay_ms(1);  // resend -    xprintf("R:%02X%02X\n", state, data); -DONE: -    state  = BIT0; -    data   = 0; -    parity = false; -RETURN: -    return; -} diff --git a/tmk_core/protocol/ibm4704.h b/tmk_core/protocol/ibm4704.h deleted file mode 100644 index 4f88d148b3..0000000000 --- a/tmk_core/protocol/ibm4704.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2014 Jun WAKO <[email protected]> -*/ - -#pragma once - -#define IBM4704_ERR_NONE 0 -#define IBM4704_ERR_PARITY 0x70 - -void    ibm4704_init(void); -uint8_t ibm4704_send(uint8_t data); -uint8_t ibm4704_recv_response(void); -uint8_t ibm4704_recv(void); - -/* Check pin configuration */ -#if !(defined(IBM4704_CLOCK_PORT) && defined(IBM4704_CLOCK_PIN) && defined(IBM4704_CLOCK_DDR) && defined(IBM4704_CLOCK_BIT)) -#    error "ibm4704 clock pin configuration is required in config.h" -#endif - -#if !(defined(IBM4704_DATA_PORT) && defined(IBM4704_DATA_PIN) && defined(IBM4704_DATA_DDR) && defined(IBM4704_DATA_BIT)) -#    error "ibm4704 data pin configuration is required in config.h" -#endif - -/*-------------------------------------------------------------------- - * static functions - *------------------------------------------------------------------*/ -static inline void clock_lo(void) { -    IBM4704_CLOCK_PORT &= ~(1 << IBM4704_CLOCK_BIT); -    IBM4704_CLOCK_DDR |= (1 << IBM4704_CLOCK_BIT); -} -static inline void clock_hi(void) { -    /* input with pull up */ -    IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT); -    IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT); -} -static inline bool clock_in(void) { -    IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT); -    IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT); -    _delay_us(1); -    return IBM4704_CLOCK_PIN & (1 << IBM4704_CLOCK_BIT); -} -static inline void data_lo(void) { -    IBM4704_DATA_PORT &= ~(1 << IBM4704_DATA_BIT); -    IBM4704_DATA_DDR |= (1 << IBM4704_DATA_BIT); -} -static inline void data_hi(void) { -    /* input with pull up */ -    IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT); -    IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT); -} -static inline bool data_in(void) { -    IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT); -    IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT); -    _delay_us(1); -    return IBM4704_DATA_PIN & (1 << IBM4704_DATA_BIT); -} - -static inline uint16_t wait_clock_lo(uint16_t us) { -    while (clock_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_clock_hi(uint16_t us) { -    while (!clock_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_lo(uint16_t us) { -    while (data_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_hi(uint16_t us) { -    while (!data_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} - -/* idle state that device can send */ -static inline void idle(void) { -    clock_hi(); -    data_hi(); -} - -/* inhibit device to send - * keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low. - */ -static inline void inhibit(void) { -    clock_hi(); -    data_lo(); -} diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk index c8935dacb7..00fec478ac 100644 --- a/tmk_core/protocol/lufa.mk +++ b/tmk_core/protocol/lufa.mk @@ -3,7 +3,6 @@ LUFA_DIR = protocol/lufa  # Path to the LUFA library  LUFA_PATH = $(LIB_PATH)/lufa -  # Create the LUFA source path variables by including the LUFA makefile  ifneq (, $(wildcard $(LUFA_PATH)/LUFA/Build/lufa_sources.mk))      # New build system from 20120730 @@ -22,23 +21,6 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)  	include $(TMK_PATH)/protocol/midi.mk  endif -ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) -	LUFA_SRC += outputselect.c \ -		$(TMK_DIR)/protocol/serial_uart.c -endif - -ifeq ($(strip $(BLUETOOTH)), AdafruitBLE) -	LUFA_SRC += spi_master.c \ -		analog.c \ -		outputselect.c \ -		$(LUFA_DIR)/adafruit_ble.cpp -endif - -ifeq ($(strip $(BLUETOOTH)), RN42) -	LUFA_SRC += outputselect.c \ -		$(TMK_DIR)/protocol/serial_uart.c -endif -  ifeq ($(strip $(VIRTSER_ENABLE)), yes)  	LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c  endif @@ -50,19 +32,10 @@ SRC += $(LUFA_DIR)/usb_util.c  VPATH += $(TMK_PATH)/$(LUFA_DIR)  VPATH += $(LUFA_PATH) -# Option modules -#ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) -#endif - -#ifdef EXTRAKEY_ENABLE -#endif -  # LUFA library compile-time options and predefined tokens  LUFA_OPTS  = -DUSB_DEVICE_ONLY  LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS  LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT -LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8  LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8  LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1 diff --git a/tmk_core/protocol/lufa/adafruit_ble.cpp b/tmk_core/protocol/lufa/adafruit_ble.cpp deleted file mode 100644 index 3f2cc35734..0000000000 --- a/tmk_core/protocol/lufa/adafruit_ble.cpp +++ /dev/null @@ -1,701 +0,0 @@ -#include "adafruit_ble.h" - -#include <stdio.h> -#include <stdlib.h> -#include <alloca.h> -#include "debug.h" -#include "timer.h" -#include "action_util.h" -#include "ringbuffer.hpp" -#include <string.h> -#include "spi_master.h" -#include "wait.h" -#include "analog.h" -#include "progmem.h" - -// These are the pin assignments for the 32u4 boards. -// You may define them to something else in your config.h -// if yours is wired up differently. -#ifndef AdafruitBleResetPin -#    define AdafruitBleResetPin D4 -#endif - -#ifndef AdafruitBleCSPin -#    define AdafruitBleCSPin B4 -#endif - -#ifndef AdafruitBleIRQPin -#    define AdafruitBleIRQPin E6 -#endif - -#ifndef AdafruitBleSpiClockSpeed -#    define AdafruitBleSpiClockSpeed 4000000UL  // SCK frequency -#endif - -#define SCK_DIVISOR (F_CPU / AdafruitBleSpiClockSpeed) - -#define SAMPLE_BATTERY -#define ConnectionUpdateInterval 1000 /* milliseconds */ - -#ifndef BATTERY_LEVEL_PIN -#    define BATTERY_LEVEL_PIN B5 -#endif - -static struct { -    bool is_connected; -    bool initialized; -    bool configured; - -#define ProbedEvents 1 -#define UsingEvents 2 -    bool event_flags; - -#ifdef SAMPLE_BATTERY -    uint16_t last_battery_update; -    uint32_t vbat; -#endif -    uint16_t last_connection_update; -} state; - -// Commands are encoded using SDEP and sent via SPI -// https://github.com/adafruit/Adafruit_BluefruitLE_nRF51/blob/master/SDEP.md - -#define SdepMaxPayload 16 -struct sdep_msg { -    uint8_t type; -    uint8_t cmd_low; -    uint8_t cmd_high; -    struct __attribute__((packed)) { -        uint8_t len : 7; -        uint8_t more : 1; -    }; -    uint8_t payload[SdepMaxPayload]; -} __attribute__((packed)); - -// The recv latency is relatively high, so when we're hammering keys quickly, -// we want to avoid waiting for the responses in the matrix loop.  We maintain -// a short queue for that.  Since there is quite a lot of space overhead for -// the AT command representation wrapped up in SDEP, we queue the minimal -// information here. - -enum queue_type { -    QTKeyReport,  // 1-byte modifier + 6-byte key report -    QTConsumer,   // 16-bit key code -#ifdef MOUSE_ENABLE -    QTMouseMove,  // 4-byte mouse report -#endif -}; - -struct queue_item { -    enum queue_type queue_type; -    uint16_t        added; -    union __attribute__((packed)) { -        struct __attribute__((packed)) { -            uint8_t modifier; -            uint8_t keys[6]; -        } key; - -        uint16_t consumer; -        struct __attribute__((packed)) { -            int8_t  x, y, scroll, pan; -            uint8_t buttons; -        } mousemove; -    }; -}; - -// Items that we wish to send -static RingBuffer<queue_item, 40> send_buf; -// Pending response; while pending, we can't send any more requests. -// This records the time at which we sent the command for which we -// are expecting a response. -static RingBuffer<uint16_t, 2> resp_buf; - -static bool process_queue_item(struct queue_item *item, uint16_t timeout); - -enum sdep_type { -    SdepCommand       = 0x10, -    SdepResponse      = 0x20, -    SdepAlert         = 0x40, -    SdepError         = 0x80, -    SdepSlaveNotReady = 0xFE,  // Try again later -    SdepSlaveOverflow = 0xFF,  // You read more data than is available -}; - -enum ble_cmd { -    BleInitialize = 0xBEEF, -    BleAtWrapper  = 0x0A00, -    BleUartTx     = 0x0A01, -    BleUartRx     = 0x0A02, -}; - -enum ble_system_event_bits { -    BleSystemConnected    = 0, -    BleSystemDisconnected = 1, -    BleSystemUartRx       = 8, -    BleSystemMidiRx       = 10, -}; - -#define SdepTimeout 150             /* milliseconds */ -#define SdepShortTimeout 10         /* milliseconds */ -#define SdepBackOff 25              /* microseconds */ -#define BatteryUpdateInterval 10000 /* milliseconds */ - -static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout = SdepTimeout); -static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose = false); - -// Send a single SDEP packet -static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) { -    spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); -    uint16_t timerStart = timer_read(); -    bool     success    = false; -    bool     ready      = false; - -    do { -        ready = spi_write(msg->type) != SdepSlaveNotReady; -        if (ready) { -            break; -        } - -        // Release it and let it initialize -        spi_stop(); -        wait_us(SdepBackOff); -        spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); -    } while (timer_elapsed(timerStart) < timeout); - -    if (ready) { -        // Slave is ready; send the rest of the packet -        spi_transmit(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload)) + msg->len); -        success = true; -    } - -    spi_stop(); - -    return success; -} - -static inline void sdep_build_pkt(struct sdep_msg *msg, uint16_t command, const uint8_t *payload, uint8_t len, bool moredata) { -    msg->type     = SdepCommand; -    msg->cmd_low  = command & 0xFF; -    msg->cmd_high = command >> 8; -    msg->len      = len; -    msg->more     = (moredata && len == SdepMaxPayload) ? 1 : 0; - -    static_assert(sizeof(*msg) == 20, "msg is correctly packed"); - -    memcpy(msg->payload, payload, len); -} - -// Read a single SDEP packet -static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) { -    bool     success    = false; -    uint16_t timerStart = timer_read(); -    bool     ready      = false; - -    do { -        ready = readPin(AdafruitBleIRQPin); -        if (ready) { -            break; -        } -        wait_us(1); -    } while (timer_elapsed(timerStart) < timeout); - -    if (ready) { -        spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); - -        do { -            // Read the command type, waiting for the data to be ready -            msg->type = spi_read(); -            if (msg->type == SdepSlaveNotReady || msg->type == SdepSlaveOverflow) { -                // Release it and let it initialize -                spi_stop(); -                wait_us(SdepBackOff); -                spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); -                continue; -            } - -            // Read the rest of the header -            spi_receive(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload))); - -            // and get the payload if there is any -            if (msg->len <= SdepMaxPayload) { -                spi_receive(msg->payload, msg->len); -            } -            success = true; -            break; -        } while (timer_elapsed(timerStart) < timeout); - -        spi_stop(); -    } -    return success; -} - -static void resp_buf_read_one(bool greedy) { -    uint16_t last_send; -    if (!resp_buf.peek(last_send)) { -        return; -    } - -    if (readPin(AdafruitBleIRQPin)) { -        struct sdep_msg msg; - -    again: -        if (sdep_recv_pkt(&msg, SdepTimeout)) { -            if (!msg.more) { -                // We got it; consume this entry -                resp_buf.get(last_send); -                dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send)); -            } - -            if (greedy && resp_buf.peek(last_send) && readPin(AdafruitBleIRQPin)) { -                goto again; -            } -        } - -    } else if (timer_elapsed(last_send) > SdepTimeout * 2) { -        dprintf("waiting_for_result: timeout, resp_buf size %d\n", (int)resp_buf.size()); - -        // Timed out: consume this entry -        resp_buf.get(last_send); -    } -} - -static void send_buf_send_one(uint16_t timeout = SdepTimeout) { -    struct queue_item item; - -    // Don't send anything more until we get an ACK -    if (!resp_buf.empty()) { -        return; -    } - -    if (!send_buf.peek(item)) { -        return; -    } -    if (process_queue_item(&item, timeout)) { -        // commit that peek -        send_buf.get(item); -        dprintf("send_buf_send_one: have %d remaining\n", (int)send_buf.size()); -    } else { -        dprint("failed to send, will retry\n"); -        wait_ms(SdepTimeout); -        resp_buf_read_one(true); -    } -} - -static void resp_buf_wait(const char *cmd) { -    bool didPrint = false; -    while (!resp_buf.empty()) { -        if (!didPrint) { -            dprintf("wait on buf for %s\n", cmd); -            didPrint = true; -        } -        resp_buf_read_one(true); -    } -} - -static bool ble_init(void) { -    state.initialized  = false; -    state.configured   = false; -    state.is_connected = false; - -    setPinInput(AdafruitBleIRQPin); - -    spi_init(); - -    // Perform a hardware reset -    setPinOutput(AdafruitBleResetPin); -    writePinHigh(AdafruitBleResetPin); -    writePinLow(AdafruitBleResetPin); -    wait_ms(10); -    writePinHigh(AdafruitBleResetPin); - -    wait_ms(1000);  // Give it a second to initialize - -    state.initialized = true; -    return state.initialized; -} - -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) { -    char *dest = resp; -    char *end  = dest + resplen; - -    while (true) { -        struct sdep_msg msg; - -        if (!sdep_recv_pkt(&msg, 2 * SdepTimeout)) { -            dprint("sdep_recv_pkt failed\n"); -            return false; -        } - -        if (msg.type != SdepResponse) { -            *resp = 0; -            return false; -        } - -        uint8_t len = min(msg.len, end - dest); -        if (len > 0) { -            memcpy(dest, msg.payload, len); -            dest += len; -        } - -        if (!msg.more) { -            // No more data is expected! -            break; -        } -    } - -    // Ensure the response is NUL terminated -    *dest = 0; - -    // "Parse" the result text; we want to snip off the trailing OK or ERROR line -    // Rewind past the possible trailing CRLF so that we can strip it -    --dest; -    while (dest > resp && (dest[0] == '\n' || dest[0] == '\r')) { -        *dest = 0; -        --dest; -    } - -    // Look back for start of preceeding line -    char *last_line = strrchr(resp, '\n'); -    if (last_line) { -        ++last_line; -    } else { -        last_line = resp; -    } - -    bool              success       = false; -    static const char kOK[] PROGMEM = "OK"; - -    success = !strcmp_P(last_line, kOK); - -    if (verbose || !success) { -        dprintf("result: %s\n", resp); -    } -    return success; -} - -static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout) { -    const char *    end = cmd + strlen(cmd); -    struct sdep_msg msg; - -    if (verbose) { -        dprintf("ble send: %s\n", cmd); -    } - -    if (resp) { -        // They want to decode the response, so we need to flush and wait -        // for all pending I/O to finish before we start this one, so -        // that we don't confuse the results -        resp_buf_wait(cmd); -        *resp = 0; -    } - -    // Fragment the command into a series of SDEP packets -    while (end - cmd > SdepMaxPayload) { -        sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, SdepMaxPayload, true); -        if (!sdep_send_pkt(&msg, timeout)) { -            return false; -        } -        cmd += SdepMaxPayload; -    } - -    sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, end - cmd, false); -    if (!sdep_send_pkt(&msg, timeout)) { -        return false; -    } - -    if (resp == NULL) { -        uint16_t now = timer_read(); -        while (!resp_buf.enqueue(now)) { -            resp_buf_read_one(false); -        } -        uint16_t later = timer_read(); -        if (TIMER_DIFF_16(later, now) > 0) { -            dprintf("waited %dms for resp_buf\n", TIMER_DIFF_16(later, now)); -        } -        return true; -    } - -    return read_response(resp, resplen, verbose); -} - -bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose) { -    char *cmdbuf = (char *)alloca(strlen_P(cmd) + 1); -    strcpy_P(cmdbuf, cmd); -    return at_command(cmdbuf, resp, resplen, verbose); -} - -bool adafruit_ble_is_connected(void) { return state.is_connected; } - -bool adafruit_ble_enable_keyboard(void) { -    char resbuf[128]; - -    if (!state.initialized && !ble_init()) { -        return false; -    } - -    state.configured = false; - -    // Disable command echo -    static const char kEcho[] PROGMEM = "ATE=0"; -    // Make the advertised name match the keyboard -    static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT); -    // Turn on keyboard support -    static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1"; - -    // Adjust intervals to improve latency.  This causes the "central" -    // system (computer/tablet) to poll us every 10-30 ms.  We can't -    // set a smaller value than 10ms, and 30ms seems to be the natural -    // processing time on my macbook.  Keeping it constrained to that -    // feels reasonable to type to. -    static const char kGapIntervals[] PROGMEM = "AT+GAPINTERVALS=10,30,,"; - -    // Reset the device so that it picks up the above changes -    static const char kATZ[] PROGMEM = "ATZ"; - -    // Turn down the power level a bit -    static const char  kPower[] PROGMEM             = "AT+BLEPOWERLEVEL=-12"; -    static PGM_P const configure_commands[] PROGMEM = { -        kEcho, kGapIntervals, kGapDevName, kHidEnOn, kPower, kATZ, -    }; - -    uint8_t i; -    for (i = 0; i < sizeof(configure_commands) / sizeof(configure_commands[0]); ++i) { -        PGM_P cmd; -        memcpy_P(&cmd, configure_commands + i, sizeof(cmd)); - -        if (!at_command_P(cmd, resbuf, sizeof(resbuf))) { -            dprintf("failed BLE command: %S: %s\n", cmd, resbuf); -            goto fail; -        } -    } - -    state.configured = true; - -    // Check connection status in a little while; allow the ATZ time -    // to kick in. -    state.last_connection_update = timer_read(); -fail: -    return state.configured; -} - -static void set_connected(bool connected) { -    if (connected != state.is_connected) { -        if (connected) { -            dprint("BLE connected\n"); -        } else { -            dprint("BLE disconnected\n"); -        } -        state.is_connected = connected; - -        // TODO: if modifiers are down on the USB interface and -        // we cut over to BLE or vice versa, they will remain stuck. -        // This feels like a good point to do something like clearing -        // the keyboard and/or generating a fake all keys up message. -        // However, I've noticed that it takes a couple of seconds -        // for macOS to to start recognizing key presses after BLE -        // is in the connected state, so I worry that doing that -        // here may not be good enough. -    } -} - -void adafruit_ble_task(void) { -    char resbuf[48]; - -    if (!state.configured && !adafruit_ble_enable_keyboard()) { -        return; -    } -    resp_buf_read_one(true); -    send_buf_send_one(SdepShortTimeout); - -    if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(AdafruitBleIRQPin)) { -        // Must be an event update -        if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) { -            uint32_t mask = strtoul(resbuf, NULL, 16); - -            if (mask & BleSystemConnected) { -                set_connected(true); -            } else if (mask & BleSystemDisconnected) { -                set_connected(false); -            } -        } -    } - -    if (timer_elapsed(state.last_connection_update) > ConnectionUpdateInterval) { -        bool shouldPoll = true; -        if (!(state.event_flags & ProbedEvents)) { -            // Request notifications about connection status changes. -            // This only works in SPIFRIEND firmware > 0.6.7, which is why -            // we check for this conditionally here. -            // Note that at the time of writing, HID reports only work correctly -            // with Apple products on firmware version 0.6.7! -            // https://forums.adafruit.com/viewtopic.php?f=8&t=104052 -            if (at_command_P(PSTR("AT+EVENTENABLE=0x1"), resbuf, sizeof(resbuf))) { -                at_command_P(PSTR("AT+EVENTENABLE=0x2"), resbuf, sizeof(resbuf)); -                state.event_flags |= UsingEvents; -            } -            state.event_flags |= ProbedEvents; - -            // leave shouldPoll == true so that we check at least once -            // before relying solely on events -        } else { -            shouldPoll = false; -        } - -        static const char kGetConn[] PROGMEM = "AT+GAPGETCONN"; -        state.last_connection_update         = timer_read(); - -        if (at_command_P(kGetConn, resbuf, sizeof(resbuf))) { -            set_connected(atoi(resbuf)); -        } -    } - -#ifdef SAMPLE_BATTERY -    if (timer_elapsed(state.last_battery_update) > BatteryUpdateInterval && resp_buf.empty()) { -        state.last_battery_update = timer_read(); - -        state.vbat = analogReadPin(BATTERY_LEVEL_PIN); -    } -#endif -} - -static bool process_queue_item(struct queue_item *item, uint16_t timeout) { -    char cmdbuf[48]; -    char fmtbuf[64]; - -    // Arrange to re-check connection after keys have settled -    state.last_connection_update = timer_read(); - -#if 1 -    if (TIMER_DIFF_16(state.last_connection_update, item->added) > 0) { -        dprintf("send latency %dms\n", TIMER_DIFF_16(state.last_connection_update, item->added)); -    } -#endif - -    switch (item->queue_type) { -        case QTKeyReport: -            strcpy_P(fmtbuf, PSTR("AT+BLEKEYBOARDCODE=%02x-00-%02x-%02x-%02x-%02x-%02x-%02x")); -            snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->key.modifier, item->key.keys[0], item->key.keys[1], item->key.keys[2], item->key.keys[3], item->key.keys[4], item->key.keys[5]); -            return at_command(cmdbuf, NULL, 0, true, timeout); - -        case QTConsumer: -            strcpy_P(fmtbuf, PSTR("AT+BLEHIDCONTROLKEY=0x%04x")); -            snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->consumer); -            return at_command(cmdbuf, NULL, 0, true, timeout); - -#ifdef MOUSE_ENABLE -        case QTMouseMove: -            strcpy_P(fmtbuf, PSTR("AT+BLEHIDMOUSEMOVE=%d,%d,%d,%d")); -            snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->mousemove.x, item->mousemove.y, item->mousemove.scroll, item->mousemove.pan); -            if (!at_command(cmdbuf, NULL, 0, true, timeout)) { -                return false; -            } -            strcpy_P(cmdbuf, PSTR("AT+BLEHIDMOUSEBUTTON=")); -            if (item->mousemove.buttons & MOUSE_BTN1) { -                strcat(cmdbuf, "L"); -            } -            if (item->mousemove.buttons & MOUSE_BTN2) { -                strcat(cmdbuf, "R"); -            } -            if (item->mousemove.buttons & MOUSE_BTN3) { -                strcat(cmdbuf, "M"); -            } -            if (item->mousemove.buttons == 0) { -                strcat(cmdbuf, "0"); -            } -            return at_command(cmdbuf, NULL, 0, true, timeout); -#endif -        default: -            return true; -    } -} - -void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) { -    struct queue_item item; -    bool              didWait = false; - -    item.queue_type   = QTKeyReport; -    item.key.modifier = hid_modifier_mask; -    item.added        = timer_read(); - -    while (nkeys >= 0) { -        item.key.keys[0] = keys[0]; -        item.key.keys[1] = nkeys >= 1 ? keys[1] : 0; -        item.key.keys[2] = nkeys >= 2 ? keys[2] : 0; -        item.key.keys[3] = nkeys >= 3 ? keys[3] : 0; -        item.key.keys[4] = nkeys >= 4 ? keys[4] : 0; -        item.key.keys[5] = nkeys >= 5 ? keys[5] : 0; - -        if (!send_buf.enqueue(item)) { -            if (!didWait) { -                dprint("wait for buf space\n"); -                didWait = true; -            } -            send_buf_send_one(); -            continue; -        } - -        if (nkeys <= 6) { -            return; -        } - -        nkeys -= 6; -        keys += 6; -    } -} - -void adafruit_ble_send_consumer_key(uint16_t usage) { -    struct queue_item item; - -    item.queue_type = QTConsumer; -    item.consumer   = usage; - -    while (!send_buf.enqueue(item)) { -        send_buf_send_one(); -    } -} - -#ifdef MOUSE_ENABLE -void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) { -    struct queue_item item; - -    item.queue_type        = QTMouseMove; -    item.mousemove.x       = x; -    item.mousemove.y       = y; -    item.mousemove.scroll  = scroll; -    item.mousemove.pan     = pan; -    item.mousemove.buttons = buttons; - -    while (!send_buf.enqueue(item)) { -        send_buf_send_one(); -    } -} -#endif - -uint32_t adafruit_ble_read_battery_voltage(void) { return state.vbat; } - -bool adafruit_ble_set_mode_leds(bool on) { -    if (!state.configured) { -        return false; -    } - -    // The "mode" led is the red blinky one -    at_command_P(on ? PSTR("AT+HWMODELED=1") : PSTR("AT+HWMODELED=0"), NULL, 0); - -    // Pin 19 is the blue "connected" LED; turn that off too. -    // When turning LEDs back on, don't turn that LED on if we're -    // not connected, as that would be confusing. -    at_command_P(on && state.is_connected ? PSTR("AT+HWGPIO=19,1") : PSTR("AT+HWGPIO=19,0"), NULL, 0); -    return true; -} - -// https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel -bool adafruit_ble_set_power_level(int8_t level) { -    char cmd[46]; -    if (!state.configured) { -        return false; -    } -    snprintf(cmd, sizeof(cmd), "AT+BLEPOWERLEVEL=%d", level); -    return at_command(cmd, NULL, 0, false); -} diff --git a/tmk_core/protocol/lufa/adafruit_ble.h b/tmk_core/protocol/lufa/adafruit_ble.h deleted file mode 100644 index b43e0771d9..0000000000 --- a/tmk_core/protocol/lufa/adafruit_ble.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Bluetooth Low Energy Protocol for QMK. - * Author: Wez Furlong, 2016 - * Supports the Adafruit BLE board built around the nRF51822 chip. - */ - -#pragma once - -#include <stdbool.h> -#include <stdint.h> -#include <string.h> - -#include "config_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Instruct the module to enable HID keyboard support and reset */ -extern bool adafruit_ble_enable_keyboard(void); - -/* Query to see if the BLE module is connected */ -extern bool adafruit_ble_query_is_connected(void); - -/* Returns true if we believe that the BLE module is connected. - * This uses our cached understanding that is maintained by - * calling ble_task() periodically. */ -extern bool adafruit_ble_is_connected(void); - -/* Call this periodically to process BLE-originated things */ -extern void adafruit_ble_task(void); - -/* Generates keypress events for a set of keys. - * The hid modifier mask specifies the state of the modifier keys for - * this set of keys. - * Also sends a key release indicator, so that the keys do not remain - * held down. */ -extern void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys); - -/* Send a consumer usage. - * (milliseconds) */ -extern void adafruit_ble_send_consumer_key(uint16_t usage); - -#ifdef MOUSE_ENABLE -/* Send a mouse/wheel movement report. - * The parameters are signed and indicate positive or negative direction - * change. */ -extern void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons); -#endif - -/* Compute battery voltage by reading an analog pin. - * Returns the integer number of millivolts */ -extern uint32_t adafruit_ble_read_battery_voltage(void); - -extern bool adafruit_ble_set_mode_leds(bool on); -extern bool adafruit_ble_set_power_level(int8_t level); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 5b56e8a03c..e3be96d93d 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -52,6 +52,7 @@  #include "usb_descriptor.h"  #include "lufa.h"  #include "quantum.h" +#include "usb_device_state.h"  #include <util/atomic.h>  #ifdef NKRO_ENABLE @@ -142,7 +143,8 @@ static void    send_keyboard(report_keyboard_t *report);  static void    send_mouse(report_mouse_t *report);  static void    send_system(uint16_t data);  static void    send_consumer(uint16_t data); -host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; +static void    send_programmable_button(uint32_t data); +host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};  #ifdef VIRTSER_ENABLE  // clang-format off @@ -413,7 +415,10 @@ void EVENT_USB_Device_Disconnect(void) {   *   * FIXME: Needs doc   */ -void EVENT_USB_Device_Reset(void) { print("[R]"); } +void EVENT_USB_Device_Reset(void) { +    print("[R]"); +    usb_device_state_set_reset(); +}  /** \brief Event USB Device Connect   * @@ -421,6 +426,8 @@ void EVENT_USB_Device_Reset(void) { print("[R]"); }   */  void EVENT_USB_Device_Suspend() {      print("[S]"); +    usb_device_state_set_suspend(USB_Device_ConfigurationNumber != 0, USB_Device_ConfigurationNumber); +  #ifdef SLEEP_LED_ENABLE      sleep_led_enable();  #endif @@ -436,6 +443,8 @@ void EVENT_USB_Device_WakeUp() {      suspend_wakeup_init();  #endif +    usb_device_state_set_resume(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber); +  #ifdef SLEEP_LED_ENABLE      sleep_led_disable();      // NOTE: converters may not accept this @@ -528,6 +537,8 @@ void EVENT_USB_Device_ConfigurationChanged(void) {      /* Setup digitizer endpoint */      ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1);  #endif + +    usb_device_state_set_configuration(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber);  }  /* FIXME: Expose this table in the docs somehow @@ -760,29 +771,35 @@ static void send_mouse(report_mouse_t *report) {  #endif  } -/** \brief Send Extra - * - * FIXME: Needs doc - */ -#ifdef EXTRAKEY_ENABLE -static void send_extra(uint8_t report_id, uint16_t data) { +#if defined(EXTRAKEY_ENABLE) || defined(PROGRAMMABLE_BUTTON_ENABLE) +static void send_report(void *report, size_t size) {      uint8_t timeout = 255;      if (USB_DeviceState != DEVICE_STATE_Configured) return; -    static report_extra_t r; -    r = (report_extra_t){.report_id = report_id, .usage = data};      Endpoint_SelectEndpoint(SHARED_IN_EPNUM);      /* Check if write ready for a polling interval around 10ms */      while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);      if (!Endpoint_IsReadWriteAllowed()) return; -    Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); +    Endpoint_Write_Stream_LE(report, size, NULL);      Endpoint_ClearIN();  }  #endif +/** \brief Send Extra + * + * FIXME: Needs doc + */ +#ifdef EXTRAKEY_ENABLE +static void send_extra(uint8_t report_id, uint16_t data) { +    static report_extra_t r; +    r = (report_extra_t){.report_id = report_id, .usage = data}; +    send_report(&r, sizeof(r)); +} +#endif +  /** \brief Send System   *   * FIXME: Needs doc @@ -822,6 +839,14 @@ static void send_consumer(uint16_t data) {  #endif  } +static void send_programmable_button(uint32_t data) { +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    static report_programmable_button_t r; +    r = (report_programmable_button_t){.report_id = REPORT_ID_PROGRAMMABLE_BUTTON, .usage = data}; +    send_report(&r, sizeof(r)); +#endif +} +  /*******************************************************************************   * sendchar   ******************************************************************************/ @@ -1044,10 +1069,10 @@ void protocol_setup(void) {  #endif      setup_mcu(); -    keyboard_setup(); +    usb_device_state_init();  } -void protocol_init(void) { +void protocol_pre_init(void) {      setup_usb();      sei(); @@ -1069,21 +1094,11 @@ void protocol_init(void) {  #else      USB_USBTask();  #endif -    /* init modules */ -    keyboard_init(); -    host_set_driver(&lufa_driver); -#ifdef SLEEP_LED_ENABLE -    sleep_led_init(); -#endif - -#ifdef VIRTSER_ENABLE -    virtser_init(); -#endif - -    print("Keyboard start.\n");  } -void protocol_task(void) { +void protocol_post_init(void) { host_set_driver(&lufa_driver); } + +void protocol_pre_task(void) {  #if !defined(NO_USB_STARTUP_CHECK)      if (USB_DeviceState == DEVICE_STATE_Suspended) {          print("[s]"); @@ -1107,9 +1122,9 @@ void protocol_task(void) {          suspend_wakeup_init();      }  #endif +} -    keyboard_task(); - +void protocol_post_task(void) {  #ifdef MIDI_ENABLE      MIDI_Device_USBTask(&USB_MIDI_Interface);  #endif diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h index 348a84c031..6a5205609e 100644 --- a/tmk_core/protocol/lufa/lufa.h +++ b/tmk_core/protocol/lufa/lufa.h @@ -56,14 +56,3 @@ extern host_driver_t lufa_driver;  #ifdef __cplusplus  }  #endif - -#ifdef API_ENABLE -#    include "api.h" -#endif - -#ifdef API_SYSEX_ENABLE -#    include "api_sysex.h" -// Allocate space for encoding overhead. -// The header and terminator are not stored to save a few bytes of precious ram -#    define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0)) -#endif diff --git a/tmk_core/protocol/lufa/outputselect.c b/tmk_core/protocol/lufa/outputselect.c deleted file mode 100644 index f758c65280..0000000000 --- a/tmk_core/protocol/lufa/outputselect.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2017 Priyadi Iman Nurcahyo -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 "outputselect.h" - -#if defined(PROTOCOL_LUFA) -#    include "lufa.h" -#endif - -#ifdef MODULE_ADAFRUIT_BLE -#    include "adafruit_ble.h" -#endif - -uint8_t desired_output = OUTPUT_DEFAULT; - -/** \brief Set Output - * - * FIXME: Needs doc - */ -void set_output(uint8_t output) { -    set_output_user(output); -    desired_output = output; -} - -/** \brief Set Output User - * - * FIXME: Needs doc - */ -__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 - * - * FIXME: Needs doc - */ -uint8_t auto_detect_output(void) { -    if (is_usb_configured()) { -        return OUTPUT_USB; -    } - -#ifdef MODULE_ADAFRUIT_BLE -    if (adafruit_ble_is_connected()) { -        return OUTPUT_BLUETOOTH; -    } -#endif - -#ifdef BLUETOOTH_ENABLE -    return OUTPUT_BLUETOOTH;  // should check if BT is connected here -#endif - -    return OUTPUT_NONE; -} - -/** \brief Where To Send - * - * FIXME: Needs doc - */ -uint8_t where_to_send(void) { -    if (desired_output == OUTPUT_AUTO) { -        return auto_detect_output(); -    } -    return desired_output; -} diff --git a/tmk_core/protocol/lufa/outputselect.h b/tmk_core/protocol/lufa/outputselect.h deleted file mode 100644 index c4548e1122..0000000000 --- a/tmk_core/protocol/lufa/outputselect.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2017 Priyadi Iman Nurcahyo -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> - -enum outputs { -    OUTPUT_AUTO, - -    OUTPUT_NONE, -    OUTPUT_USB, -    OUTPUT_BLUETOOTH -}; - -#ifndef OUTPUT_DEFAULT -#    define OUTPUT_DEFAULT OUTPUT_AUTO -#endif - -void    set_output(uint8_t output); -void    set_output_user(uint8_t output); -uint8_t auto_detect_output(void); -uint8_t where_to_send(void); diff --git a/tmk_core/protocol/lufa/ringbuffer.hpp b/tmk_core/protocol/lufa/ringbuffer.hpp deleted file mode 100644 index 70a3c4881d..0000000000 --- a/tmk_core/protocol/lufa/ringbuffer.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -// A simple ringbuffer holding Size elements of type T -template <typename T, uint8_t Size> -class RingBuffer { - protected: -  T buf_[Size]; -  uint8_t head_{0}, tail_{0}; - public: -  inline uint8_t nextPosition(uint8_t position) { -    return (position + 1) % Size; -  } - -  inline uint8_t prevPosition(uint8_t position) { -    if (position == 0) { -      return Size - 1; -    } -    return position - 1; -  } - -  inline bool enqueue(const T &item) { -    static_assert(Size > 1, "RingBuffer size must be > 1"); -    uint8_t next = nextPosition(head_); -    if (next == tail_) { -      // Full -      return false; -    } - -    buf_[head_] = item; -    head_ = next; -    return true; -  } - -  inline bool get(T &dest, bool commit = true) { -    auto tail = tail_; -    if (tail == head_) { -      // No more data -      return false; -    } - -    dest = buf_[tail]; -    tail = nextPosition(tail); - -    if (commit) { -      tail_ = tail; -    } -    return true; -  } - -  inline bool empty() const { return head_ == tail_; } - -  inline uint8_t size() const { -    int diff = head_ - tail_; -    if (diff >= 0) { -      return diff; -    } -    return Size + diff; -  } - -  inline T& front() { -    return buf_[tail_]; -  } - -  inline bool peek(T &item) { -    return get(item, false); -  } -}; diff --git a/tmk_core/protocol/m0110.c b/tmk_core/protocol/m0110.c deleted file mode 100644 index 64f2fa50ab..0000000000 --- a/tmk_core/protocol/m0110.c +++ /dev/null @@ -1,583 +0,0 @@ -/* -Copyright 2011,2012 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ -/* M0110A Support was contributed by skagon@github */ - -#include <stdbool.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "m0110.h" -#include "debug.h" - -static inline uint8_t  raw2scan(uint8_t raw); -static inline uint8_t  inquiry(void); -static inline uint8_t  instant(void); -static inline void     clock_lo(void); -static inline void     clock_hi(void); -static inline bool     clock_in(void); -static inline void     data_lo(void); -static inline void     data_hi(void); -static inline bool     data_in(void); -static inline uint16_t wait_clock_lo(uint16_t us); -static inline uint16_t wait_clock_hi(uint16_t us); -static inline uint16_t wait_data_lo(uint16_t us); -static inline uint16_t wait_data_hi(uint16_t us); -static inline void     idle(void); -static inline void     request(void); - -#define WAIT_US(stat, us, err)  \ -    do {                        \ -        if (!wait_##stat(us)) { \ -            m0110_error = err;  \ -            goto ERROR;         \ -        }                       \ -    } while (0) - -#define WAIT_MS(stat, ms, err)       \ -    do {                             \ -        uint16_t _ms = ms;           \ -        while (_ms) {                \ -            if (wait_##stat(1000)) { \ -                break;               \ -            }                        \ -            _ms--;                   \ -        }                            \ -        if (_ms == 0) {              \ -            m0110_error = err;       \ -            goto ERROR;              \ -        }                            \ -    } while (0) - -#define KEY(raw) ((raw)&0x7f) -#define IS_BREAK(raw) (((raw)&0x80) == 0x80) - -uint8_t m0110_error = 0; - -void m0110_init(void) { -    idle(); -    _delay_ms(1000); - -    /* Not needed to initialize in fact. -        uint8_t data; -        m0110_send(M0110_MODEL); -        data = m0110_recv(); -        print("m0110_init model: "); print_hex8(data); print("\n"); - -        m0110_send(M0110_TEST); -        data = m0110_recv(); -        print("m0110_init test: "); print_hex8(data); print("\n"); -    */ -} - -uint8_t m0110_send(uint8_t data) { -    m0110_error = 0; - -    request(); -    WAIT_MS(clock_lo, 250, 1);  // keyboard may block long time -    for (uint8_t bit = 0x80; bit; bit >>= 1) { -        WAIT_US(clock_lo, 250, 3); -        if (data & bit) { -            data_hi(); -        } else { -            data_lo(); -        } -        WAIT_US(clock_hi, 200, 4); -    } -    _delay_us(100);  // hold last bit for 80us -    idle(); -    return 1; -ERROR: -    print("m0110_send err: "); -    print_hex8(m0110_error); -    print("\n"); -    _delay_ms(500); -    idle(); -    return 0; -} - -uint8_t m0110_recv(void) { -    uint8_t data = 0; -    m0110_error  = 0; - -    WAIT_MS(clock_lo, 250, 1);  // keyboard may block long time -    for (uint8_t i = 0; i < 8; i++) { -        data <<= 1; -        WAIT_US(clock_lo, 200, 2); -        WAIT_US(clock_hi, 200, 3); -        if (data_in()) { -            data |= 1; -        } -    } -    idle(); -    return data; -ERROR: -    print("m0110_recv err: "); -    print_hex8(m0110_error); -    print("\n"); -    _delay_ms(500); -    idle(); -    return 0xFF; -} - -/* -Handling for exceptional case of key combinations for M0110A - -Shift and Calc/Arrow key could be operated simultaneously: - -    Case Shift   Arrow   Events          Interpret -    ------------------------------------------------------------------- -    1    Down    Down    71, 79, DD      Calc(d)*a *b -    2    Down    Up      71, 79, UU      Arrow&Calc(u)*a -    3    Up      Down    F1, 79, DD      Shift(u) *c -    4    Up      Up      F1, 79, UU      Shift(u) and Arrow&Calc(u)*a - -    Case Shift   Calc    Events          Interpret -    ------------------------------------------------------------------- -    5(1) Down    Down    71, 71, 79, DD  Shift(d) and Cacl(d) -    6(2) Down    Up      F1, 71, 79, UU  Shift(u) and Arrow&Calc(u)*a -    7(1) Up      Down    F1, 71, 79, DD  Shift(u) and Calc(d) -    8(4) Up      Up      F1, F1, 79, UU  Shift(ux2) and Arrow&Calc(u)*a - -During Calc key is hold: -    Case Shift   Arrow   Events          Interpret -    ------------------------------------------------------------------- -    A(3) ----    Down    F1, 79, DD      Shift(u) *c -    B    ----    Up      79, UU          Arrow&Calc(u)*a -    C    Down    ----    F1, 71          Shift(u) and Shift(d) -    D    Up      ----    F1              Shift(u) -    E    Hold    Down    79, DD          Normal -    F    Hold    Up      79, UU          Arrow&Calc(u)*a -    G(1) Down    Down    F1, 71, 79, DD  Shift(u)*b and Calc(d)*a -    H(2) Down    Up      F1, 71, 79, UU  Shift(u) and Arrow&Calc(u)*a -    I(3) Up      Down    F1, F1, 79, DD  Shift(ux2) *c -    J(4) Up      Up      F1, 79, UU      Shift(u) and Arrow&Calc(u)*a - -    Case Shift   Calc    Events          Interpret -    ------------------------------------------------------------------- -    K(1) ----    Down    71, 79, DD      Calc(d)*a -    L(4) ----    Up      F1, 79, UU      Shift(u) and Arrow&Calc(u)*a -    M(1) Hold    Down    71, 79, DD      Calc(d)*a -    N    Hold    Up      79, UU          Arrow&Calc(u)*a - -    Where DD/UU indicates part of Keypad Down/Up event. -    *a: Impossible to distinguish btween Arrow and Calc event. -    *b: Shift(d) event is ignored. -    *c: Arrow/Calc(d) event is ignored. -*/ -uint8_t m0110_recv_key(void) { -    static uint8_t keybuf  = 0x00; -    static uint8_t keybuf2 = 0x00; -    static uint8_t rawbuf  = 0x00; -    uint8_t        raw, raw2, raw3; - -    if (keybuf) { -        raw    = keybuf; -        keybuf = 0x00; -        return raw; -    } -    if (keybuf2) { -        raw     = keybuf2; -        keybuf2 = 0x00; -        return raw; -    } - -    if (rawbuf) { -        raw    = rawbuf; -        rawbuf = 0x00; -    } else { -        raw = instant();  // Use INSTANT for better response. Should be INQUIRY ? -    } -    switch (KEY(raw)) { -        case M0110_KEYPAD: -            raw2 = instant(); -            switch (KEY(raw2)) { -                case M0110_ARROW_UP: -                case M0110_ARROW_DOWN: -                case M0110_ARROW_LEFT: -                case M0110_ARROW_RIGHT: -                    if (IS_BREAK(raw2)) { -                        // Case B,F,N: -                        keybuf = (raw2scan(raw2) | M0110_CALC_OFFSET);  // Calc(u) -                        return (raw2scan(raw2) | M0110_KEYPAD_OFFSET);  // Arrow(u) -                    } -                    break; -            } -            // Keypad or Arrow -            return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); -            break; -        case M0110_SHIFT: -            raw2 = instant(); -            switch (KEY(raw2)) { -                case M0110_SHIFT: -                    // Case: 5-8,C,G,H -                    rawbuf = raw2; -                    return raw2scan(raw);  // Shift(d/u) -                    break; -                case M0110_KEYPAD: -                    // Shift + Arrow, Calc, or etc. -                    raw3 = instant(); -                    switch (KEY(raw3)) { -                        case M0110_ARROW_UP: -                        case M0110_ARROW_DOWN: -                        case M0110_ARROW_LEFT: -                        case M0110_ARROW_RIGHT: -                            if (IS_BREAK(raw)) { -                                if (IS_BREAK(raw3)) { -                                    // Case 4: -                                    print("(4)\n"); -                                    keybuf2 = raw2scan(raw);                         // Shift(u) -                                    keybuf  = (raw2scan(raw3) | M0110_CALC_OFFSET);  // Calc(u) -                                    return (raw2scan(raw3) | M0110_KEYPAD_OFFSET);   // Arrow(u) -                                } else { -                                    // Case 3: -                                    print("(3)\n"); -                                    return (raw2scan(raw));  // Shift(u) -                                } -                            } else { -                                if (IS_BREAK(raw3)) { -                                    // Case 2: -                                    print("(2)\n"); -                                    keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET);  // Calc(u) -                                    return (raw2scan(raw3) | M0110_KEYPAD_OFFSET);  // Arrow(u) -                                } else { -                                    // Case 1: -                                    print("(1)\n"); -                                    return (raw2scan(raw3) | M0110_CALC_OFFSET);  // Calc(d) -                                } -                            } -                            break; -                        default: -                            // Shift + Keypad -                            keybuf = (raw2scan(raw3) | M0110_KEYPAD_OFFSET); -                            return raw2scan(raw);  // Shift(d/u) -                            break; -                    } -                    break; -                default: -                    // Shift + Normal keys -                    keybuf = raw2scan(raw2); -                    return raw2scan(raw);  // Shift(d/u) -                    break; -            } -            break; -        default: -            // Normal keys -            return raw2scan(raw); -            break; -    } -} - -static inline uint8_t raw2scan(uint8_t raw) { return (raw == M0110_NULL) ? M0110_NULL : ((raw == M0110_ERROR) ? M0110_ERROR : (((raw & 0x80) | ((raw & 0x7F) >> 1)))); } - -static inline uint8_t inquiry(void) { -    m0110_send(M0110_INQUIRY); -    return m0110_recv(); -} - -static inline uint8_t instant(void) { -    m0110_send(M0110_INSTANT); -    uint8_t data = m0110_recv(); -    if (data != M0110_NULL) { -        debug_hex(data); -        debug(" "); -    } -    return data; -} - -static inline void clock_lo() { -    M0110_CLOCK_PORT &= ~(1 << M0110_CLOCK_BIT); -    M0110_CLOCK_DDR |= (1 << M0110_CLOCK_BIT); -} -static inline void clock_hi() { -    /* input with pull up */ -    M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT); -    M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT); -} -static inline bool clock_in() { -    M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT); -    M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT); -    _delay_us(1); -    return M0110_CLOCK_PIN & (1 << M0110_CLOCK_BIT); -} -static inline void data_lo() { -    M0110_DATA_PORT &= ~(1 << M0110_DATA_BIT); -    M0110_DATA_DDR |= (1 << M0110_DATA_BIT); -} -static inline void data_hi() { -    /* input with pull up */ -    M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT); -    M0110_DATA_PORT |= (1 << M0110_DATA_BIT); -} -static inline bool data_in() { -    M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT); -    M0110_DATA_PORT |= (1 << M0110_DATA_BIT); -    _delay_us(1); -    return M0110_DATA_PIN & (1 << M0110_DATA_BIT); -} - -static inline uint16_t wait_clock_lo(uint16_t us) { -    while (clock_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_clock_hi(uint16_t us) { -    while (!clock_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_lo(uint16_t us) { -    while (data_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_hi(uint16_t us) { -    while (!data_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} - -static inline void idle(void) { -    clock_hi(); -    data_hi(); -} - -static inline void request(void) { -    clock_hi(); -    data_lo(); -} - -/* -Primitive M0110 Library for AVR -============================== - - -Signaling ---------- -CLOCK is always from KEYBOARD. DATA are sent with MSB first. - -1) IDLE: both lines are high. -    CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -    DATA  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -2) KEYBOARD->HOST: HOST reads bit on rising edge. -    CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ -    DATA  ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ -                      <--> 160us(clock low) -                         <---> 180us(clock high) - -3) HOST->KEYBOARD: HOST asserts bit on falling edge. -    CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ -    DATA  ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ -                <----> 840us(request to send by host)                     <---> 80us(hold DATA) -                      <--> 180us(clock low) -                         <---> 220us(clock high) - - -Protocol --------- -COMMAND: -    Inquiry     0x10    get key event with block -    Instant     0x12    get key event -    Model       0x14    get model number(M0110 responds with 0x09) -                        bit 7   1 if another device connected(used when keypad exists?) -                        bit4-6  next device model number -                        bit1-3  keyboard model number -                        bit 0   always 1 -    Test        0x16    test(ACK:0x7D/NAK:0x77) - -KEY EVENT: -    bit 7       key state(0:press 1:release) -    bit 6-1     scan code(see below) -    bit 0       always 1 -    To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1). - -    Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79. -          Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release. - -ARROW KEYS: -    Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of -    Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation, -    it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases. - -    Raw key events: -            press               release -            ----------------    ---------------- -    Left:         0x79, 0x0D          0x79, 0x8D -    Right:        0x79, 0x05          0x79, 0x85 -    Up:           0x79, 0x1B          0x79, 0x9B -    Down:         0x79, 0x11          0x79, 0x91 -    Pad+:   0x71, 0x79, 0x0D    0xF1, 0x79, 0x8D -    Pad*:   0x71, 0x79, 0x05    0xF1, 0x79, 0x85 -    Pad/:   0x71, 0x79, 0x1B    0xF1, 0x79, 0x9B -    Pad=:   0x71, 0x79, 0x11    0xF1, 0x79, 0x91 - - -RAW CODE: -    M0110A -    ,---------------------------------------------------------. ,---------------. -    |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bcksp| |Clr|  =|  /|  *| -    |---------------------------------------------------------| |---------------| -    |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   | |  7|  8|  9|  -| -    |-----------------------------------------------------'   | |---------------| -    |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| |  4|  5|  6|  +| -    |---------------------------------------------------------| |---------------| -    |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shft|Up | |  1|  2|  3|   | -    |---------------------------------------------------------' |-----------|Ent| -    |Optio|Mac    |           Space           |  \|Lft|Rgt|Dn | |      0|  .|   | -    `---------------------------------------------------------' `---------------' -    ,---------------------------------------------------------. ,---------------. -    | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31|   67| |+0F|*11|*1B|*05| -    |---------------------------------------------------------| |---------------| -    |   61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D|   | |+33|+37|+39|+1D| -    |-----------------------------------------------------'   | |---------------| -    |    73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F|    49| |+2D|+2F|+31|*0D| -    |---------------------------------------------------------| |---------------| -    |      71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59|  71|+1B| |+27|+29|+2B|   | -    |---------------------------------------------------------' |-----------|+19| -    |   75|     6F|            63             | 55|+0D|+05|+11| |    +25|+03|   | -    `---------------------------------------------------------' `---------------' -    + 0x79, 0xDD / 0xF1, 0xUU -    * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU - - -MODEL NUMBER: -    M0110:           0x09  00001001 : model number 4 (100) -    M0110A:          0x0B  00001011 : model number 5 (101) -    M0110 & M0120:   ??? - - -Scan Code ---------- -    m0110_recv_key() function returns following scan codes instead of M0110 raw codes. -    Scan codes are 1 byte size and MSB(bit7) is set when key is released. - -        scancode = ((raw&0x80) | ((raw&0x7F)>>1)) - -    M0110                                                          M0120 -    ,---------------------------------------------------------.    ,---------------. -    |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs|    |Clr|  -|Lft|Rgt| -    |---------------------------------------------------------|    |---------------| -    |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \|    |  7|  8|  9|Up | -    |---------------------------------------------------------|    |---------------| -    |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return|    |  4|  5|  6|Dn | -    |---------------------------------------------------------|    |---------------| -    |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|        |    |  1|  2|  3|   | -    `---------------------------------------------------------'    |-----------|Ent| -         |Opt|Mac |         Space               |Enter|Opt|        |      0|  .|   | -         `------------------------------------------------'        `---------------' -    ,---------------------------------------------------------.    ,---------------. -    | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33|    | 47| 4E| 46| 42| -    |---------------------------------------------------------|    |---------------| -    |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|    | 59| 5B| 5C| 4D| -    |---------------------------------------------------------|    |---------------| -    |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24|    | 56| 57| 58| 48| -    |---------------------------------------------------------|    |---------------| -    |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|      38|    | 53| 54| 55|   | -    `---------------------------------------------------------'    |-----------| 4C| -         | 3A|  37|             31              |   34| 3A|        |     52| 41|   | -         `------------------------------------------------'        `---------------' - -    International keyboard(See page 22 of "Technical Info for 128K/512K") -    ,---------------------------------------------------------. -    | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| -    |---------------------------------------------------------| -    |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| -    |------------------------------------------------------   | -    |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24|  | -    |---------------------------------------------------------| -    |  38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A|      38| -    `---------------------------------------------------------' -         | 3A|  37|             34              |   31| 3A| -         `------------------------------------------------' - -    M0110A -    ,---------------------------------------------------------. ,---------------. -    |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bcksp| |Clr|  =|  /|  *| -    |---------------------------------------------------------| |---------------| -    |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   | |  7|  8|  9|  -| -    |-----------------------------------------------------'   | |---------------| -    |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| |  4|  5|  6|  +| -    |---------------------------------------------------------| |---------------| -    |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shft|Up | |  1|  2|  3|   | -    |---------------------------------------------------------' |-----------|Ent| -    |Optio|Mac    |           Space           |  \|Lft|Rgt|Dn | |      0|  .|   | -    `---------------------------------------------------------' `---------------' -    ,---------------------------------------------------------. ,---------------. -    | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| | 47| 68| 6D| 62| -    |---------------------------------------------------------| |---------------| -    |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E|   | | 59| 5B| 5C| 4E| -    |-----------------------------------------------------'   | |---------------| -    |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24| | 56| 57| 58| 66| -    |---------------------------------------------------------| |---------------| -    |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|  38| 4D| | 53| 54| 55|   | -    |---------------------------------------------------------' |-----------| 4C| -    |   3A|     37|            31             | 2A| 46| 42| 48| |     52| 41|   | -    `---------------------------------------------------------' `---------------' - - -References ----------- -Technical Info for 128K/512K and Plus -    ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf -    ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf -Protocol: -    Page 20 of Tech Info for 128K/512K -    http://www.mac.linux-m68k.org/devel/plushw.php -Connector: -    Page 20 of Tech Info for 128K/512K -    http://www.kbdbabel.org/conn/kbd_connector_macplus.png -Signaling: -    http://www.kbdbabel.org/signaling/kbd_signaling_mac.png -    http://typematic.blog.shinobi.jp/Entry/14/ -M0110 raw scan codes: -    Page 22 of Tech Info for 128K/512K -    Page 07 of Tech Info for Plus -    http://m0115.web.fc2.com/m0110.jpg -    http://m0115.web.fc2.com/m0110a.jpg -*/ diff --git a/tmk_core/protocol/m0110.h b/tmk_core/protocol/m0110.h deleted file mode 100644 index 63ff3e90ec..0000000000 --- a/tmk_core/protocol/m0110.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2011,2012 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -/* port settings for clock and data line */ -#if !(defined(M0110_CLOCK_PORT) && defined(M0110_CLOCK_PIN) && defined(M0110_CLOCK_DDR) && defined(M0110_CLOCK_BIT)) -#    error "M0110 clock port setting is required in config.h" -#endif - -#if !(defined(M0110_DATA_PORT) && defined(M0110_DATA_PIN) && defined(M0110_DATA_DDR) && defined(M0110_DATA_BIT)) -#    error "M0110 data port setting is required in config.h" -#endif - -/* Commands */ -#define M0110_INQUIRY 0x10 -#define M0110_INSTANT 0x14 -#define M0110_MODEL 0x16 -#define M0110_TEST 0x36 - -/* Response(raw byte from M0110) */ -#define M0110_NULL 0x7B -#define M0110_KEYPAD 0x79 -#define M0110_TEST_ACK 0x7D -#define M0110_TEST_NAK 0x77 -#define M0110_SHIFT 0x71 -#define M0110_ARROW_UP 0x1B -#define M0110_ARROW_DOWN 0x11 -#define M0110_ARROW_LEFT 0x0D -#define M0110_ARROW_RIGHT 0x05 - -/* This inidcates no response. */ -#define M0110_ERROR 0xFF - -/* scan code offset for keypad and arrow keys */ -#define M0110_KEYPAD_OFFSET 0x40 -#define M0110_CALC_OFFSET 0x60 - -extern uint8_t m0110_error; - -/* host role */ -void    m0110_init(void); -uint8_t m0110_send(uint8_t data); -uint8_t m0110_recv(void); -uint8_t m0110_recv_key(void); -uint8_t m0110_inquiry(void); -uint8_t m0110_instant(void); diff --git a/tmk_core/protocol/midi/qmk_midi.c b/tmk_core/protocol/midi/qmk_midi.c index c18dbf9930..3a454d61ae 100644 --- a/tmk_core/protocol/midi/qmk_midi.c +++ b/tmk_core/protocol/midi/qmk_midi.c @@ -4,9 +4,6 @@  #include "midi.h"  #include "usb_descriptor.h"  #include "process_midi.h" -#if API_SYSEX_ENABLE -#    include "api_sysex.h" -#endif  /*******************************************************************************   * MIDI @@ -124,41 +121,6 @@ static void cc_callback(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t v      // midi_send_cc(device, (chan + 1) % 16, num, val);  } -#ifdef API_SYSEX_ENABLE -uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0}; - -static void sysex_callback(MidiDevice* device, uint16_t start, uint8_t length, uint8_t* data) { -    // SEND_STRING("\n"); -    // send_word(start); -    // SEND_STRING(": "); -    // Don't store the header -    int16_t pos = start - 4; -    for (uint8_t place = 0; place < length; place++) { -        // send_byte(*data); -        if (pos >= 0) { -            if (*data == 0xF7) { -                // SEND_STRING("\nRD: "); -                // for (uint8_t i = 0; i < start + place + 1; i++){ -                //     send_byte(midi_buffer[i]); -                // SEND_STRING(" "); -                // } -                const unsigned decoded_length = sysex_decoded_length(pos); -                uint8_t        decoded[API_SYSEX_MAX_SIZE]; -                sysex_decode(decoded, midi_buffer, pos); -                process_api(decoded_length, decoded); -                return; -            } else if (pos >= MIDI_SYSEX_BUFFER) { -                return; -            } -            midi_buffer[pos] = *data; -        } -        // SEND_STRING(" "); -        data++; -        pos++; -    } -} -#endif -  void midi_init(void);  void setup_midi(void) { @@ -170,7 +132,4 @@ void setup_midi(void) {      midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);      midi_register_fallthrough_callback(&midi_device, fallthrough_callback);      midi_register_cc_callback(&midi_device, cc_callback); -#ifdef API_SYSEX_ENABLE -    midi_register_sysex_callback(&midi_device, sysex_callback); -#endif  } diff --git a/tmk_core/protocol/news.c b/tmk_core/protocol/news.c deleted file mode 100644 index 4463e8dd42..0000000000 --- a/tmk_core/protocol/news.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2012 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <stdbool.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include "news.h" - -void news_init(void) { NEWS_KBD_RX_INIT(); } - -// RX ring buffer -#define RBUF_SIZE 8 -static uint8_t rbuf[RBUF_SIZE]; -static uint8_t rbuf_head = 0; -static uint8_t rbuf_tail = 0; - -uint8_t news_recv(void) { -    uint8_t data = 0; -    if (rbuf_head == rbuf_tail) { -        return 0; -    } - -    data      = rbuf[rbuf_tail]; -    rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE; -    return data; -} - -// USART RX complete interrupt -ISR(NEWS_KBD_RX_VECT) { -    uint8_t next = (rbuf_head + 1) % RBUF_SIZE; -    if (next != rbuf_tail) { -        rbuf[rbuf_head] = NEWS_KBD_RX_DATA; -        rbuf_head       = next; -    } -} - -/* -SONY NEWS Keyboard Protocol -=========================== - -Resources ---------- -    Mouse protocol of NWA-5461(Japanese) -    http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d - -    SONY NEWS Info(Japanese) -    http://katsu.watanabe.name/doc/sonynews/ - - -Pinouts -------- -    EIA 232 male connector from NWP-5461 -    ------------- -    \ 1 2 3 4 5 / -     \ 6 7 8 9 / -      --------- -    1 VCC -    2 BZ(Speaker) -    3 Keyboard Data(from keyboard MCU TxD) -    4 NC -    5 GND -    6 Unknown Input(to keyboard MCU RxD via schmitt trigger) -    7 Mouse Data(from Mouse Ext connector) -    8 Unknown Input(to Keyboard MCU Input via diode and buffer) -    9 FG -    NOTE: Two LED on keyboard are controlled by pin 6,8? - -    EIA 232 male connector from NWP-411A -    ------------- -    \ 1 2 3 4 5 / -     \ 6 7 8 9 / -      --------- -    1 VCC -    2 BZ(Speaker) -    3 Keyboard Data(from keyboard MCU TxD) -    4 NC -    5 GND -    6 NC -    7 Mouse Data(from Mouse Ext connector) -    8 NC -    9 FG -    NOTE: These are just from my guess and not confirmed. - - -Signaling ---------- -    ~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~ -    Idle    Start  LSB                         MSB Stop Idle - -    Idle:       High -    Start bit:  Low -    Stop bit:   High -    Bit order:  LSB first - -    Baud rate:  9600 -    Interface:  TTL level(5V) UART - -    NOTE: This is observed on NWP-5461 with its DIP switch all OFF. - - -Format ------- -    MSB         LSB -    7 6 5 4 3 2 1 0   bit -    | | | | | | | | -    | +-+-+-+-+-+-+-- scan code(00-7F) -    +---------------- break flag: sets when released - - -Scan Codes ----------- -    SONY NEWS NWP-5461 -    ,---.   ,------------------------, ,------------------------. ,---------. -    | 7A|   | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------. -    `---'   `------------------------' `------------------------' `---------' | 64| 65| 52| -    ,-------------------------------------------------------------. ,---. ,---------------| -    | 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18|  19 | | 6A| | 4B| 4C| 4D| 4E| -    |-------------------------------------------------------------| |---| |---------------| -    |  1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27|   | | 6B| | 4F| 50| 51| 56| -    |---------------------------------------------------------'   | |---| |---------------| -    |  28  | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34|  35  | | 6C| | 53| 54| 55|   | -    |-------------------------------------------------------------| |---| |-----------| 5A| -    |  36    | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41|   42   | | 6D| | 57| 59| 58|   | -    |-------------------------------------------------------------| |---| |---------------| -    | 43  | 44 | 45 |       46          |    47    | 48| 49|  4A  | | 6E| | 66| 5B| 5C| 5D| -    `-------------------------------------------------------------' `---' `---------------' -*/ diff --git a/tmk_core/protocol/news.h b/tmk_core/protocol/news.h deleted file mode 100644 index 327a13856d..0000000000 --- a/tmk_core/protocol/news.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2012 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -/* - * Primitive PS/2 Library for AVR - */ - -/* host role */ -void    news_init(void); -uint8_t news_recv(void); - -/* device role */ diff --git a/tmk_core/protocol/next_kbd.c b/tmk_core/protocol/next_kbd.c deleted file mode 100644 index 6f118e6172..0000000000 --- a/tmk_core/protocol/next_kbd.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - -NeXT non-ADB Keyboard Protocol - -Copyright 2013, Benjamin Gould ([email protected]) - -Based on: -TMK firmware code Copyright 2011,2012 Jun WAKO <[email protected]> -Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license - -Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB -Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html -Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/ - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include <stdint.h> -#include <stdbool.h> -#include <util/atomic.h> -#include <util/delay.h> -#include "next_kbd.h" -#include "debug.h" - -static inline void     out_lo(void); -static inline void     out_hi(void); -static inline void     query(void); -static inline void     reset(void); -static inline uint32_t response(void); - -/* The keyboard sends signal with 50us pulse width on OUT line - * while it seems to miss the 50us pulse on In line. - * next_kbd_set_leds() often fails to sync LED status with 50us - * but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least. - * TODO: test on Teensy and Pro Micro configuration - */ -#define out_hi_delay(intervals)                       \ -    do {                                              \ -        out_hi();                                     \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); -#define out_lo_delay(intervals)                       \ -    do {                                              \ -        out_lo();                                     \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); -#define query_delay(intervals)                        \ -    do {                                              \ -        query();                                      \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); -#define reset_delay(intervals)                        \ -    do {                                              \ -        reset();                                      \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); - -void next_kbd_init(void) { -    out_hi(); -    NEXT_KBD_IN_DDR &= ~(1 << NEXT_KBD_IN_BIT);  // KBD_IN  to input -    NEXT_KBD_IN_PORT |= (1 << NEXT_KBD_IN_BIT);  // KBD_IN  pull up - -    query_delay(5); -    reset_delay(8); - -    query_delay(5); -    reset_delay(8); -} - -void next_kbd_set_leds(bool left, bool right) { -    cli(); -    out_lo_delay(9); - -    out_hi_delay(3); -    out_lo_delay(1); - -    if (left) { -        out_hi_delay(1); -    } else { -        out_lo_delay(1); -    } - -    if (right) { -        out_hi_delay(1); -    } else { -        out_lo_delay(1); -    } - -    out_lo_delay(7); -    out_hi(); -    sei(); -} - -#define NEXT_KBD_READ (NEXT_KBD_IN_PIN & (1 << NEXT_KBD_IN_BIT)) -uint32_t next_kbd_recv(void) { -    // First check to make sure that the keyboard is actually connected; -    // if not, just return -    // TODO: reflect the status of the keyboard in a return code -    if (!NEXT_KBD_READ) { -        sei(); -        return 0; -    } - -    query(); -    uint32_t resp = response(); - -    return resp; -} - -static inline uint32_t response(void) { -    cli(); - -    // try a 5ms read; this should be called after the query method has -    // been run so if a key is pressed we should get a response within -    // 5ms; if not then send a reset and exit -    uint8_t  i             = 0; -    uint32_t data          = 0; -    uint16_t reset_timeout = 50000; -    while (NEXT_KBD_READ && reset_timeout) { -        asm(""); -        _delay_us(1); -        reset_timeout--; -    } -    if (!reset_timeout) { -        reset(); -        sei(); -        return 0; -    } -    _delay_us(NEXT_KBD_TIMING / 2); -    for (; i < 22; i++) { -        if (NEXT_KBD_READ) { -            data |= ((uint32_t)1 << i); -            /* Note: -             * My testing with the ATmega32u4 showed that there might -             * something wrong with the timing here; by the end of the -             * second data byte some of the modifiers can get bumped out -             * to the next bit over if we just cycle through the data -             * based on the expected interval.  There is a bit (i = 10) -             * in the middle of the data that is always on followed by -             * one that is always off - so we'll use that to reset our -             * timing in case we've gotten ahead of the keyboard; -             */ -            if (i == 10) { -                i++; -                while (NEXT_KBD_READ) -                    ; -                _delay_us(NEXT_KBD_TIMING / 2); -            } -        } else { -            /* redundant - but I don't want to remove if it might screw -             * up the timing -             */ -            data |= ((uint32_t)0 << i); -        } -        _delay_us(NEXT_KBD_TIMING); -    } - -    sei(); - -    return data; -} - -static inline void out_lo(void) { -    NEXT_KBD_OUT_PORT &= ~(1 << NEXT_KBD_OUT_BIT); -    NEXT_KBD_OUT_DDR |= (1 << NEXT_KBD_OUT_BIT); -} - -static inline void out_hi(void) { -    /* input with pull up */ -    NEXT_KBD_OUT_DDR &= ~(1 << NEXT_KBD_OUT_BIT); -    NEXT_KBD_OUT_PORT |= (1 << NEXT_KBD_OUT_BIT); -} - -static inline void query(void) { -    out_lo_delay(5); -    out_hi_delay(1); -    out_lo_delay(3); -    out_hi(); -} - -static inline void reset(void) { -    out_lo_delay(1); -    out_hi_delay(4); -    out_lo_delay(1); -    out_hi_delay(6); -    out_lo_delay(10); -    out_hi(); -} diff --git a/tmk_core/protocol/next_kbd.h b/tmk_core/protocol/next_kbd.h deleted file mode 100644 index 1249ebf392..0000000000 --- a/tmk_core/protocol/next_kbd.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -NeXT non-ADB Keyboard Protocol - -Copyright 2013, Benjamin Gould ([email protected]) - -Based on: -TMK firmware code Copyright 2011,2012 Jun WAKO <[email protected]> -Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license - -Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB -Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html -Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/ - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#pragma once - -#include <stdbool.h> - -#define NEXT_KBD_KMBUS_IDLE 0x300600 -#define NEXT_KBD_TIMING 50 - -extern uint8_t next_kbd_error; - -/* host role */ -void     next_kbd_init(void); -void     next_kbd_set_leds(bool left, bool right); -uint32_t next_kbd_recv(void); diff --git a/tmk_core/protocol/ps2.h b/tmk_core/protocol/ps2.h deleted file mode 100644 index f123192852..0000000000 --- a/tmk_core/protocol/ps2.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include <stdbool.h> -#include "wait.h" -#include "ps2_io.h" -#include "print.h" - -/* - * Primitive PS/2 Library for AVR - * - * PS/2 Resources - * -------------- - * [1] The PS/2 Mouse/Keyboard Protocol - * http://www.computer-engineering.org/ps2protocol/ - * Concise and thorough primer of PS/2 protocol. - * - * [2] Keyboard and Auxiliary Device Controller - * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf - * Signal Timing and Format - * - * [3] Keyboards(101- and 102-key) - * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf - * Keyboard Layout, Scan Code Set, POR, and Commands. - * - * [4] PS/2 Reference Manuals - * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf - * Collection of IBM Personal System/2 documents. - * - * [5] TrackPoint Engineering Specifications for version 3E - * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html - */ -#define PS2_ACK 0xFA -#define PS2_RESEND 0xFE -#define PS2_SET_LED 0xED - -// TODO: error numbers -#define PS2_ERR_NONE 0 -#define PS2_ERR_STARTBIT1 1 -#define PS2_ERR_STARTBIT2 2 -#define PS2_ERR_STARTBIT3 3 -#define PS2_ERR_PARITY 0x10 -#define PS2_ERR_NODATA 0x20 - -#define PS2_LED_SCROLL_LOCK 0 -#define PS2_LED_NUM_LOCK 1 -#define PS2_LED_CAPS_LOCK 2 - -extern uint8_t ps2_error; - -void    ps2_host_init(void); -uint8_t ps2_host_send(uint8_t data); -uint8_t ps2_host_recv_response(void); -uint8_t ps2_host_recv(void); -void    ps2_host_set_led(uint8_t usb_led); - -/*-------------------------------------------------------------------- - * static functions - *------------------------------------------------------------------*/ -static inline uint16_t wait_clock_lo(uint16_t us) { -    while (clock_in() && us) { -        asm(""); -        wait_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_clock_hi(uint16_t us) { -    while (!clock_in() && us) { -        asm(""); -        wait_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_lo(uint16_t us) { -    while (data_in() && us) { -        asm(""); -        wait_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_hi(uint16_t us) { -    while (!data_in() && us) { -        asm(""); -        wait_us(1); -        us--; -    } -    return us; -} - -/* idle state that device can send */ -static inline void idle(void) { -    clock_hi(); -    data_hi(); -} - -/* inhibit device to send */ -static inline void inhibit(void) { -    clock_lo(); -    data_hi(); -} diff --git a/tmk_core/protocol/ps2_busywait.c b/tmk_core/protocol/ps2_busywait.c deleted file mode 100644 index 983194eea8..0000000000 --- a/tmk_core/protocol/ps2_busywait.c +++ /dev/null @@ -1,187 +0,0 @@ -/* -Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - * PS/2 protocol busywait version - */ - -#include <stdbool.h> -#include "wait.h" -#include "ps2.h" -#include "ps2_io.h" -#include "debug.h" - -#define WAIT(stat, us, err)     \ -    do {                        \ -        if (!wait_##stat(us)) { \ -            ps2_error = err;    \ -            goto ERROR;         \ -        }                       \ -    } while (0) - -uint8_t ps2_error = PS2_ERR_NONE; - -void ps2_host_init(void) { -    clock_init(); -    data_init(); - -    // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) -    wait_ms(2500); - -    inhibit(); -} - -uint8_t ps2_host_send(uint8_t data) { -    bool parity = true; -    ps2_error   = PS2_ERR_NONE; - -    /* terminate a transmission if we have */ -    inhibit(); -    wait_us(100);  // 100us [4]p.13, [5]p.50 - -    /* 'Request to Send' and Start bit */ -    data_lo(); -    clock_hi(); -    WAIT(clock_lo, 10000, 10);  // 10ms [5]p.50 - -    /* Data bit */ -    for (uint8_t i = 0; i < 8; i++) { -        wait_us(15); -        if (data & (1 << i)) { -            parity = !parity; -            data_hi(); -        } else { -            data_lo(); -        } -        WAIT(clock_hi, 50, 2); -        WAIT(clock_lo, 50, 3); -    } - -    /* Parity bit */ -    wait_us(15); -    if (parity) { -        data_hi(); -    } else { -        data_lo(); -    } -    WAIT(clock_hi, 50, 4); -    WAIT(clock_lo, 50, 5); - -    /* Stop bit */ -    wait_us(15); -    data_hi(); - -    /* Ack */ -    WAIT(data_lo, 50, 6); -    WAIT(clock_lo, 50, 7); - -    /* wait for idle state */ -    WAIT(clock_hi, 50, 8); -    WAIT(data_hi, 50, 9); - -    inhibit(); -    return ps2_host_recv_response(); -ERROR: -    inhibit(); -    return 0; -} - -/* receive data when host want else inhibit communication */ -uint8_t ps2_host_recv_response(void) { -    // Command may take 25ms/20ms at most([5]p.46, [3]p.21) -    // 250 * 100us(wait for start bit in ps2_host_recv) -    uint8_t data = 0; -    uint8_t try -        = 250; -    do { -        data = ps2_host_recv(); -    } while (try --&&ps2_error); -    return data; -} - -/* called after start bit comes */ -uint8_t ps2_host_recv(void) { -    uint8_t data   = 0; -    bool    parity = true; -    ps2_error      = PS2_ERR_NONE; - -    /* release lines(idle state) */ -    idle(); - -    /* start bit [1] */ -    WAIT(clock_lo, 100, 1);  // TODO: this is enough? -    WAIT(data_lo, 1, 2); -    WAIT(clock_hi, 50, 3); - -    /* data [2-9] */ -    for (uint8_t i = 0; i < 8; i++) { -        WAIT(clock_lo, 50, 4); -        if (data_in()) { -            parity = !parity; -            data |= (1 << i); -        } -        WAIT(clock_hi, 50, 5); -    } - -    /* parity [10] */ -    WAIT(clock_lo, 50, 6); -    if (data_in() != parity) { -        ps2_error = PS2_ERR_PARITY; -        goto ERROR; -    } -    WAIT(clock_hi, 50, 7); - -    /* stop bit [11] */ -    WAIT(clock_lo, 50, 8); -    WAIT(data_hi, 1, 9); -    WAIT(clock_hi, 50, 10); - -    inhibit(); -    return data; -ERROR: -    if (ps2_error > PS2_ERR_STARTBIT3) { -        xprintf("x%02X\n", ps2_error); -    } -    inhibit(); -    return 0; -} - -/* send LED state to keyboard */ -void ps2_host_set_led(uint8_t led) { -    ps2_host_send(0xED); -    ps2_host_send(led); -} diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c deleted file mode 100644 index 780040d152..0000000000 --- a/tmk_core/protocol/ps2_interrupt.c +++ /dev/null @@ -1,340 +0,0 @@ -/* -Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - * PS/2 protocol Pin interrupt version - */ - -#include <stdbool.h> - -#if defined(__AVR__) -#    include <avr/interrupt.h> -#elif defined(PROTOCOL_CHIBIOS)  // TODO: or STM32 ? -// chibiOS headers -#    include "ch.h" -#    include "hal.h" -#endif - -#include "ps2.h" -#include "ps2_io.h" -#include "print.h" -#include "wait.h" - -#define WAIT(stat, us, err)     \ -    do {                        \ -        if (!wait_##stat(us)) { \ -            ps2_error = err;    \ -            goto ERROR;         \ -        }                       \ -    } while (0) - -uint8_t ps2_error = PS2_ERR_NONE; - -static inline uint8_t pbuf_dequeue(void); -static inline void    pbuf_enqueue(uint8_t data); -static inline bool    pbuf_has_data(void); -static inline void    pbuf_clear(void); - -#if defined(PROTOCOL_CHIBIOS) -void ps2_interrupt_service_routine(void); -void palCallback(void *arg) { ps2_interrupt_service_routine(); } - -#    define PS2_INT_INIT()                             \ -        { palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); } \ -        while (0) -#    define PS2_INT_ON()                                                \ -        {                                                               \ -            palEnableLineEvent(PS2_CLOCK, PAL_EVENT_MODE_FALLING_EDGE); \ -            palSetLineCallback(PS2_CLOCK, palCallback, NULL);           \ -        }                                                               \ -        while (0) -#    define PS2_INT_OFF()                   \ -        { palDisableLineEvent(PS2_CLOCK); } \ -        while (0) -#endif  // PROTOCOL_CHIBIOS - -void ps2_host_init(void) { -    idle(); -    PS2_INT_INIT(); -    PS2_INT_ON(); -    // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) -    // wait_ms(2500); -} - -uint8_t ps2_host_send(uint8_t data) { -    bool parity = true; -    ps2_error   = PS2_ERR_NONE; - -    PS2_INT_OFF(); - -    /* terminate a transmission if we have */ -    inhibit(); -    wait_us(100);  // 100us [4]p.13, [5]p.50 - -    /* 'Request to Send' and Start bit */ -    data_lo(); -    clock_hi(); -    WAIT(clock_lo, 10000, 10);  // 10ms [5]p.50 - -    /* Data bit[2-9] */ -    for (uint8_t i = 0; i < 8; i++) { -        if (data & (1 << i)) { -            parity = !parity; -            data_hi(); -        } else { -            data_lo(); -        } -        WAIT(clock_hi, 50, 2); -        WAIT(clock_lo, 50, 3); -    } - -    /* Parity bit */ -    wait_us(15); -    if (parity) { -        data_hi(); -    } else { -        data_lo(); -    } -    WAIT(clock_hi, 50, 4); -    WAIT(clock_lo, 50, 5); - -    /* Stop bit */ -    wait_us(15); -    data_hi(); - -    /* Ack */ -    WAIT(data_lo, 50, 6); -    WAIT(clock_lo, 50, 7); - -    /* wait for idle state */ -    WAIT(clock_hi, 50, 8); -    WAIT(data_hi, 50, 9); - -    idle(); -    PS2_INT_ON(); -    return ps2_host_recv_response(); -ERROR: -    idle(); -    PS2_INT_ON(); -    return 0; -} - -uint8_t ps2_host_recv_response(void) { -    // Command may take 25ms/20ms at most([5]p.46, [3]p.21) -    uint8_t retry = 25; -    while (retry-- && !pbuf_has_data()) { -        wait_ms(1); -    } -    return pbuf_dequeue(); -} - -/* get data received by interrupt */ -uint8_t ps2_host_recv(void) { -    if (pbuf_has_data()) { -        ps2_error = PS2_ERR_NONE; -        return pbuf_dequeue(); -    } else { -        ps2_error = PS2_ERR_NODATA; -        return 0; -    } -} - -void ps2_interrupt_service_routine(void) { -    static enum { -        INIT, -        START, -        BIT0, -        BIT1, -        BIT2, -        BIT3, -        BIT4, -        BIT5, -        BIT6, -        BIT7, -        PARITY, -        STOP, -    } state               = INIT; -    static uint8_t data   = 0; -    static uint8_t parity = 1; - -    // TODO: abort if elapse 100us from previous interrupt - -    // return unless falling edge -    if (clock_in()) { -        goto RETURN; -    } - -    state++; -    switch (state) { -        case START: -            if (data_in()) goto ERROR; -            break; -        case BIT0: -        case BIT1: -        case BIT2: -        case BIT3: -        case BIT4: -        case BIT5: -        case BIT6: -        case BIT7: -            data >>= 1; -            if (data_in()) { -                data |= 0x80; -                parity++; -            } -            break; -        case PARITY: -            if (data_in()) { -                if (!(parity & 0x01)) goto ERROR; -            } else { -                if (parity & 0x01) goto ERROR; -            } -            break; -        case STOP: -            if (!data_in()) goto ERROR; -            pbuf_enqueue(data); -            goto DONE; -            break; -        default: -            goto ERROR; -    } -    goto RETURN; -ERROR: -    ps2_error = state; -DONE: -    state  = INIT; -    data   = 0; -    parity = 1; -RETURN: -    return; -} - -#if defined(__AVR__) -ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); } -#endif - -/* send LED state to keyboard */ -void ps2_host_set_led(uint8_t led) { -    ps2_host_send(0xED); -    ps2_host_send(led); -} - -/*-------------------------------------------------------------------- - * Ring buffer to store scan codes from keyboard - *------------------------------------------------------------------*/ -#define PBUF_SIZE 32 -static uint8_t     pbuf[PBUF_SIZE]; -static uint8_t     pbuf_head = 0; -static uint8_t     pbuf_tail = 0; -static inline void pbuf_enqueue(uint8_t data) { -#if defined(__AVR__) -    uint8_t sreg = SREG; -    cli(); -#elif defined(PROTOCOL_CHIBIOS) -    chSysLockFromISR(); -#endif - -    uint8_t next = (pbuf_head + 1) % PBUF_SIZE; -    if (next != pbuf_tail) { -        pbuf[pbuf_head] = data; -        pbuf_head       = next; -    } else { -        print("pbuf: full\n"); -    } - -#if defined(__AVR__) -    SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) -    chSysUnlockFromISR(); -#endif -} -static inline uint8_t pbuf_dequeue(void) { -    uint8_t val = 0; - -#if defined(__AVR__) -    uint8_t sreg = SREG; -    cli(); -#elif defined(PROTOCOL_CHIBIOS) -    chSysLock(); -#endif - -    if (pbuf_head != pbuf_tail) { -        val       = pbuf[pbuf_tail]; -        pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; -    } - -#if defined(__AVR__) -    SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) -    chSysUnlock(); -#endif - -    return val; -} -static inline bool pbuf_has_data(void) { -#if defined(__AVR__) -    uint8_t sreg = SREG; -    cli(); -#elif defined(PROTOCOL_CHIBIOS) -    chSysLock(); -#endif - -    bool has_data = (pbuf_head != pbuf_tail); - -#if defined(__AVR__) -    SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) -    chSysUnlock(); -#endif -    return has_data; -} -static inline void pbuf_clear(void) { -#if defined(__AVR__) -    uint8_t sreg = SREG; -    cli(); -#elif defined(PROTOCOL_CHIBIOS) -    chSysLock(); -#endif - -    pbuf_head = pbuf_tail = 0; - -#if defined(__AVR__) -    SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) -    chSysUnlock(); -#endif -} diff --git a/tmk_core/protocol/ps2_io.h b/tmk_core/protocol/ps2_io.h deleted file mode 100644 index de93cb7a39..0000000000 --- a/tmk_core/protocol/ps2_io.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -void clock_init(void); -void clock_lo(void); -void clock_hi(void); -bool clock_in(void); - -void data_init(void); -void data_lo(void); -void data_hi(void); -bool data_in(void); diff --git a/tmk_core/protocol/ps2_io_avr.c b/tmk_core/protocol/ps2_io_avr.c deleted file mode 100644 index a9ac5d338d..0000000000 --- a/tmk_core/protocol/ps2_io_avr.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <stdbool.h> -#include <avr/io.h> -#include <util/delay.h> - -/* Check port settings for clock and data line */ -#if !(defined(PS2_CLOCK_PORT) && defined(PS2_CLOCK_PIN) && defined(PS2_CLOCK_DDR) && defined(PS2_CLOCK_BIT)) -#    error "PS/2 clock port setting is required in config.h" -#endif - -#if !(defined(PS2_DATA_PORT) && defined(PS2_DATA_PIN) && defined(PS2_DATA_DDR) && defined(PS2_DATA_BIT)) -#    error "PS/2 data port setting is required in config.h" -#endif - -/* - * Clock - */ -void clock_init(void) {} - -void clock_lo(void) { -    PS2_CLOCK_PORT &= ~(1 << PS2_CLOCK_BIT); -    PS2_CLOCK_DDR |= (1 << PS2_CLOCK_BIT); -} - -void clock_hi(void) { -    /* input with pull up */ -    PS2_CLOCK_DDR &= ~(1 << PS2_CLOCK_BIT); -    PS2_CLOCK_PORT |= (1 << PS2_CLOCK_BIT); -} - -bool clock_in(void) { -    PS2_CLOCK_DDR &= ~(1 << PS2_CLOCK_BIT); -    PS2_CLOCK_PORT |= (1 << PS2_CLOCK_BIT); -    _delay_us(1); -    return PS2_CLOCK_PIN & (1 << PS2_CLOCK_BIT); -} - -/* - * Data - */ -void data_init(void) {} - -void data_lo(void) { -    PS2_DATA_PORT &= ~(1 << PS2_DATA_BIT); -    PS2_DATA_DDR |= (1 << PS2_DATA_BIT); -} - -void data_hi(void) { -    /* input with pull up */ -    PS2_DATA_DDR &= ~(1 << PS2_DATA_BIT); -    PS2_DATA_PORT |= (1 << PS2_DATA_BIT); -} - -bool data_in(void) { -    PS2_DATA_DDR &= ~(1 << PS2_DATA_BIT); -    PS2_DATA_PORT |= (1 << PS2_DATA_BIT); -    _delay_us(1); -    return PS2_DATA_PIN & (1 << PS2_DATA_BIT); -} diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c deleted file mode 100644 index b672bd1f47..0000000000 --- a/tmk_core/protocol/ps2_io_chibios.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdbool.h> -#include "ps2_io.h" - -// chibiOS headers -#include "ch.h" -#include "hal.h" - -/* Check port settings for clock and data line */ -#if !(defined(PS2_CLOCK)) -#    error "PS/2 clock setting is required in config.h" -#endif - -#if !(defined(PS2_DATA)) -#    error "PS/2 data setting is required in config.h" -#endif - -/* - * Clock - */ -void clock_init(void) {} - -void clock_lo(void) { -    palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN); -    palWriteLine(PS2_CLOCK, PAL_LOW); -} - -void clock_hi(void) { -    palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN); -    palWriteLine(PS2_CLOCK, PAL_HIGH); -} - -bool clock_in(void) { -    palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); -    return palReadLine(PS2_CLOCK); -} - -/* - * Data - */ -void data_init(void) {} - -void data_lo(void) { -    palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN); -    palWriteLine(PS2_DATA, PAL_LOW); -} - -void data_hi(void) { -    palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN); -    palWriteLine(PS2_DATA, PAL_HIGH); -} - -bool data_in(void) { -    palSetLineMode(PS2_DATA, PAL_MODE_INPUT); -    return palReadLine(PS2_DATA); -} diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c deleted file mode 100644 index 39251a6434..0000000000 --- a/tmk_core/protocol/ps2_mouse.c +++ /dev/null @@ -1,274 +0,0 @@ -/* -Copyright 2011,2013 Jun Wako <[email protected]> - -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 <stdbool.h> - -#if defined(__AVR__) -#    include <avr/io.h> -#endif - -#include "ps2_mouse.h" -#include "wait.h" -#include "host.h" -#include "timer.h" -#include "print.h" -#include "report.h" -#include "debug.h" -#include "ps2.h" - -/* ============================= MACROS ============================ */ - -static report_mouse_t mouse_report = {}; - -static inline void ps2_mouse_print_report(report_mouse_t *mouse_report); -static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report); -static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report); -static inline void ps2_mouse_enable_scrolling(void); -static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report); - -/* ============================= IMPLEMENTATION ============================ */ - -/* supports only 3 button mouse at this time */ -void ps2_mouse_init(void) { -    ps2_host_init(); - -    wait_ms(PS2_MOUSE_INIT_DELAY);  // wait for powering up - -    PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset"); - -    PS2_MOUSE_RECEIVE("ps2_mouse_init: read BAT"); -    PS2_MOUSE_RECEIVE("ps2_mouse_init: read DevID"); - -#ifdef PS2_MOUSE_USE_REMOTE_MODE -    ps2_mouse_set_remote_mode(); -#else -    ps2_mouse_enable_data_reporting(); -#endif - -#ifdef PS2_MOUSE_ENABLE_SCROLLING -    ps2_mouse_enable_scrolling(); -#endif - -#ifdef PS2_MOUSE_USE_2_1_SCALING -    ps2_mouse_set_scaling_2_1(); -#endif - -    ps2_mouse_init_user(); -} - -__attribute__((weak)) void ps2_mouse_init_user(void) {} - -__attribute__((weak)) void ps2_mouse_moved_user(report_mouse_t *mouse_report) {} - -void ps2_mouse_task(void) { -    static uint8_t buttons_prev = 0; -    extern int     tp_buttons; - -    /* receives packet from mouse */ -    uint8_t rcv; -    rcv = ps2_host_send(PS2_MOUSE_READ_DATA); -    if (rcv == PS2_ACK) { -        mouse_report.buttons = ps2_host_recv_response() | tp_buttons; -        mouse_report.x       = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER; -        mouse_report.y       = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER; -#ifdef PS2_MOUSE_ENABLE_SCROLLING -        mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER; -#endif -    } else { -        if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n"); -        return; -    } - -    /* if mouse moves or buttons state changes */ -    if (mouse_report.x || mouse_report.y || mouse_report.v || ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) { -#ifdef PS2_MOUSE_DEBUG_RAW -        // Used to debug raw ps2 bytes from mouse -        ps2_mouse_print_report(&mouse_report); -#endif -        buttons_prev = mouse_report.buttons; -        ps2_mouse_convert_report_to_hid(&mouse_report); -#if PS2_MOUSE_SCROLL_BTN_MASK -        ps2_mouse_scroll_button_task(&mouse_report); -#endif -        if (mouse_report.x || mouse_report.y || mouse_report.v) { -            ps2_mouse_moved_user(&mouse_report); -        } -#ifdef PS2_MOUSE_DEBUG_HID -        // Used to debug the bytes sent to the host -        ps2_mouse_print_report(&mouse_report); -#endif -        host_mouse_send(&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_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); } - -void ps2_mouse_set_remote_mode(void) { -    PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); -    ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE; -} - -void ps2_mouse_set_stream_mode(void) { -    PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set 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_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_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 ============================ */ - -#define X_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_X_SIGN)) -#define Y_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_Y_SIGN)) -#define X_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_X_OVFLW)) -#define Y_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_Y_OVFLW)) -static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) { -    // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value. -    // bit: 8    7 ... 0 -    //      sign \8-bit/ -    // -    // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used. -    // -    // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit. -    mouse_report->x = X_IS_NEG ? ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) : ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127); -    mouse_report->y = Y_IS_NEG ? ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) : ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127); - -#ifdef PS2_MOUSE_INVERT_BUTTONS -    // swap left & right buttons -    uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT; -    uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT; -    mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0); -#else -    // remove sign and overflow flags -    mouse_report->buttons &= PS2_MOUSE_BTN_MASK; -#endif - -#ifdef PS2_MOUSE_INVERT_X -    mouse_report->x = -mouse_report->x; -#endif -#ifndef PS2_MOUSE_INVERT_Y  // NOTE if not! -    // invert coordinate of y to conform to USB HID mouse -    mouse_report->y = -mouse_report->y; -#endif - -#ifdef PS2_MOUSE_ROTATE -    int8_t x = mouse_report->x; -    int8_t y = mouse_report->y; -#    if PS2_MOUSE_ROTATE == 90 -    mouse_report->x = y; -    mouse_report->y = -x; -#    elif PS2_MOUSE_ROTATE == 180 -    mouse_report->x = -x; -    mouse_report->y = -y; -#    elif PS2_MOUSE_ROTATE == 270 -    mouse_report->x = -y; -    mouse_report->y = x; -#    endif -#endif -} - -static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) { -    mouse_report->x       = 0; -    mouse_report->y       = 0; -    mouse_report->v       = 0; -    mouse_report->h       = 0; -    mouse_report->buttons = 0; -} - -static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) { -    if (!debug_mouse) return; -    print("ps2_mouse: ["); -    print_hex8(mouse_report->buttons); -    print("|"); -    print_hex8((uint8_t)mouse_report->x); -    print(" "); -    print_hex8((uint8_t)mouse_report->y); -    print(" "); -    print_hex8((uint8_t)mouse_report->v); -    print(" "); -    print_hex8((uint8_t)mouse_report->h); -    print("]\n"); -} - -static inline void ps2_mouse_enable_scrolling(void) { -    PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Initiaing scroll wheel enable: Set sample rate"); -    PS2_MOUSE_SEND(200, "200"); -    PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate"); -    PS2_MOUSE_SEND(100, "100"); -    PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate"); -    PS2_MOUSE_SEND(80, "80"); -    PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel"); -    wait_ms(20); -} - -#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) -#define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK) -static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { -    static enum { -        SCROLL_NONE, -        SCROLL_BTN, -        SCROLL_SENT, -    } scroll_state                     = SCROLL_NONE; -    static uint16_t scroll_button_time = 0; - -    if (PS2_MOUSE_SCROLL_BTN_MASK == (mouse_report->buttons & (PS2_MOUSE_SCROLL_BTN_MASK))) { -        // All scroll buttons are pressed - -        if (scroll_state == SCROLL_NONE) { -            scroll_button_time = timer_read(); -            scroll_state       = SCROLL_BTN; -        } - -        // If the mouse has moved, update the report to scroll instead of move the mouse -        if (mouse_report->x || mouse_report->y) { -            scroll_state    = SCROLL_SENT; -            mouse_report->v = -mouse_report->y / (PS2_MOUSE_SCROLL_DIVISOR_V); -            mouse_report->h = mouse_report->x / (PS2_MOUSE_SCROLL_DIVISOR_H); -            mouse_report->x = 0; -            mouse_report->y = 0; -#ifdef PS2_MOUSE_INVERT_H -            mouse_report->h = -mouse_report->h; -#endif -#ifdef PS2_MOUSE_INVERT_V -            mouse_report->v = -mouse_report->v; -#endif -        } -    } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) { -        // None of the scroll buttons are pressed - -#if PS2_MOUSE_SCROLL_BTN_SEND -        if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { -            PRESS_SCROLL_BUTTONS; -            host_mouse_send(mouse_report); -            wait_ms(100); -            RELEASE_SCROLL_BUTTONS; -        } -#endif -        scroll_state = SCROLL_NONE; -    } - -    RELEASE_SCROLL_BUTTONS; -} diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h deleted file mode 100644 index c97c6c893a..0000000000 --- a/tmk_core/protocol/ps2_mouse.h +++ /dev/null @@ -1,177 +0,0 @@ -/* -Copyright 2011 Jun Wako <[email protected]> - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program.  If not, see <http://www.gnu.org/licenses/>. -*/ - -#pragma once - -#include <stdbool.h> -#include "debug.h" -#include "report.h" - -#define PS2_MOUSE_SEND(command, message)                                                \ -    do {                                                                                \ -        __attribute__((unused)) uint8_t rcv = ps2_host_send(command);                   \ -        if (debug_mouse) {                                                              \ -            print((message));                                                           \ -            xprintf(" command: %X, result: %X, error: %X \n", command, rcv, ps2_error); \ -        }                                                                               \ -    } while (0) - -#define PS2_MOUSE_SEND_SAFE(command, message)          \ -    do {                                               \ -        if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ -            ps2_mouse_disable_data_reporting();        \ -        }                                              \ -        PS2_MOUSE_SEND(command, message);              \ -        if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ -            ps2_mouse_enable_data_reporting();         \ -        }                                              \ -    } while (0) - -#define PS2_MOUSE_SET_SAFE(command, value, message)    \ -    do {                                               \ -        if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ -            ps2_mouse_disable_data_reporting();        \ -        }                                              \ -        PS2_MOUSE_SEND(command, message);              \ -        PS2_MOUSE_SEND(value, "Sending value");        \ -        if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ -            ps2_mouse_enable_data_reporting();         \ -        }                                              \ -    } while (0) - -#define PS2_MOUSE_RECEIVE(message)                                      \ -    do {                                                                \ -        __attribute__((unused)) uint8_t rcv = ps2_host_recv_response(); \ -        if (debug_mouse) {                                              \ -            print((message));                                           \ -            xprintf(" result: %X, error: %X \n", rcv, ps2_error);       \ -        }                                                               \ -    } while (0) - -__attribute__((unused)) static enum ps2_mouse_mode_e { -    PS2_MOUSE_STREAM_MODE, -    PS2_MOUSE_REMOTE_MODE, -} ps2_mouse_mode = PS2_MOUSE_STREAM_MODE; - -/* - * Data format: - * byte|7       6       5       4       3       2       1       0 - * ----+---------------------------------------------------------------- - *    0|[Yovflw][Xovflw][Ysign ][Xsign ][ 1    ][Middle][Right ][Left  ] - *    1|[                    X movement(0-255)                         ] - *    2|[                    Y movement(0-255)                         ] - */ -#define PS2_MOUSE_BTN_MASK 0x07 -#define PS2_MOUSE_BTN_LEFT 0 -#define PS2_MOUSE_BTN_RIGHT 1 -#define PS2_MOUSE_BTN_MIDDLE 2 -#define PS2_MOUSE_X_SIGN 4 -#define PS2_MOUSE_Y_SIGN 5 -#define PS2_MOUSE_X_OVFLW 6 -#define PS2_MOUSE_Y_OVFLW 7 - -/* mouse button to start scrolling; set 0 to disable scroll */ -#ifndef PS2_MOUSE_SCROLL_BTN_MASK -#    define PS2_MOUSE_SCROLL_BTN_MASK (1 << PS2_MOUSE_BTN_MIDDLE) -#endif -/* send button event when button is released within this value(ms); set 0 to disable  */ -#ifndef PS2_MOUSE_SCROLL_BTN_SEND -#    define PS2_MOUSE_SCROLL_BTN_SEND 300 -#endif -/* divide virtical and horizontal mouse move by this to convert to scroll move */ -#ifndef PS2_MOUSE_SCROLL_DIVISOR_V -#    define PS2_MOUSE_SCROLL_DIVISOR_V 2 -#endif -#ifndef PS2_MOUSE_SCROLL_DIVISOR_H -#    define PS2_MOUSE_SCROLL_DIVISOR_H 2 -#endif -/* multiply reported mouse values by these */ -#ifndef PS2_MOUSE_X_MULTIPLIER -#    define PS2_MOUSE_X_MULTIPLIER 1 -#endif -#ifndef PS2_MOUSE_Y_MULTIPLIER -#    define PS2_MOUSE_Y_MULTIPLIER 1 -#endif -#ifndef PS2_MOUSE_V_MULTIPLIER -#    define PS2_MOUSE_V_MULTIPLIER 1 -#endif -/* For some mice this will need to be 0x0F */ -#ifndef PS2_MOUSE_SCROLL_MASK -#    define PS2_MOUSE_SCROLL_MASK 0xFF -#endif -#ifndef PS2_MOUSE_INIT_DELAY -#    define PS2_MOUSE_INIT_DELAY 1000 -#endif - -enum ps2_mouse_command_e { -    PS2_MOUSE_RESET                  = 0xFF, -    PS2_MOUSE_RESEND                 = 0xFE, -    PS2_MOSUE_SET_DEFAULTS           = 0xF6, -    PS2_MOUSE_DISABLE_DATA_REPORTING = 0xF5, -    PS2_MOUSE_ENABLE_DATA_REPORTING  = 0xF4, -    PS2_MOUSE_SET_SAMPLE_RATE        = 0xF3, -    PS2_MOUSE_GET_DEVICE_ID          = 0xF2, -    PS2_MOUSE_SET_REMOTE_MODE        = 0xF0, -    PS2_MOUSE_SET_WRAP_MODE          = 0xEC, -    PS2_MOUSE_READ_DATA              = 0xEB, -    PS2_MOUSE_SET_STREAM_MODE        = 0xEA, -    PS2_MOUSE_STATUS_REQUEST         = 0xE9, -    PS2_MOUSE_SET_RESOLUTION         = 0xE8, -    PS2_MOUSE_SET_SCALING_2_1        = 0xE7, -    PS2_MOUSE_SET_SCALING_1_1        = 0xE6, -}; - -typedef enum ps2_mouse_resolution_e { -    PS2_MOUSE_1_COUNT_MM, -    PS2_MOUSE_2_COUNT_MM, -    PS2_MOUSE_4_COUNT_MM, -    PS2_MOUSE_8_COUNT_MM, -} ps2_mouse_resolution_t; - -typedef enum ps2_mouse_sample_rate_e { -    PS2_MOUSE_10_SAMPLES_SEC  = 10, -    PS2_MOUSE_20_SAMPLES_SEC  = 20, -    PS2_MOUSE_40_SAMPLES_SEC  = 40, -    PS2_MOUSE_60_SAMPLES_SEC  = 60, -    PS2_MOUSE_80_SAMPLES_SEC  = 80, -    PS2_MOUSE_100_SAMPLES_SEC = 100, -    PS2_MOUSE_200_SAMPLES_SEC = 200, -} ps2_mouse_sample_rate_t; - -void ps2_mouse_init(void); - -void ps2_mouse_init_user(void); - -void ps2_mouse_task(void); - -void ps2_mouse_disable_data_reporting(void); - -void ps2_mouse_enable_data_reporting(void); - -void ps2_mouse_set_remote_mode(void); - -void ps2_mouse_set_stream_mode(void); - -void ps2_mouse_set_scaling_2_1(void); - -void ps2_mouse_set_scaling_1_1(void); - -void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution); - -void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate); - -void ps2_mouse_moved_user(report_mouse_t *mouse_report); diff --git a/tmk_core/protocol/ps2_usart.c b/tmk_core/protocol/ps2_usart.c deleted file mode 100644 index 6a66dc4a1e..0000000000 --- a/tmk_core/protocol/ps2_usart.c +++ /dev/null @@ -1,213 +0,0 @@ -/* -Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - * PS/2 protocol USART version - */ - -#include <stdbool.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "ps2.h" -#include "ps2_io.h" -#include "print.h" - -#define WAIT(stat, us, err)     \ -    do {                        \ -        if (!wait_##stat(us)) { \ -            ps2_error = err;    \ -            goto ERROR;         \ -        }                       \ -    } while (0) - -uint8_t ps2_error = PS2_ERR_NONE; - -static inline uint8_t pbuf_dequeue(void); -static inline void    pbuf_enqueue(uint8_t data); -static inline bool    pbuf_has_data(void); -static inline void    pbuf_clear(void); - -void ps2_host_init(void) { -    idle();  // without this many USART errors occur when cable is disconnected -    PS2_USART_INIT(); -    PS2_USART_RX_INT_ON(); -    // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) -    //_delay_ms(2500); -} - -uint8_t ps2_host_send(uint8_t data) { -    bool parity = true; -    ps2_error   = PS2_ERR_NONE; - -    PS2_USART_OFF(); - -    /* terminate a transmission if we have */ -    inhibit(); -    _delay_us(100);  // [4]p.13 - -    /* 'Request to Send' and Start bit */ -    data_lo(); -    clock_hi(); -    WAIT(clock_lo, 10000, 10);  // 10ms [5]p.50 - -    /* Data bit[2-9] */ -    for (uint8_t i = 0; i < 8; i++) { -        _delay_us(15); -        if (data & (1 << i)) { -            parity = !parity; -            data_hi(); -        } else { -            data_lo(); -        } -        WAIT(clock_hi, 50, 2); -        WAIT(clock_lo, 50, 3); -    } - -    /* Parity bit */ -    _delay_us(15); -    if (parity) { -        data_hi(); -    } else { -        data_lo(); -    } -    WAIT(clock_hi, 50, 4); -    WAIT(clock_lo, 50, 5); - -    /* Stop bit */ -    _delay_us(15); -    data_hi(); - -    /* Ack */ -    WAIT(data_lo, 50, 6); -    WAIT(clock_lo, 50, 7); - -    /* wait for idle state */ -    WAIT(clock_hi, 50, 8); -    WAIT(data_hi, 50, 9); - -    idle(); -    PS2_USART_INIT(); -    PS2_USART_RX_INT_ON(); -    return ps2_host_recv_response(); -ERROR: -    idle(); -    PS2_USART_INIT(); -    PS2_USART_RX_INT_ON(); -    return 0; -} - -uint8_t ps2_host_recv_response(void) { -    // Command may take 25ms/20ms at most([5]p.46, [3]p.21) -    uint8_t retry = 25; -    while (retry-- && !pbuf_has_data()) { -        _delay_ms(1); -    } -    return pbuf_dequeue(); -} - -uint8_t ps2_host_recv(void) { -    if (pbuf_has_data()) { -        ps2_error = PS2_ERR_NONE; -        return pbuf_dequeue(); -    } else { -        ps2_error = PS2_ERR_NODATA; -        return 0; -    } -} - -ISR(PS2_USART_RX_VECT) { -    // TODO: request RESEND when error occurs? -    uint8_t error = PS2_USART_ERROR;  // USART error should be read before data -    uint8_t data  = PS2_USART_RX_DATA; -    if (!error) { -        pbuf_enqueue(data); -    } else { -        xprintf("PS2 USART error: %02X data: %02X\n", error, data); -    } -} - -/* send LED state to keyboard */ -void ps2_host_set_led(uint8_t led) { -    ps2_host_send(0xED); -    ps2_host_send(led); -} - -/*-------------------------------------------------------------------- - * Ring buffer to store scan codes from keyboard - *------------------------------------------------------------------*/ -#define PBUF_SIZE 32 -static uint8_t     pbuf[PBUF_SIZE]; -static uint8_t     pbuf_head = 0; -static uint8_t     pbuf_tail = 0; -static inline void pbuf_enqueue(uint8_t data) { -    uint8_t sreg = SREG; -    cli(); -    uint8_t next = (pbuf_head + 1) % PBUF_SIZE; -    if (next != pbuf_tail) { -        pbuf[pbuf_head] = data; -        pbuf_head       = next; -    } else { -        print("pbuf: full\n"); -    } -    SREG = sreg; -} -static inline uint8_t pbuf_dequeue(void) { -    uint8_t val = 0; - -    uint8_t sreg = SREG; -    cli(); -    if (pbuf_head != pbuf_tail) { -        val       = pbuf[pbuf_tail]; -        pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; -    } -    SREG = sreg; - -    return val; -} -static inline bool pbuf_has_data(void) { -    uint8_t sreg = SREG; -    cli(); -    bool has_data = (pbuf_head != pbuf_tail); -    SREG          = sreg; -    return has_data; -} -static inline void pbuf_clear(void) { -    uint8_t sreg = SREG; -    cli(); -    pbuf_head = pbuf_tail = 0; -    SREG                  = sreg; -} diff --git a/tmk_core/common/report.c b/tmk_core/protocol/report.c index 2a7fc006c4..854b59ae48 100644 --- a/tmk_core/common/report.c +++ b/tmk_core/protocol/report.c @@ -24,8 +24,8 @@  #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE  #    define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)  #    define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) -#    define RO_INC(a)    RO_ADD(a, 1) -#    define RO_DEC(a)    RO_SUB(a, 1) +#    define RO_INC(a) RO_ADD(a, 1) +#    define RO_DEC(a) RO_SUB(a, 1)  static int8_t cb_head  = 0;  static int8_t cb_tail  = 0;  static int8_t cb_count = 0; diff --git a/tmk_core/common/report.h b/tmk_core/protocol/report.h index f2223e8063..1adc892f3b 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/protocol/report.h @@ -29,6 +29,7 @@ enum hid_report_ids {      REPORT_ID_MOUSE,      REPORT_ID_SYSTEM,      REPORT_ID_CONSUMER, +    REPORT_ID_PROGRAMMABLE_BUTTON,      REPORT_ID_NKRO,      REPORT_ID_JOYSTICK,      REPORT_ID_DIGITIZER @@ -196,6 +197,11 @@ typedef struct {  } __attribute__((packed)) report_extra_t;  typedef struct { +    uint8_t  report_id; +    uint32_t usage; +} __attribute__((packed)) report_programmable_button_t; + +typedef struct {  #ifdef MOUSE_SHARED_EP      uint8_t report_id;  #endif diff --git a/tmk_core/protocol/serial_mouse.h b/tmk_core/protocol/serial_mouse.h deleted file mode 100644 index cb83cf4f62..0000000000 --- a/tmk_core/protocol/serial_mouse.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2014 Robin Haberkorn <[email protected]> - -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 "serial.h" - -static inline uint8_t serial_mouse_init(void) { -    serial_init(); -    return 0; -} - -void serial_mouse_task(void); diff --git a/tmk_core/protocol/serial_mouse_microsoft.c b/tmk_core/protocol/serial_mouse_microsoft.c deleted file mode 100644 index eff0bf6e45..0000000000 --- a/tmk_core/protocol/serial_mouse_microsoft.c +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright 2014 Robin Haberkorn <[email protected]> - -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 <stdint.h> -#include <avr/io.h> -#include <util/delay.h> - -#include "serial.h" -#include "serial_mouse.h" -#include "report.h" -#include "host.h" -#include "timer.h" -#include "print.h" -#include "debug.h" - -#ifdef MAX -#    undef MAX -#endif -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) - -static void print_usb_data(const report_mouse_t *report); - -void serial_mouse_task(void) { -    /* 3 byte ring buffer */ -    static uint8_t buffer[3]; -    static int     buffer_cur = 0; - -    static report_mouse_t report = {}; - -    int16_t rcv; - -    rcv = serial_recv2(); -    if (rcv < 0) /* no new data */ -        return; - -    if (debug_mouse) xprintf("serial_mouse: byte: %04X\n", rcv); - -    /* -     * If bit 6 is one, this signals the beginning -     * of a 3 byte sequence/packet. -     */ -    if (rcv & (1 << 6)) buffer_cur = 0; - -    buffer[buffer_cur] = (uint8_t)rcv; - -    if (buffer_cur == 0 && buffer[buffer_cur] == 0x20) { -        /* -         * Logitech extension: This must be a follow-up on -         * the last 3-byte packet signaling a middle button click -         */ -        report.buttons |= MOUSE_BTN3; -        report.x = report.y = 0; - -        print_usb_data(&report); -        host_mouse_send(&report); -        return; -    } - -    buffer_cur++; - -    if (buffer_cur < 3) return; -    buffer_cur = 0; - -    /* -     * parse 3 byte packet. -     * NOTE: We only get a complete packet -     * if the mouse moved or the button states -     * change. -     */ -    report.buttons = 0; -    if (buffer[0] & (1 << 5)) report.buttons |= MOUSE_BTN1; -    if (buffer[0] & (1 << 4)) report.buttons |= MOUSE_BTN2; - -    report.x = (buffer[0] << 6) | buffer[1]; -    report.y = ((buffer[0] << 4) & 0xC0) | buffer[2]; - -    /* USB HID uses values from -127 to 127 only */ -    report.x = MAX(report.x, -127); -    report.y = MAX(report.y, -127); - -#if 0 -    if (!report.buttons && !report.x && !report.y) { -        /* -         * Microsoft extension: Middle mouse button pressed -         * FIXME: I don't know how exactly this extension works. -         */ -        report.buttons |= MOUSE_BTN3; -    } -#endif - -    print_usb_data(&report); -    host_mouse_send(&report); -} - -static void print_usb_data(const report_mouse_t *report) { -    if (!debug_mouse) return; - -    xprintf("serial_mouse usb: [%02X|%d %d %d %d]\n", report->buttons, report->x, report->y, report->v, report->h); -} diff --git a/tmk_core/protocol/serial_mouse_mousesystems.c b/tmk_core/protocol/serial_mouse_mousesystems.c deleted file mode 100644 index 0ec2b0399a..0000000000 --- a/tmk_core/protocol/serial_mouse_mousesystems.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -Copyright 2014 Robin Haberkorn <[email protected]> - -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 <stdint.h> -#include <avr/io.h> -#include <util/delay.h> - -#include "serial.h" -#include "serial_mouse.h" -#include "report.h" -#include "host.h" -#include "timer.h" -#include "print.h" -#include "debug.h" - -#ifdef MAX -#    undef MAX -#endif -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) - -//#define SERIAL_MOUSE_CENTER_SCROLL - -static void print_usb_data(const report_mouse_t *report); - -void serial_mouse_task(void) { -    /* 5 byte ring buffer */ -    static uint8_t buffer[5]; -    static int     buffer_cur = 0; - -    int16_t rcv; - -    report_mouse_t report = {0, 0, 0, 0, 0}; - -    rcv = serial_recv2(); -    if (rcv < 0) /* no new data */ -        return; - -    if (debug_mouse) xprintf("serial_mouse: byte: %04X\n", rcv); - -    /* -     * Synchronization: mouse(4) says that all -     * bytes but the first one in the packet have -     * bit 7 == 0, but this is untrue. -     * Therefore we discard all bytes up to the -     * first one with the characteristic bit pattern. -     */ -    if (buffer_cur == 0 && (rcv >> 3) != 0x10) return; - -    buffer[buffer_cur++] = (uint8_t)rcv; - -    if (buffer_cur < 5) return; -    buffer_cur = 0; - -#ifdef SERIAL_MOUSE_CENTER_SCROLL -    if ((buffer[0] & 0x7) == 0x5 && (buffer[1] || buffer[2])) { -        /* USB HID uses only values from -127 to 127 */ -        report.h = MAX((int8_t)buffer[1], -127); -        report.v = MAX((int8_t)buffer[2], -127); - -        print_usb_data(&report); -        host_mouse_send(&report); - -        if (buffer[3] || buffer[4]) { -            report.h = MAX((int8_t)buffer[3], -127); -            report.v = MAX((int8_t)buffer[4], -127); - -            print_usb_data(&report); -            host_mouse_send(&report); -        } - -        return; -    } -#endif - -    /* -     * parse 5 byte packet. -     * NOTE: We only get a complete packet -     * if the mouse moved or the button states -     * change. -     */ -    if (!(buffer[0] & (1 << 2))) report.buttons |= MOUSE_BTN1; -    if (!(buffer[0] & (1 << 1))) report.buttons |= MOUSE_BTN3; -    if (!(buffer[0] & (1 << 0))) report.buttons |= MOUSE_BTN2; - -    /* USB HID uses only values from -127 to 127 */ -    report.x = MAX((int8_t)buffer[1], -127); -    report.y = MAX(-(int8_t)buffer[2], -127); - -    print_usb_data(&report); -    host_mouse_send(&report); - -    if (buffer[3] || buffer[4]) { -        report.x = MAX((int8_t)buffer[3], -127); -        report.y = MAX(-(int8_t)buffer[4], -127); - -        print_usb_data(&report); -        host_mouse_send(&report); -    } -} - -static void print_usb_data(const report_mouse_t *report) { -    if (!debug_mouse) return; - -    xprintf("serial_mouse usb: [%02X|%d %d %d %d]\n", report->buttons, report->x, report->y, report->v, report->h); -} diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 099964ae56..a43755f899 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -237,6 +237,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {      HID_RI_END_COLLECTION(0),  #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    HID_RI_USAGE_PAGE(8, 0x0C),            // Consumer +    HID_RI_USAGE(8, 0x01),                 // Consumer Control +    HID_RI_COLLECTION(8, 0x01),            // Application +        HID_RI_REPORT_ID(8, REPORT_ID_PROGRAMMABLE_BUTTON), +        HID_RI_USAGE(8, 0x03),             // Programmable Buttons +        HID_RI_COLLECTION(8, 0x04),        // Named Array +            HID_RI_USAGE_PAGE(8, 0x09),    // Button +            HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 +            HID_RI_USAGE_MAXIMUM(8, 0x20), // Button 32 +            HID_RI_LOGICAL_MINIMUM(8, 0x00), +            HID_RI_LOGICAL_MAXIMUM(8, 0x01), +            HID_RI_REPORT_COUNT(8, 32), +            HID_RI_REPORT_SIZE(8, 1), +            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), +        HID_RI_END_COLLECTION(0), +    HID_RI_END_COLLECTION(0), +#endif +  #ifdef NKRO_ENABLE      HID_RI_USAGE_PAGE(8, 0x01),        // Generic Desktop      HID_RI_USAGE(8, 0x06),             // Keyboard diff --git a/tmk_core/protocol/usb_device_state.c b/tmk_core/protocol/usb_device_state.c new file mode 100644 index 0000000000..84f01943be --- /dev/null +++ b/tmk_core/protocol/usb_device_state.c @@ -0,0 +1,59 @@ +/* + * Copyright 2021 Andrei Purdea <[email protected]> + * + * 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 "usb_device_state.h" +#if defined(HAPTIC_ENABLE) +#    include "haptic.h" +#endif + +enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; + +__attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); } + +__attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} + +static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { +#if defined(HAPTIC_ENABLE) && HAPTIC_OFF_IN_LOW_POWER +    haptic_notify_usb_device_state_change(); +#endif +    notify_usb_device_state_change_kb(usb_device_state); +} + +void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { +    usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; +    notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { +    usb_device_state = USB_DEVICE_STATE_SUSPEND; +    notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { +    usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; +    notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_reset(void) { +    usb_device_state = USB_DEVICE_STATE_INIT; +    notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_init(void) { +    usb_device_state = USB_DEVICE_STATE_INIT; +    notify_usb_device_state_change(usb_device_state); +} diff --git a/tmk_core/protocol/usb_device_state.h b/tmk_core/protocol/usb_device_state.h new file mode 100644 index 0000000000..c229311d46 --- /dev/null +++ b/tmk_core/protocol/usb_device_state.h @@ -0,0 +1,39 @@ +/* + * Copyright 2021 Andrei Purdea <[email protected]> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_reset(void); +void usb_device_state_init(void); + +enum usb_device_state { +    USB_DEVICE_STATE_NO_INIT    = 0,  // We're in this state before calling usb_device_state_init() +    USB_DEVICE_STATE_INIT       = 1,  // Can consume up to 100mA +    USB_DEVICE_STATE_CONFIGURED = 2,  // Can consume up to what is specified in configuration descriptor, typically 500mA +    USB_DEVICE_STATE_SUSPEND    = 3   // Can consume only suspend current +}; + +extern enum usb_device_state usb_device_state; + +void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state); +void notify_usb_device_state_change_user(enum usb_device_state usb_device_state); diff --git a/tmk_core/protocol/usb_hid/parser.h b/tmk_core/protocol/usb_hid/parser.h index 036281fa66..ba35b7af5a 100644 --- a/tmk_core/protocol/usb_hid/parser.h +++ b/tmk_core/protocol/usb_hid/parser.h @@ -1,5 +1,4 @@ -#ifndef PARSER_H -#define PARSER_H +#pragma once  #include "hid.h"  #include "report.h" @@ -11,5 +10,3 @@ public:      uint16_t time_stamp;      virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);  }; - -#endif diff --git a/tmk_core/protocol/usb_hid/usb_hid.h b/tmk_core/protocol/usb_hid/usb_hid.h index 083b68d1f5..5cb5f5d035 100644 --- a/tmk_core/protocol/usb_hid/usb_hid.h +++ b/tmk_core/protocol/usb_hid/usb_hid.h @@ -1,10 +1,6 @@ -#ifndef USB_HID_H -#define USB_HID_H +#pragma once  #include "report.h" -  extern report_keyboard_t usb_hid_keyboard_report;  extern uint16_t usb_hid_time_stamp; - -#endif diff --git a/tmk_core/common/usb_util.c b/tmk_core/protocol/usb_util.c index dd1deeaa11..dd1deeaa11 100644 --- a/tmk_core/common/usb_util.c +++ b/tmk_core/protocol/usb_util.c diff --git a/tmk_core/common/usb_util.h b/tmk_core/protocol/usb_util.h index 13db9fbfbd..13db9fbfbd 100644 --- a/tmk_core/common/usb_util.h +++ b/tmk_core/protocol/usb_util.h diff --git a/tmk_core/protocol/vusb/protocol.c b/tmk_core/protocol/vusb/protocol.c index 89dc795b21..644e77e021 100644 --- a/tmk_core/protocol/vusb/protocol.c +++ b/tmk_core/protocol/vusb/protocol.c @@ -111,22 +111,16 @@ void protocol_setup(void) {      // clock prescaler      clock_prescale_set(clock_div_1);  #endif -    keyboard_setup();  } -void protocol_init(void) { +void protocol_pre_init(void) {      setup_usb();      sei(); +} -    keyboard_init(); - +void protocol_post_init(void) {      host_set_driver(vusb_driver()); -      wait_ms(50); - -#ifdef SLEEP_LED_ENABLE -    sleep_led_init(); -#endif  }  void protocol_task(void) { diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 485b20c900..bd0f1c21aa 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -226,8 +226,9 @@ static void    send_keyboard(report_keyboard_t *report);  static void    send_mouse(report_mouse_t *report);  static void    send_system(uint16_t data);  static void    send_consumer(uint16_t data); +static void    send_programmable_button(uint32_t data); -static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; +static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};  host_driver_t *vusb_driver(void) { return &driver; } @@ -300,6 +301,20 @@ void send_digitizer(report_digitizer_t *report) {  #endif  } +static void send_programmable_button(uint32_t data) { +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    static report_programmable_button_t report = { +        .report_id = REPORT_ID_PROGRAMMABLE_BUTTON, +    }; + +    report.usage = data; + +    if (usbInterruptIsReadyShared()) { +        usbSetInterruptShared((void *)&report, sizeof(report)); +    } +#endif +} +  /*------------------------------------------------------------------*   * Request from host                                                *   *------------------------------------------------------------------*/ @@ -555,7 +570,27 @@ const PROGMEM uchar shared_hid_report[] = {      0x09, 0x31,        //     Usage (Y)      0x81, 0x02,        //     Input (Data, Variable, Absolute)      0xC0,              //   End Collection -    0xC0               // End Collection +    0xC0,              // End Collection +#endif + +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    // Programmable buttons report descriptor +    0x05, 0x0C,                           // Usage Page (Consumer) +    0x09, 0x01,                           // Usage (Consumer Control) +    0xA1, 0x01,                           // Collection (Application) +    0x85, REPORT_ID_PROGRAMMABLE_BUTTON,  //   Report ID +    0x09, 0x03,                           //   Usage (Programmable Buttons) +    0xA1, 0x04,                           //   Collection (Named Array) +    0x05, 0x09,                           //     Usage Page (Button) +    0x19, 0x01,                           //     Usage Minimum (Button 1) +    0x29, 0x20,                           //     Usage Maximum (Button 32) +    0x15, 0x00,                           //     Logical Minimum (0) +    0x25, 0x01,                           //     Logical Maximum (1) +    0x95, 0x20,                           //     Report Count (32) +    0x75, 0x01,                           //     Report Size (1) +    0x81, 0x02,                           //     Input (Data, Variable, Absolute) +    0xC0,                                 //   End Collection +    0xC0,                                 // End Collection  #endif  #ifdef SHARED_EP_ENABLE diff --git a/tmk_core/protocol/xt.h b/tmk_core/protocol/xt.h deleted file mode 100644 index 538ff0e459..0000000000 --- a/tmk_core/protocol/xt.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2018 Jun WAKO <[email protected]> -Copyright 2016 Ethan Apodaca <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include "quantum.h" - -#define XT_DATA_IN()               \ -    do {                           \ -        setPinInput(XT_DATA_PIN);  \ -        writePinHigh(XT_DATA_PIN); \ -    } while (0) - -#define XT_DATA_READ() readPin(XT_DATA_PIN) - -#define XT_DATA_LO()               \ -    do {                           \ -        writePinLow(XT_DATA_PIN);  \ -        setPinOutput(XT_DATA_PIN); \ -    } while (0) - -#define XT_CLOCK_IN()               \ -    do {                            \ -        setPinInput(XT_CLOCK_PIN);  \ -        writePinHigh(XT_CLOCK_PIN); \ -    } while (0) - -#define XT_CLOCK_READ() readPin(XT_CLOCK_PIN) - -#define XT_CLOCK_LO()               \ -    do {                            \ -        writePinLow(XT_CLOCK_PIN);  \ -        setPinOutput(XT_CLOCK_PIN); \ -    } while (0) - -void xt_host_init(void); - -uint8_t xt_host_recv(void); diff --git a/tmk_core/protocol/xt_interrupt.c b/tmk_core/protocol/xt_interrupt.c deleted file mode 100644 index ba9d71848f..0000000000 --- a/tmk_core/protocol/xt_interrupt.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2018 Jun WAKO <[email protected]> -Copyright 2016 Ethan Apodaca <[email protected]> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <stdbool.h> -#include <avr/interrupt.h> -#include "xt.h" -#include "wait.h" -#include "debug.h" - -static inline uint8_t pbuf_dequeue(void); -static inline void    pbuf_enqueue(uint8_t data); -static inline bool    pbuf_has_data(void); -static inline void    pbuf_clear(void); - -void xt_host_init(void) { -    XT_INT_INIT(); -    XT_INT_OFF(); - -    /* hard reset */ -#ifdef XT_RESET -    XT_RESET(); -#endif - -    /* soft reset: pull clock line down for 20ms */ -    XT_DATA_LO(); -    XT_CLOCK_LO(); -    wait_ms(20); - -    /* input mode with pullup */ -    XT_CLOCK_IN(); -    XT_DATA_IN(); - -    XT_INT_ON(); -} - -/* get data received by interrupt */ -uint8_t xt_host_recv(void) { -    if (pbuf_has_data()) { -        return pbuf_dequeue(); -    } else { -        return 0; -    } -} - -ISR(XT_INT_VECT) { -    /* -     * XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data, -     * which should be read on falling edge of clock. -     * -     *  start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7 -     * -     * Original IBM XT keyboard sends start(0) bit while some of clones don't. -     * Start(0) bit is read as low on data line while start(1) as high. -     * -     * https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol -     */ -    static enum { START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7 } state = START; -    static uint8_t data                                                         = 0; - -    uint8_t dbit = XT_DATA_READ(); - -    // This is needed if using PCINT which can be called on both falling and rising edge -    // if (XT_CLOCK_READ()) return; - -    switch (state) { -        case START: -            // ignore start(0) bit -            if (!dbit) return; -            break; -        case BIT0 ... BIT7: -            data >>= 1; -            if (dbit) data |= 0x80; -            break; -    } -    if (state++ == BIT7) { -        pbuf_enqueue(data); -        state = START; -        data  = 0; -    } -    return; -} - -/*-------------------------------------------------------------------- - * Ring buffer to store scan codes from keyboard - *------------------------------------------------------------------*/ -#define PBUF_SIZE 32 -static uint8_t pbuf[PBUF_SIZE]; -static uint8_t pbuf_head = 0; -static uint8_t pbuf_tail = 0; - -static inline void pbuf_enqueue(uint8_t data) { -    uint8_t sreg = SREG; -    cli(); -    uint8_t next = (pbuf_head + 1) % PBUF_SIZE; -    if (next != pbuf_tail) { -        pbuf[pbuf_head] = data; -        pbuf_head       = next; -    } else { -        dprintf("pbuf: full\n"); -    } -    SREG = sreg; -} - -static inline uint8_t pbuf_dequeue(void) { -    uint8_t val = 0; - -    uint8_t sreg = SREG; -    cli(); -    if (pbuf_head != pbuf_tail) { -        val       = pbuf[pbuf_tail]; -        pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; -    } -    SREG = sreg; - -    return val; -} - -static inline bool pbuf_has_data(void) { -    uint8_t sreg = SREG; -    cli(); -    bool has_data = (pbuf_head != pbuf_tail); -    SREG          = sreg; -    return has_data; -} - -static inline void pbuf_clear(void) { -    uint8_t sreg = SREG; -    cli(); -    pbuf_head = pbuf_tail = 0; -    SREG                  = sreg; -} diff --git a/tmk_core/readme.md b/tmk_core/readme.md index a754cfee42..a47dc88185 100644 --- a/tmk_core/readme.md +++ b/tmk_core/readme.md @@ -25,7 +25,6 @@ These features can be used in your keyboard.  * Media Control Key   - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc  * USB NKRO            - 248 keys(+ 8 modifiers) simultaneously  * PS/2 mouse support  - PS/2 mouse(TrackPoint) as composite device -* Keyboard protocols  - PS/2, ADB, M0110, Sun and other old keyboard protocols  * User Function       - Customizable function of key with writing code  * Macro               - Very primitive at this time  * Keyboard Tricks     - Oneshot modifier and modifier with tapping feature @@ -84,9 +83,9 @@ Architecture        /          /| Keys/Mouse | Protocol  |d| | Action      | | | Protocol  |       /__________/ |<-----------|  LUFA     |r| |  Layer, Tap | | |  Matrix   |       |.--------.| |   LED      |  V-USB    |i| |-------------| | |  PS/2,IBM |             __________________ -     ||        || |----------->|  UART     |v| | Keymap      | | |  ADB,M0110|  Keys      / /_/_/_/_/_/_/_/ /| -     ||  Host  || |  Console   |           |e| | Mousekey    | | |  SUN/NEWS |<----------/ /_/_/_/_/_/_/_/ / / -     ||________||/.<-----------|           |r| | Report      | | |  X68K/PC98| Control  / /_/_/_/_/_/_/_/ / / +     ||        || |----------->|  UART     |v| | Keymap      | | |           |  Keys      / /_/_/_/_/_/_/_/ /| +     ||  Host  || |  Console   |           |e| | Mousekey    | | |           |<----------/ /_/_/_/_/_/_/_/ / / +     ||________||/.<-----------|           |r| | Report      | | |           | Control  / /_/_/_/_/_/_/_/ / /       `_========_'/|            |---------------------------------------------|-------->/___ /_______/ ___/ /       |_o______o_|/             | Sendchar, Print, Debug, Command, ...        |         |_________________|/                                 +---------------------------------------------+              Keyboard @@ -134,10 +133,6 @@ Files and Directories  * lufa/     - LUFA USB stack  * vusb/     - Objective Development V-USB  * ps2.c     - PS/2 protocol -* adb.c     - Apple Desktop Bus protocol -* m0110.c   - Macintosh 128K/512K/Plus keyboard protocol -* news.c    - Sony NEWS keyboard protocol -* x68k.c    - Sharp X68000 keyboard protocol  * serial_soft.c - Asynchronous Serial protocol implemented by software diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index 5a629d1eb0..70ab0eb166 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -69,8 +69,11 @@ CSTANDARD = -std=gnu99  #CXXDEFS += -D__STDC_CONSTANT_MACROS  #CXXDEFS += - - +# Speed up recompilations by opt-in usage of ccache +USE_CCACHE ?= no +ifneq ($(USE_CCACHE),no) +    CC_PREFIX ?= ccache +endif  #---------------- Compiler Options C ----------------  #  -g*:          generate debugging information @@ -79,6 +82,15 @@ CSTANDARD = -std=gnu99  #  -Wall...:     warning level  #  -Wa,...:      tell GCC to pass this to the assembler.  #    -adhlns...: create assembler listing +ifeq ($(strip $(LTO_ENABLE)), yes) +    ifeq ($(PLATFORM),CHIBIOS) +        $(info Enabling LTO on ChibiOS-targeting boards is known to have a high likelihood of failure.) +        $(info If unsure, set LTO_ENABLE = no.) +    endif +    CDEFS += -flto +    CDEFS += -DLTO_ENABLE +endif +  DEBUG_ENABLE ?= yes  ifeq ($(strip $(SKIP_DEBUG_INFO)),yes)    DEBUG_ENABLE=no @@ -347,7 +359,7 @@ BEGIN = gccversion sizebefore  # Note the obj.txt depeendency is there to force linking if a source file is deleted  %.elf: $(OBJ) $(MASTER_OUTPUT)/cflags.txt $(MASTER_OUTPUT)/ldflags.txt $(MASTER_OUTPUT)/obj.txt | $(BEGIN)  	@$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD) -	$(eval CMD=$(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS)) +	$(eval CMD=MAKE=$(MAKE) $(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS))  	@$(BUILD_CMD) | 
