aboutsummaryrefslogtreecommitdiff
path: root/tmk_core
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/arm_atsam.mk2
-rw-r--r--tmk_core/avr.mk2
-rw-r--r--tmk_core/chibios.mk308
-rw-r--r--tmk_core/common.mk19
-rw-r--r--tmk_core/common/arm_atsam/eeprom.c94
-rw-r--r--tmk_core/common/arm_atsam/gpio.h8
-rw-r--r--tmk_core/common/avr/suspend.c98
-rw-r--r--tmk_core/common/chibios/_wait.h2
-rw-r--r--tmk_core/common/chibios/bootloader.c22
-rw-r--r--tmk_core/common/chibios/chibios_config.h62
-rw-r--r--tmk_core/common/chibios/eeprom_stm32.c57
-rw-r--r--tmk_core/common/chibios/eeprom_stm32_defs.h25
-rw-r--r--tmk_core/common/chibios/flash_stm32.c48
-rw-r--r--tmk_core/common/chibios/gd32v_compatibility.h120
-rw-r--r--tmk_core/common/chibios/suspend.c89
-rw-r--r--tmk_core/common/chibios/syscall-fallbacks.c6
-rw-r--r--tmk_core/common/host.c15
-rw-r--r--tmk_core/common/host.h2
-rw-r--r--tmk_core/common/host_driver.h1
-rw-r--r--tmk_core/common/report.h6
-rw-r--r--tmk_core/common/suspend.h2
-rw-r--r--tmk_core/common/sync_timer.c2
-rw-r--r--tmk_core/common/sync_timer.h2
-rw-r--r--tmk_core/common/test/rules.mk1
-rw-r--r--tmk_core/native.mk2
-rw-r--r--tmk_core/protocol.mk34
-rw-r--r--tmk_core/protocol/adb.c535
-rw-r--r--tmk_core/protocol/adb.h106
-rw-r--r--tmk_core/protocol/arm_atsam.mk7
-rw-r--r--tmk_core/protocol/arm_atsam/arm_atsam_protocol.h4
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.c19
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.h9
-rw-r--r--tmk_core/protocol/arm_atsam/main_arm_atsam.c4
-rw-r--r--tmk_core/protocol/arm_atsam/shift_register.c118
-rw-r--r--tmk_core/protocol/arm_atsam/shift_register.h (renamed from tmk_core/protocol/arm_atsam/spi.h)25
-rw-r--r--tmk_core/protocol/arm_atsam/spi.c92
-rw-r--r--tmk_core/protocol/arm_atsam/spi_master.c109
-rw-r--r--tmk_core/protocol/arm_atsam/spi_master.h48
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb2422.h402
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_hub.c (renamed from tmk_core/protocol/arm_atsam/usb/usb2422.c)98
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_hub.h51
-rw-r--r--tmk_core/protocol/chibios/chibios.c38
-rw-r--r--tmk_core/protocol/chibios/usb_main.c15
-rw-r--r--tmk_core/protocol/ibm4704.c185
-rw-r--r--tmk_core/protocol/ibm4704.h103
-rw-r--r--tmk_core/protocol/lufa.mk27
-rw-r--r--tmk_core/protocol/lufa/adafruit_ble.cpp701
-rw-r--r--tmk_core/protocol/lufa/adafruit_ble.h59
-rw-r--r--tmk_core/protocol/lufa/lufa.c48
-rw-r--r--tmk_core/protocol/lufa/lufa.h11
-rw-r--r--tmk_core/protocol/lufa/outputselect.c79
-rw-r--r--tmk_core/protocol/lufa/outputselect.h34
-rw-r--r--tmk_core/protocol/lufa/ringbuffer.hpp66
-rw-r--r--tmk_core/protocol/m0110.c583
-rw-r--r--tmk_core/protocol/m0110.h81
-rw-r--r--tmk_core/protocol/midi/qmk_midi.c41
-rw-r--r--tmk_core/protocol/news.c161
-rw-r--r--tmk_core/protocol/news.h48
-rw-r--r--tmk_core/protocol/next_kbd.c219
-rw-r--r--tmk_core/protocol/next_kbd.h60
-rw-r--r--tmk_core/protocol/ps2.h139
-rw-r--r--tmk_core/protocol/ps2_busywait.c187
-rw-r--r--tmk_core/protocol/ps2_interrupt.c340
-rw-r--r--tmk_core/protocol/ps2_io.h11
-rw-r--r--tmk_core/protocol/ps2_io_avr.c58
-rw-r--r--tmk_core/protocol/ps2_io_chibios.c55
-rw-r--r--tmk_core/protocol/ps2_mouse.c274
-rw-r--r--tmk_core/protocol/ps2_mouse.h177
-rw-r--r--tmk_core/protocol/ps2_usart.c213
-rw-r--r--tmk_core/protocol/usb_descriptor.c19
-rw-r--r--tmk_core/protocol/usb_hid/parser.h5
-rw-r--r--tmk_core/protocol/usb_hid/usb_hid.h6
-rw-r--r--tmk_core/protocol/vusb/vusb.c36
-rw-r--r--tmk_core/protocol/xt.h73
-rw-r--r--tmk_core/protocol/xt_interrupt.c166
-rw-r--r--tmk_core/readme.md11
-rw-r--r--tmk_core/rules.mk7
77 files changed, 1097 insertions, 5895 deletions
diff --git a/tmk_core/arm_atsam.mk b/tmk_core/arm_atsam.mk
index b29de9132..b49bf764d 100644
--- a/tmk_core/arm_atsam.mk
+++ b/tmk_core/arm_atsam.mk
@@ -2,7 +2,7 @@
2############################################################################## 2##############################################################################
3# Compiler settings 3# Compiler settings
4# 4#
5CC = arm-none-eabi-gcc 5CC = $(CC_PREFIX) arm-none-eabi-gcc
6OBJCOPY = arm-none-eabi-objcopy 6OBJCOPY = arm-none-eabi-objcopy
7OBJDUMP = arm-none-eabi-objdump 7OBJDUMP = arm-none-eabi-objdump
8SIZE = arm-none-eabi-size 8SIZE = arm-none-eabi-size
diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk
index 940e95397..c52262273 100644
--- a/tmk_core/avr.mk
+++ b/tmk_core/avr.mk
@@ -2,7 +2,7 @@
2############################################################################## 2##############################################################################
3# Compiler settings 3# Compiler settings
4# 4#
5CC = avr-gcc 5CC = $(CC_PREFIX) avr-gcc
6OBJCOPY = avr-objcopy 6OBJCOPY = avr-objcopy
7OBJDUMP = avr-objdump 7OBJDUMP = avr-objdump
8SIZE = avr-size 8SIZE = avr-size
diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk
index 18839710b..957a25922 100644
--- a/tmk_core/chibios.mk
+++ b/tmk_core/chibios.mk
@@ -27,29 +27,62 @@ endif
27OPT_OS = chibios 27OPT_OS = chibios
28CHIBIOS = $(TOP_DIR)/lib/chibios 28CHIBIOS = $(TOP_DIR)/lib/chibios
29CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib 29CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib
30# Startup files. Try a few different locations, for compability with old versions and 30
31# for things hardware in the contrib repository 31#
32STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk 32# Startup, Port and Platform support selection
33ifeq ("$(wildcard $(STARTUP_MK))","") 33##############################################################################
34 STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk 34
35 ifeq ("$(wildcard $(STARTUP_MK))","") 35ifeq ($(strip $(MCU)), risc-v)
36 STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk 36 # RISC-V Support
37 endif 37 # As of 7.4.2021 there is only one supported RISC-V platform in Chibios-Contrib,
38 # therefore all required settings are hard-coded
39 STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
40 PORT_V = $(CHIBIOS_CONTRIB)/os/common/ports/RISCV-ECLIC/compilers/GCC/mk/port.mk
41 RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC
42 PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/GD/GD32VF103/platform.mk
43else
44 # ARM Support
45 # Startup files. Try a few different locations, for compability with old versions and
46 # for things hardware in the contrib repository
47 STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
48 ifeq ("$(wildcard $(STARTUP_MK))","")
49 STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
50 ifeq ("$(wildcard $(STARTUP_MK))","")
51 STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
52 endif
53 endif
54
55 # Compability with old version
56 PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
57 ifeq ("$(wildcard $(PORT_V))","")
58 PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
59 endif
60
61 RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
62 ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
63 RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
64 endif
38endif 65endif
39include $(STARTUP_MK)
40# HAL-OSAL files (optional).
41include $(CHIBIOS)/os/hal/hal.mk
42 66
43ifeq ("$(PLATFORM_NAME)","") 67ifeq ("$(PLATFORM_NAME)","")
44 PLATFORM_NAME = platform 68 PLATFORM_NAME = platform
45endif 69endif
46 70
47PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
48ifeq ("$(wildcard $(PLATFORM_MK))","") 71ifeq ("$(wildcard $(PLATFORM_MK))","")
49PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk 72 PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
73 ifeq ("$(wildcard $(PLATFORM_MK))","")
74 PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
75 endif
50endif 76endif
77
78include $(STARTUP_MK)
79include $(PORT_V)
51include $(PLATFORM_MK) 80include $(PLATFORM_MK)
52 81
82#
83# Board support selection.
84##############################################################################
85
53BOARD_MK := 86BOARD_MK :=
54 87
55ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/board.mk)","") 88ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/board.mk)","")
@@ -77,13 +110,19 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/board/board
77endif 110endif
78 111
79ifeq ("$(wildcard $(BOARD_MK))","") 112ifeq ("$(wildcard $(BOARD_MK))","")
80 BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk 113 BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
81 ifeq ("$(wildcard $(BOARD_MK))","") 114 ifeq ("$(wildcard $(BOARD_MK))","")
82 BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk 115 BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
83 endif 116 endif
84endif 117endif
85 118
86# Bootloader address 119include $(BOARD_MK)
120
121#
122# Bootloader selection.
123##############################################################################
124
125# Set bootloader address if supplied.
87ifdef STM32_BOOTLOADER_ADDRESS 126ifdef STM32_BOOTLOADER_ADDRESS
88 OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS) 127 OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
89endif 128endif
@@ -113,6 +152,10 @@ else ifneq ("$(wildcard $(BOARD_PATH)/configs/bootloader_defs.h)","")
113 OPT_DEFS += -include $(BOARD_PATH)/configs/bootloader_defs.h 152 OPT_DEFS += -include $(BOARD_PATH)/configs/bootloader_defs.h
114endif 153endif
115 154
155#
156# ChibiOS config selection.
157##############################################################################
158
116# Work out the config file directories 159# Work out the config file directories
117ifneq ("$(wildcard $(KEYBOARD_PATH_5)/chconf.h)","") 160ifneq ("$(wildcard $(KEYBOARD_PATH_5)/chconf.h)","")
118 CHCONFDIR = $(KEYBOARD_PATH_5) 161 CHCONFDIR = $(KEYBOARD_PATH_5)
@@ -130,6 +173,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/boards/chibios/common/configs/chcon
130 CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs 173 CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs
131endif 174endif
132 175
176#
177# HAL config selection.
178##############################################################################
179
133ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","") 180ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","")
134 HALCONFDIR = $(KEYBOARD_PATH_5) 181 HALCONFDIR = $(KEYBOARD_PATH_5)
135else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/halconf.h)","") 182else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/halconf.h)","")
@@ -146,40 +193,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/common/configs/halco
146 HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs 193 HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs
147endif 194endif
148 195
149# HAL-OSAL files (optional). 196#
150include $(CHIBIOS)/os/hal/hal.mk 197# Linker script selection.
151 198##############################################################################
152ifeq ("$(PLATFORM_NAME)","")
153 PLATFORM_NAME = platform
154endif
155
156PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
157ifeq ("$(wildcard $(PLATFORM_MK))","")
158PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
159endif
160include $(PLATFORM_MK)
161
162
163include $(BOARD_MK)
164-include $(CHIBIOS)/os/hal/osal/rt/osal.mk # ChibiOS <= 19.x
165-include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk # ChibiOS >= 20.x
166# RTOS files (optional).
167include $(CHIBIOS)/os/rt/rt.mk
168# Compability with old version
169PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
170ifeq ("$(wildcard $(PORT_V))","")
171PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
172endif
173include $(PORT_V)
174# Other files (optional).
175include $(CHIBIOS)/os/hal/lib/streams/streams.mk
176
177RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
178ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
179RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
180endif
181 199
182# Define linker script file here
183ifneq ("$(wildcard $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld)","") 200ifneq ("$(wildcard $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld)","")
184 LDSCRIPT = $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld 201 LDSCRIPT = $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld
185else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/ld/$(MCU_LDSCRIPT).ld)","") 202else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/ld/$(MCU_LDSCRIPT).ld)","")
@@ -202,22 +219,36 @@ else
202 LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld 219 LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld
203endif 220endif
204 221
205CHIBISRC = $(STARTUPSRC) \ 222#
206 $(KERNSRC) \ 223# Include ChibiOS makefiles.
207 $(PORTSRC) \ 224##############################################################################
208 $(OSALSRC) \ 225
209 $(HALSRC) \ 226# HAL-OSAL files (optional).
210 $(PLATFORMSRC) \ 227include $(CHIBIOS)/os/hal/hal.mk
211 $(BOARDSRC) \ 228-include $(CHIBIOS)/os/hal/osal/rt/osal.mk # ChibiOS <= 19.x
212 $(STREAMSSRC) \ 229-include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk # ChibiOS >= 20.x
213 $(CHIBIOS)/os/various/syscalls.c \ 230# RTOS files (optional).
214 $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \ 231include $(CHIBIOS)/os/rt/rt.mk
215 $(PLATFORM_COMMON_DIR)/wait.c 232# Other files (optional).
233include $(CHIBIOS)/os/hal/lib/streams/streams.mk
234
235PLATFORM_SRC = \
236 $(STARTUPSRC) \
237 $(KERNSRC) \
238 $(PORTSRC) \
239 $(OSALSRC) \
240 $(HALSRC) \
241 $(PLATFORMSRC) \
242 $(BOARDSRC) \
243 $(STREAMSSRC) \
244 $(CHIBIOS)/os/various/syscalls.c \
245 $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
246 $(PLATFORM_COMMON_DIR)/wait.c
216 247
217# Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise. 248# Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise.
218QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) 249QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM)
219 250
220CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC)) 251PLATFORM_SRC := $(patsubst $(TOP_DIR)/%,%,$(PLATFORM_SRC))
221 252
222EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \ 253EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \
223 $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs \ 254 $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs \
@@ -247,9 +278,9 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/hal
247endif 278endif
248 279
249ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes) 280ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes)
250 include $(CHIBIOS_CONTRIB)/os/hal/hal.mk 281 include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
251 CHIBISRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB) 282 PLATFORM_SRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB)
252 EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various 283 EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various
253endif 284endif
254 285
255# 286#
@@ -267,61 +298,120 @@ ifneq ("$(wildcard $(BOARD_PATH)/configs/post_config.h)","")
267endif 298endif
268 299
269############################################################################## 300##############################################################################
270# Compiler settings 301# Compiler and Linker configuration
271# 302#
272CC = arm-none-eabi-gcc 303
273OBJCOPY = arm-none-eabi-objcopy 304# Use defined stack sizes of the main thread in linker scripts
274OBJDUMP = arm-none-eabi-objdump 305LDSYMBOLS =--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
275SIZE = arm-none-eabi-size 306
276AR = arm-none-eabi-ar 307# Shared Compiler flags for all toolchains
277NM = arm-none-eabi-nm 308SHARED_CFLAGS = -fomit-frame-pointer \
278HEX = $(OBJCOPY) -O $(FORMAT) 309 -ffunction-sections \
279EEP = 310 -fdata-sections \
280BIN = $(OBJCOPY) -O binary 311 -fno-common \
281 312 -fshort-wchar
282THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB 313
283 314# Shared Linker flags for all toolchains
284COMPILEFLAGS += -fomit-frame-pointer 315SHARED_LDFLAGS = -T $(LDSCRIPT) \
285COMPILEFLAGS += -falign-functions=16 316 -Wl,$(LDSYMBOLS) \
286COMPILEFLAGS += -ffunction-sections 317 -Wl,--gc-sections \
287COMPILEFLAGS += -fdata-sections 318 -nostartfiles
288COMPILEFLAGS += -fno-common 319
289COMPILEFLAGS += -fshort-wchar 320ifeq ($(strip $(MCU)), risc-v)
290COMPILEFLAGS += $(THUMBFLAGS) 321 # RISC-V toolchain specific configuration
291 322 # Find suitable GCC compiler
292# FPU options default (Cortex-M4 and Cortex-M7 single precision). 323 ifeq ($(strip $(TOOLCHAIN)),)
293USE_FPU_OPT ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant 324 ifneq ($(shell which riscv32-unknown-elf-gcc 2>/dev/null),)
294 325 TOOLCHAIN = riscv32-unknown-elf-
295# FPU-related options 326 else
296USE_FPU ?= no 327 ifneq ($(shell which riscv64-unknown-elf-gcc 2>/dev/null),)
297ifneq ($(USE_FPU),no) 328 TOOLCHAIN = riscv64-unknown-elf-
298 COMPILEFLAGS += $(USE_FPU_OPT) 329 else
299 OPT_DEFS += -DCORTEX_USE_FPU=TRUE 330 $(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!")
331 endif
332 endif
333 endif
334
335 # Default to compiling with picolibc for RISC-V targets if available,
336 # which is available by default on current (bullseye) debian based systems.
337 ifeq ($(shell $(TOOLCHAIN)gcc --specs=picolibc.specs -E - 2>/dev/null >/dev/null </dev/null ; echo $$?),0)
338 # Toolchain specific Compiler flags
339 # Note that we still link with our own linker script
340 # by providing it via the -T flag above.
341 TOOLCHAIN_CFLAGS = --specs=picolibc.specs
342
343 # Tell QMK that we are compiling with picolibc.
344 OPT_DEFS += -DUSE_PICOLIBC
345 endif
346
347 # MCU architecture flags
348 MCUFLAGS = -march=$(MCU_ARCH) \
349 -mabi=$(MCU_ABI) \
350 -mcmodel=$(MCU_CMODEL) \
351 -mstrict-align
300else 352else
301 OPT_DEFS += -DCORTEX_USE_FPU=FALSE 353 # ARM toolchain specific configuration
354 TOOLCHAIN ?= arm-none-eabi-
355
356 # Toolchain specific Linker flags
357 TOOLCHAIN_LDFLAGS = -Wl,--no-wchar-size-warning \
358 --specs=nano.specs
359
360 # MCU architecture flags
361 MCUFLAGS = -mcpu=$(MCU) \
362 -mthumb -DTHUMB_PRESENT \
363 -mno-thumb-interwork -DTHUMB_NO_INTERWORKING \
364 -mno-unaligned-access
365
366 # Some ARM cores like the M4 and M7 have floating point units which can be enabled
367 USE_FPU ?= no
368
369 ifneq ($(USE_FPU),no)
370 OPT_DEFS += -DCORTEX_USE_FPU=TRUE
371
372 # Default is single precision floats
373 USE_FPU_OPT ?= -mfloat-abi=hard \
374 -mfpu=fpv4-sp-d16 \
375 -fsingle-precision-constant
376
377 MCUFLAGS += $(USE_FPU_OPT)
378 else
379 OPT_DEFS += -DCORTEX_USE_FPU=FALSE
380 endif
302endif 381endif
303 382
304CFLAGS += $(COMPILEFLAGS) 383# Assembler flags
384ASFLAGS += $(SHARED_ASFLAGS) $(TOOLCHAIN_ASFLAGS)
305 385
306ASFLAGS += $(THUMBFLAGS) 386# C Compiler flags
387CFLAGS += $(SHARED_CFLAGS) $(TOOLCHAIN_CFLAGS)
307 388
308CXXFLAGS += $(COMPILEFLAGS) 389# C++ Compiler flags
309CXXFLAGS += -fno-rtti 390CXXFLAGS += $(CFLAGS) $(SHARED_CXXFLAGS) $(TOOLCHAIN_CXXFLAGS) -fno-rtti
310 391
311LDFLAGS +=-Wl,--gc-sections 392# Linker flags
312LDFLAGS +=-Wl,--no-wchar-size-warning 393LDFLAGS += $(SHARED_LDFLAGS) $(TOOLCHAIN_LDFLAGS) $(MCUFLAGS)
313LDFLAGS += -mno-thumb-interwork -mthumb
314LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
315LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
316LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS)
317LDFLAGS += --specs=nano.specs
318 394
395# Tell QMK that we are hosting it on ChibiOS.
319OPT_DEFS += -DPROTOCOL_CHIBIOS 396OPT_DEFS += -DPROTOCOL_CHIBIOS
320 397
321# Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already 398# Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already
322OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1 399OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1
323 400
324MCUFLAGS = -mcpu=$(MCU) 401# Construct GCC toolchain
402CC = $(CC_PREFIX) $(TOOLCHAIN)gcc
403OBJCOPY = $(TOOLCHAIN)objcopy
404OBJDUMP = $(TOOLCHAIN)objdump
405SIZE = $(TOOLCHAIN)size
406AR = $(TOOLCHAIN)ar
407NM = $(TOOLCHAIN)nm
408HEX = $(OBJCOPY) -O $(FORMAT)
409EEP =
410BIN = $(OBJCOPY) -O binary
411
412##############################################################################
413# Make targets
414#
325 415
326DEBUG = gdb 416DEBUG = gdb
327 417
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
index e44ff2f0a..f0faa2dc3 100644
--- a/tmk_core/common.mk
+++ b/tmk_core/common.mk
@@ -55,8 +55,6 @@ ifeq ($(strip $(NKRO_ENABLE)), yes)
55 $(info NKRO is not currently supported on V-USB, and has been disabled.) 55 $(info NKRO is not currently supported on V-USB, and has been disabled.)
56 else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) 56 else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
57 $(info NKRO is not currently supported with Bluetooth, and has been disabled.) 57 $(info NKRO is not currently supported with Bluetooth, and has been disabled.)
58 else ifneq ($(BLUETOOTH),)
59 $(info NKRO is not currently supported with Bluetooth, and has been disabled.)
60 else 58 else
61 TMK_COMMON_DEFS += -DNKRO_ENABLE 59 TMK_COMMON_DEFS += -DNKRO_ENABLE
62 SHARED_EP_ENABLE = yes 60 SHARED_EP_ENABLE = yes
@@ -77,23 +75,6 @@ ifeq ($(strip $(NO_SUSPEND_POWER_DOWN)), yes)
77 TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN 75 TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN
78endif 76endif
79 77
80ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
81 TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
82 TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
83endif
84
85ifeq ($(strip $(BLUETOOTH)), AdafruitBLE)
86 TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
87 TMK_COMMON_DEFS += -DMODULE_ADAFRUIT_BLE
88 TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
89endif
90
91ifeq ($(strip $(BLUETOOTH)), RN42)
92 TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
93 TMK_COMMON_DEFS += -DMODULE_RN42
94 TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
95endif
96
97ifeq ($(strip $(SWAP_HANDS_ENABLE)), yes) 78ifeq ($(strip $(SWAP_HANDS_ENABLE)), yes)
98 TMK_COMMON_DEFS += -DSWAP_HANDS_ENABLE 79 TMK_COMMON_DEFS += -DSWAP_HANDS_ENABLE
99endif 80endif
diff --git a/tmk_core/common/arm_atsam/eeprom.c b/tmk_core/common/arm_atsam/eeprom.c
index ccd5d15a5..ff1a69262 100644
--- a/tmk_core/common/arm_atsam/eeprom.c
+++ b/tmk_core/common/arm_atsam/eeprom.c
@@ -13,24 +13,110 @@
13 * You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16
17#include "eeprom.h" 16#include "eeprom.h"
17#include "debug.h"
18#include "samd51j18a.h"
19#include "core_cm4.h"
20#include "component/nvmctrl.h"
18 21
19#ifndef EEPROM_SIZE 22#ifndef EEPROM_SIZE
20# include "eeconfig.h" 23# include "eeconfig.h"
21# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO 24# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
22#endif 25#endif
23 26
24__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE]; 27#ifndef MAX
28# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
29#endif
30
31#ifndef BUSY_RETRIES
32# define BUSY_RETRIES 10000
33#endif
34
35// #define DEBUG_EEPROM_OUTPUT
36
37/*
38 * Debug print utils
39 */
40#if defined(DEBUG_EEPROM_OUTPUT)
41# define eeprom_printf(fmt, ...) xprintf(fmt, ##__VA_ARGS__);
42#else /* NO_DEBUG */
43# define eeprom_printf(fmt, ...)
44#endif /* NO_DEBUG */
45
46__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE] = {0};
47volatile uint8_t * SmartEEPROM8 = (uint8_t *)SEEPROM_ADDR;
48
49static inline bool eeprom_is_busy(void) {
50 int timeout = BUSY_RETRIES;
51 while (NVMCTRL->SEESTAT.bit.BUSY && timeout-- > 0)
52 ;
53
54 return NVMCTRL->SEESTAT.bit.BUSY;
55}
56
57static uint32_t get_virtual_eeprom_size(void) {
58 // clang-format off
59 static const uint32_t VIRTUAL_EEPROM_MAP[11][8] = {
60 /* 4 8 16 32 64 128 256 512 */
61 /* 0*/ { 0, 0, 0, 0, 0, 0, 0, 0 },
62 /* 1*/ { 512, 1024, 2048, 4096, 4096, 4096, 4096, 4096 },
63 /* 2*/ { 512, 1024, 2048, 4096, 8192, 8192, 8192, 8192 },
64 /* 3*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 },
65 /* 4*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 },
66 /* 5*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
67 /* 6*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
68 /* 7*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
69 /* 8*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
70 /* 9*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 },
71 /*10*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 },
72 };
73 // clang-format on
74
75 static uint32_t virtual_eeprom_size = UINT32_MAX;
76 if (virtual_eeprom_size == UINT32_MAX) {
77 virtual_eeprom_size = VIRTUAL_EEPROM_MAP[NVMCTRL->SEESTAT.bit.PSZ][NVMCTRL->SEESTAT.bit.SBLK];
78 }
79 // eeprom_printf("get_virtual_eeprom_size:: %d:%d:%d\n", NVMCTRL->SEESTAT.bit.PSZ, NVMCTRL->SEESTAT.bit.SBLK, virtual_eeprom_size);
80 return virtual_eeprom_size;
81}
25 82
26uint8_t eeprom_read_byte(const uint8_t *addr) { 83uint8_t eeprom_read_byte(const uint8_t *addr) {
27 uintptr_t offset = (uintptr_t)addr; 84 uintptr_t offset = (uintptr_t)addr;
28 return buffer[offset]; 85 if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) {
86 eeprom_printf("eeprom_read_byte:: out of bounds\n");
87 return 0x0;
88 }
89
90 if (get_virtual_eeprom_size() == 0) {
91 return buffer[offset];
92 }
93
94 if (eeprom_is_busy()) {
95 eeprom_printf("eeprom_write_byte:: timeout\n");
96 return 0x0;
97 }
98
99 return SmartEEPROM8[offset];
29} 100}
30 101
31void eeprom_write_byte(uint8_t *addr, uint8_t value) { 102void eeprom_write_byte(uint8_t *addr, uint8_t value) {
32 uintptr_t offset = (uintptr_t)addr; 103 uintptr_t offset = (uintptr_t)addr;
33 buffer[offset] = value; 104 if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) {
105 eeprom_printf("eeprom_write_byte:: out of bounds\n");
106 return;
107 }
108
109 if (get_virtual_eeprom_size() == 0) {
110 buffer[offset] = value;
111 return;
112 }
113
114 if (eeprom_is_busy()) {
115 eeprom_printf("eeprom_write_byte:: timeout\n");
116 return;
117 }
118
119 SmartEEPROM8[offset] = value;
34} 120}
35 121
36uint16_t eeprom_read_word(const uint16_t *addr) { 122uint16_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 c2d5a3088..915ed0ef4 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;
64 PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ 64 PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
65 } while (0) 65 } while (0)
66 66
67#define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin))) 67#define writePin(pin, level) \
68 do { \
69 if (level) \
70 PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
71 else \
72 PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
73 } while (0)
68 74
69#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0) 75#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0)
70 76
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
index 690d7f38c..b614746e6 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/tmk_core/common/avr/suspend.c
@@ -16,25 +16,6 @@
16# include "vusb.h" 16# include "vusb.h"
17#endif 17#endif
18 18
19#ifdef BACKLIGHT_ENABLE
20# include "backlight.h"
21#endif
22
23#ifdef AUDIO_ENABLE
24# include "audio.h"
25#endif /* AUDIO_ENABLE */
26
27#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
28# include "rgblight.h"
29#endif
30
31#ifdef LED_MATRIX_ENABLE
32# include "led_matrix.h"
33#endif
34#ifdef RGB_MATRIX_ENABLE
35# include "rgb_matrix.h"
36#endif
37
38/** \brief Suspend idle 19/** \brief Suspend idle
39 * 20 *
40 * FIXME: needs doc 21 * FIXME: needs doc
@@ -50,17 +31,6 @@ void suspend_idle(uint8_t time) {
50 31
51// TODO: This needs some cleanup 32// TODO: This needs some cleanup
52 33
53/** \brief Run keyboard level Power down
54 *
55 * FIXME: needs doc
56 */
57__attribute__((weak)) void suspend_power_down_user(void) {}
58/** \brief Run keyboard level Power down
59 *
60 * FIXME: needs doc
61 */
62__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
63
64#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) 34#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
65 35
66// clang-format off 36// clang-format off
@@ -135,41 +105,9 @@ void suspend_power_down(void) {
135 if (!vusb_suspended) return; 105 if (!vusb_suspended) return;
136#endif 106#endif
137 107
138 suspend_power_down_kb(); 108 suspend_power_down_quantum();
139 109
140#ifndef NO_SUSPEND_POWER_DOWN 110#ifndef NO_SUSPEND_POWER_DOWN
141 // Turn off backlight
142# ifdef BACKLIGHT_ENABLE
143 backlight_set(0);
144# endif
145
146 // Turn off LED indicators
147 uint8_t leds_off = 0;
148# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
149 if (is_backlight_enabled()) {
150 // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
151 leds_off |= (1 << USB_LED_CAPS_LOCK);
152 }
153# endif
154 led_set(leds_off);
155
156 // Turn off audio
157# ifdef AUDIO_ENABLE
158 stop_all_notes();
159# endif
160
161 // Turn off underglow
162# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
163 rgblight_suspend();
164# endif
165
166# if defined(LED_MATRIX_ENABLE)
167 led_matrix_set_suspend_state(true);
168# endif
169# if defined(RGB_MATRIX_ENABLE)
170 rgb_matrix_set_suspend_state(true);
171# endif
172
173 // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt) 111 // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt)
174# if defined(WDT_vect) 112# if defined(WDT_vect)
175 power_down(WDTO_15MS); 113 power_down(WDTO_15MS);
@@ -189,18 +127,6 @@ bool suspend_wakeup_condition(void) {
189 return false; 127 return false;
190} 128}
191 129
192/** \brief run user level code immediately after wakeup
193 *
194 * FIXME: needs doc
195 */
196__attribute__((weak)) void suspend_wakeup_init_user(void) {}
197
198/** \brief run keyboard level code immediately after wakeup
199 *
200 * FIXME: needs doc
201 */
202__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
203
204/** \brief run immediately after wakeup 130/** \brief run immediately after wakeup
205 * 131 *
206 * FIXME: needs doc 132 * FIXME: needs doc
@@ -209,27 +135,7 @@ void suspend_wakeup_init(void) {
209 // clear keyboard state 135 // clear keyboard state
210 clear_keyboard(); 136 clear_keyboard();
211 137
212 // Turn on backlight 138 suspend_wakeup_init_quantum();
213#ifdef BACKLIGHT_ENABLE
214 backlight_init();
215#endif
216
217 // Restore LED indicators
218 led_set(host_keyboard_leds());
219
220 // Wake up underglow
221#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
222 rgblight_wakeup();
223#endif
224
225#if defined(LED_MATRIX_ENABLE)
226 led_matrix_set_suspend_state(false);
227#endif
228#if defined(RGB_MATRIX_ENABLE)
229 rgb_matrix_set_suspend_state(false);
230#endif
231
232 suspend_wakeup_init_kb();
233} 139}
234 140
235#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) 141#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 b740afbd2..2f36c64a2 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);
43 43
44#include "_wait.c" 44#include "_wait.c"
45 45
46#define CPU_CLOCK STM32_SYSCLK
47
48/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus 46/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus
49 * to which the GPIO is connected. 47 * to which the GPIO is connected.
50 * The connected buses differ depending on the various series of MCUs. 48 * 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 f9514ee5f..5cadadeee 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) {
95 } 95 }
96} 96}
97 97
98#elif defined(GD32VF103)
99
100# define DBGMCU_KEY_UNLOCK 0x4B5A6978
101# define DBGMCU_CMD_RESET 0x1
102
103__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
104__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;
105
106__attribute__((weak)) void bootloader_jump(void) {
107 /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
108 * register to generate a software reset request.
109 * BUT instead two undocumented registers in the debug peripheral
110 * that allow issueing a software reset. WHO would need the MSFRST
111 * register anyway? Source:
112 * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
113 *DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
114 *DBGMCU_CMD = DBGMCU_CMD_RESET;
115}
116
117void enter_bootloader_mode_if_requested(void) { /* Jumping to bootloader is not possible from user code. */
118}
119
98#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS 120#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS
99/* Kinetis */ 121/* Kinetis */
100 122
diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h
index 23c65f942..ad2f808a9 100644
--- a/tmk_core/common/chibios/chibios_config.h
+++ b/tmk_core/common/chibios/chibios_config.h
@@ -19,22 +19,60 @@
19# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used 19# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
20#endif 20#endif
21 21
22#if defined(STM32F1XX) 22// STM32 compatibility
23# define USE_GPIOV1 23#if defined(MCU_STM32)
24# define CPU_CLOCK STM32_SYSCLK
25
26# if defined(STM32F1XX)
27# define USE_GPIOV1
28# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_STM32_ALTERNATE_OPENDRAIN
29# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_STM32_ALTERNATE_PUSHPULL
30# else
31# define PAL_OUTPUT_TYPE_OPENDRAIN PAL_STM32_OTYPE_OPENDRAIN
32# define PAL_OUTPUT_TYPE_PUSHPULL PAL_STM32_OTYPE_PUSHPULL
33# define PAL_OUTPUT_SPEED_HIGHEST PAL_STM32_OSPEED_HIGHEST
34# define PAL_PUPDR_FLOATING PAL_STM32_PUPDR_FLOATING
35# endif
36
37# if defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32L1XX)
38# define USE_I2CV1
39# endif
40#endif
41
42// GD32 compatibility
43#if defined(MCU_GD32V)
44# define CPU_CLOCK GD32_SYSCLK
45
46# if defined(GD32VF103)
47# define USE_GPIOV1
48# define USE_I2CV1
49# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN
50# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL
51# endif
24#endif 52#endif
25 53
26#if defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32L1XX) 54#if defined(GD32VF103)
27# define USE_I2CV1 55/* This chip has the same API as STM32F103, but uses different names for literally the same thing.
56 * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
57 * we just redefine the GD32 names. */
58# include "gd32v_compatibility.h"
28#endif 59#endif
29 60
30// teensy 61// teensy compatibility
31#if defined(K20x) || defined(KL2x) 62#if defined(MCU_KINETIS)
32# define USE_I2CV1 63# define CPU_CLOCK KINETIS_SYSCLK_FREQUENCY
33# define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed 64
34# define USE_GPIOV1 65# if defined(K20x) || defined(KL2x)
35# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY 66# define USE_I2CV1
67# define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed
68# define USE_GPIOV1
69# endif
36#endif 70#endif
37 71
38#if defined(MK66F18) 72#if defined(HT32)
39# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY 73# define CPU_CLOCK HT32_CK_SYS_FREQUENCY
74# define PAL_MODE_ALTERNATE PAL_HT32_MODE_AF
75# define PAL_OUTPUT_TYPE_OPENDRAIN (PAL_HT32_MODE_OD | PAL_HT32_MODE_DIR)
76# define PAL_OUTPUT_TYPE_PUSHPULL PAL_HT32_MODE_DIR
77# define PAL_OUTPUT_SPEED_HIGHEST 0
40#endif 78#endif
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c
index 1fdf8c1e2..acc6a4851 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) {
620} 620}
621 621
622/***************************************************************************** 622/*****************************************************************************
623 * Wrap library in AVR style functions. 623 * Bind to eeprom_driver.c
624 *******************************************************************************/ 624 *******************************************************************************/
625uint8_t eeprom_read_byte(const uint8_t *Address) { return EEPROM_ReadDataByte((const uintptr_t)Address); } 625void eeprom_driver_init(void) { EEPROM_Init(); }
626 626
627void eeprom_write_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } 627void eeprom_driver_erase(void) { EEPROM_Erase(); }
628
629void eeprom_update_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); }
630
631uint16_t eeprom_read_word(const uint16_t *Address) { return EEPROM_ReadDataWord((const uintptr_t)Address); }
632
633void eeprom_write_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); }
634
635void eeprom_update_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); }
636
637uint32_t eeprom_read_dword(const uint32_t *Address) {
638 const uint16_t p = (const uintptr_t)Address;
639 /* Check word alignment */
640 if (p % 2) {
641 /* Not aligned */
642 return (uint32_t)EEPROM_ReadDataByte(p) | (uint32_t)(EEPROM_ReadDataWord(p + 1) << 8) | (uint32_t)(EEPROM_ReadDataByte(p + 3) << 24);
643 } else {
644 /* Aligned */
645 return EEPROM_ReadDataWord(p) | (EEPROM_ReadDataWord(p + 2) << 16);
646 }
647}
648
649void eeprom_write_dword(uint32_t *Address, uint32_t Value) {
650 uint16_t p = (const uintptr_t)Address;
651 /* Check word alignment */
652 if (p % 2) {
653 /* Not aligned */
654 EEPROM_WriteDataByte(p, (uint8_t)Value);
655 EEPROM_WriteDataWord(p + 1, (uint16_t)(Value >> 8));
656 EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24));
657 } else {
658 /* Aligned */
659 EEPROM_WriteDataWord(p, (uint16_t)Value);
660 EEPROM_WriteDataWord(p + 2, (uint16_t)(Value >> 16));
661 }
662}
663
664void eeprom_update_dword(uint32_t *Address, uint32_t Value) { eeprom_write_dword(Address, Value); }
665 628
666void eeprom_read_block(void *buf, const void *addr, size_t len) { 629void eeprom_read_block(void *buf, const void *addr, size_t len) {
667 const uint8_t *src = (const uint8_t *)addr; 630 const uint8_t *src = (const uint8_t *)addr;
@@ -670,14 +633,14 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
670 /* Check word alignment */ 633 /* Check word alignment */
671 if (len && (uintptr_t)src % 2) { 634 if (len && (uintptr_t)src % 2) {
672 /* Read the unaligned first byte */ 635 /* Read the unaligned first byte */
673 *dest++ = eeprom_read_byte(src++); 636 *dest++ = EEPROM_ReadDataByte((const uintptr_t)src++);
674 --len; 637 --len;
675 } 638 }
676 639
677 uint16_t value; 640 uint16_t value;
678 bool aligned = ((uintptr_t)dest % 2 == 0); 641 bool aligned = ((uintptr_t)dest % 2 == 0);
679 while (len > 1) { 642 while (len > 1) {
680 value = eeprom_read_word((uint16_t *)src); 643 value = EEPROM_ReadDataWord((const uintptr_t)((uint16_t *)src));
681 if (aligned) { 644 if (aligned) {
682 *(uint16_t *)dest = value; 645 *(uint16_t *)dest = value;
683 dest += 2; 646 dest += 2;
@@ -689,7 +652,7 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
689 len -= 2; 652 len -= 2;
690 } 653 }
691 if (len) { 654 if (len) {
692 *dest = eeprom_read_byte(src); 655 *dest = EEPROM_ReadDataByte((const uintptr_t)src);
693 } 656 }
694} 657}
695 658
@@ -700,7 +663,7 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
700 /* Check word alignment */ 663 /* Check word alignment */
701 if (len && (uintptr_t)dest % 2) { 664 if (len && (uintptr_t)dest % 2) {
702 /* Write the unaligned first byte */ 665 /* Write the unaligned first byte */
703 eeprom_write_byte(dest++, *src++); 666 EEPROM_WriteDataByte((uintptr_t)dest++, *src++);
704 --len; 667 --len;
705 } 668 }
706 669
@@ -712,15 +675,13 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
712 } else { 675 } else {
713 value = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8); 676 value = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8);
714 } 677 }
715 eeprom_write_word((uint16_t *)dest, value); 678 EEPROM_WriteDataWord((uintptr_t)((uint16_t *)dest), value);
716 dest += 2; 679 dest += 2;
717 src += 2; 680 src += 2;
718 len -= 2; 681 len -= 2;
719 } 682 }
720 683
721 if (len) { 684 if (len) {
722 eeprom_write_byte(dest, *src); 685 EEPROM_WriteDataByte((uintptr_t)dest, *src);
723 } 686 }
724} 687}
725
726void 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 22b4ab858..66904f247 100644
--- a/tmk_core/common/chibios/eeprom_stm32_defs.h
+++ b/tmk_core/common/chibios/eeprom_stm32_defs.h
@@ -18,7 +18,7 @@
18#include <hal.h> 18#include <hal.h>
19 19
20#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) 20#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT)
21# if defined(STM32F103xB) || defined(STM32F042x6) 21# if defined(STM32F103xB) || defined(STM32F042x6) || defined(GD32VF103C8) || defined(GD32VF103CB)
22# ifndef FEE_PAGE_SIZE 22# ifndef FEE_PAGE_SIZE
23# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte 23# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte
24# endif 24# endif
@@ -32,25 +32,38 @@
32# ifndef FEE_PAGE_COUNT 32# ifndef FEE_PAGE_COUNT
33# define FEE_PAGE_COUNT 4 // How many pages are used 33# define FEE_PAGE_COUNT 4 // How many pages are used
34# endif 34# endif
35# elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE)
36# ifndef FEE_PAGE_SIZE
37# define FEE_PAGE_SIZE 0x4000 // Page size = 16KByte
38# endif
39# ifndef FEE_PAGE_COUNT
40# define FEE_PAGE_COUNT 1 // How many pages are used
41# endif
35# endif 42# endif
36#endif 43#endif
37 44
38#if !defined(FEE_MCU_FLASH_SIZE) 45#if !defined(FEE_MCU_FLASH_SIZE)
39# if defined(STM32F042x6) 46# if defined(STM32F042x6)
40# define FEE_MCU_FLASH_SIZE 32 // Size in Kb 47# define FEE_MCU_FLASH_SIZE 32 // Size in Kb
41# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) 48# elif defined(GD32VF103C8)
49# define FEE_MCU_FLASH_SIZE 64 // Size in Kb
50# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(GD32VF103CB)
42# define FEE_MCU_FLASH_SIZE 128 // Size in Kb 51# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
43# elif defined(STM32F303xC) 52# elif defined(STM32F303xC) || defined(STM32F401xC)
44# define FEE_MCU_FLASH_SIZE 256 // Size in Kb 53# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
45# elif defined(STM32F103xE) 54# elif defined(STM32F103xE) || defined(STM32F401xE) || defined(STM32F411xE)
46# define FEE_MCU_FLASH_SIZE 512 // Size in Kb 55# define FEE_MCU_FLASH_SIZE 512 // Size in Kb
56# elif defined(STM32F405xG)
57# define FEE_MCU_FLASH_SIZE 1024 // Size in Kb
47# endif 58# endif
48#endif 59#endif
49 60
50/* Start of the emulated eeprom */ 61/* Start of the emulated eeprom */
51#if !defined(FEE_PAGE_BASE_ADDRESS) 62#if !defined(FEE_PAGE_BASE_ADDRESS)
52# if 0 63# if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE)
53/* TODO: Add support for F4 */ 64# ifndef FEE_PAGE_BASE_ADDRESS
65# define FEE_PAGE_BASE_ADDRESS 0x08004000 // bodge to force 2nd 16k page
66# endif
54# else 67# else
55# ifndef FEE_FLASH_BASE 68# ifndef FEE_FLASH_BASE
56# define FEE_FLASH_BASE 0x8000000 69# define FEE_FLASH_BASE 0x8000000
diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c
index 6b80ff71c..72c41b8b7 100644
--- a/tmk_core/common/chibios/flash_stm32.c
+++ b/tmk_core/common/chibios/flash_stm32.c
@@ -19,10 +19,38 @@
19#include <hal.h> 19#include <hal.h>
20#include "flash_stm32.h" 20#include "flash_stm32.h"
21 21
22#if defined(EEPROM_EMU_STM32F103xB) 22#if defined(STM32F1XX)
23# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR 23# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
24#endif 24#endif
25 25
26#if defined(MCU_GD32V)
27/* GigaDevice GD32VF103 is a STM32F103 clone at heart. */
28# include "gd32v_compatibility.h"
29#endif
30
31#if defined(STM32F4XX)
32# define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR)
33
34# define FLASH_KEY1 0x45670123U
35# define FLASH_KEY2 0xCDEF89ABU
36
37static uint8_t ADDR2PAGE(uint32_t Page_Address) {
38 switch (Page_Address) {
39 case 0x08000000 ... 0x08003FFF:
40 return 0;
41 case 0x08004000 ... 0x08007FFF:
42 return 1;
43 case 0x08008000 ... 0x0800BFFF:
44 return 2;
45 case 0x0800C000 ... 0x0800FFFF:
46 return 3;
47 }
48
49 // TODO: bad times...
50 return 7;
51}
52#endif
53
26/* Delay definition */ 54/* Delay definition */
27#define EraseTimeout ((uint32_t)0x00000FFF) 55#define EraseTimeout ((uint32_t)0x00000FFF)
28#define ProgramTimeout ((uint32_t)0x0000001F) 56#define ProgramTimeout ((uint32_t)0x0000001F)
@@ -53,7 +81,9 @@ FLASH_Status FLASH_GetStatus(void) {
53 81
54 if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP; 82 if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
55 83
84#if defined(FLASH_OBR_OPTERR)
56 if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT; 85 if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
86#endif
57 87
58 return FLASH_COMPLETE; 88 return FLASH_COMPLETE;
59} 89}
@@ -95,15 +125,24 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
95 125
96 if (status == FLASH_COMPLETE) { 126 if (status == FLASH_COMPLETE) {
97 /* if the previous operation is completed, proceed to erase the page */ 127 /* if the previous operation is completed, proceed to erase the page */
128#if defined(FLASH_CR_SNB)
129 FLASH->CR &= ~FLASH_CR_SNB;
130 FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos);
131#else
98 FLASH->CR |= FLASH_CR_PER; 132 FLASH->CR |= FLASH_CR_PER;
99 FLASH->AR = Page_Address; 133 FLASH->AR = Page_Address;
134#endif
100 FLASH->CR |= FLASH_CR_STRT; 135 FLASH->CR |= FLASH_CR_STRT;
101 136
102 /* Wait for last operation to be completed */ 137 /* Wait for last operation to be completed */
103 status = FLASH_WaitForLastOperation(EraseTimeout); 138 status = FLASH_WaitForLastOperation(EraseTimeout);
104 if (status != FLASH_TIMEOUT) { 139 if (status != FLASH_TIMEOUT) {
105 /* if the erase operation is completed, disable the PER Bit */ 140 /* if the erase operation is completed, disable the configured Bits */
141#if defined(FLASH_CR_SNB)
142 FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
143#else
106 FLASH->CR &= ~FLASH_CR_PER; 144 FLASH->CR &= ~FLASH_CR_PER;
145#endif
107 } 146 }
108 FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR); 147 FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
109 } 148 }
@@ -126,6 +165,11 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
126 status = FLASH_WaitForLastOperation(ProgramTimeout); 165 status = FLASH_WaitForLastOperation(ProgramTimeout);
127 if (status == FLASH_COMPLETE) { 166 if (status == FLASH_COMPLETE) {
128 /* if the previous operation is completed, proceed to program the new data */ 167 /* if the previous operation is completed, proceed to program the new data */
168
169#if defined(FLASH_CR_PSIZE)
170 FLASH->CR &= ~FLASH_CR_PSIZE;
171 FLASH->CR |= FLASH_CR_PSIZE_0;
172#endif
129 FLASH->CR |= FLASH_CR_PG; 173 FLASH->CR |= FLASH_CR_PG;
130 *(__IO uint16_t*)Address = Data; 174 *(__IO uint16_t*)Address = Data;
131 /* Wait for last operation to be completed */ 175 /* 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 000000000..f4dcfd8c5
--- /dev/null
+++ b/tmk_core/common/chibios/gd32v_compatibility.h
@@ -0,0 +1,120 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19/* GD32VF103 has the same API as STM32F103, but uses different names for literally the same thing.
20 * As of 23.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
21 * we just redefine the GD32 names. */
22
23/* Close your eyes kids. */
24#define MCU_STM32
25
26/* AFIO redefines */
27#define MAPR PCF0
28#define AFIO_MAPR_USART1_REMAP AFIO_PCF0_USART0_REMAP
29#define AFIO_MAPR_USART2_REMAP AFIO_PCF0_USART1_REMAP
30#define AFIO_MAPR_USART3_REMAP_PARTIALREMAP AFIO_PCF0_USART2_REMAP_PARTIALREMAP
31#define AFIO_MAPR_USART3_REMAP_FULLREMAP AFIO_PCF0_USART2_REMAP_FULLREMAP
32
33/* DMA redefines. */
34#define STM32_DMA_STREAM(stream) GD32_DMA_STREAM(stream)
35#define STM32_DMA_STREAM_ID(peripheral, channel) GD32_DMA_STREAM_ID(peripheral - 1, channel - 1)
36#define STM32_DMA_CR_DIR_M2P GD32_DMA_CTL_DIR_M2P
37#define STM32_DMA_CR_PSIZE_WORD GD32_DMA_CTL_PWIDTH_WORD
38#define STM32_DMA_CR_MSIZE_WORD GD32_DMA_CTL_MWIDTH_WORD
39#define STM32_DMA_CR_MINC GD32_DMA_CTL_MNAGA
40#define STM32_DMA_CR_CIRC GD32_DMA_CTL_CMEN
41#define STM32_DMA_CR_PL GD32_DMA_CTL_PRIO
42#define STM32_DMA_CR_CHSEL GD32_DMA_CTL_CHSEL
43#define cr1 ctl0
44#define cr2 ctl1
45#define cr3 ctl2
46#define dier dmainten
47
48/* ADC redefines */
49#if HAL_USE_ADC
50# define STM32_ADC_USE_ADC1 GD32_ADC_USE_ADC0
51
52# define smpr1 sampt0
53# define smpr2 sampt1
54# define sqr1 rsq0
55# define sqr2 rsq1
56# define sqr3 rsq2
57
58# define ADC_SMPR2_SMP_AN0 ADC_SAMPT1_SMP_SPT0
59# define ADC_SMPR2_SMP_AN1 ADC_SAMPT1_SMP_SPT1
60# define ADC_SMPR2_SMP_AN2 ADC_SAMPT1_SMP_SPT2
61# define ADC_SMPR2_SMP_AN3 ADC_SAMPT1_SMP_SPT3
62# define ADC_SMPR2_SMP_AN4 ADC_SAMPT1_SMP_SPT4
63# define ADC_SMPR2_SMP_AN5 ADC_SAMPT1_SMP_SPT5
64# define ADC_SMPR2_SMP_AN6 ADC_SAMPT1_SMP_SPT6
65# define ADC_SMPR2_SMP_AN7 ADC_SAMPT1_SMP_SPT7
66# define ADC_SMPR2_SMP_AN8 ADC_SAMPT1_SMP_SPT8
67# define ADC_SMPR2_SMP_AN9 ADC_SAMPT1_SMP_SPT9
68
69# define ADC_SMPR1_SMP_AN10 ADC_SAMPT0_SMP_SPT10
70# define ADC_SMPR1_SMP_AN11 ADC_SAMPT0_SMP_SPT11
71# define ADC_SMPR1_SMP_AN12 ADC_SAMPT0_SMP_SPT12
72# define ADC_SMPR1_SMP_AN13 ADC_SAMPT0_SMP_SPT13
73# define ADC_SMPR1_SMP_AN14 ADC_SAMPT0_SMP_SPT14
74# define ADC_SMPR1_SMP_AN15 ADC_SAMPT0_SMP_SPT15
75
76# define ADC_SQR3_SQ1_N ADC_RSQ2_RSQ1_N
77#endif
78
79/* FLASH redefines */
80#if defined(EEPROM_ENABLE)
81# define SR STAT
82# define FLASH_SR_BSY FLASH_STAT_BUSY
83# define FLASH_SR_PGERR FLASH_STAT_PGERR
84# define FLASH_SR_EOP FLASH_STAT_ENDF
85# define FLASH_SR_WRPRTERR FLASH_STAT_WPERR
86# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
87# define FLASH_OBR_OPTERR FLASH_OBSTAT_OBERR
88# define AR ADDR
89# define CR CTL
90# define FLASH_CR_PER FLASH_CTL_PER
91# define FLASH_CR_STRT FLASH_CTL_START
92# define FLASH_CR_LOCK FLASH_CTL_LK
93# define FLASH_CR_PG FLASH_CTL_PG
94# define KEYR KEY
95#endif
96
97/* Serial USART redefines. */
98#if HAL_USE_SERIAL
99# if !defined(SERIAL_USART_CR1)
100# define SERIAL_USART_CR1 (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL) // parity enable, odd parity, 9 bit length
101# endif
102# if !defined(SERIAL_USART_CR2)
103# define SERIAL_USART_CR2 (USART_CTL1_STB_1) // 2 stop bits
104# endif
105# if !defined(SERIAL_USART_CR3)
106# define SERIAL_USART_CR3 0x0
107# endif
108# define USART_CR3_HDSEL USART_CTL2_HDEN
109# define CCR CHCV
110#endif
111
112/* SPI redefines. */
113#if HAL_USE_SPI
114# define SPI_CR1_LSBFIRST SPI_CTL0_LF
115# define SPI_CR1_CPHA SPI_CTL0_CKPH
116# define SPI_CR1_CPOL SPI_CTL0_CKPL
117# define SPI_CR1_BR_0 SPI_CTL0_PSC_0
118# define SPI_CR1_BR_1 SPI_CTL0_PSC_1
119# define SPI_CR1_BR_2 SPI_CTL0_PSC_2
120#endif
diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c
index 38517e06f..9310a9992 100644
--- a/tmk_core/common/chibios/suspend.c
+++ b/tmk_core/common/chibios/suspend.c
@@ -7,30 +7,12 @@
7#include "action.h" 7#include "action.h"
8#include "action_util.h" 8#include "action_util.h"
9#include "mousekey.h" 9#include "mousekey.h"
10#include "programmable_button.h"
10#include "host.h" 11#include "host.h"
11#include "suspend.h" 12#include "suspend.h"
12#include "led.h" 13#include "led.h"
13#include "wait.h" 14#include "wait.h"
14 15
15#ifdef AUDIO_ENABLE
16# include "audio.h"
17#endif /* AUDIO_ENABLE */
18
19#ifdef BACKLIGHT_ENABLE
20# include "backlight.h"
21#endif
22
23#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
24# include "rgblight.h"
25#endif
26
27#ifdef LED_MATRIX_ENABLE
28# include "led_matrix.h"
29#endif
30#ifdef RGB_MATRIX_ENABLE
31# include "rgb_matrix.h"
32#endif
33
34/** \brief suspend idle 16/** \brief suspend idle
35 * 17 *
36 * FIXME: needs doc 18 * FIXME: needs doc
@@ -40,61 +22,12 @@ void suspend_idle(uint8_t time) {
40 wait_ms(time); 22 wait_ms(time);
41} 23}
42 24
43/** \brief Run keyboard level Power down
44 *
45 * FIXME: needs doc
46 */
47__attribute__((weak)) void suspend_power_down_user(void) {}
48/** \brief Run keyboard level Power down
49 *
50 * FIXME: needs doc
51 */
52__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
53
54/** \brief suspend power down 25/** \brief suspend power down
55 * 26 *
56 * FIXME: needs doc 27 * FIXME: needs doc
57 */ 28 */
58void suspend_power_down(void) { 29void suspend_power_down(void) {
59#ifdef BACKLIGHT_ENABLE 30 suspend_power_down_quantum();
60 backlight_set(0);
61#endif
62
63#ifdef LED_MATRIX_ENABLE
64 led_matrix_task();
65#endif
66#ifdef RGB_MATRIX_ENABLE
67 rgb_matrix_task();
68#endif
69
70 // Turn off LED indicators
71 uint8_t leds_off = 0;
72#if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
73 if (is_backlight_enabled()) {
74 // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
75 leds_off |= (1 << USB_LED_CAPS_LOCK);
76 }
77#endif
78 led_set(leds_off);
79
80 // TODO: figure out what to power down and how
81 // shouldn't power down TPM/FTM if we want a breathing LED
82 // also shouldn't power down USB
83#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
84 rgblight_suspend();
85#endif
86
87#if defined(LED_MATRIX_ENABLE)
88 led_matrix_set_suspend_state(true);
89#endif
90#if defined(RGB_MATRIX_ENABLE)
91 rgb_matrix_set_suspend_state(true);
92#endif
93#ifdef AUDIO_ENABLE
94 stop_all_notes();
95#endif /* AUDIO_ENABLE */
96
97 suspend_power_down_kb();
98 // on AVR, this enables the watchdog for 15ms (max), and goes to 31 // on AVR, this enables the watchdog for 15ms (max), and goes to
99 // SLEEP_MODE_PWR_DOWN 32 // SLEEP_MODE_PWR_DOWN
100 33
@@ -147,23 +80,13 @@ void suspend_wakeup_init(void) {
147#ifdef MOUSEKEY_ENABLE 80#ifdef MOUSEKEY_ENABLE
148 mousekey_clear(); 81 mousekey_clear();
149#endif /* MOUSEKEY_ENABLE */ 82#endif /* MOUSEKEY_ENABLE */
83#ifdef PROGRAMMABLE_BUTTON_ENABLE
84 programmable_button_clear();
85#endif /* PROGRAMMABLE_BUTTON_ENABLE */
150#ifdef EXTRAKEY_ENABLE 86#ifdef EXTRAKEY_ENABLE
151 host_system_send(0); 87 host_system_send(0);
152 host_consumer_send(0); 88 host_consumer_send(0);
153#endif /* EXTRAKEY_ENABLE */ 89#endif /* EXTRAKEY_ENABLE */
154#ifdef BACKLIGHT_ENABLE
155 backlight_init();
156#endif /* BACKLIGHT_ENABLE */
157 led_set(host_keyboard_leds());
158#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
159 rgblight_wakeup();
160#endif
161 90
162#if defined(LED_MATRIX_ENABLE) 91 suspend_wakeup_init_quantum();
163 led_matrix_set_suspend_state(false);
164#endif
165#if defined(RGB_MATRIX_ENABLE)
166 rgb_matrix_set_suspend_state(false);
167#endif
168 suspend_wakeup_init_kb();
169} 92}
diff --git a/tmk_core/common/chibios/syscall-fallbacks.c b/tmk_core/common/chibios/syscall-fallbacks.c
index 739017ae1..4569879c7 100644
--- a/tmk_core/common/chibios/syscall-fallbacks.c
+++ b/tmk_core/common/chibios/syscall-fallbacks.c
@@ -18,6 +18,12 @@
18#include <sys/stat.h> 18#include <sys/stat.h>
19#include <sys/types.h> 19#include <sys/types.h>
20 20
21/* To compile the ChibiOS syscall stubs with picolibc
22 * the _reent struct has to be defined. */
23#if defined(USE_PICOLIBC)
24struct _reent;
25#endif
26
21#pragma GCC diagnostic ignored "-Wmissing-prototypes" 27#pragma GCC diagnostic ignored "-Wmissing-prototypes"
22 28
23__attribute__((weak, used)) int _open_r(struct _reent *r, const char *path, int flag, int m) { 29__attribute__((weak, used)) int _open_r(struct _reent *r, const char *path, int flag, int m) {
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
index f0c396b18..56d4bb084 100644
--- a/tmk_core/common/host.c
+++ b/tmk_core/common/host.c
@@ -30,8 +30,9 @@ extern keymap_config_t keymap_config;
30#endif 30#endif
31 31
32static host_driver_t *driver; 32static host_driver_t *driver;
33static uint16_t last_system_report = 0; 33static uint16_t last_system_report = 0;
34static uint16_t last_consumer_report = 0; 34static uint16_t last_consumer_report = 0;
35static uint32_t last_programmable_button_report = 0;
35 36
36void host_set_driver(host_driver_t *d) { driver = d; } 37void host_set_driver(host_driver_t *d) { driver = d; }
37 38
@@ -122,6 +123,16 @@ void host_digitizer_send(digitizer_t *digitizer) {
122 123
123__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} 124__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {}
124 125
126void host_programmable_button_send(uint32_t report) {
127 if (report == last_programmable_button_report) return;
128 last_programmable_button_report = report;
129
130 if (!driver) return;
131 (*driver->send_programmable_button)(report);
132}
133
125uint16_t host_last_system_report(void) { return last_system_report; } 134uint16_t host_last_system_report(void) { return last_system_report; }
126 135
127uint16_t host_last_consumer_report(void) { return last_consumer_report; } 136uint16_t host_last_consumer_report(void) { return last_consumer_report; }
137
138uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; }
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h
index 2cffef6e1..6b15f0d0c 100644
--- a/tmk_core/common/host.h
+++ b/tmk_core/common/host.h
@@ -47,9 +47,11 @@ void host_keyboard_send(report_keyboard_t *report);
47void host_mouse_send(report_mouse_t *report); 47void host_mouse_send(report_mouse_t *report);
48void host_system_send(uint16_t data); 48void host_system_send(uint16_t data);
49void host_consumer_send(uint16_t data); 49void host_consumer_send(uint16_t data);
50void host_programmable_button_send(uint32_t data);
50 51
51uint16_t host_last_system_report(void); 52uint16_t host_last_system_report(void);
52uint16_t host_last_consumer_report(void); 53uint16_t host_last_consumer_report(void);
54uint32_t host_last_programmable_button_report(void);
53 55
54#ifdef __cplusplus 56#ifdef __cplusplus
55} 57}
diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h
index 2aebca043..affd0dcb3 100644
--- a/tmk_core/common/host_driver.h
+++ b/tmk_core/common/host_driver.h
@@ -29,6 +29,7 @@ typedef struct {
29 void (*send_mouse)(report_mouse_t *); 29 void (*send_mouse)(report_mouse_t *);
30 void (*send_system)(uint16_t); 30 void (*send_system)(uint16_t);
31 void (*send_consumer)(uint16_t); 31 void (*send_consumer)(uint16_t);
32 void (*send_programmable_button)(uint32_t);
32} host_driver_t; 33} host_driver_t;
33 34
34void send_digitizer(report_digitizer_t *report); \ No newline at end of file 35void send_digitizer(report_digitizer_t *report); \ No newline at end of file
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index f2223e806..1adc892f3 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -29,6 +29,7 @@ enum hid_report_ids {
29 REPORT_ID_MOUSE, 29 REPORT_ID_MOUSE,
30 REPORT_ID_SYSTEM, 30 REPORT_ID_SYSTEM,
31 REPORT_ID_CONSUMER, 31 REPORT_ID_CONSUMER,
32 REPORT_ID_PROGRAMMABLE_BUTTON,
32 REPORT_ID_NKRO, 33 REPORT_ID_NKRO,
33 REPORT_ID_JOYSTICK, 34 REPORT_ID_JOYSTICK,
34 REPORT_ID_DIGITIZER 35 REPORT_ID_DIGITIZER
@@ -196,6 +197,11 @@ typedef struct {
196} __attribute__((packed)) report_extra_t; 197} __attribute__((packed)) report_extra_t;
197 198
198typedef struct { 199typedef struct {
200 uint8_t report_id;
201 uint32_t usage;
202} __attribute__((packed)) report_programmable_button_t;
203
204typedef struct {
199#ifdef MOUSE_SHARED_EP 205#ifdef MOUSE_SHARED_EP
200 uint8_t report_id; 206 uint8_t report_id;
201#endif 207#endif
diff --git a/tmk_core/common/suspend.h b/tmk_core/common/suspend.h
index 95845e4b6..081735f90 100644
--- a/tmk_core/common/suspend.h
+++ b/tmk_core/common/suspend.h
@@ -10,8 +10,10 @@ void suspend_wakeup_init(void);
10 10
11void suspend_wakeup_init_user(void); 11void suspend_wakeup_init_user(void);
12void suspend_wakeup_init_kb(void); 12void suspend_wakeup_init_kb(void);
13void suspend_wakeup_init_quantum(void);
13void suspend_power_down_user(void); 14void suspend_power_down_user(void);
14void suspend_power_down_kb(void); 15void suspend_power_down_kb(void);
16void suspend_power_down_quantum(void);
15 17
16#ifndef USB_SUSPEND_WAKEUP_DELAY 18#ifndef USB_SUSPEND_WAKEUP_DELAY
17# define USB_SUSPEND_WAKEUP_DELAY 0 19# define USB_SUSPEND_WAKEUP_DELAY 0
diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c
index 68b92d8b4..de24b463b 100644
--- a/tmk_core/common/sync_timer.c
+++ b/tmk_core/common/sync_timer.c
@@ -26,7 +26,7 @@ SOFTWARE.
26#include "sync_timer.h" 26#include "sync_timer.h"
27#include "keyboard.h" 27#include "keyboard.h"
28 28
29#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) 29#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
30volatile int32_t sync_timer_ms; 30volatile int32_t sync_timer_ms;
31 31
32void sync_timer_init(void) { sync_timer_ms = 0; } 32void sync_timer_init(void) { sync_timer_ms = 0; }
diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h
index 744e2b50d..9ddef45bb 100644
--- a/tmk_core/common/sync_timer.h
+++ b/tmk_core/common/sync_timer.h
@@ -32,7 +32,7 @@ SOFTWARE.
32extern "C" { 32extern "C" {
33#endif 33#endif
34 34
35#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) 35#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
36void sync_timer_init(void); 36void sync_timer_init(void);
37void sync_timer_update(uint32_t time); 37void sync_timer_update(uint32_t time);
38uint16_t sync_timer_read(void); 38uint16_t sync_timer_read(void);
diff --git a/tmk_core/common/test/rules.mk b/tmk_core/common/test/rules.mk
index 48632a095..73d2302da 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)
16eeprom_stm32_large_INC := $(eeprom_stm32_INC) 16eeprom_stm32_large_INC := $(eeprom_stm32_INC)
17 17
18eeprom_stm32_SRC := \ 18eeprom_stm32_SRC := \
19 $(TOP_DIR)/drivers/eeprom/eeprom_driver.c \
19 $(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \ 20 $(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \
20 $(TMK_PATH)/common/test/flash_stm32_mock.c \ 21 $(TMK_PATH)/common/test/flash_stm32_mock.c \
21 $(TMK_PATH)/common/chibios/eeprom_stm32.c 22 $(TMK_PATH)/common/chibios/eeprom_stm32.c
diff --git a/tmk_core/native.mk b/tmk_core/native.mk
index f609fd0e6..eb2424ec5 100644
--- a/tmk_core/native.mk
+++ b/tmk_core/native.mk
@@ -1,7 +1,7 @@
1SYSTEM_TYPE := $(shell gcc -dumpmachine) 1SYSTEM_TYPE := $(shell gcc -dumpmachine)
2GCC_VERSION := $(shell gcc --version 2>/dev/null) 2GCC_VERSION := $(shell gcc --version 2>/dev/null)
3 3
4CC = gcc 4CC = $(CC_PREFIX) gcc
5OBJCOPY = 5OBJCOPY =
6OBJDUMP = 6OBJDUMP =
7SIZE = 7SIZE =
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk
index b61f2f546..8aa063c91 100644
--- a/tmk_core/protocol.mk
+++ b/tmk_core/protocol.mk
@@ -1,30 +1,5 @@
1PROTOCOL_DIR = protocol 1PROTOCOL_DIR = protocol
2 2
3ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
4 SRC += $(PROTOCOL_DIR)/ps2_mouse.c
5 OPT_DEFS += -DPS2_MOUSE_ENABLE
6 OPT_DEFS += -DMOUSE_ENABLE
7endif
8
9ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes)
10 SRC += protocol/ps2_busywait.c
11 SRC += protocol/ps2_io_avr.c
12 OPT_DEFS += -DPS2_USE_BUSYWAIT
13endif
14
15ifeq ($(strip $(PS2_USE_INT)), yes)
16 SRC += protocol/ps2_interrupt.c
17 SRC += protocol/ps2_io_$(PLATFORM_KEY).c
18 OPT_DEFS += -DPS2_USE_INT
19endif
20
21ifeq ($(strip $(PS2_USE_USART)), yes)
22 SRC += protocol/ps2_usart.c
23 SRC += protocol/ps2_io_$(PLATFORM_KEY).c
24 OPT_DEFS += -DPS2_USE_USART
25endif
26
27
28ifeq ($(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)), yes) 3ifeq ($(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)), yes)
29 SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c 4 SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c
30 OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \ 5 OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \
@@ -45,15 +20,6 @@ ifeq ($(strip $(SERIAL_MOUSE_USE_UART)), yes)
45 SRC += $(PROTOCOL_DIR)/serial_uart.c 20 SRC += $(PROTOCOL_DIR)/serial_uart.c
46endif 21endif
47 22
48ifeq ($(strip $(ADB_MOUSE_ENABLE)), yes)
49 OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
50endif
51
52ifeq ($(strip $(XT_ENABLE)), yes)
53 SRC += $(PROTOCOL_DIR)/xt_interrupt.c
54 OPT_DEFS += -DXT_ENABLE
55endif
56
57ifeq ($(strip $(USB_HID_ENABLE)), yes) 23ifeq ($(strip $(USB_HID_ENABLE)), yes)
58 include $(TMK_DIR)/protocol/usb_hid.mk 24 include $(TMK_DIR)/protocol/usb_hid.mk
59endif 25endif
diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c
deleted file mode 100644
index 367f1b09f..000000000
--- a/tmk_core/protocol/adb.c
+++ /dev/null
@@ -1,535 +0,0 @@
1/*
2Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
3Copyright 2013 Shay Green <gblargg@gmail.com>
4
5This software is licensed with a Modified BSD License.
6All of this is supposed to be Free Software, Open Source, DFSG-free,
7GPL-compatible, and OK to use in both free and proprietary applications.
8Additions and corrections to this file are welcome.
9
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions are met:
13
14* Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16
17* Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in
19 the documentation and/or other materials provided with the
20 distribution.
21
22* Neither the name of the copyright holders nor the names of
23 contributors may be used to endorse or promote products derived
24 from this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36POSSIBILITY OF SUCH DAMAGE.
37*/
38
39#include <stdbool.h>
40#include <util/delay.h>
41#include <avr/io.h>
42#include <avr/interrupt.h>
43#include "adb.h"
44#include "print.h"
45
46// GCC doesn't inline functions normally
47#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT))
48#define data_hi() (ADB_DDR &= ~(1 << ADB_DATA_BIT))
49#define data_in() (ADB_PIN & (1 << ADB_DATA_BIT))
50
51#ifdef ADB_PSW_BIT
52static inline void psw_lo(void);
53static inline void psw_hi(void);
54static inline bool psw_in(void);
55#endif
56
57static inline void attention(void);
58static inline void place_bit0(void);
59static inline void place_bit1(void);
60static inline void send_byte(uint8_t data);
61static inline uint16_t wait_data_lo(uint16_t us);
62static inline uint16_t wait_data_hi(uint16_t us);
63
64void adb_host_init(void) {
65 ADB_PORT &= ~(1 << ADB_DATA_BIT);
66 data_hi();
67#ifdef ADB_PSW_BIT
68 psw_hi();
69#endif
70}
71
72#ifdef ADB_PSW_BIT
73bool adb_host_psw(void) { return psw_in(); }
74#endif
75
76/*
77 * Don't call this in a row without the delay, otherwise it makes some of poor controllers
78 * overloaded and misses strokes. Recommended interval is 12ms.
79 *
80 * Thanks a lot, blargg!
81 * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
82 * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
83 */
84uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); }
85
86#ifdef ADB_MOUSE_ENABLE
87__attribute__((weak)) void adb_mouse_init(void) { return; }
88
89__attribute__((weak)) void adb_mouse_task(void) { return; }
90
91uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); }
92#endif
93
94// This sends Talk command to read data from register and returns length of the data.
95uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
96 for (int8_t i = 0; i < len; i++) buf[i] = 0;
97
98 cli();
99 attention();
100 send_byte((addr << 4) | ADB_CMD_TALK | reg);
101 place_bit0(); // Stopbit(0)
102 // TODO: Service Request(Srq):
103 // Device holds low part of comannd stopbit for 140-260us
104 //
105 // Command:
106 // ......._ ______________________ ___ ............_ -------
107 // | | | | | | |
108 // Command | | | | | Data bytes | |
109 // ........|___| | 140-260 |__| |_............|___|
110 // |stop0 | Tlt Stop-to-Start |start1| |stop0 |
111 //
112 // Command without data:
113 // ......._ __________________________
114 // | |
115 // Command | |
116 // ........|___| | 140-260 |
117 // |stop0 | Tlt Stop-to-Start |
118 //
119 // Service Request:
120 // ......._ ______ ___ ............_ -------
121 // | 140-260 | | | | | |
122 // Command | Service Request | | | | Data bytes | |
123 // ........|___________________| |__| |_............|___|
124 // |stop0 | |start1| |stop0 |
125 // ......._ __________
126 // | 140-260 |
127 // Command | Service Request |
128 // ........|___________________|
129 // |stop0 |
130 // This can be happened?
131 // ......._ ______________________ ___ ............_ -----
132 // | | | | | | 140-260 |
133 // Command | | | | | Data bytes | Service Request |
134 // ........|___| | 140-260 |__| |_............|_________________|
135 // |stop0 | Tlt Stop-to-Start |start1| |stop0 |
136 //
137 // "Service requests are issued by the devices during a very specific time at the
138 // end of the reception of the command packet.
139 // If a device in need of service issues a service request, it must do so within
140 // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs."
141 //
142 // "A device sends a Service Request signal by holding the bus low during the low
143 // portion of the stop bit of any command or data transaction. The device must lengthen
144 // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
145 // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
146 if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
147 xprintf("R");
148 sei();
149 return 0;
150 }
151 if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
152 sei();
153 return 0; // No data from device(not error);
154 }
155
156 // start bit(1)
157 if (!wait_data_hi(40)) {
158 xprintf("S");
159 sei();
160 return 0;
161 }
162 if (!wait_data_lo(100)) {
163 xprintf("s");
164 sei();
165 return 0;
166 }
167
168 uint8_t n = 0; // bit count
169 do {
170 //
171 // |<- bit_cell_max(130) ->|
172 // | |<- lo ->|
173 // | | |<-hi->|
174 // _______
175 // | | |
176 // | 130-lo | lo-hi |
177 // |________| |
178 //
179 uint8_t lo = (uint8_t)wait_data_hi(130);
180 if (!lo) goto error; // no more bit or after stop bit
181
182 uint8_t hi = (uint8_t)wait_data_lo(lo);
183 if (!hi) goto error; // stop bit extedned by Srq?
184
185 if (n / 8 >= len) continue; // can't store in buf
186
187 buf[n / 8] <<= 1;
188 if ((130 - lo) < (lo - hi)) {
189 buf[n / 8] |= 1;
190 }
191 } while (++n);
192
193error:
194 sei();
195 return n / 8;
196}
197
198uint16_t adb_host_talk(uint8_t addr, uint8_t reg) {
199 uint8_t len;
200 uint8_t buf[8];
201 len = adb_host_talk_buf(addr, reg, buf, 8);
202 if (len != 2) return 0;
203 return (buf[0] << 8 | buf[1]);
204}
205
206void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
207 cli();
208 attention();
209 send_byte((addr << 4) | ADB_CMD_LISTEN | reg);
210 place_bit0(); // Stopbit(0)
211 // TODO: Service Request
212 _delay_us(200); // Tlt/Stop to Start
213 place_bit1(); // Startbit(1)
214 for (int8_t i = 0; i < len; i++) {
215 send_byte(buf[i]);
216 // xprintf("%02X ", buf[i]);
217 }
218 place_bit0(); // Stopbit(0);
219 sei();
220}
221
222void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) {
223 uint8_t buf[2] = {data_h, data_l};
224 adb_host_listen_buf(addr, reg, buf, 2);
225}
226
227void adb_host_flush(uint8_t addr) {
228 cli();
229 attention();
230 send_byte((addr << 4) | ADB_CMD_FLUSH);
231 place_bit0(); // Stopbit(0)
232 _delay_us(200); // Tlt/Stop to Start
233 sei();
234}
235
236// send state of LEDs
237void adb_host_kbd_led(uint8_t led) {
238 // Listen Register2
239 // upper byte: not used
240 // lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
241 adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07);
242}
243
244#ifdef ADB_PSW_BIT
245static inline void psw_lo() {
246 ADB_DDR |= (1 << ADB_PSW_BIT);
247 ADB_PORT &= ~(1 << ADB_PSW_BIT);
248}
249static inline void psw_hi() {
250 ADB_PORT |= (1 << ADB_PSW_BIT);
251 ADB_DDR &= ~(1 << ADB_PSW_BIT);
252}
253static inline bool psw_in() {
254 ADB_PORT |= (1 << ADB_PSW_BIT);
255 ADB_DDR &= ~(1 << ADB_PSW_BIT);
256 return ADB_PIN & (1 << ADB_PSW_BIT);
257}
258#endif
259
260static inline void attention(void) {
261 data_lo();
262 _delay_us(800 - 35); // bit1 holds lo for 35 more
263 place_bit1();
264}
265
266static inline void place_bit0(void) {
267 data_lo();
268 _delay_us(65);
269 data_hi();
270 _delay_us(35);
271}
272
273static inline void place_bit1(void) {
274 data_lo();
275 _delay_us(35);
276 data_hi();
277 _delay_us(65);
278}
279
280static inline void send_byte(uint8_t data) {
281 for (int i = 0; i < 8; i++) {
282 if (data & (0x80 >> i))
283 place_bit1();
284 else
285 place_bit0();
286 }
287}
288
289// These are carefully coded to take 6 cycles of overhead.
290// inline asm approach became too convoluted
291static inline uint16_t wait_data_lo(uint16_t us) {
292 do {
293 if (!data_in()) break;
294 _delay_us(1 - (6 * 1000000.0 / F_CPU));
295 } while (--us);
296 return us;
297}
298
299static inline uint16_t wait_data_hi(uint16_t us) {
300 do {
301 if (data_in()) break;
302 _delay_us(1 - (6 * 1000000.0 / F_CPU));
303 } while (--us);
304 return us;
305}
306
307/*
308ADB Protocol
309============
310
311Resources
312---------
313ADB - The Untold Story: Space Aliens Ate My Mouse
314 http://developer.apple.com/legacy/mac/library/#technotes/hw/hw_01.html
315ADB Manager
316 http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Devices/ADB_Manager.pdf
317 Service request(5-17)
318Apple IIgs Hardware Reference Second Edition [Chapter6 p121]
319 ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf
320ADB Keycode
321 http://72.0.193.250/Documentation/macppc/adbkeycodes/
322 http://m0115.web.fc2.com/m0115.jpg
323 [Inside Macintosh volume V, pages 191-192]
324 http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-421.18.3/IOHIDFamily/Cosmo_USB2ADB.c
325ADB Signaling
326 http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf
327ADB Overview & History
328 http://en.wikipedia.org/wiki/Apple_Desktop_Bus
329Microchip Application Note: ADB device(with code for PIC16C)
330 http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062
331AVR ATtiny2131 ADB to PS/2 converter(Japanese)
332 http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html
333
334
335Pinouts
336-------
337 ADB female socket from the front:
338 __________
339 | | <--- top
340 | 4o o3 |
341 |2o o1|
342 | == |
343 |________| <--- bottom
344 | | <--- 4pins
345
346
347 ADB female socket from bottom:
348
349 ========== <--- front
350 | |
351 | |
352 |2o o1|
353 |4o o3|
354 ---------- <--- back
355
356 1: Data
357 2: Power SW(low when press Power key)
358 3: Vcc(5V)
359 4: GND
360
361
362Commands
363--------
364 ADB command is 1byte and consists of 4bit-address, 2bit-command
365 type and 2bit-register. The commands are always sent by Host.
366
367 Command format:
368 7 6 5 4 3 2 1 0
369 | | | |------------ address
370 | |-------- command type
371 | |---- register
372
373 bits commands
374 ------------------------------------------------------
375 - - - - 0 0 0 0 Send Reset(reset all devices)
376 A A A A 0 0 0 1 Flush(reset a device)
377 - - - - 0 0 1 0 Reserved
378 - - - - 0 0 1 1 Reserved
379 - - - - 0 1 - - Reserved
380 A A A A 1 0 R R Listen(write to a device)
381 A A A A 1 1 R R Talk(read from a device)
382
383 The command to read keycodes from keyboard is 0x2C which
384 consist of keyboard address 2 and Talk against register 0.
385
386 Address:
387 2: keyboard
388 3: mice
389
390 Registers:
391 0: application(keyboard uses this to store its data.)
392 1: application
393 2: application(keyboard uses this for LEDs and state of modifiers)
394 3: status and command
395
396
397Communication
398-------------
399 This is a minimum information for keyboard communication.
400 See "Resources" for detail.
401
402 Signaling:
403
404 ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~
405
406 |800us | |7 Command 0| | | |15-64 Data 0|Stopbit(0)
407 +Attention | | | +Startbit(1)
408 +Startbit(1) | +Tlt(140-260us)
409 +stopbit(0)
410
411 Bit cells:
412
413 bit0: ______~~~
414 65 :35us
415
416 bit1: ___~~~~~~
417 35 :65us
418
419 bit0 low time: 60-70% of bit cell(42-91us)
420 bit1 low time: 30-40% of bit cell(21-52us)
421 bit cell time: 70-130us
422 [from Apple IIgs Hardware Reference Second Edition]
423
424 Criterion for bit0/1:
425 After 55us if line is low/high then bit is 0/1.
426
427 Attention & start bit:
428 Host asserts low in 560-1040us then places start bit(1).
429
430 Tlt(Stop to Start):
431 Bus stays high in 140-260us then device places start bit(1).
432
433 Global reset:
434 Host asserts low in 2.8-5.2ms. All devices are forced to reset.
435
436 Service request from device(Srq):
437 Device can request to send at commad(Global only?) stop bit.
438 Requesting device keeps low for 140-260us at stop bit of command.
439
440
441Keyboard Data(Register0)
442 This 16bit data can contains two keycodes and two released flags.
443 First keycode is palced in upper byte. When one keyocode is sent,
444 lower byte is 0xFF.
445 Release flag is 1 when key is released.
446
447 1514 . . . . . 8 7 6 . . . . . 0
448 | | | | | | | | | +-+-+-+-+-+-+- Keycode2
449 | | | | | | | | +--------------- Released2(1 when the key is released)
450 | +-+-+-+-+-+-+----------------- Keycode1
451 +------------------------------- Released1(1 when the key is released)
452
453 Keycodes:
454 Scancode consists of 7bit keycode and 1bit release flag.
455 Device can send two keycodes at once. If just one keycode is sent
456 keycode1 contains it and keyocode2 is 0xFF.
457
458 Power switch:
459 You can read the state from PSW line(active low) however
460 the switch has a special scancode 0x7F7F, so you can
461 also read from Data line. It uses 0xFFFF for release scancode.
462
463Keyboard LEDs & state of keys(Register2)
464 This register hold current state of three LEDs and nine keys.
465 The state of LEDs can be changed by sending Listen command.
466
467 1514 . . . . . . 7 6 5 . 3 2 1 0
468 | | | | | | | | | | | | | | | +- LED1(NumLock)
469 | | | | | | | | | | | | | | +--- LED2(CapsLock)
470 | | | | | | | | | | | | | +----- LED3(ScrollLock)
471 | | | | | | | | | | +-+-+------- Reserved
472 | | | | | | | | | +------------- ScrollLock
473 | | | | | | | | +--------------- NumLock
474 | | | | | | | +----------------- Apple/Command
475 | | | | | | +------------------- Option
476 | | | | | +--------------------- Shift
477 | | | | +----------------------- Control
478 | | | +------------------------- Reset/Power
479 | | +--------------------------- CapsLock
480 | +----------------------------- Delete
481 +------------------------------- Reserved
482
483Address, Handler ID and bits(Register3)
484 1514131211 . . 8 7 . . . . . . 0
485 | | | | | | | | | | | | | | | |
486 | | | | | | | | +-+-+-+-+-+-+-+- Handler ID
487 | | | | +-+-+-+----------------- Address
488 | | | +------------------------- 0
489 | | +--------------------------- Service request enable(1 = enabled)
490 | +----------------------------- Exceptional event(alwyas 1 if not used)
491 +------------------------------- 0
492
493ADB Bit Cells
494 bit cell time: 70-130us
495 low part of bit0: 60-70% of bit cell
496 low part of bit1: 30-40% of bit cell
497
498 bit cell time 70us 130us
499 --------------------------------------------
500 low part of bit0 42-49 78-91
501 high part of bit0 21-28 39-52
502 low part of bit1 21-28 39-52
503 high part of bit1 42-49 78-91
504
505
506 bit0:
507 70us bit cell:
508 ____________~~~~~~
509 42-49 21-28
510
511 130us bit cell:
512 ____________~~~~~~
513 78-91 39-52
514
515 bit1:
516 70us bit cell:
517 ______~~~~~~~~~~~~
518 21-28 42-49
519
520 130us bit cell:
521 ______~~~~~~~~~~~~
522 39-52 78-91
523
524 [from Apple IIgs Hardware Reference Second Edition]
525
526Keyboard Handle ID
527 Apple Standard Keyboard M0116: 0x01
528 Apple Extended Keyboard M0115: 0x02
529 Apple Extended Keyboard II M3501: 0x02
530 Apple Adjustable Keybaord: 0x10
531
532 http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802
533
534END_OF_ADB
535*/
diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h
deleted file mode 100644
index fe8becc2d..000000000
--- a/tmk_core/protocol/adb.h
+++ /dev/null
@@ -1,106 +0,0 @@
1/*
2Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#pragma once
39
40#include <stdint.h>
41#include <stdbool.h>
42
43#if !(defined(ADB_PORT) && defined(ADB_PIN) && defined(ADB_DDR) && defined(ADB_DATA_BIT))
44# error "ADB port setting is required in config.h"
45#endif
46
47#define ADB_POWER 0x7F
48#define ADB_CAPS 0x39
49
50/* ADB commands */
51// Default Address
52#define ADB_ADDR_0 0
53#define ADB_ADDR_DONGLE 1
54#define ADB_ADDR_KEYBOARD 2
55#define ADB_ADDR_MOUSE 3
56#define ADB_ADDR_TABLET 4
57#define ADB_ADDR_APPLIANCE 7
58#define ADB_ADDR_8 8
59#define ADB_ADDR_9 9
60#define ADB_ADDR_10 10
61#define ADB_ADDR_11 11
62#define ADB_ADDR_12 12
63#define ADB_ADDR_13 13
64#define ADB_ADDR_14 14
65#define ADB_ADDR_15 15
66// for temporary purpose, do not use for polling
67#define ADB_ADDR_TMP 15
68#define ADB_ADDR_MOUSE_POLL 10
69// Command Type
70#define ADB_CMD_RESET 0
71#define ADB_CMD_FLUSH 1
72#define ADB_CMD_LISTEN 8
73#define ADB_CMD_TALK 12
74// Register
75#define ADB_REG_0 0
76#define ADB_REG_1 1
77#define ADB_REG_2 2
78#define ADB_REG_3 3
79
80/* ADB keyboard handler id */
81#define ADB_HANDLER_STD 0x01 /* IIGS, M0116 */
82#define ADB_HANDLER_AEK 0x02 /* M0115, M3501 */
83#define ADB_HANDLER_AEK_RMOD 0x03 /* M0115, M3501, alternate mode enableing right modifiers */
84#define ADB_HANDLER_STD_ISO 0x04 /* M0118, ISO swapping keys */
85#define ADB_HANDLER_AEK_ISO 0x05 /* M0115, M3501, ISO swapping keys */
86#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */
87#define ADB_HANDLER_CLASSIC1_MOUSE 0x01
88#define ADB_HANDLER_CLASSIC2_MOUSE 0x02
89#define ADB_HANDLER_EXTENDED_MOUSE 0x04
90#define ADB_HANDLER_TURBO_MOUSE 0x32
91
92// ADB host
93void adb_host_init(void);
94bool adb_host_psw(void);
95uint16_t adb_host_talk(uint8_t addr, uint8_t reg);
96uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
97void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l);
98void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
99void adb_host_flush(uint8_t addr);
100void adb_host_kbd_led(uint8_t led);
101uint16_t adb_host_kbd_recv(void);
102uint16_t adb_host_mouse_recv(void);
103
104// ADB Mouse
105void adb_mouse_task(void);
106void adb_mouse_init(void);
diff --git a/tmk_core/protocol/arm_atsam.mk b/tmk_core/protocol/arm_atsam.mk
index 5bb45d658..ffd1fa9f5 100644
--- a/tmk_core/protocol/arm_atsam.mk
+++ b/tmk_core/protocol/arm_atsam.mk
@@ -9,7 +9,8 @@ ifeq ($(RGB_MATRIX_DRIVER),custom)
9 SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c 9 SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c
10endif 10endif
11SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c 11SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
12SRC += $(ARM_ATSAM_DIR)/spi.c 12SRC += $(ARM_ATSAM_DIR)/shift_register.c
13SRC += $(ARM_ATSAM_DIR)/spi_master.c
13SRC += $(ARM_ATSAM_DIR)/startup.c 14SRC += $(ARM_ATSAM_DIR)/startup.c
14 15
15SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c 16SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c
@@ -19,10 +20,12 @@ SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c
19SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c 20SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c
20SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c 21SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c
21SRC += $(ARM_ATSAM_DIR)/usb/ui.c 22SRC += $(ARM_ATSAM_DIR)/usb/ui.c
22SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c
23SRC += $(ARM_ATSAM_DIR)/usb/usb.c 23SRC += $(ARM_ATSAM_DIR)/usb/usb.c
24SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c 24SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c
25SRC += $(ARM_ATSAM_DIR)/usb/usb_hub.c
25SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c 26SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c
26 27
28SRC += $(DRIVER_PATH)/usb2422.c
29
27# Search Path 30# Search Path
28VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR) 31VPATH += $(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 d126c66e7..e1749f872 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/>.
27#include "wait.h" 27#include "wait.h"
28#include "adc.h" 28#include "adc.h"
29#include "i2c_master.h" 29#include "i2c_master.h"
30#include "spi.h" 30#include "shift_register.h"
31 31
32#include "./usb/usb2422.h" 32#include "./usb/usb_hub.h"
33 33
34#ifndef MD_BOOTLOADER 34#ifndef MD_BOOTLOADER
35 35
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c
index dda2f85b0..af046625f 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) {
564 564
565 return 1; 565 return 1;
566} 566}
567
568__attribute__((weak)) void i2c_init(void) {
569 static bool is_initialised = false;
570 if (!is_initialised) {
571 is_initialised = true;
572
573 i2c0_init();
574 }
575}
576
577i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) {
578 uint8_t ret = i2c0_transmit(address, (uint8_t *)data, length, timeout);
579 SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
580 while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {
581 DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP);
582 }
583 return ret ? I2C_STATUS_SUCCESS : I2C_STATUS_ERROR;
584}
585
567#endif // !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE) 586#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 68773f213..e11235d44 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);
101uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout); 101uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
102void i2c0_stop(void); 102void i2c0_stop(void);
103 103
104// Terrible interface compatiblity...
105#define I2C_STATUS_SUCCESS (0)
106#define I2C_STATUS_ERROR (-1)
107
108typedef int16_t i2c_status_t;
109
110void i2c_init(void);
111i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout);
112
104#endif // _I2C_MASTER_H_ 113#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 858b4cd9f..1df5112ed 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) {
296 296
297 matrix_init(); 297 matrix_init();
298 298
299 USB2422_init(); 299 USB_Hub_init();
300 300
301 DBGC(DC_MAIN_UDC_START_BEGIN); 301 DBGC(DC_MAIN_UDC_START_BEGIN);
302 udc_start(); 302 udc_start();
@@ -306,7 +306,7 @@ int main(void) {
306 CDC_init(); 306 CDC_init();
307 DBGC(DC_MAIN_CDC_INIT_COMPLETE); 307 DBGC(DC_MAIN_CDC_INIT_COMPLETE);
308 308
309 while (USB2422_Port_Detect_Init() == 0) { 309 while (USB_Hub_Port_Detect_Init() == 0) {
310 } 310 }
311 311
312 DBG_LED_OFF; 312 DBG_LED_OFF;
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 000000000..8d63af1b5
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/shift_register.c
@@ -0,0 +1,118 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19
20#include "spi_master.h"
21#include "wait.h"
22#include "gpio.h"
23
24// #define SR_USE_BITBANG
25
26// Bodge for when spi_master is not available
27#ifdef SR_USE_BITBANG
28# define CLOCK_DELAY 10
29
30void shift_init_impl(void) {
31 setPinOutput(SR_EXP_RCLK_PIN);
32 setPinOutput(SPI_DATAOUT_PIN);
33 setPinOutput(SPI_SCLK_PIN);
34}
35
36void shift_out_impl(const uint8_t *data, uint16_t length) {
37 writePinLow(SR_EXP_RCLK_PIN);
38 for (uint16_t i = 0; i < length; i++) {
39 uint8_t val = data[i];
40
41 // shift out lsb first
42 for (uint8_t bit = 0; bit < 8; bit++) {
43 writePin(SPI_DATAOUT_PIN, !!(val & (1 << bit)));
44 writePin(SPI_SCLK_PIN, true);
45 wait_us(CLOCK_DELAY);
46
47 writePin(SPI_SCLK_PIN, false);
48 wait_us(CLOCK_DELAY);
49 }
50 }
51 writePinHigh(SR_EXP_RCLK_PIN);
52 return SPI_STATUS_SUCCESS;
53}
54
55#else
56
57void shift_init_impl(void) { spi_init(); }
58
59void shift_out_impl(const uint8_t *data, uint16_t length) {
60 spi_start(SR_EXP_RCLK_PIN, true, 0, 0);
61
62 spi_transmit(data, length);
63
64 spi_stop();
65}
66#endif
67
68// ***************************************************************
69
70void shift_out(const uint8_t *data, uint16_t length) { shift_out_impl(data, length); }
71
72void shift_enable(void) {
73 setPinOutput(SR_EXP_OE_PIN);
74 writePinLow(SR_EXP_OE_PIN);
75}
76
77void shift_disable(void) {
78 setPinOutput(SR_EXP_OE_PIN);
79 writePinHigh(SR_EXP_OE_PIN);
80}
81
82void shift_init(void) {
83 shift_disable();
84 shift_init_impl();
85}
86
87// ***************************************************************
88
89sr_exp_t sr_exp_data;
90
91void SR_EXP_WriteData(void) {
92 uint8_t data[2] = {
93 sr_exp_data.reg & 0xFF, // Shift in bits 7-0
94 (sr_exp_data.reg >> 8) & 0xFF, // Shift in bits 15-8
95 };
96 shift_out(data, 2);
97}
98
99void SR_EXP_Init(void) {
100 shift_init();
101
102 sr_exp_data.reg = 0;
103 sr_exp_data.bit.HUB_CONNECT = 0;
104 sr_exp_data.bit.HUB_RESET_N = 0;
105 sr_exp_data.bit.S_UP = 0;
106 sr_exp_data.bit.E_UP_N = 1;
107 sr_exp_data.bit.S_DN1 = 1;
108 sr_exp_data.bit.E_DN1_N = 1;
109 sr_exp_data.bit.E_VBUS_1 = 0;
110 sr_exp_data.bit.E_VBUS_2 = 0;
111 sr_exp_data.bit.SRC_1 = 1;
112 sr_exp_data.bit.SRC_2 = 1;
113 sr_exp_data.bit.IRST = 1;
114 sr_exp_data.bit.SDB_N = 0;
115 SR_EXP_WriteData();
116
117 shift_enable();
118}
diff --git a/tmk_core/protocol/arm_atsam/spi.h b/tmk_core/protocol/arm_atsam/shift_register.h
index dcd45f31a..56a8c7f71 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
15along with this program. If not, see <http://www.gnu.org/licenses/>. 15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17 17
18#ifndef _SPI_H_ 18#pragma once
19#define _SPI_H_
20 19
21/* Macros for Shift Register control */ 20#include <stdint.h>
22#define SR_EXP_RCLK_LO PORT->Group[SR_EXP_RCLK_PORT].OUTCLR.reg = (1 << SR_EXP_RCLK_PIN)
23#define SR_EXP_RCLK_HI PORT->Group[SR_EXP_RCLK_PORT].OUTSET.reg = (1 << SR_EXP_RCLK_PIN)
24#define SR_EXP_OE_N_ENA PORT->Group[SR_EXP_OE_N_PORT].OUTCLR.reg = (1 << SR_EXP_OE_N_PIN)
25#define SR_EXP_OE_N_DIS PORT->Group[SR_EXP_OE_N_PORT].OUTSET.reg = (1 << SR_EXP_OE_N_PIN)
26
27/* Determine bits to set for mux selection */
28#if SR_EXP_DATAOUT_PIN % 2 == 0
29# define SR_EXP_DATAOUT_MUX_SEL PMUXE
30#else
31# define SR_EXP_DATAOUT_MUX_SEL PMUXO
32#endif
33
34/* Determine bits to set for mux selection */
35#if SR_EXP_SCLK_PIN % 2 == 0
36# define SR_EXP_SCLK_MUX_SEL PMUXE
37#else
38# define SR_EXP_SCLK_MUX_SEL PMUXO
39#endif
40 21
41/* Data structure to define Shift Register output expander hardware */ 22/* Data structure to define Shift Register output expander hardware */
42/* This structure gets shifted into registers LSB first */ 23/* This structure gets shifted into registers LSB first */
@@ -66,5 +47,3 @@ extern sr_exp_t sr_exp_data;
66 47
67void SR_EXP_WriteData(void); 48void SR_EXP_WriteData(void);
68void SR_EXP_Init(void); 49void SR_EXP_Init(void);
69
70#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 3b118bc1f..000000000
--- a/tmk_core/protocol/arm_atsam/spi.c
+++ /dev/null
@@ -1,92 +0,0 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19
20sr_exp_t sr_exp_data;
21
22void SR_EXP_WriteData(void) {
23 SR_EXP_RCLK_LO;
24
25 while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) {
26 DBGC(DC_SPI_WRITE_DRE);
27 }
28
29 SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF; // Shift in bits 7-0
30 while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) {
31 DBGC(DC_SPI_WRITE_TXC_1);
32 }
33
34 SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF; // Shift in bits 15-8
35 while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) {
36 DBGC(DC_SPI_WRITE_TXC_2);
37 }
38
39 SR_EXP_RCLK_HI;
40}
41
42void SR_EXP_Init(void) {
43 DBGC(DC_SPI_INIT_BEGIN);
44
45 CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
46
47 // Set up MCU Shift Register pins
48 PORT->Group[SR_EXP_RCLK_PORT].DIRSET.reg = (1 << SR_EXP_RCLK_PIN);
49 PORT->Group[SR_EXP_OE_N_PORT].DIRSET.reg = (1 << SR_EXP_OE_N_PIN);
50
51 // Set up MCU SPI pins
52 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
53 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
54 PORT->Group[SR_EXP_DATAOUT_PORT].PINCFG[SR_EXP_DATAOUT_PIN].bit.PMUXEN = 1; // MUX Enable
55 PORT->Group[SR_EXP_SCLK_PORT].PINCFG[SR_EXP_SCLK_PIN].bit.PMUXEN = 1; // MUX Enable
56
57 // Initialize Shift Register
58 SR_EXP_OE_N_DIS;
59 SR_EXP_RCLK_HI;
60
61 SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; // Data Order - LSB is transferred first
62 SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
63 SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
64 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.)
65 SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1]
66 SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation
67
68 SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled
69 while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) {
70 DBGC(DC_SPI_SYNC_ENABLING);
71 }
72
73 sr_exp_data.reg = 0;
74 sr_exp_data.bit.HUB_CONNECT = 0;
75 sr_exp_data.bit.HUB_RESET_N = 0;
76 sr_exp_data.bit.S_UP = 0;
77 sr_exp_data.bit.E_UP_N = 1;
78 sr_exp_data.bit.S_DN1 = 1;
79 sr_exp_data.bit.E_DN1_N = 1;
80 sr_exp_data.bit.E_VBUS_1 = 0;
81 sr_exp_data.bit.E_VBUS_2 = 0;
82 sr_exp_data.bit.SRC_1 = 1;
83 sr_exp_data.bit.SRC_2 = 1;
84 sr_exp_data.bit.IRST = 1;
85 sr_exp_data.bit.SDB_N = 0;
86 SR_EXP_WriteData();
87
88 // Enable Shift Register output
89 SR_EXP_OE_N_ENA;
90
91 DBGC(DC_SPI_INIT_COMPLETE);
92}
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 000000000..9781d45b1
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/spi_master.c
@@ -0,0 +1,109 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "arm_atsam_protocol.h"
19#include "spi_master.h"
20#include "gpio.h"
21
22/* Determine bits to set for mux selection */
23#if SPI_DATAOUT_PIN % 2 == 0
24# define SPI_DATAOUT_MUX_SEL PMUXE
25#else
26# define SPI_DATAOUT_MUX_SEL PMUXO
27#endif
28
29/* Determine bits to set for mux selection */
30#if SPI_SCLK_PIN % 2 == 0
31# define SPI_SCLK_MUX_SEL PMUXE
32#else
33# define SPI_SCLK_MUX_SEL PMUXO
34#endif
35
36static pin_t currentSelectPin = NO_PIN;
37
38__attribute__((weak)) void spi_init(void) {
39 static bool is_initialised = false;
40 if (!is_initialised) {
41 is_initialised = true;
42
43 DBGC(DC_SPI_INIT_BEGIN);
44
45 CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
46
47 // Set up MCU SPI pins
48 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
49 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
50 PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PINCFG[SAMD_PIN(SPI_DATAOUT_PIN)].bit.PMUXEN = 1; // MUX Enable
51 PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PINCFG[SAMD_PIN(SPI_SCLK_PIN)].bit.PMUXEN = 1; // MUX Enable
52
53 DBGC(DC_SPI_INIT_COMPLETE);
54 }
55}
56
57bool spi_start(pin_t csPin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
58 if (currentSelectPin != NO_PIN || csPin == NO_PIN) {
59 return false;
60 }
61
62 currentSelectPin = csPin;
63 setPinOutput(currentSelectPin);
64 writePinLow(currentSelectPin);
65
66 SPI_SERCOM->SPI.CTRLA.bit.DORD = lsbFirst; // Data Order - LSB is transferred first
67 SPI_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
68 SPI_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
69 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.)
70 SPI_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1]
71 SPI_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation
72
73 SPI_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled
74 while (SPI_SERCOM->SPI.SYNCBUSY.bit.ENABLE) {
75 DBGC(DC_SPI_SYNC_ENABLING);
76 }
77 return true;
78}
79
80spi_status_t spi_transmit(const uint8_t *data, uint16_t length) {
81 while (!(SPI_SERCOM->SPI.INTFLAG.bit.DRE)) {
82 DBGC(DC_SPI_WRITE_DRE);
83 }
84
85 for (uint16_t i = 0; i < length; i++) {
86 SPI_SERCOM->SPI.DATA.bit.DATA = data[i];
87 while (!(SPI_SERCOM->SPI.INTFLAG.bit.TXC)) {
88 DBGC(DC_SPI_WRITE_TXC_1);
89 }
90 }
91
92 return SPI_STATUS_SUCCESS;
93}
94
95void spi_stop(void) {
96 if (currentSelectPin != NO_PIN) {
97 setPinOutput(currentSelectPin);
98 writePinHigh(currentSelectPin);
99 currentSelectPin = NO_PIN;
100 }
101}
102
103// Not implemented yet....
104
105spi_status_t spi_write(uint8_t data);
106
107spi_status_t spi_read(void);
108
109spi_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 000000000..26c55128b
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/spi_master.h
@@ -0,0 +1,48 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <https://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include <stdbool.h>
20
21typedef int16_t spi_status_t;
22
23#define SPI_STATUS_SUCCESS (0)
24#define SPI_STATUS_ERROR (-1)
25#define SPI_STATUS_TIMEOUT (-2)
26
27#define SPI_TIMEOUT_IMMEDIATE (0)
28#define SPI_TIMEOUT_INFINITE (0xFFFF)
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33void spi_init(void);
34
35bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
36
37spi_status_t spi_write(uint8_t data);
38
39spi_status_t spi_read(void);
40
41spi_status_t spi_transmit(const uint8_t *data, uint16_t length);
42
43spi_status_t spi_receive(uint8_t *data, uint16_t length);
44
45void spi_stop(void);
46#ifdef __cplusplus
47}
48#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 b4830b5bc..000000000
--- a/tmk_core/protocol/arm_atsam/usb/usb2422.h
+++ /dev/null
@@ -1,402 +0,0 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _USB2422_H_
19#define _USB2422_H_
20
21#define REV_USB2422 0x100
22
23#define USB2422_ADDR 0x58 // I2C device address, one instance
24
25#define USB2422_HUB_ACTIVE_GROUP 0 // PA
26#define USB2422_HUB_ACTIVE_PIN 18 // 18
27
28/* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */
29#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
30typedef union {
31 struct {
32 uint16_t VID_LSB : 8;
33 uint16_t VID_MSB : 8;
34 } bit; /*!< Structure used for bit access */
35 uint16_t reg; /*!< Type used for register access */
36} USB2422_VID_Type;
37#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
38
39/* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */
40#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
41typedef union {
42 struct {
43 uint16_t PID_LSB : 8;
44 uint16_t PID_MSB : 8;
45 } bit; /*!< Structure used for bit access */
46 uint16_t reg; /*!< Type used for register access */
47} USB2422_PID_Type;
48#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
49
50/* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */
51#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
52typedef union {
53 struct {
54 uint16_t DID_LSB : 8;
55 uint16_t DID_MSB : 8;
56 } bit; /*!< Structure used for bit access */
57 uint16_t reg; /*!< Type used for register access */
58} USB2422_DID_Type;
59#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
60
61/* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */
62#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
63typedef union {
64 struct {
65 uint8_t PORT_PWR : 1;
66 uint8_t CURRENT_SNS : 2;
67 uint8_t EOP_DISABLE : 1;
68 uint8_t MTT_ENABLE : 1;
69 uint8_t HS_DISABLE : 1;
70 uint8_t : 1;
71 uint8_t SELF_BUS_PWR : 1;
72 } bit; /*!< Structure used for bit access */
73 uint8_t reg; /*!< Type used for register access */
74} USB2422_CFG1_Type;
75#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
76
77/* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */
78#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
79typedef union {
80 struct {
81 uint8_t : 3;
82 uint8_t COMPOUND : 1;
83 uint8_t OC_TIMER : 2;
84 uint8_t : 1;
85 uint8_t DYNAMIC : 1;
86 } bit; /*!< Structure used for bit access */
87 uint8_t reg; /*!< Type used for register access */
88} USB2422_CFG2_Type;
89#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
90
91/* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */
92#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
93typedef union {
94 struct {
95 uint8_t STRING_EN : 1;
96 uint8_t : 2;
97 uint8_t PRTMAP_EN : 1;
98 uint8_t : 4;
99 } bit; /*!< Structure used for bit access */
100 uint8_t reg; /*!< Type used for register access */
101} USB2422_CFG3_Type;
102#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
103
104/* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */
105#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
106typedef union {
107 struct {
108 uint8_t : 5;
109 uint8_t PORT2_NR : 1;
110 uint8_t PORT1_NR : 1;
111 uint8_t : 1;
112 } bit; /*!< Structure used for bit access */
113 uint8_t reg; /*!< Type used for register access */
114} USB2422_NRD_Type;
115#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
116
117/* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */
118#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
119typedef union {
120 struct {
121 uint8_t : 1;
122 uint8_t PORT1_DIS : 1;
123 uint8_t PORT2_DIS : 1;
124 uint8_t : 5;
125 } bit; /*!< Structure used for bit access */
126 uint8_t reg; /*!< Type used for register access */
127} USB2422_PDS_Type;
128#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
129
130/* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */
131#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
132typedef union {
133 struct {
134 uint8_t : 1;
135 uint8_t PORT1_DIS : 1;
136 uint8_t PORT2_DIS : 1;
137 uint8_t : 5;
138 } bit; /*!< Structure used for bit access */
139 uint8_t reg; /*!< Type used for register access */
140} USB2422_PDB_Type;
141#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
142
143/* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */
144#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
145typedef union {
146 struct {
147 uint8_t MAX_PWR_SP : 8;
148 } bit; /*!< Structure used for bit access */
149 uint8_t reg; /*!< Type used for register access */
150} USB2422_MAXPS_Type;
151#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
152
153/* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */
154#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
155typedef union {
156 struct {
157 uint8_t MAX_PWR_BP : 8;
158 } bit; /*!< Structure used for bit access */
159 uint8_t reg; /*!< Type used for register access */
160} USB2422_MAXPB_Type;
161#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
162
163/* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */
164#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
165typedef union {
166 struct {
167 uint8_t HC_MAX_C_SP : 8;
168 } bit; /*!< Structure used for bit access */
169 uint8_t reg; /*!< Type used for register access */
170} USB2422_HCMCS_Type;
171#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
172
173/* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */
174#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
175typedef union {
176 struct {
177 uint8_t HC_MAX_C_BP : 8;
178 } bit; /*!< Structure used for bit access */
179 uint8_t reg; /*!< Type used for register access */
180} USB2422_HCMCB_Type;
181#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
182
183/* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */
184#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
185typedef union {
186 struct {
187 uint8_t POWER_ON_TIME : 8;
188 } bit; /*!< Structure used for bit access */
189 uint8_t reg; /*!< Type used for register access */
190} USB2422_PWRT_Type;
191#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
192
193/* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */
194#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
195typedef union {
196 struct {
197 uint8_t LANGID_LSB : 8;
198 } bit; /*!< Structure used for bit access */
199 uint8_t reg; /*!< Type used for register access */
200} USB2422_LANGID_LSB_Type;
201#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
202
203/* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */
204#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
205typedef union {
206 struct {
207 uint8_t LANGID_MSB : 8;
208 } bit; /*!< Structure used for bit access */
209 uint8_t reg; /*!< Type used for register access */
210} USB2422_LANGID_MSB_Type;
211#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
212
213/* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */
214#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
215typedef union {
216 struct {
217 uint8_t MFR_STR_LEN : 8;
218 } bit; /*!< Structure used for bit access */
219 uint8_t reg; /*!< Type used for register access */
220} USB2422_MFRSL_Type;
221#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
222
223/* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */
224#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
225typedef union {
226 struct {
227 uint8_t PRD_STR_LEN : 8;
228 } bit; /*!< Structure used for bit access */
229 uint8_t reg; /*!< Type used for register access */
230} USB2422_PRDSL_Type;
231#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
232
233/* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */
234#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
235typedef union {
236 struct {
237 uint8_t SER_STR_LEN : 8;
238 } bit; /*!< Structure used for bit access */
239 uint8_t reg; /*!< Type used for register access */
240} USB2422_SERSL_Type;
241#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
242
243/* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */
244#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
245typedef uint16_t USB2422_MFRSTR_Type;
246#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
247
248/* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */
249#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
250typedef uint16_t USB2422_PRDSTR_Type;
251#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
252
253/* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */
254#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
255typedef uint16_t USB2422_SERSTR_Type;
256#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
257
258/* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */
259#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
260typedef union {
261 struct {
262 uint8_t : 1;
263 uint8_t PORT1_BCE : 1;
264 uint8_t PORT2_BCE : 1;
265 uint8_t : 5;
266 } bit; /*!< Structure used for bit access */
267 uint8_t reg; /*!< Type used for register access */
268} USB2422_BCEN_Type;
269#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
270
271/* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */
272#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
273typedef union {
274 struct {
275 uint8_t BOOST : 2;
276 uint8_t : 6;
277 } bit; /*!< Structure used for bit access */
278 uint8_t reg; /*!< Type used for register access */
279} USB2422_BOOSTUP_Type;
280#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
281
282/* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */
283#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
284typedef union {
285 struct {
286 uint8_t BOOST1 : 2;
287 uint8_t BOOST2 : 2;
288 uint8_t : 4;
289 } bit; /*!< Structure used for bit access */
290 uint8_t reg; /*!< Type used for register access */
291} USB2422_BOOSTDOWN_Type;
292#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
293
294/* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */
295#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
296typedef union {
297 struct {
298 uint8_t : 1;
299 uint8_t PORT1_SP : 1;
300 uint8_t PORT2_SP : 1;
301 uint8_t : 5;
302 } bit; /*!< Structure used for bit access */
303 uint8_t reg; /*!< Type used for register access */
304} USB2422_PRTSP_Type;
305#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
306
307/* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */
308#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
309typedef union {
310 struct {
311 uint8_t PORT1_REMAP : 4;
312 uint8_t PORT2_REMAP : 4;
313 } bit; /*!< Structure used for bit access */
314 uint8_t reg; /*!< Type used for register access */
315} USB2422_PRTR12_Type;
316#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
317#define USB2422_PRTR12_DISABLE 0
318#define USB2422_PRT12_P2TOL1 1
319#define USB2422_PRT12_P2XTOL2 2
320#define USB2422_PRT12_P1TOL1 1
321#define USB2422_PRT12_P1XTOL2 2
322
323/* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */
324#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
325typedef union {
326 struct {
327 uint8_t USB_ATTACH : 1;
328 uint8_t RESET : 1;
329 uint8_t INTF_PWRDN : 1;
330 uint8_t : 5;
331 } bit; /*!< Structure used for bit access */
332 uint8_t reg; /*!< Type used for register access */
333} USB2422_STCD_Type;
334#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
335
336/** \brief USB2422 device hardware registers */
337#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
338typedef struct {
339 USB2422_VID_Type VID; /**< \brief Offset: 0x00*/
340 USB2422_PID_Type PID; /**< \brief Offset: 0x02*/
341 USB2422_DID_Type DID; /**< \brief Offset: 0x04*/
342 USB2422_CFG1_Type CFG1; /**< \brief Offset: 0x06*/
343 USB2422_CFG2_Type CFG2; /**< \brief Offset: 0x07*/
344 USB2422_CFG3_Type CFG3; /**< \brief Offset: 0x08*/
345 USB2422_NRD_Type NRD; /**< \brief Offset: 0x09*/
346 USB2422_PDS_Type PDS; /**< \brief Offset: 0x0A*/
347 USB2422_PDB_Type PDB; /**< \brief Offset: 0x0B*/
348 USB2422_MAXPS_Type MAXPS; /**< \brief Offset: 0x0C*/
349 USB2422_MAXPB_Type MAXPB; /**< \brief Offset: 0x0D*/
350 USB2422_HCMCS_Type HCMCS; /**< \brief Offset: 0x0E*/
351 USB2422_HCMCB_Type HCMCB; /**< \brief Offset: 0x0F*/
352 USB2422_PWRT_Type PWRT; /**< \brief Offset: 0x10*/
353 USB2422_LANGID_LSB_Type LANGID_LSB; /**< \brief Offset: 0x11*/
354 USB2422_LANGID_MSB_Type LANGID_MSB; /**< \brief Offset: 0x12*/
355 USB2422_MFRSL_Type MFRSL; /**< \brief Offset: 0x13*/
356 USB2422_PRDSL_Type PRDSL; /**< \brief Offset: 0x14*/
357 USB2422_SERSL_Type SERSL; /**< \brief Offset: 0x15*/
358 USB2422_MFRSTR_Type MFRSTR[31]; /**< \brief Offset: 0x16*/
359 USB2422_PRDSTR_Type PRDSTR[31]; /**< \brief Offset: 0x54*/
360 USB2422_SERSTR_Type SERSTR[31]; /**< \brief Offset: 0x92*/
361 USB2422_BCEN_Type BCEN; /**< \brief Offset: 0xD0*/
362 uint8_t Reserved1[0x25];
363 USB2422_BOOSTUP_Type BOOSTUP; /**< \brief Offset: 0xF6*/
364 uint8_t Reserved2[0x1];
365 USB2422_BOOSTDOWN_Type BOOSTDOWN; /**< \brief Offset: 0xF8*/
366 uint8_t Reserved3[0x1];
367 USB2422_PRTSP_Type PRTSP; /**< \brief Offset: 0xFA*/
368 USB2422_PRTR12_Type PRTR12; /**< \brief Offset: 0xFB*/
369 uint8_t Reserved4[0x3];
370 USB2422_STCD_Type STCD; /**< \brief Offset: 0xFF*/
371} Usb2422;
372#endif
373
374#define PORT_DETECT_RETRY_INTERVAL 2000
375
376#define USB_EXTRA_ADC_THRESHOLD 900
377
378#define USB_EXTRA_STATE_DISABLED 0
379#define USB_EXTRA_STATE_ENABLED 1
380#define USB_EXTRA_STATE_UNKNOWN 2
381#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
382
383#define USB_HOST_PORT_1 0
384#define USB_HOST_PORT_2 1
385#define USB_HOST_PORT_UNKNOWN 2
386
387extern uint8_t usb_host_port;
388extern uint8_t usb_extra_state;
389extern uint8_t usb_extra_manual;
390extern uint8_t usb_gcr_auto;
391
392void USB2422_init(void);
393void USB_reset(void);
394void USB_configure(void);
395uint16_t USB_active(void);
396void USB_set_host_by_voltage(void);
397uint16_t adc_get(uint8_t muxpos);
398uint8_t USB2422_Port_Detect_Init(void);
399void USB_HandleExtraDevice(void);
400void USB_ExtraSetState(uint8_t state);
401
402#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 a878cb6b7..c5fd284aa 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/>.
16*/ 16*/
17 17
18#include "arm_atsam_protocol.h" 18#include "arm_atsam_protocol.h"
19#include "drivers/usb2422.h"
19#include <string.h> 20#include <string.h>
20 21
21Usb2422 USB2422_shadow;
22unsigned char i2c0_buf[34];
23
24const uint16_t MFRNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'I', 'n', 'c', '.'}; // Massdrop Inc.
25const uint16_t PRDNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'H', 'u', 'b'}; // Massdrop Hub
26#ifndef MD_BOOTLOADER
27// Serial number reported stops before first found space character or at last found character
28const uint16_t SERNAME[] = {'U', 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e'}; // Unavailable
29#else
30// In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space
31// The offset allows the application to use the factory programmed serial (which may differ from the physical serial label)
32// Serial number reported stops before first found space character or when max size is reached
33__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'};
34// NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough
35// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
36#endif // MD_BOOTLOADER
37
38uint8_t usb_host_port; 22uint8_t usb_host_port;
39 23
40#ifndef MD_BOOTLOADER 24#ifndef MD_BOOTLOADER
@@ -47,29 +31,7 @@ uint8_t usb_gcr_auto;
47 31
48uint16_t adc_extra; 32uint16_t adc_extra;
49 33
50void USB_write2422_block(void) { 34void USB_Hub_init(void) {
51 unsigned char *dest = i2c0_buf;
52 unsigned char *src;
53 unsigned char *base = (unsigned char *)&USB2422_shadow;
54
55 DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);
56
57 for (src = base; src < base + 256; src += 32) {
58 dest[0] = src - base;
59 dest[1] = 32;
60 memcpy(&dest[2], src, 32);
61 i2c0_transmit(USB2422_ADDR, dest, 34, 50000);
62 SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
63 while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {
64 DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP);
65 }
66 wait_us(100);
67 }
68
69 DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
70}
71
72void USB2422_init(void) {
73 Gclk * pgclk = GCLK; 35 Gclk * pgclk = GCLK;
74 Mclk * pmclk = MCLK; 36 Mclk * pmclk = MCLK;
75 Port * pport = PORT; 37 Port * pport = PORT;
@@ -147,9 +109,7 @@ void USB2422_init(void) {
147 pusb->DEVICE.QOSCTRL.bit.DQOS = 2; 109 pusb->DEVICE.QOSCTRL.bit.DQOS = 2;
148 pusb->DEVICE.QOSCTRL.bit.CQOS = 2; 110 pusb->DEVICE.QOSCTRL.bit.CQOS = 2;
149 111
150 pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1; 112 USB2422_init();
151
152 i2c0_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration
153 113
154 sr_exp_data.bit.HUB_CONNECT = 1; // connect signal 114 sr_exp_data.bit.HUB_CONNECT = 1; // connect signal
155 sr_exp_data.bit.HUB_RESET_N = 1; // reset high 115 sr_exp_data.bit.HUB_RESET_N = 1; // reset high
@@ -181,62 +141,16 @@ void USB_reset(void) {
181} 141}
182 142
183void USB_configure(void) { 143void USB_configure(void) {
184 Usb2422 *pusb2422 = &USB2422_shadow;
185 memset(pusb2422, 0, sizeof(Usb2422));
186
187 uint16_t *serial_use = (uint16_t *)SERNAME; // Default to use SERNAME from this file
188 uint8_t serial_length = sizeof(SERNAME) / sizeof(uint16_t); // Default to use SERNAME from this file
189#ifndef MD_BOOTLOADER
190 uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
191#else // MD_BOOTLOADER
192 uint32_t serial_ptrloc = (uint32_t)&_erom - 4;
193#endif // MD_BOOTLOADER
194 uint32_t serial_address = *(uint32_t *)serial_ptrloc; // Address of bootloader's serial number if available
195
196 DBGC(DC_USB_CONFIGURE_BEGIN); 144 DBGC(DC_USB_CONFIGURE_BEGIN);
197 145
198 if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) // Check for factory programmed serial address 146 USB2422_configure();
199 {
200 if ((serial_address & 0xFF) % 4 == 0) // Check alignment
201 {
202 serial_use = (uint16_t *)(serial_address);
203 serial_length = 0;
204 while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) && serial_length < BOOTLOADER_SERIAL_MAX_SIZE) {
205 serial_length++;
206 DBGC(DC_USB_CONFIGURE_GET_SERIAL);
207 }
208 }
209 }
210
211 // configure Usb2422 registers
212 pusb2422->VID.reg = 0x04D8; // from Microchip 4/19/2018
213 pusb2422->PID.reg = 0xEEC5; // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub
214 pusb2422->DID.reg = 0x0101; // BCD 01.01
215 pusb2422->CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
216 pusb2422->CFG1.bit.HS_DISABLE = 1; // full or high speed
217 // pusb2422->CFG2.bit.COMPOUND = 0; // compound device
218 pusb2422->CFG3.bit.STRING_EN = 1; // strings enabled
219 // pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable
220 pusb2422->MAXPB.reg = 20; // 0mA
221 pusb2422->HCMCB.reg = 20; // 0mA
222 pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t);
223 pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t);
224 pusb2422->SERSL.reg = serial_length;
225 memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME));
226 memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME));
227 memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t));
228 // pusb2422->BOOSTUP.bit.BOOST=3; //upstream port
229 // pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port
230 // pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close
231 pusb2422->STCD.bit.USB_ATTACH = 1;
232 USB_write2422_block();
233 147
234 adc_extra = 0; 148 adc_extra = 0;
235 149
236 DBGC(DC_USB_CONFIGURE_COMPLETE); 150 DBGC(DC_USB_CONFIGURE_COMPLETE);
237} 151}
238 152
239uint16_t USB_active(void) { return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0; } 153uint16_t USB_active(void) { return USB2422_active(); }
240 154
241void USB_set_host_by_voltage(void) { 155void USB_set_host_by_voltage(void) {
242 // UP is upstream device (HOST) 156 // UP is upstream device (HOST)
@@ -314,7 +228,7 @@ void USB_set_host_by_voltage(void) {
314 DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE); 228 DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
315} 229}
316 230
317uint8_t USB2422_Port_Detect_Init(void) { 231uint8_t USB_Hub_Port_Detect_Init(void) {
318 uint32_t port_detect_retry_ms; 232 uint32_t port_detect_retry_ms;
319 uint32_t tmod; 233 uint32_t tmod;
320 234
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 000000000..76b1e0a32
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_hub.h
@@ -0,0 +1,51 @@
1/*
2Copyright 2018 Massdrop Inc.
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef _USB2422_H_
19#define _USB2422_H_
20
21#define REV_USB2422 0x100
22
23#define PORT_DETECT_RETRY_INTERVAL 2000
24
25#define USB_EXTRA_ADC_THRESHOLD 900
26
27#define USB_EXTRA_STATE_DISABLED 0
28#define USB_EXTRA_STATE_ENABLED 1
29#define USB_EXTRA_STATE_UNKNOWN 2
30#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
31
32#define USB_HOST_PORT_1 0
33#define USB_HOST_PORT_2 1
34#define USB_HOST_PORT_UNKNOWN 2
35
36extern uint8_t usb_host_port;
37extern uint8_t usb_extra_state;
38extern uint8_t usb_extra_manual;
39extern uint8_t usb_gcr_auto;
40
41void USB_Hub_init(void);
42uint8_t USB_Hub_Port_Detect_Init(void);
43void USB_reset(void);
44void USB_configure(void);
45uint16_t USB_active(void);
46void USB_set_host_by_voltage(void);
47uint16_t adc_get(uint8_t muxpos);
48void USB_HandleExtraDevice(void);
49void USB_ExtraSetState(uint8_t state);
50
51#endif //_USB2422_H_
diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c
index 78a2e3fcb..c860328c8 100644
--- a/tmk_core/protocol/chibios/chibios.c
+++ b/tmk_core/protocol/chibios/chibios.c
@@ -27,6 +27,7 @@
27#include "keyboard.h" 27#include "keyboard.h"
28#include "action.h" 28#include "action.h"
29#include "action_util.h" 29#include "action_util.h"
30#include "usb_device_state.h"
30#include "mousekey.h" 31#include "mousekey.h"
31#include "led.h" 32#include "led.h"
32#include "sendchar.h" 33#include "sendchar.h"
@@ -42,12 +43,6 @@
42#ifdef SLEEP_LED_ENABLE 43#ifdef SLEEP_LED_ENABLE
43# include "sleep_led.h" 44# include "sleep_led.h"
44#endif 45#endif
45#ifdef SERIAL_LINK_ENABLE
46# include "serial_link/system/serial_link.h"
47#endif
48#ifdef VISUALIZER_ENABLE
49# include "visualizer/visualizer.h"
50#endif
51#ifdef MIDI_ENABLE 46#ifdef MIDI_ENABLE
52# include "qmk_midi.h" 47# include "qmk_midi.h"
53#endif 48#endif
@@ -139,6 +134,8 @@ void boardInit(void) {
139} 134}
140 135
141void protocol_setup(void) { 136void protocol_setup(void) {
137 usb_device_state_init();
138
142 // TESTING 139 // TESTING
143 // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); 140 // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
144 141
@@ -154,19 +151,11 @@ void protocol_init(void) {
154 setup_midi(); 151 setup_midi();
155#endif 152#endif
156 153
157#ifdef SERIAL_LINK_ENABLE
158 init_serial_link();
159#endif
160
161#ifdef VISUALIZER_ENABLE
162 visualizer_init();
163#endif
164
165 host_driver_t *driver = NULL; 154 host_driver_t *driver = NULL;
166 155
167 /* Wait until the USB or serial link is active */ 156 /* Wait until USB is active */
168 while (true) { 157 while (true) {
169#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE) 158#if defined(WAIT_FOR_USB)
170 if (USB_DRIVER.state == USB_ACTIVE) { 159 if (USB_DRIVER.state == USB_ACTIVE) {
171 driver = &chibios_driver; 160 driver = &chibios_driver;
172 break; 161 break;
@@ -175,13 +164,6 @@ void protocol_init(void) {
175 driver = &chibios_driver; 164 driver = &chibios_driver;
176 break; 165 break;
177#endif 166#endif
178#ifdef SERIAL_LINK_ENABLE
179 if (is_serial_link_connected()) {
180 driver = get_serial_link_driver();
181 break;
182 }
183 serial_link_update();
184#endif
185 wait_ms(50); 167 wait_ms(50);
186 } 168 }
187 169
@@ -211,14 +193,8 @@ void protocol_task(void) {
211#if !defined(NO_USB_STARTUP_CHECK) 193#if !defined(NO_USB_STARTUP_CHECK)
212 if (USB_DRIVER.state == USB_SUSPENDED) { 194 if (USB_DRIVER.state == USB_SUSPENDED) {
213 print("[s]"); 195 print("[s]");
214# ifdef VISUALIZER_ENABLE
215 visualizer_suspend();
216# endif
217 while (USB_DRIVER.state == USB_SUSPENDED) { 196 while (USB_DRIVER.state == USB_SUSPENDED) {
218 /* Do this in the suspended state */ 197 /* Do this in the suspended state */
219# ifdef SERIAL_LINK_ENABLE
220 serial_link_update();
221# endif
222 suspend_power_down(); // on AVR this deep sleeps for 15ms 198 suspend_power_down(); // on AVR this deep sleeps for 15ms
223 /* Remote wakeup */ 199 /* Remote wakeup */
224 if (suspend_wakeup_condition()) { 200 if (suspend_wakeup_condition()) {
@@ -232,10 +208,6 @@ void protocol_task(void) {
232# ifdef MOUSEKEY_ENABLE 208# ifdef MOUSEKEY_ENABLE
233 mousekey_send(); 209 mousekey_send();
234# endif /* MOUSEKEY_ENABLE */ 210# endif /* MOUSEKEY_ENABLE */
235
236# ifdef VISUALIZER_ENABLE
237 visualizer_resume();
238# endif
239 } 211 }
240#endif 212#endif
241 213
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index 04049c1a9..3b16a0ff7 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -39,6 +39,7 @@
39# include "led.h" 39# include "led.h"
40#endif 40#endif
41#include "wait.h" 41#include "wait.h"
42#include "usb_device_state.h"
42#include "usb_descriptor.h" 43#include "usb_descriptor.h"
43#include "usb_driver.h" 44#include "usb_driver.h"
44 45
@@ -412,6 +413,7 @@ static inline bool usb_event_queue_dequeue(usbevent_t *event) {
412} 413}
413 414
414static inline void usb_event_suspend_handler(void) { 415static inline void usb_event_suspend_handler(void) {
416 usb_device_state_set_suspend(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);
415#ifdef SLEEP_LED_ENABLE 417#ifdef SLEEP_LED_ENABLE
416 sleep_led_enable(); 418 sleep_led_enable();
417#endif /* SLEEP_LED_ENABLE */ 419#endif /* SLEEP_LED_ENABLE */
@@ -419,6 +421,7 @@ static inline void usb_event_suspend_handler(void) {
419 421
420static inline void usb_event_wakeup_handler(void) { 422static inline void usb_event_wakeup_handler(void) {
421 suspend_wakeup_init(); 423 suspend_wakeup_init();
424 usb_device_state_set_resume(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);
422#ifdef SLEEP_LED_ENABLE 425#ifdef SLEEP_LED_ENABLE
423 sleep_led_disable(); 426 sleep_led_disable();
424 // NOTE: converters may not accept this 427 // NOTE: converters may not accept this
@@ -440,6 +443,15 @@ void usb_event_queue_task(void) {
440 last_suspend_state = false; 443 last_suspend_state = false;
441 usb_event_wakeup_handler(); 444 usb_event_wakeup_handler();
442 break; 445 break;
446 case USB_EVENT_CONFIGURED:
447 usb_device_state_set_configuration(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);
448 break;
449 case USB_EVENT_UNCONFIGURED:
450 usb_device_state_set_configuration(false, 0);
451 break;
452 case USB_EVENT_RESET:
453 usb_device_state_set_reset();
454 break;
443 default: 455 default:
444 // Nothing to do, we don't handle it. 456 // Nothing to do, we don't handle it.
445 break; 457 break;
@@ -482,13 +494,14 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
482 if (last_suspend_state) { 494 if (last_suspend_state) {
483 usb_event_queue_enqueue(USB_EVENT_WAKEUP); 495 usb_event_queue_enqueue(USB_EVENT_WAKEUP);
484 } 496 }
497 usb_event_queue_enqueue(USB_EVENT_CONFIGURED);
485 return; 498 return;
486 case USB_EVENT_SUSPEND: 499 case USB_EVENT_SUSPEND:
487 usb_event_queue_enqueue(USB_EVENT_SUSPEND);
488 /* Falls into.*/ 500 /* Falls into.*/
489 case USB_EVENT_UNCONFIGURED: 501 case USB_EVENT_UNCONFIGURED:
490 /* Falls into.*/ 502 /* Falls into.*/
491 case USB_EVENT_RESET: 503 case USB_EVENT_RESET:
504 usb_event_queue_enqueue(event);
492 for (int i = 0; i < NUM_USB_DRIVERS; i++) { 505 for (int i = 0; i < NUM_USB_DRIVERS; i++) {
493 chSysLockFromISR(); 506 chSysLockFromISR();
494 /* Disconnection event on suspend.*/ 507 /* Disconnection event on suspend.*/
diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c
deleted file mode 100644
index a19443976..000000000
--- a/tmk_core/protocol/ibm4704.c
+++ /dev/null
@@ -1,185 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3*/
4#include <stdbool.h>
5#include <util/delay.h>
6#include "debug.h"
7#include "ring_buffer.h"
8#include "ibm4704.h"
9
10#define WAIT(stat, us, err) \
11 do { \
12 if (!wait_##stat(us)) { \
13 ibm4704_error = err; \
14 goto ERROR; \
15 } \
16 } while (0)
17
18uint8_t ibm4704_error = 0;
19
20void ibm4704_init(void) {
21 inhibit(); // keep keyboard from sending
22 IBM4704_INT_INIT();
23 IBM4704_INT_ON();
24 idle(); // allow keyboard sending
25}
26
27/*
28Host to Keyboard
29----------------
30Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
31
32 ____ __ __ __ __ __ __ __ __ __ ________
33Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
34 ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
35Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
36 | Start 0 1 2 3 4 5 6 7 P Stop
37 Request by host
38
39Start bit: can be long as 300-350us.
40Request: Host pulls Clock line down to request to send a command.
41Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
42 After request host release Clock line once Data line becomes hi.
43 Host writes a bit while Clock is hi and Keyboard reads while low.
44Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo.
45*/
46uint8_t ibm4704_send(uint8_t data) {
47 bool parity = true; // odd parity
48 ibm4704_error = 0;
49
50 IBM4704_INT_OFF();
51
52 /* Request to send */
53 idle();
54 clock_lo();
55
56 /* wait for Start bit(Clock:lo/Data:hi) */
57 WAIT(data_hi, 300, 0x30);
58
59 /* Data bit */
60 for (uint8_t i = 0; i < 8; i++) {
61 WAIT(clock_hi, 100, 0x40 + i);
62 if (data & (1 << i)) {
63 parity = !parity;
64 data_hi();
65 } else {
66 data_lo();
67 }
68 WAIT(clock_lo, 100, 0x48 + i);
69 }
70
71 /* Parity bit */
72 WAIT(clock_hi, 100, 0x34);
73 if (parity) {
74 data_hi();
75 } else {
76 data_lo();
77 }
78 WAIT(clock_lo, 100, 0x35);
79
80 /* Stop bit */
81 WAIT(clock_hi, 100, 0x34);
82 data_hi();
83
84 /* End */
85 WAIT(data_lo, 100, 0x36);
86
87 idle();
88 IBM4704_INT_ON();
89 return 0;
90ERROR:
91 idle();
92 if (ibm4704_error > 0x30) {
93 xprintf("S:%02X ", ibm4704_error);
94 }
95 IBM4704_INT_ON();
96 return -1;
97}
98
99/* wait forever to receive data */
100uint8_t ibm4704_recv_response(void) {
101 while (!rbuf_has_data()) {
102 _delay_ms(1);
103 }
104 return rbuf_dequeue();
105}
106
107uint8_t ibm4704_recv(void) {
108 if (rbuf_has_data()) {
109 return rbuf_dequeue();
110 } else {
111 return -1;
112 }
113}
114
115/*
116Keyboard to Host
117----------------
118Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
119
120 ____ __ __ __ __ __ __ __ __ __ _______
121Clock \_____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
122 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
123Data ____/ X____X____X____X____X____X____X____X____X____X________
124 Start 0 1 2 3 4 5 6 7 P Stop
125
126Start bit: can be long as 300-350us.
127Inhibit: Pull Data line down to inhibit keyboard to send.
128Timing: Host reads bit while Clock is hi.(rising edge)
129Stop bit: Keyboard pulls down Data line to lo after 9th clock.
130*/
131ISR(IBM4704_INT_VECT) {
132 static enum { BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP } state = BIT0;
133 // LSB first
134 static uint8_t data = 0;
135 // Odd parity
136 static uint8_t parity = false;
137
138 ibm4704_error = 0;
139
140 switch (state) {
141 case BIT0:
142 case BIT1:
143 case BIT2:
144 case BIT3:
145 case BIT4:
146 case BIT5:
147 case BIT6:
148 case BIT7:
149 data >>= 1;
150 if (data_in()) {
151 data |= 0x80;
152 parity = !parity;
153 }
154 break;
155 case PARITY:
156 if (data_in()) {
157 parity = !parity;
158 }
159 if (!parity) goto ERROR;
160 break;
161 case STOP:
162 // Data:Low
163 WAIT(data_lo, 100, state);
164 if (!rbuf_enqueue(data)) {
165 print("rbuf: full\n");
166 }
167 ibm4704_error = IBM4704_ERR_NONE;
168 goto DONE;
169 break;
170 default:
171 goto ERROR;
172 }
173 state++;
174 goto RETURN;
175ERROR:
176 ibm4704_error = state;
177 while (ibm4704_send(0xFE)) _delay_ms(1); // resend
178 xprintf("R:%02X%02X\n", state, data);
179DONE:
180 state = BIT0;
181 data = 0;
182 parity = false;
183RETURN:
184 return;
185}
diff --git a/tmk_core/protocol/ibm4704.h b/tmk_core/protocol/ibm4704.h
deleted file mode 100644
index 4f88d148b..000000000
--- a/tmk_core/protocol/ibm4704.h
+++ /dev/null
@@ -1,103 +0,0 @@
1/*
2Copyright 2014 Jun WAKO <wakojun@gmail.com>
3*/
4
5#pragma once
6
7#define IBM4704_ERR_NONE 0
8#define IBM4704_ERR_PARITY 0x70
9
10void ibm4704_init(void);
11uint8_t ibm4704_send(uint8_t data);
12uint8_t ibm4704_recv_response(void);
13uint8_t ibm4704_recv(void);
14
15/* Check pin configuration */
16#if !(defined(IBM4704_CLOCK_PORT) && defined(IBM4704_CLOCK_PIN) && defined(IBM4704_CLOCK_DDR) && defined(IBM4704_CLOCK_BIT))
17# error "ibm4704 clock pin configuration is required in config.h"
18#endif
19
20#if !(defined(IBM4704_DATA_PORT) && defined(IBM4704_DATA_PIN) && defined(IBM4704_DATA_DDR) && defined(IBM4704_DATA_BIT))
21# error "ibm4704 data pin configuration is required in config.h"
22#endif
23
24/*--------------------------------------------------------------------
25 * static functions
26 *------------------------------------------------------------------*/
27static inline void clock_lo(void) {
28 IBM4704_CLOCK_PORT &= ~(1 << IBM4704_CLOCK_BIT);
29 IBM4704_CLOCK_DDR |= (1 << IBM4704_CLOCK_BIT);
30}
31static inline void clock_hi(void) {
32 /* input with pull up */
33 IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT);
34 IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT);
35}
36static inline bool clock_in(void) {
37 IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT);
38 IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT);
39 _delay_us(1);
40 return IBM4704_CLOCK_PIN & (1 << IBM4704_CLOCK_BIT);
41}
42static inline void data_lo(void) {
43 IBM4704_DATA_PORT &= ~(1 << IBM4704_DATA_BIT);
44 IBM4704_DATA_DDR |= (1 << IBM4704_DATA_BIT);
45}
46static inline void data_hi(void) {
47 /* input with pull up */
48 IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT);
49 IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT);
50}
51static inline bool data_in(void) {
52 IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT);
53 IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT);
54 _delay_us(1);
55 return IBM4704_DATA_PIN & (1 << IBM4704_DATA_BIT);
56}
57
58static inline uint16_t wait_clock_lo(uint16_t us) {
59 while (clock_in() && us) {
60 asm("");
61 _delay_us(1);
62 us--;
63 }
64 return us;
65}
66static inline uint16_t wait_clock_hi(uint16_t us) {
67 while (!clock_in() && us) {
68 asm("");
69 _delay_us(1);
70 us--;
71 }
72 return us;
73}
74static inline uint16_t wait_data_lo(uint16_t us) {
75 while (data_in() && us) {
76 asm("");
77 _delay_us(1);
78 us--;
79 }
80 return us;
81}
82static inline uint16_t wait_data_hi(uint16_t us) {
83 while (!data_in() && us) {
84 asm("");
85 _delay_us(1);
86 us--;
87 }
88 return us;
89}
90
91/* idle state that device can send */
92static inline void idle(void) {
93 clock_hi();
94 data_hi();
95}
96
97/* inhibit device to send
98 * keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low.
99 */
100static inline void inhibit(void) {
101 clock_hi();
102 data_lo();
103}
diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk
index c8935dacb..00fec478a 100644
--- a/tmk_core/protocol/lufa.mk
+++ b/tmk_core/protocol/lufa.mk
@@ -3,7 +3,6 @@ LUFA_DIR = protocol/lufa
3# Path to the LUFA library 3# Path to the LUFA library
4LUFA_PATH = $(LIB_PATH)/lufa 4LUFA_PATH = $(LIB_PATH)/lufa
5 5
6
7# Create the LUFA source path variables by including the LUFA makefile 6# Create the LUFA source path variables by including the LUFA makefile
8ifneq (, $(wildcard $(LUFA_PATH)/LUFA/Build/lufa_sources.mk)) 7ifneq (, $(wildcard $(LUFA_PATH)/LUFA/Build/lufa_sources.mk))
9 # New build system from 20120730 8 # New build system from 20120730
@@ -22,23 +21,6 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
22 include $(TMK_PATH)/protocol/midi.mk 21 include $(TMK_PATH)/protocol/midi.mk
23endif 22endif
24 23
25ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
26 LUFA_SRC += outputselect.c \
27 $(TMK_DIR)/protocol/serial_uart.c
28endif
29
30ifeq ($(strip $(BLUETOOTH)), AdafruitBLE)
31 LUFA_SRC += spi_master.c \
32 analog.c \
33 outputselect.c \
34 $(LUFA_DIR)/adafruit_ble.cpp
35endif
36
37ifeq ($(strip $(BLUETOOTH)), RN42)
38 LUFA_SRC += outputselect.c \
39 $(TMK_DIR)/protocol/serial_uart.c
40endif
41
42ifeq ($(strip $(VIRTSER_ENABLE)), yes) 24ifeq ($(strip $(VIRTSER_ENABLE)), yes)
43 LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c 25 LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c
44endif 26endif
@@ -50,19 +32,10 @@ SRC += $(LUFA_DIR)/usb_util.c
50VPATH += $(TMK_PATH)/$(LUFA_DIR) 32VPATH += $(TMK_PATH)/$(LUFA_DIR)
51VPATH += $(LUFA_PATH) 33VPATH += $(LUFA_PATH)
52 34
53# Option modules
54#ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
55#endif
56
57#ifdef EXTRAKEY_ENABLE
58#endif
59
60# LUFA library compile-time options and predefined tokens 35# LUFA library compile-time options and predefined tokens
61LUFA_OPTS = -DUSB_DEVICE_ONLY 36LUFA_OPTS = -DUSB_DEVICE_ONLY
62LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS 37LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS
63LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" 38LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
64#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT
65LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
66LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 39LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
67LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1 40LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1
68 41
diff --git a/tmk_core/protocol/lufa/adafruit_ble.cpp b/tmk_core/protocol/lufa/adafruit_ble.cpp
deleted file mode 100644
index 3f2cc3573..000000000
--- a/tmk_core/protocol/lufa/adafruit_ble.cpp
+++ /dev/null
@@ -1,701 +0,0 @@
1#include "adafruit_ble.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <alloca.h>
6#include "debug.h"
7#include "timer.h"
8#include "action_util.h"
9#include "ringbuffer.hpp"
10#include <string.h>
11#include "spi_master.h"
12#include "wait.h"
13#include "analog.h"
14#include "progmem.h"
15
16// These are the pin assignments for the 32u4 boards.
17// You may define them to something else in your config.h
18// if yours is wired up differently.
19#ifndef AdafruitBleResetPin
20# define AdafruitBleResetPin D4
21#endif
22
23#ifndef AdafruitBleCSPin
24# define AdafruitBleCSPin B4
25#endif
26
27#ifndef AdafruitBleIRQPin
28# define AdafruitBleIRQPin E6
29#endif
30
31#ifndef AdafruitBleSpiClockSpeed
32# define AdafruitBleSpiClockSpeed 4000000UL // SCK frequency
33#endif
34
35#define SCK_DIVISOR (F_CPU / AdafruitBleSpiClockSpeed)
36
37#define SAMPLE_BATTERY
38#define ConnectionUpdateInterval 1000 /* milliseconds */
39
40#ifndef BATTERY_LEVEL_PIN
41# define BATTERY_LEVEL_PIN B5
42#endif
43
44static struct {
45 bool is_connected;
46 bool initialized;
47 bool configured;
48
49#define ProbedEvents 1
50#define UsingEvents 2
51 bool event_flags;
52
53#ifdef SAMPLE_BATTERY
54 uint16_t last_battery_update;
55 uint32_t vbat;
56#endif
57 uint16_t last_connection_update;
58} state;
59
60// Commands are encoded using SDEP and sent via SPI
61// https://github.com/adafruit/Adafruit_BluefruitLE_nRF51/blob/master/SDEP.md
62
63#define SdepMaxPayload 16
64struct sdep_msg {
65 uint8_t type;
66 uint8_t cmd_low;
67 uint8_t cmd_high;
68 struct __attribute__((packed)) {
69 uint8_t len : 7;
70 uint8_t more : 1;
71 };
72 uint8_t payload[SdepMaxPayload];
73} __attribute__((packed));
74
75// The recv latency is relatively high, so when we're hammering keys quickly,
76// we want to avoid waiting for the responses in the matrix loop. We maintain
77// a short queue for that. Since there is quite a lot of space overhead for
78// the AT command representation wrapped up in SDEP, we queue the minimal
79// information here.
80
81enum queue_type {
82 QTKeyReport, // 1-byte modifier + 6-byte key report
83 QTConsumer, // 16-bit key code
84#ifdef MOUSE_ENABLE
85 QTMouseMove, // 4-byte mouse report
86#endif
87};
88
89struct queue_item {
90 enum queue_type queue_type;
91 uint16_t added;
92 union __attribute__((packed)) {
93 struct __attribute__((packed)) {
94 uint8_t modifier;
95 uint8_t keys[6];
96 } key;
97
98 uint16_t consumer;
99 struct __attribute__((packed)) {
100 int8_t x, y, scroll, pan;
101 uint8_t buttons;
102 } mousemove;
103 };
104};
105
106// Items that we wish to send
107static RingBuffer<queue_item, 40> send_buf;
108// Pending response; while pending, we can't send any more requests.
109// This records the time at which we sent the command for which we
110// are expecting a response.
111static RingBuffer<uint16_t, 2> resp_buf;
112
113static bool process_queue_item(struct queue_item *item, uint16_t timeout);
114
115enum sdep_type {
116 SdepCommand = 0x10,
117 SdepResponse = 0x20,
118 SdepAlert = 0x40,
119 SdepError = 0x80,
120 SdepSlaveNotReady = 0xFE, // Try again later
121 SdepSlaveOverflow = 0xFF, // You read more data than is available
122};
123
124enum ble_cmd {
125 BleInitialize = 0xBEEF,
126 BleAtWrapper = 0x0A00,
127 BleUartTx = 0x0A01,
128 BleUartRx = 0x0A02,
129};
130
131enum ble_system_event_bits {
132 BleSystemConnected = 0,
133 BleSystemDisconnected = 1,
134 BleSystemUartRx = 8,
135 BleSystemMidiRx = 10,
136};
137
138#define SdepTimeout 150 /* milliseconds */
139#define SdepShortTimeout 10 /* milliseconds */
140#define SdepBackOff 25 /* microseconds */
141#define BatteryUpdateInterval 10000 /* milliseconds */
142
143static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout = SdepTimeout);
144static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose = false);
145
146// Send a single SDEP packet
147static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) {
148 spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
149 uint16_t timerStart = timer_read();
150 bool success = false;
151 bool ready = false;
152
153 do {
154 ready = spi_write(msg->type) != SdepSlaveNotReady;
155 if (ready) {
156 break;
157 }
158
159 // Release it and let it initialize
160 spi_stop();
161 wait_us(SdepBackOff);
162 spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
163 } while (timer_elapsed(timerStart) < timeout);
164
165 if (ready) {
166 // Slave is ready; send the rest of the packet
167 spi_transmit(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload)) + msg->len);
168 success = true;
169 }
170
171 spi_stop();
172
173 return success;
174}
175
176static inline void sdep_build_pkt(struct sdep_msg *msg, uint16_t command, const uint8_t *payload, uint8_t len, bool moredata) {
177 msg->type = SdepCommand;
178 msg->cmd_low = command & 0xFF;
179 msg->cmd_high = command >> 8;
180 msg->len = len;
181 msg->more = (moredata && len == SdepMaxPayload) ? 1 : 0;
182
183 static_assert(sizeof(*msg) == 20, "msg is correctly packed");
184
185 memcpy(msg->payload, payload, len);
186}
187
188// Read a single SDEP packet
189static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
190 bool success = false;
191 uint16_t timerStart = timer_read();
192 bool ready = false;
193
194 do {
195 ready = readPin(AdafruitBleIRQPin);
196 if (ready) {
197 break;
198 }
199 wait_us(1);
200 } while (timer_elapsed(timerStart) < timeout);
201
202 if (ready) {
203 spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
204
205 do {
206 // Read the command type, waiting for the data to be ready
207 msg->type = spi_read();
208 if (msg->type == SdepSlaveNotReady || msg->type == SdepSlaveOverflow) {
209 // Release it and let it initialize
210 spi_stop();
211 wait_us(SdepBackOff);
212 spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
213 continue;
214 }
215
216 // Read the rest of the header
217 spi_receive(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload)));
218
219 // and get the payload if there is any
220 if (msg->len <= SdepMaxPayload) {
221 spi_receive(msg->payload, msg->len);
222 }
223 success = true;
224 break;
225 } while (timer_elapsed(timerStart) < timeout);
226
227 spi_stop();
228 }
229 return success;
230}
231
232static void resp_buf_read_one(bool greedy) {
233 uint16_t last_send;
234 if (!resp_buf.peek(last_send)) {
235 return;
236 }
237
238 if (readPin(AdafruitBleIRQPin)) {
239 struct sdep_msg msg;
240
241 again:
242 if (sdep_recv_pkt(&msg, SdepTimeout)) {
243 if (!msg.more) {
244 // We got it; consume this entry
245 resp_buf.get(last_send);
246 dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send));
247 }
248
249 if (greedy && resp_buf.peek(last_send) && readPin(AdafruitBleIRQPin)) {
250 goto again;
251 }
252 }
253
254 } else if (timer_elapsed(last_send) > SdepTimeout * 2) {
255 dprintf("waiting_for_result: timeout, resp_buf size %d\n", (int)resp_buf.size());
256
257 // Timed out: consume this entry
258 resp_buf.get(last_send);
259 }
260}
261
262static void send_buf_send_one(uint16_t timeout = SdepTimeout) {
263 struct queue_item item;
264
265 // Don't send anything more until we get an ACK
266 if (!resp_buf.empty()) {
267 return;
268 }
269
270 if (!send_buf.peek(item)) {
271 return;
272 }
273 if (process_queue_item(&item, timeout)) {
274 // commit that peek
275 send_buf.get(item);
276 dprintf("send_buf_send_one: have %d remaining\n", (int)send_buf.size());
277 } else {
278 dprint("failed to send, will retry\n");
279 wait_ms(SdepTimeout);
280 resp_buf_read_one(true);
281 }
282}
283
284static void resp_buf_wait(const char *cmd) {
285 bool didPrint = false;
286 while (!resp_buf.empty()) {
287 if (!didPrint) {
288 dprintf("wait on buf for %s\n", cmd);
289 didPrint = true;
290 }
291 resp_buf_read_one(true);
292 }
293}
294
295static bool ble_init(void) {
296 state.initialized = false;
297 state.configured = false;
298 state.is_connected = false;
299
300 setPinInput(AdafruitBleIRQPin);
301
302 spi_init();
303
304 // Perform a hardware reset
305 setPinOutput(AdafruitBleResetPin);
306 writePinHigh(AdafruitBleResetPin);
307 writePinLow(AdafruitBleResetPin);
308 wait_ms(10);
309 writePinHigh(AdafruitBleResetPin);
310
311 wait_ms(1000); // Give it a second to initialize
312
313 state.initialized = true;
314 return state.initialized;
315}
316
317static inline uint8_t min(uint8_t a, uint8_t b) { return a < b ? a : b; }
318
319static bool read_response(char *resp, uint16_t resplen, bool verbose) {
320 char *dest = resp;
321 char *end = dest + resplen;
322
323 while (true) {
324 struct sdep_msg msg;
325
326 if (!sdep_recv_pkt(&msg, 2 * SdepTimeout)) {
327 dprint("sdep_recv_pkt failed\n");
328 return false;
329 }
330
331 if (msg.type != SdepResponse) {
332 *resp = 0;
333 return false;
334 }
335
336 uint8_t len = min(msg.len, end - dest);
337 if (len > 0) {
338 memcpy(dest, msg.payload, len);
339 dest += len;
340 }
341
342 if (!msg.more) {
343 // No more data is expected!
344 break;
345 }
346 }
347
348 // Ensure the response is NUL terminated
349 *dest = 0;
350
351 // "Parse" the result text; we want to snip off the trailing OK or ERROR line
352 // Rewind past the possible trailing CRLF so that we can strip it
353 --dest;
354 while (dest > resp && (dest[0] == '\n' || dest[0] == '\r')) {
355 *dest = 0;
356 --dest;
357 }
358
359 // Look back for start of preceeding line
360 char *last_line = strrchr(resp, '\n');
361 if (last_line) {
362 ++last_line;
363 } else {
364 last_line = resp;
365 }
366
367 bool success = false;
368 static const char kOK[] PROGMEM = "OK";
369
370 success = !strcmp_P(last_line, kOK);
371
372 if (verbose || !success) {
373 dprintf("result: %s\n", resp);
374 }
375 return success;
376}
377
378static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout) {
379 const char * end = cmd + strlen(cmd);
380 struct sdep_msg msg;
381
382 if (verbose) {
383 dprintf("ble send: %s\n", cmd);
384 }
385
386 if (resp) {
387 // They want to decode the response, so we need to flush and wait
388 // for all pending I/O to finish before we start this one, so
389 // that we don't confuse the results
390 resp_buf_wait(cmd);
391 *resp = 0;
392 }
393
394 // Fragment the command into a series of SDEP packets
395 while (end - cmd > SdepMaxPayload) {
396 sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, SdepMaxPayload, true);
397 if (!sdep_send_pkt(&msg, timeout)) {
398 return false;
399 }
400 cmd += SdepMaxPayload;
401 }
402
403 sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, end - cmd, false);
404 if (!sdep_send_pkt(&msg, timeout)) {
405 return false;
406 }
407
408 if (resp == NULL) {
409 uint16_t now = timer_read();
410 while (!resp_buf.enqueue(now)) {
411 resp_buf_read_one(false);
412 }
413 uint16_t later = timer_read();
414 if (TIMER_DIFF_16(later, now) > 0) {
415 dprintf("waited %dms for resp_buf\n", TIMER_DIFF_16(later, now));
416 }
417 return true;
418 }
419
420 return read_response(resp, resplen, verbose);
421}
422
423bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose) {
424 char *cmdbuf = (char *)alloca(strlen_P(cmd) + 1);
425 strcpy_P(cmdbuf, cmd);
426 return at_command(cmdbuf, resp, resplen, verbose);
427}
428
429bool adafruit_ble_is_connected(void) { return state.is_connected; }
430
431bool adafruit_ble_enable_keyboard(void) {
432 char resbuf[128];
433
434 if (!state.initialized && !ble_init()) {
435 return false;
436 }
437
438 state.configured = false;
439
440 // Disable command echo
441 static const char kEcho[] PROGMEM = "ATE=0";
442 // Make the advertised name match the keyboard
443 static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT);
444 // Turn on keyboard support
445 static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1";
446
447 // Adjust intervals to improve latency. This causes the "central"
448 // system (computer/tablet) to poll us every 10-30 ms. We can't
449 // set a smaller value than 10ms, and 30ms seems to be the natural
450 // processing time on my macbook. Keeping it constrained to that
451 // feels reasonable to type to.
452 static const char kGapIntervals[] PROGMEM = "AT+GAPINTERVALS=10,30,,";
453
454 // Reset the device so that it picks up the above changes
455 static const char kATZ[] PROGMEM = "ATZ";
456
457 // Turn down the power level a bit
458 static const char kPower[] PROGMEM = "AT+BLEPOWERLEVEL=-12";
459 static PGM_P const configure_commands[] PROGMEM = {
460 kEcho, kGapIntervals, kGapDevName, kHidEnOn, kPower, kATZ,
461 };
462
463 uint8_t i;
464 for (i = 0; i < sizeof(configure_commands) / sizeof(configure_commands[0]); ++i) {
465 PGM_P cmd;
466 memcpy_P(&cmd, configure_commands + i, sizeof(cmd));
467
468 if (!at_command_P(cmd, resbuf, sizeof(resbuf))) {
469 dprintf("failed BLE command: %S: %s\n", cmd, resbuf);
470 goto fail;
471 }
472 }
473
474 state.configured = true;
475
476 // Check connection status in a little while; allow the ATZ time
477 // to kick in.
478 state.last_connection_update = timer_read();
479fail:
480 return state.configured;
481}
482
483static void set_connected(bool connected) {
484 if (connected != state.is_connected) {
485 if (connected) {
486 dprint("BLE connected\n");
487 } else {
488 dprint("BLE disconnected\n");
489 }
490 state.is_connected = connected;
491
492 // TODO: if modifiers are down on the USB interface and
493 // we cut over to BLE or vice versa, they will remain stuck.
494 // This feels like a good point to do something like clearing
495 // the keyboard and/or generating a fake all keys up message.
496 // However, I've noticed that it takes a couple of seconds
497 // for macOS to to start recognizing key presses after BLE
498 // is in the connected state, so I worry that doing that
499 // here may not be good enough.
500 }
501}
502
503void adafruit_ble_task(void) {
504 char resbuf[48];
505
506 if (!state.configured && !adafruit_ble_enable_keyboard()) {
507 return;
508 }
509 resp_buf_read_one(true);
510 send_buf_send_one(SdepShortTimeout);
511
512 if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(AdafruitBleIRQPin)) {
513 // Must be an event update
514 if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) {
515 uint32_t mask = strtoul(resbuf, NULL, 16);
516
517 if (mask & BleSystemConnected) {
518 set_connected(true);
519 } else if (mask & BleSystemDisconnected) {
520 set_connected(false);
521 }
522 }
523 }
524
525 if (timer_elapsed(state.last_connection_update) > ConnectionUpdateInterval) {
526 bool shouldPoll = true;
527 if (!(state.event_flags & ProbedEvents)) {
528 // Request notifications about connection status changes.
529 // This only works in SPIFRIEND firmware > 0.6.7, which is why
530 // we check for this conditionally here.
531 // Note that at the time of writing, HID reports only work correctly
532 // with Apple products on firmware version 0.6.7!
533 // https://forums.adafruit.com/viewtopic.php?f=8&t=104052
534 if (at_command_P(PSTR("AT+EVENTENABLE=0x1"), resbuf, sizeof(resbuf))) {
535 at_command_P(PSTR("AT+EVENTENABLE=0x2"), resbuf, sizeof(resbuf));
536 state.event_flags |= UsingEvents;
537 }
538 state.event_flags |= ProbedEvents;
539
540 // leave shouldPoll == true so that we check at least once
541 // before relying solely on events
542 } else {
543 shouldPoll = false;
544 }
545
546 static const char kGetConn[] PROGMEM = "AT+GAPGETCONN";
547 state.last_connection_update = timer_read();
548
549 if (at_command_P(kGetConn, resbuf, sizeof(resbuf))) {
550 set_connected(atoi(resbuf));
551 }
552 }
553
554#ifdef SAMPLE_BATTERY
555 if (timer_elapsed(state.last_battery_update) > BatteryUpdateInterval && resp_buf.empty()) {
556 state.last_battery_update = timer_read();
557
558 state.vbat = analogReadPin(BATTERY_LEVEL_PIN);
559 }
560#endif
561}
562
563static bool process_queue_item(struct queue_item *item, uint16_t timeout) {
564 char cmdbuf[48];
565 char fmtbuf[64];
566
567 // Arrange to re-check connection after keys have settled
568 state.last_connection_update = timer_read();
569
570#if 1
571 if (TIMER_DIFF_16(state.last_connection_update, item->added) > 0) {
572 dprintf("send latency %dms\n", TIMER_DIFF_16(state.last_connection_update, item->added));
573 }
574#endif
575
576 switch (item->queue_type) {
577 case QTKeyReport:
578 strcpy_P(fmtbuf, PSTR("AT+BLEKEYBOARDCODE=%02x-00-%02x-%02x-%02x-%02x-%02x-%02x"));
579 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]);
580 return at_command(cmdbuf, NULL, 0, true, timeout);
581
582 case QTConsumer:
583 strcpy_P(fmtbuf, PSTR("AT+BLEHIDCONTROLKEY=0x%04x"));
584 snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->consumer);
585 return at_command(cmdbuf, NULL, 0, true, timeout);
586
587#ifdef MOUSE_ENABLE
588 case QTMouseMove:
589 strcpy_P(fmtbuf, PSTR("AT+BLEHIDMOUSEMOVE=%d,%d,%d,%d"));
590 snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->mousemove.x, item->mousemove.y, item->mousemove.scroll, item->mousemove.pan);
591 if (!at_command(cmdbuf, NULL, 0, true, timeout)) {
592 return false;
593 }
594 strcpy_P(cmdbuf, PSTR("AT+BLEHIDMOUSEBUTTON="));
595 if (item->mousemove.buttons & MOUSE_BTN1) {
596 strcat(cmdbuf, "L");
597 }
598 if (item->mousemove.buttons & MOUSE_BTN2) {
599 strcat(cmdbuf, "R");
600 }
601 if (item->mousemove.buttons & MOUSE_BTN3) {
602 strcat(cmdbuf, "M");
603 }
604 if (item->mousemove.buttons == 0) {
605 strcat(cmdbuf, "0");
606 }
607 return at_command(cmdbuf, NULL, 0, true, timeout);
608#endif
609 default:
610 return true;
611 }
612}
613
614void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) {
615 struct queue_item item;
616 bool didWait = false;
617
618 item.queue_type = QTKeyReport;
619 item.key.modifier = hid_modifier_mask;
620 item.added = timer_read();
621
622 while (nkeys >= 0) {
623 item.key.keys[0] = keys[0];
624 item.key.keys[1] = nkeys >= 1 ? keys[1] : 0;
625 item.key.keys[2] = nkeys >= 2 ? keys[2] : 0;
626 item.key.keys[3] = nkeys >= 3 ? keys[3] : 0;
627 item.key.keys[4] = nkeys >= 4 ? keys[4] : 0;
628 item.key.keys[5] = nkeys >= 5 ? keys[5] : 0;
629
630 if (!send_buf.enqueue(item)) {
631 if (!didWait) {
632 dprint("wait for buf space\n");
633 didWait = true;
634 }
635 send_buf_send_one();
636 continue;
637 }
638
639 if (nkeys <= 6) {
640 return;
641 }
642
643 nkeys -= 6;
644 keys += 6;
645 }
646}
647
648void adafruit_ble_send_consumer_key(uint16_t usage) {
649 struct queue_item item;
650
651 item.queue_type = QTConsumer;
652 item.consumer = usage;
653
654 while (!send_buf.enqueue(item)) {
655 send_buf_send_one();
656 }
657}
658
659#ifdef MOUSE_ENABLE
660void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) {
661 struct queue_item item;
662
663 item.queue_type = QTMouseMove;
664 item.mousemove.x = x;
665 item.mousemove.y = y;
666 item.mousemove.scroll = scroll;
667 item.mousemove.pan = pan;
668 item.mousemove.buttons = buttons;
669
670 while (!send_buf.enqueue(item)) {
671 send_buf_send_one();
672 }
673}
674#endif
675
676uint32_t adafruit_ble_read_battery_voltage(void) { return state.vbat; }
677
678bool adafruit_ble_set_mode_leds(bool on) {
679 if (!state.configured) {
680 return false;
681 }
682
683 // The "mode" led is the red blinky one
684 at_command_P(on ? PSTR("AT+HWMODELED=1") : PSTR("AT+HWMODELED=0"), NULL, 0);
685
686 // Pin 19 is the blue "connected" LED; turn that off too.
687 // When turning LEDs back on, don't turn that LED on if we're
688 // not connected, as that would be confusing.
689 at_command_P(on && state.is_connected ? PSTR("AT+HWGPIO=19,1") : PSTR("AT+HWGPIO=19,0"), NULL, 0);
690 return true;
691}
692
693// https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel
694bool adafruit_ble_set_power_level(int8_t level) {
695 char cmd[46];
696 if (!state.configured) {
697 return false;
698 }
699 snprintf(cmd, sizeof(cmd), "AT+BLEPOWERLEVEL=%d", level);
700 return at_command(cmd, NULL, 0, false);
701}
diff --git a/tmk_core/protocol/lufa/adafruit_ble.h b/tmk_core/protocol/lufa/adafruit_ble.h
deleted file mode 100644
index b43e0771d..000000000
--- a/tmk_core/protocol/lufa/adafruit_ble.h
+++ /dev/null
@@ -1,59 +0,0 @@
1/* Bluetooth Low Energy Protocol for QMK.
2 * Author: Wez Furlong, 2016
3 * Supports the Adafruit BLE board built around the nRF51822 chip.
4 */
5
6#pragma once
7
8#include <stdbool.h>
9#include <stdint.h>
10#include <string.h>
11
12#include "config_common.h"
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
18/* Instruct the module to enable HID keyboard support and reset */
19extern bool adafruit_ble_enable_keyboard(void);
20
21/* Query to see if the BLE module is connected */
22extern bool adafruit_ble_query_is_connected(void);
23
24/* Returns true if we believe that the BLE module is connected.
25 * This uses our cached understanding that is maintained by
26 * calling ble_task() periodically. */
27extern bool adafruit_ble_is_connected(void);
28
29/* Call this periodically to process BLE-originated things */
30extern void adafruit_ble_task(void);
31
32/* Generates keypress events for a set of keys.
33 * The hid modifier mask specifies the state of the modifier keys for
34 * this set of keys.
35 * Also sends a key release indicator, so that the keys do not remain
36 * held down. */
37extern void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys);
38
39/* Send a consumer usage.
40 * (milliseconds) */
41extern void adafruit_ble_send_consumer_key(uint16_t usage);
42
43#ifdef MOUSE_ENABLE
44/* Send a mouse/wheel movement report.
45 * The parameters are signed and indicate positive or negative direction
46 * change. */
47extern void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons);
48#endif
49
50/* Compute battery voltage by reading an analog pin.
51 * Returns the integer number of millivolts */
52extern uint32_t adafruit_ble_read_battery_voltage(void);
53
54extern bool adafruit_ble_set_mode_leds(bool on);
55extern bool adafruit_ble_set_power_level(int8_t level);
56
57#ifdef __cplusplus
58}
59#endif
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 5b56e8a03..753762358 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -52,6 +52,7 @@
52#include "usb_descriptor.h" 52#include "usb_descriptor.h"
53#include "lufa.h" 53#include "lufa.h"
54#include "quantum.h" 54#include "quantum.h"
55#include "usb_device_state.h"
55#include <util/atomic.h> 56#include <util/atomic.h>
56 57
57#ifdef NKRO_ENABLE 58#ifdef NKRO_ENABLE
@@ -142,7 +143,8 @@ static void send_keyboard(report_keyboard_t *report);
142static void send_mouse(report_mouse_t *report); 143static void send_mouse(report_mouse_t *report);
143static void send_system(uint16_t data); 144static void send_system(uint16_t data);
144static void send_consumer(uint16_t data); 145static void send_consumer(uint16_t data);
145host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; 146static void send_programmable_button(uint32_t data);
147host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};
146 148
147#ifdef VIRTSER_ENABLE 149#ifdef VIRTSER_ENABLE
148// clang-format off 150// clang-format off
@@ -413,7 +415,10 @@ void EVENT_USB_Device_Disconnect(void) {
413 * 415 *
414 * FIXME: Needs doc 416 * FIXME: Needs doc
415 */ 417 */
416void EVENT_USB_Device_Reset(void) { print("[R]"); } 418void EVENT_USB_Device_Reset(void) {
419 print("[R]");
420 usb_device_state_set_reset();
421}
417 422
418/** \brief Event USB Device Connect 423/** \brief Event USB Device Connect
419 * 424 *
@@ -421,6 +426,8 @@ void EVENT_USB_Device_Reset(void) { print("[R]"); }
421 */ 426 */
422void EVENT_USB_Device_Suspend() { 427void EVENT_USB_Device_Suspend() {
423 print("[S]"); 428 print("[S]");
429 usb_device_state_set_suspend(USB_Device_ConfigurationNumber != 0, USB_Device_ConfigurationNumber);
430
424#ifdef SLEEP_LED_ENABLE 431#ifdef SLEEP_LED_ENABLE
425 sleep_led_enable(); 432 sleep_led_enable();
426#endif 433#endif
@@ -436,6 +443,8 @@ void EVENT_USB_Device_WakeUp() {
436 suspend_wakeup_init(); 443 suspend_wakeup_init();
437#endif 444#endif
438 445
446 usb_device_state_set_resume(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber);
447
439#ifdef SLEEP_LED_ENABLE 448#ifdef SLEEP_LED_ENABLE
440 sleep_led_disable(); 449 sleep_led_disable();
441 // NOTE: converters may not accept this 450 // NOTE: converters may not accept this
@@ -528,6 +537,8 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
528 /* Setup digitizer endpoint */ 537 /* Setup digitizer endpoint */
529 ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1); 538 ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1);
530#endif 539#endif
540
541 usb_device_state_set_configuration(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber);
531} 542}
532 543
533/* FIXME: Expose this table in the docs somehow 544/* FIXME: Expose this table in the docs somehow
@@ -760,29 +771,35 @@ static void send_mouse(report_mouse_t *report) {
760#endif 771#endif
761} 772}
762 773
763/** \brief Send Extra 774#if defined(EXTRAKEY_ENABLE) || defined(PROGRAMMABLE_BUTTON_ENABLE)
764 * 775static void send_report(void *report, size_t size) {
765 * FIXME: Needs doc
766 */
767#ifdef EXTRAKEY_ENABLE
768static void send_extra(uint8_t report_id, uint16_t data) {
769 uint8_t timeout = 255; 776 uint8_t timeout = 255;
770 777
771 if (USB_DeviceState != DEVICE_STATE_Configured) return; 778 if (USB_DeviceState != DEVICE_STATE_Configured) return;
772 779
773 static report_extra_t r;
774 r = (report_extra_t){.report_id = report_id, .usage = data};
775 Endpoint_SelectEndpoint(SHARED_IN_EPNUM); 780 Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
776 781
777 /* Check if write ready for a polling interval around 10ms */ 782 /* Check if write ready for a polling interval around 10ms */
778 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); 783 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
779 if (!Endpoint_IsReadWriteAllowed()) return; 784 if (!Endpoint_IsReadWriteAllowed()) return;
780 785
781 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); 786 Endpoint_Write_Stream_LE(report, size, NULL);
782 Endpoint_ClearIN(); 787 Endpoint_ClearIN();
783} 788}
784#endif 789#endif
785 790
791/** \brief Send Extra
792 *
793 * FIXME: Needs doc
794 */
795#ifdef EXTRAKEY_ENABLE
796static void send_extra(uint8_t report_id, uint16_t data) {
797 static report_extra_t r;
798 r = (report_extra_t){.report_id = report_id, .usage = data};
799 send_report(&r, sizeof(r));
800}
801#endif
802
786/** \brief Send System 803/** \brief Send System
787 * 804 *
788 * FIXME: Needs doc 805 * FIXME: Needs doc
@@ -822,6 +839,14 @@ static void send_consumer(uint16_t data) {
822#endif 839#endif
823} 840}
824 841
842static void send_programmable_button(uint32_t data) {
843#ifdef PROGRAMMABLE_BUTTON_ENABLE
844 static report_programmable_button_t r;
845 r = (report_programmable_button_t){.report_id = REPORT_ID_PROGRAMMABLE_BUTTON, .usage = data};
846 send_report(&r, sizeof(r));
847#endif
848}
849
825/******************************************************************************* 850/*******************************************************************************
826 * sendchar 851 * sendchar
827 ******************************************************************************/ 852 ******************************************************************************/
@@ -1044,6 +1069,7 @@ void protocol_setup(void) {
1044#endif 1069#endif
1045 1070
1046 setup_mcu(); 1071 setup_mcu();
1072 usb_device_state_init();
1047 keyboard_setup(); 1073 keyboard_setup();
1048} 1074}
1049 1075
diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h
index 348a84c03..6a5205609 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;
56#ifdef __cplusplus 56#ifdef __cplusplus
57} 57}
58#endif 58#endif
59
60#ifdef API_ENABLE
61# include "api.h"
62#endif
63
64#ifdef API_SYSEX_ENABLE
65# include "api_sysex.h"
66// Allocate space for encoding overhead.
67// The header and terminator are not stored to save a few bytes of precious ram
68# define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0))
69#endif
diff --git a/tmk_core/protocol/lufa/outputselect.c b/tmk_core/protocol/lufa/outputselect.c
deleted file mode 100644
index f758c6528..000000000
--- a/tmk_core/protocol/lufa/outputselect.c
+++ /dev/null
@@ -1,79 +0,0 @@
1/*
2Copyright 2017 Priyadi Iman Nurcahyo
3This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or
6(at your option) any later version.
7This program is distributed in the hope that it will be useful,
8but WITHOUT ANY WARRANTY; without even the implied warranty of
9MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10GNU General Public License for more details.
11You should have received a copy of the GNU General Public License
12along with this program. If not, see <http://www.gnu.org/licenses/>.
13*/
14
15#include "outputselect.h"
16
17#if defined(PROTOCOL_LUFA)
18# include "lufa.h"
19#endif
20
21#ifdef MODULE_ADAFRUIT_BLE
22# include "adafruit_ble.h"
23#endif
24
25uint8_t desired_output = OUTPUT_DEFAULT;
26
27/** \brief Set Output
28 *
29 * FIXME: Needs doc
30 */
31void set_output(uint8_t output) {
32 set_output_user(output);
33 desired_output = output;
34}
35
36/** \brief Set Output User
37 *
38 * FIXME: Needs doc
39 */
40__attribute__((weak)) void set_output_user(uint8_t output) {}
41
42static bool is_usb_configured(void) {
43#if defined(PROTOCOL_LUFA)
44 return USB_DeviceState == DEVICE_STATE_Configured;
45#endif
46}
47
48/** \brief Auto Detect Output
49 *
50 * FIXME: Needs doc
51 */
52uint8_t auto_detect_output(void) {
53 if (is_usb_configured()) {
54 return OUTPUT_USB;
55 }
56
57#ifdef MODULE_ADAFRUIT_BLE
58 if (adafruit_ble_is_connected()) {
59 return OUTPUT_BLUETOOTH;
60 }
61#endif
62
63#ifdef BLUETOOTH_ENABLE
64 return OUTPUT_BLUETOOTH; // should check if BT is connected here
65#endif
66
67 return OUTPUT_NONE;
68}
69
70/** \brief Where To Send
71 *
72 * FIXME: Needs doc
73 */
74uint8_t where_to_send(void) {
75 if (desired_output == OUTPUT_AUTO) {
76 return auto_detect_output();
77 }
78 return desired_output;
79}
diff --git a/tmk_core/protocol/lufa/outputselect.h b/tmk_core/protocol/lufa/outputselect.h
deleted file mode 100644
index c4548e112..000000000
--- a/tmk_core/protocol/lufa/outputselect.h
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2Copyright 2017 Priyadi Iman Nurcahyo
3This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or
6(at your option) any later version.
7This program is distributed in the hope that it will be useful,
8but WITHOUT ANY WARRANTY; without even the implied warranty of
9MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10GNU General Public License for more details.
11You should have received a copy of the GNU General Public License
12along with this program. If not, see <http://www.gnu.org/licenses/>.
13*/
14
15#pragma once
16
17#include <stdint.h>
18
19enum outputs {
20 OUTPUT_AUTO,
21
22 OUTPUT_NONE,
23 OUTPUT_USB,
24 OUTPUT_BLUETOOTH
25};
26
27#ifndef OUTPUT_DEFAULT
28# define OUTPUT_DEFAULT OUTPUT_AUTO
29#endif
30
31void set_output(uint8_t output);
32void set_output_user(uint8_t output);
33uint8_t auto_detect_output(void);
34uint8_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 70a3c4881..000000000
--- a/tmk_core/protocol/lufa/ringbuffer.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
1#pragma once
2// A simple ringbuffer holding Size elements of type T
3template <typename T, uint8_t Size>
4class RingBuffer {
5 protected:
6 T buf_[Size];
7 uint8_t head_{0}, tail_{0};
8 public:
9 inline uint8_t nextPosition(uint8_t position) {
10 return (position + 1) % Size;
11 }
12
13 inline uint8_t prevPosition(uint8_t position) {
14 if (position == 0) {
15 return Size - 1;
16 }
17 return position - 1;
18 }
19
20 inline bool enqueue(const T &item) {
21 static_assert(Size > 1, "RingBuffer size must be > 1");
22 uint8_t next = nextPosition(head_);
23 if (next == tail_) {
24 // Full
25 return false;
26 }
27
28 buf_[head_] = item;
29 head_ = next;
30 return true;
31 }
32
33 inline bool get(T &dest, bool commit = true) {
34 auto tail = tail_;
35 if (tail == head_) {
36 // No more data
37 return false;
38 }
39
40 dest = buf_[tail];
41 tail = nextPosition(tail);
42
43 if (commit) {
44 tail_ = tail;
45 }
46 return true;
47 }
48
49 inline bool empty() const { return head_ == tail_; }
50
51 inline uint8_t size() const {
52 int diff = head_ - tail_;
53 if (diff >= 0) {
54 return diff;
55 }
56 return Size + diff;
57 }
58
59 inline T& front() {
60 return buf_[tail_];
61 }
62
63 inline bool peek(T &item) {
64 return get(item, false);
65 }
66};
diff --git a/tmk_core/protocol/m0110.c b/tmk_core/protocol/m0110.c
deleted file mode 100644
index 64f2fa50a..000000000
--- a/tmk_core/protocol/m0110.c
+++ /dev/null
@@ -1,583 +0,0 @@
1/*
2Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37/* M0110A Support was contributed by skagon@github */
38
39#include <stdbool.h>
40#include <avr/io.h>
41#include <avr/interrupt.h>
42#include <util/delay.h>
43#include "m0110.h"
44#include "debug.h"
45
46static inline uint8_t raw2scan(uint8_t raw);
47static inline uint8_t inquiry(void);
48static inline uint8_t instant(void);
49static inline void clock_lo(void);
50static inline void clock_hi(void);
51static inline bool clock_in(void);
52static inline void data_lo(void);
53static inline void data_hi(void);
54static inline bool data_in(void);
55static inline uint16_t wait_clock_lo(uint16_t us);
56static inline uint16_t wait_clock_hi(uint16_t us);
57static inline uint16_t wait_data_lo(uint16_t us);
58static inline uint16_t wait_data_hi(uint16_t us);
59static inline void idle(void);
60static inline void request(void);
61
62#define WAIT_US(stat, us, err) \
63 do { \
64 if (!wait_##stat(us)) { \
65 m0110_error = err; \
66 goto ERROR; \
67 } \
68 } while (0)
69
70#define WAIT_MS(stat, ms, err) \
71 do { \
72 uint16_t _ms = ms; \
73 while (_ms) { \
74 if (wait_##stat(1000)) { \
75 break; \
76 } \
77 _ms--; \
78 } \
79 if (_ms == 0) { \
80 m0110_error = err; \
81 goto ERROR; \
82 } \
83 } while (0)
84
85#define KEY(raw) ((raw)&0x7f)
86#define IS_BREAK(raw) (((raw)&0x80) == 0x80)
87
88uint8_t m0110_error = 0;
89
90void m0110_init(void) {
91 idle();
92 _delay_ms(1000);
93
94 /* Not needed to initialize in fact.
95 uint8_t data;
96 m0110_send(M0110_MODEL);
97 data = m0110_recv();
98 print("m0110_init model: "); print_hex8(data); print("\n");
99
100 m0110_send(M0110_TEST);
101 data = m0110_recv();
102 print("m0110_init test: "); print_hex8(data); print("\n");
103 */
104}
105
106uint8_t m0110_send(uint8_t data) {
107 m0110_error = 0;
108
109 request();
110 WAIT_MS(clock_lo, 250, 1); // keyboard may block long time
111 for (uint8_t bit = 0x80; bit; bit >>= 1) {
112 WAIT_US(clock_lo, 250, 3);
113 if (data & bit) {
114 data_hi();
115 } else {
116 data_lo();
117 }
118 WAIT_US(clock_hi, 200, 4);
119 }
120 _delay_us(100); // hold last bit for 80us
121 idle();
122 return 1;
123ERROR:
124 print("m0110_send err: ");
125 print_hex8(m0110_error);
126 print("\n");
127 _delay_ms(500);
128 idle();
129 return 0;
130}
131
132uint8_t m0110_recv(void) {
133 uint8_t data = 0;
134 m0110_error = 0;
135
136 WAIT_MS(clock_lo, 250, 1); // keyboard may block long time
137 for (uint8_t i = 0; i < 8; i++) {
138 data <<= 1;
139 WAIT_US(clock_lo, 200, 2);
140 WAIT_US(clock_hi, 200, 3);
141 if (data_in()) {
142 data |= 1;
143 }
144 }
145 idle();
146 return data;
147ERROR:
148 print("m0110_recv err: ");
149 print_hex8(m0110_error);
150 print("\n");
151 _delay_ms(500);
152 idle();
153 return 0xFF;
154}
155
156/*
157Handling for exceptional case of key combinations for M0110A
158
159Shift and Calc/Arrow key could be operated simultaneously:
160
161 Case Shift Arrow Events Interpret
162 -------------------------------------------------------------------
163 1 Down Down 71, 79, DD Calc(d)*a *b
164 2 Down Up 71, 79, UU Arrow&Calc(u)*a
165 3 Up Down F1, 79, DD Shift(u) *c
166 4 Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
167
168 Case Shift Calc Events Interpret
169 -------------------------------------------------------------------
170 5(1) Down Down 71, 71, 79, DD Shift(d) and Cacl(d)
171 6(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a
172 7(1) Up Down F1, 71, 79, DD Shift(u) and Calc(d)
173 8(4) Up Up F1, F1, 79, UU Shift(ux2) and Arrow&Calc(u)*a
174
175During Calc key is hold:
176 Case Shift Arrow Events Interpret
177 -------------------------------------------------------------------
178 A(3) ---- Down F1, 79, DD Shift(u) *c
179 B ---- Up 79, UU Arrow&Calc(u)*a
180 C Down ---- F1, 71 Shift(u) and Shift(d)
181 D Up ---- F1 Shift(u)
182 E Hold Down 79, DD Normal
183 F Hold Up 79, UU Arrow&Calc(u)*a
184 G(1) Down Down F1, 71, 79, DD Shift(u)*b and Calc(d)*a
185 H(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a
186 I(3) Up Down F1, F1, 79, DD Shift(ux2) *c
187 J(4) Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
188
189 Case Shift Calc Events Interpret
190 -------------------------------------------------------------------
191 K(1) ---- Down 71, 79, DD Calc(d)*a
192 L(4) ---- Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
193 M(1) Hold Down 71, 79, DD Calc(d)*a
194 N Hold Up 79, UU Arrow&Calc(u)*a
195
196 Where DD/UU indicates part of Keypad Down/Up event.
197 *a: Impossible to distinguish btween Arrow and Calc event.
198 *b: Shift(d) event is ignored.
199 *c: Arrow/Calc(d) event is ignored.
200*/
201uint8_t m0110_recv_key(void) {
202 static uint8_t keybuf = 0x00;
203 static uint8_t keybuf2 = 0x00;
204 static uint8_t rawbuf = 0x00;
205 uint8_t raw, raw2, raw3;
206
207 if (keybuf) {
208 raw = keybuf;
209 keybuf = 0x00;
210 return raw;
211 }
212 if (keybuf2) {
213 raw = keybuf2;
214 keybuf2 = 0x00;
215 return raw;
216 }
217
218 if (rawbuf) {
219 raw = rawbuf;
220 rawbuf = 0x00;
221 } else {
222 raw = instant(); // Use INSTANT for better response. Should be INQUIRY ?
223 }
224 switch (KEY(raw)) {
225 case M0110_KEYPAD:
226 raw2 = instant();
227 switch (KEY(raw2)) {
228 case M0110_ARROW_UP:
229 case M0110_ARROW_DOWN:
230 case M0110_ARROW_LEFT:
231 case M0110_ARROW_RIGHT:
232 if (IS_BREAK(raw2)) {
233 // Case B,F,N:
234 keybuf = (raw2scan(raw2) | M0110_CALC_OFFSET); // Calc(u)
235 return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); // Arrow(u)
236 }
237 break;
238 }
239 // Keypad or Arrow
240 return (raw2scan(raw2) | M0110_KEYPAD_OFFSET);
241 break;
242 case M0110_SHIFT:
243 raw2 = instant();
244 switch (KEY(raw2)) {
245 case M0110_SHIFT:
246 // Case: 5-8,C,G,H
247 rawbuf = raw2;
248 return raw2scan(raw); // Shift(d/u)
249 break;
250 case M0110_KEYPAD:
251 // Shift + Arrow, Calc, or etc.
252 raw3 = instant();
253 switch (KEY(raw3)) {
254 case M0110_ARROW_UP:
255 case M0110_ARROW_DOWN:
256 case M0110_ARROW_LEFT:
257 case M0110_ARROW_RIGHT:
258 if (IS_BREAK(raw)) {
259 if (IS_BREAK(raw3)) {
260 // Case 4:
261 print("(4)\n");
262 keybuf2 = raw2scan(raw); // Shift(u)
263 keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u)
264 return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u)
265 } else {
266 // Case 3:
267 print("(3)\n");
268 return (raw2scan(raw)); // Shift(u)
269 }
270 } else {
271 if (IS_BREAK(raw3)) {
272 // Case 2:
273 print("(2)\n");
274 keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u)
275 return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u)
276 } else {
277 // Case 1:
278 print("(1)\n");
279 return (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(d)
280 }
281 }
282 break;
283 default:
284 // Shift + Keypad
285 keybuf = (raw2scan(raw3) | M0110_KEYPAD_OFFSET);
286 return raw2scan(raw); // Shift(d/u)
287 break;
288 }
289 break;
290 default:
291 // Shift + Normal keys
292 keybuf = raw2scan(raw2);
293 return raw2scan(raw); // Shift(d/u)
294 break;
295 }
296 break;
297 default:
298 // Normal keys
299 return raw2scan(raw);
300 break;
301 }
302}
303
304static inline uint8_t raw2scan(uint8_t raw) { return (raw == M0110_NULL) ? M0110_NULL : ((raw == M0110_ERROR) ? M0110_ERROR : (((raw & 0x80) | ((raw & 0x7F) >> 1)))); }
305
306static inline uint8_t inquiry(void) {
307 m0110_send(M0110_INQUIRY);
308 return m0110_recv();
309}
310
311static inline uint8_t instant(void) {
312 m0110_send(M0110_INSTANT);
313 uint8_t data = m0110_recv();
314 if (data != M0110_NULL) {
315 debug_hex(data);
316 debug(" ");
317 }
318 return data;
319}
320
321static inline void clock_lo() {
322 M0110_CLOCK_PORT &= ~(1 << M0110_CLOCK_BIT);
323 M0110_CLOCK_DDR |= (1 << M0110_CLOCK_BIT);
324}
325static inline void clock_hi() {
326 /* input with pull up */
327 M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT);
328 M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT);
329}
330static inline bool clock_in() {
331 M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT);
332 M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT);
333 _delay_us(1);
334 return M0110_CLOCK_PIN & (1 << M0110_CLOCK_BIT);
335}
336static inline void data_lo() {
337 M0110_DATA_PORT &= ~(1 << M0110_DATA_BIT);
338 M0110_DATA_DDR |= (1 << M0110_DATA_BIT);
339}
340static inline void data_hi() {
341 /* input with pull up */
342 M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT);
343 M0110_DATA_PORT |= (1 << M0110_DATA_BIT);
344}
345static inline bool data_in() {
346 M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT);
347 M0110_DATA_PORT |= (1 << M0110_DATA_BIT);
348 _delay_us(1);
349 return M0110_DATA_PIN & (1 << M0110_DATA_BIT);
350}
351
352static inline uint16_t wait_clock_lo(uint16_t us) {
353 while (clock_in() && us) {
354 asm("");
355 _delay_us(1);
356 us--;
357 }
358 return us;
359}
360static inline uint16_t wait_clock_hi(uint16_t us) {
361 while (!clock_in() && us) {
362 asm("");
363 _delay_us(1);
364 us--;
365 }
366 return us;
367}
368static inline uint16_t wait_data_lo(uint16_t us) {
369 while (data_in() && us) {
370 asm("");
371 _delay_us(1);
372 us--;
373 }
374 return us;
375}
376static inline uint16_t wait_data_hi(uint16_t us) {
377 while (!data_in() && us) {
378 asm("");
379 _delay_us(1);
380 us--;
381 }
382 return us;
383}
384
385static inline void idle(void) {
386 clock_hi();
387 data_hi();
388}
389
390static inline void request(void) {
391 clock_hi();
392 data_lo();
393}
394
395/*
396Primitive M0110 Library for AVR
397==============================
398
399
400Signaling
401---------
402CLOCK is always from KEYBOARD. DATA are sent with MSB first.
403
4041) IDLE: both lines are high.
405 CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
406 DATA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
407
4082) KEYBOARD->HOST: HOST reads bit on rising edge.
409 CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
410 DATA ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
411 <--> 160us(clock low)
412 <---> 180us(clock high)
413
4143) HOST->KEYBOARD: HOST asserts bit on falling edge.
415 CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
416 DATA ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
417 <----> 840us(request to send by host) <---> 80us(hold DATA)
418 <--> 180us(clock low)
419 <---> 220us(clock high)
420
421
422Protocol
423--------
424COMMAND:
425 Inquiry 0x10 get key event with block
426 Instant 0x12 get key event
427 Model 0x14 get model number(M0110 responds with 0x09)
428 bit 7 1 if another device connected(used when keypad exists?)
429 bit4-6 next device model number
430 bit1-3 keyboard model number
431 bit 0 always 1
432 Test 0x16 test(ACK:0x7D/NAK:0x77)
433
434KEY EVENT:
435 bit 7 key state(0:press 1:release)
436 bit 6-1 scan code(see below)
437 bit 0 always 1
438 To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1).
439
440 Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79.
441 Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release.
442
443ARROW KEYS:
444 Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of
445 Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation,
446 it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases.
447
448 Raw key events:
449 press release
450 ---------------- ----------------
451 Left: 0x79, 0x0D 0x79, 0x8D
452 Right: 0x79, 0x05 0x79, 0x85
453 Up: 0x79, 0x1B 0x79, 0x9B
454 Down: 0x79, 0x11 0x79, 0x91
455 Pad+: 0x71, 0x79, 0x0D 0xF1, 0x79, 0x8D
456 Pad*: 0x71, 0x79, 0x05 0xF1, 0x79, 0x85
457 Pad/: 0x71, 0x79, 0x1B 0xF1, 0x79, 0x9B
458 Pad=: 0x71, 0x79, 0x11 0xF1, 0x79, 0x91
459
460
461RAW CODE:
462 M0110A
463 ,---------------------------------------------------------. ,---------------.
464 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *|
465 |---------------------------------------------------------| |---------------|
466 |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -|
467 |-----------------------------------------------------' | |---------------|
468 |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +|
469 |---------------------------------------------------------| |---------------|
470 |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
471 |---------------------------------------------------------' |-----------|Ent|
472 |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| |
473 `---------------------------------------------------------' `---------------'
474 ,---------------------------------------------------------. ,---------------.
475 | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31| 67| |+0F|*11|*1B|*05|
476 |---------------------------------------------------------| |---------------|
477 | 61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D| | |+33|+37|+39|+1D|
478 |-----------------------------------------------------' | |---------------|
479 | 73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F| 49| |+2D|+2F|+31|*0D|
480 |---------------------------------------------------------| |---------------|
481 | 71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59| 71|+1B| |+27|+29|+2B| |
482 |---------------------------------------------------------' |-----------|+19|
483 | 75| 6F| 63 | 55|+0D|+05|+11| | +25|+03| |
484 `---------------------------------------------------------' `---------------'
485 + 0x79, 0xDD / 0xF1, 0xUU
486 * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU
487
488
489MODEL NUMBER:
490 M0110: 0x09 00001001 : model number 4 (100)
491 M0110A: 0x0B 00001011 : model number 5 (101)
492 M0110 & M0120: ???
493
494
495Scan Code
496---------
497 m0110_recv_key() function returns following scan codes instead of M0110 raw codes.
498 Scan codes are 1 byte size and MSB(bit7) is set when key is released.
499
500 scancode = ((raw&0x80) | ((raw&0x7F)>>1))
501
502 M0110 M0120
503 ,---------------------------------------------------------. ,---------------.
504 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Clr| -|Lft|Rgt|
505 |---------------------------------------------------------| |---------------|
506 |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | 7| 8| 9|Up |
507 |---------------------------------------------------------| |---------------|
508 |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6|Dn |
509 |---------------------------------------------------------| |---------------|
510 |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | 1| 2| 3| |
511 `---------------------------------------------------------' |-----------|Ent|
512 |Opt|Mac | Space |Enter|Opt| | 0| .| |
513 `------------------------------------------------' `---------------'
514 ,---------------------------------------------------------. ,---------------.
515 | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 4E| 46| 42|
516 |---------------------------------------------------------| |---------------|
517 | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | 59| 5B| 5C| 4D|
518 |---------------------------------------------------------| |---------------|
519 | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 48|
520 |---------------------------------------------------------| |---------------|
521 | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | 53| 54| 55| |
522 `---------------------------------------------------------' |-----------| 4C|
523 | 3A| 37| 31 | 34| 3A| | 52| 41| |
524 `------------------------------------------------' `---------------'
525
526 International keyboard(See page 22 of "Technical Info for 128K/512K")
527 ,---------------------------------------------------------.
528 | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33|
529 |---------------------------------------------------------|
530 | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|
531 |------------------------------------------------------ |
532 | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| |
533 |---------------------------------------------------------|
534 | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A| 38|
535 `---------------------------------------------------------'
536 | 3A| 37| 34 | 31| 3A|
537 `------------------------------------------------'
538
539 M0110A
540 ,---------------------------------------------------------. ,---------------.
541 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *|
542 |---------------------------------------------------------| |---------------|
543 |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -|
544 |-----------------------------------------------------' | |---------------|
545 |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +|
546 |---------------------------------------------------------| |---------------|
547 |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
548 |---------------------------------------------------------' |-----------|Ent|
549 |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| |
550 `---------------------------------------------------------' `---------------'
551 ,---------------------------------------------------------. ,---------------.
552 | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 68| 6D| 62|
553 |---------------------------------------------------------| |---------------|
554 | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| | | 59| 5B| 5C| 4E|
555 |-----------------------------------------------------' | |---------------|
556 | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 66|
557 |---------------------------------------------------------| |---------------|
558 | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| 4D| | 53| 54| 55| |
559 |---------------------------------------------------------' |-----------| 4C|
560 | 3A| 37| 31 | 2A| 46| 42| 48| | 52| 41| |
561 `---------------------------------------------------------' `---------------'
562
563
564References
565----------
566Technical Info for 128K/512K and Plus
567 ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
568 ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
569Protocol:
570 Page 20 of Tech Info for 128K/512K
571 http://www.mac.linux-m68k.org/devel/plushw.php
572Connector:
573 Page 20 of Tech Info for 128K/512K
574 http://www.kbdbabel.org/conn/kbd_connector_macplus.png
575Signaling:
576 http://www.kbdbabel.org/signaling/kbd_signaling_mac.png
577 http://typematic.blog.shinobi.jp/Entry/14/
578M0110 raw scan codes:
579 Page 22 of Tech Info for 128K/512K
580 Page 07 of Tech Info for Plus
581 http://m0115.web.fc2.com/m0110.jpg
582 http://m0115.web.fc2.com/m0110a.jpg
583*/
diff --git a/tmk_core/protocol/m0110.h b/tmk_core/protocol/m0110.h
deleted file mode 100644
index 63ff3e90e..000000000
--- a/tmk_core/protocol/m0110.h
+++ /dev/null
@@ -1,81 +0,0 @@
1/*
2Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#pragma once
39
40/* port settings for clock and data line */
41#if !(defined(M0110_CLOCK_PORT) && defined(M0110_CLOCK_PIN) && defined(M0110_CLOCK_DDR) && defined(M0110_CLOCK_BIT))
42# error "M0110 clock port setting is required in config.h"
43#endif
44
45#if !(defined(M0110_DATA_PORT) && defined(M0110_DATA_PIN) && defined(M0110_DATA_DDR) && defined(M0110_DATA_BIT))
46# error "M0110 data port setting is required in config.h"
47#endif
48
49/* Commands */
50#define M0110_INQUIRY 0x10
51#define M0110_INSTANT 0x14
52#define M0110_MODEL 0x16
53#define M0110_TEST 0x36
54
55/* Response(raw byte from M0110) */
56#define M0110_NULL 0x7B
57#define M0110_KEYPAD 0x79
58#define M0110_TEST_ACK 0x7D
59#define M0110_TEST_NAK 0x77
60#define M0110_SHIFT 0x71
61#define M0110_ARROW_UP 0x1B
62#define M0110_ARROW_DOWN 0x11
63#define M0110_ARROW_LEFT 0x0D
64#define M0110_ARROW_RIGHT 0x05
65
66/* This inidcates no response. */
67#define M0110_ERROR 0xFF
68
69/* scan code offset for keypad and arrow keys */
70#define M0110_KEYPAD_OFFSET 0x40
71#define M0110_CALC_OFFSET 0x60
72
73extern uint8_t m0110_error;
74
75/* host role */
76void m0110_init(void);
77uint8_t m0110_send(uint8_t data);
78uint8_t m0110_recv(void);
79uint8_t m0110_recv_key(void);
80uint8_t m0110_inquiry(void);
81uint8_t m0110_instant(void);
diff --git a/tmk_core/protocol/midi/qmk_midi.c b/tmk_core/protocol/midi/qmk_midi.c
index c18dbf993..3a454d61a 100644
--- a/tmk_core/protocol/midi/qmk_midi.c
+++ b/tmk_core/protocol/midi/qmk_midi.c
@@ -4,9 +4,6 @@
4#include "midi.h" 4#include "midi.h"
5#include "usb_descriptor.h" 5#include "usb_descriptor.h"
6#include "process_midi.h" 6#include "process_midi.h"
7#if API_SYSEX_ENABLE
8# include "api_sysex.h"
9#endif
10 7
11/******************************************************************************* 8/*******************************************************************************
12 * MIDI 9 * MIDI
@@ -124,41 +121,6 @@ static void cc_callback(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t v
124 // midi_send_cc(device, (chan + 1) % 16, num, val); 121 // midi_send_cc(device, (chan + 1) % 16, num, val);
125} 122}
126 123
127#ifdef API_SYSEX_ENABLE
128uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
129
130static void sysex_callback(MidiDevice* device, uint16_t start, uint8_t length, uint8_t* data) {
131 // SEND_STRING("\n");
132 // send_word(start);
133 // SEND_STRING(": ");
134 // Don't store the header
135 int16_t pos = start - 4;
136 for (uint8_t place = 0; place < length; place++) {
137 // send_byte(*data);
138 if (pos >= 0) {
139 if (*data == 0xF7) {
140 // SEND_STRING("\nRD: ");
141 // for (uint8_t i = 0; i < start + place + 1; i++){
142 // send_byte(midi_buffer[i]);
143 // SEND_STRING(" ");
144 // }
145 const unsigned decoded_length = sysex_decoded_length(pos);
146 uint8_t decoded[API_SYSEX_MAX_SIZE];
147 sysex_decode(decoded, midi_buffer, pos);
148 process_api(decoded_length, decoded);
149 return;
150 } else if (pos >= MIDI_SYSEX_BUFFER) {
151 return;
152 }
153 midi_buffer[pos] = *data;
154 }
155 // SEND_STRING(" ");
156 data++;
157 pos++;
158 }
159}
160#endif
161
162void midi_init(void); 124void midi_init(void);
163 125
164void setup_midi(void) { 126void setup_midi(void) {
@@ -170,7 +132,4 @@ void setup_midi(void) {
170 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); 132 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
171 midi_register_fallthrough_callback(&midi_device, fallthrough_callback); 133 midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
172 midi_register_cc_callback(&midi_device, cc_callback); 134 midi_register_cc_callback(&midi_device, cc_callback);
173#ifdef API_SYSEX_ENABLE
174 midi_register_sysex_callback(&midi_device, sysex_callback);
175#endif
176} 135}
diff --git a/tmk_core/protocol/news.c b/tmk_core/protocol/news.c
deleted file mode 100644
index 4463e8dd4..000000000
--- a/tmk_core/protocol/news.c
+++ /dev/null
@@ -1,161 +0,0 @@
1/*
2Copyright 2012 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#include <stdbool.h>
39#include <avr/io.h>
40#include <avr/interrupt.h>
41#include "news.h"
42
43void news_init(void) { NEWS_KBD_RX_INIT(); }
44
45// RX ring buffer
46#define RBUF_SIZE 8
47static uint8_t rbuf[RBUF_SIZE];
48static uint8_t rbuf_head = 0;
49static uint8_t rbuf_tail = 0;
50
51uint8_t news_recv(void) {
52 uint8_t data = 0;
53 if (rbuf_head == rbuf_tail) {
54 return 0;
55 }
56
57 data = rbuf[rbuf_tail];
58 rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
59 return data;
60}
61
62// USART RX complete interrupt
63ISR(NEWS_KBD_RX_VECT) {
64 uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
65 if (next != rbuf_tail) {
66 rbuf[rbuf_head] = NEWS_KBD_RX_DATA;
67 rbuf_head = next;
68 }
69}
70
71/*
72SONY NEWS Keyboard Protocol
73===========================
74
75Resources
76---------
77 Mouse protocol of NWA-5461(Japanese)
78 http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d
79
80 SONY NEWS Info(Japanese)
81 http://katsu.watanabe.name/doc/sonynews/
82
83
84Pinouts
85-------
86 EIA 232 male connector from NWP-5461
87 -------------
88 \ 1 2 3 4 5 /
89 \ 6 7 8 9 /
90 ---------
91 1 VCC
92 2 BZ(Speaker)
93 3 Keyboard Data(from keyboard MCU TxD)
94 4 NC
95 5 GND
96 6 Unknown Input(to keyboard MCU RxD via schmitt trigger)
97 7 Mouse Data(from Mouse Ext connector)
98 8 Unknown Input(to Keyboard MCU Input via diode and buffer)
99 9 FG
100 NOTE: Two LED on keyboard are controlled by pin 6,8?
101
102 EIA 232 male connector from NWP-411A
103 -------------
104 \ 1 2 3 4 5 /
105 \ 6 7 8 9 /
106 ---------
107 1 VCC
108 2 BZ(Speaker)
109 3 Keyboard Data(from keyboard MCU TxD)
110 4 NC
111 5 GND
112 6 NC
113 7 Mouse Data(from Mouse Ext connector)
114 8 NC
115 9 FG
116 NOTE: These are just from my guess and not confirmed.
117
118
119Signaling
120---------
121 ~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~
122 Idle Start LSB MSB Stop Idle
123
124 Idle: High
125 Start bit: Low
126 Stop bit: High
127 Bit order: LSB first
128
129 Baud rate: 9600
130 Interface: TTL level(5V) UART
131
132 NOTE: This is observed on NWP-5461 with its DIP switch all OFF.
133
134
135Format
136------
137 MSB LSB
138 7 6 5 4 3 2 1 0 bit
139 | | | | | | | |
140 | +-+-+-+-+-+-+-- scan code(00-7F)
141 +---------------- break flag: sets when released
142
143
144Scan Codes
145----------
146 SONY NEWS NWP-5461
147 ,---. ,------------------------, ,------------------------. ,---------.
148 | 7A| | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------.
149 `---' `------------------------' `------------------------' `---------' | 64| 65| 52|
150 ,-------------------------------------------------------------. ,---. ,---------------|
151 | 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19 | | 6A| | 4B| 4C| 4D| 4E|
152 |-------------------------------------------------------------| |---| |---------------|
153 | 1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| | | 6B| | 4F| 50| 51| 56|
154 |---------------------------------------------------------' | |---| |---------------|
155 | 28 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35 | | 6C| | 53| 54| 55| |
156 |-------------------------------------------------------------| |---| |-----------| 5A|
157 | 36 | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41| 42 | | 6D| | 57| 59| 58| |
158 |-------------------------------------------------------------| |---| |---------------|
159 | 43 | 44 | 45 | 46 | 47 | 48| 49| 4A | | 6E| | 66| 5B| 5C| 5D|
160 `-------------------------------------------------------------' `---' `---------------'
161*/
diff --git a/tmk_core/protocol/news.h b/tmk_core/protocol/news.h
deleted file mode 100644
index 327a13856..000000000
--- a/tmk_core/protocol/news.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/*
2Copyright 2012 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#pragma once
39
40/*
41 * Primitive PS/2 Library for AVR
42 */
43
44/* host role */
45void news_init(void);
46uint8_t news_recv(void);
47
48/* device role */
diff --git a/tmk_core/protocol/next_kbd.c b/tmk_core/protocol/next_kbd.c
deleted file mode 100644
index 6f118e617..000000000
--- a/tmk_core/protocol/next_kbd.c
+++ /dev/null
@@ -1,219 +0,0 @@
1/*
2
3NeXT non-ADB Keyboard Protocol
4
5Copyright 2013, Benjamin Gould (bgould@github.com)
6
7Based on:
8TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
9Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
10
11Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
12Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
13Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
14
15This software is licensed with a Modified BSD License.
16All of this is supposed to be Free Software, Open Source, DFSG-free,
17GPL-compatible, and OK to use in both free and proprietary applications.
18Additions and corrections to this file are welcome.
19
20Redistribution and use in source and binary forms, with or without
21modification, are permitted provided that the following conditions are met:
22
23* Redistributions of source code must retain the above copyright
24 notice, this list of conditions and the following disclaimer.
25
26* Redistributions in binary form must reproduce the above copyright
27 notice, this list of conditions and the following disclaimer in
28 the documentation and/or other materials provided with the
29 distribution.
30
31* Neither the name of the copyright holders nor the names of
32 contributors may be used to endorse or promote products derived
33 from this software without specific prior written permission.
34
35THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
39LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45POSSIBILITY OF SUCH DAMAGE.
46
47*/
48
49#include <stdint.h>
50#include <stdbool.h>
51#include <util/atomic.h>
52#include <util/delay.h>
53#include "next_kbd.h"
54#include "debug.h"
55
56static inline void out_lo(void);
57static inline void out_hi(void);
58static inline void query(void);
59static inline void reset(void);
60static inline uint32_t response(void);
61
62/* The keyboard sends signal with 50us pulse width on OUT line
63 * while it seems to miss the 50us pulse on In line.
64 * next_kbd_set_leds() often fails to sync LED status with 50us
65 * but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least.
66 * TODO: test on Teensy and Pro Micro configuration
67 */
68#define out_hi_delay(intervals) \
69 do { \
70 out_hi(); \
71 _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
72 } while (0);
73#define out_lo_delay(intervals) \
74 do { \
75 out_lo(); \
76 _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
77 } while (0);
78#define query_delay(intervals) \
79 do { \
80 query(); \
81 _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
82 } while (0);
83#define reset_delay(intervals) \
84 do { \
85 reset(); \
86 _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
87 } while (0);
88
89void next_kbd_init(void) {
90 out_hi();
91 NEXT_KBD_IN_DDR &= ~(1 << NEXT_KBD_IN_BIT); // KBD_IN to input
92 NEXT_KBD_IN_PORT |= (1 << NEXT_KBD_IN_BIT); // KBD_IN pull up
93
94 query_delay(5);
95 reset_delay(8);
96
97 query_delay(5);
98 reset_delay(8);
99}
100
101void next_kbd_set_leds(bool left, bool right) {
102 cli();
103 out_lo_delay(9);
104
105 out_hi_delay(3);
106 out_lo_delay(1);
107
108 if (left) {
109 out_hi_delay(1);
110 } else {
111 out_lo_delay(1);
112 }
113
114 if (right) {
115 out_hi_delay(1);
116 } else {
117 out_lo_delay(1);
118 }
119
120 out_lo_delay(7);
121 out_hi();
122 sei();
123}
124
125#define NEXT_KBD_READ (NEXT_KBD_IN_PIN & (1 << NEXT_KBD_IN_BIT))
126uint32_t next_kbd_recv(void) {
127 // First check to make sure that the keyboard is actually connected;
128 // if not, just return
129 // TODO: reflect the status of the keyboard in a return code
130 if (!NEXT_KBD_READ) {
131 sei();
132 return 0;
133 }
134
135 query();
136 uint32_t resp = response();
137
138 return resp;
139}
140
141static inline uint32_t response(void) {
142 cli();
143
144 // try a 5ms read; this should be called after the query method has
145 // been run so if a key is pressed we should get a response within
146 // 5ms; if not then send a reset and exit
147 uint8_t i = 0;
148 uint32_t data = 0;
149 uint16_t reset_timeout = 50000;
150 while (NEXT_KBD_READ && reset_timeout) {
151 asm("");
152 _delay_us(1);
153 reset_timeout--;
154 }
155 if (!reset_timeout) {
156 reset();
157 sei();
158 return 0;
159 }
160 _delay_us(NEXT_KBD_TIMING / 2);
161 for (; i < 22; i++) {
162 if (NEXT_KBD_READ) {
163 data |= ((uint32_t)1 << i);
164 /* Note:
165 * My testing with the ATmega32u4 showed that there might
166 * something wrong with the timing here; by the end of the
167 * second data byte some of the modifiers can get bumped out
168 * to the next bit over if we just cycle through the data
169 * based on the expected interval. There is a bit (i = 10)
170 * in the middle of the data that is always on followed by
171 * one that is always off - so we'll use that to reset our
172 * timing in case we've gotten ahead of the keyboard;
173 */
174 if (i == 10) {
175 i++;
176 while (NEXT_KBD_READ)
177 ;
178 _delay_us(NEXT_KBD_TIMING / 2);
179 }
180 } else {
181 /* redundant - but I don't want to remove if it might screw
182 * up the timing
183 */
184 data |= ((uint32_t)0 << i);
185 }
186 _delay_us(NEXT_KBD_TIMING);
187 }
188
189 sei();
190
191 return data;
192}
193
194static inline void out_lo(void) {
195 NEXT_KBD_OUT_PORT &= ~(1 << NEXT_KBD_OUT_BIT);
196 NEXT_KBD_OUT_DDR |= (1 << NEXT_KBD_OUT_BIT);
197}
198
199static inline void out_hi(void) {
200 /* input with pull up */
201 NEXT_KBD_OUT_DDR &= ~(1 << NEXT_KBD_OUT_BIT);
202 NEXT_KBD_OUT_PORT |= (1 << NEXT_KBD_OUT_BIT);
203}
204
205static inline void query(void) {
206 out_lo_delay(5);
207 out_hi_delay(1);
208 out_lo_delay(3);
209 out_hi();
210}
211
212static inline void reset(void) {
213 out_lo_delay(1);
214 out_hi_delay(4);
215 out_lo_delay(1);
216 out_hi_delay(6);
217 out_lo_delay(10);
218 out_hi();
219}
diff --git a/tmk_core/protocol/next_kbd.h b/tmk_core/protocol/next_kbd.h
deleted file mode 100644
index 1249ebf39..000000000
--- a/tmk_core/protocol/next_kbd.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2NeXT non-ADB Keyboard Protocol
3
4Copyright 2013, Benjamin Gould (bgould@github.com)
5
6Based on:
7TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
8Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
9
10Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
11Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
12Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
13
14This software is licensed with a Modified BSD License.
15All of this is supposed to be Free Software, Open Source, DFSG-free,
16GPL-compatible, and OK to use in both free and proprietary applications.
17Additions and corrections to this file are welcome.
18
19Redistribution and use in source and binary forms, with or without
20modification, are permitted provided that the following conditions are met:
21
22* Redistributions of source code must retain the above copyright
23 notice, this list of conditions and the following disclaimer.
24
25* Redistributions in binary form must reproduce the above copyright
26 notice, this list of conditions and the following disclaimer in
27 the documentation and/or other materials provided with the
28 distribution.
29
30* Neither the name of the copyright holders nor the names of
31 contributors may be used to endorse or promote products derived
32 from this software without specific prior written permission.
33
34THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
38LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44POSSIBILITY OF SUCH DAMAGE.
45
46*/
47
48#pragma once
49
50#include <stdbool.h>
51
52#define NEXT_KBD_KMBUS_IDLE 0x300600
53#define NEXT_KBD_TIMING 50
54
55extern uint8_t next_kbd_error;
56
57/* host role */
58void next_kbd_init(void);
59void next_kbd_set_leds(bool left, bool right);
60uint32_t next_kbd_recv(void);
diff --git a/tmk_core/protocol/ps2.h b/tmk_core/protocol/ps2.h
deleted file mode 100644
index f12319285..000000000
--- a/tmk_core/protocol/ps2.h
+++ /dev/null
@@ -1,139 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#pragma once
39
40#include <stdbool.h>
41#include "wait.h"
42#include "ps2_io.h"
43#include "print.h"
44
45/*
46 * Primitive PS/2 Library for AVR
47 *
48 * PS/2 Resources
49 * --------------
50 * [1] The PS/2 Mouse/Keyboard Protocol
51 * http://www.computer-engineering.org/ps2protocol/
52 * Concise and thorough primer of PS/2 protocol.
53 *
54 * [2] Keyboard and Auxiliary Device Controller
55 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
56 * Signal Timing and Format
57 *
58 * [3] Keyboards(101- and 102-key)
59 * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
60 * Keyboard Layout, Scan Code Set, POR, and Commands.
61 *
62 * [4] PS/2 Reference Manuals
63 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
64 * Collection of IBM Personal System/2 documents.
65 *
66 * [5] TrackPoint Engineering Specifications for version 3E
67 * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
68 */
69#define PS2_ACK 0xFA
70#define PS2_RESEND 0xFE
71#define PS2_SET_LED 0xED
72
73// TODO: error numbers
74#define PS2_ERR_NONE 0
75#define PS2_ERR_STARTBIT1 1
76#define PS2_ERR_STARTBIT2 2
77#define PS2_ERR_STARTBIT3 3
78#define PS2_ERR_PARITY 0x10
79#define PS2_ERR_NODATA 0x20
80
81#define PS2_LED_SCROLL_LOCK 0
82#define PS2_LED_NUM_LOCK 1
83#define PS2_LED_CAPS_LOCK 2
84
85extern uint8_t ps2_error;
86
87void ps2_host_init(void);
88uint8_t ps2_host_send(uint8_t data);
89uint8_t ps2_host_recv_response(void);
90uint8_t ps2_host_recv(void);
91void ps2_host_set_led(uint8_t usb_led);
92
93/*--------------------------------------------------------------------
94 * static functions
95 *------------------------------------------------------------------*/
96static inline uint16_t wait_clock_lo(uint16_t us) {
97 while (clock_in() && us) {
98 asm("");
99 wait_us(1);
100 us--;
101 }
102 return us;
103}
104static inline uint16_t wait_clock_hi(uint16_t us) {
105 while (!clock_in() && us) {
106 asm("");
107 wait_us(1);
108 us--;
109 }
110 return us;
111}
112static inline uint16_t wait_data_lo(uint16_t us) {
113 while (data_in() && us) {
114 asm("");
115 wait_us(1);
116 us--;
117 }
118 return us;
119}
120static inline uint16_t wait_data_hi(uint16_t us) {
121 while (!data_in() && us) {
122 asm("");
123 wait_us(1);
124 us--;
125 }
126 return us;
127}
128
129/* idle state that device can send */
130static inline void idle(void) {
131 clock_hi();
132 data_hi();
133}
134
135/* inhibit device to send */
136static inline void inhibit(void) {
137 clock_lo();
138 data_hi();
139}
diff --git a/tmk_core/protocol/ps2_busywait.c b/tmk_core/protocol/ps2_busywait.c
deleted file mode 100644
index 983194eea..000000000
--- a/tmk_core/protocol/ps2_busywait.c
+++ /dev/null
@@ -1,187 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38/*
39 * PS/2 protocol busywait version
40 */
41
42#include <stdbool.h>
43#include "wait.h"
44#include "ps2.h"
45#include "ps2_io.h"
46#include "debug.h"
47
48#define WAIT(stat, us, err) \
49 do { \
50 if (!wait_##stat(us)) { \
51 ps2_error = err; \
52 goto ERROR; \
53 } \
54 } while (0)
55
56uint8_t ps2_error = PS2_ERR_NONE;
57
58void ps2_host_init(void) {
59 clock_init();
60 data_init();
61
62 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
63 wait_ms(2500);
64
65 inhibit();
66}
67
68uint8_t ps2_host_send(uint8_t data) {
69 bool parity = true;
70 ps2_error = PS2_ERR_NONE;
71
72 /* terminate a transmission if we have */
73 inhibit();
74 wait_us(100); // 100us [4]p.13, [5]p.50
75
76 /* 'Request to Send' and Start bit */
77 data_lo();
78 clock_hi();
79 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
80
81 /* Data bit */
82 for (uint8_t i = 0; i < 8; i++) {
83 wait_us(15);
84 if (data & (1 << i)) {
85 parity = !parity;
86 data_hi();
87 } else {
88 data_lo();
89 }
90 WAIT(clock_hi, 50, 2);
91 WAIT(clock_lo, 50, 3);
92 }
93
94 /* Parity bit */
95 wait_us(15);
96 if (parity) {
97 data_hi();
98 } else {
99 data_lo();
100 }
101 WAIT(clock_hi, 50, 4);
102 WAIT(clock_lo, 50, 5);
103
104 /* Stop bit */
105 wait_us(15);
106 data_hi();
107
108 /* Ack */
109 WAIT(data_lo, 50, 6);
110 WAIT(clock_lo, 50, 7);
111
112 /* wait for idle state */
113 WAIT(clock_hi, 50, 8);
114 WAIT(data_hi, 50, 9);
115
116 inhibit();
117 return ps2_host_recv_response();
118ERROR:
119 inhibit();
120 return 0;
121}
122
123/* receive data when host want else inhibit communication */
124uint8_t ps2_host_recv_response(void) {
125 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
126 // 250 * 100us(wait for start bit in ps2_host_recv)
127 uint8_t data = 0;
128 uint8_t try
129 = 250;
130 do {
131 data = ps2_host_recv();
132 } while (try --&&ps2_error);
133 return data;
134}
135
136/* called after start bit comes */
137uint8_t ps2_host_recv(void) {
138 uint8_t data = 0;
139 bool parity = true;
140 ps2_error = PS2_ERR_NONE;
141
142 /* release lines(idle state) */
143 idle();
144
145 /* start bit [1] */
146 WAIT(clock_lo, 100, 1); // TODO: this is enough?
147 WAIT(data_lo, 1, 2);
148 WAIT(clock_hi, 50, 3);
149
150 /* data [2-9] */
151 for (uint8_t i = 0; i < 8; i++) {
152 WAIT(clock_lo, 50, 4);
153 if (data_in()) {
154 parity = !parity;
155 data |= (1 << i);
156 }
157 WAIT(clock_hi, 50, 5);
158 }
159
160 /* parity [10] */
161 WAIT(clock_lo, 50, 6);
162 if (data_in() != parity) {
163 ps2_error = PS2_ERR_PARITY;
164 goto ERROR;
165 }
166 WAIT(clock_hi, 50, 7);
167
168 /* stop bit [11] */
169 WAIT(clock_lo, 50, 8);
170 WAIT(data_hi, 1, 9);
171 WAIT(clock_hi, 50, 10);
172
173 inhibit();
174 return data;
175ERROR:
176 if (ps2_error > PS2_ERR_STARTBIT3) {
177 xprintf("x%02X\n", ps2_error);
178 }
179 inhibit();
180 return 0;
181}
182
183/* send LED state to keyboard */
184void ps2_host_set_led(uint8_t led) {
185 ps2_host_send(0xED);
186 ps2_host_send(led);
187}
diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c
deleted file mode 100644
index 780040d15..000000000
--- a/tmk_core/protocol/ps2_interrupt.c
+++ /dev/null
@@ -1,340 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38/*
39 * PS/2 protocol Pin interrupt version
40 */
41
42#include <stdbool.h>
43
44#if defined(__AVR__)
45# include <avr/interrupt.h>
46#elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ?
47// chibiOS headers
48# include "ch.h"
49# include "hal.h"
50#endif
51
52#include "ps2.h"
53#include "ps2_io.h"
54#include "print.h"
55#include "wait.h"
56
57#define WAIT(stat, us, err) \
58 do { \
59 if (!wait_##stat(us)) { \
60 ps2_error = err; \
61 goto ERROR; \
62 } \
63 } while (0)
64
65uint8_t ps2_error = PS2_ERR_NONE;
66
67static inline uint8_t pbuf_dequeue(void);
68static inline void pbuf_enqueue(uint8_t data);
69static inline bool pbuf_has_data(void);
70static inline void pbuf_clear(void);
71
72#if defined(PROTOCOL_CHIBIOS)
73void ps2_interrupt_service_routine(void);
74void palCallback(void *arg) { ps2_interrupt_service_routine(); }
75
76# define PS2_INT_INIT() \
77 { palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); } \
78 while (0)
79# define PS2_INT_ON() \
80 { \
81 palEnableLineEvent(PS2_CLOCK, PAL_EVENT_MODE_FALLING_EDGE); \
82 palSetLineCallback(PS2_CLOCK, palCallback, NULL); \
83 } \
84 while (0)
85# define PS2_INT_OFF() \
86 { palDisableLineEvent(PS2_CLOCK); } \
87 while (0)
88#endif // PROTOCOL_CHIBIOS
89
90void ps2_host_init(void) {
91 idle();
92 PS2_INT_INIT();
93 PS2_INT_ON();
94 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
95 // wait_ms(2500);
96}
97
98uint8_t ps2_host_send(uint8_t data) {
99 bool parity = true;
100 ps2_error = PS2_ERR_NONE;
101
102 PS2_INT_OFF();
103
104 /* terminate a transmission if we have */
105 inhibit();
106 wait_us(100); // 100us [4]p.13, [5]p.50
107
108 /* 'Request to Send' and Start bit */
109 data_lo();
110 clock_hi();
111 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
112
113 /* Data bit[2-9] */
114 for (uint8_t i = 0; i < 8; i++) {
115 if (data & (1 << i)) {
116 parity = !parity;
117 data_hi();
118 } else {
119 data_lo();
120 }
121 WAIT(clock_hi, 50, 2);
122 WAIT(clock_lo, 50, 3);
123 }
124
125 /* Parity bit */
126 wait_us(15);
127 if (parity) {
128 data_hi();
129 } else {
130 data_lo();
131 }
132 WAIT(clock_hi, 50, 4);
133 WAIT(clock_lo, 50, 5);
134
135 /* Stop bit */
136 wait_us(15);
137 data_hi();
138
139 /* Ack */
140 WAIT(data_lo, 50, 6);
141 WAIT(clock_lo, 50, 7);
142
143 /* wait for idle state */
144 WAIT(clock_hi, 50, 8);
145 WAIT(data_hi, 50, 9);
146
147 idle();
148 PS2_INT_ON();
149 return ps2_host_recv_response();
150ERROR:
151 idle();
152 PS2_INT_ON();
153 return 0;
154}
155
156uint8_t ps2_host_recv_response(void) {
157 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
158 uint8_t retry = 25;
159 while (retry-- && !pbuf_has_data()) {
160 wait_ms(1);
161 }
162 return pbuf_dequeue();
163}
164
165/* get data received by interrupt */
166uint8_t ps2_host_recv(void) {
167 if (pbuf_has_data()) {
168 ps2_error = PS2_ERR_NONE;
169 return pbuf_dequeue();
170 } else {
171 ps2_error = PS2_ERR_NODATA;
172 return 0;
173 }
174}
175
176void ps2_interrupt_service_routine(void) {
177 static enum {
178 INIT,
179 START,
180 BIT0,
181 BIT1,
182 BIT2,
183 BIT3,
184 BIT4,
185 BIT5,
186 BIT6,
187 BIT7,
188 PARITY,
189 STOP,
190 } state = INIT;
191 static uint8_t data = 0;
192 static uint8_t parity = 1;
193
194 // TODO: abort if elapse 100us from previous interrupt
195
196 // return unless falling edge
197 if (clock_in()) {
198 goto RETURN;
199 }
200
201 state++;
202 switch (state) {
203 case START:
204 if (data_in()) goto ERROR;
205 break;
206 case BIT0:
207 case BIT1:
208 case BIT2:
209 case BIT3:
210 case BIT4:
211 case BIT5:
212 case BIT6:
213 case BIT7:
214 data >>= 1;
215 if (data_in()) {
216 data |= 0x80;
217 parity++;
218 }
219 break;
220 case PARITY:
221 if (data_in()) {
222 if (!(parity & 0x01)) goto ERROR;
223 } else {
224 if (parity & 0x01) goto ERROR;
225 }
226 break;
227 case STOP:
228 if (!data_in()) goto ERROR;
229 pbuf_enqueue(data);
230 goto DONE;
231 break;
232 default:
233 goto ERROR;
234 }
235 goto RETURN;
236ERROR:
237 ps2_error = state;
238DONE:
239 state = INIT;
240 data = 0;
241 parity = 1;
242RETURN:
243 return;
244}
245
246#if defined(__AVR__)
247ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); }
248#endif
249
250/* send LED state to keyboard */
251void ps2_host_set_led(uint8_t led) {
252 ps2_host_send(0xED);
253 ps2_host_send(led);
254}
255
256/*--------------------------------------------------------------------
257 * Ring buffer to store scan codes from keyboard
258 *------------------------------------------------------------------*/
259#define PBUF_SIZE 32
260static uint8_t pbuf[PBUF_SIZE];
261static uint8_t pbuf_head = 0;
262static uint8_t pbuf_tail = 0;
263static inline void pbuf_enqueue(uint8_t data) {
264#if defined(__AVR__)
265 uint8_t sreg = SREG;
266 cli();
267#elif defined(PROTOCOL_CHIBIOS)
268 chSysLockFromISR();
269#endif
270
271 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
272 if (next != pbuf_tail) {
273 pbuf[pbuf_head] = data;
274 pbuf_head = next;
275 } else {
276 print("pbuf: full\n");
277 }
278
279#if defined(__AVR__)
280 SREG = sreg;
281#elif defined(PROTOCOL_CHIBIOS)
282 chSysUnlockFromISR();
283#endif
284}
285static inline uint8_t pbuf_dequeue(void) {
286 uint8_t val = 0;
287
288#if defined(__AVR__)
289 uint8_t sreg = SREG;
290 cli();
291#elif defined(PROTOCOL_CHIBIOS)
292 chSysLock();
293#endif
294
295 if (pbuf_head != pbuf_tail) {
296 val = pbuf[pbuf_tail];
297 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
298 }
299
300#if defined(__AVR__)
301 SREG = sreg;
302#elif defined(PROTOCOL_CHIBIOS)
303 chSysUnlock();
304#endif
305
306 return val;
307}
308static inline bool pbuf_has_data(void) {
309#if defined(__AVR__)
310 uint8_t sreg = SREG;
311 cli();
312#elif defined(PROTOCOL_CHIBIOS)
313 chSysLock();
314#endif
315
316 bool has_data = (pbuf_head != pbuf_tail);
317
318#if defined(__AVR__)
319 SREG = sreg;
320#elif defined(PROTOCOL_CHIBIOS)
321 chSysUnlock();
322#endif
323 return has_data;
324}
325static inline void pbuf_clear(void) {
326#if defined(__AVR__)
327 uint8_t sreg = SREG;
328 cli();
329#elif defined(PROTOCOL_CHIBIOS)
330 chSysLock();
331#endif
332
333 pbuf_head = pbuf_tail = 0;
334
335#if defined(__AVR__)
336 SREG = sreg;
337#elif defined(PROTOCOL_CHIBIOS)
338 chSysUnlock();
339#endif
340}
diff --git a/tmk_core/protocol/ps2_io.h b/tmk_core/protocol/ps2_io.h
deleted file mode 100644
index de93cb7a3..000000000
--- a/tmk_core/protocol/ps2_io.h
+++ /dev/null
@@ -1,11 +0,0 @@
1#pragma once
2
3void clock_init(void);
4void clock_lo(void);
5void clock_hi(void);
6bool clock_in(void);
7
8void data_init(void);
9void data_lo(void);
10void data_hi(void);
11bool 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 a9ac5d338..000000000
--- a/tmk_core/protocol/ps2_io_avr.c
+++ /dev/null
@@ -1,58 +0,0 @@
1#include <stdbool.h>
2#include <avr/io.h>
3#include <util/delay.h>
4
5/* Check port settings for clock and data line */
6#if !(defined(PS2_CLOCK_PORT) && defined(PS2_CLOCK_PIN) && defined(PS2_CLOCK_DDR) && defined(PS2_CLOCK_BIT))
7# error "PS/2 clock port setting is required in config.h"
8#endif
9
10#if !(defined(PS2_DATA_PORT) && defined(PS2_DATA_PIN) && defined(PS2_DATA_DDR) && defined(PS2_DATA_BIT))
11# error "PS/2 data port setting is required in config.h"
12#endif
13
14/*
15 * Clock
16 */
17void clock_init(void) {}
18
19void clock_lo(void) {
20 PS2_CLOCK_PORT &= ~(1 << PS2_CLOCK_BIT);
21 PS2_CLOCK_DDR |= (1 << PS2_CLOCK_BIT);
22}
23
24void clock_hi(void) {
25 /* input with pull up */
26 PS2_CLOCK_DDR &= ~(1 << PS2_CLOCK_BIT);
27 PS2_CLOCK_PORT |= (1 << PS2_CLOCK_BIT);
28}
29
30bool clock_in(void) {
31 PS2_CLOCK_DDR &= ~(1 << PS2_CLOCK_BIT);
32 PS2_CLOCK_PORT |= (1 << PS2_CLOCK_BIT);
33 _delay_us(1);
34 return PS2_CLOCK_PIN & (1 << PS2_CLOCK_BIT);
35}
36
37/*
38 * Data
39 */
40void data_init(void) {}
41
42void data_lo(void) {
43 PS2_DATA_PORT &= ~(1 << PS2_DATA_BIT);
44 PS2_DATA_DDR |= (1 << PS2_DATA_BIT);
45}
46
47void data_hi(void) {
48 /* input with pull up */
49 PS2_DATA_DDR &= ~(1 << PS2_DATA_BIT);
50 PS2_DATA_PORT |= (1 << PS2_DATA_BIT);
51}
52
53bool data_in(void) {
54 PS2_DATA_DDR &= ~(1 << PS2_DATA_BIT);
55 PS2_DATA_PORT |= (1 << PS2_DATA_BIT);
56 _delay_us(1);
57 return PS2_DATA_PIN & (1 << PS2_DATA_BIT);
58}
diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c
deleted file mode 100644
index b672bd1f4..000000000
--- a/tmk_core/protocol/ps2_io_chibios.c
+++ /dev/null
@@ -1,55 +0,0 @@
1#include <stdbool.h>
2#include "ps2_io.h"
3
4// chibiOS headers
5#include "ch.h"
6#include "hal.h"
7
8/* Check port settings for clock and data line */
9#if !(defined(PS2_CLOCK))
10# error "PS/2 clock setting is required in config.h"
11#endif
12
13#if !(defined(PS2_DATA))
14# error "PS/2 data setting is required in config.h"
15#endif
16
17/*
18 * Clock
19 */
20void clock_init(void) {}
21
22void clock_lo(void) {
23 palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN);
24 palWriteLine(PS2_CLOCK, PAL_LOW);
25}
26
27void clock_hi(void) {
28 palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN);
29 palWriteLine(PS2_CLOCK, PAL_HIGH);
30}
31
32bool clock_in(void) {
33 palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT);
34 return palReadLine(PS2_CLOCK);
35}
36
37/*
38 * Data
39 */
40void data_init(void) {}
41
42void data_lo(void) {
43 palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN);
44 palWriteLine(PS2_DATA, PAL_LOW);
45}
46
47void data_hi(void) {
48 palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN);
49 palWriteLine(PS2_DATA, PAL_HIGH);
50}
51
52bool data_in(void) {
53 palSetLineMode(PS2_DATA, PAL_MODE_INPUT);
54 return palReadLine(PS2_DATA);
55}
diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c
deleted file mode 100644
index 39251a643..000000000
--- a/tmk_core/protocol/ps2_mouse.c
+++ /dev/null
@@ -1,274 +0,0 @@
1/*
2Copyright 2011,2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <stdbool.h>
19
20#if defined(__AVR__)
21# include <avr/io.h>
22#endif
23
24#include "ps2_mouse.h"
25#include "wait.h"
26#include "host.h"
27#include "timer.h"
28#include "print.h"
29#include "report.h"
30#include "debug.h"
31#include "ps2.h"
32
33/* ============================= MACROS ============================ */
34
35static report_mouse_t mouse_report = {};
36
37static inline void ps2_mouse_print_report(report_mouse_t *mouse_report);
38static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report);
39static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report);
40static inline void ps2_mouse_enable_scrolling(void);
41static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report);
42
43/* ============================= IMPLEMENTATION ============================ */
44
45/* supports only 3 button mouse at this time */
46void ps2_mouse_init(void) {
47 ps2_host_init();
48
49 wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up
50
51 PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset");
52
53 PS2_MOUSE_RECEIVE("ps2_mouse_init: read BAT");
54 PS2_MOUSE_RECEIVE("ps2_mouse_init: read DevID");
55
56#ifdef PS2_MOUSE_USE_REMOTE_MODE
57 ps2_mouse_set_remote_mode();
58#else
59 ps2_mouse_enable_data_reporting();
60#endif
61
62#ifdef PS2_MOUSE_ENABLE_SCROLLING
63 ps2_mouse_enable_scrolling();
64#endif
65
66#ifdef PS2_MOUSE_USE_2_1_SCALING
67 ps2_mouse_set_scaling_2_1();
68#endif
69
70 ps2_mouse_init_user();
71}
72
73__attribute__((weak)) void ps2_mouse_init_user(void) {}
74
75__attribute__((weak)) void ps2_mouse_moved_user(report_mouse_t *mouse_report) {}
76
77void ps2_mouse_task(void) {
78 static uint8_t buttons_prev = 0;
79 extern int tp_buttons;
80
81 /* receives packet from mouse */
82 uint8_t rcv;
83 rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
84 if (rcv == PS2_ACK) {
85 mouse_report.buttons = ps2_host_recv_response() | tp_buttons;
86 mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER;
87 mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER;
88#ifdef PS2_MOUSE_ENABLE_SCROLLING
89 mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER;
90#endif
91 } else {
92 if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
93 return;
94 }
95
96 /* if mouse moves or buttons state changes */
97 if (mouse_report.x || mouse_report.y || mouse_report.v || ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
98#ifdef PS2_MOUSE_DEBUG_RAW
99 // Used to debug raw ps2 bytes from mouse
100 ps2_mouse_print_report(&mouse_report);
101#endif
102 buttons_prev = mouse_report.buttons;
103 ps2_mouse_convert_report_to_hid(&mouse_report);
104#if PS2_MOUSE_SCROLL_BTN_MASK
105 ps2_mouse_scroll_button_task(&mouse_report);
106#endif
107 if (mouse_report.x || mouse_report.y || mouse_report.v) {
108 ps2_mouse_moved_user(&mouse_report);
109 }
110#ifdef PS2_MOUSE_DEBUG_HID
111 // Used to debug the bytes sent to the host
112 ps2_mouse_print_report(&mouse_report);
113#endif
114 host_mouse_send(&mouse_report);
115 }
116
117 ps2_mouse_clear_report(&mouse_report);
118}
119
120void ps2_mouse_disable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); }
121
122void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); }
123
124void ps2_mouse_set_remote_mode(void) {
125 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode");
126 ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE;
127}
128
129void ps2_mouse_set_stream_mode(void) {
130 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode");
131 ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
132}
133
134void ps2_mouse_set_scaling_2_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); }
135
136void ps2_mouse_set_scaling_1_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); }
137
138void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution"); }
139
140void 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"); }
141
142/* ============================= HELPERS ============================ */
143
144#define X_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_X_SIGN))
145#define Y_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_Y_SIGN))
146#define X_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_X_OVFLW))
147#define Y_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_Y_OVFLW))
148static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) {
149 // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value.
150 // bit: 8 7 ... 0
151 // sign \8-bit/
152 //
153 // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
154 //
155 // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
156 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);
157 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);
158
159#ifdef PS2_MOUSE_INVERT_BUTTONS
160 // swap left & right buttons
161 uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT;
162 uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT;
163 mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0);
164#else
165 // remove sign and overflow flags
166 mouse_report->buttons &= PS2_MOUSE_BTN_MASK;
167#endif
168
169#ifdef PS2_MOUSE_INVERT_X
170 mouse_report->x = -mouse_report->x;
171#endif
172#ifndef PS2_MOUSE_INVERT_Y // NOTE if not!
173 // invert coordinate of y to conform to USB HID mouse
174 mouse_report->y = -mouse_report->y;
175#endif
176
177#ifdef PS2_MOUSE_ROTATE
178 int8_t x = mouse_report->x;
179 int8_t y = mouse_report->y;
180# if PS2_MOUSE_ROTATE == 90
181 mouse_report->x = y;
182 mouse_report->y = -x;
183# elif PS2_MOUSE_ROTATE == 180
184 mouse_report->x = -x;
185 mouse_report->y = -y;
186# elif PS2_MOUSE_ROTATE == 270
187 mouse_report->x = -y;
188 mouse_report->y = x;
189# endif
190#endif
191}
192
193static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) {
194 mouse_report->x = 0;
195 mouse_report->y = 0;
196 mouse_report->v = 0;
197 mouse_report->h = 0;
198 mouse_report->buttons = 0;
199}
200
201static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) {
202 if (!debug_mouse) return;
203 print("ps2_mouse: [");
204 print_hex8(mouse_report->buttons);
205 print("|");
206 print_hex8((uint8_t)mouse_report->x);
207 print(" ");
208 print_hex8((uint8_t)mouse_report->y);
209 print(" ");
210 print_hex8((uint8_t)mouse_report->v);
211 print(" ");
212 print_hex8((uint8_t)mouse_report->h);
213 print("]\n");
214}
215
216static inline void ps2_mouse_enable_scrolling(void) {
217 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Initiaing scroll wheel enable: Set sample rate");
218 PS2_MOUSE_SEND(200, "200");
219 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
220 PS2_MOUSE_SEND(100, "100");
221 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
222 PS2_MOUSE_SEND(80, "80");
223 PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel");
224 wait_ms(20);
225}
226
227#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK)
228#define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK)
229static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) {
230 static enum {
231 SCROLL_NONE,
232 SCROLL_BTN,
233 SCROLL_SENT,
234 } scroll_state = SCROLL_NONE;
235 static uint16_t scroll_button_time = 0;
236
237 if (PS2_MOUSE_SCROLL_BTN_MASK == (mouse_report->buttons & (PS2_MOUSE_SCROLL_BTN_MASK))) {
238 // All scroll buttons are pressed
239
240 if (scroll_state == SCROLL_NONE) {
241 scroll_button_time = timer_read();
242 scroll_state = SCROLL_BTN;
243 }
244
245 // If the mouse has moved, update the report to scroll instead of move the mouse
246 if (mouse_report->x || mouse_report->y) {
247 scroll_state = SCROLL_SENT;
248 mouse_report->v = -mouse_report->y / (PS2_MOUSE_SCROLL_DIVISOR_V);
249 mouse_report->h = mouse_report->x / (PS2_MOUSE_SCROLL_DIVISOR_H);
250 mouse_report->x = 0;
251 mouse_report->y = 0;
252#ifdef PS2_MOUSE_INVERT_H
253 mouse_report->h = -mouse_report->h;
254#endif
255#ifdef PS2_MOUSE_INVERT_V
256 mouse_report->v = -mouse_report->v;
257#endif
258 }
259 } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) {
260 // None of the scroll buttons are pressed
261
262#if PS2_MOUSE_SCROLL_BTN_SEND
263 if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
264 PRESS_SCROLL_BUTTONS;
265 host_mouse_send(mouse_report);
266 wait_ms(100);
267 RELEASE_SCROLL_BUTTONS;
268 }
269#endif
270 scroll_state = SCROLL_NONE;
271 }
272
273 RELEASE_SCROLL_BUTTONS;
274}
diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h
deleted file mode 100644
index c97c6c893..000000000
--- a/tmk_core/protocol/ps2_mouse.h
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#pragma once
19
20#include <stdbool.h>
21#include "debug.h"
22#include "report.h"
23
24#define PS2_MOUSE_SEND(command, message) \
25 do { \
26 __attribute__((unused)) uint8_t rcv = ps2_host_send(command); \
27 if (debug_mouse) { \
28 print((message)); \
29 xprintf(" command: %X, result: %X, error: %X \n", command, rcv, ps2_error); \
30 } \
31 } while (0)
32
33#define PS2_MOUSE_SEND_SAFE(command, message) \
34 do { \
35 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
36 ps2_mouse_disable_data_reporting(); \
37 } \
38 PS2_MOUSE_SEND(command, message); \
39 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
40 ps2_mouse_enable_data_reporting(); \
41 } \
42 } while (0)
43
44#define PS2_MOUSE_SET_SAFE(command, value, message) \
45 do { \
46 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
47 ps2_mouse_disable_data_reporting(); \
48 } \
49 PS2_MOUSE_SEND(command, message); \
50 PS2_MOUSE_SEND(value, "Sending value"); \
51 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
52 ps2_mouse_enable_data_reporting(); \
53 } \
54 } while (0)
55
56#define PS2_MOUSE_RECEIVE(message) \
57 do { \
58 __attribute__((unused)) uint8_t rcv = ps2_host_recv_response(); \
59 if (debug_mouse) { \
60 print((message)); \
61 xprintf(" result: %X, error: %X \n", rcv, ps2_error); \
62 } \
63 } while (0)
64
65__attribute__((unused)) static enum ps2_mouse_mode_e {
66 PS2_MOUSE_STREAM_MODE,
67 PS2_MOUSE_REMOTE_MODE,
68} ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
69
70/*
71 * Data format:
72 * byte|7 6 5 4 3 2 1 0
73 * ----+----------------------------------------------------------------
74 * 0|[Yovflw][Xovflw][Ysign ][Xsign ][ 1 ][Middle][Right ][Left ]
75 * 1|[ X movement(0-255) ]
76 * 2|[ Y movement(0-255) ]
77 */
78#define PS2_MOUSE_BTN_MASK 0x07
79#define PS2_MOUSE_BTN_LEFT 0
80#define PS2_MOUSE_BTN_RIGHT 1
81#define PS2_MOUSE_BTN_MIDDLE 2
82#define PS2_MOUSE_X_SIGN 4
83#define PS2_MOUSE_Y_SIGN 5
84#define PS2_MOUSE_X_OVFLW 6
85#define PS2_MOUSE_Y_OVFLW 7
86
87/* mouse button to start scrolling; set 0 to disable scroll */
88#ifndef PS2_MOUSE_SCROLL_BTN_MASK
89# define PS2_MOUSE_SCROLL_BTN_MASK (1 << PS2_MOUSE_BTN_MIDDLE)
90#endif
91/* send button event when button is released within this value(ms); set 0 to disable */
92#ifndef PS2_MOUSE_SCROLL_BTN_SEND
93# define PS2_MOUSE_SCROLL_BTN_SEND 300
94#endif
95/* divide virtical and horizontal mouse move by this to convert to scroll move */
96#ifndef PS2_MOUSE_SCROLL_DIVISOR_V
97# define PS2_MOUSE_SCROLL_DIVISOR_V 2
98#endif
99#ifndef PS2_MOUSE_SCROLL_DIVISOR_H
100# define PS2_MOUSE_SCROLL_DIVISOR_H 2
101#endif
102/* multiply reported mouse values by these */
103#ifndef PS2_MOUSE_X_MULTIPLIER
104# define PS2_MOUSE_X_MULTIPLIER 1
105#endif
106#ifndef PS2_MOUSE_Y_MULTIPLIER
107# define PS2_MOUSE_Y_MULTIPLIER 1
108#endif
109#ifndef PS2_MOUSE_V_MULTIPLIER
110# define PS2_MOUSE_V_MULTIPLIER 1
111#endif
112/* For some mice this will need to be 0x0F */
113#ifndef PS2_MOUSE_SCROLL_MASK
114# define PS2_MOUSE_SCROLL_MASK 0xFF
115#endif
116#ifndef PS2_MOUSE_INIT_DELAY
117# define PS2_MOUSE_INIT_DELAY 1000
118#endif
119
120enum ps2_mouse_command_e {
121 PS2_MOUSE_RESET = 0xFF,
122 PS2_MOUSE_RESEND = 0xFE,
123 PS2_MOSUE_SET_DEFAULTS = 0xF6,
124 PS2_MOUSE_DISABLE_DATA_REPORTING = 0xF5,
125 PS2_MOUSE_ENABLE_DATA_REPORTING = 0xF4,
126 PS2_MOUSE_SET_SAMPLE_RATE = 0xF3,
127 PS2_MOUSE_GET_DEVICE_ID = 0xF2,
128 PS2_MOUSE_SET_REMOTE_MODE = 0xF0,
129 PS2_MOUSE_SET_WRAP_MODE = 0xEC,
130 PS2_MOUSE_READ_DATA = 0xEB,
131 PS2_MOUSE_SET_STREAM_MODE = 0xEA,
132 PS2_MOUSE_STATUS_REQUEST = 0xE9,
133 PS2_MOUSE_SET_RESOLUTION = 0xE8,
134 PS2_MOUSE_SET_SCALING_2_1 = 0xE7,
135 PS2_MOUSE_SET_SCALING_1_1 = 0xE6,
136};
137
138typedef enum ps2_mouse_resolution_e {
139 PS2_MOUSE_1_COUNT_MM,
140 PS2_MOUSE_2_COUNT_MM,
141 PS2_MOUSE_4_COUNT_MM,
142 PS2_MOUSE_8_COUNT_MM,
143} ps2_mouse_resolution_t;
144
145typedef enum ps2_mouse_sample_rate_e {
146 PS2_MOUSE_10_SAMPLES_SEC = 10,
147 PS2_MOUSE_20_SAMPLES_SEC = 20,
148 PS2_MOUSE_40_SAMPLES_SEC = 40,
149 PS2_MOUSE_60_SAMPLES_SEC = 60,
150 PS2_MOUSE_80_SAMPLES_SEC = 80,
151 PS2_MOUSE_100_SAMPLES_SEC = 100,
152 PS2_MOUSE_200_SAMPLES_SEC = 200,
153} ps2_mouse_sample_rate_t;
154
155void ps2_mouse_init(void);
156
157void ps2_mouse_init_user(void);
158
159void ps2_mouse_task(void);
160
161void ps2_mouse_disable_data_reporting(void);
162
163void ps2_mouse_enable_data_reporting(void);
164
165void ps2_mouse_set_remote_mode(void);
166
167void ps2_mouse_set_stream_mode(void);
168
169void ps2_mouse_set_scaling_2_1(void);
170
171void ps2_mouse_set_scaling_1_1(void);
172
173void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution);
174
175void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate);
176
177void 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 6a66dc4a1..000000000
--- a/tmk_core/protocol/ps2_usart.c
+++ /dev/null
@@ -1,213 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38/*
39 * PS/2 protocol USART version
40 */
41
42#include <stdbool.h>
43#include <avr/interrupt.h>
44#include <util/delay.h>
45#include "ps2.h"
46#include "ps2_io.h"
47#include "print.h"
48
49#define WAIT(stat, us, err) \
50 do { \
51 if (!wait_##stat(us)) { \
52 ps2_error = err; \
53 goto ERROR; \
54 } \
55 } while (0)
56
57uint8_t ps2_error = PS2_ERR_NONE;
58
59static inline uint8_t pbuf_dequeue(void);
60static inline void pbuf_enqueue(uint8_t data);
61static inline bool pbuf_has_data(void);
62static inline void pbuf_clear(void);
63
64void ps2_host_init(void) {
65 idle(); // without this many USART errors occur when cable is disconnected
66 PS2_USART_INIT();
67 PS2_USART_RX_INT_ON();
68 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
69 //_delay_ms(2500);
70}
71
72uint8_t ps2_host_send(uint8_t data) {
73 bool parity = true;
74 ps2_error = PS2_ERR_NONE;
75
76 PS2_USART_OFF();
77
78 /* terminate a transmission if we have */
79 inhibit();
80 _delay_us(100); // [4]p.13
81
82 /* 'Request to Send' and Start bit */
83 data_lo();
84 clock_hi();
85 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
86
87 /* Data bit[2-9] */
88 for (uint8_t i = 0; i < 8; i++) {
89 _delay_us(15);
90 if (data & (1 << i)) {
91 parity = !parity;
92 data_hi();
93 } else {
94 data_lo();
95 }
96 WAIT(clock_hi, 50, 2);
97 WAIT(clock_lo, 50, 3);
98 }
99
100 /* Parity bit */
101 _delay_us(15);
102 if (parity) {
103 data_hi();
104 } else {
105 data_lo();
106 }
107 WAIT(clock_hi, 50, 4);
108 WAIT(clock_lo, 50, 5);
109
110 /* Stop bit */
111 _delay_us(15);
112 data_hi();
113
114 /* Ack */
115 WAIT(data_lo, 50, 6);
116 WAIT(clock_lo, 50, 7);
117
118 /* wait for idle state */
119 WAIT(clock_hi, 50, 8);
120 WAIT(data_hi, 50, 9);
121
122 idle();
123 PS2_USART_INIT();
124 PS2_USART_RX_INT_ON();
125 return ps2_host_recv_response();
126ERROR:
127 idle();
128 PS2_USART_INIT();
129 PS2_USART_RX_INT_ON();
130 return 0;
131}
132
133uint8_t ps2_host_recv_response(void) {
134 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
135 uint8_t retry = 25;
136 while (retry-- && !pbuf_has_data()) {
137 _delay_ms(1);
138 }
139 return pbuf_dequeue();
140}
141
142uint8_t ps2_host_recv(void) {
143 if (pbuf_has_data()) {
144 ps2_error = PS2_ERR_NONE;
145 return pbuf_dequeue();
146 } else {
147 ps2_error = PS2_ERR_NODATA;
148 return 0;
149 }
150}
151
152ISR(PS2_USART_RX_VECT) {
153 // TODO: request RESEND when error occurs?
154 uint8_t error = PS2_USART_ERROR; // USART error should be read before data
155 uint8_t data = PS2_USART_RX_DATA;
156 if (!error) {
157 pbuf_enqueue(data);
158 } else {
159 xprintf("PS2 USART error: %02X data: %02X\n", error, data);
160 }
161}
162
163/* send LED state to keyboard */
164void ps2_host_set_led(uint8_t led) {
165 ps2_host_send(0xED);
166 ps2_host_send(led);
167}
168
169/*--------------------------------------------------------------------
170 * Ring buffer to store scan codes from keyboard
171 *------------------------------------------------------------------*/
172#define PBUF_SIZE 32
173static uint8_t pbuf[PBUF_SIZE];
174static uint8_t pbuf_head = 0;
175static uint8_t pbuf_tail = 0;
176static inline void pbuf_enqueue(uint8_t data) {
177 uint8_t sreg = SREG;
178 cli();
179 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
180 if (next != pbuf_tail) {
181 pbuf[pbuf_head] = data;
182 pbuf_head = next;
183 } else {
184 print("pbuf: full\n");
185 }
186 SREG = sreg;
187}
188static inline uint8_t pbuf_dequeue(void) {
189 uint8_t val = 0;
190
191 uint8_t sreg = SREG;
192 cli();
193 if (pbuf_head != pbuf_tail) {
194 val = pbuf[pbuf_tail];
195 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
196 }
197 SREG = sreg;
198
199 return val;
200}
201static inline bool pbuf_has_data(void) {
202 uint8_t sreg = SREG;
203 cli();
204 bool has_data = (pbuf_head != pbuf_tail);
205 SREG = sreg;
206 return has_data;
207}
208static inline void pbuf_clear(void) {
209 uint8_t sreg = SREG;
210 cli();
211 pbuf_head = pbuf_tail = 0;
212 SREG = sreg;
213}
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index 099964ae5..a43755f89 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[] = {
237 HID_RI_END_COLLECTION(0), 237 HID_RI_END_COLLECTION(0),
238#endif 238#endif
239 239
240#ifdef PROGRAMMABLE_BUTTON_ENABLE
241 HID_RI_USAGE_PAGE(8, 0x0C), // Consumer
242 HID_RI_USAGE(8, 0x01), // Consumer Control
243 HID_RI_COLLECTION(8, 0x01), // Application
244 HID_RI_REPORT_ID(8, REPORT_ID_PROGRAMMABLE_BUTTON),
245 HID_RI_USAGE(8, 0x03), // Programmable Buttons
246 HID_RI_COLLECTION(8, 0x04), // Named Array
247 HID_RI_USAGE_PAGE(8, 0x09), // Button
248 HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
249 HID_RI_USAGE_MAXIMUM(8, 0x20), // Button 32
250 HID_RI_LOGICAL_MINIMUM(8, 0x00),
251 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
252 HID_RI_REPORT_COUNT(8, 32),
253 HID_RI_REPORT_SIZE(8, 1),
254 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
255 HID_RI_END_COLLECTION(0),
256 HID_RI_END_COLLECTION(0),
257#endif
258
240#ifdef NKRO_ENABLE 259#ifdef NKRO_ENABLE
241 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop 260 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
242 HID_RI_USAGE(8, 0x06), // Keyboard 261 HID_RI_USAGE(8, 0x06), // Keyboard
diff --git a/tmk_core/protocol/usb_hid/parser.h b/tmk_core/protocol/usb_hid/parser.h
index 036281fa6..ba35b7af5 100644
--- a/tmk_core/protocol/usb_hid/parser.h
+++ b/tmk_core/protocol/usb_hid/parser.h
@@ -1,5 +1,4 @@
1#ifndef PARSER_H 1#pragma once
2#define PARSER_H
3 2
4#include "hid.h" 3#include "hid.h"
5#include "report.h" 4#include "report.h"
@@ -11,5 +10,3 @@ public:
11 uint16_t time_stamp; 10 uint16_t time_stamp;
12 virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); 11 virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
13}; 12};
14
15#endif
diff --git a/tmk_core/protocol/usb_hid/usb_hid.h b/tmk_core/protocol/usb_hid/usb_hid.h
index 083b68d1f..5cb5f5d03 100644
--- a/tmk_core/protocol/usb_hid/usb_hid.h
+++ b/tmk_core/protocol/usb_hid/usb_hid.h
@@ -1,10 +1,6 @@
1#ifndef USB_HID_H 1#pragma once
2#define USB_HID_H
3 2
4#include "report.h" 3#include "report.h"
5 4
6
7extern report_keyboard_t usb_hid_keyboard_report; 5extern report_keyboard_t usb_hid_keyboard_report;
8extern uint16_t usb_hid_time_stamp; 6extern uint16_t usb_hid_time_stamp;
9
10#endif
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index 485b20c90..e4db5d065 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);
226static void send_mouse(report_mouse_t *report); 226static void send_mouse(report_mouse_t *report);
227static void send_system(uint16_t data); 227static void send_system(uint16_t data);
228static void send_consumer(uint16_t data); 228static void send_consumer(uint16_t data);
229static void send_programmable_button(uint32_t data);
229 230
230static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; 231static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};
231 232
232host_driver_t *vusb_driver(void) { return &driver; } 233host_driver_t *vusb_driver(void) { return &driver; }
233 234
@@ -296,6 +297,19 @@ void send_digitizer(report_digitizer_t *report) {
296#ifdef DIGITIZER_ENABLE 297#ifdef DIGITIZER_ENABLE
297 if (usbInterruptIsReadyShared()) { 298 if (usbInterruptIsReadyShared()) {
298 usbSetInterruptShared((void *)report, sizeof(report_digitizer_t)); 299 usbSetInterruptShared((void *)report, sizeof(report_digitizer_t));
300#endif
301}
302
303static void send_programmable_button(uint32_t data) {
304#ifdef PROGRAMMABLE_BUTTON_ENABLE
305 static report_programmable_button_t report = {
306 .report_id = REPORT_ID_PROGRAMMABLE_BUTTON,
307 };
308
309 report.usage = data;
310
311 if (usbInterruptIsReadyShared()) {
312 usbSetInterruptShared((void *)&report, sizeof(report));
299 } 313 }
300#endif 314#endif
301} 315}
@@ -558,6 +572,26 @@ const PROGMEM uchar shared_hid_report[] = {
558 0xC0 // End Collection 572 0xC0 // End Collection
559#endif 573#endif
560 574
575#ifdef PROGRAMMABLE_BUTTON_ENABLE
576 // Programmable buttons report descriptor
577 0x05, 0x0C, // Usage Page (Consumer)
578 0x09, 0x01, // Usage (Consumer Control)
579 0xA1, 0x01, // Collection (Application)
580 0x85, REPORT_ID_PROGRAMMABLE_BUTTON, // Report ID
581 0x09, 0x03, // Usage (Programmable Buttons)
582 0xA1, 0x04, // Collection (Named Array)
583 0x05, 0x09, // Usage Page (Button)
584 0x19, 0x01, // Usage Minimum (Button 1)
585 0x29, 0x20, // Usage Maximum (Button 32)
586 0x15, 0x00, // Logical Minimum (0)
587 0x25, 0x01, // Logical Maximum (1)
588 0x95, 0x20, // Report Count (32)
589 0x75, 0x01, // Report Size (1)
590 0x81, 0x02, // Input (Data, Variable, Absolute)
591 0xC0, // End Collection
592 0xC0 // End Collection
593#endif
594
561#ifdef SHARED_EP_ENABLE 595#ifdef SHARED_EP_ENABLE
562}; 596};
563#endif 597#endif
diff --git a/tmk_core/protocol/xt.h b/tmk_core/protocol/xt.h
deleted file mode 100644
index 538ff0e45..000000000
--- a/tmk_core/protocol/xt.h
+++ /dev/null
@@ -1,73 +0,0 @@
1/*
2Copyright 2018 Jun WAKO <wakojun@gmail.com>
3Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
4
5This software is licensed with a Modified BSD License.
6All of this is supposed to be Free Software, Open Source, DFSG-free,
7GPL-compatible, and OK to use in both free and proprietary applications.
8Additions and corrections to this file are welcome.
9
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions are met:
13
14* Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16
17* Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in
19 the documentation and/or other materials provided with the
20 distribution.
21
22* Neither the name of the copyright holders nor the names of
23 contributors may be used to endorse or promote products derived
24 from this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36POSSIBILITY OF SUCH DAMAGE.
37*/
38
39#pragma once
40
41#include "quantum.h"
42
43#define XT_DATA_IN() \
44 do { \
45 setPinInput(XT_DATA_PIN); \
46 writePinHigh(XT_DATA_PIN); \
47 } while (0)
48
49#define XT_DATA_READ() readPin(XT_DATA_PIN)
50
51#define XT_DATA_LO() \
52 do { \
53 writePinLow(XT_DATA_PIN); \
54 setPinOutput(XT_DATA_PIN); \
55 } while (0)
56
57#define XT_CLOCK_IN() \
58 do { \
59 setPinInput(XT_CLOCK_PIN); \
60 writePinHigh(XT_CLOCK_PIN); \
61 } while (0)
62
63#define XT_CLOCK_READ() readPin(XT_CLOCK_PIN)
64
65#define XT_CLOCK_LO() \
66 do { \
67 writePinLow(XT_CLOCK_PIN); \
68 setPinOutput(XT_CLOCK_PIN); \
69 } while (0)
70
71void xt_host_init(void);
72
73uint8_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 ba9d71848..000000000
--- a/tmk_core/protocol/xt_interrupt.c
+++ /dev/null
@@ -1,166 +0,0 @@
1/*
2Copyright 2018 Jun WAKO <wakojun@gmail.com>
3Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
4
5This software is licensed with a Modified BSD License.
6All of this is supposed to be Free Software, Open Source, DFSG-free,
7GPL-compatible, and OK to use in both free and proprietary applications.
8Additions and corrections to this file are welcome.
9
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions are met:
13
14* Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16
17* Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in
19 the documentation and/or other materials provided with the
20 distribution.
21
22* Neither the name of the copyright holders nor the names of
23 contributors may be used to endorse or promote products derived
24 from this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36POSSIBILITY OF SUCH DAMAGE.
37*/
38
39#include <stdbool.h>
40#include <avr/interrupt.h>
41#include "xt.h"
42#include "wait.h"
43#include "debug.h"
44
45static inline uint8_t pbuf_dequeue(void);
46static inline void pbuf_enqueue(uint8_t data);
47static inline bool pbuf_has_data(void);
48static inline void pbuf_clear(void);
49
50void xt_host_init(void) {
51 XT_INT_INIT();
52 XT_INT_OFF();
53
54 /* hard reset */
55#ifdef XT_RESET
56 XT_RESET();
57#endif
58
59 /* soft reset: pull clock line down for 20ms */
60 XT_DATA_LO();
61 XT_CLOCK_LO();
62 wait_ms(20);
63
64 /* input mode with pullup */
65 XT_CLOCK_IN();
66 XT_DATA_IN();
67
68 XT_INT_ON();
69}
70
71/* get data received by interrupt */
72uint8_t xt_host_recv(void) {
73 if (pbuf_has_data()) {
74 return pbuf_dequeue();
75 } else {
76 return 0;
77 }
78}
79
80ISR(XT_INT_VECT) {
81 /*
82 * XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data,
83 * which should be read on falling edge of clock.
84 *
85 * start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7
86 *
87 * Original IBM XT keyboard sends start(0) bit while some of clones don't.
88 * Start(0) bit is read as low on data line while start(1) as high.
89 *
90 * https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
91 */
92 static enum { START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7 } state = START;
93 static uint8_t data = 0;
94
95 uint8_t dbit = XT_DATA_READ();
96
97 // This is needed if using PCINT which can be called on both falling and rising edge
98 // if (XT_CLOCK_READ()) return;
99
100 switch (state) {
101 case START:
102 // ignore start(0) bit
103 if (!dbit) return;
104 break;
105 case BIT0 ... BIT7:
106 data >>= 1;
107 if (dbit) data |= 0x80;
108 break;
109 }
110 if (state++ == BIT7) {
111 pbuf_enqueue(data);
112 state = START;
113 data = 0;
114 }
115 return;
116}
117
118/*--------------------------------------------------------------------
119 * Ring buffer to store scan codes from keyboard
120 *------------------------------------------------------------------*/
121#define PBUF_SIZE 32
122static uint8_t pbuf[PBUF_SIZE];
123static uint8_t pbuf_head = 0;
124static uint8_t pbuf_tail = 0;
125
126static inline void pbuf_enqueue(uint8_t data) {
127 uint8_t sreg = SREG;
128 cli();
129 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
130 if (next != pbuf_tail) {
131 pbuf[pbuf_head] = data;
132 pbuf_head = next;
133 } else {
134 dprintf("pbuf: full\n");
135 }
136 SREG = sreg;
137}
138
139static inline uint8_t pbuf_dequeue(void) {
140 uint8_t val = 0;
141
142 uint8_t sreg = SREG;
143 cli();
144 if (pbuf_head != pbuf_tail) {
145 val = pbuf[pbuf_tail];
146 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
147 }
148 SREG = sreg;
149
150 return val;
151}
152
153static inline bool pbuf_has_data(void) {
154 uint8_t sreg = SREG;
155 cli();
156 bool has_data = (pbuf_head != pbuf_tail);
157 SREG = sreg;
158 return has_data;
159}
160
161static inline void pbuf_clear(void) {
162 uint8_t sreg = SREG;
163 cli();
164 pbuf_head = pbuf_tail = 0;
165 SREG = sreg;
166}
diff --git a/tmk_core/readme.md b/tmk_core/readme.md
index a754cfee4..a47dc8818 100644
--- a/tmk_core/readme.md
+++ b/tmk_core/readme.md
@@ -25,7 +25,6 @@ These features can be used in your keyboard.
25* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc 25* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
26* USB NKRO - 248 keys(+ 8 modifiers) simultaneously 26* USB NKRO - 248 keys(+ 8 modifiers) simultaneously
27* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device 27* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
28* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
29* User Function - Customizable function of key with writing code 28* User Function - Customizable function of key with writing code
30* Macro - Very primitive at this time 29* Macro - Very primitive at this time
31* Keyboard Tricks - Oneshot modifier and modifier with tapping feature 30* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
@@ -84,9 +83,9 @@ Architecture
84 / /| Keys/Mouse | Protocol |d| | Action | | | Protocol | 83 / /| Keys/Mouse | Protocol |d| | Action | | | Protocol |
85 /__________/ |<-----------| LUFA |r| | Layer, Tap | | | Matrix | 84 /__________/ |<-----------| LUFA |r| | Layer, Tap | | | Matrix |
86 |.--------.| | LED | V-USB |i| |-------------| | | PS/2,IBM | __________________ 85 |.--------.| | LED | V-USB |i| |-------------| | | PS/2,IBM | __________________
87 || || |----------->| UART |v| | Keymap | | | ADB,M0110| Keys / /_/_/_/_/_/_/_/ /| 86 || || |----------->| UART |v| | Keymap | | | | Keys / /_/_/_/_/_/_/_/ /|
88 || Host || | Console | |e| | Mousekey | | | SUN/NEWS |<----------/ /_/_/_/_/_/_/_/ / / 87 || Host || | Console | |e| | Mousekey | | | |<----------/ /_/_/_/_/_/_/_/ / /
89 ||________||/.<-----------| |r| | Report | | | X68K/PC98| Control / /_/_/_/_/_/_/_/ / / 88 ||________||/.<-----------| |r| | Report | | | | Control / /_/_/_/_/_/_/_/ / /
90 `_========_'/| |---------------------------------------------|-------->/___ /_______/ ___/ / 89 `_========_'/| |---------------------------------------------|-------->/___ /_______/ ___/ /
91 |_o______o_|/ | Sendchar, Print, Debug, Command, ... | |_________________|/ 90 |_o______o_|/ | Sendchar, Print, Debug, Command, ... | |_________________|/
92 +---------------------------------------------+ Keyboard 91 +---------------------------------------------+ Keyboard
@@ -134,10 +133,6 @@ Files and Directories
134* lufa/ - LUFA USB stack 133* lufa/ - LUFA USB stack
135* vusb/ - Objective Development V-USB 134* vusb/ - Objective Development V-USB
136* ps2.c - PS/2 protocol 135* ps2.c - PS/2 protocol
137* adb.c - Apple Desktop Bus protocol
138* m0110.c - Macintosh 128K/512K/Plus keyboard protocol
139* news.c - Sony NEWS keyboard protocol
140* x68k.c - Sharp X68000 keyboard protocol
141* serial_soft.c - Asynchronous Serial protocol implemented by software 136* serial_soft.c - Asynchronous Serial protocol implemented by software
142 137
143 138
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index 5a629d1eb..56a331e28 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -69,8 +69,11 @@ CSTANDARD = -std=gnu99
69#CXXDEFS += -D__STDC_CONSTANT_MACROS 69#CXXDEFS += -D__STDC_CONSTANT_MACROS
70#CXXDEFS += 70#CXXDEFS +=
71 71
72 72# Speed up recompilations by opt-in usage of ccache
73 73USE_CCACHE ?= no
74ifneq ($(USE_CCACHE),no)
75 CC_PREFIX ?= ccache
76endif
74 77
75#---------------- Compiler Options C ---------------- 78#---------------- Compiler Options C ----------------
76# -g*: generate debugging information 79# -g*: generate debugging information