Merge upstream QMK Firmware at '0.12.52~1'

This commit is contained in:
Drashna Jael're
2021-06-29 12:23:03 -07:00
415 changed files with 18692 additions and 7301 deletions

View File

@@ -154,38 +154,45 @@ dfu-split-left: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size
dfu-split-right: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size
$(call EXEC_DFU,eeprom-righthand.eep)
AVRDUDE_PROGRAMMER ?= avrdude
define EXEC_AVRDUDE
USB= ;\
if $(GREP) -q -s Microsoft /proc/version; then \
echo 'ERROR: AVR flashing cannot be automated within the Windows Subsystem for Linux (WSL) currently. Instead, take the .hex file generated and flash it using QMK Toolbox, AVRDUDE, AVRDUDESS, or XLoader.'; \
else \
printf "Detecting USB port, reset your controller now."; \
TMP1=`mktemp`; \
TMP2=`mktemp`; \
ls /dev/tty* > $$TMP1; \
while [ -z $$USB ]; do \
sleep 0.5; \
printf "."; \
ls /dev/tty* > $$TMP2; \
USB=`comm -13 $$TMP1 $$TMP2 | $(GREP) -o '/dev/tty.*'`; \
mv $$TMP2 $$TMP1; \
done; \
rm $$TMP1; \
echo ""; \
echo "Device $$USB has appeared; assuming it is the controller."; \
if $(GREP) -q -s 'MINGW\|MSYS' /proc/version; then \
USB=`echo "$$USB" | perl -pne 's/\/dev\/ttyS(\d+)/COM.($$1+1)/e'`; \
echo "Remapped MSYS2 USB port to $$USB"; \
sleep 1; \
list_devices() { \
if $(GREP) -q -s icrosoft /proc/version; then \
wmic.exe path Win32_SerialPort get DeviceID 2>/dev/null | LANG=C perl -pne 's/COM(\d+)/COM.($$1-1)/e' | sed 's!COM!/dev/ttyS!' | xargs echo -n | sort; \
elif [ "`uname`" = "FreeBSD" ]; then \
ls /dev/tty* | grep -v '\.lock$$' | grep -v '\.init$$'; \
else \
printf "Waiting for $$USB to become writable."; \
while [ ! -w "$$USB" ]; do sleep 0.5; printf "."; done; echo ""; \
ls /dev/tty*; \
fi; \
if [ -z "$(1)" ]; then \
avrdude -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex; \
else \
avrdude -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex -U eeprom:w:$(QUANTUM_PATH)/split_common/$(1); \
fi \
}; \
USB= ;\
printf "Detecting USB port, reset your controller now."; \
TMP1=`mktemp`; \
TMP2=`mktemp`; \
list_devices > $$TMP1; \
while [ -z "$$USB" ]; do \
sleep 0.5; \
printf "."; \
list_devices > $$TMP2; \
USB=`comm -13 $$TMP1 $$TMP2 | $(GREP) -o '/dev/tty.*'`; \
mv $$TMP2 $$TMP1; \
done; \
rm $$TMP1; \
echo ""; \
echo "Device $$USB has appeared; assuming it is the controller."; \
if $(GREP) -q -s 'MINGW\|MSYS\|icrosoft' /proc/version; then \
USB=`echo "$$USB" | LANG=C perl -pne 's/\/dev\/ttyS(\d+)/COM.($$1+1)/e'`; \
echo "Remapped USB port to $$USB"; \
sleep 1; \
else \
printf "Waiting for $$USB to become writable."; \
while [ ! -w "$$USB" ]; do sleep 0.5; printf "."; done; echo ""; \
fi; \
if [ -z "$(1)" ]; then \
$(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex; \
else \
$(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex -U eeprom:w:$(QUANTUM_PATH)/split_common/$(1); \
fi
endef
@@ -204,7 +211,7 @@ avrdude-split-right: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
$(call EXEC_AVRDUDE,eeprom-righthand.eep)
define EXEC_USBASP
avrdude -p $(MCU) -c usbasp -U flash:w:$(BUILD_DIR)/$(TARGET).hex
$(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU) -c usbasp -U flash:w:$(BUILD_DIR)/$(TARGET).hex
endef
usbasp: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
@@ -283,8 +290,11 @@ extcoff: $(BUILD_DIR)/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof
bootloader:
ifneq ($(strip $(BOOTLOADER)), qmk-dfu)
$(error Please set BOOTLOADER = qmk-dfu first!)
endif
make -C lib/lufa/Bootloaders/DFU/ clean
$(TMK_DIR)/make_dfu_header.sh $(ALL_CONFIGS)
bin/qmk generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h
$(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
$(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0))
$(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0))

View File

@@ -71,6 +71,9 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/board/board.mk)","
BOARD_PATH = $(TOP_DIR)/platforms/chibios/$(BOARD)
BOARD_MK += $(TOP_DIR)/platforms/chibios/$(BOARD)/board/board.mk
KEYBOARD_PATHS += $(BOARD_PATH)/configs
ifneq ("$(wildcard $(BOARD_PATH)/rules.mk)","")
include $(BOARD_PATH)/rules.mk
endif
endif
ifeq ("$(wildcard $(BOARD_MK))","")
@@ -309,6 +312,7 @@ LDFLAGS += -mno-thumb-interwork -mthumb
LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS)
LDFLAGS += --specs=nano.specs
OPT_DEFS += -DPROTOCOL_CHIBIOS

View File

@@ -10,27 +10,20 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/action_macro.c \
$(COMMON_DIR)/action_layer.c \
$(COMMON_DIR)/action_util.c \
$(COMMON_DIR)/print.c \
$(COMMON_DIR)/debug.c \
$(COMMON_DIR)/sendchar_null.c \
$(COMMON_DIR)/util.c \
$(COMMON_DIR)/eeconfig.c \
$(COMMON_DIR)/report.c \
$(PLATFORM_COMMON_DIR)/suspend.c \
$(PLATFORM_COMMON_DIR)/timer.c \
$(COMMON_DIR)/sync_timer.c \
$(PLATFORM_COMMON_DIR)/bootloader.c \
ifeq ($(PLATFORM),AVR)
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/xprintf.S
else ifeq ($(PLATFORM),CHIBIOS)
TMK_COMMON_SRC += $(PRINTF_PATH)/printf.c
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_FLOAT
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T
VPATH += $(PRINTF_PATH)
else ifeq ($(PLATFORM),ARM_ATSAM)
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c
# Use platform provided print - fall back to lib/printf
ifneq ("$(wildcard $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk)","")
include $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk
else
include $(TMK_PATH)/$(COMMON_DIR)/lib_printf.mk
endif
# Option modules
@@ -67,10 +60,6 @@ ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes)
endif
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
TMK_COMMON_SRC += $(COMMON_DIR)/mousekey.c
TMK_COMMON_DEFS += -DMOUSEKEY_ENABLE
TMK_COMMON_DEFS += -DMOUSE_ENABLE
ifeq ($(strip $(MOUSE_SHARED_EP)), yes)
TMK_COMMON_DEFS += -DMOUSE_SHARED_EP
SHARED_EP_ENABLE = yes
@@ -98,17 +87,16 @@ else
TMK_COMMON_DEFS += -DNO_DEBUG
endif
ifeq ($(strip $(COMMAND_ENABLE)), yes)
TMK_COMMON_SRC += $(COMMON_DIR)/command.c
TMK_COMMON_DEFS += -DCOMMAND_ENABLE
endif
ifeq ($(strip $(NKRO_ENABLE)), yes)
ifneq ($(PROTOCOL),VUSB)
ifeq ($(PROTOCOL), VUSB)
$(info NKRO is not currently supported on V-USB, and has been disabled.)
else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
$(info NKRO is not currently supported with Bluetooth, and has been disabled.)
else ifneq ($(BLUETOOTH),)
$(info NKRO is not currently supported with Bluetooth, and has been disabled.)
else
TMK_COMMON_DEFS += -DNKRO_ENABLE
SHARED_EP_ENABLE = yes
else
$(info NKRO is not currently supported on V-USB, and has been disabled.)
endif
endif

View File

@@ -47,10 +47,6 @@ int tp_buttons;
int retro_tapping_counter = 0;
#endif
#ifdef FAUXCLICKY_ENABLE
# include "fauxclicky.h"
#endif
#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; }
#endif
@@ -80,15 +76,10 @@ void action_exec(keyevent_t event) {
#endif
}
#ifdef FAUXCLICKY_ENABLE
if (IS_PRESSED(event)) {
FAUXCLICKY_ACTION_PRESS;
if (event.pressed) {
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();
}
if (IS_RELEASED(event)) {
FAUXCLICKY_ACTION_RELEASE;
}
fauxclicky_check();
#endif
#ifdef SWAP_HANDS_ENABLE
if (!IS_NOEVENT(event)) {
@@ -251,11 +242,6 @@ void process_action(keyrecord_t *record, action_t action) {
uint8_t tap_count = record->tap.count;
#endif
if (event.pressed) {
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();
}
#ifndef NO_ACTION_ONESHOT
bool do_release_oneshot = false;
// notice we only clear the one shot layer if the pressed key is not a modifier.
@@ -424,56 +410,22 @@ void process_action(keyrecord_t *record, action_t action) {
case ACT_MOUSEKEY:
if (event.pressed) {
mousekey_on(action.key.code);
switch (action.key.code) {
# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE)
case KC_MS_BTN1:
register_button(true, MOUSE_BTN1);
break;
case KC_MS_BTN2:
register_button(true, MOUSE_BTN2);
break;
case KC_MS_BTN3:
register_button(true, MOUSE_BTN3);
break;
# endif
# ifdef POINTING_DEVICE_ENABLE
case KC_MS_BTN4:
register_button(true, MOUSE_BTN4);
break;
case KC_MS_BTN5:
register_button(true, MOUSE_BTN5);
break;
# endif
default:
mousekey_send();
break;
}
} else {
mousekey_off(action.key.code);
switch (action.key.code) {
}
switch (action.key.code) {
# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE)
case KC_MS_BTN1:
register_button(false, MOUSE_BTN1);
break;
case KC_MS_BTN2:
register_button(false, MOUSE_BTN2);
break;
case KC_MS_BTN3:
register_button(false, MOUSE_BTN3);
break;
# ifdef POINTING_DEVICE_ENABLE
case KC_MS_BTN1 ... KC_MS_BTN8:
# else
case KC_MS_BTN1 ... KC_MS_BTN3:
# endif
register_button(event.pressed, MOUSE_BTN_MASK(action.key.code - KC_MS_BTN1));
break;
# endif
# ifdef POINTING_DEVICE_ENABLE
case KC_MS_BTN4:
register_button(false, MOUSE_BTN4);
break;
case KC_MS_BTN5:
register_button(false, MOUSE_BTN5);
break;
# endif
default:
mousekey_send();
break;
}
default:
mousekey_send();
break;
}
break;
#endif
@@ -936,23 +888,28 @@ void unregister_code(uint8_t code) {
#endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)
/** \brief Tap a keycode with a delay.
*
* FIXME: Needs documentation.
* \param code The basic keycode to tap.
* \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it.
*/
void tap_code(uint8_t code) {
void tap_code_delay(uint8_t code, uint16_t delay) {
register_code(code);
if (code == KC_CAPS) {
wait_ms(TAP_HOLD_CAPS_DELAY);
} else {
wait_ms(TAP_CODE_DELAY);
for (uint16_t i = delay; i > 0; i--) {
wait_ms(1);
}
unregister_code(code);
}
/** \brief Tap a keycode with the default delay.
*
* \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
*/
void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
*
* \param mods A bitfield of modifiers to unregister.
* \param mods A bitfield of modifiers to register.
*/
void register_mods(uint8_t mods) {
if (mods) {
@@ -972,6 +929,7 @@ void unregister_mods(uint8_t mods) {
}
}
/** \brief Adds the given weak modifiers and sends a keyboard report immediately.
*
* \param mods A bitfield of modifiers to register.
@@ -1017,6 +975,10 @@ void clear_keyboard_but_mods(void) {
* FIXME: Needs documentation.
*/
void clear_keyboard_but_mods_and_keys() {
#ifdef EXTRAKEY_ENABLE
host_system_send(0);
host_consumer_send(0);
#endif
clear_weak_mods();
clear_macro_mods();
send_keyboard_report();
@@ -1024,10 +986,6 @@ void clear_keyboard_but_mods_and_keys() {
mousekey_clear();
mousekey_send();
#endif
#ifdef EXTRAKEY_ENABLE
host_system_send(0);
host_consumer_send(0);
#endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)

View File

@@ -100,6 +100,7 @@ void process_action(keyrecord_t *record, action_t action);
void register_code(uint8_t code);
void unregister_code(uint8_t code);
void tap_code(uint8_t code);
void tap_code_delay(uint8_t code, uint16_t delay);
void register_mods(uint8_t mods);
void unregister_mods(uint8_t mods);
void register_weak_mods(uint8_t mods);

View File

@@ -120,14 +120,21 @@ bool process_tapping(keyrecord_t *keyp) {
* useful for long TAPPING_TERM but may prevent fast typing.
*/
# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY)
else if (
else if (((
# ifdef TAPPING_TERM_PER_KEY
(get_tapping_term(get_event_keycode(tapping_key.event, false), keyp) >= 500) &&
get_tapping_term(get_event_keycode(tapping_key.event, false), keyp)
# else
TAPPING_TERM
# endif
>= 500)
# ifdef PERMISSIVE_HOLD_PER_KEY
!get_permissive_hold(get_event_keycode(tapping_key.event, false), keyp) &&
|| get_permissive_hold(get_event_keycode(tapping_key.event, false), keyp)
# elif defined(PERMISSIVE_HOLD)
|| true
# endif
IS_RELEASED(event) && waiting_buffer_typed(event)) {
) &&
IS_RELEASED(event) && waiting_buffer_typed(event)) {
debug("Tapping: End. No tap. Interfered by typing key\n");
process_record(&tapping_key);
tapping_key = (keyrecord_t){};

View File

@@ -1,4 +1,4 @@
/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
/* Copyright 2012 Jun Wako <wakojun@gmail.com> */
/* Very basic print functions, intended to be used with usb_debug_only.c
* http://www.pjrc.com/teensy/
* Copyright (c) 2008 PJRC.COM, LLC
@@ -21,27 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include "print.h"
#include "arm_atsam/printf.h"
#ifndef NO_PRINT
# if defined(__AVR__)
# define sendchar(c) xputc(c)
void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { xdev_out(sendchar_func); }
# elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
// don't need anything extra
# elif defined(__arm__) /* __AVR__ */
// TODO
// void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
# endif /* __AVR__ */
#endif
// Create user & normal print defines
#define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
#define print(s) __xprintf(s)
#define println(s) __xprintf(s "\r\n")
#define uprint(s) __xprintf(s)
#define uprintln(s) __xprintf(s "\r\n")
#define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)

View File

@@ -15,11 +15,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "printf.h"
#include "sendchar.h"
#ifdef CONSOLE_ENABLE
# include "samd51j18a.h"
# include "arm_atsam_protocol.h"
# include "printf.h"
# include <string.h>
# include <stdarg.h>
@@ -66,3 +68,8 @@ void console_printf(char *fmt, ...) {
}
#endif // CONSOLE_ENABLE
<<<<<<< HEAD
=======
void print_set_sendchar(sendchar_func_t send) {}
>>>>>>> 0.12.52~1

View File

@@ -0,0 +1 @@
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c

View File

@@ -7,7 +7,8 @@
*
* FIXME: needs doc
*/
void suspend_idle(uint8_t time) { /* Note: Not used anywhere currently */ }
void suspend_idle(uint8_t time) { /* Note: Not used anywhere currently */
}
/** \brief Run user level Power down
*

View File

@@ -0,0 +1,32 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// Macro to help make GPIO and other controls atomic.
#ifndef IGNORE_ATOMIC_BLOCK
# if __has_include_next("atomic_util.h")
# include_next "atomic_util.h" /* Include the platforms atomic.h */
# else
# define ATOMIC_BLOCK _Static_assert(0, "ATOMIC_BLOCK not implemented")
# define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE not implemented")
# define ATOMIC_BLOCK_FORCEON _Static_assert(0, "ATOMIC_BLOCK_FORCEON not implemented")
# endif
#else /* do nothing atomic macro */
# define ATOMIC_BLOCK for (uint8_t __ToDo = 1; __ToDo; __ToDo = 0)
# define ATOMIC_BLOCK_RESTORESTATE ATOMIC_BLOCK
# define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK
#endif

View File

@@ -0,0 +1,33 @@
/* Copyright 2012 Jun Wako <wakojun@gmail.com> */
/* Very basic print functions, intended to be used with usb_debug_only.c
* http://www.pjrc.com/teensy/
* Copyright (c) 2008 PJRC.COM, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "avr/xprintf.h"
// Create user & normal print defines
#define print(s) xputs(PSTR(s))
#define println(s) xputs(PSTR(s "\r\n"))
#define uprint(s) xputs(PSTR(s))
#define uprintln(s) xputs(PSTR(s "\r\n"))
#define uprintf(fmt, ...) __xprintf(PSTR(fmt), ##__VA_ARGS__)

View File

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

View File

@@ -77,7 +77,7 @@ uint32_t reset_key __attribute__((section(".noinit,\"aw\",@nobits;")));
*
* FIXME: needs doc
*/
void bootloader_jump(void) {
__attribute__((weak)) void bootloader_jump(void) {
#if !defined(BOOTLOADER_SIZE)
uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);

View File

@@ -0,0 +1,34 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <avr/io.h>
#include "pin_defs.h"
typedef uint8_t pin_t;
#define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low")
#define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
#define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
#define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
#define writePin(pin, level) ((level) ? writePinHigh(pin) : writePinLow(pin))
#define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
#define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))

View File

@@ -0,0 +1,128 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <avr/io.h>
#define PORT_SHIFTER 4 // this may be 4 for all AVR chips
// If you want to add more to this list, reference the PINx definitions in these header
// files: https://github.com/vancegroup-mirrors/avr-libc/tree/master/avr-libc/include/avr
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
# define ADDRESS_BASE 0x00
# define PINB_ADDRESS 0x3
# define PINC_ADDRESS 0x6
# define PIND_ADDRESS 0x9
# define PINE_ADDRESS 0xC
# define PINF_ADDRESS 0xF
#elif defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
# define ADDRESS_BASE 0x00
# define PINB_ADDRESS 0x3
# define PINC_ADDRESS 0x6
# define PIND_ADDRESS 0x9
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
# define ADDRESS_BASE 0x00
# define PINA_ADDRESS 0x0
# define PINB_ADDRESS 0x3
# define PINC_ADDRESS 0x6
# define PIND_ADDRESS 0x9
# define PINE_ADDRESS 0xC
# define PINF_ADDRESS 0xF
#elif defined(__AVR_ATmega32A__)
# define ADDRESS_BASE 0x10
# define PIND_ADDRESS 0x0
# define PINC_ADDRESS 0x3
# define PINB_ADDRESS 0x6
# define PINA_ADDRESS 0x9
#elif defined(__AVR_ATtiny85__)
# define ADDRESS_BASE 0x10
# define PINB_ADDRESS 0x6
#else
# error "Pins are not defined"
#endif
#define PINDEF(port, pin) ((PIN##port##_ADDRESS << PORT_SHIFTER) | pin)
#define _PIN_ADDRESS(p, offset) _SFR_IO8(ADDRESS_BASE + ((p) >> PORT_SHIFTER) + (offset))
// Port X Input Pins Address
#define PINx_ADDRESS(p) _PIN_ADDRESS(p, 0)
// Port X Data Direction Register, 0:input 1:output
#define DDRx_ADDRESS(p) _PIN_ADDRESS(p, 1)
// Port X Data Register
#define PORTx_ADDRESS(p) _PIN_ADDRESS(p, 2)
/* I/O pins */
#ifdef PORTA
# define A0 PINDEF(A, 0)
# define A1 PINDEF(A, 1)
# define A2 PINDEF(A, 2)
# define A3 PINDEF(A, 3)
# define A4 PINDEF(A, 4)
# define A5 PINDEF(A, 5)
# define A6 PINDEF(A, 6)
# define A7 PINDEF(A, 7)
#endif
#ifdef PORTB
# define B0 PINDEF(B, 0)
# define B1 PINDEF(B, 1)
# define B2 PINDEF(B, 2)
# define B3 PINDEF(B, 3)
# define B4 PINDEF(B, 4)
# define B5 PINDEF(B, 5)
# define B6 PINDEF(B, 6)
# define B7 PINDEF(B, 7)
#endif
#ifdef PORTC
# define C0 PINDEF(C, 0)
# define C1 PINDEF(C, 1)
# define C2 PINDEF(C, 2)
# define C3 PINDEF(C, 3)
# define C4 PINDEF(C, 4)
# define C5 PINDEF(C, 5)
# define C6 PINDEF(C, 6)
# define C7 PINDEF(C, 7)
#endif
#ifdef PORTD
# define D0 PINDEF(D, 0)
# define D1 PINDEF(D, 1)
# define D2 PINDEF(D, 2)
# define D3 PINDEF(D, 3)
# define D4 PINDEF(D, 4)
# define D5 PINDEF(D, 5)
# define D6 PINDEF(D, 6)
# define D7 PINDEF(D, 7)
#endif
#ifdef PORTE
# define E0 PINDEF(E, 0)
# define E1 PINDEF(E, 1)
# define E2 PINDEF(E, 2)
# define E3 PINDEF(E, 3)
# define E4 PINDEF(E, 4)
# define E5 PINDEF(E, 5)
# define E6 PINDEF(E, 6)
# define E7 PINDEF(E, 7)
#endif
#ifdef PORTF
# define F0 PINDEF(F, 0)
# define F1 PINDEF(F, 1)
# define F2 PINDEF(F, 2)
# define F3 PINDEF(F, 3)
# define F4 PINDEF(F, 4)
# define F5 PINDEF(F, 5)
# define F6 PINDEF(F, 6)
# define F7 PINDEF(F, 7)
#endif

View File

@@ -14,34 +14,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "xprintf.h"
#include "sendchar.h"
#pragma once
#include <stdint.h>
// convert to L string
#define LSTR(s) XLSTR(s)
#define XLSTR(s) L## #s
// convert to string
#define STR(s) XSTR(s)
#define XSTR(s) #s
#ifdef __cplusplus
extern "C" {
#endif
uint8_t bitpop(uint8_t bits);
uint8_t bitpop16(uint16_t bits);
uint8_t bitpop32(uint32_t bits);
uint8_t biton(uint8_t bits);
uint8_t biton16(uint16_t bits);
uint8_t biton32(uint32_t bits);
uint8_t bitrev(uint8_t bits);
uint16_t bitrev16(uint16_t bits);
uint32_t bitrev32(uint32_t bits);
#ifdef __cplusplus
}
#endif
void print_set_sendchar(sendchar_func_t func) { xdev_out(func); }

View File

@@ -0,0 +1,2 @@
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/xprintf.S
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c

View File

@@ -90,7 +90,7 @@ void sleep_led_toggle(void) {
*
* (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
*
* http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
* https://www.wolframalpha.com/input/?i=sin%28x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
* (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
*/
static const uint8_t breathing_table[64] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

View File

@@ -4,7 +4,6 @@
#include <avr/interrupt.h>
#include "matrix.h"
#include "action.h"
#include "suspend_avr.h"
#include "suspend.h"
#include "timer.h"
#include "led.h"
@@ -13,6 +12,9 @@
#ifdef PROTOCOL_LUFA
# include "lufa.h"
#endif
#ifdef PROTOCOL_VUSB
# include "vusb.h"
#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
@@ -52,7 +54,25 @@ __attribute__((weak)) void suspend_power_down_user(void) {}
*/
__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
#ifndef NO_SUSPEND_POWER_DOWN
#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
// clang-format off
#define wdt_intr_enable(value) \
__asm__ __volatile__ ( \
"in __tmp_reg__,__SREG__" "\n\t" \
"cli" "\n\t" \
"wdr" "\n\t" \
"sts %0,%1" "\n\t" \
"out __SREG__,__tmp_reg__" "\n\t" \
"sts %0,%2" "\n\t" \
: /* no outputs */ \
: "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
"r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | _BV(WDIE) | (value & 0x07))) \
: "r0" \
)
// clang-format on
/** \brief Power down MCU with watchdog timer
*
* wdto: watchdog timer timeout defined in <avr/wdt.h>
@@ -74,35 +94,11 @@ static uint8_t wdt_timeout = 0;
* FIXME: needs doc
*/
static void power_down(uint8_t wdto) {
# ifdef PROTOCOL_LUFA
if (USB_DeviceState == DEVICE_STATE_Configured) return;
# endif
wdt_timeout = wdto;
// Watchdog Interrupt Mode
wdt_intr_enable(wdto);
# ifdef BACKLIGHT_ENABLE
backlight_set(0);
# endif
// Turn off LED indicators
uint8_t leds_off = 0;
# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
if (is_backlight_enabled()) {
// Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
leds_off |= (1 << USB_LED_CAPS_LOCK);
}
# endif
led_set(leds_off);
# ifdef AUDIO_ENABLE
stop_all_notes();
# endif /* AUDIO_ENABLE */
# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
rgblight_suspend();
# endif
// TODO: more power saving
// See PicoPower application note
// - I/O port input with pullup
@@ -125,10 +121,45 @@ static void power_down(uint8_t wdto) {
* FIXME: needs doc
*/
void suspend_power_down(void) {
#ifdef PROTOCOL_LUFA
if (USB_DeviceState == DEVICE_STATE_Configured) return;
#endif
#ifdef PROTOCOL_VUSB
if (!vusb_suspended) return;
#endif
suspend_power_down_kb();
#ifndef NO_SUSPEND_POWER_DOWN
// Turn off backlight
# ifdef BACKLIGHT_ENABLE
backlight_set(0);
# endif
// Turn off LED indicators
uint8_t leds_off = 0;
# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
if (is_backlight_enabled()) {
// Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
leds_off |= (1 << USB_LED_CAPS_LOCK);
}
# endif
led_set(leds_off);
// Turn off audio
# ifdef AUDIO_ENABLE
stop_all_notes();
# endif
// Turn off underglow
# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
rgblight_suspend();
# endif
// Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt)
# if defined(WDT_vect)
power_down(WDTO_15MS);
# endif
#endif
}
@@ -163,17 +194,24 @@ __attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_us
void suspend_wakeup_init(void) {
// clear keyboard state
clear_keyboard();
// Turn on backlight
#ifdef BACKLIGHT_ENABLE
backlight_init();
#endif
// Restore LED indicators
led_set(host_keyboard_leds());
// Wake up underglow
#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
rgblight_wakeup();
#endif
suspend_wakeup_init_kb();
}
#ifndef NO_SUSPEND_POWER_DOWN
#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
/* watchdog timeout */
ISR(WDT_vect) {
// compensate timer for sleep

View File

@@ -1,25 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
// clang-format off
#define wdt_intr_enable(value) \
__asm__ __volatile__ ( \
"in __tmp_reg__,__SREG__" "\n\t" \
"cli" "\n\t" \
"wdr" "\n\t" \
"sts %0,%1" "\n\t" \
"out __SREG__,__tmp_reg__" "\n\t" \
"sts %0,%2" "\n\t" \
: /* no outputs */ \
: "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
"r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
_BV(WDIE) | (value & 0x07)) ) \
: "r0" \
)
// clang-format on

View File

@@ -0,0 +1,37 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <ch.h>
static __inline__ uint8_t __interrupt_disable__(void) {
chSysLock();
return 1;
}
static __inline__ void __interrupt_enable__(const uint8_t *__s) {
chSysUnlock();
__asm__ volatile("" ::: "memory");
(void)__s;
}
#define ATOMIC_BLOCK(type) for (type, __ToDo = __interrupt_disable__(); __ToDo; __ToDo = 0)
#define ATOMIC_FORCEON uint8_t sreg_save __attribute__((__cleanup__(__interrupt_enable__))) = 0
#define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE not implemented")
#define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK(ATOMIC_FORCEON)

View File

@@ -363,7 +363,7 @@ void eeprom_initialize(void) {
return;
}
} while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
flashend = (uint32_t)(p - 1);
}
uint8_t eeprom_read_byte(const uint8_t *addr) {

View File

@@ -0,0 +1,34 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <hal.h>
#include "pin_defs.h"
typedef ioline_t pin_t;
#define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT)
#define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)
#define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)
#define setPinOutput(pin) palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)
#define writePinHigh(pin) palSetLine(pin)
#define writePinLow(pin) palClearLine(pin)
#define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin)))
#define readPin(pin) palReadLine(pin)
#define togglePin(pin) palToggleLine(pin)

View File

@@ -0,0 +1,242 @@
/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// Defines mapping for Proton C replacement
#ifdef CONVERT_TO_PROTON_C
// Left side (front)
# define D3 PAL_LINE(GPIOA, 9)
# define D2 PAL_LINE(GPIOA, 10)
// GND
// GND
# define D1 PAL_LINE(GPIOB, 7)
# define D0 PAL_LINE(GPIOB, 6)
# define D4 PAL_LINE(GPIOB, 5)
# define C6 PAL_LINE(GPIOB, 4)
# define D7 PAL_LINE(GPIOB, 3)
# define E6 PAL_LINE(GPIOB, 2)
# define B4 PAL_LINE(GPIOB, 1)
# define B5 PAL_LINE(GPIOB, 0)
// Right side (front)
// RAW
// GND
// RESET
// VCC
# define F4 PAL_LINE(GPIOA, 2)
# define F5 PAL_LINE(GPIOA, 1)
# define F6 PAL_LINE(GPIOA, 0)
# define F7 PAL_LINE(GPIOB, 8)
# define B1 PAL_LINE(GPIOB, 13)
# define B3 PAL_LINE(GPIOB, 14)
# define B2 PAL_LINE(GPIOB, 15)
# define B6 PAL_LINE(GPIOB, 9)
// LEDs (only D5/C13 uses an actual LED)
# ifdef CONVERT_TO_PROTON_C_RXLED
# define D5 PAL_LINE(GPIOC, 14)
# define B0 PAL_LINE(GPIOC, 13)
# else
# define D5 PAL_LINE(GPIOC, 13)
# define B0 PAL_LINE(GPIOC, 14)
# endif
#else
# define A0 PAL_LINE(GPIOA, 0)
# define A1 PAL_LINE(GPIOA, 1)
# define A2 PAL_LINE(GPIOA, 2)
# define A3 PAL_LINE(GPIOA, 3)
# define A4 PAL_LINE(GPIOA, 4)
# define A5 PAL_LINE(GPIOA, 5)
# define A6 PAL_LINE(GPIOA, 6)
# define A7 PAL_LINE(GPIOA, 7)
# define A8 PAL_LINE(GPIOA, 8)
# define A9 PAL_LINE(GPIOA, 9)
# define A10 PAL_LINE(GPIOA, 10)
# define A11 PAL_LINE(GPIOA, 11)
# define A12 PAL_LINE(GPIOA, 12)
# define A13 PAL_LINE(GPIOA, 13)
# define A14 PAL_LINE(GPIOA, 14)
# define A15 PAL_LINE(GPIOA, 15)
# define B0 PAL_LINE(GPIOB, 0)
# define B1 PAL_LINE(GPIOB, 1)
# define B2 PAL_LINE(GPIOB, 2)
# define B3 PAL_LINE(GPIOB, 3)
# define B4 PAL_LINE(GPIOB, 4)
# define B5 PAL_LINE(GPIOB, 5)
# define B6 PAL_LINE(GPIOB, 6)
# define B7 PAL_LINE(GPIOB, 7)
# define B8 PAL_LINE(GPIOB, 8)
# define B9 PAL_LINE(GPIOB, 9)
# define B10 PAL_LINE(GPIOB, 10)
# define B11 PAL_LINE(GPIOB, 11)
# define B12 PAL_LINE(GPIOB, 12)
# define B13 PAL_LINE(GPIOB, 13)
# define B14 PAL_LINE(GPIOB, 14)
# define B15 PAL_LINE(GPIOB, 15)
# define B16 PAL_LINE(GPIOB, 16)
# define B17 PAL_LINE(GPIOB, 17)
# define B18 PAL_LINE(GPIOB, 18)
# define B19 PAL_LINE(GPIOB, 19)
# define C0 PAL_LINE(GPIOC, 0)
# define C1 PAL_LINE(GPIOC, 1)
# define C2 PAL_LINE(GPIOC, 2)
# define C3 PAL_LINE(GPIOC, 3)
# define C4 PAL_LINE(GPIOC, 4)
# define C5 PAL_LINE(GPIOC, 5)
# define C6 PAL_LINE(GPIOC, 6)
# define C7 PAL_LINE(GPIOC, 7)
# define C8 PAL_LINE(GPIOC, 8)
# define C9 PAL_LINE(GPIOC, 9)
# define C10 PAL_LINE(GPIOC, 10)
# define C11 PAL_LINE(GPIOC, 11)
# define C12 PAL_LINE(GPIOC, 12)
# define C13 PAL_LINE(GPIOC, 13)
# define C14 PAL_LINE(GPIOC, 14)
# define C15 PAL_LINE(GPIOC, 15)
# define D0 PAL_LINE(GPIOD, 0)
# define D1 PAL_LINE(GPIOD, 1)
# define D2 PAL_LINE(GPIOD, 2)
# define D3 PAL_LINE(GPIOD, 3)
# define D4 PAL_LINE(GPIOD, 4)
# define D5 PAL_LINE(GPIOD, 5)
# define D6 PAL_LINE(GPIOD, 6)
# define D7 PAL_LINE(GPIOD, 7)
# define D8 PAL_LINE(GPIOD, 8)
# define D9 PAL_LINE(GPIOD, 9)
# define D10 PAL_LINE(GPIOD, 10)
# define D11 PAL_LINE(GPIOD, 11)
# define D12 PAL_LINE(GPIOD, 12)
# define D13 PAL_LINE(GPIOD, 13)
# define D14 PAL_LINE(GPIOD, 14)
# define D15 PAL_LINE(GPIOD, 15)
# define E0 PAL_LINE(GPIOE, 0)
# define E1 PAL_LINE(GPIOE, 1)
# define E2 PAL_LINE(GPIOE, 2)
# define E3 PAL_LINE(GPIOE, 3)
# define E4 PAL_LINE(GPIOE, 4)
# define E5 PAL_LINE(GPIOE, 5)
# define E6 PAL_LINE(GPIOE, 6)
# define E7 PAL_LINE(GPIOE, 7)
# define E8 PAL_LINE(GPIOE, 8)
# define E9 PAL_LINE(GPIOE, 9)
# define E10 PAL_LINE(GPIOE, 10)
# define E11 PAL_LINE(GPIOE, 11)
# define E12 PAL_LINE(GPIOE, 12)
# define E13 PAL_LINE(GPIOE, 13)
# define E14 PAL_LINE(GPIOE, 14)
# define E15 PAL_LINE(GPIOE, 15)
# define F0 PAL_LINE(GPIOF, 0)
# define F1 PAL_LINE(GPIOF, 1)
# define F2 PAL_LINE(GPIOF, 2)
# define F3 PAL_LINE(GPIOF, 3)
# define F4 PAL_LINE(GPIOF, 4)
# define F5 PAL_LINE(GPIOF, 5)
# define F6 PAL_LINE(GPIOF, 6)
# define F7 PAL_LINE(GPIOF, 7)
# define F8 PAL_LINE(GPIOF, 8)
# define F9 PAL_LINE(GPIOF, 9)
# define F10 PAL_LINE(GPIOF, 10)
# define F11 PAL_LINE(GPIOF, 11)
# define F12 PAL_LINE(GPIOF, 12)
# define F13 PAL_LINE(GPIOF, 13)
# define F14 PAL_LINE(GPIOF, 14)
# define F15 PAL_LINE(GPIOF, 15)
# define G0 PAL_LINE(GPIOG, 0)
# define G1 PAL_LINE(GPIOG, 1)
# define G2 PAL_LINE(GPIOG, 2)
# define G3 PAL_LINE(GPIOG, 3)
# define G4 PAL_LINE(GPIOG, 4)
# define G5 PAL_LINE(GPIOG, 5)
# define G6 PAL_LINE(GPIOG, 6)
# define G7 PAL_LINE(GPIOG, 7)
# define G8 PAL_LINE(GPIOG, 8)
# define G9 PAL_LINE(GPIOG, 9)
# define G10 PAL_LINE(GPIOG, 10)
# define G11 PAL_LINE(GPIOG, 11)
# define G12 PAL_LINE(GPIOG, 12)
# define G13 PAL_LINE(GPIOG, 13)
# define G14 PAL_LINE(GPIOG, 14)
# define G15 PAL_LINE(GPIOG, 15)
# define H0 PAL_LINE(GPIOH, 0)
# define H1 PAL_LINE(GPIOH, 1)
# define H2 PAL_LINE(GPIOH, 2)
# define H3 PAL_LINE(GPIOH, 3)
# define H4 PAL_LINE(GPIOH, 4)
# define H5 PAL_LINE(GPIOH, 5)
# define H6 PAL_LINE(GPIOH, 6)
# define H7 PAL_LINE(GPIOH, 7)
# define H8 PAL_LINE(GPIOH, 8)
# define H9 PAL_LINE(GPIOH, 9)
# define H10 PAL_LINE(GPIOH, 10)
# define H11 PAL_LINE(GPIOH, 11)
# define H12 PAL_LINE(GPIOH, 12)
# define H13 PAL_LINE(GPIOH, 13)
# define H14 PAL_LINE(GPIOH, 14)
# define H15 PAL_LINE(GPIOH, 15)
# define I0 PAL_LINE(GPIOI, 0)
# define I1 PAL_LINE(GPIOI, 1)
# define I2 PAL_LINE(GPIOI, 2)
# define I3 PAL_LINE(GPIOI, 3)
# define I4 PAL_LINE(GPIOI, 4)
# define I5 PAL_LINE(GPIOI, 5)
# define I6 PAL_LINE(GPIOI, 6)
# define I7 PAL_LINE(GPIOI, 7)
# define I8 PAL_LINE(GPIOI, 8)
# define I9 PAL_LINE(GPIOI, 9)
# define I10 PAL_LINE(GPIOI, 10)
# define I11 PAL_LINE(GPIOI, 11)
# define I12 PAL_LINE(GPIOI, 12)
# define I13 PAL_LINE(GPIOI, 13)
# define I14 PAL_LINE(GPIOI, 14)
# define I15 PAL_LINE(GPIOI, 15)
# define J0 PAL_LINE(GPIOJ, 0)
# define J1 PAL_LINE(GPIOJ, 1)
# define J2 PAL_LINE(GPIOJ, 2)
# define J3 PAL_LINE(GPIOJ, 3)
# define J4 PAL_LINE(GPIOJ, 4)
# define J5 PAL_LINE(GPIOJ, 5)
# define J6 PAL_LINE(GPIOJ, 6)
# define J7 PAL_LINE(GPIOJ, 7)
# define J8 PAL_LINE(GPIOJ, 8)
# define J9 PAL_LINE(GPIOJ, 9)
# define J10 PAL_LINE(GPIOJ, 10)
# define J11 PAL_LINE(GPIOJ, 11)
# define J12 PAL_LINE(GPIOJ, 12)
# define J13 PAL_LINE(GPIOJ, 13)
# define J14 PAL_LINE(GPIOJ, 14)
# define J15 PAL_LINE(GPIOJ, 15)
// Keyboards can `#define KEYBOARD_REQUIRES_GPIOK` if they need to access GPIO-K pins. These conflict with a whole
// bunch of layout definitions, so it's intentionally left out unless absolutely required -- in that case, the
// keyboard designer should use a different symbol when defining their layout macros.
# ifdef KEYBOARD_REQUIRES_GPIOK
# define K0 PAL_LINE(GPIOK, 0)
# define K1 PAL_LINE(GPIOK, 1)
# define K2 PAL_LINE(GPIOK, 2)
# define K3 PAL_LINE(GPIOK, 3)
# define K4 PAL_LINE(GPIOK, 4)
# define K5 PAL_LINE(GPIOK, 5)
# define K6 PAL_LINE(GPIOK, 6)
# define K7 PAL_LINE(GPIOK, 7)
# define K8 PAL_LINE(GPIOK, 8)
# define K9 PAL_LINE(GPIOK, 9)
# define K10 PAL_LINE(GPIOK, 10)
# define K11 PAL_LINE(GPIOK, 11)
# define K12 PAL_LINE(GPIOK, 12)
# define K13 PAL_LINE(GPIOK, 13)
# define K14 PAL_LINE(GPIOK, 14)
# define K15 PAL_LINE(GPIOK, 15)
# endif
#endif

View File

@@ -1,787 +0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include "wait.h"
#include "keycode.h"
#include "host.h"
#include "keymap.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "timer.h"
#include "keyboard.h"
#include "bootloader.h"
#include "action_layer.h"
#include "action_util.h"
#include "eeconfig.h"
#include "sleep_led.h"
#include "led.h"
#include "command.h"
#include "quantum.h"
#include "version.h"
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
#if defined(MOUSEKEY_ENABLE) && !defined(MK_3_SPEED)
# include "mousekey.h"
#endif
#ifdef AUDIO_ENABLE
# include "audio.h"
#endif /* AUDIO_ENABLE */
static bool command_common(uint8_t code);
static void command_common_help(void);
static void print_version(void);
static void print_status(void);
static bool command_console(uint8_t code);
static void command_console_help(void);
#if defined(MOUSEKEY_ENABLE) && !defined(MK_3_SPEED)
static bool mousekey_console(uint8_t code);
static void mousekey_console_help(void);
#endif
static void switch_default_layer(uint8_t layer);
command_state_t command_state = ONESHOT;
bool command_proc(uint8_t code) {
switch (command_state) {
case ONESHOT:
if (!IS_COMMAND()) return false;
return (command_extra(code) || command_common(code));
break;
case CONSOLE:
if (IS_COMMAND())
return (command_extra(code) || command_common(code));
else
return (command_console_extra(code) || command_console(code));
break;
#if defined(MOUSEKEY_ENABLE) && !defined(MK_3_SPEED)
case MOUSEKEY:
mousekey_console(code);
break;
#endif
default:
command_state = ONESHOT;
return false;
}
return true;
}
/* TODO: Refactoring is needed. */
/* This allows to define extra commands. return false when not processed. */
bool command_extra(uint8_t code) __attribute__((weak));
bool command_extra(uint8_t code) {
(void)code;
return false;
}
bool command_console_extra(uint8_t code) __attribute__((weak));
bool command_console_extra(uint8_t code) {
(void)code;
return false;
}
/***********************************************************
* Command common
***********************************************************/
static void command_common_help(void) {
print("\n\t- Magic -\n" STR(MAGIC_KEY_DEBUG) ": Debug Message Toggle\n" STR(MAGIC_KEY_DEBUG_MATRIX) ": Matrix Debug Mode Toggle - Show keypresses in matrix grid\n" STR(MAGIC_KEY_DEBUG_KBD) ": Keyboard Debug Toggle - Show keypress report\n" STR(MAGIC_KEY_DEBUG_MOUSE) ": Debug Mouse Toggle\n" STR(MAGIC_KEY_VERSION) ": Version\n" STR(MAGIC_KEY_STATUS) ": Status\n" STR(MAGIC_KEY_CONSOLE) ": Activate Console Mode\n"
#if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
STR(MAGIC_KEY_LAYER0) ": Switch to Layer 0\n" STR(MAGIC_KEY_LAYER1) ": Switch to Layer 1\n" STR(MAGIC_KEY_LAYER2) ": Switch to Layer 2\n" STR(MAGIC_KEY_LAYER3) ": Switch to Layer 3\n" STR(MAGIC_KEY_LAYER4) ": Switch to Layer 4\n" STR(MAGIC_KEY_LAYER5) ": Switch to Layer 5\n" STR(MAGIC_KEY_LAYER6) ": Switch to Layer 6\n" STR(MAGIC_KEY_LAYER7) ": Switch to Layer 7\n" STR(MAGIC_KEY_LAYER8) ": Switch to Layer 8\n" STR(MAGIC_KEY_LAYER9) ": Switch to Layer 9\n"
#endif
#if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
"F1-F10: Switch to Layer 0-9 (F10 = L0)\n"
#endif
#if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
"0-9: Switch to Layer 0-9\n"
#endif
STR(MAGIC_KEY_LAYER0_ALT) ": Switch to Layer 0 (alternate)\n"
STR(MAGIC_KEY_BOOTLOADER) ": Jump to Bootloader\n" STR(MAGIC_KEY_BOOTLOADER_ALT) ": Jump to Bootloader (alternate)\n"
#ifdef KEYBOARD_LOCK_ENABLE
STR(MAGIC_KEY_LOCK) ": Lock Keyboard\n"
#endif
STR(MAGIC_KEY_EEPROM) ": Print EEPROM Settings\n" STR(MAGIC_KEY_EEPROM_CLEAR) ": Clear EEPROM\n"
#ifdef NKRO_ENABLE
STR(MAGIC_KEY_NKRO) ": NKRO Toggle\n"
#endif
#ifdef SLEEP_LED_ENABLE
STR(MAGIC_KEY_SLEEP_LED) ": Sleep LED Test\n"
#endif
);
}
static void print_version(void) {
// print version & information
print("\n\t- Version -\n");
print("DESC: " STR(DESCRIPTION) "\n");
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
"VER: " STR(DEVICE_VER) "\n");
print("BUILD: (" __DATE__ ")\n");
#ifndef SKIP_VERSION
# ifdef PROTOCOL_CHIBIOS
print("CHIBIOS: " STR(CHIBIOS_VERSION) ", CONTRIB: " STR(CHIBIOS_CONTRIB_VERSION) "\n");
# endif
#endif
/* build options */
print("OPTIONS:"
#ifdef PROTOCOL_LUFA
" LUFA"
#endif
#ifdef PROTOCOL_VUSB
" VUSB"
#endif
#ifdef BOOTMAGIC_ENABLE
" BOOTMAGIC"
#endif
#ifdef MOUSEKEY_ENABLE
" MOUSEKEY"
#endif
#ifdef EXTRAKEY_ENABLE
" EXTRAKEY"
#endif
#ifdef CONSOLE_ENABLE
" CONSOLE"
#endif
#ifdef COMMAND_ENABLE
" COMMAND"
#endif
#ifdef NKRO_ENABLE
" NKRO"
#endif
#ifdef LTO_ENABLE
" LTO"
#endif
" " STR(BOOTLOADER_SIZE) "\n");
print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
#if defined(__AVR__)
" AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ " AVR_ARCH: avr" STR(__AVR_ARCH__)
#endif
"\n");
return;
}
static void print_status(void) {
print("\n\t- Status -\n");
print_val_hex8(host_keyboard_leds());
#ifndef PROTOCOL_VUSB
// these aren't set on the V-USB protocol, so we just ignore them for now
print_val_hex8(keyboard_protocol);
print_val_hex8(keyboard_idle);
#endif
#ifdef NKRO_ENABLE
print_val_hex8(keymap_config.nkro);
#endif
print_val_hex32(timer_read32());
return;
}
static void print_eeconfig(void) {
// Print these variables if NO_PRINT or USER_PRINT are not defined.
#if !defined(NO_PRINT) && !defined(USER_PRINT)
print("default_layer: ");
print_dec(eeconfig_read_default_layer());
print("\n");
debug_config_t dc;
dc.raw = eeconfig_read_debug();
print("debug_config.raw: ");
print_hex8(dc.raw);
print("\n");
print(".enable: ");
print_dec(dc.enable);
print("\n");
print(".matrix: ");
print_dec(dc.matrix);
print("\n");
print(".keyboard: ");
print_dec(dc.keyboard);
print("\n");
print(".mouse: ");
print_dec(dc.mouse);
print("\n");
keymap_config_t kc;
kc.raw = eeconfig_read_keymap();
print("keymap_config.raw: ");
print_hex8(kc.raw);
print("\n");
print(".swap_control_capslock: ");
print_dec(kc.swap_control_capslock);
print("\n");
print(".capslock_to_control: ");
print_dec(kc.capslock_to_control);
print("\n");
print(".swap_lctl_lgui: ");
print_dec(kc.swap_lctl_lgui);
print("\n");
print(".swap_rctl_rgui: ");
print_dec(kc.swap_rctl_rgui);
print("\n");
print(".swap_lalt_lgui: ");
print_dec(kc.swap_lalt_lgui);
print("\n");
print(".swap_ralt_rgui: ");
print_dec(kc.swap_ralt_rgui);
print("\n");
print(".no_gui: ");
print_dec(kc.no_gui);
print("\n");
print(".swap_grave_esc: ");
print_dec(kc.swap_grave_esc);
print("\n");
print(".swap_backslash_backspace: ");
print_dec(kc.swap_backslash_backspace);
print("\n");
print(".nkro: ");
print_dec(kc.nkro);
print("\n");
# ifdef BACKLIGHT_ENABLE
backlight_config_t bc;
bc.raw = eeconfig_read_backlight();
print("backlight_config.raw: ");
print_hex8(bc.raw);
print("\n");
print(".enable: ");
print_dec(bc.enable);
print("\n");
print(".level: ");
print_dec(bc.level);
print("\n");
# endif /* BACKLIGHT_ENABLE */
#endif /* !NO_PRINT */
}
static bool command_common(uint8_t code) {
#ifdef KEYBOARD_LOCK_ENABLE
static host_driver_t *host_driver = 0;
#endif
switch (code) {
#ifdef SLEEP_LED_ENABLE
// test breathing sleep LED
case MAGIC_KC(MAGIC_KEY_SLEEP_LED):
print("Sleep LED Test\n");
sleep_led_toggle();
led_set(host_keyboard_leds());
break;
#endif
// print stored eeprom config
case MAGIC_KC(MAGIC_KEY_EEPROM):
print("eeconfig:\n");
print_eeconfig();
break;
// clear eeprom
case MAGIC_KC(MAGIC_KEY_EEPROM_CLEAR):
print("Clearing EEPROM\n");
eeconfig_init();
break;
#ifdef KEYBOARD_LOCK_ENABLE
// lock/unlock keyboard
case MAGIC_KC(MAGIC_KEY_LOCK):
if (host_get_driver()) {
host_driver = host_get_driver();
clear_keyboard();
host_set_driver(0);
print("Locked.\n");
} else {
host_set_driver(host_driver);
print("Unlocked.\n");
}
break;
#endif
// print help
case MAGIC_KC(MAGIC_KEY_HELP):
case MAGIC_KC(MAGIC_KEY_HELP_ALT):
command_common_help();
break;
// activate console
case MAGIC_KC(MAGIC_KEY_CONSOLE):
debug_matrix = false;
debug_keyboard = false;
debug_mouse = false;
debug_enable = false;
command_console_help();
print("C> ");
command_state = CONSOLE;
break;
// jump to bootloader
case MAGIC_KC(MAGIC_KEY_BOOTLOADER):
case MAGIC_KC(MAGIC_KEY_BOOTLOADER_ALT):
print("\n\nJumping to bootloader... ");
reset_keyboard();
break;
// debug toggle
case MAGIC_KC(MAGIC_KEY_DEBUG):
debug_enable = !debug_enable;
if (debug_enable) {
print("\ndebug: on\n");
} else {
print("\ndebug: off\n");
debug_matrix = false;
debug_keyboard = false;
debug_mouse = false;
}
break;
// debug matrix toggle
case MAGIC_KC(MAGIC_KEY_DEBUG_MATRIX):
debug_matrix = !debug_matrix;
if (debug_matrix) {
print("\nmatrix: on\n");
debug_enable = true;
} else {
print("\nmatrix: off\n");
}
break;
// debug keyboard toggle
case MAGIC_KC(MAGIC_KEY_DEBUG_KBD):
debug_keyboard = !debug_keyboard;
if (debug_keyboard) {
print("\nkeyboard: on\n");
debug_enable = true;
} else {
print("\nkeyboard: off\n");
}
break;
// debug mouse toggle
case MAGIC_KC(MAGIC_KEY_DEBUG_MOUSE):
debug_mouse = !debug_mouse;
if (debug_mouse) {
print("\nmouse: on\n");
debug_enable = true;
} else {
print("\nmouse: off\n");
}
break;
// print version
case MAGIC_KC(MAGIC_KEY_VERSION):
print_version();
break;
// print status
case MAGIC_KC(MAGIC_KEY_STATUS):
print_status();
break;
#ifdef NKRO_ENABLE
// NKRO toggle
case MAGIC_KC(MAGIC_KEY_NKRO):
clear_keyboard(); // clear to prevent stuck keys
keymap_config.nkro = !keymap_config.nkro;
if (keymap_config.nkro) {
print("NKRO: on\n");
} else {
print("NKRO: off\n");
}
break;
#endif
// switch layers
case MAGIC_KC(MAGIC_KEY_LAYER0_ALT):
switch_default_layer(0);
break;
#if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
case MAGIC_KC(MAGIC_KEY_LAYER0):
switch_default_layer(0);
break;
case MAGIC_KC(MAGIC_KEY_LAYER1):
switch_default_layer(1);
break;
case MAGIC_KC(MAGIC_KEY_LAYER2):
switch_default_layer(2);
break;
case MAGIC_KC(MAGIC_KEY_LAYER3):
switch_default_layer(3);
break;
case MAGIC_KC(MAGIC_KEY_LAYER4):
switch_default_layer(4);
break;
case MAGIC_KC(MAGIC_KEY_LAYER5):
switch_default_layer(5);
break;
case MAGIC_KC(MAGIC_KEY_LAYER6):
switch_default_layer(6);
break;
case MAGIC_KC(MAGIC_KEY_LAYER7):
switch_default_layer(7);
break;
case MAGIC_KC(MAGIC_KEY_LAYER8):
switch_default_layer(8);
break;
case MAGIC_KC(MAGIC_KEY_LAYER9):
switch_default_layer(9);
break;
#endif
#if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
case KC_F1 ... KC_F9:
switch_default_layer((code - KC_F1) + 1);
break;
case KC_F10:
switch_default_layer(0);
break;
#endif
#if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
case KC_1 ... KC_9:
switch_default_layer((code - KC_1) + 1);
break;
case KC_0:
switch_default_layer(0);
break;
#endif
default:
print("?");
return false;
}
return true;
}
/***********************************************************
* Command console
***********************************************************/
static void command_console_help(void) {
print("\n\t- Console -\n"
"ESC/q: quit\n"
#ifdef MOUSEKEY_ENABLE
"m: mousekey\n"
#endif
);
}
static bool command_console(uint8_t code) {
switch (code) {
case KC_H:
case KC_SLASH: /* ? */
command_console_help();
break;
case KC_Q:
case KC_ESC:
command_state = ONESHOT;
return false;
#if defined(MOUSEKEY_ENABLE) && !defined(MK_3_SPEED)
case KC_M:
mousekey_console_help();
print("M> ");
command_state = MOUSEKEY;
return true;
#endif
default:
print("?");
return false;
}
print("C> ");
return true;
}
#if defined(MOUSEKEY_ENABLE) && !defined(MK_3_SPEED)
/***********************************************************
* Mousekey console
***********************************************************/
static uint8_t mousekey_param = 0;
static void mousekey_param_print(void) {
// Print these variables if NO_PRINT or USER_PRINT are not defined.
# if !defined(NO_PRINT) && !defined(USER_PRINT)
print("\n\t- Values -\n");
print("1: delay(*10ms): ");
pdec(mk_delay);
print("\n");
print("2: interval(ms): ");
pdec(mk_interval);
print("\n");
print("3: max_speed: ");
pdec(mk_max_speed);
print("\n");
print("4: time_to_max: ");
pdec(mk_time_to_max);
print("\n");
print("5: wheel_max_speed: ");
pdec(mk_wheel_max_speed);
print("\n");
print("6: wheel_time_to_max: ");
pdec(mk_wheel_time_to_max);
print("\n");
# endif /* !NO_PRINT */
}
//#define PRINT_SET_VAL(v) print(#v " = "); print_dec(v); print("\n");
# define PRINT_SET_VAL(v) xprintf(# v " = %d\n", (v))
static void mousekey_param_inc(uint8_t param, uint8_t inc) {
switch (param) {
case 1:
if (mk_delay + inc < UINT8_MAX)
mk_delay += inc;
else
mk_delay = UINT8_MAX;
PRINT_SET_VAL(mk_delay);
break;
case 2:
if (mk_interval + inc < UINT8_MAX)
mk_interval += inc;
else
mk_interval = UINT8_MAX;
PRINT_SET_VAL(mk_interval);
break;
case 3:
if (mk_max_speed + inc < UINT8_MAX)
mk_max_speed += inc;
else
mk_max_speed = UINT8_MAX;
PRINT_SET_VAL(mk_max_speed);
break;
case 4:
if (mk_time_to_max + inc < UINT8_MAX)
mk_time_to_max += inc;
else
mk_time_to_max = UINT8_MAX;
PRINT_SET_VAL(mk_time_to_max);
break;
case 5:
if (mk_wheel_max_speed + inc < UINT8_MAX)
mk_wheel_max_speed += inc;
else
mk_wheel_max_speed = UINT8_MAX;
PRINT_SET_VAL(mk_wheel_max_speed);
break;
case 6:
if (mk_wheel_time_to_max + inc < UINT8_MAX)
mk_wheel_time_to_max += inc;
else
mk_wheel_time_to_max = UINT8_MAX;
PRINT_SET_VAL(mk_wheel_time_to_max);
break;
}
}
static void mousekey_param_dec(uint8_t param, uint8_t dec) {
switch (param) {
case 1:
if (mk_delay > dec)
mk_delay -= dec;
else
mk_delay = 0;
PRINT_SET_VAL(mk_delay);
break;
case 2:
if (mk_interval > dec)
mk_interval -= dec;
else
mk_interval = 0;
PRINT_SET_VAL(mk_interval);
break;
case 3:
if (mk_max_speed > dec)
mk_max_speed -= dec;
else
mk_max_speed = 0;
PRINT_SET_VAL(mk_max_speed);
break;
case 4:
if (mk_time_to_max > dec)
mk_time_to_max -= dec;
else
mk_time_to_max = 0;
PRINT_SET_VAL(mk_time_to_max);
break;
case 5:
if (mk_wheel_max_speed > dec)
mk_wheel_max_speed -= dec;
else
mk_wheel_max_speed = 0;
PRINT_SET_VAL(mk_wheel_max_speed);
break;
case 6:
if (mk_wheel_time_to_max > dec)
mk_wheel_time_to_max -= dec;
else
mk_wheel_time_to_max = 0;
PRINT_SET_VAL(mk_wheel_time_to_max);
break;
}
}
static void mousekey_console_help(void) {
print("\n\t- Mousekey -\n"
"ESC/q: quit\n"
"1: delay(*10ms)\n"
"2: interval(ms)\n"
"3: max_speed\n"
"4: time_to_max\n"
"5: wheel_max_speed\n"
"6: wheel_time_to_max\n"
"\n"
"p: print values\n"
"d: set defaults\n"
"up: +1\n"
"down: -1\n"
"pgup: +10\n"
"pgdown: -10\n"
"\n"
"speed = delta * max_speed * (repeat / time_to_max)\n");
xprintf("where delta: cursor=%d, wheel=%d\n"
"See http://en.wikipedia.org/wiki/Mouse_keys\n",
MOUSEKEY_MOVE_DELTA, MOUSEKEY_WHEEL_DELTA);
}
static bool mousekey_console(uint8_t code) {
switch (code) {
case KC_H:
case KC_SLASH: /* ? */
mousekey_console_help();
break;
case KC_Q:
case KC_ESC:
if (mousekey_param) {
mousekey_param = 0;
} else {
print("C> ");
command_state = CONSOLE;
return false;
}
break;
case KC_P:
mousekey_param_print();
break;
case KC_1:
case KC_2:
case KC_3:
case KC_4:
case KC_5:
case KC_6:
mousekey_param = numkey2num(code);
break;
case KC_UP:
mousekey_param_inc(mousekey_param, 1);
break;
case KC_DOWN:
mousekey_param_dec(mousekey_param, 1);
break;
case KC_PGUP:
mousekey_param_inc(mousekey_param, 10);
break;
case KC_PGDN:
mousekey_param_dec(mousekey_param, 10);
break;
case KC_D:
mk_delay = MOUSEKEY_DELAY / 10;
mk_interval = MOUSEKEY_INTERVAL;
mk_max_speed = MOUSEKEY_MAX_SPEED;
mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
print("set default\n");
break;
default:
print("?");
return false;
}
if (mousekey_param) {
xprintf("M%d> ", mousekey_param);
} else {
print("M>");
}
return true;
}
#endif
/***********************************************************
* Utilities
***********************************************************/
uint8_t numkey2num(uint8_t code) {
switch (code) {
case KC_1:
return 1;
case KC_2:
return 2;
case KC_3:
return 3;
case KC_4:
return 4;
case KC_5:
return 5;
case KC_6:
return 6;
case KC_7:
return 7;
case KC_8:
return 8;
case KC_9:
return 9;
case KC_0:
return 0;
}
return 0;
}
static void switch_default_layer(uint8_t layer) {
xprintf("L%d\n", layer);
default_layer_set(1UL << layer);
clear_keyboard();
}

View File

@@ -1,163 +0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
/* FIXME: Add doxygen comments for the behavioral defines in here. */
/* TODO: Refactoring */
typedef enum { ONESHOT, CONSOLE, MOUSEKEY } command_state_t;
extern command_state_t command_state;
/* This allows to extend commands. Return false when command is not processed. */
bool command_extra(uint8_t code);
bool command_console_extra(uint8_t code);
#ifdef COMMAND_ENABLE
uint8_t numkey2num(uint8_t code);
bool command_proc(uint8_t code);
#else
# define command_proc(code) false
#endif
#ifndef IS_COMMAND
# define IS_COMMAND() (get_mods() == MOD_MASK_SHIFT)
#endif
#ifndef MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
# define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
#endif
#ifndef MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
# define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
#endif
#ifndef MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
# define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
#endif
#ifndef MAGIC_KEY_HELP
# define MAGIC_KEY_HELP H
#endif
#ifndef MAGIC_KEY_HELP_ALT
# define MAGIC_KEY_HELP_ALT SLASH
#endif
#ifndef MAGIC_KEY_DEBUG
# define MAGIC_KEY_DEBUG D
#endif
#ifndef MAGIC_KEY_DEBUG_MATRIX
# define MAGIC_KEY_DEBUG_MATRIX X
#endif
#ifndef MAGIC_KEY_DEBUG_KBD
# define MAGIC_KEY_DEBUG_KBD K
#endif
#ifndef MAGIC_KEY_DEBUG_MOUSE
# define MAGIC_KEY_DEBUG_MOUSE M
#endif
#ifndef MAGIC_KEY_VERSION
# define MAGIC_KEY_VERSION V
#endif
#ifndef MAGIC_KEY_STATUS
# define MAGIC_KEY_STATUS S
#endif
#ifndef MAGIC_KEY_CONSOLE
# define MAGIC_KEY_CONSOLE C
#endif
#ifndef MAGIC_KEY_LAYER0
# define MAGIC_KEY_LAYER0 0
#endif
#ifndef MAGIC_KEY_LAYER0_ALT
# define MAGIC_KEY_LAYER0_ALT GRAVE
#endif
#ifndef MAGIC_KEY_LAYER1
# define MAGIC_KEY_LAYER1 1
#endif
#ifndef MAGIC_KEY_LAYER2
# define MAGIC_KEY_LAYER2 2
#endif
#ifndef MAGIC_KEY_LAYER3
# define MAGIC_KEY_LAYER3 3
#endif
#ifndef MAGIC_KEY_LAYER4
# define MAGIC_KEY_LAYER4 4
#endif
#ifndef MAGIC_KEY_LAYER5
# define MAGIC_KEY_LAYER5 5
#endif
#ifndef MAGIC_KEY_LAYER6
# define MAGIC_KEY_LAYER6 6
#endif
#ifndef MAGIC_KEY_LAYER7
# define MAGIC_KEY_LAYER7 7
#endif
#ifndef MAGIC_KEY_LAYER8
# define MAGIC_KEY_LAYER8 8
#endif
#ifndef MAGIC_KEY_LAYER9
# define MAGIC_KEY_LAYER9 9
#endif
#ifndef MAGIC_KEY_BOOTLOADER
# define MAGIC_KEY_BOOTLOADER B
#endif
#ifndef MAGIC_KEY_BOOTLOADER_ALT
# define MAGIC_KEY_BOOTLOADER_ALT ESC
#endif
#ifndef MAGIC_KEY_LOCK
# define MAGIC_KEY_LOCK CAPS
#endif
#ifndef MAGIC_KEY_EEPROM
# define MAGIC_KEY_EEPROM E
#endif
#ifndef MAGIC_KEY_EEPROM_CLEAR
# define MAGIC_KEY_EEPROM_CLEAR BSPACE
#endif
#ifndef MAGIC_KEY_NKRO
# define MAGIC_KEY_NKRO N
#endif
#ifndef MAGIC_KEY_SLEEP_LED
# define MAGIC_KEY_SLEEP_LED Z
#endif
#define XMAGIC_KC(key) KC_##key
#define MAGIC_KC(key) XMAGIC_KC(key)

View File

@@ -1,24 +1,25 @@
#include <stdbool.h>
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
debug_config_t debug_config = {
/* GCC Bug 10676 - Using unnamed fields in initializers
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 */
#if GCC_VERSION >= 40600
.enable = false,
.matrix = false,
.keyboard = false,
.mouse = false,
.reserved = 0
#else
{
false, // .enable
false, // .matrix
false, // .keyboard
false, // .mouse
0 // .reserved
}
#endif
.enable = false, //
.matrix = false, //
.keyboard = false, //
.mouse = false, //
.reserved = 0 //
};

View File

@@ -6,6 +6,7 @@
#ifdef ORYX_ENABLE
# include "oryx.h"
#endif
#ifdef STM32_EEPROM_ENABLE
# include <hal.h>
# include "eeprom_stm32.h"
@@ -60,19 +61,18 @@ void eeconfig_init_quantum(void) {
eeprom_update_byte(EECONFIG_VELOCIKEY, 0);
eeprom_update_dword(EECONFIG_RGB_MATRIX, 0);
eeprom_update_byte(EECONFIG_RGB_MATRIX_SPEED, 0);
#ifdef ORYX_ENABLE
eeconfig_init_oryx();
#endif
// TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS
// within the emulated eeprom via dfu-util or another tool
#if defined INIT_EE_HANDS_LEFT
#pragma message "Faking EE_HANDS for left hand"
# pragma message "Faking EE_HANDS for left hand"
eeprom_update_byte(EECONFIG_HANDEDNESS, 1);
#elif defined INIT_EE_HANDS_RIGHT
#pragma message "Faking EE_HANDS for right hand"
# pragma message "Faking EE_HANDS for right hand"
eeprom_update_byte(EECONFIG_HANDEDNESS, 0);
#endif
#ifdef ORYX_ENABLE
eeconfig_init_oryx();
#endif
#if defined(HAPTIC_ENABLE)
haptic_reset();

View File

@@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdbool.h>
#ifndef EECONFIG_MAGIC_NUMBER
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEF
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEB // When changing, decrement this value to avoid future re-init issues
#endif
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF

22
tmk_core/common/gpio.h Normal file
View File

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

View File

@@ -41,7 +41,7 @@ uint8_t host_keyboard_leds(void) {
}
led_t host_keyboard_led_state(void) {
if (!driver) return (led_t) {0};
if (!driver) return (led_t){0};
return (led_t)((*driver->keyboard_leds)());
}

View File

@@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "led.h"
#include "keycode.h"
#include "timer.h"
#include "sync_timer.h"
#include "print.h"
#include "debug.h"
#include "command.h"
@@ -53,15 +54,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
#endif
#ifdef RGB_MATRIX_ENABLE
# include "rgb_matrix.h"
#endif
#ifdef ENCODER_ENABLE
# include "encoder.h"
#endif
#ifdef STENO_ENABLE
# include "process_steno.h"
#endif
#ifdef FAUXCLICKY_ENABLE
# include "fauxclicky.h"
#endif
#ifdef SERIAL_LINK_ENABLE
# include "serial_link/system/serial_link.h"
#endif
@@ -96,10 +97,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "dip_switch.h"
#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) { return last_input_modification_time; }
uint32_t last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); }
static uint32_t last_matrix_modification_time = 0;
uint32_t last_matrix_activity_time(void) { return last_matrix_modification_time; }
uint32_t last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); }
void last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); }
static uint32_t last_encoder_modification_time = 0;
uint32_t last_encoder_activity_time(void) { return last_encoder_modification_time; }
uint32_t last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); }
void last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); }
// Only enable this if console is enabled to print to
#if defined(DEBUG_MATRIX_SCAN_RATE)
static uint32_t matrix_timer = 0;
static uint32_t matrix_scan_count = 0;
static uint32_t matrix_timer = 0;
static uint32_t matrix_scan_count = 0;
static uint32_t last_matrix_scan_count = 0;
void matrix_scan_perf_task(void) {
@@ -108,17 +123,15 @@ void matrix_scan_perf_task(void) {
uint32_t timer_now = timer_read32();
if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
# if defined(CONSOLE_ENABLE)
dprintf("matrix scan frequency: %d\n", matrix_scan_count);
dprintf("matrix scan frequency: %lu\n", matrix_scan_count);
# endif
last_matrix_scan_count = matrix_scan_count;
matrix_timer = timer_now;
matrix_scan_count = 0;
matrix_timer = timer_now;
matrix_scan_count = 0;
}
}
uint32_t get_matrix_scan_rate(void) {
return last_matrix_scan_count;
}
uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; }
#else
# define matrix_scan_perf_task()
#endif
@@ -173,6 +186,9 @@ void disable_jtag(void) {
#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD);
#elif defined(__AVR_ATmega32A__)
MCUCSR |= _BV(JTD);
MCUCSR |= _BV(JTD);
#endif
}
@@ -213,7 +229,10 @@ __attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user
* FIXME: needs doc
*/
void keyboard_setup(void) {
#ifndef NO_JTAG_DISABLE
disable_jtag();
#endif
print_set_sendchar(sendchar);
matrix_setup();
keyboard_pre_init_kb();
}
@@ -257,6 +276,7 @@ __attribute__((weak)) void housekeeping_task_user(void) {}
*/
void keyboard_init(void) {
timer_init();
sync_timer_init();
matrix_init();
#ifdef VIA_ENABLE
via_init();
@@ -293,9 +313,6 @@ void keyboard_init(void) {
#ifdef STENO_ENABLE
steno_init();
#endif
#ifdef FAUXCLICKY_ENABLE
fauxclicky_init();
#endif
#ifdef POINTING_DEVICE_ENABLE
pointing_device_init();
#endif
@@ -314,6 +331,17 @@ void keyboard_init(void) {
keyboard_post_init_kb(); /* Always keep this last */
}
/** \brief key_event_task
*
* This function is responsible for calling into other systems when they need to respond to electrical switch press events.
* This is differnet than keycode events as no layer processing, or filtering occurs.
*/
void switch_events(uint8_t row, uint8_t col, bool pressed) {
#if defined(RGB_MATRIX_ENABLE)
process_rgb_matrix(row, col, pressed);
#endif
}
/** \brief Keyboard task: Do keyboard routine jobs
*
* Do routine keyboard jobs:
@@ -334,42 +362,45 @@ void keyboard_task(void) {
#ifdef QMK_KEYS_PER_SCAN
uint8_t keys_processed = 0;
#endif
#ifdef ENCODER_ENABLE
bool encoders_changed = false;
#endif
housekeeping_task_kb();
housekeeping_task_user();
#if defined(OLED_DRIVER_ENABLE) && !defined(OLED_DISABLE_TIMEOUT)
uint8_t ret = matrix_scan();
#else
matrix_scan();
#endif
uint8_t matrix_changed = matrix_scan();
if (matrix_changed) last_matrix_activity_trigger();
if (should_process_keypress()) {
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
matrix_row = matrix_get_row(r);
matrix_change = matrix_row ^ matrix_prev[r];
if (matrix_change) {
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
matrix_row = matrix_get_row(r);
matrix_change = matrix_row ^ matrix_prev[r];
if (matrix_change) {
#ifdef MATRIX_HAS_GHOST
if (has_ghost_in_row(r, matrix_row)) {
continue;
}
if (has_ghost_in_row(r, matrix_row)) {
continue;
}
#endif
if (debug_matrix) matrix_print();
matrix_row_t col_mask = 1;
for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
if (matrix_change & col_mask) {
if (debug_matrix) matrix_print();
matrix_row_t col_mask = 1;
for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
if (matrix_change & col_mask) {
if (should_process_keypress()) {
action_exec((keyevent_t){
.key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */
});
// record a processed key
matrix_prev[r] ^= col_mask;
#ifdef QMK_KEYS_PER_SCAN
// only jump out if we have processed "enough" keys.
if (++keys_processed >= QMK_KEYS_PER_SCAN)
#endif
// process a key per task call
goto MATRIX_LOOP_END;
}
// record a processed key
matrix_prev[r] ^= col_mask;
switch_events(r, c, (matrix_row & col_mask));
#ifdef QMK_KEYS_PER_SCAN
// only jump out if we have processed "enough" keys.
if (++keys_processed >= QMK_KEYS_PER_SCAN)
#endif
// process a key per task call
goto MATRIX_LOOP_END;
}
}
}
@@ -391,6 +422,10 @@ MATRIX_LOOP_END:
rgblight_task();
#endif
#ifdef RGB_MATRIX_ENABLE
rgb_matrix_task();
#endif
#if defined(BACKLIGHT_ENABLE)
# if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)
backlight_task();
@@ -398,7 +433,8 @@ MATRIX_LOOP_END:
#endif
#ifdef ENCODER_ENABLE
encoder_read();
encoders_changed = encoder_read();
if (encoders_changed) last_encoder_activity_trigger();
#endif
#ifdef QWIIC_ENABLE
@@ -408,8 +444,12 @@ MATRIX_LOOP_END:
#ifdef OLED_DRIVER_ENABLE
oled_task();
# ifndef OLED_DISABLE_TIMEOUT
// Wake up oled if user is using those fabulous keys!
if (ret) oled_on();
// Wake up oled if user is using those fabulous keys or spinning those encoders!
# ifdef ENCODER_ENABLE
if (matrix_changed || encoders_changed) oled_on();
# else
if (matrix_changed) oled_on();
# endif
# endif
#endif

View File

@@ -52,8 +52,6 @@ static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) &&
#define TICK \
(keyevent_t) { .key = (keypos_t){.row = 255, .col = 255}, .pressed = false, .time = (timer_read() | 1) }
void disable_jtag(void);
/* it runs once at early stage of startup before keyboard_init. */
void keyboard_setup(void);
/* it runs once after initializing host side protocol, debug and MCU peripherals. */
@@ -75,6 +73,15 @@ void keyboard_post_init_user(void);
void housekeeping_task_kb(void);
void housekeeping_task_user(void);
uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity
uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity
uint32_t last_matrix_activity_time(void); // Timestamp of the last matrix activity
uint32_t last_matrix_activity_elapsed(void); // Number of milliseconds since the last matrix activity
uint32_t last_encoder_activity_time(void); // Timestamp of the last encoder activity
uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity
uint32_t get_matrix_scan_rate(void);
#ifdef __cplusplus

View File

@@ -39,7 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2)
#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT)
#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5)
#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN8)
#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT)
#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
@@ -205,6 +205,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_BTN3 KC_MS_BTN3
#define KC_BTN4 KC_MS_BTN4
#define KC_BTN5 KC_MS_BTN5
#define KC_BTN6 KC_MS_BTN6
#define KC_BTN7 KC_MS_BTN7
#define KC_BTN8 KC_MS_BTN8
#define KC_WH_U KC_MS_WH_UP
#define KC_WH_D KC_MS_WH_DOWN
#define KC_WH_L KC_MS_WH_LEFT
@@ -520,16 +523,29 @@ enum internal_special_keycodes {
};
enum mouse_keys {
/* Mouse Buttons */
/* Mouse Buttons */
#ifdef VIA_ENABLE
KC_MS_UP = 0xF0,
#else
KC_MS_UP = 0xED,
#endif
KC_MS_DOWN,
KC_MS_LEFT,
KC_MS_RIGHT,
KC_MS_RIGHT, // 0xF0
KC_MS_BTN1,
KC_MS_BTN2,
KC_MS_BTN3,
KC_MS_BTN4,
KC_MS_BTN5,
#ifdef VIA_ENABLE
KC_MS_BTN6 = KC_MS_BTN5,
KC_MS_BTN7 = KC_MS_BTN5,
KC_MS_BTN8 = KC_MS_BTN5,
#else
KC_MS_BTN6,
KC_MS_BTN7,
KC_MS_BTN8,
#endif
/* Mouse Wheel */
KC_MS_WH_UP,
@@ -540,5 +556,5 @@ enum mouse_keys {
/* Acceleration */
KC_MS_ACCEL0,
KC_MS_ACCEL1,
KC_MS_ACCEL2
KC_MS_ACCEL2 // 0xFF
};

View File

@@ -1,54 +0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
/* FIXME: Add doxygen comments here. */
/* keyboard LEDs */
#define USB_LED_NUM_LOCK 0
#define USB_LED_CAPS_LOCK 1
#define USB_LED_SCROLL_LOCK 2
#define USB_LED_COMPOSE 3
#define USB_LED_KANA 4
#ifdef __cplusplus
extern "C" {
#endif
typedef union {
uint8_t raw;
struct {
bool num_lock : 1;
bool caps_lock : 1;
bool scroll_lock : 1;
bool compose : 1;
bool kana : 1;
uint8_t reserved : 3;
};
} led_t;
void led_set(uint8_t usb_led);
void led_init_ports(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,9 @@
PRINTF_PATH = $(LIB_PATH)/printf
TMK_COMMON_SRC += $(PRINTF_PATH)/printf.c
TMK_COMMON_SRC += $(COMMON_DIR)/printf.c
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_FLOAT
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG
TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T
VPATH += $(PRINTF_PATH)

View File

@@ -1,76 +0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#if (MATRIX_COLS <= 8)
typedef uint8_t matrix_row_t;
#elif (MATRIX_COLS <= 16)
typedef uint16_t matrix_row_t;
#elif (MATRIX_COLS <= 32)
typedef uint32_t matrix_row_t;
#else
# error "MATRIX_COLS: invalid value"
#endif
#define MATRIX_ROW_SHIFTER ((matrix_row_t)1)
#ifdef __cplusplus
extern "C" {
#endif
/* number of matrix rows */
uint8_t matrix_rows(void);
/* number of matrix columns */
uint8_t matrix_cols(void);
/* should be called at early stage of startup before matrix_init.(optional) */
void matrix_setup(void);
/* intialize matrix for scaning. */
void matrix_init(void);
/* scan all key states on matrix */
uint8_t matrix_scan(void);
/* whether modified from previous scan. used after matrix_scan. */
bool matrix_is_modified(void) __attribute__((deprecated));
/* whether a switch is on */
bool matrix_is_on(uint8_t row, uint8_t col);
/* matrix state on row */
matrix_row_t matrix_get_row(uint8_t row);
/* print matrix for debug */
void matrix_print(void);
/* delay between changing matrix pin state and reading values */
void matrix_io_delay(void);
/* power control */
void matrix_power_up(void);
void matrix_power_down(void);
/* executes code for Quantum */
void matrix_init_quantum(void);
void matrix_scan_quantum(void);
void matrix_init_kb(void);
void matrix_scan_kb(void);
void matrix_init_user(void);
void matrix_scan_user(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1,446 +0,0 @@
/*
* Copyright 2011 Jun Wako <wakojun@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include "keycode.h"
#include "host.h"
#include "timer.h"
#include "print.h"
#include "debug.h"
#include "mousekey.h"
inline int8_t times_inv_sqrt2(int8_t x) {
// 181/256 is pretty close to 1/sqrt(2)
// 0.70703125 0.707106781
// 1 too small for x=99 and x=198
// This ends up being a mult and discard lower 8 bits
return (x * 181) >> 8;
}
static report_mouse_t mouse_report = {0};
static void mousekey_debug(void);
static uint8_t mousekey_accel = 0;
static uint8_t mousekey_repeat = 0;
static uint8_t mousekey_wheel_repeat = 0;
#ifndef MK_3_SPEED
static uint16_t last_timer_c = 0;
static uint16_t last_timer_w = 0;
/*
* Mouse keys acceleration algorithm
* http://en.wikipedia.org/wiki/Mouse_keys
*
* speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
*/
/* milliseconds between the initial key press and first repeated motion event (0-2550) */
uint8_t mk_delay = MOUSEKEY_DELAY / 10;
/* milliseconds between repeated motion events (0-255) */
uint8_t mk_interval = MOUSEKEY_INTERVAL;
/* steady speed (in action_delta units) applied each event (0-255) */
uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
/* number of events (count) accelerating to steady speed (0-255) */
uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
// int8_t mk_curve = 0;
/* wheel params */
/* milliseconds between the initial key press and first repeated motion event (0-2550) */
uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10;
/* milliseconds between repeated motion events (0-255) */
uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
# ifndef MK_COMBINED
static uint8_t move_unit(void) {
uint16_t unit;
if (mousekey_accel & (1 << 0)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4;
} else if (mousekey_accel & (1 << 1)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
} else if (mousekey_accel & (1 << 2)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
} else if (mousekey_repeat == 0) {
unit = MOUSEKEY_MOVE_DELTA;
} else if (mousekey_repeat >= mk_time_to_max) {
unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
} else {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
}
return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
}
static uint8_t wheel_unit(void) {
uint16_t unit;
if (mousekey_accel & (1 << 0)) {
unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4;
} else if (mousekey_accel & (1 << 1)) {
unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2;
} else if (mousekey_accel & (1 << 2)) {
unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
} else if (mousekey_wheel_repeat == 0) {
unit = MOUSEKEY_WHEEL_DELTA;
} else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) {
unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
} else {
unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max;
}
return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
}
# else /* #ifndef MK_COMBINED */
static uint8_t move_unit(void) {
uint16_t unit;
if (mousekey_accel & (1 << 0)) {
unit = 1;
} else if (mousekey_accel & (1 << 1)) {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
} else if (mousekey_accel & (1 << 2)) {
unit = MOUSEKEY_MOVE_MAX;
} else if (mousekey_repeat == 0) {
unit = MOUSEKEY_MOVE_DELTA;
} else if (mousekey_repeat >= mk_time_to_max) {
unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
} else {
unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
}
return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
}
static uint8_t wheel_unit(void) {
uint16_t unit;
if (mousekey_accel & (1 << 0)) {
unit = 1;
} else if (mousekey_accel & (1 << 1)) {
unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2;
} else if (mousekey_accel & (1 << 2)) {
unit = MOUSEKEY_WHEEL_MAX;
} else if (mousekey_repeat == 0) {
unit = MOUSEKEY_WHEEL_DELTA;
} else if (mousekey_repeat >= mk_wheel_time_to_max) {
unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
} else {
unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
}
return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
}
# endif /* #ifndef MK_COMBINED */
void mousekey_task(void) {
// report cursor and scroll movement independently
report_mouse_t const tmpmr = mouse_report;
mouse_report.x = 0;
mouse_report.y = 0;
mouse_report.v = 0;
mouse_report.h = 0;
if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) {
if (mousekey_repeat != UINT8_MAX) mousekey_repeat++;
if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1);
if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1);
/* diagonal move [1/sqrt(2)] */
if (mouse_report.x && mouse_report.y) {
mouse_report.x = times_inv_sqrt2(mouse_report.x);
if (mouse_report.x == 0) {
mouse_report.x = 1;
}
mouse_report.y = times_inv_sqrt2(mouse_report.y);
if (mouse_report.y == 0) {
mouse_report.y = 1;
}
}
}
if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) {
if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++;
if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1);
if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1);
/* diagonal move [1/sqrt(2)] */
if (mouse_report.v && mouse_report.h) {
mouse_report.v = times_inv_sqrt2(mouse_report.v);
if (mouse_report.v == 0) {
mouse_report.v = 1;
}
mouse_report.h = times_inv_sqrt2(mouse_report.h);
if (mouse_report.h == 0) {
mouse_report.h = 1;
}
}
}
if (mouse_report.x || mouse_report.y || mouse_report.v || mouse_report.h) mousekey_send();
mouse_report = tmpmr;
}
void mousekey_on(uint8_t code) {
if (code == KC_MS_UP)
mouse_report.y = move_unit() * -1;
else if (code == KC_MS_DOWN)
mouse_report.y = move_unit();
else if (code == KC_MS_LEFT)
mouse_report.x = move_unit() * -1;
else if (code == KC_MS_RIGHT)
mouse_report.x = move_unit();
else if (code == KC_MS_WH_UP)
mouse_report.v = wheel_unit();
else if (code == KC_MS_WH_DOWN)
mouse_report.v = wheel_unit() * -1;
else if (code == KC_MS_WH_LEFT)
mouse_report.h = wheel_unit() * -1;
else if (code == KC_MS_WH_RIGHT)
mouse_report.h = wheel_unit();
else if (code == KC_MS_BTN1)
mouse_report.buttons |= MOUSE_BTN1;
else if (code == KC_MS_BTN2)
mouse_report.buttons |= MOUSE_BTN2;
else if (code == KC_MS_BTN3)
mouse_report.buttons |= MOUSE_BTN3;
else if (code == KC_MS_BTN4)
mouse_report.buttons |= MOUSE_BTN4;
else if (code == KC_MS_BTN5)
mouse_report.buttons |= MOUSE_BTN5;
else if (code == KC_MS_ACCEL0)
mousekey_accel |= (1 << 0);
else if (code == KC_MS_ACCEL1)
mousekey_accel |= (1 << 1);
else if (code == KC_MS_ACCEL2)
mousekey_accel |= (1 << 2);
}
void mousekey_off(uint8_t code) {
if (code == KC_MS_UP && mouse_report.y < 0)
mouse_report.y = 0;
else if (code == KC_MS_DOWN && mouse_report.y > 0)
mouse_report.y = 0;
else if (code == KC_MS_LEFT && mouse_report.x < 0)
mouse_report.x = 0;
else if (code == KC_MS_RIGHT && mouse_report.x > 0)
mouse_report.x = 0;
else if (code == KC_MS_WH_UP && mouse_report.v > 0)
mouse_report.v = 0;
else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
mouse_report.v = 0;
else if (code == KC_MS_WH_LEFT && mouse_report.h < 0)
mouse_report.h = 0;
else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0)
mouse_report.h = 0;
else if (code == KC_MS_BTN1)
mouse_report.buttons &= ~MOUSE_BTN1;
else if (code == KC_MS_BTN2)
mouse_report.buttons &= ~MOUSE_BTN2;
else if (code == KC_MS_BTN3)
mouse_report.buttons &= ~MOUSE_BTN3;
else if (code == KC_MS_BTN4)
mouse_report.buttons &= ~MOUSE_BTN4;
else if (code == KC_MS_BTN5)
mouse_report.buttons &= ~MOUSE_BTN5;
else if (code == KC_MS_ACCEL0)
mousekey_accel &= ~(1 << 0);
else if (code == KC_MS_ACCEL1)
mousekey_accel &= ~(1 << 1);
else if (code == KC_MS_ACCEL2)
mousekey_accel &= ~(1 << 2);
if (mouse_report.x == 0 && mouse_report.y == 0) mousekey_repeat = 0;
if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0;
}
#else /* #ifndef MK_3_SPEED */
enum { mkspd_unmod, mkspd_0, mkspd_1, mkspd_2, mkspd_COUNT };
# ifndef MK_MOMENTARY_ACCEL
static uint8_t mk_speed = mkspd_1;
# else
static uint8_t mk_speed = mkspd_unmod;
static uint8_t mkspd_DEFAULT = mkspd_unmod;
# endif
static uint16_t last_timer_c = 0;
static uint16_t last_timer_w = 0;
uint16_t c_offsets[mkspd_COUNT] = {MK_C_OFFSET_UNMOD, MK_C_OFFSET_0, MK_C_OFFSET_1, MK_C_OFFSET_2};
uint16_t c_intervals[mkspd_COUNT] = {MK_C_INTERVAL_UNMOD, MK_C_INTERVAL_0, MK_C_INTERVAL_1, MK_C_INTERVAL_2};
uint16_t w_offsets[mkspd_COUNT] = {MK_W_OFFSET_UNMOD, MK_W_OFFSET_0, MK_W_OFFSET_1, MK_W_OFFSET_2};
uint16_t w_intervals[mkspd_COUNT] = {MK_W_INTERVAL_UNMOD, MK_W_INTERVAL_0, MK_W_INTERVAL_1, MK_W_INTERVAL_2};
void mousekey_task(void) {
// report cursor and scroll movement independently
report_mouse_t const tmpmr = mouse_report;
mouse_report.x = 0;
mouse_report.y = 0;
mouse_report.v = 0;
mouse_report.h = 0;
if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > c_intervals[mk_speed]) {
mouse_report.x = tmpmr.x;
mouse_report.y = tmpmr.y;
}
if ((tmpmr.h || tmpmr.v) && timer_elapsed(last_timer_w) > w_intervals[mk_speed]) {
mouse_report.v = tmpmr.v;
mouse_report.h = tmpmr.h;
}
if (mouse_report.x || mouse_report.y || mouse_report.v || mouse_report.h) mousekey_send();
mouse_report = tmpmr;
}
void adjust_speed(void) {
uint16_t const c_offset = c_offsets[mk_speed];
uint16_t const w_offset = w_offsets[mk_speed];
if (mouse_report.x > 0) mouse_report.x = c_offset;
if (mouse_report.x < 0) mouse_report.x = c_offset * -1;
if (mouse_report.y > 0) mouse_report.y = c_offset;
if (mouse_report.y < 0) mouse_report.y = c_offset * -1;
if (mouse_report.h > 0) mouse_report.h = w_offset;
if (mouse_report.h < 0) mouse_report.h = w_offset * -1;
if (mouse_report.v > 0) mouse_report.v = w_offset;
if (mouse_report.v < 0) mouse_report.v = w_offset * -1;
// adjust for diagonals
if (mouse_report.x && mouse_report.y) {
mouse_report.x = times_inv_sqrt2(mouse_report.x);
if (mouse_report.x == 0) {
mouse_report.x = 1;
}
mouse_report.y = times_inv_sqrt2(mouse_report.y);
if (mouse_report.y == 0) {
mouse_report.y = 1;
}
}
if (mouse_report.h && mouse_report.v) {
mouse_report.h = times_inv_sqrt2(mouse_report.h);
mouse_report.v = times_inv_sqrt2(mouse_report.v);
}
}
void mousekey_on(uint8_t code) {
uint16_t const c_offset = c_offsets[mk_speed];
uint16_t const w_offset = w_offsets[mk_speed];
uint8_t const old_speed = mk_speed;
if (code == KC_MS_UP)
mouse_report.y = c_offset * -1;
else if (code == KC_MS_DOWN)
mouse_report.y = c_offset;
else if (code == KC_MS_LEFT)
mouse_report.x = c_offset * -1;
else if (code == KC_MS_RIGHT)
mouse_report.x = c_offset;
else if (code == KC_MS_WH_UP)
mouse_report.v = w_offset;
else if (code == KC_MS_WH_DOWN)
mouse_report.v = w_offset * -1;
else if (code == KC_MS_WH_LEFT)
mouse_report.h = w_offset * -1;
else if (code == KC_MS_WH_RIGHT)
mouse_report.h = w_offset;
else if (code == KC_MS_BTN1)
mouse_report.buttons |= MOUSE_BTN1;
else if (code == KC_MS_BTN2)
mouse_report.buttons |= MOUSE_BTN2;
else if (code == KC_MS_BTN3)
mouse_report.buttons |= MOUSE_BTN3;
else if (code == KC_MS_BTN4)
mouse_report.buttons |= MOUSE_BTN4;
else if (code == KC_MS_BTN5)
mouse_report.buttons |= MOUSE_BTN5;
else if (code == KC_MS_ACCEL0)
mk_speed = mkspd_0;
else if (code == KC_MS_ACCEL1)
mk_speed = mkspd_1;
else if (code == KC_MS_ACCEL2)
mk_speed = mkspd_2;
if (mk_speed != old_speed) adjust_speed();
}
void mousekey_off(uint8_t code) {
# ifdef MK_MOMENTARY_ACCEL
uint8_t const old_speed = mk_speed;
# endif
if (code == KC_MS_UP && mouse_report.y < 0)
mouse_report.y = 0;
else if (code == KC_MS_DOWN && mouse_report.y > 0)
mouse_report.y = 0;
else if (code == KC_MS_LEFT && mouse_report.x < 0)
mouse_report.x = 0;
else if (code == KC_MS_RIGHT && mouse_report.x > 0)
mouse_report.x = 0;
else if (code == KC_MS_WH_UP && mouse_report.v > 0)
mouse_report.v = 0;
else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
mouse_report.v = 0;
else if (code == KC_MS_WH_LEFT && mouse_report.h < 0)
mouse_report.h = 0;
else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0)
mouse_report.h = 0;
else if (code == KC_MS_BTN1)
mouse_report.buttons &= ~MOUSE_BTN1;
else if (code == KC_MS_BTN2)
mouse_report.buttons &= ~MOUSE_BTN2;
else if (code == KC_MS_BTN3)
mouse_report.buttons &= ~MOUSE_BTN3;
else if (code == KC_MS_BTN4)
mouse_report.buttons &= ~MOUSE_BTN4;
else if (code == KC_MS_BTN5)
mouse_report.buttons &= ~MOUSE_BTN5;
# ifdef MK_MOMENTARY_ACCEL
else if (code == KC_MS_ACCEL0)
mk_speed = mkspd_DEFAULT;
else if (code == KC_MS_ACCEL1)
mk_speed = mkspd_DEFAULT;
else if (code == KC_MS_ACCEL2)
mk_speed = mkspd_DEFAULT;
if (mk_speed != old_speed) adjust_speed();
# endif
}
#endif /* #ifndef MK_3_SPEED */
void mousekey_send(void) {
mousekey_debug();
uint16_t time = timer_read();
if (mouse_report.x || mouse_report.y) last_timer_c = time;
if (mouse_report.v || mouse_report.h) last_timer_w = time;
host_mouse_send(&mouse_report);
}
void mousekey_clear(void) {
mouse_report = (report_mouse_t){};
mousekey_repeat = 0;
mousekey_wheel_repeat = 0;
mousekey_accel = 0;
}
static void mousekey_debug(void) {
if (!debug_mouse) return;
print("mousekey [btn|x y v h](rep/acl): [");
phex(mouse_report.buttons);
print("|");
print_decs(mouse_report.x);
print(" ");
print_decs(mouse_report.y);
print(" ");
print_decs(mouse_report.v);
print(" ");
print_decs(mouse_report.h);
print("](");
print_dec(mousekey_repeat);
print("/");
print_dec(mousekey_accel);
print(")\n");
}

View File

@@ -1,142 +0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdbool.h>
#include "host.h"
#ifndef MK_3_SPEED
/* max value on report descriptor */
# ifndef MOUSEKEY_MOVE_MAX
# define MOUSEKEY_MOVE_MAX 127
# elif MOUSEKEY_MOVE_MAX > 127
# error MOUSEKEY_MOVE_MAX needs to be smaller than 127
# endif
# ifndef MOUSEKEY_WHEEL_MAX
# define MOUSEKEY_WHEEL_MAX 127
# elif MOUSEKEY_WHEEL_MAX > 127
# error MOUSEKEY_WHEEL_MAX needs to be smaller than 127
# endif
# ifndef MOUSEKEY_MOVE_DELTA
# define MOUSEKEY_MOVE_DELTA 5
# endif
# ifndef MOUSEKEY_WHEEL_DELTA
# define MOUSEKEY_WHEEL_DELTA 1
# endif
# ifndef MOUSEKEY_DELAY
# define MOUSEKEY_DELAY 300
# endif
# ifndef MOUSEKEY_INTERVAL
# define MOUSEKEY_INTERVAL 50
# endif
# ifndef MOUSEKEY_MAX_SPEED
# define MOUSEKEY_MAX_SPEED 10
# endif
# ifndef MOUSEKEY_TIME_TO_MAX
# define MOUSEKEY_TIME_TO_MAX 20
# endif
# ifndef MOUSEKEY_WHEEL_DELAY
# define MOUSEKEY_WHEEL_DELAY 300
# endif
# ifndef MOUSEKEY_WHEEL_INTERVAL
# define MOUSEKEY_WHEEL_INTERVAL 100
# endif
# ifndef MOUSEKEY_WHEEL_MAX_SPEED
# define MOUSEKEY_WHEEL_MAX_SPEED 8
# endif
# ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
# define MOUSEKEY_WHEEL_TIME_TO_MAX 40
# endif
#else /* #ifndef MK_3_SPEED */
# ifndef MK_C_OFFSET_UNMOD
# define MK_C_OFFSET_UNMOD 16
# endif
# ifndef MK_C_INTERVAL_UNMOD
# define MK_C_INTERVAL_UNMOD 16
# endif
# ifndef MK_C_OFFSET_0
# define MK_C_OFFSET_0 1
# endif
# ifndef MK_C_INTERVAL_0
# define MK_C_INTERVAL_0 32
# endif
# ifndef MK_C_OFFSET_1
# define MK_C_OFFSET_1 4
# endif
# ifndef MK_C_INTERVAL_1
# define MK_C_INTERVAL_1 16
# endif
# ifndef MK_C_OFFSET_2
# define MK_C_OFFSET_2 32
# endif
# ifndef MK_C_INTERVAL_2
# define MK_C_INTERVAL_2 16
# endif
# ifndef MK_W_OFFSET_UNMOD
# define MK_W_OFFSET_UNMOD 1
# endif
# ifndef MK_W_INTERVAL_UNMOD
# define MK_W_INTERVAL_UNMOD 40
# endif
# ifndef MK_W_OFFSET_0
# define MK_W_OFFSET_0 1
# endif
# ifndef MK_W_INTERVAL_0
# define MK_W_INTERVAL_0 360
# endif
# ifndef MK_W_OFFSET_1
# define MK_W_OFFSET_1 1
# endif
# ifndef MK_W_INTERVAL_1
# define MK_W_INTERVAL_1 120
# endif
# ifndef MK_W_OFFSET_2
# define MK_W_OFFSET_2 1
# endif
# ifndef MK_W_INTERVAL_2
# define MK_W_INTERVAL_2 20
# endif
#endif /* #ifndef MK_3_SPEED */
#ifdef __cplusplus
extern "C" {
#endif
extern uint8_t mk_delay;
extern uint8_t mk_interval;
extern uint8_t mk_max_speed;
extern uint8_t mk_time_to_max;
extern uint8_t mk_wheel_max_speed;
extern uint8_t mk_wheel_time_to_max;
void mousekey_task(void);
void mousekey_on(uint8_t code);
void mousekey_off(uint8_t code);
void mousekey_clear(void);
void mousekey_send(void);
#ifdef __cplusplus
}
#endif

View File

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

View File

@@ -27,104 +27,76 @@
#include <stdint.h>
#include <stdbool.h>
#include "util.h"
#include "sendchar.h"
#include "progmem.h"
#if defined(PROTOCOL_CHIBIOS) || defined(PROTOCOL_ARM_ATSAM)
# define PSTR(x) x
#endif
void print_set_sendchar(sendchar_func_t func);
#ifndef NO_PRINT
# if defined(__AVR__) /* __AVR__ */
# include "avr/xprintf.h"
# ifdef USER_PRINT /* USER_PRINT */
// Remove normal print defines
# define print(s)
# define println(s)
# undef xprintf
# define xprintf(fmt, ...)
// Create user print defines
# define uprint(s) xputs(PSTR(s))
# define uprintln(s) xputs(PSTR(s "\r\n"))
# define uprintf(fmt, ...) __xprintf(PSTR(fmt), ##__VA_ARGS__)
# else /* NORMAL PRINT */
// Create user & normal print defines
# define print(s) xputs(PSTR(s))
# define println(s) xputs(PSTR(s "\r\n"))
# define uprint(s) print(s)
# define uprintln(s) println(s)
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
# ifdef __cplusplus
extern "C"
# endif
/* function pointer of sendchar to be used by print utility */
void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
# elif defined(PROTOCOL_CHIBIOS) /* PROTOCOL_CHIBIOS */
# if __has_include_next("_print.h")
# include_next "_print.h" /* Include the platforms print.h */
# else
// Fall back to lib/printf
# include "printf.h" // lib/printf/printf.h
# ifdef USER_PRINT /* USER_PRINT */
// Remove normal print defines
# define print(s)
# define println(s)
# define xprintf(fmt, ...)
// Create user print defines
# define uprint(s) printf(s)
# define uprintln(s) printf(s "\r\n")
# define uprintf printf
# else /* NORMAL PRINT */
// Create user & normal print defines
# define print(s) printf(s)
# define println(s) printf(s "\r\n")
# define xprintf printf
# define uprint(s) printf(s)
# define uprintln(s) printf(s "\r\n")
# define uprintf printf
# endif /* USER_PRINT / NORMAL PRINT */
# elif defined(PROTOCOL_ARM_ATSAM) /* PROTOCOL_ARM_ATSAM */
# include "arm_atsam/printf.h"
# ifdef USER_PRINT /* USER_PRINT */
// Remove normal print defines
# define print(s)
# define println(s)
# define xprintf(fmt, ...)
// Create user print defines
# define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define uprint(s) xprintf(s)
# define uprintln(s) xprintf(s "\r\n")
# else /* NORMAL PRINT */
// Create user & normal print defines
# define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define print(s) xprintf(s)
# define println(s) xprintf(s "\r\n")
# define uprint(s) print(s)
# define uprintln(s) println(s)
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
# define print(s) printf(s)
# define println(s) printf(s "\r\n")
# define xprintf printf
# define uprint(s) printf(s)
# define uprintln(s) printf(s "\r\n")
# define uprintf printf
# endif /* __AVR__ / PROTOCOL_CHIBIOS / PROTOCOL_ARM_ATSAM */
#else /* NO_PRINT */
# undef xprintf
// Remove print defines
# define print(s)
# define println(s)
# define xprintf(fmt, ...)
# define uprintf(fmt, ...)
# define uprint(s)
# define uprintln(s)
#endif /* NO_PRINT */
#ifdef USER_PRINT
// Remove normal print defines
# undef print
# undef println
# undef xprintf
# define print(s)
# define println(s)
# define xprintf(fmt, ...)
#endif
#define print_dec(i) xprintf("%u", i)
#define print_decs(i) xprintf("%d", i)
/* hex */
#define print_hex4(i) xprintf("%X", i)
#define print_hex8(i) xprintf("%02X", i)
#define print_hex16(i) xprintf("%04X", i)
#define print_hex32(i) xprintf("%08lX", i)
/* binary */
#define print_bin4(i) xprintf("%04b", i)
#define print_bin8(i) xprintf("%08b", i)
#define print_bin16(i) xprintf("%016b", i)
#define print_bin32(i) xprintf("%032lb", i)
#define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
/* print value utility */
#define print_val_dec(v) xprintf(#v ": %u\n", v)
#define print_val_decs(v) xprintf(#v ": %d\n", v)
#define print_val_hex8(v) xprintf(#v ": %X\n", v)
#define print_val_hex16(v) xprintf(#v ": %02X\n", v)
#define print_val_hex32(v) xprintf(#v ": %04lX\n", v)
#define print_val_bin8(v) xprintf(#v ": %08b\n", v)
#define print_val_bin16(v) xprintf(#v ": %016b\n", v)
#define print_val_bin32(v) xprintf(#v ": %032lb\n", v)
#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v))
#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v))
#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v))
// User print disables the normal print messages in the body of QMK/TMK code and
// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do
@@ -132,139 +104,32 @@ extern "C"
// print (and store their wasteful strings).
//
// !!! DO NOT USE USER PRINT CALLS IN THE BODY OF QMK/TMK !!!
//
# ifdef USER_PRINT
// Disable normal print
# define print_dec(data)
# define print_decs(data)
# define print_hex4(data)
# define print_hex8(data)
# define print_hex16(data)
# define print_hex32(data)
# define print_bin4(data)
# define print_bin8(data)
# define print_bin16(data)
# define print_bin32(data)
# define print_bin_reverse8(data)
# define print_bin_reverse16(data)
# define print_bin_reverse32(data)
# define print_val_dec(v)
# define print_val_decs(v)
# define print_val_hex8(v)
# define print_val_hex16(v)
# define print_val_hex32(v)
# define print_val_bin8(v)
# define print_val_bin16(v)
# define print_val_bin32(v)
# define print_val_bin_reverse8(v)
# define print_val_bin_reverse16(v)
# define print_val_bin_reverse32(v)
# else /* NORMAL_PRINT */
// Enable normal print
/* decimal */
# define print_dec(i) xprintf("%u", i)
# define print_decs(i) xprintf("%d", i)
/* hex */
# define print_hex4(i) xprintf("%X", i)
# define print_hex8(i) xprintf("%02X", i)
# define print_hex16(i) xprintf("%04X", i)
# define print_hex32(i) xprintf("%08lX", i)
/* binary */
# define print_bin4(i) xprintf("%04b", i)
# define print_bin8(i) xprintf("%08b", i)
# define print_bin16(i) xprintf("%016b", i)
# define print_bin32(i) xprintf("%032lb", i)
# define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
# define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
# define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
/* print value utility */
# define print_val_dec(v) xprintf(# v ": %u\n", v)
# define print_val_decs(v) xprintf(# v ": %d\n", v)
# define print_val_hex8(v) xprintf(# v ": %X\n", v)
# define print_val_hex16(v) xprintf(# v ": %02X\n", v)
# define print_val_hex32(v) xprintf(# v ": %04lX\n", v)
# define print_val_bin8(v) xprintf(# v ": %08b\n", v)
# define print_val_bin16(v) xprintf(# v ": %016b\n", v)
# define print_val_bin32(v) xprintf(# v ": %032lb\n", v)
# define print_val_bin_reverse8(v) xprintf(# v ": %08b\n", bitrev(v))
# define print_val_bin_reverse16(v) xprintf(# v ": %016b\n", bitrev16(v))
# define print_val_bin_reverse32(v) xprintf(# v ": %032lb\n", bitrev32(v))
# endif /* USER_PRINT / NORMAL_PRINT */
// User Print
/* decimal */
# define uprint_dec(i) uprintf("%u", i)
# define uprint_decs(i) uprintf("%d", i)
#define uprint_dec(i) uprintf("%u", i)
#define uprint_decs(i) uprintf("%d", i)
/* hex */
# define uprint_hex4(i) uprintf("%X", i)
# define uprint_hex8(i) uprintf("%02X", i)
# define uprint_hex16(i) uprintf("%04X", i)
# define uprint_hex32(i) uprintf("%08lX", i)
#define uprint_hex4(i) uprintf("%X", i)
#define uprint_hex8(i) uprintf("%02X", i)
#define uprint_hex16(i) uprintf("%04X", i)
#define uprint_hex32(i) uprintf("%08lX", i)
/* binary */
# define uprint_bin4(i) uprintf("%04b", i)
# define uprint_bin8(i) uprintf("%08b", i)
# define uprint_bin16(i) uprintf("%016b", i)
# define uprint_bin32(i) uprintf("%032lb", i)
# define uprint_bin_reverse8(i) uprintf("%08b", bitrev(i))
# define uprint_bin_reverse16(i) uprintf("%016b", bitrev16(i))
# define uprint_bin_reverse32(i) uprintf("%032lb", bitrev32(i))
#define uprint_bin4(i) uprintf("%04b", i)
#define uprint_bin8(i) uprintf("%08b", i)
#define uprint_bin16(i) uprintf("%016b", i)
#define uprint_bin32(i) uprintf("%032lb", i)
#define uprint_bin_reverse8(i) uprintf("%08b", bitrev(i))
#define uprint_bin_reverse16(i) uprintf("%016b", bitrev16(i))
#define uprint_bin_reverse32(i) uprintf("%032lb", bitrev32(i))
/* print value utility */
# define uprint_val_dec(v) uprintf(# v ": %u\n", v)
# define uprint_val_decs(v) uprintf(# v ": %d\n", v)
# define uprint_val_hex8(v) uprintf(# v ": %X\n", v)
# define uprint_val_hex16(v) uprintf(# v ": %02X\n", v)
# define uprint_val_hex32(v) uprintf(# v ": %04lX\n", v)
# define uprint_val_bin8(v) uprintf(# v ": %08b\n", v)
# define uprint_val_bin16(v) uprintf(# v ": %016b\n", v)
# define uprint_val_bin32(v) uprintf(# v ": %032lb\n", v)
# define uprint_val_bin_reverse8(v) uprintf(# v ": %08b\n", bitrev(v))
# define uprint_val_bin_reverse16(v) uprintf(# v ": %016b\n", bitrev16(v))
# define uprint_val_bin_reverse32(v) uprintf(# v ": %032lb\n", bitrev32(v))
#else /* NO_PRINT */
# define xprintf(fmt, ...)
# define print(s)
# define println(s)
# define print_set_sendchar(func)
# define print_dec(data)
# define print_decs(data)
# define print_hex4(data)
# define print_hex8(data)
# define print_hex16(data)
# define print_hex32(data)
# define print_bin4(data)
# define print_bin8(data)
# define print_bin16(data)
# define print_bin32(data)
# define print_bin_reverse8(data)
# define print_bin_reverse16(data)
# define print_bin_reverse32(data)
# define print_val_dec(v)
# define print_val_decs(v)
# define print_val_hex8(v)
# define print_val_hex16(v)
# define print_val_hex32(v)
# define print_val_bin8(v)
# define print_val_bin16(v)
# define print_val_bin32(v)
# define print_val_bin_reverse8(v)
# define print_val_bin_reverse16(v)
# define print_val_bin_reverse32(v)
#endif /* NO_PRINT */
/* Backward compatiblitly for old name */
#define pdec(data) print_dec(data)
#define pdec16(data) print_dec(data)
#define phex(data) print_hex8(data)
#define phex16(data) print_hex16(data)
#define pbin(data) print_bin8(data)
#define pbin16(data) print_bin16(data)
#define pbin_reverse(data) print_bin_reverse8(data)
#define pbin_reverse16(data) print_bin_reverse16(data)
#define uprint_val_dec(v) uprintf(#v ": %u\n", v)
#define uprint_val_decs(v) uprintf(#v ": %d\n", v)
#define uprint_val_hex8(v) uprintf(#v ": %X\n", v)
#define uprint_val_hex16(v) uprintf(#v ": %02X\n", v)
#define uprint_val_hex32(v) uprintf(#v ": %04lX\n", v)
#define uprint_val_bin8(v) uprintf(#v ": %08b\n", v)
#define uprint_val_bin16(v) uprintf(#v ": %016b\n", v)
#define uprint_val_bin32(v) uprintf(#v ": %032lb\n", v)
#define uprint_val_bin_reverse8(v) uprintf(#v ": %08b\n", bitrev(v))
#define uprint_val_bin_reverse16(v) uprintf(#v ": %016b\n", bitrev16(v))
#define uprint_val_bin_reverse32(v) uprintf(#v ": %032lb\n", bitrev32(v))

View File

@@ -1,5 +1,5 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,17 +14,14 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include "sendchar.h"
#pragma once
// bind lib/printf to console interface - sendchar
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xCAFE
#define DEVICE_VER 0x0814
#define MANUFACTURER t.m.k.
#define PRODUCT USB to USB keyboard converter
static int8_t null_sendchar_func(uint8_t c) { return 0; }
static sendchar_func_t func = null_sendchar_func;
#define DESCRIPTION Product from t.m.k. keyboard firmware project
void print_set_sendchar(sendchar_func_t send) { func = send; }
/* matrix size */
#define MATRIX_ROWS 32
#define MATRIX_COLS 8
void _putchar(char character) { func(character); }

View File

@@ -4,6 +4,7 @@
# include <avr/pgmspace.h>
#else
# define PROGMEM
# define PSTR(x) x
# define PGM_P const char*
# define memcpy_P(dest, src, n) memcpy(dest, src, n)
# define pgm_read_byte(address_short) *((uint8_t*)(address_short))

View File

@@ -34,12 +34,16 @@ enum hid_report_ids {
};
/* Mouse buttons */
#define MOUSE_BTN_MASK(n) (1 << (n))
enum mouse_buttons {
MOUSE_BTN1 = (1 << 0),
MOUSE_BTN2 = (1 << 1),
MOUSE_BTN3 = (1 << 2),
MOUSE_BTN4 = (1 << 3),
MOUSE_BTN5 = (1 << 4)
MOUSE_BTN1 = MOUSE_BTN_MASK(0),
MOUSE_BTN2 = MOUSE_BTN_MASK(1),
MOUSE_BTN3 = MOUSE_BTN_MASK(2),
MOUSE_BTN4 = MOUSE_BTN_MASK(3),
MOUSE_BTN5 = MOUSE_BTN_MASK(4),
MOUSE_BTN6 = MOUSE_BTN_MASK(5),
MOUSE_BTN7 = MOUSE_BTN_MASK(6),
MOUSE_BTN8 = MOUSE_BTN_MASK(7)
};
/* Consumer Page (0x0C)
@@ -76,7 +80,21 @@ enum consumer_usages {
AL_ASSISTANT = 0x1CB,
AL_KEYBOARD_LAYOUT = 0x1AE,
// 15.16 Generic GUI Application Controls
AC_NEW = 0x201,
AC_OPEN = 0x202,
AC_CLOSE = 0x203,
AC_EXIT = 0x204,
AC_MAXIMIZE = 0x205,
AC_MINIMIZE = 0x206,
AC_SAVE = 0x207,
AC_PRINT = 0x208,
AC_PROPERTIES = 0x209,
AC_UNDO = 0x21A,
AC_COPY = 0x21B,
AC_CUT = 0x21C,
AC_PASTE = 0x21D,
AC_SELECT_ALL = 0x21E,
AC_FIND = 0x21F,
AC_SEARCH = 0x221,
AC_HOME = 0x223,
AC_BACK = 0x224,
@@ -92,9 +110,12 @@ enum consumer_usages {
*/
enum desktop_usages {
// 4.5.1 System Controls - Power Controls
SYSTEM_POWER_DOWN = 0x81,
SYSTEM_SLEEP = 0x82,
SYSTEM_WAKE_UP = 0x83
SYSTEM_POWER_DOWN = 0x81,
SYSTEM_SLEEP = 0x82,
SYSTEM_WAKE_UP = 0x83,
SYSTEM_RESTART = 0x8F,
// 4.10 System Display Controls
SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5
};
// clang-format on

View File

@@ -23,6 +23,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
extern "C" {
#endif
typedef int8_t (*sendchar_func_t)(uint8_t c);
/* transmit a character. return 0 on success, -1 on error. */
int8_t sendchar(uint8_t c);

View File

@@ -14,5 +14,5 @@ void suspend_power_down_user(void);
void suspend_power_down_kb(void);
#ifndef USB_SUSPEND_WAKEUP_DELAY
# define USB_SUSPEND_WAKEUP_DELAY 200
# define USB_SUSPEND_WAKEUP_DELAY 0
#endif

View File

@@ -0,0 +1,58 @@
/*
Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
If you happen to meet one of the copyright holders in a bar you are obligated
to buy them one pint of beer.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sync_timer.h"
#include "keyboard.h"
#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
volatile int32_t sync_timer_ms;
void sync_timer_init(void) { sync_timer_ms = 0; }
void sync_timer_update(uint32_t time) {
if (is_keyboard_master()) return;
sync_timer_ms = time - timer_read32();
}
uint16_t sync_timer_read(void) {
if (is_keyboard_master()) return timer_read();
return sync_timer_read32();
}
uint32_t sync_timer_read32(void) {
if (is_keyboard_master()) return timer_read32();
return sync_timer_ms + timer_read32();
}
uint16_t sync_timer_elapsed(uint16_t last) {
if (is_keyboard_master()) return timer_elapsed(last);
return TIMER_DIFF_16(sync_timer_read(), last);
}
uint32_t sync_timer_elapsed32(uint32_t last) {
if (is_keyboard_master()) return timer_elapsed32(last);
return TIMER_DIFF_32(sync_timer_read32(), last);
}
#endif

View File

@@ -0,0 +1,54 @@
/*
Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
If you happen to meet one of the copyright holders in a bar you are obligated
to buy them one pint of beer.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include "timer.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
void sync_timer_init(void);
void sync_timer_update(uint32_t time);
uint16_t sync_timer_read(void);
uint32_t sync_timer_read32(void);
uint16_t sync_timer_elapsed(uint16_t last);
uint32_t sync_timer_elapsed32(uint32_t last);
#else
# define sync_timer_init()
# define sync_timer_clear()
# define sync_timer_update(t)
# define sync_timer_read() timer_read()
# define sync_timer_read32() timer_read32()
# define sync_timer_elapsed(t) timer_elapsed(t)
# define sync_timer_elapsed32(t) timer_elapsed32(t)
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -1,172 +0,0 @@
// TODO: Teensy support(ATMega32u4/AT90USB128)
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
/* UART Example for Teensy USB Development Board
* http://www.pjrc.com/teensy/
* Copyright (c) 2009 PJRC.COM, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Version 1.0: Initial Release
// Version 1.1: Add support for Teensy 2.0, minor optimizations
#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
# define UDRn UDR0
# define UBRRnL UBRR0L
# define UCSRnA UCSR0A
# define UCSRnB UCSR0B
# define UCSRnC UCSR0C
# define U2Xn U2X0
# define RXENn RXEN0
# define TXENn TXEN0
# define RXCIEn RXCIE0
# define UCSZn1 UCSZ01
# define UCSZn0 UCSZ00
# define UDRIEn UDRIE0
# define USARTn_UDRE_vect USART_UDRE_vect
# define USARTn_RX_vect USART_RX_vect
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
# define UDRn UDR1
# define UBRRnL UBRR1L
# define UCSRnA UCSR1A
# define UCSRnB UCSR1B
# define UCSRnC UCSR1C
# define U2Xn U2X1
# define RXENn RXEN1
# define TXENn TXEN1
# define RXCIEn RXCIE1
# define UCSZn1 UCSZ11
# define UCSZn0 UCSZ10
# define UDRIEn UDRIE1
# define USARTn_UDRE_vect USART1_UDRE_vect
# define USARTn_RX_vect USART1_RX_vect
#elif defined(__AVR_ATmega32A__)
# define UDRn UDR
# define UBRRnL UBRRL
# define UCSRnA UCSRA
# define UCSRnB UCSRB
# define UCSRnC UCSRC
# define U2Xn U2X
# define RXENn RXEN
# define TXENn TXEN
# define RXCIEn RXCIE
# define UCSZn1 UCSZ1
# define UCSZn0 UCSZ0
# define UDRIEn UDRIE
# define USARTn_UDRE_vect USART_UDRE_vect
# define USARTn_RX_vect USART_RX_vect
#endif
// These buffers may be any size from 2 to 256 bytes.
#define RX_BUFFER_SIZE 64
#define TX_BUFFER_SIZE 256
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
static volatile uint8_t tx_buffer_head;
static volatile uint8_t tx_buffer_tail;
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
static volatile uint8_t rx_buffer_head;
static volatile uint8_t rx_buffer_tail;
// Initialize the UART
void uart_init(uint32_t baud) {
cli();
UBRRnL = (F_CPU / 4 / baud - 1) / 2;
UCSRnA = (1 << U2Xn);
UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
UCSRnC = (1 << UCSZn1) | (1 << UCSZn0);
tx_buffer_head = tx_buffer_tail = 0;
rx_buffer_head = rx_buffer_tail = 0;
sei();
}
// Transmit a byte
void uart_putchar(uint8_t c) {
uint8_t i;
i = tx_buffer_head + 1;
if (i >= TX_BUFFER_SIZE) i = 0;
// return immediately to avoid deadlock when interrupt is disabled(called from ISR)
if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return;
while (tx_buffer_tail == i)
; // wait until space in buffer
// cli();
tx_buffer[i] = c;
tx_buffer_head = i;
UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
// sei();
}
// Receive a byte
uint8_t uart_getchar(void) {
uint8_t c, i;
while (rx_buffer_head == rx_buffer_tail)
; // wait for character
i = rx_buffer_tail + 1;
if (i >= RX_BUFFER_SIZE) i = 0;
c = rx_buffer[i];
rx_buffer_tail = i;
return c;
}
// Return the number of bytes waiting in the receive buffer.
// Call this before uart_getchar() to check if it will need
// to wait for a byte to arrive.
uint8_t uart_available(void) {
uint8_t head, tail;
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return RX_BUFFER_SIZE + head - tail;
}
// Transmit Interrupt
ISR(USARTn_UDRE_vect) {
uint8_t i;
if (tx_buffer_head == tx_buffer_tail) {
// buffer is empty, disable transmit interrupt
UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
} else {
i = tx_buffer_tail + 1;
if (i >= TX_BUFFER_SIZE) i = 0;
UDRn = tx_buffer[i];
tx_buffer_tail = i;
}
}
// Receive Interrupt
ISR(USARTn_RX_vect) {
uint8_t c, i;
c = UDRn;
i = rx_buffer_head + 1;
if (i >= RX_BUFFER_SIZE) i = 0;
if (i != rx_buffer_tail) {
rx_buffer[i] = c;
rx_buffer_head = i;
}
}

View File

@@ -1,8 +0,0 @@
#pragma once
#include <stdint.h>
void uart_init(uint32_t baud);
void uart_putchar(uint8_t c);
uint8_t uart_getchar(void);
uint8_t uart_available(void);

View File

@@ -1,123 +0,0 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "util.h"
// bit population - return number of on-bit
__attribute__((noinline)) uint8_t bitpop(uint8_t bits) {
uint8_t c;
for (c = 0; bits; c++) bits &= bits - 1;
return c;
/*
const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
return bit_count[bits>>4] + bit_count[bits&0x0F]
*/
}
uint8_t bitpop16(uint16_t bits) {
uint8_t c;
for (c = 0; bits; c++) bits &= bits - 1;
return c;
}
uint8_t bitpop32(uint32_t bits) {
uint8_t c;
for (c = 0; bits; c++) bits &= bits - 1;
return c;
}
// most significant on-bit - return highest location of on-bit
// NOTE: return 0 when bit0 is on or all bits are off
__attribute__((noinline)) uint8_t biton(uint8_t bits) {
uint8_t n = 0;
if (bits >> 4) {
bits >>= 4;
n += 4;
}
if (bits >> 2) {
bits >>= 2;
n += 2;
}
if (bits >> 1) {
bits >>= 1;
n += 1;
}
return n;
}
uint8_t biton16(uint16_t bits) {
uint8_t n = 0;
if (bits >> 8) {
bits >>= 8;
n += 8;
}
if (bits >> 4) {
bits >>= 4;
n += 4;
}
if (bits >> 2) {
bits >>= 2;
n += 2;
}
if (bits >> 1) {
bits >>= 1;
n += 1;
}
return n;
}
uint8_t biton32(uint32_t bits) {
uint8_t n = 0;
if (bits >> 16) {
bits >>= 16;
n += 16;
}
if (bits >> 8) {
bits >>= 8;
n += 8;
}
if (bits >> 4) {
bits >>= 4;
n += 4;
}
if (bits >> 2) {
bits >>= 2;
n += 2;
}
if (bits >> 1) {
bits >>= 1;
n += 1;
}
return n;
}
__attribute__((noinline)) uint8_t bitrev(uint8_t bits) {
bits = (bits & 0x0f) << 4 | (bits & 0xf0) >> 4;
bits = (bits & 0b00110011) << 2 | (bits & 0b11001100) >> 2;
bits = (bits & 0b01010101) << 1 | (bits & 0b10101010) >> 1;
return bits;
}
uint16_t bitrev16(uint16_t bits) {
bits = bitrev(bits & 0x00ff) << 8 | bitrev((bits & 0xff00) >> 8);
return bits;
}
uint32_t bitrev32(uint32_t bits) {
bits = (uint32_t)bitrev16(bits & 0x0000ffff) << 16 | bitrev16((bits & 0xffff0000) >> 16);
return bits;
}

View File

@@ -6,10 +6,89 @@
extern "C" {
#endif
#if defined(__ARMEL__) || defined(__ARMEB__)
# ifndef __OPTIMIZE__
# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed"
# endif
# define wait_cpuclock(x) wait_cpuclock_allnop(x)
# define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t"
__attribute__((always_inline)) static inline void wait_cpuclock_allnop(unsigned int n) { /* n: 1..135 */
/* The argument n must be a constant expression.
* That way, compiler optimization will remove unnecessary code. */
if (n < 1) {
return;
}
if (n > 8) {
unsigned int n8 = n / 8;
n = n - n8 * 8;
switch (n8) {
case 16:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 15:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 14:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 13:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 12:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 11:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 10:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 9:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 8:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 7:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 6:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 5:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 4:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 3:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 2:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 1:
asm volatile(CLOCK_DELAY_NOP8::: "memory");
case 0:
break;
}
}
switch (n) {
case 8:
asm volatile("nop" ::: "memory");
case 7:
asm volatile("nop" ::: "memory");
case 6:
asm volatile("nop" ::: "memory");
case 5:
asm volatile("nop" ::: "memory");
case 4:
asm volatile("nop" ::: "memory");
case 3:
asm volatile("nop" ::: "memory");
case 2:
asm volatile("nop" ::: "memory");
case 1:
asm volatile("nop" ::: "memory");
case 0:
break;
}
}
#endif
#if defined(__AVR__)
# include <util/delay.h>
# define wait_ms(ms) _delay_ms(ms)
# define wait_us(us) _delay_us(us)
# define wait_cpuclock(x) __builtin_avr_delay_cycles(x)
#elif defined PROTOCOL_CHIBIOS
# include <ch.h>
# define wait_ms(ms) \

View File

@@ -1,14 +0,0 @@
#!/bin/sh
ALL_CONFIGS=$*
GREP="grep"
cat <<- EOF > lib/lufa/Bootloaders/DFU/Keyboard.h
#pragma once
$($GREP "MANUFACTURER[ \t]" $ALL_CONFIGS -h | tail -1)
$($GREP "PRODUCT[ \t]" $ALL_CONFIGS -h | tail -1 | tr -d '\r') Bootloader
$($GREP "QMK_ESC_OUTPUT[ \t]" $ALL_CONFIGS -h | tail -1)
$($GREP "QMK_ESC_INPUT[ \t]" $ALL_CONFIGS -h | tail -1)
$($GREP "QMK_LED[ \t]" $ALL_CONFIGS -h | tail -1)
$($GREP "QMK_SPEAKER[ \t]" $ALL_CONFIGS -h | tail -1)
EOF

View File

@@ -1,5 +1,5 @@
/*
Copyright 2011 Jun WAKO <wakojun@gmail.com>
Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
Copyright 2013 Shay Green <gblargg@gmail.com>
This software is licensed with a Modified BSD License.
@@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "adb.h"
#include "print.h"
// GCC doesn't inline functions normally
#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT))
@@ -59,7 +60,6 @@ static inline void place_bit1(void);
static inline void send_byte(uint8_t data);
static inline uint16_t wait_data_lo(uint16_t us);
static inline uint16_t wait_data_hi(uint16_t us);
static inline uint16_t adb_host_dev_recv(uint8_t device);
void adb_host_init(void) {
ADB_PORT &= ~(1 << ADB_DATA_BIT);
@@ -81,119 +81,164 @@ bool adb_host_psw(void) { return psw_in(); }
* <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
* <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
*/
// ADB Bit Cells
//
// bit cell time: 70-130us
// low part of bit0: 60-70% of bit cell
// low part of bit1: 30-40% of bit cell
//
// bit cell time 70us 130us
// --------------------------------------------
// low part of bit0 42-49 78-91
// high part of bit0 21-28 39-52
// low part of bit1 21-28 39-52
// high part of bit1 42-49 78-91
//
//
// bit0:
// 70us bit cell:
// ____________~~~~~~
// 42-49 21-28
//
// 130us bit cell:
// ____________~~~~~~
// 78-91 39-52
//
// bit1:
// 70us bit cell:
// ______~~~~~~~~~~~~
// 21-28 42-49
//
// 130us bit cell:
// ______~~~~~~~~~~~~
// 39-52 78-91
//
// [from Apple IIgs Hardware Reference Second Edition]
enum { ADDR_KEYB = 0x20, ADDR_MOUSE = 0x30 };
uint16_t adb_host_kbd_recv(void) { return adb_host_dev_recv(ADDR_KEYB); }
uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); }
#ifdef ADB_MOUSE_ENABLE
void adb_mouse_init(void) { return; }
__attribute__((weak)) void adb_mouse_init(void) { return; }
uint16_t adb_host_mouse_recv(void) { return adb_host_dev_recv(ADDR_MOUSE); }
__attribute__((weak)) void adb_mouse_task(void) { return; }
uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); }
#endif
static inline uint16_t adb_host_dev_recv(uint8_t device) {
uint16_t data = 0;
// This sends Talk command to read data from register and returns length of the data.
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
for (int8_t i = 0; i < len; i++) buf[i] = 0;
cli();
attention();
send_byte(device | 0x0C); // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00)
place_bit0(); // Stopbit(0)
send_byte((addr << 4) | ADB_CMD_TALK | reg);
place_bit0(); // Stopbit(0)
// TODO: Service Request(Srq):
// Device holds low part of comannd stopbit for 140-260us
//
// Command:
// ......._ ______________________ ___ ............_ -------
// | | | | | | |
// Command | | | | | Data bytes | |
// ........|___| | 140-260 |__| |_............|___|
// |stop0 | Tlt Stop-to-Start |start1| |stop0 |
//
// Command without data:
// ......._ __________________________
// | |
// Command | |
// ........|___| | 140-260 |
// |stop0 | Tlt Stop-to-Start |
//
// Service Request:
// ......._ ______ ___ ............_ -------
// | 140-260 | | | | | |
// Command | Service Request | | | | Data bytes | |
// ........|___________________| |__| |_............|___|
// |stop0 | |start1| |stop0 |
// ......._ __________
// | 140-260 |
// Command | Service Request |
// ........|___________________|
// |stop0 |
// This can be happened?
// ......._ ______________________ ___ ............_ -----
// | | | | | | 140-260 |
// Command | | | | | Data bytes | Service Request |
// ........|___| | 140-260 |__| |_............|_________________|
// |stop0 | Tlt Stop-to-Start |start1| |stop0 |
//
// "Service requests are issued by the devices during a very specific time at the
// end of the reception of the command packet.
// If a device in need of service issues a service request, it must do so within
// the 65 µs of the Stop Bits low time and maintain the line low for a total of 300 µs."
//
// "A device sends a Service Request signal by holding the bus low during the low
// portion of the stop bit of any command or data transaction. The device must lengthen
// the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
// http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
xprintf("R");
sei();
return -30; // something wrong
return 0;
}
if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
sei();
return 0; // No data to send
return 0; // No data from device(not error);
}
uint8_t n = 17; // start bit + 16 data bits
// start bit(1)
if (!wait_data_hi(40)) {
xprintf("S");
sei();
return 0;
}
if (!wait_data_lo(100)) {
xprintf("s");
sei();
return 0;
}
uint8_t n = 0; // bit count
do {
//
// |<- bit_cell_max(130) ->|
// | |<- lo ->|
// | | |<-hi->|
// _______
// | | |
// | 130-lo | lo-hi |
// |________| |
//
uint8_t lo = (uint8_t)wait_data_hi(130);
if (!lo) goto error;
if (!lo) goto error; // no more bit or after stop bit
uint8_t hi = (uint8_t)wait_data_lo(lo);
if (!hi) goto error;
if (!hi) goto error; // stop bit extedned by Srq?
hi = lo - hi;
lo = 130 - lo;
if (n / 8 >= len) continue; // can't store in buf
data <<= 1;
if (lo < hi) {
data |= 1;
} else if (n == 17) {
sei();
return -20;
buf[n / 8] <<= 1;
if ((130 - lo) < (lo - hi)) {
buf[n / 8] |= 1;
}
} while (--n);
// Stop bit can't be checked normally since it could have service request lenghtening
// and its high state never goes low.
if (!wait_data_hi(351) || wait_data_lo(91)) {
sei();
return -21;
}
sei();
return data;
} while (++n);
error:
sei();
return -n;
return n / 8;
}
void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) {
uint16_t adb_host_talk(uint8_t addr, uint8_t reg) {
uint8_t len;
uint8_t buf[8];
len = adb_host_talk_buf(addr, reg, buf, 8);
if (len != 2) return 0;
return (buf[0] << 8 | buf[1]);
}
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
cli();
attention();
send_byte(cmd);
place_bit0(); // Stopbit(0)
send_byte((addr << 4) | ADB_CMD_LISTEN | reg);
place_bit0(); // Stopbit(0)
// TODO: Service Request
_delay_us(200); // Tlt/Stop to Start
place_bit1(); // Startbit(1)
send_byte(data_h);
send_byte(data_l);
for (int8_t i = 0; i < len; i++) {
send_byte(buf[i]);
// xprintf("%02X ", buf[i]);
}
place_bit0(); // Stopbit(0);
sei();
}
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) {
uint8_t buf[2] = {data_h, data_l};
adb_host_listen_buf(addr, reg, buf, 2);
}
void adb_host_flush(uint8_t addr) {
cli();
attention();
send_byte((addr << 4) | ADB_CMD_FLUSH);
place_bit0(); // Stopbit(0)
_delay_us(200); // Tlt/Stop to Start
sei();
}
// send state of LEDs
void adb_host_kbd_led(uint8_t led) {
// Addr:Keyboard(0010), Cmd:Listen(10), Register2(10)
// send upper byte (not used)
// send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0:
adb_host_listen(0x2A, 0, led & 0x07);
// Listen Register2
// upper byte: not used
// lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07);
}
#ifdef ADB_PSW_BIT
@@ -327,7 +372,7 @@ Commands
bits commands
------------------------------------------------------
- - - - 0 0 0 0 Send Request(reset all devices)
- - - - 0 0 0 0 Send Reset(reset all devices)
A A A A 0 0 0 1 Flush(reset a device)
- - - - 0 0 1 0 Reserved
- - - - 0 0 1 1 Reserved
@@ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2)
| +----------------------------- Delete
+------------------------------- Reserved
Address, Handler ID and bits(Register3)
1514131211 . . 8 7 . . . . . . 0
| | | | | | | | | | | | | | | |
| | | | | | | | +-+-+-+-+-+-+-+- Handler ID
| | | | +-+-+-+----------------- Address
| | | +------------------------- 0
| | +--------------------------- Service request enable(1 = enabled)
| +----------------------------- Exceptional event(alwyas 1 if not used)
+------------------------------- 0
ADB Bit Cells
bit cell time: 70-130us
low part of bit0: 60-70% of bit cell
low part of bit1: 30-40% of bit cell
bit cell time 70us 130us
--------------------------------------------
low part of bit0 42-49 78-91
high part of bit0 21-28 39-52
low part of bit1 21-28 39-52
high part of bit1 42-49 78-91
bit0:
70us bit cell:
____________~~~~~~
42-49 21-28
130us bit cell:
____________~~~~~~
78-91 39-52
bit1:
70us bit cell:
______~~~~~~~~~~~~
21-28 42-49
130us bit cell:
______~~~~~~~~~~~~
39-52 78-91
[from Apple IIgs Hardware Reference Second Edition]
Keyboard Handle ID
Apple Standard Keyboard M0116: 0x01
Apple Extended Keyboard M0115: 0x02
Apple Extended Keyboard II M3501: 0x02
Apple Adjustable Keybaord: 0x10
http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802
END_OF_ADB
*/

View File

@@ -1,5 +1,5 @@
/*
Copyright 2011 Jun WAKO <wakojun@gmail.com>
Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -47,12 +47,60 @@ POSSIBILITY OF SUCH DAMAGE.
#define ADB_POWER 0x7F
#define ADB_CAPS 0x39
/* ADB commands */
// Default Address
#define ADB_ADDR_0 0
#define ADB_ADDR_DONGLE 1
#define ADB_ADDR_KEYBOARD 2
#define ADB_ADDR_MOUSE 3
#define ADB_ADDR_TABLET 4
#define ADB_ADDR_APPLIANCE 7
#define ADB_ADDR_8 8
#define ADB_ADDR_9 9
#define ADB_ADDR_10 10
#define ADB_ADDR_11 11
#define ADB_ADDR_12 12
#define ADB_ADDR_13 13
#define ADB_ADDR_14 14
#define ADB_ADDR_15 15
// for temporary purpose, do not use for polling
#define ADB_ADDR_TMP 15
#define ADB_ADDR_MOUSE_POLL 10
// Command Type
#define ADB_CMD_RESET 0
#define ADB_CMD_FLUSH 1
#define ADB_CMD_LISTEN 8
#define ADB_CMD_TALK 12
// Register
#define ADB_REG_0 0
#define ADB_REG_1 1
#define ADB_REG_2 2
#define ADB_REG_3 3
/* ADB keyboard handler id */
#define ADB_HANDLER_STD 0x01 /* IIGS, M0116 */
#define ADB_HANDLER_AEK 0x02 /* M0115, M3501 */
#define ADB_HANDLER_AEK_RMOD 0x03 /* M0115, M3501, alternate mode enableing right modifiers */
#define ADB_HANDLER_STD_ISO 0x04 /* M0118, ISO swapping keys */
#define ADB_HANDLER_AEK_ISO 0x05 /* M0115, M3501, ISO swapping keys */
#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */
#define ADB_HANDLER_CLASSIC1_MOUSE 0x01
#define ADB_HANDLER_CLASSIC2_MOUSE 0x02
#define ADB_HANDLER_EXTENDED_MOUSE 0x04
#define ADB_HANDLER_TURBO_MOUSE 0x32
// ADB host
void adb_host_init(void);
bool adb_host_psw(void);
uint16_t adb_host_talk(uint8_t addr, uint8_t reg);
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l);
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
void adb_host_flush(uint8_t addr);
void adb_host_kbd_led(uint8_t led);
uint16_t adb_host_kbd_recv(void);
uint16_t adb_host_mouse_recv(void);
void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l);
void adb_host_kbd_led(uint8_t led);
void adb_mouse_task(void);
void adb_mouse_init(void);
// ADB Mouse
void adb_mouse_task(void);
void adb_mouse_init(void);

View File

@@ -28,6 +28,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define I2C_LED_USE_DMA 1 // Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers
DmacDescriptor dmac_desc;
DmacDescriptor dmac_desc_wb;
static uint8_t i2c_led_q[I2C_Q_SIZE]; // I2C queue circular buffer
static uint8_t i2c_led_q_s; // Start of circular buffer
static uint8_t i2c_led_q_e; // End of circular buffer

View File

@@ -24,8 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "issi3733_driver.h"
# include "config.h"
__attribute__((__aligned__(16))) DmacDescriptor dmac_desc;
__attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb;
extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc;
extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb;
uint8_t I2C3733_Init_Control(void);
uint8_t I2C3733_Init_Drivers(void);

View File

@@ -305,11 +305,5 @@ int main(void) {
// dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired);
}
#endif // CONSOLE_ENABLE
// Run housekeeping
housekeeping_task_kb();
housekeeping_task_user();
}
return 1;
}

View File

@@ -15,16 +15,17 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "arm_atsam_protocol.h"
#include "tmk_core/common/led.h"
#include "rgb_matrix.h"
#include <string.h>
#include <math.h>
#ifdef RGB_MATRIX_ENABLE
# include "arm_atsam_protocol.h"
# include "led.h"
# include "rgb_matrix.h"
# include <string.h>
# include <math.h>
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
__attribute__((weak)) led_instruction_t led_instructions[] = {{.end = 1}};
static void md_rgb_matrix_config_override(int i);
#endif // USE_MASSDROP_CONFIGURATOR
# endif // USE_MASSDROP_CONFIGURATOR
void SERCOM1_0_Handler(void) {
if (SERCOM1->I2CM.INTFLAG.bit.ERROR) {
@@ -58,17 +59,17 @@ RGB led_buffer[ISSI3733_LED_COUNT];
uint8_t gcr_desired;
uint8_t gcr_actual;
uint8_t gcr_actual_last;
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
uint8_t gcr_breathe;
float breathe_mult;
float pomod;
#endif
# endif
#define ACT_GCR_NONE 0
#define ACT_GCR_INC 1
#define ACT_GCR_DEC 2
# define ACT_GCR_NONE 0
# define ACT_GCR_INC 1
# define ACT_GCR_DEC 2
#define LED_GCR_STEP_AUTO 2
# define LED_GCR_STEP_AUTO 2
static uint8_t gcr_min_counter;
static uint8_t v_5v_cat_hit;
@@ -78,11 +79,11 @@ void gcr_compute(void) {
uint8_t action = ACT_GCR_NONE;
uint8_t gcr_use = gcr_desired;
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
if (led_animation_breathing) {
gcr_use = gcr_breathe;
}
#endif
# endif
// If the 5v takes a catastrophic hit, disable the LED drivers briefly, assert auto gcr mode, min gcr and let the auto take over
if (v_5v < V5_CAT) {
@@ -150,7 +151,7 @@ void gcr_compute(void) {
gcr_actual -= LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
// If breathe mode is active, the top end can fluctuate if the host can not supply enough current
// So set the breathe GCR to where it becomes stable
if (led_animation_breathing == 1) {
@@ -159,7 +160,7 @@ void gcr_compute(void) {
// and the same would happen maybe one or two more times. Therefore I'm favoring
// powering through one full breathe and letting gcr settle completely
}
#endif
# endif
}
}
}
@@ -196,25 +197,25 @@ void md_rgb_matrix_prepare(void) {
}
}
void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) {
static void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) {
if (i < ISSI3733_LED_COUNT) {
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
md_rgb_matrix_config_override(i);
#else
# else
led_buffer[i].r = r;
led_buffer[i].g = g;
led_buffer[i].b = b;
#endif
# endif
}
}
void led_set_all(uint8_t r, uint8_t g, uint8_t b) {
static void led_set_all(uint8_t r, uint8_t g, uint8_t b) {
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
led_set_one(i, r, g, b);
}
}
void init(void) {
static void init(void) {
DBGC(DC_LED_MATRIX_INIT_BEGIN);
issi3733_prepare_arrays();
@@ -227,16 +228,16 @@ void init(void) {
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
}
void flush(void) {
#ifdef USE_MASSDROP_CONFIGURATOR
static void flush(void) {
# ifdef USE_MASSDROP_CONFIGURATOR
if (!led_enabled) {
return;
} // Prevent calculations and I2C traffic if LED drivers are not enabled
#else
# else
if (!sr_exp_data.bit.SDB_N) {
return;
} // Prevent calculations and I2C traffic if LED drivers are not enabled
#endif
# endif
// Wait for previous transfer to complete
while (i2c_led_q_running) {
@@ -249,7 +250,7 @@ void flush(void) {
*led_map[i].rgb.b = led_buffer[i].b;
}
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
breathe_mult = 1;
if (led_animation_breathing) {
@@ -275,7 +276,7 @@ void flush(void) {
pomod = (uint32_t)pomod % 10000;
pomod /= 100.0f;
#endif // USE_MASSDROP_CONFIGURATOR
# endif // USE_MASSDROP_CONFIGURATOR
uint8_t drvid;
@@ -295,25 +296,27 @@ void md_rgb_matrix_indicators(void) {
if (kbled && rgb_matrix_config.enable) {
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
if (
#if USB_LED_NUM_LOCK_SCANCODE != 255
# if USB_LED_NUM_LOCK_SCANCODE != 255
(led_map[i].scan == USB_LED_NUM_LOCK_SCANCODE && (kbled & (1 << USB_LED_NUM_LOCK))) ||
#endif // NUM LOCK
#if USB_LED_CAPS_LOCK_SCANCODE != 255
# endif // NUM LOCK
# if USB_LED_CAPS_LOCK_SCANCODE != 255
(led_map[i].scan == USB_LED_CAPS_LOCK_SCANCODE && (kbled & (1 << USB_LED_CAPS_LOCK))) ||
#endif // CAPS LOCK
#if USB_LED_SCROLL_LOCK_SCANCODE != 255
# endif // CAPS LOCK
# if USB_LED_SCROLL_LOCK_SCANCODE != 255
(led_map[i].scan == USB_LED_SCROLL_LOCK_SCANCODE && (kbled & (1 << USB_LED_SCROLL_LOCK))) ||
#endif // SCROLL LOCK
#if USB_LED_COMPOSE_SCANCODE != 255
# endif // SCROLL LOCK
# if USB_LED_COMPOSE_SCANCODE != 255
(led_map[i].scan == USB_LED_COMPOSE_SCANCODE && (kbled & (1 << USB_LED_COMPOSE))) ||
#endif // COMPOSE
#if USB_LED_KANA_SCANCODE != 255
# endif // COMPOSE
# if USB_LED_KANA_SCANCODE != 255
(led_map[i].scan == USB_LED_KANA_SCANCODE && (kbled & (1 << USB_LED_KANA))) ||
#endif // KANA
# endif // KANA
(0)) {
led_buffer[i].r = 255 - led_buffer[i].r;
led_buffer[i].g = 255 - led_buffer[i].g;
led_buffer[i].b = 255 - led_buffer[i].b;
if (rgb_matrix_get_flags() & LED_FLAG_INDICATOR) {
led_buffer[i].r = 255 - led_buffer[i].r;
led_buffer[i].g = 255 - led_buffer[i].g;
led_buffer[i].b = 255 - led_buffer[i].b;
}
}
}
}
@@ -325,7 +328,7 @@ const rgb_matrix_driver_t rgb_matrix_driver = {.init = init, .flush = flush, .se
= Legacy Lighting Support =
==============================================================================*/
#ifdef USE_MASSDROP_CONFIGURATOR
# ifdef USE_MASSDROP_CONFIGURATOR
// Ported from Massdrop QMK GitHub Repo
// TODO?: wire these up to keymap.c
@@ -467,4 +470,5 @@ static void md_rgb_matrix_config_override(int i) {
led_buffer[i].b = (uint8_t)bo;
}
#endif // USE_MASSDROP_CONFIGURATOR
# endif // USE_MASSDROP_CONFIGURATOR
#endif // RGB_MATRIX_ENABLE

View File

@@ -15,9 +15,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_MASSDROP_CONFIGURATOR
#ifdef RGB_MATRIX_ENABLE
# ifdef USE_MASSDROP_CONFIGURATOR
# include "md_rgb_matrix.h"
# include "md_rgb_matrix.h"
// Teal <-> Salmon
led_setup_t leds_teal_salmon[] = {
@@ -96,4 +97,5 @@ void *led_setups[] = {leds_rainbow_s, leds_rainbow_ns, leds_teal_salmon, leds_ye
const uint8_t led_setups_count = sizeof(led_setups) / sizeof(led_setups[0]);
#endif
# endif // USE_MASSDROP_CONFIGURATOR
#endif // RGB_MATRIX_ENABLE

View File

@@ -374,39 +374,33 @@ static uint8_t udi_hid_exk_report_trans[UDI_HID_EXK_REPORT_SIZE];
COMPILER_WORD_ALIGNED
UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {{
// clang-format off
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x80, // Usage (System Control)
0xA1, 0x01, // Collection (Application)
0x85, REPORT_ID_SYSTEM, // Report ID
0x1A, 0x81,
0x00, // Usage Minimum (81) (System Power Down)
0x2A, 0x83,
0x00, // Usage Maximum (83) (System Wake Up)
0x16, 0x01,
0x00, // Logical Minimum (1)
0x26, 0x03,
0x00, // Logical Maximum (3)
0x95, 0x01, // Report Count (1)
0x75, 0x10, // Report Size (16)
0x81, 0x00, // Input (Data, Array, Absolute)
0xC0, // End Collection
0x19, 0x01, // Usage Minimum (Pointer)
0x2A, 0xB7, 0x00, // Usage Maximum (System Display LCD Autoscale)
0x15, 0x01, // Logical Minimum
0x26, 0xB7, 0x00, // Logical Maximum
0x95, 0x01, // Report Count (1)
0x75, 0x10, // Report Size (16)
0x81, 0x00, // Input (Data, Array, Absolute)
0xC0, // End Collection
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, REPORT_ID_CONSUMER, // Report ID
0x1A, 0x01,
0x00, // Usage Minimum (Consumer Control)
0x2A, 0x9C,
0x02, // Usage Maximum (AC Distribute Vertically)
0x16, 0x01,
0x00, // Logical Minimum
0x26, 0x9C,
0x02, // Logical Maximum
0x95, 0x01, // Report Count (1)
0x75, 0x10, // Report Size (16)
0x81, 0x00, // Input (Data, Array, Absolute)
0xC0 // End Collection
0x19, 0x01, // Usage Minimum (Consumer Control)
0x2A, 0xA0, 0x02, // Usage Maximum (AC Desktop Show All Applications)
0x15, 0x01, // Logical Minimum
0x26, 0xA0, 0x02, // Logical Maximum
0x95, 0x01, // Report Count (1)
0x75, 0x10, // Report Size (16)
0x81, 0x00, // Input (Data, Array, Absolute)
0xC0 // End Collection
//clang-format on
}};
static bool udi_hid_exk_setreport(void);

View File

@@ -186,9 +186,10 @@ COMPILER_PACK_RESET()
#define USB_HID_COUNTRY_UK 32 // UK
#define USB_HID_COUNTRY_US 33 // US
#define USB_HID_COUNTRY_YUGOSLAVIA 34 // Yugoslavia
#define USB_HID_COUNTRY_TURKISH_F 35 // Turkish-F
//! @}
//! @}
#define USB_HID_COUNTRY_TURKISH_F \
35 // Turkish-F
//! @}
//! @}
//! @}
//! \name HID KEYS values

View File

@@ -167,6 +167,7 @@ int main(void) {
keyboard_setup();
/* Init USB */
usb_event_queue_init();
init_usb_driver(&USB_DRIVER);
#ifdef MIDI_ENABLE
@@ -225,6 +226,8 @@ int main(void) {
/* Main loop */
while (true) {
usb_event_queue_task();
#if !defined(NO_USB_STARTUP_CHECK)
if (USB_DRIVER.state == USB_SUSPENDED) {
print("[s]");

View File

@@ -27,6 +27,7 @@
#include <ch.h>
#include <hal.h>
#include <string.h>
#include "usb_main.h"
@@ -50,6 +51,7 @@ extern keymap_config_t keymap_config;
#ifdef WEBUSB_ENABLE
# include "webusb.h"
#endif
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
#endif
@@ -168,6 +170,7 @@ static const USBEndpointConfig shared_ep_config = {
};
#endif
#ifdef WEBUSB_ENABLE
/** Microsoft OS 2.0 Descriptor. This is used by Windows to select the USB driver for the device.
*
@@ -397,6 +400,69 @@ static usb_driver_configs_t drivers = {
* ---------------------------------------------------------
*/
#define USB_EVENT_QUEUE_SIZE 16
usbevent_t event_queue[USB_EVENT_QUEUE_SIZE];
uint8_t event_queue_head;
uint8_t event_queue_tail;
void usb_event_queue_init(void) {
// Initialise the event queue
memset(&event_queue, 0, sizeof(event_queue));
event_queue_head = 0;
event_queue_tail = 0;
}
static inline bool usb_event_queue_enqueue(usbevent_t event) {
uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE;
if (next == event_queue_tail) {
return false;
}
event_queue[event_queue_head] = event;
event_queue_head = next;
return true;
}
static inline bool usb_event_queue_dequeue(usbevent_t *event) {
if (event_queue_head == event_queue_tail) {
return false;
}
*event = event_queue[event_queue_tail];
event_queue_tail = (event_queue_tail + 1) % USB_EVENT_QUEUE_SIZE;
return true;
}
static inline void usb_event_suspend_handler(void) {
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif /* SLEEP_LED_ENABLE */
}
static inline void usb_event_wakeup_handler(void) {
suspend_wakeup_init();
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
// NOTE: converters may not accept this
led_set(host_keyboard_leds());
#endif /* SLEEP_LED_ENABLE */
}
void usb_event_queue_task(void) {
usbevent_t event;
while (usb_event_queue_dequeue(&event)) {
switch (event) {
case USB_EVENT_SUSPEND:
usb_event_suspend_handler();
break;
case USB_EVENT_WAKEUP:
usb_event_wakeup_handler();
break;
default:
// Nothing to do, we don't handle it.
break;
}
}
}
/* Handles the USB driver global events
* TODO: maybe disable some things when connection is lost? */
static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
@@ -431,9 +497,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
osalSysUnlockFromISR();
return;
case USB_EVENT_SUSPEND:
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif /* SLEEP_LED_ENABLE */
usb_event_queue_enqueue(USB_EVENT_SUSPEND);
/* Falls into.*/
case USB_EVENT_UNCONFIGURED:
/* Falls into.*/
@@ -454,12 +518,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
qmkusbWakeupHookI(&drivers.array[i].driver);
chSysUnlockFromISR();
}
suspend_wakeup_init();
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
// NOTE: converters may not accept this
led_set(host_keyboard_leds());
#endif /* SLEEP_LED_ENABLE */
usb_event_queue_enqueue(USB_EVENT_WAKEUP);
return;
case USB_EVENT_STALLED:
@@ -575,7 +634,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
if (!keymap_config.nkro && keyboard_idle) {
#else /* NKRO_ENABLE */
if (keyboard_idle) {
#endif /* NKRO_ENABLE */
#endif /* NKRO_ENABLE */
/* arm the idle timer if boot protocol & idle */
osalSysLockFromISR();
chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
@@ -867,7 +926,7 @@ void send_mouse(report_mouse_t *report) {
}
#else /* MOUSE_ENABLE */
void send_mouse(report_mouse_t *report) { (void)report; }
void send_mouse(report_mouse_t *report) { (void)report; }
#endif /* MOUSE_ENABLE */
/* ---------------------------------------------------------
@@ -923,9 +982,32 @@ void send_consumer(uint16_t data) {
#ifdef CONSOLE_ENABLE
int8_t sendchar(uint8_t c) {
// The previous implmentation had timeouts, but I think it's better to just slow down
// and make sure that everything is transferred, rather than dropping stuff
return chnWrite(&drivers.console_driver.driver, &c, 1);
static bool timed_out = false;
/* The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state.
*
* When a 5ms timeout write has timed out, hid_listen is most likely not running, or not
* listening to this keyboard, so we go into the timed_out state. In this state we assume
* that hid_listen is most likely not gonna be connected to us any time soon, so it would
* be wasteful to write follow-up characters with a 5ms timeout, it would all add up and
* unncecessarily slow down the firmware. However instead of just dropping the characters,
* we write them with a TIME_IMMEDIATE timeout, which is a zero timeout,
* and this will succeed only if hid_listen gets connected again. When a write with
* TIME_IMMEDIATE timeout succeeds, we know that hid_listen is listening to us again, and
* we can go back to the timed_out = false state, and following writes will be executed
* with a 5ms timeout. The reason we don't just send all characters with the TIME_IMMEDIATE
* timeout is that this could cause bytes to be lost even if hid_listen is running, if there
* is a lot of data being sent over the console.
*
* This logic will work correctly as long as hid_listen is able to receive at least 200
* bytes per second. On a heavily overloaded machine that's so overloaded that it's
* unusable, and constantly swapping, hid_listen might have trouble receiving 200 bytes per
* second, so some bytes might be lost on the console.
*/
const sysinterval_t timeout = timed_out ? TIME_IMMEDIATE : TIME_MS2I(5);
const size_t result = chnWriteTimeout(&drivers.console_driver.driver, &c, 1, timeout);
timed_out = (result == 0);
return result;
}
// Just a dummy function for now, this could be exposed as a weak function
@@ -946,15 +1028,8 @@ void console_task(void) {
} while (size > 0);
}
#else /* CONSOLE_ENABLE */
int8_t sendchar(uint8_t c) {
(void)c;
return 0;
}
#endif /* CONSOLE_ENABLE */
void _putchar(char character) { sendchar(character); }
#ifdef RAW_ENABLE
void raw_hid_send(uint8_t *data, uint8_t length) {
// TODO: implement variable size packet

View File

@@ -37,6 +37,17 @@ void init_usb_driver(USBDriver *usbp);
/* Restart the USB driver and bus */
void restart_usb_driver(USBDriver *usbp);
/* ---------------
* USB Event queue
* ---------------
*/
/* Initialisation of the FIFO */
void usb_event_queue_init(void);
/* Task to dequeue and execute any handlers for the USB events on the main thread */
void usb_event_queue_task(void);
/* ---------------
* Keyboard header
* ---------------

View File

@@ -782,9 +782,7 @@ static void send_keyboard(report_keyboard_t *report) {
uint8_t timeout = 255;
#ifdef BLUETOOTH_ENABLE
uint8_t where = where_to_send();
if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
if (where_to_send() == OUTPUT_BLUETOOTH) {
# ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
# elif MODULE_RN42
@@ -797,9 +795,6 @@ static void send_keyboard(report_keyboard_t *report) {
serial_send(report->keys[i]);
}
# endif
}
if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
return;
}
#endif
@@ -840,9 +835,7 @@ static void send_mouse(report_mouse_t *report) {
uint8_t timeout = 255;
# ifdef BLUETOOTH_ENABLE
uint8_t where = where_to_send();
if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
if (where_to_send() == OUTPUT_BLUETOOTH) {
# ifdef MODULE_ADAFRUIT_BLE
// FIXME: mouse buttons
adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons);
@@ -857,9 +850,6 @@ static void send_mouse(report_mouse_t *report) {
serial_send(report->h); // should try sending the wheel h here
serial_send(0x00);
# endif
}
if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
return;
}
# endif
@@ -918,9 +908,13 @@ static void send_system(uint16_t data) {
static void send_consumer(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
# ifdef BLUETOOTH_ENABLE
<<<<<<< HEAD
uint8_t where = where_to_send();
if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
=======
if (where_to_send() == OUTPUT_BLUETOOTH) {
>>>>>>> 0.12.52~1
# ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_send_consumer_key(data);
# elif MODULE_RN42
@@ -934,9 +928,12 @@ static void send_consumer(uint16_t data) {
serial_send(bitmap & 0xFF);
serial_send((bitmap >> 8) & 0xFF);
# endif
<<<<<<< HEAD
}
if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
=======
>>>>>>> 0.12.52~1
return;
}
# endif
@@ -955,9 +952,14 @@ static void send_consumer(uint16_t data) {
* FIXME: Needs doc
*/
int8_t sendchar(uint8_t c) {
<<<<<<< HEAD
// Not wait once timeouted.
=======
// Do not wait if the previous write has timed_out.
>>>>>>> 0.12.52~1
// Because sendchar() is called so many times, waiting each call causes big lag.
static bool timeouted = false;
// The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state.
static bool timed_out = false;
// prevents Console_Task() from running during sendchar() runs.
// or char will be lost. These two function is mutually exclusive.
@@ -971,11 +973,11 @@ int8_t sendchar(uint8_t c) {
goto ERROR_EXIT;
}
if (timeouted && !Endpoint_IsReadWriteAllowed()) {
if (timed_out && !Endpoint_IsReadWriteAllowed()) {
goto ERROR_EXIT;
}
timeouted = false;
timed_out = false;
uint8_t timeout = SEND_TIMEOUT;
while (!Endpoint_IsReadWriteAllowed()) {
@@ -986,7 +988,7 @@ int8_t sendchar(uint8_t c) {
goto ERROR_EXIT;
}
if (!(timeout--)) {
timeouted = true;
timed_out = true;
goto ERROR_EXIT;
}
_delay_ms(1);
@@ -1136,7 +1138,6 @@ static void setup_usb(void) {
// for Console_Task
USB_Device_EnableSOFEvents();
print_set_sendchar(sendchar);
}
/** \brief Main

View File

@@ -21,21 +21,11 @@ enum outputs {
OUTPUT_NONE,
OUTPUT_USB,
OUTPUT_BLUETOOTH,
// backward compatibility
OUTPUT_USB_AND_BT
OUTPUT_BLUETOOTH
};
/**
* backward compatibility for BLUETOOTH_ENABLE, send to BT and USB by default
*/
#ifndef OUTPUT_DEFAULT
# ifdef BLUETOOTH_ENABLE
# define OUTPUT_DEFAULT OUTPUT_USB_AND_BT
# else
# define OUTPUT_DEFAULT OUTPUT_AUTO
# endif
# define OUTPUT_DEFAULT OUTPUT_AUTO
#endif
void set_output(uint8_t output);

View File

@@ -95,11 +95,11 @@ void m0110_init(void) {
uint8_t data;
m0110_send(M0110_MODEL);
data = m0110_recv();
print("m0110_init model: "); phex(data); print("\n");
print("m0110_init model: "); print_hex8(data); print("\n");
m0110_send(M0110_TEST);
data = m0110_recv();
print("m0110_init test: "); phex(data); print("\n");
print("m0110_init test: "); print_hex8(data); print("\n");
*/
}
@@ -122,7 +122,7 @@ uint8_t m0110_send(uint8_t data) {
return 1;
ERROR:
print("m0110_send err: ");
phex(m0110_error);
print_hex8(m0110_error);
print("\n");
_delay_ms(500);
idle();
@@ -146,7 +146,7 @@ uint8_t m0110_recv(void) {
return data;
ERROR:
print("m0110_recv err: ");
phex(m0110_error);
print_hex8(m0110_error);
print("\n");
_delay_ms(500);
idle();

View File

@@ -5,7 +5,7 @@
#include "usb_descriptor.h"
#include "process_midi.h"
#if API_SYSEX_ENABLE
# include "api.h"
# include "api_sysex.h"
#endif
/*******************************************************************************

View File

@@ -190,7 +190,7 @@ static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) {
static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) {
if (!debug_mouse) return;
print("ps2_mouse: [");
phex(mouse_report->buttons);
print_hex8(mouse_report->buttons);
print("|");
print_hex8((uint8_t)mouse_report->x);
print(" ");

View File

@@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma once
#define SERIAL_UART_DATA UDR1
/* host role */
void serial_init(void);
uint8_t serial_recv(void);

View File

@@ -40,6 +40,22 @@ POSSIBILITY OF SUCH DAMAGE.
#include <avr/interrupt.h>
#include "serial.h"
#ifndef SERIAL_UART_BAUD
# define SERIAL_UART_BAUD 9600
#endif
#define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
#define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
#define SERIAL_UART_RXD_VECT USART1_RX_vect
#ifndef SERIAL_UART_INIT_CUSTOM
# define SERIAL_UART_INIT_CUSTOM \
/* enable TX */ \
UCSR1B = _BV(TXEN1); \
/* 8-bit data */ \
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10);
#endif
#if defined(SERIAL_UART_RTS_LO) && defined(SERIAL_UART_RTS_HI)
// Buffer state
// Empty: RBUF_SPACE == RBUF_SIZE(head==tail)
@@ -61,7 +77,14 @@ POSSIBILITY OF SUCH DAMAGE.
# define rbuf_check_rts_hi()
#endif
void serial_init(void) { SERIAL_UART_INIT(); }
void serial_init(void) {
do {
// Set baud rate
UBRR1L = SERIAL_UART_UBRR;
UBRR1L = SERIAL_UART_UBRR >> 8;
SERIAL_UART_INIT_CUSTOM;
} while (0);
}
// RX ring buffer
#define RBUF_SIZE 256

View File

@@ -40,7 +40,7 @@
#include "report.h"
#include "usb_descriptor.h"
#ifdef WEBUSB_ENABLE
#include "webusb_descriptor.h"
# include "webusb_descriptor.h"
#endif
#include "usb_descriptor_common.h"
@@ -119,19 +119,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
# endif
HID_RI_USAGE(8, 0x01), // Pointer
HID_RI_COLLECTION(8, 0x00), // Physical
// Buttons (5 bits)
// Buttons (8 bits)
HID_RI_USAGE_PAGE(8, 0x09), // Button
HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
HID_RI_USAGE_MAXIMUM(8, 0x05), // Button 5
HID_RI_USAGE_MAXIMUM(8, 0x08), // Button 8
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, 0x05),
HID_RI_REPORT_COUNT(8, 0x08),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
// Button padding (3 bits)
HID_RI_REPORT_COUNT(8, 0x01),
HID_RI_REPORT_SIZE(8, 0x03),
HID_RI_INPUT(8, HID_IOF_CONSTANT),
// X/Y position (2 bytes)
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
@@ -288,8 +284,8 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
#ifdef WEBUSB_ENABLE
const USB_Descriptor_BOS_t PROGMEM BOSDescriptor = BOS_DESCRIPTOR(
(MS_OS_20_PLATFORM_DESCRIPTOR(MS_OS_20_VENDOR_CODE, MS_OS_20_DESCRIPTOR_SET_TOTAL_LENGTH))
(WEBUSB_PLATFORM_DESCRIPTOR(WEBUSB_VENDOR_CODE, WEBUSB_LANDING_PAGE_INDEX))
(MS_OS_20_PLATFORM_DESCRIPTOR(MS_OS_20_VENDOR_CODE, MS_OS_20_DESCRIPTOR_SET_TOTAL_LENGTH))
(WEBUSB_PLATFORM_DESCRIPTOR(WEBUSB_VENDOR_CODE, WEBUSB_LANDING_PAGE_INDEX))
);
#endif
#ifdef JOYSTICK_ENABLE
@@ -369,6 +365,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
#else
.USBSpecification = VERSION_BCD(1, 1, 0),
#endif
#if VIRTSER_ENABLE
.Class = USB_CSCP_IADDeviceClass,
.SubClass = USB_CSCP_IADDeviceSubclass,

View File

@@ -49,7 +49,7 @@
# include <hal.h>
#endif
#ifdef WEBUSB_ENABLE
#include "webusb_descriptor.h"
# include "webusb_descriptor.h"
#endif
/*
@@ -271,6 +271,7 @@ enum usb_endpoints {
# define WEBUSB_IN_EPADDR (ENDPOINT_DIR_IN | WEBUSB_IN_EPNUM)
# define WEBUSB_OUT_EPADDR (ENDPOINT_DIR_OUT | WEBUSB_OUT_EPNUM)
#endif
#ifdef JOYSTICK_ENABLE
JOYSTICK_IN_EPNUM = NEXT_EPNUM,
# if STM32_USB_USE_OTG1

View File

@@ -1,126 +0,0 @@
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device.
# Please customize your programmer settings(PROGRAM_CMD)
#
# make teensy = Download the hex file to the device, using teensy_loader_cli.
# (must have teensy_loader_cli installed).
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
# have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
# have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
# (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
# (must have Atmel FLIP installed).
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Target file name (without extension).
TARGET = usb_hid_test
TMK_DIR = ../../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# MCU name
MCU = atmega32u4
# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency in Hz. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
#
# This will be an integer division of F_USB below, as it is sourced by
# F_USB after it has run through any CPU prescalers. Note that this value
# does not *change* the processor frequency - it should merely be updated to
# reflect the processor speed set externally so that the code can use accurate
# software delays.
F_CPU = 16000000
#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8
# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)
# Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Build Options
# comment out to disable the options.
#
# Console for debug
OPT_DEFS += -DCONSOLE_ENABLE
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
#OPT_DEFS += -DBOOT_SIZE=4096
SRC = test.cpp
SRC += common/debug.c
SRC += common/print.c
CONFIG_H = config.h
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TMK_DIR)
VPATH += $(TMK_DIR)/common
# program Leonardo
PROGRAM_CMD = avrdude -p$(MCU) -cavr109 -P$(DEV) -b57600 -Uflash:w:$(TARGET).hex
include $(TMK_DIR)/protocol/usb_hid.mk
include $(TMK_DIR)/protocol/lufa.mk
include $(TMK_DIR)/rules.mk

View File

@@ -1,92 +0,0 @@
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <util/delay.h>
#include <Arduino.h>
// USB HID host
#include "Usb.h"
#include "hid.h"
#include "hidboot.h"
#include "parser.h"
// LUFA
#include "lufa.h"
#include "debug.h"
#include "leonardo_led.h"
static USB usb_host;
static HIDBoot<HID_PROTOCOL_KEYBOARD> kbd(&usb_host);
static KBDReportParser kbd_parser;
static void LUFA_setup(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
// Leonardo needs. Without this USB device is not recognized.
USB_Disable();
USB_Init();
// for Console_Task
USB_Device_EnableSOFEvents();
}
static void HID_setup()
{
// Arduino Timer startup: wiring.c
init();
if (usb_host.Init() == -1) {
debug("HID init: failed\n");
LED_TX_OFF;
}
_delay_ms(200);
kbd.SetReportParser(0, (HIDReportParser*)&kbd_parser);
}
int main(void)
{
// LED for debug
LED_TX_INIT;
LED_TX_ON;
print_enable = true;
debug_enable = true;
debug_matrix = true;
debug_keyboard = true;
debug_mouse = true;
LUFA_setup();
sei();
// wait for startup of sendchar routine
while (USB_DeviceState != DEVICE_STATE_Configured) ;
if (debug_enable) {
_delay_ms(1000);
}
HID_setup();
debug("init: done\n");
for (;;) {
usb_host.Task();
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
// LUFA Task for control request
USB_USBTask();
#endif
}
return 0;
}

View File

@@ -53,10 +53,10 @@ static void initForUsbConnectivity(void) {
usbDeviceConnect();
}
static void usb_remote_wakeup(void) {
static void vusb_send_remote_wakeup(void) {
cli();
int8_t ddr_orig = USBDDR;
uint8_t ddr_orig = USBDDR;
USBOUT |= (1 << USBMINUS);
USBDDR = ddr_orig | USBMASK;
USBOUT ^= USBMASK;
@@ -70,16 +70,34 @@ static void usb_remote_wakeup(void) {
sei();
}
bool vusb_suspended = false;
static void vusb_suspend(void) {
vusb_suspended = true;
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif
suspend_power_down();
}
#if USB_COUNT_SOF
static void vusb_wakeup(void) {
vusb_suspended = false;
suspend_wakeup_init();
# ifdef SLEEP_LED_ENABLE
sleep_led_disable();
# endif
}
#endif
/** \brief Setup USB
*
* FIXME: Needs doc
*/
static void setup_usb(void) {
initForUsbConnectivity();
// for Console_Task
print_set_sendchar(sendchar);
}
static void setup_usb(void) { initForUsbConnectivity(); }
/** \brief Main
*
@@ -87,9 +105,8 @@ static void setup_usb(void) {
*/
int main(void) __attribute__((weak));
int main(void) {
bool suspended = false;
#if USB_COUNT_SOF
uint16_t last_timer = timer_read();
uint16_t sof_timer = timer_read();
#endif
#ifdef CLKPR
@@ -112,23 +129,24 @@ int main(void) {
while (1) {
#if USB_COUNT_SOF
if (usbSofCount != 0) {
suspended = false;
usbSofCount = 0;
last_timer = timer_read();
# ifdef SLEEP_LED_ENABLE
sleep_led_disable();
# endif
sof_timer = timer_read();
if (vusb_suspended) {
vusb_wakeup();
}
} else {
// Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1)
if (timer_elapsed(last_timer) > 5) {
suspended = true;
# ifdef SLEEP_LED_ENABLE
sleep_led_enable();
# endif
if (!vusb_suspended && timer_elapsed(sof_timer) > 5) {
vusb_suspend();
}
}
#endif
if (!suspended) {
if (vusb_suspended) {
vusb_suspend();
if (suspend_wakeup_condition()) {
vusb_send_remote_wakeup();
}
} else {
usbPoll();
// TODO: configuration process is inconsistent. it sometime fails.
@@ -145,6 +163,7 @@ int main(void) {
raw_hid_task();
}
#endif
#ifdef CONSOLE_ENABLE
usbPoll();
@@ -154,10 +173,7 @@ int main(void) {
#endif
// Run housekeeping
housekeeping_task_kb();
housekeeping_task_user();
} else if (suspend_wakeup_condition()) {
usb_remote_wakeup();
housekeeping_task();
}
}
}

View File

@@ -0,0 +1,356 @@
/* Name: usbconfig.h
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2005-04-01
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
*/
#pragma once
// clang-format off
/*
General Description:
This file is an example configuration (with inline documentation) for the USB
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
other hardware interrupt, as long as it is the highest level interrupt, see
section at the end of this file).
*/
/* ---------------------------- Hardware Config ---------------------------- */
#ifndef USB_CFG_IOPORTNAME
#define USB_CFG_IOPORTNAME D
#endif
/* This is the port where the USB bus is connected. When you configure it to
* "B", the registers PORTB, PINB and DDRB will be used.
*/
#ifndef USB_CFG_DMINUS_BIT
#define USB_CFG_DMINUS_BIT 3
#endif
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
* This may be any bit in the port.
*/
#ifndef USB_CFG_DPLUS_BIT
#define USB_CFG_DPLUS_BIT 2
#endif
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
* This may be any bit in the port. Please note that D+ must also be connected
* to interrupt pin INT0! [You can also use other interrupts, see section
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
* markers every millisecond.]
*/
#define USB_CFG_CHECK_CRC 0
/* Define this to 1 if you want that the driver checks integrity of incoming
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
* currently only available for 18 MHz crystal clock. You must choose
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
*/
/* ----------------------- Optional Hardware Config ------------------------ */
/* #define USB_CFG_PULLUP_IOPORTNAME D */
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
* V+, you can connect and disconnect the device from firmware by calling
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
* This constant defines the port on which the pullup resistor is connected.
*/
/* #define USB_CFG_PULLUP_BIT 4 */
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
* above) where the 1.5k pullup resistor is connected. See description
* above for details.
*/
/* --------------------------- Functional Range ---------------------------- */
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1
/* Define this to 1 if you want to compile a version with two endpoints: The
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
* number).
*/
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1
/* Define this to 1 if you want to compile a version with three endpoints: The
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
* configured below) and a catch-all default interrupt-in endpoint as above.
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
*/
#define USB_CFG_EP3_NUMBER 3
/* If the so-called endpoint 3 is used, it can now be configured to any other
* endpoint number (except 0) with this macro. Default if undefined is 3.
*/
#define USB_CFG_HAVE_INTRIN_ENDPOINT4 1
/* Define this to 1 if you want to compile a version with three endpoints: The
* default control endpoint 0, an interrupt-in endpoint 4 (or the number
* configured below) and a catch-all default interrupt-in endpoint as above.
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
*/
#define USB_CFG_EP4_NUMBER 4
/* If the so-called endpoint 4 is used, it can now be configured to any other
* endpoint number (except 0) with this macro. Default if undefined is 4.
*/
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
/* The above macro defines the startup condition for data toggling on the
* interrupt/bulk endpoints 1, 3 and 4. Defaults to USBPID_DATA1.
* Since the token is toggled BEFORE sending any data, the first packet is
* sent with the oposite value of this configuration!
*/
#define USB_CFG_IMPLEMENT_HALT 0
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
* it is required by the standard. We have made it a config option because it
* bloats the code considerably.
*/
#define USB_CFG_SUPPRESS_INTR_CODE 0
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
* want to send any data over them. If this macro is defined to 1, functions
* usbSetInterrupt(), usbSetInterrupt3() and usbSetInterrupt4() are omitted.
* This is useful if you need the interrupt-in endpoints in order to comply
* to an interface (e.g. HID), but never want to send any data. This option
* saves a couple of bytes in flash memory and the transmit buffers in RAM.
*/
#define USB_CFG_IS_SELF_POWERED 0
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
* device is powered from the USB bus.
*/
#define USB_CFG_IMPLEMENT_FN_WRITE 1
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
* transfers. Set it to 0 if you don't need it and want to save a couple of
* bytes.
*/
#define USB_CFG_IMPLEMENT_FN_READ 0
/* Set this to 1 if you need to send control replies which are generated
* "on the fly" when usbFunctionRead() is called. If you only want to send
* data from a static buffer, set it to 0 and return the data from
* usbFunctionSetup(). This saves a couple of bytes.
*/
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 1
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
* You must implement the function usbFunctionWriteOut() which receives all
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
* can be found in 'usbRxToken'.
*/
#define USB_CFG_HAVE_FLOWCONTROL 0
/* Define this to 1 if you want flowcontrol over USB data. See the definition
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
* usbdrv.h.
*/
#define USB_CFG_DRIVER_FLASH_PAGE 0
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
* where the driver's constants (descriptors) are located. Or in other words:
* Define this to 1 for boot loaders on the ATMega128.
*/
#define USB_CFG_LONG_TRANSFERS 0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
* in a single control-in or control-out transfer. Note that the capability
* for long transfers increases the driver size.
*/
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
/* This macro is a hook if you want to do unconventional things. If it is
* defined, it's inserted at the beginning of received message processing.
* If you eat the received message and don't want default processing to
* proceed, do a return after doing your things. One possible application
* (besides debugging) is to flash a status LED on each packet.
*/
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
/* This macro is a hook if you need to know when an USB RESET occurs. It has
* one parameter which distinguishes between the start of RESET state and its
* end.
*/
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
* received.
*/
#ifndef USB_COUNT_SOF
#define USB_COUNT_SOF 1
#endif
/* define this macro to 1 if you need the global variable "usbSofCount" which
* counts SOF packets. This feature requires that the hardware interrupt is
* connected to D- instead of D+.
*/
/* #ifdef __ASSEMBLER__
* macro myAssemblerMacro
* in YL, TCNT0
* sts timer0Snapshot, YL
* endm
* #endif
* #define USB_SOF_HOOK myAssemblerMacro
* This macro (if defined) is executed in the assembler module when a
* Start Of Frame condition is detected. It is recommended to define it to
* the name of an assembler macro which is defined here as well so that more
* than one assembler instruction can be used. The macro may use the register
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
* immediately after an SOF pulse may be lost and must be retried by the host.
* What can you do with this hook? Since the SOF signal occurs exactly every
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
* designs running on the internal RC oscillator.
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
#define USB_CFG_CHECK_DATA_TOGGLING 0
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
* errors, when the host does not receive an ACK. Please note that you need to
* implement the filtering yourself in usbFunctionWriteOut() and
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
* for each control- and out-endpoint to check for duplicate packets.
*/
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
#define USB_USE_FAST_CRC 0
/* The assembler module has two implementations for the CRC algorithm. One is
* faster, the other is smaller. This CRC routine is only used for transmitted
* messages where timing is not critical. The faster routine needs 31 cycles
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
* may be worth the 32 bytes bigger code size if you transmit lots of data and
* run the AVR close to its limit.
*/
/* -------------------------- Device Description --------------------------- */
#define USB_CFG_VENDOR_ID
/* USB vendor ID for the device, low byte first. If you have registered your
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
* *** IMPORTANT NOTE ***
* This template uses obdev's shared VID/PID pair for Vendor Class devices
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
* the implications!
*/
#define USB_CFG_DEVICE_ID
/* This is the ID of the product, low byte first. It is interpreted in the
* scope of the vendor ID. If you have registered your own VID with usb.org
* or if you have licensed a PID from somebody else, define it here. Otherwise
* you may use one of obdev's free shared VID/PID pairs. See the file
* USB-IDs-for-free.txt for details!
* *** IMPORTANT NOTE ***
* This template uses obdev's shared VID/PID pair for Vendor Class devices
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
* the implications!
*/
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0
/* Define this to the length of the HID report descriptor, if you implement
* an HID device. Otherwise don't define it or define it to 0.
* If you use this define, you must add a PROGMEM character array named
* "usbHidReportDescriptor" to your code which contains the report descriptor.
* Don't forget to keep the array and this define in sync!
*/
/* #define USB_PUBLIC static */
/* Use the define above if you #include usbdrv.c instead of linking against it.
* This technique saves a couple of bytes in flash memory.
*/
/* ------------------- Fine Control over USB Descriptors ------------------- */
/* If you don't want to use the driver's default USB descriptors, you can
* provide our own. These can be provided as (1) fixed length static data in
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
* information about this function.
* Descriptor handling is configured through the descriptor's properties. If
* no properties are defined or if they are 0, the default descriptor is used.
* Possible properties are:
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
* you want RAM pointers.
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
* in static memory is in RAM, not in flash memory.
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
* the driver must know the descriptor's length. The descriptor itself is
* found at the address of a well known identifier (see below).
* List of static descriptor names (must be declared PROGMEM if in flash):
* char usbDescriptorDevice[];
* char usbDescriptorConfiguration[];
* char usbDescriptorHidReport[];
* char usbDescriptorString0[];
* int usbDescriptorStringVendor[];
* int usbDescriptorStringDevice[];
* int usbDescriptorStringSerialNumber[];
* Other descriptors can't be provided statically, they must be provided
* dynamically at runtime.
*
* Descriptor properties are or-ed or added together, e.g.:
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
*
* The following descriptors are defined:
* USB_CFG_DESCR_PROPS_DEVICE
* USB_CFG_DESCR_PROPS_CONFIGURATION
* USB_CFG_DESCR_PROPS_STRINGS
* USB_CFG_DESCR_PROPS_STRING_0
* USB_CFG_DESCR_PROPS_STRING_VENDOR
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
* USB_CFG_DESCR_PROPS_HID
* USB_CFG_DESCR_PROPS_HID_REPORT
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
*
* Note about string descriptors: String descriptors are not just strings, they
* are Unicode strings prefixed with a 2 byte header. Example:
* int serialNumberDescriptor[] = {
* USB_STRING_DESCRIPTOR_HEADER(6),
* 'S', 'e', 'r', 'i', 'a', 'l'
* };
*/
#define USB_CFG_DESCR_PROPS_DEVICE USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_STRINGS USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_STRING_0 USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_STRING_VENDOR USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
#define usbMsgPtr_t unsigned short
/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to
* a scalar type here because gcc generates slightly shorter code for scalar
* arithmetics than for pointer arithmetics. Remove this define for backward
* type compatibility or define it to an 8 bit type if you use data in RAM only
* and all RAM is below 256 bytes (tiny memory model in IAR CC).
*/
/* ----------------------- Optional MCU Description ------------------------ */
/* The following configurations have working defaults in usbdrv.h. You
* usually don't need to set them explicitly. Only if you want to run
* the driver on a device which is not yet supported or with a compiler
* which is not fully supported (such as IAR C) or if you use a differnt
* interrupt than INT0, you may have to define some of these.
*/
/* #define USB_INTR_CFG MCUCR */
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
/* #define USB_INTR_CFG_CLR 0 */
/* #define USB_INTR_ENABLE GIMSK */
/* #define USB_INTR_ENABLE_BIT INT0 */
/* #define USB_INTR_PENDING GIFR */
/* #define USB_INTR_PENDING_BIT INTF0 */
/* #define USB_INTR_VECTOR INT0_vect */
/* Set INT1 for D- falling edge to count SOF */
/* #define USB_INTR_CFG EICRA */
#ifndef USB_INTR_CFG_SET
#define USB_INTR_CFG_SET ((1 << ISC11) | (0 << ISC10))
#endif
/* #define USB_INTR_CFG_CLR 0 */
/* #define USB_INTR_ENABLE EIMSK */
#ifndef USB_INTR_ENABLE_BIT
#define USB_INTR_ENABLE_BIT INT1
#endif
/* #define USB_INTR_PENDING EIFR */
#ifndef USB_INTR_PENDING_BIT
#define USB_INTR_PENDING_BIT INTF1
#endif
#ifndef USB_INTR_VECTOR
#define USB_INTR_VECTOR INT1_vect
#endif

View File

@@ -296,7 +296,7 @@ static void send_consumer(uint16_t data) {
*------------------------------------------------------------------*/
static struct {
uint16_t len;
enum { NONE, BOOTLOADER, SET_LED } kind;
enum { NONE, SET_LED } kind;
} last_req;
usbMsgLen_t usbFunctionSetup(uchar data[8]) {
@@ -323,11 +323,6 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
dprint("SET_LED:");
last_req.kind = SET_LED;
last_req.len = rq->wLength.word;
#ifdef BOOTLOADER_SIZE
} else if (rq->wValue.word == 0x0301) {
last_req.kind = BOOTLOADER;
last_req.len = rq->wLength.word;
#endif
}
return USB_NO_MSG; // to get data in usbFunctionWrite
} else {
@@ -352,11 +347,6 @@ uchar usbFunctionWrite(uchar *data, uchar len) {
last_req.len = 0;
return 1;
break;
case BOOTLOADER:
usbDeviceDisconnect();
bootloader_jump();
return 1;
break;
case NONE:
default:
return -1;
@@ -454,19 +444,15 @@ const PROGMEM uchar shared_hid_report[] = {
0x85, REPORT_ID_MOUSE, // Report ID
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
// Buttons (5 bits)
// Buttons (8 bits)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button 1)
0x29, 0x05, // Usage Maximum (Button 5)
0x29, 0x08, // Usage Maximum (Button 8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x05, // Report Count (5)
0x95, 0x08, // Report Count (8)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Button padding (3 bits)
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x81, 0x03, // Input (Constant)
// X/Y position (2 bytes)
0x05, 0x01, // Usage Page (Generic Desktop)

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "host_driver.h"
#include <usbdrv/usbdrv.h>
typedef struct usbDescriptorHeader {
uchar bLength;
@@ -119,5 +120,7 @@ typedef struct usbConfigurationDescriptor {
#define USB_STRING_LEN(s) (sizeof(usbDescriptorHeader_t) + ((s) << 1))
extern bool vusb_suspended;
host_driver_t *vusb_driver(void);
void vusb_transfer_keyboard(void);

View File

@@ -38,33 +38,36 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma once
#define XT_DATA_IN() \
do { \
XT_DATA_DDR &= ~(1 << XT_DATA_BIT); \
XT_DATA_PORT |= (1 << XT_DATA_BIT); \
#include "quantum.h"
#define XT_DATA_IN() \
do { \
setPinInput(XT_DATA_PIN); \
writePinHigh(XT_DATA_PIN); \
} while (0)
#define XT_DATA_READ() (XT_DATA_PIN & (1 << XT_DATA_BIT))
#define XT_DATA_READ() readPin(XT_DATA_PIN)
#define XT_DATA_LO() \
do { \
XT_DATA_PORT &= ~(1 << XT_DATA_BIT); \
XT_DATA_DDR |= (1 << XT_DATA_BIT); \
#define XT_DATA_LO() \
do { \
writePinLow(XT_DATA_PIN); \
setPinOutput(XT_DATA_PIN); \
} while (0)
#define XT_CLOCK_IN() \
do { \
XT_CLOCK_DDR &= ~(1 << XT_CLOCK_BIT); \
XT_CLOCK_PORT |= (1 << XT_CLOCK_BIT); \
#define XT_CLOCK_IN() \
do { \
setPinInput(XT_CLOCK_PIN); \
writePinHigh(XT_CLOCK_PIN); \
} while (0)
#define XT_CLOCK_READ() (XT_CLOCK_PIN & (1 << XT_CLOCK_BIT))
#define XT_CLOCK_READ() readPin(XT_CLOCK_PIN)
#define XT_CLOCK_LO() \
do { \
XT_CLOCK_PORT &= ~(1 << XT_CLOCK_BIT); \
XT_CLOCK_DDR |= (1 << XT_CLOCK_BIT); \
#define XT_CLOCK_LO() \
do { \
writePinLow(XT_CLOCK_PIN); \
setPinOutput(XT_CLOCK_PIN); \
} while (0)
void xt_host_init(void);
void xt_host_init(void);
uint8_t xt_host_recv(void);

View File

@@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <stdbool.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "xt.h"
#include "wait.h"
#include "debug.h"
@@ -60,7 +59,7 @@ void xt_host_init(void) {
/* soft reset: pull clock line down for 20ms */
XT_DATA_LO();
XT_CLOCK_LO();
_delay_ms(20);
wait_ms(20);
/* input mode with pullup */
XT_CLOCK_IN();
@@ -120,9 +119,10 @@ ISR(XT_INT_VECT) {
* Ring buffer to store scan codes from keyboard
*------------------------------------------------------------------*/
#define PBUF_SIZE 32
static uint8_t pbuf[PBUF_SIZE];
static uint8_t pbuf_head = 0;
static uint8_t pbuf_tail = 0;
static uint8_t pbuf[PBUF_SIZE];
static uint8_t pbuf_head = 0;
static uint8_t pbuf_tail = 0;
static inline void pbuf_enqueue(uint8_t data) {
uint8_t sreg = SREG;
cli();
@@ -135,6 +135,7 @@ static inline void pbuf_enqueue(uint8_t data) {
}
SREG = sreg;
}
static inline uint8_t pbuf_dequeue(void) {
uint8_t val = 0;
@@ -148,6 +149,7 @@ static inline uint8_t pbuf_dequeue(void) {
return val;
}
static inline bool pbuf_has_data(void) {
uint8_t sreg = SREG;
cli();
@@ -155,6 +157,7 @@ static inline bool pbuf_has_data(void) {
SREG = sreg;
return has_data;
}
static inline void pbuf_clear(void) {
uint8_t sreg = SREG;
cli();

View File

@@ -67,7 +67,6 @@ Start Your Own Project
#define PRODUCT_ID 0xBEEF
#define MANUFACTURER t.m.k.
#define PRODUCT Macway mod
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod
#### 2. Keyboard matrix configuration
#define MATRIX_ROWS 8

View File

@@ -1,45 +0,0 @@
#pragma once
/*--------------------------------------------------------------------
* Ring buffer to store scan codes from keyboard
*------------------------------------------------------------------*/
#ifndef RBUF_SIZE
# define RBUF_SIZE 32
#endif
#include <util/atomic.h>
#include <stdint.h>
#include <stdbool.h>
static uint8_t rbuf[RBUF_SIZE];
static uint8_t rbuf_head = 0;
static uint8_t rbuf_tail = 0;
static inline bool rbuf_enqueue(uint8_t data) {
bool ret = false;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
if (next != rbuf_tail) {
rbuf[rbuf_head] = data;
rbuf_head = next;
ret = true;
}
}
return ret;
}
static inline uint8_t rbuf_dequeue(void) {
uint8_t val = 0;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
if (rbuf_head != rbuf_tail) {
val = rbuf[rbuf_tail];
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
}
}
return val;
}
static inline bool rbuf_has_data(void) {
bool has_data;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { has_data = (rbuf_head != rbuf_tail); }
return has_data;
}
static inline void rbuf_clear(void) {
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { rbuf_head = rbuf_tail = 0; }
}

View File

@@ -108,6 +108,10 @@ endif
CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
CFLAGS += $(CSTANDARD)
# This fixes lots of keyboards linking errors but SHOULDN'T BE A FINAL SOLUTION
# Fixing of multiple variable definitions must be made.
CFLAGS += -fcommon
#---------------- Compiler Options C++ ----------------
# -g*: generate debugging information
# -O*: optimization level
@@ -124,6 +128,7 @@ CXXFLAGS += -O$(OPT)
CXXFLAGS += -w
CXXFLAGS += -Wall
CXXFLAGS += -Wundef
ifneq ($(strip $(ALLOW_WARNINGS)), yes)
CXXFLAGS += -Werror
endif